import test from 'node:test'; import assert from 'node:assert/strict'; import fs from 'node:fs'; import { newImportExemption, evaluateImportExemption, recordImportExemptions, saveImportExemptionBook, importExemptionBook, importExemptionCurrent, importExemptionRules, importRuleSource, } from '../../resources/js/lib/iva-import-exemptions.ts'; import { internationalShipEligibility, internationalAircraftEligibility, internationalAssetTreatments, } from '../../resources/js/lib/iva-international-assets.ts'; import { salesCurrent } from '../../resources/js/lib/iva-operations.ts'; import { acquisitionCurrent } from '../../resources/js/lib/iva-acquisitions.ts'; import { createProjectDossierReport } from '../../resources/js/lib/project-dossier-report.ts'; const frozen = JSON.parse( fs.readFileSync( new URL('./fixtures/iva-g6b-inputs.json', import.meta.url), 'utf8', ), ); const ids = [ 'eligible_ship_import', 'ship_operation_object_import', 'eligible_aircraft_import', 'aircraft_operation_object_import', ]; const row = (treatment = 'eligible_ship_import') => ({ ...newImportExemption('g6c-' + treatment, 'MZN'), treatment, description: 'SYNTHETIC QA ' + treatment, period: '2026-12', declaredValue: '4000', importer: 'SYNTHETIC QA operador', documentRef: 'SYNTHETIC QA G6C ' + treatment, documentDate: '2026-11-13', evidence: 'SYNTHETIC QA meio identificado, utilização elegível e ligação do bem importado expressamente assumidas; não é documento real', conditions: Object.fromEntries( importExemptionRules .find((r) => r.id === treatment) .conditions.map(([key]) => [key, 'yes']), ), }); const draft = () => ({ ...structuredClone(frozen), context_opportunity: 'opportunity:332', project_title: 'SYNTHETIC QA — G6C / Embarcações e aviões', }); void test('P053/P054 four treatments require every own condition;unknown and false never become exempt zero or ordinary tax', () => { for (const id of ids) { const input = row(id), rule = importExemptionRules.find((r) => r.id === id); assert.equal(evaluateImportExemption(input, 'MZN').importVat, '0.00'); for (const [key] of rule.conditions) for (const value of ['', 'no', 'unknown']) { const result = evaluateImportExemption( { ...input, conditions: { ...input.conditions, [key]: value }, }, 'MZN', ); assert.equal( result.status, value === 'no' ? 'not_applicable' : 'indeterminate', ); assert.equal(result.importVat, null); } for (const patch of [ { period: '2025-12' }, { currency: 'USD' }, { evidence: '' }, { documentRef: '' }, { documentDate: '2026-02-30' }, ]) assert.equal( evaluateImportExemption({ ...input, ...patch }, 'MZN') .importVat, null, ); assert.deepEqual(input, row(id)); } assert.equal( new Set( ids.map( (id) => importExemptionRules.find((r) => r.id === id).branch, ), ).size, 2, ); }); void test('import definitions reuse accepted vessel/aircraft eligibility;principal asset does not substitute for linked object', () => { assert.equal( importExemptionRules.find((r) => r.id === ids[0]).conditions[0][1], internationalShipEligibility, ); assert.equal( importExemptionRules.find((r) => r.id === ids[2]).conditions[0][1], internationalAircraftEligibility, ); assert.ok( internationalAssetTreatments .find((r) => r.id === 'international_ship_operations') .conditions.includes(internationalShipEligibility), ); assert.ok( internationalAssetTreatments .find((r) => r.id === 'international_aircraft_operations') .conditions.includes(internationalAircraftEligibility), ); assert.match( internationalAircraftEligibility, /principalmente.*internacional/, ); assert.match(internationalAircraftEligibility, /voo internacional isolado/); const ship = row(); const object = { ...ship, treatment: 'ship_operation_object_import' }; assert.equal( evaluateImportExemption(object, 'MZN').status, 'indeterminate', ); assert.equal(object.conditions.importedShip, 'yes'); assert.equal(object.documentRef, ship.documentRef); assert.equal( evaluateImportExemption( { ...object, conditions: { ...object.conditions, shipObjectLink: 'yes' }, }, 'MZN', ).status, 'exempt', ); assert.equal( evaluateImportExemption( { ...row('aircraft_operation_object_import'), conditions: { eligibleAircraft: 'yes', importedAircraft: 'yes', }, }, 'MZN', ).status, 'indeterminate', ); assert.match(importRuleSource(ids[1]), /12\(1\)\(h\/i\)/); assert.match(importRuleSource(ids[3]), /13\(1\)\(f\/g\)/); }); void test('classification archives unknown and failed versions;edits preserve earlier result and mark it historical', () => { const d = draft(), input = row(); let book = recordImportExemptions(d, { rows: [{ ...input, conditions: { eligibleShip: 'yes' } }], }); assert.equal(book.result.rows[0].status, 'indeterminate'); book = recordImportExemptions(d, { ...book, rows: [ { ...input, conditions: { ...input.conditions, eligibleShip: 'no' }, }, ], }); assert.equal(book.result.rows[0].status, 'not_applicable'); book = recordImportExemptions(d, { ...book, rows: ids.map(row) }); assert.equal(book.history.length, 2); assert.equal(book.history[0].rows[0].importVat, null); assert.equal(book.history[1].rows[0].importVat, null); assert.ok(importExemptionCurrent(d, book)); for (const patch of [ { currency: 'USD' }, { context_opportunity: 'opportunity:331' }, { selection_labels: { province_id: 'Maputo' } }, ]) assert.ok(!importExemptionCurrent({ ...d, ...patch }, book)); assert.ok( !importExemptionCurrent(d, { ...book, rows: [{ ...input, declaredValue: '4100' }], }), ); }); void test('save/recover/report preserve23acceptedbooks current;only new asset treatments add version and do not populate field11', () => { const d = draft(), prior = JSON.parse(frozen.modelo_a_snapshot); let book = recordImportExemptions(d, { rows: ids.map((id) => ({ ...row(id), conditions: {} })), }); book = recordImportExemptions(d, { ...book, rows: ids.map(row) }); d.modelo_a_snapshot = saveImportExemptionBook(d, book); assert.deepEqual(importExemptionBook(JSON.parse(JSON.stringify(d))), book); assert.match(book.result.sourceKey, /import-assets\/1/); assert.doesNotMatch(book.result.sourceKey, /beneficiaryVersion/); assert.match(book.result.source, /12\(1\)\(h\/i\)/); const next = JSON.parse(d.modelo_a_snapshot); assert.deepEqual(next.salesOperations, prior.salesOperations); assert.deepEqual(next.books, prior.books); for (const [scope, imports] of Object.entries(prior.importExemptions)) { assert.deepEqual(next.importExemptions[scope], imports); assert.ok( importExemptionCurrent( { ...d, context_opportunity: scope }, imports, ), ); } for (const [scope, sales] of Object.entries(next.salesOperations)) assert.ok(salesCurrent({ ...d, context_opportunity: scope }, sales)); assert.ok( acquisitionCurrent( { ...d, context_opportunity: 'opportunity:329' }, next.books['opportunity:329'], ), ); assert.equal( next.books['opportunity:329'].result.periods[0].fields['11'], null, ); assert.equal( next.books['opportunity:329'].result.periods[0].fields['17'], null, ); const report = JSON.stringify( createProjectDossierReport(d, { selectedSections: new Set(['finance']), version: 'QA G6C', }), ); for (const token of [ 'P053', 'P054', 'opportunity:332', 'Manica', '2026-12', 'SYNTHETIC QA G6C', '0.00', '12(1)(h/i)', 'campo11', ...ids, ]) assert.ok(report.includes(token), token); if (process.env.IVA_G6C_CALCULATED) fs.writeFileSync(process.env.IVA_G6C_CALCULATED, JSON.stringify(d)); });