import test from 'node:test'; import assert from 'node:assert/strict'; import fs from 'node:fs'; import { newImportExemption, evaluateImportExemption, recordImportExemptions, saveImportExemptionBook, importExemptionBook, importExemptionCurrent, importExemptionRules, importDevelopmentSource, importDevelopmentFields, } from '../../resources/js/lib/iva-import-exemptions.ts'; import { createProjectDossierReport } from '../../resources/js/lib/project-dossier-report.ts'; const frozen = JSON.parse( fs.readFileSync( new URL('./fixtures/iva-g6h-preserved-inputs.json', import.meta.url), 'utf8', ), ); const rules = importExemptionRules.filter((r) => r.branch === 'P060'); const row = (rule) => ({ ...newImportExemption('g6h-' + rule.id, 'MZN'), treatment: rule.id, description: 'SYNTHETIC QA materiais/equipamentos projecto ONU', period: '2026-12', declaredValue: '5000', importer: 'SYNTHETIC QA entidade promotora', documentRef: 'SYNTHETIC QA G6H ' + rule.id, documentDate: '2026-11-14', evidence: 'SYNTHETIC QA pressupostos expressos; concessão aduaneira no plano e lista aprovada; não documento real', ...Object.fromEntries( importDevelopmentFields.map(([key, label]) => [ key, 'SYNTHETIC QA ' + label + ';operação2026-12/bens A;pressuposto expresso', ]), ), ...(rule.id === 'un_development_reduction' ? { developmentReductionPercent: '50', developmentNormalVat: '800', developmentNormalVatRef: 'SYNTHETIC QA IVA sem benefício informado, não calculado da base pelo portal', } : {}), conditions: Object.fromEntries( rule.conditions.map(([key]) => [key, 'yes']), ), }); const draft = () => ({ ...structuredClone(frozen), context_opportunity: 'opportunity:338', project_title: 'SYNTHETIC QA — G6H / Projecto de desenvolvimento', }); void test('P060 own funding,accreditation,destination,decision,list/plan and customs conditions;unknown/no never produce exempt zero', () => { assert.equal(rules.length, 2); assert.match(importDevelopmentSource, /12\(4\)/); for (const rule of rules) { const input = row(rule), ok = evaluateImportExemption(input, 'MZN'); assert.equal( ok.importVat, rule.id === 'un_development_exemption' ? '0.00' : '400.00', ); assert.equal( ok.status, rule.id === 'un_development_exemption' ? 'exempt' : 'reduced', ); assert.equal(ok.serviceVat, undefined); for (const [key] of rule.conditions) for (const value of ['', 'unknown', 'no']) { const r = evaluateImportExemption( { ...input, conditions: { ...input.conditions, [key]: value }, }, 'MZN', ); assert.equal( r.status, value === 'no' ? 'not_applicable' : 'indeterminate', ); assert.equal(r.importVat, null); } for (const [key] of importDevelopmentFields) assert.equal( evaluateImportExemption({ ...input, [key]: '' }, 'MZN') .importVat, null, ); for (const patch of [ { period: '2025-12' }, { documentDate: '2026-02-30' }, { currency: 'USD' }, { documentRef: '' }, { evidence: '' }, ]) assert.equal( evaluateImportExemption({ ...input, ...patch }, 'MZN') .importVat, null, ); } }); void test('partial benefit is exact proportion of supplied VAT,not a VAT/customs rate or full exemption;missing is not zero', () => { const input = row(rules[1]); for (const [normal, percent, expected] of [ ['800', '25', '600.00'], ['800', '75', '200.00'], ['1.234567', '33.333333', '0.82304467078189'], ['999999999999999.999999', '99.999999', '9999999.99999999999999'], ['0', '50', '0.00'], ]) { const r = evaluateImportExemption( { ...input, developmentNormalVat: normal, developmentReductionPercent: percent, }, 'MZN', ); assert.equal(r.status, 'reduced'); assert.equal(r.importVat, expected); assert.ok(!r.reason.includes('%/100')); } for (const patch of [ { developmentReductionPercent: '' }, { developmentReductionPercent: '-1' }, { developmentReductionPercent: '101' }, { developmentReductionPercent: '100' }, { developmentReductionPercent: '0.0000001' }, { developmentNormalVat: '' }, { developmentNormalVat: '-1' }, { developmentNormalVat: 'NaN' }, { developmentNormalVatRef: '' }, ]) assert.equal( evaluateImportExemption({ ...input, ...patch }, 'MZN').importVat, null, ); assert.equal( evaluateImportExemption( { ...input, developmentReductionPercent: '0' }, 'MZN', ).status, 'not_applicable', ); const full = row(rules[0]); assert.equal( evaluateImportExemption( { ...full, developmentNormalVat: '', developmentReductionPercent: '50', }, 'MZN', ).importVat, '0.00', 'hidden stale partial fields do not override full-rights condition', ); assert.equal( evaluateImportExemption({ ...full, treatment: rules[1].id }, 'MZN') .status, 'indeterminate', 'switch does not inherit own rights-reduction eligibility', ); }); void test('save/recovery/report keep77 delivered branches and partial P084/P085 exact;new contexts/history and reference edits isolated', () => { const d = draft(), prior = JSON.parse(d.modelo_a_snapshot); let book = recordImportExemptions(d, { rows: rules.map((rule) => ({ ...row(rule), conditions: {} })), }); book = recordImportExemptions(d, { ...book, rows: rules.map((rule) => ({ ...row(rule), conditions: { ...row(rule).conditions, developmentFavourableDecision: 'no', }, })), }); book = recordImportExemptions(d, { ...book, rows: rules.map(row) }); assert.equal(book.history.length, 2); assert.ok( book.history.every((h) => h.rows.every((r) => r.importVat === null)), ); assert.ok(importExemptionCurrent(d, book)); assert.match(book.result.sourceKey, /import-un-development\/1/); for (const field of [ 'developmentDecisionRef', 'developmentListRef', 'developmentPlanRef', 'developmentScope', 'developmentRightsRef', 'developmentReductionPercent', 'developmentNormalVat', ]) assert.ok( !importExemptionCurrent(d, { ...book, rows: book.rows.map((r) => ({ ...r, [field]: 'changed' })), }), ); assert.ok( !importExemptionCurrent( { ...d, context_opportunity: 'opportunity:339' }, book, ), ); d.modelo_a_snapshot = saveImportExemptionBook(d, book); assert.deepEqual(importExemptionBook(JSON.parse(JSON.stringify(d))), book); const next = JSON.parse(d.modelo_a_snapshot); assert.deepEqual( { ...next, importExemptions: prior.importExemptions }, prior, ); for (const [scope, previous] of Object.entries(prior.importExemptions)) { assert.deepEqual(next.importExemptions[scope], previous); assert.ok( importExemptionCurrent( { ...d, context_opportunity: scope }, previous, ), ); } assert.equal( next.importExemptions['opportunity:337'].result.rows[0].importVat, '0.00', ); assert.equal( next.importExemptions['opportunity:336'].result.rows[0].serviceVat, '0.00', ); assert.equal( next.importExemptions['opportunity:336'].result.rows[0].importVat, null, ); assert.equal( next.books['opportunity:329'].result.periods[0].fields['11'], null, ); const report = JSON.stringify( createProjectDossierReport(d, { selectedSections: new Set(['finance']), version: 'QA G6H', }), ); for (const token of [ 'P060', '12(2)(c)', '12(4)', '400.00', 'opportunity:338', 'Manica', '2026-12', 'Lista discriminada aprovada', 'Plano de importações', 'Redução proporcional', 'campo11', ]) assert.ok(report.includes(token), token); if (process.env.IVA_G6H_CALCULATED) fs.writeFileSync(process.env.IVA_G6H_CALCULATED, JSON.stringify(d)); }); void test('optional fields retain documents when switching,while malformed references cannot overwrite saved originals', () => { const d = draft(), original = d.modelo_a_snapshot; for (const key of [ ...importDevelopmentFields.map(([key]) => key), 'developmentReductionPercent', 'developmentNormalVat', 'developmentNormalVatRef', ]) assert.throws( () => saveImportExemptionBook(d, { rows: [{ ...row(rules[1]), [key]: 42 }], }), /Referências do projecto de desenvolvimento/, ); assert.equal(d.modelo_a_snapshot, original); const changed = { ...row(rules[1]), treatment: 'un_development_exemption' }; d.modelo_a_snapshot = saveImportExemptionBook(d, { rows: [changed] }); assert.equal( importExemptionBook(d).rows[0].developmentReductionPercent, '50', ); assert.equal( importExemptionBook(d).rows[0].developmentPlanRef, changed.developmentPlanRef, ); assert.equal( evaluateImportExemption(changed, 'MZN').status, 'indeterminate', ); });