import test from 'node:test'; import assert from 'node:assert/strict'; import fs from 'node:fs'; import { newReducedBase, switchReducedTreatment, reducedBaseConditions, ownReducedConditions, reducedBaseTreatments, publicWorkCategories, evaluateReducedBase, recordReducedBases, saveReducedBaseBook, reducedBaseBook, reducedBaseCurrent, reducedBaseReportRows, } from '../../resources/js/lib/iva-reduced-bases.ts'; const frozen = JSON.parse( fs.readFileSync( 'tests/frontend/fixtures/iva-g7-reduced-preserved.json', 'utf8', ), ); const draft = { ...frozen, currency: 'MZN', context_opportunity: 'opportunity:351', project_title: 'SYNTHETIC QA — G7 bases reduzidas / Manica', }; function row(t) { const rule = reducedBaseTreatments.find((x) => x.id === t); return { ...newReducedBase(t, 'MZN'), treatment: t, description: 'SYNTHETIC QA ' + rule.branch, period: '2026-12', origin: 'projected', operationDate: '2026-12-12', documentRef: 'SYNTHETIC QA documento/pressuposto', documentDate: '2026-12-12', priceScope: 'SYNTHETIC QA objecto/operação/local/período', priceRef: 'SYNTHETIC QA preço/taxa aplicável', priceFrom: '2026-01-01', priceTo: '2026-12-31', consideration: '1000.25', compositionRef: 'SYNTHETIC QA total antes redução,semIVA,15(1)/(5)/(6)', evidence: 'SYNTHETIC QA pressupostos expressos', projectRef: 'SYNTHETIC QA projecto público/contrato', workCategory: 'roads', conditions: Object.fromEntries( [...reducedBaseConditions, ...ownReducedConditions(t)].map( ([key]) => [key, 'yes'], ), ), }; } const expected = ['620.155', '850.2125', '400.10', '750.1875']; for (const [i, rule] of reducedBaseTreatments.entries()) void test( rule.branch + ' ownconditions,exact base and separate deduction proportion', () => { const r = row(rule.id), result = evaluateReducedBase(r, 'MZN'); assert.equal(result.status, 'determined'); assert.equal(result.baseAmount, expected[i]); assert.equal(result.deductionProportion, rule.percent + '%'); assert.equal(result.vat, null); assert.equal(result.rate, null); for (const [key] of [ ...reducedBaseConditions, ...ownReducedConditions(rule.id), ]) { const missing = structuredClone(r); delete missing.conditions[key]; assert.equal( evaluateReducedBase(missing, 'MZN').status, 'indeterminate', ); missing.conditions[key] = 'no'; assert.equal( evaluateReducedBase(missing, 'MZN').status, 'not_applicable', ); assert.equal( evaluateReducedBase(missing, 'MZN').baseAmount, null, ); assert.equal( evaluateReducedBase(missing, 'MZN').deductionProportion, null, ); } for (const field of [ 'description', 'documentRef', 'priceScope', 'compositionRef', 'evidence', 'consideration', ]) assert.equal( evaluateReducedBase({ ...r, [field]: '' }, 'MZN').status, 'indeterminate', field, ); for (const patch of [ { operationDate: '2026-11-12' }, { documentDate: '2026-02-30' }, { period: '2025-12' }, { currency: 'USD' }, { consideration: '1,5' }, { consideration: '-1' }, { consideration: '1e3' }, ]) assert.equal( evaluateReducedBase({ ...r, ...patch }, 'MZN').status, 'indeterminate', ); assert.equal(evaluateReducedBase(r, 'USD').status, 'indeterminate'); assert.equal( evaluateReducedBase({ ...r, consideration: '0' }, 'MZN') .baseAmount, '0.00', ); if (rule.id === 'public_works') { assert.equal( evaluateReducedBase( { ...r, priceRef: '', priceFrom: '', priceTo: '' }, 'MZN', ).baseAmount, expected[i], ); for (const c of publicWorkCategories) assert.equal( evaluateReducedBase({ ...r, workCategory: c.id }, 'MZN') .status, 'determined', ); assert.equal( evaluateReducedBase( { ...r, workCategory: 'private_work' }, 'MZN', ).status, 'indeterminate', ); assert.equal( evaluateReducedBase({ ...r, projectRef: '' }, 'MZN').status, 'indeterminate', ); assert.match(result.reason, /base40%/); } else { for (const patch of [ { priceRef: '' }, { priceFrom: '' }, { priceFrom: '2027-01-01' }, { priceTo: '2026-11-30' }, { priceTo: '2025-12-31' }, ]) assert.equal( evaluateReducedBase({ ...r, ...patch }, 'MZN').status, 'indeterminate', ); assert.equal( evaluateReducedBase({ ...r, priceTo: '' }, 'MZN').status, 'determined', ); } }, ); void test('Exactfraction retained,no 60percent works base,no duplicate reduction and no automatic deduction', () => { assert.equal( evaluateReducedBase( { ...row('regulated_energy'), consideration: '0.000001' }, 'MZN', ).baseAmount, '0.00000062', ); assert.equal( evaluateReducedBase( { ...row('public_works'), consideration: '0.000001' }, 'MZN', ).baseAmount, '0.0000004', ); assert.equal( evaluateReducedBase( { ...row('public_water'), consideration: '999999999999999.999999' }, 'MZN', ).baseAmount, '749999999999999.99999925', ); const reduced = row('public_works'); reduced.conditions.fullNetInvoice = 'no'; assert.equal(evaluateReducedBase(reduced, 'MZN').baseAmount, null); const changed = switchReducedTreatment( row('regulated_energy'), 'public_works', ); assert.equal(changed.priceRef, row('regulated_energy').priceRef); assert.equal(changed.projectRef, row('regulated_energy').projectRef); assert.equal(changed.conditions.publicWorks, undefined); assert.equal(evaluateReducedBase(changed, 'MZN').status, 'indeterminate'); }); void test('Four branches save/recover/history/report and all previous books are preserved', () => { const rows = reducedBaseTreatments.map((t) => row(t.id)); let book = recordReducedBases(draft, { rows }); book = recordReducedBases(draft, book); assert.equal(book.history.length, 1); assert.notEqual(book.result.inputs, book.rows); const next = { ...draft, modelo_a_snapshot: saveReducedBaseBook(draft, book), }; assert.deepEqual(reducedBaseBook(next), book); assert.ok(reducedBaseCurrent(next, book)); assert.equal(reducedBaseCurrent({ ...next, currency: 'USD' }, book), false); assert.equal( reducedBaseCurrent({ ...next, context_opportunity: 'other' }, book), false, ); assert.equal(reducedBaseReportRows(next).length, 4); for (const t of reducedBaseTreatments) assert.ok( reducedBaseReportRows(next).some((r) => r[1].includes(t.branch)), ); const store = JSON.parse(next.modelo_a_snapshot); delete store.regulatedReducedBases; assert.deepEqual(store, JSON.parse(frozen.modelo_a_snapshot)); assert.throws(() => recordReducedBases(next, { rows: [rows[0], rows[0]] })); assert.throws(() => reducedBaseBook({ ...next, modelo_a_snapshot: JSON.stringify({ ...JSON.parse(next.modelo_a_snapshot), regulatedReducedBases: [], }), }), ); if (process.env.IVA_REDUCED_FIXTURE) fs.writeFileSync( process.env.IVA_REDUCED_FIXTURE, JSON.stringify(next, null, 2) + '\n', ); });