Skip to content

Commit

Permalink
DB models
Browse files Browse the repository at this point in the history
  • Loading branch information
joel-jeremy committed Jan 27, 2025
1 parent 4fe5834 commit f515ed8
Show file tree
Hide file tree
Showing 63 changed files with 913 additions and 370 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ function makePayee(name: string, options?: { favorite: boolean }): PayeeEntity {
return {
id: name.toLowerCase() + '-id',
name,
favorite: options?.favorite ? 1 : 0,
favorite: options?.favorite ? true : false,
transfer_acct: undefined,
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,7 @@ export function PayeeAutocomplete({
return filteredSuggestions;
}

return [{ id: 'new', favorite: 0, name: '' }, ...filteredSuggestions];
return [{ id: 'new', favorite: false, name: '' }, ...filteredSuggestions];
}, [commonPayees, payees, focusTransferPayees, accounts, hasPayeeInput]);

const dispatch = useDispatch();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -230,8 +230,8 @@ function AccountList({
const { t } = useTranslation();
const failedAccounts = useFailedAccounts();
const syncingAccountIds = useSelector(state => state.account.accountsSyncing);
const onBudgetAccounts = accounts.filter(account => account.offbudget === 0);
const offBudgetAccounts = accounts.filter(account => account.offbudget === 1);
const onBudgetAccounts = accounts.filter(account => !account.offbudget);
const offBudgetAccounts = accounts.filter(account => account.offbudget);

return (
<Page
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,11 @@ function needsCategory(
accounts: AccountEntity[],
) {
const acct = accounts.find(a => a.id === currentTransfer);
const isOffBudget = acct && acct.offbudget === 1;
const isOffBudget = acct && acct.offbudget;

// The user must select a category if transferring from a budgeted
// account to an off budget account
return account.offbudget === 0 && isOffBudget;
return !account.offbudget && isOffBudget;
}

type CloseAccountModalProps = {
Expand All @@ -49,7 +49,7 @@ export function CloseAccountModal({
canDelete,
}: CloseAccountModalProps) {
const { t } = useTranslation(); // Initialize translation hook
const accounts = useAccounts().filter(a => a.closed === 0);
const accounts = useAccounts().filter(a => !a.closed);
const { grouped: categoryGroups, list: categories } = useCategories();
const [loading, setLoading] = useState(false);
const [transferAccountId, setTransferAccountId] = useState('');
Expand Down
18 changes: 12 additions & 6 deletions packages/desktop-client/src/components/payees/ManagePayees.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -154,16 +154,16 @@ export const ManagePayees = ({
function onFavorite() {
const allFavorited = [...selected.items]
.map(id => payeesById[id].favorite)
.every(f => f === 1);
.every(f => f === true);
if (allFavorited) {
onBatchChange({
updated: [...selected.items].map(id => ({ id, favorite: 0 })),
updated: [...selected.items].map(id => ({ id, favorite: false })),
added: [],
deleted: [],
});
} else {
onBatchChange({
updated: [...selected.items].map(id => ({ id, favorite: 1 })),
updated: [...selected.items].map(id => ({ id, favorite: true })),
added: [],
deleted: [],
});
Expand All @@ -174,16 +174,22 @@ export const ManagePayees = ({
function onLearn() {
const allLearnCategories = [...selected.items]
.map(id => payeesById[id].learn_categories)
.every(f => f === 1);
.every(f => f === true);
if (allLearnCategories) {
onBatchChange({
updated: [...selected.items].map(id => ({ id, learn_categories: 0 })),
updated: [...selected.items].map(id => ({
id,
learn_categories: false,
})),
added: [],
deleted: [],
});
} else {
onBatchChange({
updated: [...selected.items].map(id => ({ id, learn_categories: 1 })),
updated: [...selected.items].map(id => ({
id,
learn_categories: true,
})),
added: [],
deleted: [],
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -179,13 +179,13 @@ export const PayeeTableRow = memo(
onDelete(id);
break;
case 'favorite':
onUpdate(id, 'favorite', payee.favorite ? 0 : 1);
onUpdate(id, 'favorite', payee.favorite ? false : true);
break;
case 'learn':
onUpdate(
id,
'learn_categories',
payee.learn_categories ? 0 : 1,
payee.learn_categories ? false : true,
);
break;
case 'view-rules':
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,16 +52,16 @@ const payees: PayeeEntity[] = [
{
id: 'bob-id',
name: 'Bob',
favorite: 1,
favorite: true,
},
{
id: 'alice-id',
name: 'Alice',
favorite: 1,
favorite: true,
},
{
id: 'guy',
favorite: 0,
favorite: false,
name: 'This guy on the side of the road',
},
];
Expand Down
5 changes: 1 addition & 4 deletions packages/desktop-client/src/hooks/useClosedAccounts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,5 @@ import { useAccounts } from './useAccounts';

export function useClosedAccounts() {
const accounts = useAccounts();
return useMemo(
() => accounts.filter(account => account.closed === 1),
[accounts],
);
return useMemo(() => accounts.filter(account => account.closed), [accounts]);
}
5 changes: 1 addition & 4 deletions packages/desktop-client/src/hooks/useOffBudgetAccounts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,7 @@ import { useAccounts } from './useAccounts';
export function useOffBudgetAccounts() {
const accounts = useAccounts();
return useMemo(
() =>
accounts.filter(
account => account.closed === 0 && account.offbudget === 1,
),
() => accounts.filter(account => !account.closed && account.offbudget),
[accounts],
);
}
5 changes: 1 addition & 4 deletions packages/desktop-client/src/hooks/useOnBudgetAccounts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,7 @@ import { useAccounts } from './useAccounts';
export function useOnBudgetAccounts() {
const accounts = useAccounts();
return useMemo(
() =>
accounts.filter(
account => account.closed === 0 && account.offbudget === 0,
),
() => accounts.filter(account => !account.closed && !account.offbudget),
[accounts],
);
}
3 changes: 2 additions & 1 deletion packages/loot-core/src/client/transfer.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// @ts-strict-ignore
import * as db from '../server/db';
import { transactionModel } from '../server/models';

import * as transfer from './transfer';

Expand All @@ -22,7 +23,7 @@ async function createTransaction(account: string, amount: number, extra = {}) {
...extra,
};
transaction.id = await db.insertTransaction(transaction);
return await db.getTransaction(transaction.id);
return transactionModel.fromDbView(await db.getTransaction(transaction.id));
}

describe('Transfer', () => {
Expand Down
4 changes: 2 additions & 2 deletions packages/loot-core/src/mocks/budget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -461,13 +461,13 @@ async function fillOther(handlers, account, payees, groups) {
async function createBudget(accounts, payees, groups) {
const primaryAccount = accounts.find(a => (a.name = 'Bank of America'));
const earliestDate = (
await db.first<TransactionEntity>(
await db.first<db.DbViewTransaction>(
`SELECT * FROM v_transactions t LEFT JOIN accounts a ON t.account = a.id
WHERE a.offbudget = 0 AND t.is_child = 0 ORDER BY date ASC LIMIT 1`,
)
).date;
const earliestPrimaryDate = (
await db.first<TransactionEntity>(
await db.first<db.DbViewTransaction>(
`SELECT * FROM v_transactions t LEFT JOIN accounts a ON t.account = a.id
WHERE a.id = ? AND a.offbudget = 0 AND t.is_child = 0 ORDER BY date ASC LIMIT 1`,
[primaryAccount.id],
Expand Down
6 changes: 3 additions & 3 deletions packages/loot-core/src/mocks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@ export function generateAccount(
name,
bankId: null,
bankName: null,
offbudget: offbudget ? 1 : 0,
offbudget: offbudget ? true : false,
sort_order: 0,
tombstone: 0,
closed: 0,
tombstone: false,
closed: false,
...emptySyncFields(),
};

Expand Down
3 changes: 1 addition & 2 deletions packages/loot-core/src/server/accounts/link.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
// @ts-strict-ignore
import { v4 as uuidv4 } from 'uuid';

import { BankEntity } from '../../types/models';
import * as db from '../db';

export async function findOrCreateBank(institution, requisitionId) {
const bank = await db.first<Pick<BankEntity, 'id' | 'bank_id'>>(
const bank = await db.first<Pick<db.DbBank, 'id' | 'bank_id'>>(
'SELECT id, bank_id, name FROM banks WHERE bank_id = ?',
[requisitionId],
);
Expand Down
3 changes: 1 addition & 2 deletions packages/loot-core/src/server/accounts/parse-file.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
import * as d from 'date-fns';

import { amountToInteger } from '../../shared/util';
import { TransactionEntity } from '../../types/models';
import * as db from '../db';
import * as prefs from '../prefs';

Expand All @@ -23,7 +22,7 @@ afterAll(() => {
});

async function getTransactions(accountId) {
return db.runQuery<TransactionEntity>(
return db.runQuery<db.DbTransaction>(
'SELECT * FROM transactions WHERE acct = ?',
[accountId],
true,
Expand Down
7 changes: 3 additions & 4 deletions packages/loot-core/src/server/accounts/payees.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
// @ts-strict-ignore
import { CategoryEntity, PayeeEntity } from '../../types/models';
import * as db from '../db';

export async function createPayee(description) {
// Check to make sure no payee already exists with exactly the same
// name
const row = await db.first<Pick<PayeeEntity, 'id'>>(
const row = await db.first<Pick<db.DbPayee, 'id'>>(
`SELECT id FROM payees WHERE UNICODE_LOWER(name) = ? AND tombstone = 0`,
[description.toLowerCase()],
);
Expand All @@ -18,14 +17,14 @@ export async function createPayee(description) {
}

export async function getStartingBalancePayee() {
let category = await db.first<CategoryEntity>(`
let category = await db.first<db.DbCategory>(`
SELECT * FROM categories
WHERE is_income = 1 AND
LOWER(name) = 'starting balances' AND
tombstone = 0
`);
if (category === null) {
category = await db.first<CategoryEntity>(
category = await db.first<db.DbCategory>(
'SELECT * FROM categories WHERE is_income = 1 AND tombstone = 0',
);
}
Expand Down
3 changes: 1 addition & 2 deletions packages/loot-core/src/server/accounts/sync.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
// @ts-strict-ignore
import * as monthUtils from '../../shared/months';
import { TransactionEntity } from '../../types/models';
import * as db from '../db';
import { loadMappings } from '../db/mappings';
import { post } from '../post';
Expand All @@ -25,7 +24,7 @@ beforeEach(async () => {
});

function getAllTransactions() {
return db.all<TransactionEntity & { payee_name: string }>(
return db.all<db.DbViewTransactionInternal & { payee_name: string }>(
`SELECT t.*, p.name as payee_name
FROM v_transactions_internal t
LEFT JOIN payees p ON p.id = t.payee
Expand Down
8 changes: 4 additions & 4 deletions packages/loot-core/src/server/accounts/sync.ts
Original file line number Diff line number Diff line change
Expand Up @@ -454,7 +454,7 @@ export async function reconcileTransactions(
}

if (existing.is_parent && existing.cleared !== updates.cleared) {
const children = await db.all<Pick<TransactionEntity, 'id'>>(
const children = await db.all<Pick<db.DbViewTransaction, 'id'>>(
'SELECT id FROM v_transactions WHERE parent_id = ?',
[existing.id],
);
Expand Down Expand Up @@ -527,7 +527,7 @@ export async function matchTransactions(
);

// The first pass runs the rules, and preps data for fuzzy matching
const accounts: AccountEntity[] = await db.getAccounts();
const accounts = await db.getAccounts();
const accountsMap = new Map(accounts.map(account => [account.id, account]));

const transactionsStep1 = [];
Expand All @@ -546,7 +546,7 @@ export async function matchTransactions(
// is the highest fidelity match and should always be attempted
// first.
if (trans.imported_id) {
match = await db.first<TransactionEntity>(
match = await db.first<db.DbViewTransaction>(
'SELECT * FROM v_transactions WHERE imported_id = ? AND account = ?',
[trans.imported_id, acctId],
);
Expand Down Expand Up @@ -680,7 +680,7 @@ export async function addTransactions(
{ rawPayeeName: true },
);

const accounts: AccountEntity[] = await db.getAccounts();
const accounts: db.DbAccount[] = await db.getAccounts();
const accountsMap = new Map(accounts.map(account => [account.id, account]));

for (const { trans: originalTrans, subtransactions } of normalized) {
Expand Down
22 changes: 11 additions & 11 deletions packages/loot-core/src/server/accounts/transaction-rules.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// @ts-strict-ignore
import { q } from '../../shared/query';
import { RawRuleEntity, RuleEntity } from '../../types/models';
import { RuleEntity } from '../../types/models';
import { runQuery } from '../aql';
import * as db from '../db';
import { loadMappings } from '../db/mappings';
Expand Down Expand Up @@ -941,13 +941,13 @@ describe('Learning categories', () => {

// Internally, it should still be stored with the internal names
// so that it's backwards compatible
const { conditions, actions, ...rawRule } = await db.first<RawRuleEntity>(
'SELECT * FROM rules',
);
const rawRule = await db.first<db.DbRule>('SELECT * FROM rules');
const parsedRule: RuleEntity = {
conditions: JSON.parse(conditions),
actions: JSON.parse(actions),
...rawRule,
conditions: JSON.parse(rawRule.conditions),
actions: JSON.parse(rawRule.actions),
conditionsOp: rawRule.conditions_op as RuleEntity['conditionsOp'],
stage: rawRule.stage as RuleEntity['stage'],
};
expect(parsedRule.conditions[0].field).toBe('imported_description');
const action = parsedRule.actions[0];
Expand Down Expand Up @@ -977,13 +977,13 @@ describe('Learning categories', () => {
// This rule internally has been stored with the public names.
// Making this work now allows us to switch to it by default in
// the future
const { conditions, actions, ...rawRule } = await db.first<RawRuleEntity>(
'SELECT * FROM rules',
);
const rawRule = await db.first<db.DbRule>('SELECT * FROM rules');
const parsedRule: RuleEntity = {
conditions: JSON.parse(conditions),
actions: JSON.parse(actions),
...rawRule,
conditions: JSON.parse(rawRule.conditions),
actions: JSON.parse(rawRule.actions),
conditionsOp: rawRule.conditions_op as RuleEntity['conditionsOp'],
stage: rawRule.stage as RuleEntity['stage'],
};
expect(parsedRule.conditions[0].field).toBe('imported_payee');
const action = parsedRule.actions[0];
Expand Down
Loading

0 comments on commit f515ed8

Please sign in to comment.