import test from 'node:test'; import assert from 'node:assert/strict'; import fs from 'node:fs'; import { newExclusionBase, newExclusionPart, switchExclusionPart, exclusionTreatments, exclusionConditions, partConditions, evaluateExclusion, recordExclusions, saveExclusionBook, exclusionBook, exclusionCurrent, exclusionReportRows, } from '../../resources/js/lib/iva-exclusion-base.ts'; import { compositionCurrent } from '../../resources/js/lib/iva-composition-base.ts'; import { fuelBaseCurrent } from '../../resources/js/lib/iva-fuel-base.ts'; import { createProjectDossierReport } from '../../resources/js/lib/project-dossier-report.ts'; const frozen = JSON.parse( fs.readFileSync( new URL('./fixtures/iva-g7g-preserved-inputs.json', import.meta.url), 'utf8', ), ); const part = (treatment = 'judicial_indemnity', id = treatment) => ({ ...newExclusionPart(id), treatment, description: 'SYNTHETIC QA ' + treatment, amount: { judicial_indemnity: '100.10', granted_discount: '50.25', third_party_payment: '30.15', returnable_packaging: '20.05', }[treatment], included: 'yes', reference: 'SYNTHETIC QA referência ' + id + ' / declaração judicial e contrato quando aplicável', scope: 'SYNTHETIC QA operação A,montante e condições deste tratamento', accountRef: 'SYNTHETIC QA contas de terceiros A', beneficiaryRef: 'SYNTHETIC QA adquirente B', documentExcerpt: 'SYNTHETIC QA factura A,embalagens separadas,devolução acordada expressamente', conditions: Object.fromEntries( partConditions(treatment).map(([key]) => [key, 'yes']), ), }); const row = () => ({ ...newExclusionBase('g7g-operation-A', 'MZN'), description: 'SYNTHETIC QA exclusões operação A', period: '2026-12', operationRef: 'SYNTHETIC QA operação A', initialAmount: '1000.25', initialRef: 'SYNTHETIC QA montante sem próprioIVA,inclusões15(5)consideradas', documentRef: 'SYNTHETIC QA G7G documento A', documentDate: '2026-12-12', exclusionRef: 'SYNTHETIC QA quatro exclusões reconciliadas,sem duplicação', evidence: 'SYNTHETIC QA pressupostos expressos,não documento real', conditions: Object.fromEntries( exclusionConditions.map(([key]) => [key, 'yes']), ), parts: exclusionTreatments.map((t) => part(t.id)), }); const draft = () => ({ ...structuredClone(frozen), context_opportunity: 'opportunity:345', project_title: 'SYNTHETIC QA — G7G / Exclusões da contraprestação', }); void test('P102 four treatments each own statutoryconditions and references;unknown/no never become automatic exclusion', () => { const input = row(), ok = evaluateExclusion(input, 'MZN'); assert.equal(ok.baseAmount, '799.70'); assert.equal(ok.vat, null); assert.equal(ok.rate, null); for (const [key] of exclusionConditions) for (const value of ['', 'unknown', 'no']) { const r = evaluateExclusion( { ...input, conditions: { ...input.conditions, [key]: value } }, 'MZN', ); assert.equal( r.status, value === 'no' ? 'not_applicable' : 'indeterminate', ); assert.equal(r.baseAmount, null); } for (const t of exclusionTreatments) { const p = part(t.id); assert.equal( evaluateExclusion({ ...input, parts: [p] }, 'MZN').status, 'determined', ); for (const [key] of partConditions(t.id)) for (const value of ['', 'unknown', 'no']) { const r = evaluateExclusion( { ...input, parts: [ { ...p, conditions: { ...p.conditions, [key]: value }, }, ], }, 'MZN', ); assert.equal( r.status, value === 'no' ? 'not_applicable' : 'indeterminate', ); assert.equal(r.baseAmount, null); assert.equal(r.vat, null); } for (const patch of [ { reference: '' }, { scope: '' }, { description: '' }, { included: '' }, { amount: '' }, ]) assert.equal( evaluateExclusion( { ...input, parts: [{ ...p, ...patch }] }, 'MZN', ).baseAmount, null, ); } for (const patch of [ { description: '' }, { operationRef: '' }, { initialRef: '' }, { documentRef: '' }, { documentDate: '2026-02-30' }, { exclusionRef: '' }, { evidence: '' }, { period: '2025-12' }, { currency: 'USD' }, ]) assert.equal( evaluateExclusion({ ...input, ...patch }, 'MZN').baseAmount, null, ); for (const patch of [{ accountRef: '' }, { beneficiaryRef: '' }]) assert.equal( evaluateExclusion( { ...input, parts: [{ ...part('third_party_payment'), ...patch }], }, 'MZN', ).baseAmount, null, ); assert.equal( evaluateExclusion( { ...input, parts: [ { ...part('returnable_packaging'), documentExcerpt: '' }, ], }, 'MZN', ).baseAmount, null, ); }); void test('subtract included exclusions only,alreadyexcluded retained;exactdecimal/zero/excess;switch retains unrelated references and clearsconditions', () => { const input = row(); assert.equal( evaluateExclusion( { ...input, parts: input.parts.map((p) => ({ ...p, included: 'no' })), }, 'MZN', ).baseAmount, '1000.25', ); assert.equal( evaluateExclusion( { ...input, parts: input.parts.map((p) => ({ ...p, included: p.treatment === 'judicial_indemnity' ? 'no' : 'yes', })), }, 'MZN', ).baseAmount, '899.80', ); assert.equal( evaluateExclusion( { ...input, initialAmount: '0', parts: [{ ...part(), amount: '0' }], }, 'MZN', ).baseAmount, '0.00', ); assert.equal( evaluateExclusion( { ...input, initialAmount: '1.000002', parts: [{ ...part(), amount: '0.000001' }], }, 'MZN', ).baseAmount, '1.000001', ); assert.equal( evaluateExclusion( { ...input, initialAmount: '999999999999999.999999', parts: [{ ...part(), amount: '0.000001' }], }, 'MZN', ).baseAmount, '999999999999999.999998', ); for (const amount of ['-1', 'NaN', '0.0000001', '', '1000.26']) assert.equal( evaluateExclusion( { ...input, parts: [{ ...part(), amount }] }, 'MZN', ).baseAmount, null, ); assert.equal( evaluateExclusion({ ...input, initialAmount: '' }, 'MZN').baseAmount, null, ); const switched = switchExclusionPart( part('third_party_payment'), 'returnable_packaging', ); assert.deepEqual(switched.conditions, {}); for (const field of [ 'amount', 'reference', 'scope', 'accountRef', 'beneficiaryRef', 'documentExcerpt', 'included', ]) assert.equal(switched[field], part('third_party_payment')[field]); assert.equal( evaluateExclusion({ ...input, parts: [switched] }, 'MZN').baseAmount, null, ); assert.equal( evaluateExclusion({ ...input, parts: [] }, 'MZN').baseAmount, null, ); assert.equal( evaluateExclusion({ ...input, parts: [part(), part()] }, 'MZN') .baseAmount, null, ); }); void test('save/recovery/history/report keep one base/four exclusions and all84 previous books/currentkeys unchanged', () => { const d = draft(), prior = JSON.parse(d.modelo_a_snapshot); assert.deepEqual(exclusionBook(d), { rows: [] }); assert.deepEqual(exclusionReportRows(d), []); let book = recordExclusions(d, { rows: [{ ...row(), conditions: {} }] }); book = recordExclusions(d, { ...book, rows: [ { ...row(), parts: [ { ...part('granted_discount'), conditions: { granted: 'no' }, }, ], }, ], }); book = recordExclusions(d, { ...book, rows: [row()] }); assert.equal(book.history.length, 2); assert.ok( book.history.every((h) => h.rows.every((r) => r.baseAmount === null && r.vat === null), ), ); assert.ok(exclusionCurrent(d, book)); assert.equal(book.result.rows.length, 1); assert.equal(book.result.inputs[0].parts.length, 4); for (const field of [ 'amount', 'included', 'reference', 'treatment', 'scope', 'accountRef', 'beneficiaryRef', 'documentExcerpt', ]) assert.ok( !exclusionCurrent(d, { ...book, rows: book.rows.map((r) => ({ ...r, parts: r.parts.map((p) => ({ ...p, [field]: 'changed' })), })), }), ); for (const patch of [ { context_opportunity: 'opportunity:346' }, { currency: 'USD' }, { selection_labels: { province_id: 'Maputo' } }, ]) assert.ok(!exclusionCurrent({ ...d, ...patch }, book)); d.modelo_a_snapshot = saveExclusionBook(d, book); assert.deepEqual(exclusionBook(JSON.parse(JSON.stringify(d))), book); const next = JSON.parse(d.modelo_a_snapshot); const { considerationExclusions: _considerationExclusions, ...untouched } = next; assert.deepEqual(untouched, prior); for (const [scope, previous] of Object.entries( prior.considerationCompositions, )) assert.ok( compositionCurrent({ ...d, context_opportunity: scope }, previous), ); for (const [scope, previous] of Object.entries(prior.regulatedFuelBases)) assert.ok( fuelBaseCurrent({ ...d, context_opportunity: scope }, previous), ); assert.equal( next.considerationCompositions['opportunity:344'].result.rows[0] .baseAmount, '1150.60', ); assert.equal( next.noncashBases['opportunity:343'].result.rows[1].baseAmount, '2700.75', ); assert.equal( next.regulatedFuelBases['opportunity:342'].result.rows[0].baseAmount, '1400.15', ); assert.equal( next.importExemptions['opportunity:338'].result.rows[1].importVat, '400.00', ); assert.equal( next.books['opportunity:329'].result.periods[0].fields['11'], null, ); const report = JSON.stringify( createProjectDossierReport(d, { selectedSections: new Set(['finance']), version: 'QA G7G', }), ); for (const token of [ 'Base P102', '799.70', 'IVA: Indeterminado', 'opportunity:345', 'Manica', '2026-12', 'operação A', '15(6)', '100.10', '27(5)(b)', 'contas de terceiros A', 'devolução acordada', 'campo11', ]) assert.ok(report.includes(token), token); assert.equal(exclusionReportRows(d).length, 1); assert.deepEqual( exclusionReportRows({ ...d, context_opportunity: 'opportunity:346' }), [], ); if (process.env.IVA_G7G_CALCULATED) fs.writeFileSync(process.env.IVA_G7G_CALCULATED, JSON.stringify(d)); }); void test('corrupt nested exclusions/store cannot overwrite originals;duplicate operation ids cannot be recorded', () => { const d = draft(), original = d.modelo_a_snapshot; for (const patch of [ { initialAmount: 4 }, { conditions: [] }, { parts: {} }, { parts: [{ ...part(), amount: 4 }] }, { parts: [{ ...part(), conditions: [] }] }, { parts: [null] }, ]) assert.throws( () => saveExclusionBook(d, { rows: [{ ...row(), ...patch }] }), /originais preservados/, ); assert.equal(d.modelo_a_snapshot, original); assert.throws( () => recordExclusions(d, { rows: [row(), row()] }), /distintos/, ); assert.throws(() => recordExclusions(d, { rows: [] }), /distintos/); assert.throws( () => exclusionBook({ ...d, modelo_a_snapshot: JSON.stringify({ ...JSON.parse(original), considerationExclusions: [], }), }), /originais preservados/, ); });