UNPKG

actual-moneymoney

Version:

An importer for syncing MoneyMoney accounts and transactions to Actual.

96 lines (95 loc) 4.9 kB
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; import { getAccounts } from 'moneymoney'; export class AccountMap { constructor(budgetConfig, logger, actualApi) { this.budgetConfig = budgetConfig; this.logger = logger; this.actualApi = actualApi; } getMap(moneyMoneyAccountRefs) { if (!moneyMoneyAccountRefs) return this.mapping; const customMap = new Map(); for (const ref of moneyMoneyAccountRefs) { const monMonAccount = this.getMoneyMoneyAccountByRef(ref); if (!monMonAccount) { this.logger.error(`Specified account ref '${ref}' did not resolve to any MoneyMoney accounts.`); continue; } const actualAccount = this.mapping.get(monMonAccount); if (!actualAccount) { this.logger.error(`Could not find an Actual account for specified MoneyMoney account with ref '${ref}'.`); continue; } customMap.set(monMonAccount, actualAccount); } return customMap; } checkMoneyMoneyAccountRef(account, ref) { return (account.uuid === ref || account.accountNumber === ref || account.name === ref); } getMoneyMoneyAccountByRef(ref) { const matchingAccounts = this.moneyMoneyAccounts.filter((acc) => this.checkMoneyMoneyAccountRef(acc, ref)); if (matchingAccounts.length === 0) { this.logger.warn(`No MoneyMoney account found for reference '${ref}'.`); return null; } else if (matchingAccounts.length > 1) { this.logger.warn(`Found multiple MoneyMoney accounts matching the reference '${ref}'. Using the first one.`); } return matchingAccounts[0]; } checkActualAccountRef(account, ref) { return account.id === ref || account.name === ref; } getActualAccountByRef(ref) { const matchingAccounts = this.actualAccounts.filter((acc) => this.checkActualAccountRef(acc, ref)); if (matchingAccounts.length === 0) { this.logger.warn(`No Actual account found for reference '${ref}'.`); return null; } else if (matchingAccounts.length > 1) { this.logger.warn(`Found multiple Actual accounts matching the reference '${ref}'. Using the first one.`); } return matchingAccounts[0]; } loadFromConfig() { return __awaiter(this, void 0, void 0, function* () { if (this.mapping) return; const accountMapping = this.budgetConfig.accountMapping; const parsedAccountMapping = new Map(); this.moneyMoneyAccounts = yield getAccounts(); this.logger.debug(`Found ${this.moneyMoneyAccounts.length} accounts in MoneyMoney.`); this.actualAccounts = yield this.actualApi.getAccounts(); this.logger.debug(`Found ${this.actualAccounts.length} accounts in Actual.`); this.logger.debug(`Account mapping contains ${Object.entries(accountMapping).length} entries.`); for (const [moneyMoneyRef, actualRef] of Object.entries(accountMapping)) { const moneyMoneyAccount = this.getMoneyMoneyAccountByRef(moneyMoneyRef); const actualAccount = this.getActualAccountByRef(actualRef); if (!actualAccount) { this.logger.debug(`No Actual account found for reference '${actualRef}'. Skipping...`); continue; } else if (!moneyMoneyAccount) { this.logger.debug(`No MoneyMoney account found for reference '${moneyMoneyRef}'. Skipping...`); continue; } this.logger.debug(`MoneyMoney account '${moneyMoneyAccount.name}' will import to Actual account '${actualAccount.name}'.`); parsedAccountMapping.set(moneyMoneyAccount, actualAccount); } this.logger.info('Parsed account mapping', Array.from(parsedAccountMapping.entries()).map(([monMonAccount, actualAccount]) => `${monMonAccount.name} → ${actualAccount.name}`)); this.mapping = parsedAccountMapping; }); } }