// Generated, do not edit. sha256:ebad02dba29ae50bcbaf9c21bb59936cf43f6be868e86ac00d0e6055f404b26f import * as db from '../db.js'; import { ACCOUNT_SOURCE_KINDS } from '../../shared/config.js'; import { fail } from '../../shared/app-error.js'; import { eventsNetByAccount } from './events.js'; import { trackUpdate, trackUpdateWhere, trackDelete, trackDeleteWhere, withOrigin } from './change-log.js'; function mergeCompatibility(survivor, victim) { const S = ACCOUNT_SOURCE_KINDS[survivor.kind] || []; const V = ACCOUNT_SOURCE_KINDS[victim.kind] || []; if ((S.length === 0) !== (V.length === 0)) { return { ok: false, reason: 'sourceMismatch' }; } if (V.some(k => !S.includes(k))) { return { ok: false, reason: 'kindCannotCarry' }; } return { ok: true, reason: null }; } export function mergeCheck(survivorId, victimId) { if (!survivorId || !victimId) return { ok: false, reason: 'pickTwo', counts: null }; if (Number(survivorId) === Number(victimId)) return { ok: false, reason: 'sameAccount', counts: null }; const survivor = db.one(`SELECT * FROM Account WHERE id=?`, [survivorId]); const victim = db.one(`SELECT * FROM Account WHERE id=?`, [victimId]); if (!survivor || !victim) return { ok: false, reason: 'notFound', counts: null }; const compat = mergeCompatibility(survivor, victim); const counts = { sources: db.one(`SELECT COUNT(*) AS n FROM WalletSource WHERE accountId=?`, [victimId]).n, events: db.one(`SELECT COUNT(*) AS n FROM Event WHERE fromAccountId=?1 OR toAccountId=?1`, [victimId]).n, schedules: db.one(`SELECT COUNT(*) AS n FROM InterestSchedule WHERE accountId=?`, [victimId]).n, valuations: db.one(`SELECT COUNT(*) AS n FROM Valuation WHERE accountId =?`, [victimId]).n, }; return { ok: compat.ok, reason: compat.reason, counts, survivorName: survivor.name, victimName: victim.name }; } export async function mergeAccounts(survivorId, victimId) { survivorId = Number(survivorId); victimId = Number(victimId); const chk = mergeCheck(survivorId, victimId); if (!chk.ok) fail(`accounts.mergeReason_${chk.reason}`, null, `Merge not possible (${chk.reason}).`); return withOrigin('merge', victimId, () => voerSamenvoegingUit(survivorId, victimId, chk)); } async function voerSamenvoegingUit(survivorId, victimId, chk) { const preDiff = new Map(); for (const v of db.all(`SELECT id, accountId, assetId, rateAt, balance FROM Valuation WHERE accountId = ?1 OR accountId = ?2`, [survivorId, victimId])) { preDiff.set(v.id, v.balance - eventsNetByAccount(v.accountId, v.assetId, v.rateAt)); } trackUpdateWhere('Event', `fromAccountId = ?`, [victimId], () => db.run(`UPDATE Event SET fromAccountId=?1 WHERE fromAccountId=?2`, [survivorId, victimId])); trackUpdateWhere('Event', `toAccountId = ?`, [victimId], () => db.run(`UPDATE Event SET toAccountId=?1 WHERE toAccountId=?2`, [survivorId, victimId])); trackUpdateWhere('WalletSource', `accountId = ?`, [victimId], () => db.run(`UPDATE WalletSource SET accountId=?1 WHERE accountId=?2`, [survivorId, victimId])); db.run(`UPDATE WalletAddress SET accountId=?1 WHERE accountId=?2`, [survivorId, victimId]); db.run(`UPDATE WalletTransaction SET accountId=?1 WHERE accountId=?2`, [survivorId, victimId]); db.run(`UPDATE ScanLog SET accountId=?1 WHERE accountId=?2`, [survivorId, victimId]); db.run(`UPDATE ReconcileProposal SET accountId=?1 WHERE accountId=?2`, [survivorId, victimId]); db.run(`UPDATE ImportBatch SET accountId=?1 WHERE accountId=?2`, [survivorId, victimId]); trackUpdateWhere('InterestSchedule', `accountId = ?`, [victimId], () => db.run(`UPDATE InterestSchedule SET accountId=?1 WHERE accountId=?2`, [survivorId, victimId])); trackDeleteWhere('Valuation', `accountId = ?2 AND EXISTS (SELECT 1 FROM Valuation v2 WHERE v2.accountId = ?1 AND v2.assetId=Valuation.assetId AND v2.valuedOn=Valuation.valuedOn)`, [survivorId, victimId], () => db.run(`DELETE FROM Valuation WHERE accountId =?2 AND EXISTS (SELECT 1 FROM Valuation v2 WHERE v2.accountId =?1 AND v2.assetId=Valuation.assetId AND v2.valuedOn=Valuation.valuedOn)`, [survivorId, victimId])); trackUpdateWhere('Valuation', `accountId = ?`, [victimId], () => db.run(`UPDATE Valuation SET accountId =?1 WHERE accountId = ?2`, [survivorId, victimId])); for (const [id, diff] of preDiff) { const v = db.one(`SELECT id, assetId, rateAt FROM Valuation WHERE id=?`, [id]); if (!v) continue; const newNet = eventsNetByAccount(survivorId, v.assetId, v.rateAt); trackUpdate('Valuation', id, () => db.run(`UPDATE Valuation SET balance=? WHERE id=?`, [newNet + diff, id])); } trackDelete('Account', victimId, () => db.run(`DELETE FROM Account WHERE id=?`, [victimId])); await db.persist(); return chk.counts; }