Skip to content

Commit

Permalink
Merge branch 'master' into zach/simplefin
Browse files Browse the repository at this point in the history
  • Loading branch information
zachwhelchel authored Jan 11, 2024
2 parents bca5dc3 + 6de1fe3 commit a907efa
Show file tree
Hide file tree
Showing 19 changed files with 773 additions and 23 deletions.
19 changes: 19 additions & 0 deletions migrations/1702667624000-rename-nordigen-secrets.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import getAccountDb from '../src/account-db.js';

export const up = async function () {
await getAccountDb().exec(
`UPDATE secrets SET name = 'gocardless_secretId' WHERE name = 'nordigen_secretId'`,
);
await getAccountDb().exec(
`UPDATE secrets SET name = 'gocardless_secretKey' WHERE name = 'nordigen_secretKey'`,
);
};

export const down = async function () {
await getAccountDb().exec(
`UPDATE secrets SET name = 'nordigen_secretId' WHERE name = 'gocardless_secretId'`,
);
await getAccountDb().exec(
`UPDATE secrets SET name = 'nordigen_secretKey' WHERE name = 'gocardless_secretKey'`,
);
};
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "actual-sync",
"version": "23.12.1",
"version": "24.1.0",
"license": "MIT",
"description": "actual syncing server",
"type": "module",
Expand All @@ -16,7 +16,7 @@
},
"dependencies": {
"@actual-app/crdt": "2.1.0",
"@actual-app/web": "23.12.0",
"@actual-app/web": "24.1.0",
"bcrypt": "^5.1.0",
"better-sqlite3": "^9.1.1",
"body-parser": "^1.20.1",
Expand Down
4 changes: 4 additions & 0 deletions src/app-gocardless/bank-factory.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import AmericanExpressAesudef1 from './banks/american-express-aesudef1.js';
import IngIngddeff from './banks/ing-ingddeff.js';
import IngPlIngbplpw from './banks/ing-pl-ingbplpw.js';
import IntegrationBank from './banks/integration-bank.js';
import MbankRetailBrexplpw from './banks/mbank-retail-brexplpw.js';
Expand All @@ -8,9 +9,11 @@ import BnpBeGebabebb from './banks/bnp-be-gebabebb.js';
import DanskeBankDabNO22 from './banks/danskebank-dabno22.js';
import SparNordSpNoDK22 from './banks/sparnord-spnodk22.js';
import Belfius from './banks/belfius_gkccbebb.js';
import SpkMarburgBiedenkopfHeladef1mar from './banks/spk-marburg-biedenkopf-heladef1mar.js';

const banks = [
AmericanExpressAesudef1,
IngIngddeff,
IngPlIngbplpw,
MbankRetailBrexplpw,
SandboxfinanceSfin0000,
Expand All @@ -19,6 +22,7 @@ const banks = [
DanskeBankDabNO22,
SparNordSpNoDK22,
Belfius,
SpkMarburgBiedenkopfHeladef1mar,
];

export default (institutionId) =>
Expand Down
56 changes: 56 additions & 0 deletions src/app-gocardless/banks/ing-ingddeff.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { printIban, amountToInteger } from '../utils.js';

/** @type {import('./bank.interface.js').IBank} */
export default {
institutionIds: ['ING_INGDDEFF'],

normalizeAccount(account) {
return {
account_id: account.id,
institution: account.institution,
mask: account.iban.slice(-4),
iban: account.iban,
name: [account.product, printIban(account)].join(' '),
official_name: account.product,
type: 'checking',
};
},

normalizeTransaction(transaction, _booked) {
const remittanceInformationMatch = /remittanceinformation:(.*)$/.exec(
transaction.remittanceInformationUnstructured,
);
const remittanceInformation = remittanceInformationMatch
? remittanceInformationMatch[1]
: transaction.remittanceInformationUnstructured;

return {
...transaction,
remittanceInformationUnstructured: remittanceInformation,
date: transaction.bookingDate || transaction.valueDate,
};
},

sortTransactions(transactions = []) {
return transactions.sort((a, b) => {
const diff =
+new Date(b.valueDate || b.bookingDate) -
+new Date(a.valueDate || a.bookingDate);
if (diff) return diff;
const idA = parseInt(a.transactionId);
const idB = parseInt(b.transactionId);
if (!isNaN(idA) && !isNaN(idB)) return idB - idA;
return 0;
});
},

calculateStartingBalance(sortedTransactions = [], balances = []) {
const currentBalance = balances.find(
(balance) => 'interimBooked' === balance.balanceType,
);

return sortedTransactions.reduce((total, trans) => {
return total - amountToInteger(trans.transactionAmount.amount);
}, amountToInteger(currentBalance.balanceAmount.amount));
},
};
4 changes: 2 additions & 2 deletions src/app-gocardless/banks/sparnord-spnodk22.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const SORTED_BALANCE_TYPE_LIST = [

/** @type {import('./bank.interface.js').IBank} */
export default {
institutionIds: ['SPARNORD_SPNODK22'],
institutionIds: ['SPARNORD_SPNODK22', 'LAGERNES_BANK_LAPNDKK1'],

normalizeAccount(account) {
return {
Expand All @@ -33,7 +33,7 @@ export default {
},

/**
* Spar Nord only gives information regarding the transaction in additionalInformation
* Banks on the BEC backend only give information regarding the transaction in additionalInformation
*/
normalizeTransaction(transaction, _booked) {
return {
Expand Down
87 changes: 87 additions & 0 deletions src/app-gocardless/banks/spk-marburg-biedenkopf-heladef1mar.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import {
printIban,
amountToInteger,
sortByBookingDateOrValueDate,
} from '../utils.js';
import d from 'date-fns';

const SORTED_BALANCE_TYPE_LIST = [
'closingBooked',
'expected',
'forwardAvailable',
'interimAvailable',
'interimBooked',
'nonInvoiced',
'openingBooked',
];

/** @type {import('./bank.interface.js').IBank} */
export default {
institutionIds: ['SPK_MARBURG_BIEDENKOPF_HELADEF1MAR'],

normalizeAccount(account) {
return {
account_id: account.id,
institution: account.institution,
mask: (account?.iban || '0000').slice(-4),
iban: account?.iban || null,
name: [account.product, printIban(account), account.currency]
.filter(Boolean)
.join(' '),
official_name: account.product,
type: 'checking',
};
},

normalizeTransaction(transaction, _booked) {
const date =
transaction.bookingDate ||
transaction.bookingDateTime ||
transaction.valueDate ||
transaction.valueDateTime;

// If we couldn't find a valid date field we filter out this transaction
// and hope that we will import it again once the bank has processed the
// transaction further.
if (!date) {
return null;
}

let remittanceInformationUnstructured;

if (transaction.remittanceInformationUnstructured) {
remittanceInformationUnstructured =
transaction.remittanceInformationUnstructured;
} else if (transaction.remittanceInformationStructured) {
remittanceInformationUnstructured =
transaction.remittanceInformationStructured;
} else if (transaction.remittanceInformationStructuredArray?.length > 0) {
remittanceInformationUnstructured =
transaction.remittanceInformationStructuredArray?.join(' ');
}

return {
...transaction,
date: d.format(d.parseISO(date), 'yyyy-MM-dd'),
remittanceInformationUnstructured: remittanceInformationUnstructured,
};
},

sortTransactions(transactions = []) {
return sortByBookingDateOrValueDate(transactions);
},

calculateStartingBalance(sortedTransactions = [], balances = []) {
const currentBalance = balances
.filter((item) => SORTED_BALANCE_TYPE_LIST.includes(item.balanceType))
.sort(
(a, b) =>
SORTED_BALANCE_TYPE_LIST.indexOf(a.balanceType) -
SORTED_BALANCE_TYPE_LIST.indexOf(b.balanceType),
)[0];

return sortedTransactions.reduce((total, trans) => {
return total - amountToInteger(trans.transactionAmount.amount);
}, amountToInteger(currentBalance?.balanceAmount?.amount || 0));
},
};
Loading

0 comments on commit a907efa

Please sign in to comment.