Skip to content

Commit

Permalink
fixed:issue->#1968 Import from nYNAB fails with unknown error (#2191)
Browse files Browse the repository at this point in the history
* Allow case insensitive ynab5 import for special 'starting balance' payee

* set upcoming release number to related github issue

* extract string comparison into separate function

and reuse when checking starting balance/s on ynab4 import

* make all category group checks case insensitive

when importing from ynab5 to make the check strategy consistent when importing from ynab5

* extract findById into sreusable function

to 'simplify' usage

* Add null check

Co-authored-by: Joel Jeremy Marquez <[email protected]>

---------

Co-authored-by: Joel Jeremy Marquez <[email protected]>
  • Loading branch information
Marethyu1 and joel-jeremy authored Jan 12, 2024
1 parent e205344 commit 540c410
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 22 deletions.
60 changes: 38 additions & 22 deletions packages/loot-core/src/server/importers/ynab5.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,25 +39,26 @@ async function importCategories(
// so it's already handled.

const categories = await actual.getCategories();
const incomeCatId = categories.find(cat => cat.name === 'Income').id;
const incomeCatId = findIdByName(categories, 'Income');
const ynabIncomeCategories = ['To be Budgeted', 'Inflow: Ready to Assign'];

function checkSpecialCat(cat) {
if (
cat.category_group_id ===
data.category_groups.find(
group => group.name === 'Internal Master Category',
).id
findIdByName(data.category_groups, 'Internal Master Category')
) {
if (ynabIncomeCategories.includes(cat.name)) {
if (
ynabIncomeCategories.some(ynabIncomeCategory =>
equalsIgnoreCase(cat.name, ynabIncomeCategory),
)
) {
return 'income';
} else {
return 'internal';
}
} else if (
cat.category_group_id ===
data.category_groups.find(group => group.name === 'Credit Card Payments')
.id
findIdByName(data.category_groups, 'Credit Card Payments')
) {
return 'creditCard';
}
Expand All @@ -70,8 +71,8 @@ async function importCategories(
let groupId;
// Ignores internal category and credit cards
if (
group.name !== 'Internal Master Category' &&
group.name !== 'Credit Card Payments'
!equalsIgnoreCase(group.name, 'Internal Master Category') &&
!equalsIgnoreCase(group.name, 'Credit Card Payments')
) {
groupId = await actual.createCategoryGroup({
name: group.name,
Expand Down Expand Up @@ -132,13 +133,10 @@ async function importTransactions(
) {
const payees = await actual.getPayees();
const categories = await actual.getCategories();
const incomeCatId = categories.find(cat => cat.name === 'Income').id;
const startingBalanceCatId = categories.find(
cat => cat.name === 'Starting Balances',
).id; //better way to do it?
const startingPayeeYNAB = data.payees.find(
payee => payee.name === 'Starting Balance',
).id;
const incomeCatId = findIdByName(categories, 'Income');
const startingBalanceCatId = findIdByName(categories, 'Starting Balances'); //better way to do it?

const startingPayeeYNAB = findIdByName(data.payees, 'Starting Balance');

const transactionsGrouped = groupBy(data.transactions, 'account_id');
const subtransactionsGrouped = groupBy(
Expand Down Expand Up @@ -258,12 +256,14 @@ async function importBudgets(

const budgets = sortByKey(data.months, 'month');

const internalCatIdYnab = data.category_groups.find(
group => group.name === 'Internal Master Category',
).id;
const creditcardCatIdYnab = data.category_groups.find(
group => group.name === 'Credit Card Payments',
).id;
const internalCatIdYnab = findIdByName(
data.category_groups,
'Internal Master Category',
);
const creditcardCatIdYnab = findIdByName(
data.category_groups,
'Credit Card Payments',
);

await actual.batchBudgetUpdates(async () => {
for (const budget of budgets) {
Expand Down Expand Up @@ -327,3 +327,19 @@ export function parseFile(buffer: Buffer): YNAB5.Budget {
export function getBudgetName(_filepath: string, data: YNAB5.Budget) {
return data.budget_name || data.name;
}

function equalsIgnoreCase(stringa: string, stringb: string): boolean {
return (
stringa.localeCompare(stringb, undefined, {
sensitivity: 'base',
}) === 0
);
}

function findByNameIgnoreCase(categories: YNAB5.CategoryGroup[], name: string) {
return categories.find(cat => equalsIgnoreCase(cat.name, name));
}

function findIdByName(categories: YNAB5.CategoryGroup[], name: string) {
return findByNameIgnoreCase(categories, name)?.id;
}
6 changes: 6 additions & 0 deletions upcoming-release-notes/2191.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
category: Bugfix
authors: [Marethyu1]
---

Allow case insensitive ynab5 import for special 'starting balance' payee

0 comments on commit 540c410

Please sign in to comment.