import test from 'node:test'; import assert from 'node:assert/strict'; import fs from 'node:fs'; import { newRegularization, evaluateRegularization, recordRegularizations, saveRegularizationBook, regularizationBook, regularizationFields, regularizationsCurrent, frozenAssetRows, } from '../../resources/js/lib/iva-regularizations.ts'; import { acquisitionBook, recordAcquisitions, saveAcquisitionBook, acquisitionCurrent, acquisitionReportRows, readAcquisitionStore, } from '../../resources/js/lib/iva-acquisitions.ts'; import { recordSales, saveSalesBook, } from '../../resources/js/lib/iva-operations.ts'; const frozen = JSON.parse( fs.readFileSync( new URL('./fixtures/iva-l2e-preserved.json', import.meta.url), 'utf8', ), ); export function regularizationFixture() { const draft = structuredClone(frozen); draft.context_opportunity = 'opportunity:370'; draft.project_title = 'SYNTHETIC QA — L2-E activos e regularizações'; const source = structuredClone(acquisitionBook(draft).result); const annual = { ...newRegularization('annual-2026', 'annual', source), numerator: '2', denominator: '3', reference: 'SYNTHETIC QA contas anuais2026', reason: 'SYNTHETIC QA âmbito anual da entidade', facts: { scope: 'yes', recorded: 'yes', annual: 'yes', exclusions: 'yes', }, }; const correction = { ...newRegularization('credit-note', 'purchase_correction', source), rowIds: ['actual'], receivedDate: '2026-12-15', correctedDeductible: '4', reference: 'SYNTHETIC QA nota de créditoNC1', reason: 'SYNTHETIC QA redução da aquisição', facts: { scope: 'yes', recorded: 'yes', supplierCorrection: 'yes', rightUnchanged: 'yes', }, }; return { draft, annual, correction, book: { version: 1, events: [annual, correction], completePeriods: ['2026-12'], }, }; } void test('annual adjustment uses frozen C-limited input and actually deducted D,ceil final ratio and both signs', () => { const { draft, annual } = regularizationFixture(); let r = evaluateRegularization(draft, annual); assert.equal(r.status, 'determined'); assert.deepEqual(r.rawRatio, { numerator: '2', denominator: '3' }); assert.deepEqual(r.ratio, { numerator: '67', denominator: '100' }); assert.deepEqual(r.delta, { numerator: '132', denominator: '25' }); assert.match(r.reason, /campo12/); r = evaluateRegularization(draft, { ...annual, numerator: '1', denominator: '2', }); assert.deepEqual(r.delta, { numerator: '-4', denominator: '25' }); assert.match(r.reason, /campo13/); for (const patch of [ { period: '2026-11' }, { denominator: '0' }, { numerator: '4' }, { reference: '' }, { rowIds: ['actual'] }, { rowIds: ['missing'] }, { facts: { ...annual.facts, annual: '' } }, { facts: { ...annual.facts, recorded: '' } }, ]) assert.equal( evaluateRegularization(draft, { ...annual, ...patch }).delta, null, JSON.stringify(patch), ); const altered = structuredClone(draft); const book = acquisitionBook(altered); book.rows[1].d.numerator = '3'; altered.modelo_a_snapshot = saveAcquisitionBook(altered, book); assert.deepEqual( evaluateRegularization(altered, annual).delta, { numerator: '132', denominator: '25' }, 'current edits never recalculate historical deduction', ); const fabricated = structuredClone(annual); fabricated.source.rows[1].deductibleExact.numerator = '0'; assert.equal(evaluateRegularization(draft, fabricated).delta, null); }); void test('credit note keeps exact historical fraction,receipt deadline and source conditions;unsupported increase stays unknown', () => { const { draft, correction } = regularizationFixture(); const r = evaluateRegularization(draft, correction); assert.deepEqual(r.delta, { numerator: '-4', denominator: '3' }); assert.match(r.reason, /campo13/); for (const patch of [ { period: '2026-11' }, { receivedDate: '2026-02-30' }, { receivedDate: '2026-10-10' }, { correctedDeductible: '6' }, { correctedDeductible: '' }, { facts: { ...correction.facts, supplierCorrection: '' } }, { rowIds: ['actual', 'diesel'] }, ]) assert.equal( evaluateRegularization(draft, { ...correction, ...patch }).delta, null, JSON.stringify(patch), ); assert.deepEqual( evaluateRegularization(draft, { ...correction, correctedDeductible: '0', }).delta, { numerator: '-16', denominator: '3' }, ); }); void test('F uses exact 12/13 once,requires coverage and detects stale E without overwriting D history or other opportunities', () => { let { draft, book } = regularizationFixture(); const before = JSON.parse(draft.modelo_a_snapshot); book = recordRegularizations(draft, book); draft.modelo_a_snapshot = saveRegularizationBook(draft, book); const acquired = acquisitionBook(draft); assert.equal(acquisitionCurrent(draft, acquired), false); assert.throws(() => recordAcquisitions(draft, acquired), /ausência12\/13/); acquired.periods[0].absent = acquired.periods[0].absent.filter( (f) => !['12', '13'].includes(f), ); const adjusted = recordAcquisitions(draft, acquired); draft.modelo_a_snapshot = saveAcquisitionBook(draft, adjusted); const p = adjusted.result.periods[0]; assert.deepEqual( ['12', '13', '15', '16', '17', '18'].map((f) => p.fields[f]), ['5.28', '1.333333', '29.44', '161.333333', '131.893333', '0.00'], ); assert.deepEqual(p.exactFields['13'], { numerator: '4', denominator: '3' }); assert.ok(acquisitionCurrent(draft, adjusted)); assert.ok(regularizationsCurrent(draft, book)); assert.deepEqual( adjusted.history.at(-1), before.books['opportunity:370'].result, ); const after = JSON.parse(draft.modelo_a_snapshot); for (const [k, map] of Object.entries(before)) { if (k === 'version') continue; for (const [id, v] of Object.entries(map)) { if (k === 'books' && id === 'opportunity:370') continue; assert.deepEqual(after[k][id], v, k + id); } } for (const id of ['opportunity:368', 'opportunity:369', 'opportunity:371']) assert.ok( acquisitionCurrent( { ...draft, context_opportunity: id }, after.books[id], ), ); const incomplete = { ...book, completePeriods: [] }; assert.equal( regularizationFields( { ...draft, modelo_a_snapshot: saveRegularizationBook(draft, incomplete), }, '2026-12', ).fields['12'], null, ); const divergent = structuredClone(adjusted); divergent.rows[1].d.numerator = '2'; assert.equal( recordAcquisitions(draft, divergent).result.periods[0].fields['15'], null, 'changed original deduction must be reconciled before F', ); const changed = structuredClone(book); changed.events[0].numerator = '1'; draft.modelo_a_snapshot = saveRegularizationBook(draft, changed); assert.equal(acquisitionCurrent(draft, adjusted), false); assert.equal(regularizationFields(draft, '2026-12').fields['13'], null); assert.deepEqual(changed.result, book.result); }); void test('F retains reduced-output uncertainty even when only E events remain in the current period book', () => { let { draft, book } = regularizationFixture(); book = recordRegularizations(draft, book); draft.modelo_a_snapshot = saveRegularizationBook(draft, book); const acquisitions = { ...acquisitionBook(draft), rows: [], periods: [ { period: '2026-12', complete: true, importsComplete: true, absent: [], }, ], }; const first = recordAcquisitions(draft, acquisitions); draft.modelo_a_snapshot = saveAcquisitionBook(draft, first); assert.equal(first.result.periods[0].fields['15'], '5.28'); const s = JSON.parse(draft.modelo_a_snapshot); s.regulatedReducedBases['opportunity:370'] = structuredClone( s.regulatedReducedBases['opportunity:371'], ); draft.modelo_a_snapshot = JSON.stringify(s); assert.equal(acquisitionCurrent(draft, first), false); const result = recordAcquisitions(draft, first).result; assert.equal(result.periods[0].fields['15'], '5.28'); for (const f of ['14', '16', '17', '18']) assert.equal(result.periods[0].fields[f], null, f); }); void test('annual adjustment composes C exclusion before D exactly once,including a projected investment asset', () => { let { draft } = regularizationFixture(); let b = acquisitionBook(draft); const diesel = structuredClone(b.rows[2]); diesel.id = 'diesel-pro-rata'; diesel.field = '08'; diesel.documentRef = 'SYNTHETIC QA activo gasóleo'; diesel.d.method = 'pro_rata'; b = recordAcquisitions(draft, { ...b, rows: [diesel], result: undefined, history: undefined, }); draft.modelo_a_snapshot = saveAcquisitionBook(draft, b); const e = { ...newRegularization('annual-diesel', 'annual', b.result), numerator: '2', denominator: '3', reference: 'SYNTHETIC QA anual', reason: 'SYNTHETIC QA âmbito', facts: { scope: 'yes', recorded: 'yes', annual: 'yes', exclusions: 'yes', }, }; assert.deepEqual(b.result.rows[0].allocationCalculation.before, { numerator: '8', denominator: '1', }); assert.deepEqual(evaluateRegularization(draft, e).delta, { numerator: '66', denominator: '25', }); }); void test('deduplication includes original document/line across revisions and rejects unsequenced annual plus credit note', () => { const { draft, book, annual, correction } = regularizationFixture(); assert.throws( () => recordRegularizations(draft, { ...book, events: [annual, { ...annual, id: 'duplicate' }], }), /Mesma aquisição/, ); assert.throws( () => recordRegularizations(draft, { ...book, events: [correction, { ...correction, id: 'other' }], }), /Mesma aquisição/, ); assert.throws( () => recordRegularizations(draft, { ...book, events: [annual, { ...correction, rowIds: ['pro-rata'] }], }), /sequencial/, ); }); void test('investment imports retain customs field11 while entering the frozen asset control register', () => { const { draft } = regularizationFixture(); let b = acquisitionBook(draft); b.rows[3].investmentAsset = true; b = recordAcquisitions(draft, b); draft.modelo_a_snapshot = saveAcquisitionBook(draft, b); assert.equal(b.result.periods[0].fields['11'], '10.72'); const register = JSON.stringify(frozenAssetRows(draft)); assert.match(register, /import-due/); assert.match(register, /268\/25/); assert.equal(b.rows[3].field, '11'); }); void test('unrecoverable E source or fraction is visible and a missing calculated event never turns into zero', () => { const { draft, book } = regularizationFixture(); const saved = recordRegularizations(draft, book); const incomplete = structuredClone(saved); incomplete.result.events = []; const altered = { ...draft, modelo_a_snapshot: saveRegularizationBook(draft, incomplete), }; assert.equal(regularizationFields(altered, '2026-12').fields['12'], null); for (const mutate of [ (b) => (b.events[0].source = {}), (b) => (b.result.events[0].delta.denominator = '0'), (b) => (b.events[0].facts.scope = 'maybe'), ]) { const bad = structuredClone(saved); mutate(bad); assert.throws( () => readAcquisitionStore(saveRegularizationBook(draft, bad)), /Regulariza|regulariza/, ); } }); void test('asset register reuses frozen acquisition values and E save/recovery/report preserves source,history and prior maps', () => { let { draft, book } = regularizationFixture(); book = recordRegularizations(draft, book); const first = structuredClone(book.result); book = recordRegularizations(draft, book); assert.deepEqual(book.history, [first]); draft.modelo_a_snapshot = saveRegularizationBook(draft, book); let acquired = acquisitionBook(draft); acquired.periods[0].absent = acquired.periods[0].absent.filter( (f) => !['12', '13'].includes(f), ); acquired = recordAcquisitions(draft, acquired); draft.modelo_a_snapshot = saveAcquisitionBook(draft, acquired); const assetDraft = { ...draft, context_opportunity: 'opportunity:372' }; const s = JSON.parse(draft.modelo_a_snapshot); assetDraft.modelo_a_snapshot = saveSalesBook( assetDraft, recordSales( assetDraft, structuredClone(s.salesOperations['opportunity:370']), ), ); const asset = structuredClone(acquired.rows[0]); asset.id = 'asset-control'; asset.field = '08'; asset.description = 'SYNTHETIC QA activo de investimento'; asset.documentRef = 'SYNTHETIC QA activo1'; const assetBook = recordAcquisitions(assetDraft, { currency: 'MZN', taxpayerRegistered: 'yes', rows: [asset], periods: [ { period: '2026-12', complete: true, importsComplete: true, absent: ['12', '13'], }, ], }); assetDraft.modelo_a_snapshot = saveAcquisitionBook(assetDraft, assetBook); const report = JSON.stringify(frozenAssetRows(assetDraft)); for (const token of [ 'activo1', '2026-12-10', '16/3', 'RCIVA27', 'IVA suportado16', ]) assert.ok(report.includes(token), token); const recovered = JSON.parse( JSON.stringify({ ...assetDraft, context_opportunity: 'opportunity:370', }), ); assert.deepEqual(regularizationBook(recovered), book); const text = JSON.stringify(acquisitionReportRows(recovered)); for (const token of [ 'Regularização annual-2026', '5.28', '4/3', '131.893333', 'Pressuposto', '22(4–8)', ]) assert.ok(text.includes(token), token); if (process.env.IVA_L2E_CALCULATED) fs.writeFileSync( process.env.IVA_L2E_CALCULATED, JSON.stringify(recovered), ); });