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

Create category rules for ynab imports #1944

Merged
merged 4 commits into from
Nov 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
13 changes: 11 additions & 2 deletions packages/api/methods.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,17 @@ export function setBudgetCarryover(month, categoryId, flag) {
return send('api/budget-set-carryover', { month, categoryId, flag });
}

export function addTransactions(accountId, transactions) {
return send('api/transactions-add', { accountId, transactions });
export function addTransactions(
accountId,
transactions,
{ learnCategories = false, runTransfers = false } = {},
) {
return send('api/transactions-add', {
accountId,
transactions,
learnCategories,
runTransfers,
});
}

export function importTransactions(accountId, transactions) {
Expand Down
10 changes: 7 additions & 3 deletions packages/loot-core/src/server/accounts/sync.ts
Original file line number Diff line number Diff line change
Expand Up @@ -705,7 +705,7 @@ export async function reconcileTransactions(acctId, transactions) {
export async function addTransactions(
acctId,
transactions,
{ runTransfers = true } = {},
{ runTransfers = true, learnCategories = false } = {},
) {
const added = [];

Expand Down Expand Up @@ -737,8 +737,12 @@ export async function addTransactions(
await createNewPayees(payeesToCreate, added);

let newTransactions;
if (runTransfers) {
let res = await batchUpdateTransactions({ added });
if (runTransfers || learnCategories) {
let res = await batchUpdateTransactions({
added,
learnCategories,
runTransfers,
});
newTransactions = res.added.map(t => t.id);
} else {
await batchMessages(async () => {
Expand Down
25 changes: 15 additions & 10 deletions packages/loot-core/src/server/accounts/transactions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export async function batchUpdateTransactions({
updated,
learnCategories = false,
detectOrphanPayees = true,
runTransfers = true,
}: {
added?: Array<{ id: string; payee: unknown; category: unknown }>;
deleted?: Array<{ id: string; payee: unknown }>;
Expand All @@ -51,6 +52,7 @@ export async function batchUpdateTransactions({
}>;
learnCategories?: boolean;
detectOrphanPayees?: boolean;
runTransfers?: boolean;
}) {
// Track the ids of each type of transaction change (see below for why)
let addedIds = [];
Expand Down Expand Up @@ -126,18 +128,21 @@ export async function batchUpdateTransactions({
// to the client so that can apply them. Note that added
// transactions just return the full transaction.
let resultAdded = allAdded;
let resultUpdated: Awaited<ReturnType<typeof transfer.onUpdate>>[];
let resultUpdated = allUpdated;
let transfersUpdated: Awaited<ReturnType<typeof transfer.onUpdate>>[];

await batchMessages(async () => {
await Promise.all(allAdded.map(t => transfer.onInsert(t)));
if (runTransfers) {
await batchMessages(async () => {
await Promise.all(allAdded.map(t => transfer.onInsert(t)));

// Return any updates from here
resultUpdated = (
await Promise.all(allUpdated.map(t => transfer.onUpdate(t)))
).filter(Boolean);
// Return any updates from here
transfersUpdated = (
await Promise.all(allUpdated.map(t => transfer.onUpdate(t)))
).filter(Boolean);

await Promise.all(allDeleted.map(t => transfer.onDelete(t)));
});
await Promise.all(allDeleted.map(t => transfer.onDelete(t)));
});
}

if (learnCategories) {
// Analyze any updated categories and update rules to learn from
Expand Down Expand Up @@ -176,6 +181,6 @@ export async function batchUpdateTransactions({

return {
added: resultAdded,
updated: resultUpdated,
updated: runTransfers ? transfersUpdated : resultUpdated,
};
}
7 changes: 6 additions & 1 deletion packages/loot-core/src/server/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -393,9 +393,14 @@ handlers['api/transactions-import'] = withMutation(async function ({
handlers['api/transactions-add'] = withMutation(async function ({
accountId,
transactions,
runTransfers = false,
learnCategories = false,
}) {
checkFileOpen();
await addTransactions(accountId, transactions, { runTransfers: false });
await addTransactions(accountId, transactions, {
runTransfers,
learnCategories,
});
return 'ok';
});

Expand Down
4 changes: 3 additions & 1 deletion packages/loot-core/src/server/importers/ynab4.ts
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,9 @@ async function importTransactions(
})
.filter(x => x);

await actual.addTransactions(entityIdMap.get(accountId), toImport);
await actual.addTransactions(entityIdMap.get(accountId), toImport, {
learnCategories: true,
});
}),
);
}
Expand Down
4 changes: 3 additions & 1 deletion packages/loot-core/src/server/importers/ynab5.ts
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,9 @@ async function importTransactions(
})
.filter(x => x);

await actual.addTransactions(entityIdMap.get(accountId), toImport);
await actual.addTransactions(entityIdMap.get(accountId), toImport, {
learnCategories: true,
});
}),
);
}
Expand Down
6 changes: 6 additions & 0 deletions upcoming-release-notes/1944.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
category: Enhancements
authors: [twk3]
---

Create category rules during ynab imports