import test from 'node:test'; import assert from 'node:assert/strict'; import fs from 'node:fs'; import { newFuelBase, switchFuelTaxTreatment, fuelBaseTreatments, fuelBaseConditions, evaluateFuelBase, recordFuelBases, saveFuelBaseBook, fuelBaseBook, fuelBaseCurrent, fuelBaseReportRows, } from '../../resources/js/lib/iva-fuel-base.ts'; import { actSaleCurrent } from '../../resources/js/lib/iva-act-sale-base.ts'; import { commissionBaseCurrent } from '../../resources/js/lib/iva-commission-base.ts'; import { createProjectDossierReport } from '../../resources/js/lib/project-dossier-report.ts'; const frozen = JSON.parse( fs.readFileSync( new URL('./fixtures/iva-g7d-preserved-inputs.json', import.meta.url), 'utf8', ), ); const row = (treatment = fuelBaseTreatments[0].id) => ({ ...newFuelBase('g7d-' + treatment, 'MZN'), treatment, description: 'SYNTHETIC QA revenda de combustível A', period: '2026-12', operationDate: '2026-12-12', priceRef: 'SYNTHETIC QA referência preço A / Autoridade Pública', priceScope: 'SYNTHETIC QA combustível A, revenda A, Manica, dezembro2026, pressupostos', priceFrom: '2026-12-01', priceTo: '2026-12-31', documentRef: 'SYNTHETIC QA G7D ' + treatment, documentDate: '2026-12-12', consideration: '1500.25', fuelTax: '100.10', fuelTaxRef: 'SYNTHETIC QA TC desta operação sem estimar taxa', compositionRef: 'SYNTHETIC QA composição15(1)/(5)/(6),líquida de IVA', evidence: 'SYNTHETIC QA pressupostos expressos,não documento real', conditions: Object.fromEntries( fuelBaseConditions.map(([key]) => [key, 'yes']), ), }); const draft = () => ({ ...structuredClone(frozen), context_opportunity: 'opportunity:342', project_title: 'SYNTHETIC QA — G7D / Bases de combustíveis', }); void test('P095 own resale/price/scope/composition conditions; missing references and wrong date never become zero', () => { for (const rule of fuelBaseTreatments) { const input = row(rule.id), ok = evaluateFuelBase(input, 'MZN'); assert.equal(ok.status, 'determined'); assert.equal( ok.baseAmount, rule.id === 'fuel_tax_included' ? '1400.15' : '1500.25', ); assert.equal(ok.vat, null); assert.equal(ok.rate, null); for (const [key] of fuelBaseConditions) for (const value of ['', 'unknown', 'no']) { const r = evaluateFuelBase( { ...input, conditions: { ...input.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 [ { description: '' }, { priceRef: '' }, { priceScope: '' }, { documentRef: '' }, { documentDate: '2026-02-30' }, { compositionRef: '' }, { evidence: '' }, { period: '2025-12' }, { currency: 'USD' }, { treatment: 'unknown' }, { operationDate: '2026-11-12' }, { operationDate: '2026-02-30' }, { priceFrom: '' }, { priceTo: 'invalid' }, { priceFrom: '2026-12-20' }, { priceTo: '2026-12-11' }, { priceFrom: '2026-12-31', priceTo: '2026-12-01' }, ]) assert.equal( evaluateFuelBase({ ...input, ...patch }, 'MZN').baseAmount, null, ); assert.equal( evaluateFuelBase({ ...input, priceTo: '' }, 'MZN').status, 'determined', ); for (const operationDate of ['2026-12-01', '2026-12-31']) assert.equal( evaluateFuelBase({ ...input, operationDate }, 'MZN').status, 'determined', ); } }); void test('TC subtracted exactly once only when included; zero,precision,excess and treatment changes preserve inputs', () => { const input = row(); for (const [patch, expected] of [ [{ consideration: '0', fuelTax: '0' }, '0.00'], [{ consideration: '1.000002', fuelTax: '0.000001' }, '1.000001'], [ { consideration: '999999999999999.999999', fuelTax: '0.000001' }, '999999999999999.999998', ], [ { treatment: 'fuel_tax_excluded', fuelTax: 'invalid', fuelTaxRef: '', }, '1500.25', ], ]) assert.equal( evaluateFuelBase({ ...input, ...patch }, 'MZN').baseAmount, expected, ); for (const patch of [ { consideration: '' }, { fuelTax: '' }, { fuelTaxRef: '' }, { consideration: '-1' }, { fuelTax: 'NaN' }, { fuelTax: '0.0000001' }, { fuelTax: '1500.26' }, ]) assert.equal( evaluateFuelBase({ ...input, ...patch }, 'MZN').baseAmount, null, ); const switched = switchFuelTaxTreatment(input, 'fuel_tax_excluded'); assert.equal(switched.conditions.fuelTaxTreatment, ''); for (const field of [ 'consideration', 'fuelTax', 'fuelTaxRef', 'priceRef', 'priceScope', 'priceFrom', 'priceTo', 'documentRef', ]) assert.equal(switched[field], input[field]); assert.equal(evaluateFuelBase(switched, 'MZN').baseAmount, null); assert.equal( evaluateFuelBase( { ...switched, conditions: { ...switched.conditions, fuelTaxTreatment: 'yes' }, }, 'MZN', ).baseAmount, '1500.25', ); }); void test('save/recovery/history/report preserve all81 delivered books including P094/P091 and currentkeys', () => { const d = draft(), prior = JSON.parse(d.modelo_a_snapshot); assert.deepEqual(fuelBaseBook(d), { rows: [] }); assert.deepEqual(fuelBaseReportRows(d), []); let book = recordFuelBases(d, { rows: fuelBaseTreatments.map((rule) => ({ ...row(rule.id), conditions: {}, })), }); book = recordFuelBases(d, { ...book, rows: fuelBaseTreatments.map((rule) => ({ ...row(rule.id), conditions: { ...row(rule.id).conditions, publicFixedPrice: 'no' }, })), }); book = recordFuelBases(d, { ...book, rows: fuelBaseTreatments.map((rule) => row(rule.id)), }); assert.equal(book.history.length, 2); assert.ok( book.history.every((h) => h.rows.every((r) => r.baseAmount === null && r.vat === null), ), ); assert.ok(fuelBaseCurrent(d, book)); for (const field of [ 'treatment', 'consideration', 'fuelTax', 'fuelTaxRef', 'priceRef', 'priceScope', 'priceFrom', 'priceTo', 'operationDate', ]) assert.ok( !fuelBaseCurrent(d, { ...book, rows: book.rows.map((r) => ({ ...r, [field]: 'changed' })), }), ); for (const patch of [ { context_opportunity: 'opportunity:343' }, { currency: 'USD' }, { selection_labels: { province_id: 'Maputo' } }, ]) assert.ok(!fuelBaseCurrent({ ...d, ...patch }, book)); d.modelo_a_snapshot = saveFuelBaseBook(d, book); assert.deepEqual(fuelBaseBook(JSON.parse(JSON.stringify(d))), book); const next = JSON.parse(d.modelo_a_snapshot); const { regulatedFuelBases: _regulatedFuelBases, ...untouched } = next; assert.deepEqual(untouched, prior); for (const [scope, previous] of Object.entries(prior.actSaleBases)) assert.ok( actSaleCurrent({ ...d, context_opportunity: scope }, previous), ); for (const [scope, previous] of Object.entries(prior.commissionBases)) assert.ok( commissionBaseCurrent( { ...d, context_opportunity: scope }, previous, ), ); assert.equal( next.actSaleBases['opportunity:341'].result.rows[1].baseAmount, '2200.50', ); assert.equal( next.commissionBases['opportunity:340'].result.rows[0].baseAmount, '900.15', ); assert.equal( next.publicAuthorityBases['opportunity:339'].result.rows[0].vat, null, ); 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 G7D', }), ); for (const token of [ 'Base P095', '1400.15', '1500.25', 'IVA: Indeterminado', 'opportunity:342', 'Manica', '2026-12-12', 'preço A', '15(2)(i)', '100.10', '2026-12-01', '2026-12-31', 'campo11', ]) assert.ok(report.includes(token), token); assert.deepEqual( fuelBaseReportRows({ ...d, context_opportunity: 'opportunity:343' }), [], ); if (process.env.IVA_G7D_CALCULATED) fs.writeFileSync(process.env.IVA_G7D_CALCULATED, JSON.stringify(d)); }); void test('corrupt fuel rows/store cannot overwrite originals; duplicate operation identifiers cannot be recorded', () => { const d = draft(), original = d.modelo_a_snapshot; for (const patch of [ { fuelTax: 4 }, { conditions: [] }, { priceRef: null }, ]) assert.throws( () => saveFuelBaseBook(d, { rows: [{ ...row(), ...patch }] }), /originais preservados/, ); assert.equal(d.modelo_a_snapshot, original); assert.throws( () => recordFuelBases(d, { rows: [row(), row()] }), /distintos/, ); assert.throws(() => recordFuelBases(d, { rows: [] }), /distintos/); assert.throws( () => fuelBaseBook({ ...d, modelo_a_snapshot: JSON.stringify({ ...JSON.parse(original), regulatedFuelBases: [], }), }), /originais preservados/, ); });