// Generated, do not edit. sha256:defdf4c970fac7940f2bd495e2911283709af51809bb6a2d4c4f9c43ed032b8f import * as db from '../db.js'; import { toSearchName } from '../../shared/search-name.js'; import { nowUtcIso } from '../../shared/time.js'; import { ENUMS } from '../../shared/config.js'; import { assertEnum, assertName, assertTaxCategory, assertTaxScope, assertWealthScope } from './_shared.js'; import { capacityReachedFor } from './_limits.js'; import { fail } from '../../shared/app-error.js'; import { purgeWalletSourceSecret } from './wallet-sources.js'; import { accountPositions } from './positions.js'; import { trackUpdate, trackDelete } from './change-log.js'; export function listAccounts() { return db.all(`SELECT * FROM Account ORDER BY name`); } export function listSelectableAccounts({ metGesloten = false, ookId = null } = {}) { return metGesloten ? db.all(`SELECT * FROM Account ORDER BY isActive DESC, name`) : db.all(`SELECT * FROM Account WHERE isActive = 1 OR id = ?1 ORDER BY isActive DESC, name`, [ookId ?? null]); } export async function createAccount({ name, kind, isOwnCustody, scanEnabled, taxCategory, taxScope, wealthScope }) { assertEnum('kind', ENUMS.ACCOUNT_KIND, kind); if (kind === 'bank') { const max = capacityReachedFor('fiatAccounts'); if (max !== null) { fail('accounts.maxFreeBank', { max }, `The free version holds ${max} fiat account(s). A licence lifts that; nothing is removed in the meantime.`); } } const naam = assertName('Accountnaam', name); const categorie = assertTaxCategory(taxCategory); const scope = assertTaxScope(taxScope); const wealth = assertWealthScope(wealthScope); db.run(`INSERT INTO Account (name, searchName, kind, isOwnCustody, scanEnabled, isActive, closedAt, taxCategory, taxScope, wealthScope) VALUES (?,?,?,?,?,1,NULL,?,?,?)`, [naam, toSearchName(naam), kind, isOwnCustody ? 1 : 0, scanEnabled ? 1 : 0, categorie, scope, wealth]); const id = db.lastId(); await db.persist(); return id; } export async function updateAccount(id, a) { assertEnum('kind', ENUMS.ACCOUNT_KIND, a.kind); const naam = assertName('Accountnaam', a.name); const categorie = assertTaxCategory(a.taxCategory); const scopeGiven = Object.hasOwn(a, 'taxScope'); const scope = scopeGiven ? assertTaxScope(a.taxScope) : null; const wealthGiven = Object.hasOwn(a, 'wealthScope'); const wealth = wealthGiven ? assertWealthScope(a.wealthScope) : null; trackUpdate('Account', id, () => db.run(`UPDATE Account SET name=?, searchName=?, kind=?, isOwnCustody=?, scanEnabled=?, taxCategory=?, taxScope = CASE WHEN ? THEN ? ELSE taxScope END, wealthScope = CASE WHEN ? THEN ? ELSE wealthScope END WHERE id=?`, [naam, toSearchName(naam), a.kind, a.isOwnCustody ? 1 : 0, a.scanEnabled ? 1 : 0, categorie, scopeGiven ? 1 : 0, scope, wealthGiven ? 1 : 0, wealth, id])); await db.persist(); } export async function deleteAccount(id) { const used = db.one(`SELECT (SELECT COUNT(*) FROM Event WHERE fromAccountId=?1 OR toAccountId=?1) + (SELECT COUNT(*) FROM Valuation WHERE accountId =?1) + (SELECT COUNT(*) FROM ScanLog WHERE accountId=?1) + (SELECT COUNT(*) FROM ReconcileProposal WHERE accountId=?1) AS n`, [id]).n; if (used > 0) fail('accounts.inUse', { n: used }, `Account is used by ${used} record(s); remove or relink those first.`); for (const s of db.all(`SELECT id FROM WalletSource WHERE accountId=? AND kind='nwc'`, [id])) { await purgeWalletSourceSecret(s.id); } trackDelete('Account', id, () => db.run(`DELETE FROM Account WHERE id=?`, [id])); await db.persist(); } export function deactivateCheck(accountId) { const account = db.one(`SELECT * FROM Account WHERE id = ?`, [accountId]); if (!account) return { found: false, findings: [] }; const n = (sql, params = [accountId]) => db.one(sql, params).n; const findings = []; if (account.scanEnabled) { findings.push({ kind: 'scanEnabled', count: 1 }); } const sources = n(`SELECT COUNT(*) AS n FROM WalletSource WHERE accountId = ?`); if (sources) findings.push({ kind: 'walletSources', count: sources }); const vandaag = new Date().toISOString().slice(0, 10); const schedules = n( `SELECT COUNT(*) AS n FROM InterestSchedule WHERE accountId = ? AND (endsOn IS NULL OR endsOn >= ?)`, [accountId, vandaag]); if (schedules) findings.push({ kind: 'openSchedules', count: schedules }); const proposals = n(`SELECT COUNT(*) AS n FROM ReconcileProposal WHERE accountId = ? AND status = 'pending'`); if (proposals) findings.push({ kind: 'pendingProposals', count: proposals }); const balances = accountPositions(accountId); if (balances.length) findings.push({ kind: 'balance', count: balances.length, balances }); const events = n(`SELECT COUNT(*) AS n FROM Event WHERE fromAccountId = ?1 OR toAccountId = ?1`); if (events) findings.push({ kind: 'events', count: events, informational: true }); return { found: true, isActive: !!account.isActive, name: account.name, findings }; } export async function deactivateAccount(id, closedAt = nowUtcIso()) { const account = db.one(`SELECT isActive FROM Account WHERE id = ?`, [id]); if (!account) fail('accounts.unknownAccount', { id }, `Account #${id} does not exist.`); trackUpdate('Account', id, () => db.run(`UPDATE Account SET isActive = 0, closedAt = ?, scanEnabled = 0 WHERE id = ?`, [closedAt, id])); await db.persist(); } export async function reactivateAccount(id) { const account = db.one(`SELECT isActive FROM Account WHERE id = ?`, [id]); if (!account) fail('accounts.unknownAccount', { id }, `Account #${id} does not exist.`); trackUpdate('Account', id, () => db.run(`UPDATE Account SET isActive = 1, closedAt = NULL WHERE id = ?`, [id])); await db.persist(); }