Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: add more concrete types to loot-core #1186

Merged
merged 25 commits into from
Jul 29, 2023
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions packages/loot-core/src/mocks/budget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -454,10 +454,10 @@ async function createBudget(accounts, payees, groups) {
}

function setBudgetIfSpent(month, cat) {
let spent = sheet.getCellValue(
let spent: number = sheet.getCellValue(
j-f1 marked this conversation as resolved.
Show resolved Hide resolved
monthUtils.sheetForMonth(month),
`sum-amount-${cat.id}`,
);
) as number;

if (spent < 0) {
setBudget(month, cat, -spent);
Expand Down Expand Up @@ -515,7 +515,10 @@ async function createBudget(accounts, payees, groups) {
month <= monthUtils.currentMonth()
) {
let sheetName = monthUtils.sheetForMonth(month);
let toBudget = sheet.getCellValue(sheetName, 'to-budget');
let toBudget: number = sheet.getCellValue(
sheetName,
'to-budget',
) as number;
let available = toBudget - prevSaved;

if (available - 403000 > 0) {
Expand All @@ -534,7 +537,7 @@ async function createBudget(accounts, payees, groups) {
await sheet.waitOnSpreadsheet();

let sheetName = monthUtils.sheetForMonth(monthUtils.currentMonth());
let toBudget = sheet.getCellValue(sheetName, 'to-budget');
let toBudget: number = sheet.getCellValue(sheetName, 'to-budget') as number;
j-f1 marked this conversation as resolved.
Show resolved Hide resolved
if (toBudget < 0) {
await addTransactions(primaryAccount.id, [
{
Expand Down
2 changes: 1 addition & 1 deletion packages/loot-core/src/server/accounts/parse-file.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ async function parseOFX(filepath): Promise<ParseFileResult> {
transactions: data.map(trans => ({
amount: trans.amount,
imported_id: trans.fi_id,
date: trans.date ? dayFromDate(trans.date * 1000) : null,
date: trans.date ? dayFromDate(new Date(trans.date * 1000)) : null,
payee_name: trans.name,
imported_payee: trans.name,
notes: trans.memo || null,
Expand Down
20 changes: 10 additions & 10 deletions packages/loot-core/src/server/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -298,16 +298,16 @@ handlers['api/budget-month'] = async function ({ month }) {
// different (for now)
return {
month,
incomeAvailable: value('available-funds'),
lastMonthOverspent: value('last-month-overspent'),
forNextMonth: value('buffered'),
totalBudgeted: value('total-budgeted'),
toBudget: value('to-budget'),

fromLastMonth: value('from-last-month'),
totalIncome: value('total-income'),
totalSpent: value('total-spent'),
totalBalance: value('total-leftover'),
incomeAvailable: value('available-funds') as number,
lastMonthOverspent: value('last-month-overspent') as number,
forNextMonth: value('buffered') as number,
totalBudgeted: value('total-budgeted') as number,
toBudget: value('to-budget') as number,

fromLastMonth: value('from-last-month') as number,
totalIncome: value('total-income') as number,
totalSpent: value('total-spent') as number,
totalBalance: value('total-leftover') as number,

categoryGroups: groups.map(group => {
if (group.is_income) {
Expand Down
125 changes: 103 additions & 22 deletions packages/loot-core/src/server/budget/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ import * as prefs from '../prefs';
import * as sheet from '../sheet';
import { batchMessages } from '../sync';

export async function getSheetValue(sheetName, cell) {
export async function getSheetValue(
sheetName: string,
cell: string,
): Promise<number> {
const node = await sheet.getCell(sheetName, cell);
return safeNumber(typeof node.value === 'number' ? node.value : 0);
}
Expand All @@ -14,26 +17,37 @@ export async function getSheetValue(sheetName, cell) {
// forth. buffered should never be allowed to go into the negative,
// and you shouldn't be allowed to pull non-existant money from
// leftover.
function calcBufferedAmount(toBudget, buffered, amount) {
function calcBufferedAmount(
toBudget: number,
buffered: number,
amount: number,
): number {
amount = Math.min(Math.max(amount, -buffered), Math.max(toBudget, 0));
return buffered + amount;
}

function getBudgetTable() {
function getBudgetTable(): string {
let { budgetType } = prefs.getPrefs() || {};
return budgetType === 'report' ? 'reflect_budgets' : 'zero_budgets';
}

function isReflectBudget() {
function isReflectBudget(): boolean {
let { budgetType } = prefs.getPrefs();
return budgetType === 'report';
}

function dbMonth(month) {
function dbMonth(month: string): number {
return parseInt(month.replace('-', ''));
}

function getBudgetData(table, month) {
// TODO: complete list of fields.
type BudgetData = {
is_income: 1 | 0;
category: string;
amount: number;
};

function getBudgetData(table: string, month: string): Promise<BudgetData[]> {
return db.all(
`
SELECT b.*, c.is_income FROM v_categories c
Expand All @@ -44,7 +58,7 @@ function getBudgetData(table, month) {
);
}

function getAllMonths(startMonth) {
function getAllMonths(startMonth: string): string[] {
let { createdMonths } = sheet.get().meta();
let latest = null;
for (let month of createdMonths) {
Expand All @@ -57,7 +71,13 @@ function getAllMonths(startMonth) {

// TODO: Valid month format in all the functions below

export function getBudget({ category, month }) {
export function getBudget({
category,
month,
}: {
category: string;
month: string;
}): number {
let table = getBudgetTable();
let existing = db.firstSync(
`SELECT * FROM ${table} WHERE month = ? AND category = ?`,
Expand All @@ -66,7 +86,15 @@ export function getBudget({ category, month }) {
return existing ? existing.amount || 0 : 0;
}

export function setBudget({ category, month, amount }) {
export function setBudget({
category,
month,
amount,
}: {
category: string;
month: string;
amount: unknown;
}): Promise<void> {
amount = safeNumber(typeof amount === 'number' ? amount : 0);
const table = getBudgetTable();

Expand All @@ -85,7 +113,7 @@ export function setBudget({ category, month, amount }) {
});
}

export function setBuffer(month, amount) {
export function setBuffer(month: string, amount: unknown): Promise<void> {
let existing = db.firstSync(
`SELECT id FROM zero_budget_months WHERE id = ?`,
[month],
Expand All @@ -99,7 +127,12 @@ export function setBuffer(month, amount) {
return db.insert('zero_budget_months', { id: month, buffered: amount });
}

function setCarryover(table, category, month, flag) {
function setCarryover(
table: string,
category: string,
month: string,
flag: boolean,
): Promise<void> {
let existing = db.firstSync(
`SELECT id FROM ${table} WHERE month = ? AND category = ?`,
[month, category],
Expand All @@ -117,10 +150,14 @@ function setCarryover(table, category, month, flag) {

// Actions

export async function copyPreviousMonth({ month }) {
export async function copyPreviousMonth({
month,
}: {
month: string;
}): Promise<void> {
let prevMonth = dbMonth(monthUtils.prevMonth(month));
let table = getBudgetTable();
let budgetData = await getBudgetData(table, prevMonth);
let budgetData = await getBudgetData(table, prevMonth.toString());

await batchMessages(async () => {
budgetData.forEach(prevBudget => {
Expand All @@ -136,7 +173,7 @@ export async function copyPreviousMonth({ month }) {
});
}

export async function setZero({ month }) {
export async function setZero({ month }: { month: string }): Promise<void> {
let categories = await db.all(
'SELECT * FROM v_categories WHERE tombstone = 0',
);
Expand All @@ -151,7 +188,11 @@ export async function setZero({ month }) {
});
}

export async function set3MonthAvg({ month }) {
export async function set3MonthAvg({
month,
}: {
month: string;
}): Promise<void> {
let categories = await db.all(
'SELECT * FROM v_categories WHERE tombstone = 0',
);
Expand Down Expand Up @@ -185,7 +226,13 @@ export async function set3MonthAvg({ month }) {
});
}

export async function holdForNextMonth({ month, amount }) {
export async function holdForNextMonth({
month,
amount,
}: {
month: string;
amount: number;
}): Promise<boolean> {
let row = await db.first(
'SELECT buffered FROM zero_budget_months WHERE id = ?',
[month],
Expand All @@ -207,11 +254,19 @@ export async function holdForNextMonth({ month, amount }) {
return false;
}

export async function resetHold({ month }) {
export async function resetHold({ month }: { month: string }): Promise<void> {
await setBuffer(month, 0);
}

export async function coverOverspending({ month, to, from }) {
export async function coverOverspending({
month,
to,
from,
}: {
month: string;
to: string;
from: string;
}): Promise<void> {
let sheetName = monthUtils.sheetForMonth(month);
let toBudgeted = await getSheetValue(sheetName, 'budget-' + to);
let leftover = await getSheetValue(sheetName, 'leftover-' + to);
Expand Down Expand Up @@ -239,7 +294,15 @@ export async function coverOverspending({ month, to, from }) {
await setBudget({ category: to, month, amount: toBudgeted + amountCovered });
}

export async function transferAvailable({ month, amount, category }) {
export async function transferAvailable({
month,
amount,
category,
}: {
month: string;
amount: number;
category: string;
}): Promise<void> {
let sheetName = monthUtils.sheetForMonth(month);
let leftover = await getSheetValue(sheetName, 'to-budget');
amount = Math.max(Math.min(amount, leftover), 0);
Expand All @@ -248,7 +311,17 @@ export async function transferAvailable({ month, amount, category }) {
await setBudget({ category, month, amount: budgeted + amount });
}

export async function transferCategory({ month, amount, from, to }) {
export async function transferCategory({
month,
amount,
from,
to,
}: {
month: string;
amount: number;
to: string;
from: string;
}): Promise<void> {
const sheetName = monthUtils.sheetForMonth(month);
const fromBudgeted = await getSheetValue(sheetName, 'budget-' + from);

Expand All @@ -262,13 +335,21 @@ export async function transferCategory({ month, amount, from, to }) {
}
}

export async function setCategoryCarryover({ startMonth, category, flag }) {
export async function setCategoryCarryover({
startMonth,
category,
flag,
}: {
startMonth: string;
category: string;
flag: boolean;
}): Promise<void> {
let table = getBudgetTable();
let months = getAllMonths(startMonth);

await batchMessages(async () => {
for (let month of months) {
setCarryover(table, category, dbMonth(month), flag);
setCarryover(table, category, dbMonth(month).toString(), flag);
}
});
}
2 changes: 1 addition & 1 deletion packages/loot-core/src/server/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ handlers['report-budget-month'] = async function ({ month }) {
};

handlers['budget-set-type'] = async function ({ type }) {
if (type !== 'rollover' && type !== 'report') {
if (!prefs.BUDGET_TYPES.includes(type)) {
throw new Error('Invalid budget type: ' + type);
}

Expand Down
Loading