import test from 'node:test'; import assert from 'node:assert/strict'; import fs from 'node:fs'; import { recordSales, saveSalesBook, } from '../../resources/js/lib/iva-operations.ts'; import { recordAcquisitions, saveAcquisitionBook, acquisitionBook, acquisitionCurrent, } from '../../resources/js/lib/iva-acquisitions.ts'; import { closureBook, closureSources, newClosure, newClosureCredit, recordClosure, saveClosureBook, adoptPreviousCredit, closureCurrent, closureReportRows, } from '../../resources/js/lib/iva-closure.ts'; const preserved = JSON.parse( fs.readFileSync( new URL('./fixtures/iva-l3ab-preserved.json', import.meta.url), 'utf8', ), ); export function closureFixture() { const draft = { ...structuredClone(preserved), context_opportunity: 'opportunity:373', project_title: 'SYNTHETIC QA — L3-A/B fecho do IVA', }; const s = JSON.parse(draft.modelo_a_snapshot), base = s.books['opportunity:370']; const sales = ['2026-01', '2026-02', '2026-03'].map((period, i) => ({ ...structuredClone(s.salesOperations['opportunity:370'].rows[0]), id: 'sale-' + i, period, amount: i === 1 ? '500' : '1000', sourcePeriod: period, })); draft.modelo_a_snapshot = saveSalesBook( draft, recordSales(draft, { currency: 'MZN', rows: sales, periods: sales.map((r) => ({ period: r.period, complete: true })), }), ); const purchase = { ...structuredClone(base.rows[0]), id: 'purchase-Jan', period: '2026-01', documentDate: '2026-01-10', documentRef: 'SYNTHETIC QA aquisiçãoJaneiro', net: '1625', vat: '260', gross: '1885', d: { ...structuredClone(base.rows[0].d), numerator: '1', denominator: '1', }, }; const acquisitions = recordAcquisitions(draft, { currency: 'MZN', taxpayerRegistered: 'yes', rows: [purchase], periods: sales.map((r) => ({ period: r.period, complete: true, importsComplete: true, absent: ['12', '13'], })), }); draft.modelo_a_snapshot = saveAcquisitionBook(draft, acquisitions); const make = (period) => ({ ...newClosure( 'close-' + period, closureSources(draft).find((s) => s.period === period), 'SYNTHETIC QA entidade373', ), firstDeclaration: 'yes', creditsComplete: 'yes', filing: 'timely', submissionDate: `2026-${String(Number(period.slice(5)) + 1).padStart(2, '0')}-15`, filingRef: 'SYNTHETIC QA entrega em prazo assumida', interest: 'none', interestRef: 'SYNTHETIC QA pressuposto sem juros', destination: 'report', }); const jan = make('2026-01'); jan.credits = [ { ...newClosureCredit('opening', 'opening'), period: '2025-12', reference: 'SYNTHETIC QA saldoabertura', amount: '50', }, ]; let book = recordClosure(draft, { version: 1, rows: [jan] }); const feb = make('2026-02'); feb.credits = [ adoptPreviousCredit( newClosureCredit('carry-Feb', 'previous'), book.result.rows[0], ), ]; book = recordClosure(draft, { ...book, rows: [jan, feb] }); const mar = make('2026-03'); mar.credits = [ adoptPreviousCredit( newClosureCredit('carry-Mar', 'previous'), book.result.rows[1], ), { ...newClosureCredit('communication', 'communication'), period: '2026-02', reference: 'SYNTHETIC QA comunicaçãoAT20', date: '2026-03-10', amount: '20', }, ]; mar.interest = 'documented'; mar.interestAmount = '2'; mar.interestRef = 'SYNTHETIC QA jurosidentificados'; mar.payments = [ { id: 'payment1', reference: 'SYNTHETIC QA reciboP1', date: '2026-04-16', amount: '30', }, ]; book = recordClosure(draft, { ...book, rows: [jan, feb, mar] }); return { draft, book, make, acquisitions }; } const amount = (r, f) => r.fields[f] && `${r.fields[f].numerator}/${r.fields[f].denominator}`; void test('three periods reconcile opening credit,carry,communicated credit,interest and payment without double deduction', () => { const { draft, book } = closureFixture(); assert.deepEqual( book.result.rows.map((r) => r.status), ['determined', 'determined', 'determined'], ); assert.deepEqual( book.result.rows.map((r) => amount(r, '26')), ['150/1', '70/1', '0/1'], ); const mar = book.result.rows[2]; assert.equal(amount(mar, '19'), '70/1'); assert.equal(amount(mar, '20'), '20/1'); assert.equal(amount(mar, '22'), '70/1'); assert.equal(amount(mar, '24'), '72/1'); assert.deepEqual(mar.paid, { numerator: '30', denominator: '1' }); assert.deepEqual(mar.outstanding, { numerator: '42', denominator: '1' }); assert.equal(mar.fields['21'], null); assert.equal(amount(mar, '27'), '0/1'); assert.ok(acquisitionCurrent(draft, acquisitionBook(draft))); assert.equal(book.history.length, 2); }); void test('origin,coverage,deadline and unsupported paths remain explicit;unknown never becomes zero', () => { const { draft, book } = closureFixture(); for (const patch of [ { creditsComplete: '' }, { filing: '' }, { filing: 'late' }, { firstDeclaration: 'no' }, { entityRef: '' }, { submissionDate: '' }, { destination: 'refund' }, ]) { const changed = structuredClone(book); changed.rows[0] = { ...changed.rows[0], ...patch }; const r = recordClosure(draft, changed).result.rows; assert.equal(r[0].status, 'indeterminate', JSON.stringify(patch)); assert.equal(r[1].status, 'indeterminate'); } const interest = structuredClone(book); interest.rows[2].interest = ''; const r = recordClosure(draft, interest).result.rows[2]; assert.equal(amount(r, '22'), '70/1'); assert.equal(r.fields['24'], null); const future = structuredClone(book); future.rows[2].credits[1].date = '2026-05-01'; assert.equal( recordClosure(draft, future).result.rows[2].fields['20'], null, ); const effective = structuredClone(book); effective.rows[0].origin = 'effective'; assert.match( recordClosure(draft, effective).result.rows[0].reason, /projectados/, ); }); void test('duplicate documents,opening versus communication and payment references cannot create duplicate use', () => { const { draft, book } = closureFixture(); const b = structuredClone(book); b.rows[0].credits.push({ ...b.rows[0].credits[0], id: 'copy' }); assert.equal(recordClosure(draft, b).result.rows[0].fields['19'], null); const cross = structuredClone(book); cross.rows[0].credits.push({ ...cross.rows[0].credits[0], id: 'copy', kind: 'communication', date: '2026-01-05', }); assert.equal(recordClosure(draft, cross).result.rows[0].fields['19'], null); const payments = structuredClone(book); payments.rows[2].payments.push({ ...payments.rows[2].payments[0], id: 'copy', }); const p = recordClosure(draft, payments).result.rows[2]; assert.equal(p.paid, null); assert.equal(amount(p, '26'), '0/1'); assert.equal(amount(p, '24'), '72/1'); const opening = structuredClone(book); opening.rows[1].credits = [ { ...opening.rows[0].credits[0], id: 'new-opening', period: '2026-01' }, ]; assert.match( recordClosure(draft, opening).result.rows[1].reason, /reutilize26/, ); }); void test('changing a predecessor preserves historical results and requires explicit carry adoption;payment edit does not change carry', () => { const { draft, book } = closureFixture(); const first = structuredClone(book.result); let changed = structuredClone(book); changed.rows[0].credits[0].amount = '60'; assert.equal(closureCurrent(draft, changed), false); changed = recordClosure(draft, changed); assert.equal(amount(changed.result.rows[0], '26'), '160/1'); assert.equal(changed.result.rows[1].status, 'indeterminate'); assert.deepEqual(changed.history.at(-1), first); changed.rows[1].credits[0] = adoptPreviousCredit( changed.rows[1].credits[0], changed.result.rows[0], ); changed = recordClosure(draft, changed); assert.equal(amount(changed.result.rows[1], '26'), '80/1'); assert.equal(changed.result.rows[2].status, 'indeterminate'); changed.rows[2].credits[0] = adoptPreviousCredit( changed.rows[2].credits[0], changed.result.rows[1], ); changed = recordClosure(draft, changed); assert.equal(amount(changed.result.rows[2], '22'), '60/1'); const pay = structuredClone(book); pay.rows[0].payments = [ { id: 'unexpected', reference: 'SYNTHETIC QA pagamentoanterior', date: '2026-02-16', amount: '1', }, ]; const v = recordClosure(draft, pay); assert.equal(v.result.rows[0].carryKey, first.rows[0].carryKey); assert.equal(v.result.rows[1].status, 'determined'); }); void test('overpayment remains a payment fact and does not create credit20/25/26', () => { const { draft, book } = closureFixture(); book.rows[2].payments[0].amount = '100'; const r = recordClosure(draft, book).result.rows[2]; assert.deepEqual(r.overpayment, { numerator: '28', denominator: '1' }); assert.equal(amount(r, '20'), '20/1'); assert.equal(amount(r, '25'), '0/1'); assert.equal(amount(r, '26'), '0/1'); }); void test('carry between periods preserves exact fractions instead of adding rounded presentation', () => { const { draft, book } = closureFixture(); let a = acquisitionBook(draft); a.rows[0].net = '3125'; a.rows[0].vat = '500'; a.rows[0].gross = '3625'; a.rows[0].d.denominator = '3'; a = recordAcquisitions(draft, a); draft.modelo_a_snapshot = saveAcquisitionBook(draft, a); book.rows[0].source = closureSources(draft).find( (s) => s.revision === a.result.revision && s.period === '2026-01', ); let b = recordClosure(draft, book); assert.deepEqual(b.result.rows[0].fields['26'], { numerator: '170', denominator: '3', }); b.rows[1].credits[0] = adoptPreviousCredit( b.rows[1].credits[0], b.result.rows[0], ); b = recordClosure(draft, b); assert.deepEqual(b.result.rows[1].fields['22'], { numerator: '70', denominator: '3', }); }); void test('recovered opportunities keep scenarios separate and expose collisions of effective scope', () => { const { draft, book } = closureFixture(); const other = structuredClone(book); const store = JSON.parse(draft.modelo_a_snapshot); store.ivaClosures = { 'opportunity:other': other }; draft.modelo_a_snapshot = JSON.stringify(store); assert.equal( recordClosure(draft, book).result.rows[0].status, 'determined', 'projected scenarios do not consume each other', ); book.rows[0].origin = 'effective'; other.rows[0].origin = 'effective'; store.ivaClosures['opportunity:other'] = other; draft.modelo_a_snapshot = JSON.stringify(store); assert.match( recordClosure(draft, book).result.rows[0].reason, /noutra oportunidade/, ); }); void test('frozen L2 sources are reused exactly and incomplete or fabricated sources cannot close balances', () => { const { draft, book } = closureFixture(); const b = structuredClone(book); b.rows[0].source.credit = { numerator: '999', denominator: '1' }; assert.equal( recordClosure(draft, b).result.rows[0].status, 'indeterminate', ); const removed = { ...draft }; const s = JSON.parse(draft.modelo_a_snapshot); delete s.books['opportunity:373'].result; removed.modelo_a_snapshot = JSON.stringify(s); assert.equal( recordClosure(removed, book).result.rows[0].fields['18'], null, ); assert.deepEqual( acquisitionBook(draft).result.periods.map((p) => [ p.fields['17'], p.fields['18'], ]), [ ['0.00', '100.00'], ['80.00', '0.00'], ['160.00', '0.00'], ], ); const unchanged = recordAcquisitions(draft, acquisitionBook(draft)); const extraVersion = { ...draft, modelo_a_snapshot: saveAcquisitionBook(draft, unchanged), }; assert.ok( closureCurrent(extraVersion, book), 'adding an unrelated L2 version does not rewrite or stale the selected frozen results', ); }); void test('save recovery and report preserve every prior L1/L2 map,values and closure histories', () => { let { draft, book } = closureFixture(); const before = JSON.parse(preserved.modelo_a_snapshot); const acquired = structuredClone(acquisitionBook(draft)); draft.modelo_a_snapshot = saveClosureBook(draft, book); const recovered = JSON.parse(JSON.stringify(draft)); assert.deepEqual(closureBook(recovered), book); assert.ok(closureCurrent(recovered, book)); assert.ok(acquisitionCurrent(recovered, acquisitionBook(recovered))); assert.deepEqual(acquisitionBook(recovered), acquired); const after = JSON.parse(recovered.modelo_a_snapshot); for (const [k, map] of Object.entries(before)) { if (k === 'version') continue; for (const [id, v] of Object.entries(map)) assert.deepEqual(after[k][id], v, k + id); } const report = JSON.stringify(closureReportRows(recovered)); for (const token of [ '2026-01', '2026-02', '2026-03', '150/1', '70/1', '72/1', '30/1', '42/1', 'saldoabertura', 'comunicaçãoAT20', 'reciboP1', 'opportunity:373', ]) assert.ok(report.includes(token), token); const malformed = JSON.parse(recovered.modelo_a_snapshot); malformed.ivaClosures = null; assert.throws( () => closureBook({ ...recovered, modelo_a_snapshot: JSON.stringify(malformed), }), /não recuperável/, ); book.rows[0].credits[0].amount = '999'; const edited = { ...recovered, modelo_a_snapshot: saveClosureBook(recovered, book), }; assert.equal(closureCurrent(edited, book), false); assert.match(JSON.stringify(closureReportRows(edited)), /50/); assert.equal(book.result.inputs[0].credits[0].amount, '50'); if (process.env.IVA_L3AB_CALCULATED) fs.writeFileSync( process.env.IVA_L3AB_CALCULATED, JSON.stringify(recovered), ); });