import test from 'node:test'; import assert from 'node:assert/strict'; import fs from 'node:fs'; import { newImportExemption, evaluateImportExemption, recordImportExemptions, saveImportExemptionBook, importExemptionBook, importExemptionCurrent, importExemptionRules, importServiceSource, } from '../../resources/js/lib/iva-import-exemptions.ts'; import { createProjectDossierReport } from '../../resources/js/lib/project-dossier-report.ts'; import { offerReusableData } from '../../resources/js/lib/iva-offer-preparations.ts'; const frozen = JSON.parse( fs.readFileSync( new URL('./fixtures/iva-offer-paths-inputs.json', import.meta.url), 'utf8', ), ); const rules = importExemptionRules.filter((r) => r.branch === 'P050'); const row = (rule) => ({ ...newImportExemption('g6f-' + rule.id, 'MZN'), treatment: rule.id, description: 'SYNTHETIC QA ' + rule.label, period: '2026-12', declaredValue: '5000', importer: 'SYNTHETIC QA importador destinatário', documentRef: 'SYNTHETIC QA G6F ' + rule.id, documentDate: '2026-11-14', evidence: 'SYNTHETIC QA serviço e montante integral incluídos na base identificada, conforme artigo16; pressuposto expresso, não documento real', serviceImportRef: 'SYNTHETIC QA importação DU-A,2026-12', serviceBaseRef: 'SYNTHETIC QA base DU-A,linha serviço5000MZN', serviceProvider: 'SYNTHETIC QA prestador', ...(rule.id === 'accessory_service_first_destination' ? { serviceFirstDestination: 'SYNTHETIC QA Manica,primeiro destino no documento de transporte', } : {}), conditions: Object.fromEntries( rule.conditions.map(([key]) => [key, 'yes']), ), }); const draft = () => ({ ...structuredClone(frozen), context_opportunity: 'opportunity:336', project_title: 'SYNTHETIC QA — G6F / Serviços na base da importação', }); void test('P050 two treatments exempt only service VAT;every missing/failed condition leaves service and imported-goods tax indeterminate', () => { assert.equal(rules.length, 2); assert.match(importServiceSource, /16\(2\)/); for (const rule of rules) { const input = row(rule), ok = evaluateImportExemption(input, 'MZN'); assert.equal(ok.serviceVat, '0.00'); assert.equal(ok.importVat, null); assert.match(ok.reason, /IVA do serviço/); 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.serviceVat, null); assert.equal(r.importVat, null); } for (const patch of [ { serviceImportRef: '' }, { serviceBaseRef: '' }, { declaredValue: '' }, { documentRef: '' }, { period: '2025-12' }, { currency: 'USD' }, { documentDate: '2026-02-30' }, ]) assert.equal( evaluateImportExemption({ ...input, ...patch }, 'MZN') .serviceVat, null, ); } }); void test('first-destination reference is required only for added accessory service;switching keeps facts but cannot inherit own eligibility', () => { const inValue = row(rules[0]), accessory = row(rules[1]); assert.equal( evaluateImportExemption( { ...accessory, serviceFirstDestination: '' }, 'MZN', ).status, 'indeterminate', ); assert.equal(evaluateImportExemption(inValue, 'MZN').status, 'exempt'); const changed = { ...inValue, treatment: rules[1].id }; assert.equal( evaluateImportExemption(changed, 'MZN').status, 'indeterminate', ); assert.equal(changed.documentRef, inValue.documentRef); assert.ok( !rules[0].conditions.some( ([key]) => key === 'serviceToFirstDestination', ), ); const beyond = { ...accessory, conditions: { ...accessory.conditions, serviceToFirstDestination: 'no', }, }; assert.equal( evaluateImportExemption(beyond, 'MZN').status, 'not_applicable', ); assert.equal( evaluateImportExemption( { ...inValue, conditions: { ...inValue.conditions, serviceFullValueIncluded: 'no', }, }, 'MZN', ).serviceVat, null, ); }); void test('save/recovery/report preserve27fiscalbooks and946fc089scenarios/requests/history exactly;service is not added to base or deduction', () => { const d = draft(), prior = JSON.parse(frozen.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, serviceFullValueIncluded: '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.serviceVat === null && r.importVat === null), ), ); d.modelo_a_snapshot = saveImportExemptionBook(d, book); assert.deepEqual(importExemptionBook(JSON.parse(JSON.stringify(d))), book); assert.match(book.result.sourceKey, /import-included-services\/1/); const next = JSON.parse(d.modelo_a_snapshot); for (const key of ['books', 'salesOperations', 'offerPreparations']) assert.deepEqual(next[key], prior[key]); 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.books['opportunity:329'].result.periods[0].fields['11'], null, ); const report = JSON.stringify( createProjectDossierReport(d, { selectedSections: new Set(['finance']), version: 'QA G6F', }), ); for (const token of [ 'Serviço associado à importação P050', 'IVA do serviço: 0.00', 'opportunity:336', 'Manica', '2026-12', 'SYNTHETIC QA G6F', '12(1)(e)', 'primeiro destino', 'campo11', ]) assert.ok(report.includes(token), token); assert.ok(!report.includes('IVA na importação: 0.00')); if (process.env.IVA_G6F_CALCULATED) fs.writeFileSync(process.env.IVA_G6F_CALCULATED, JSON.stringify(d)); }); void test('old goods rows keep own tax representation and malformed optional service references cannot overwrite saved originals', () => { const d = draft(), prior = JSON.parse(d.modelo_a_snapshot); for (const book of Object.values(prior.importExemptions)) assert.ok( book.result.rows.every((row) => !Object.hasOwn(row, 'serviceVat')), ); assert.throws( () => saveImportExemptionBook(d, { rows: [{ ...row(rules[0]), serviceBaseRef: 42 }], }), /Referências do serviço/, ); const serviceOnly = { ...d, context_opportunity: 'opportunity:336' }; serviceOnly.modelo_a_snapshot = saveImportExemptionBook(serviceOnly, { rows: rules.map(row), }); assert.equal( offerReusableData(serviceOnly).length, 0, 'P050 services cannot be reused as imported goods in P084', ); });