import test from 'node:test'; import assert from 'node:assert/strict'; import fs from 'node:fs'; import { newSalesOperation, recordSales, saveSalesBook, operationTreatments, salesBook, } from '../../resources/js/lib/iva-operations.ts'; import { newAcquisition, evaluateAcquisition, recordAcquisitions, saveAcquisitionBook, acquisitionBook, acquisitionCurrent, acquisitionReportRows, readAcquisitionStore, } from '../../resources/js/lib/iva-acquisitions.ts'; import { createAcquisitionRightLink } from '../../resources/js/lib/iva-acquisition-right.ts'; import { newAcquisitionBC, reuseAcquisitionImport, acquisitionImportSources, } from '../../resources/js/lib/iva-acquisition-bc.ts'; import { newImportExemption, saveImportExemptionBook, } from '../../resources/js/lib/iva-import-exemptions.ts'; const frozen = JSON.parse( fs.readFileSync( new URL('./fixtures/iva-l2bc-preserved.json', import.meta.url), 'utf8', ), ); export function bcFixture() { const draft = { ...structuredClone(frozen), context_opportunity: 'opportunity:369', project_title: 'SYNTHETIC QA — L2-B/C importações e exclusões', }; const sale = { ...newSalesOperation('sale', '2026-12', 'MZN'), description: 'SYNTHETIC QA venda geral', establishment: 'Manica', amount: '1000', basis: 'net', treatment: 'general', confirmed: operationTreatments .find((t) => t.id === 'general') .conditions.map((_, i) => i), evidence: 'SYNTHETIC QA condições', }; draft.modelo_a_snapshot = saveSalesBook( draft, recordSales(draft, { currency: 'MZN', rows: [sale], periods: [{ period: '2026-12', complete: true }], }), ); const link = { ...createAcquisitionRightLink(draft, 'sale'), scopeConfirmed: 'yes', allocationRef: 'SYNTHETIC QA afectação exclusiva', noExcludedPayments: 'yes', }; const row = (id, patch = {}, bc = {}) => ({ ...newAcquisition(id, '2026-12', 'MZN'), net: '100', vat: '16', gross: '116', description: 'SYNTHETIC QA ' + id, documentType: 'invoice', documentRef: 'SYNTHETIC QA ' + id, documentDate: '2026-12-10', supplier: 'SYNTHETIC QA fornecedor', supplierRegistered: 'yes', legalDocument: 'yes', held: 'yes', domestic: 'yes', allocation: 'taxable_only', exclusion: 'none', integrity: 'yes', deductionLink: structuredClone(link), bc: { ...newAcquisitionBC(), expense: 'ordinary', reducedSupply: 'no', evidence: 'SYNTHETIC QA natureza e âmbito', ...bc, }, ...patch, }); const imported = row( 'import-due', { field: '11', domestic: 'no', documentType: 'customs', supplier: '', supplierRegistered: '', }, { importer: 'SYNTHETIC QA importador', belongs: 'yes', ownImportVat: 'yes', vatBasis: 'due', goodsRef: 'SYNTHETIC QA bens/linha1', vatRef: 'SYNTHETIC QA bilhete de despacho', facts: { exigibleInPeriod: 'yes' }, }, ); const book = { currency: 'MZN', rightVersion: 'acquisition-operation-right/1', taxpayerRegistered: 'yes', rows: [ imported, row( 'diesel', {}, { expense: 'fuel', fuelKind: 'diesel', dieselUse: 'other', facts: { resale: 'no' }, }, ), row('travel', {}, { expense: 'travel' }), row( 'fixed-phone', {}, { expense: 'telephone', facts: { ownLandline: 'yes' } }, ), ], periods: [ { period: '2026-12', complete: true, importsComplete: true, absent: ['12', '13'], }, ], }; return { draft, book, row, imported }; } void test('B customs document has own conditions, unknown is not exempt/zero and supplier domestic registration is irrelevant', () => { const { draft, imported } = bcFixture(); const run = (patch = {}, bc = {}) => evaluateAcquisition( { ...imported, ...patch, bc: { ...imported.bc, ...bc } }, 'MZN', 'yes', draft, ); assert.equal(run().deductible, '16.00'); assert.equal(run().eligibility.status, 'eligible'); assert.equal( run({ net: '', gross: '' }, { reducedSupply: '' }).deductible, '16.00', ); assert.equal(run({ vat: '' }).deductible, null); assert.equal( run({ acquisitionTreatment: 'former_exploration_exemption' }) .deductible, null, ); assert.equal(run({ acquisitionTreatment: 'unknown' }).deductible, null); for (const bc of [ { belongs: '' }, { importer: '' }, { goodsRef: '' }, { vatRef: '' }, { ownImportVat: '' }, { vatBasis: 'unknown' }, { facts: { exigibleInPeriod: '' } }, { facts: { exigibleInPeriod: 'no' } }, ]) assert.equal(run({}, bc).deductible, null, JSON.stringify(bc)); assert.equal(run({ documentType: 'invoice' }).deductible, null); assert.equal(run({ held: '' }).deductible, null); assert.equal(run({ documentDate: '2026-11-10' }).deductible, null); assert.equal( run({ vat: '0', gross: '100' }, { vatBasis: 'exempt' }).deductible, '0.00', ); assert.equal( run({ vat: '0', gross: '100' }, { vatBasis: 'zero' }).deductible, '0.00', ); assert.equal( run({ vat: '', gross: '' }, { vatBasis: 'exempt' }).deductible, null, ); assert.equal(run({}, { vatBasis: 'exempt' }).deductible, null); }); void test('C exclusions/exceptions retain their own scope and unknown facts never imply no exclusion', () => { const { draft, row } = bcFixture(); const run = (bc, patch = {}) => evaluateAcquisition(row('case', patch, bc), 'MZN', 'yes', draft); const cases = [ [ { expense: 'vehicle', facts: { tourism: 'yes', saleOrExploit: 'no' }, }, '0.00', ], [ { expense: 'vehicle', facts: { tourism: 'yes', saleOrExploit: 'yes' }, }, '16.00', ], [{ expense: 'vehicle', facts: { tourism: 'no' } }, '16.00'], [{ expense: 'vehicle', facts: {} }, null], [ { expense: 'fuel', facts: { resale: 'no' }, fuelKind: 'other' }, '0.00', ], [{ expense: 'fuel', facts: { resale: 'yes' } }, '16.00'], [ { expense: 'fuel', facts: { resale: 'no' }, fuelKind: 'diesel', dieselUse: 'other', }, '8.00', ], [{ expense: 'travel' }, '0.00'], [ { expense: 'lodging_food', facts: { commercialTraveller: 'yes' } }, '16.00', ], [ { expense: 'lodging_food', facts: { commercialTraveller: 'no' } }, '0.00', ], [{ expense: 'lodging_food', facts: {} }, null], [{ expense: 'beverages', facts: { beverageSpecial: 'no' } }, '0.00'], [{ expense: 'beverages', facts: {} }, null], [{ expense: 'telephone', facts: { ownLandline: 'yes' } }, '16.00'], [{ expense: 'telephone', facts: { ownLandline: 'no' } }, '0.00'], [{ expense: 'telephone', facts: {} }, null], [{ expense: 'luxury' }, '0.00'], [{ expense: 'ordinary', reducedSupply: 'yes' }, '0.00'], [{ expense: 'ordinary', reducedSupply: '' }, null], ]; for (const [bc, expected] of cases) { const r = run(bc); assert.equal(r.deductible, expected, JSON.stringify(bc)); assert.ok(r.eligibility.reason); assert.match(r.eligibility.source, /20\(3\)/); } for (const dieselUse of [ 'heavy_passengers', 'public_passengers', 'machine', 'agriculture', ]) { assert.equal( run({ expense: 'fuel', fuelKind: 'diesel', dieselUse, facts: { resale: 'no', dieselScope: 'yes' }, }).deductible, '16.00', ); assert.equal( run({ expense: 'fuel', fuelKind: 'diesel', dieselUse, facts: { resale: 'no', dieselScope: '' }, }).deductible, null, ); } for (const patch of [ { held: '' }, { legalDocument: '' }, { documentDate: '2026-11-01' }, { allocation: 'mixed' }, { integrity: '' }, ]) assert.equal( run({ expense: 'telephone', facts: { ownLandline: 'yes' } }, patch) .deductible, null, ); }); void test('F includes import11, excludes denied purchases and preserves exact diesel fractions across totals', () => { const { draft, book } = bcFixture(); const result = recordAcquisitions(draft, book).result; assert.deepEqual( ['09', '11', '14', '15', '16', '17', '18'].map( (k) => result.periods[0].fields[k], ), ['24.00', '16.00', '1000.00', '40.00', '160.00', '120.00', '0.00'], ); const partial = structuredClone(book); partial.periods[0].importsComplete = false; assert.equal( recordAcquisitions(draft, partial).result.periods[0].fields['11'], null, ); assert.equal( recordAcquisitions(draft, partial).result.periods[0].fields['15'], null, ); partial.periods[0].absent.push('11'); assert.throws(() => recordAcquisitions(draft, partial), /importações/); const precision = structuredClone(book); precision.rows = [0, 1].map((i) => ({ ...book.rows[1], id: 'exact-' + i, documentLine: String(i), net: '1', vat: '0.000001', gross: '1.000001', })); const exact = recordAcquisitions(draft, precision).result; assert.deepEqual(exact.rows[0].deductibleExact, { numerator: '1', denominator: '2000000', }); assert.equal(exact.periods[0].fields['09'], '0.000001'); assert.deepEqual(exact.periods[0].exactFields['15'], { numerator: '1', denominator: '1000000', }); const duplicate = structuredClone(book); duplicate.rows.push({ ...book.rows[0], id: 'duplicate', origin: 'effective', }); assert.throws(() => recordAcquisitions(draft, duplicate), /dupla dedução/); }); void test('import reuse fills only missing data, detects source drift and preserves A plus every prior map and frozen history', () => { let { draft, book, imported } = bcFixture(); const origin = { ...newImportExemption('source', 'MZN'), description: 'SYNTHETIC QA origemL1', period: '2026-12', importer: 'SYNTHETIC QA origem importador', documentRef: 'ORIGINAL', documentDate: '2026-12-12', }; draft.modelo_a_snapshot = saveImportExemptionBook(draft, { rows: [origin], }); assert.equal(acquisitionImportSources(draft).length, 1); const reused = reuseAcquisitionImport( draft, imported, 'importExemptions', 'source', ); assert.equal(reused.documentRef, imported.documentRef); assert.equal(reused.documentDate, imported.documentDate); assert.equal(reused.bc.importer, imported.bc.importer); assert.equal(reused.vat, '16'); book.rows[0] = reused; book = recordAcquisitions(draft, book); draft.modelo_a_snapshot = saveAcquisitionBook(draft, book); const first = structuredClone(book.result); book = recordAcquisitions(draft, book); draft.modelo_a_snapshot = saveAcquisitionBook(draft, book); const recovered = JSON.parse(JSON.stringify(draft)); assert.ok(acquisitionCurrent(recovered, acquisitionBook(recovered))); assert.deepEqual(book.history, [first]); const before = JSON.parse(frozen.modelo_a_snapshot), after = JSON.parse(draft.modelo_a_snapshot); for (const k of Object.keys(before).filter((k) => k !== 'version')) for (const [id, value] of Object.entries(before[k])) assert.deepEqual(after[k][id], value, k + id); assert.ok( acquisitionCurrent( { ...recovered, context_opportunity: 'opportunity:368' }, before.books['opportunity:368'], ), ); const report = JSON.stringify(acquisitionReportRows(recovered)); for (const v of [ 'CondiçõesB/C', '40.00', '120.00', 'importador', '20(3)', '8/1', ]) assert.ok(report.includes(v), v); draft.modelo_a_snapshot = saveImportExemptionBook(draft, { rows: [{ ...origin, description: 'Editado' }], }); assert.equal(acquisitionCurrent(draft, book), false); assert.equal( evaluateAcquisition(book.rows[0], 'MZN', 'yes', draft).deductible, null, ); assert.deepEqual(book.history[0], first); draft.modelo_a_snapshot = saveImportExemptionBook(draft, { rows: [{ ...origin, treatment: 'service_in_customs_value' }], }); const service = reuseAcquisitionImport( draft, book.rows[0], 'importExemptions', 'source', ); assert.equal( evaluateAcquisition(service, 'MZN', 'yes', draft).deductible, null, ); assert.match( evaluateAcquisition(service, 'MZN', 'yes', draft).reason, /não IVA próprio/, ); const broken = JSON.parse(recovered.modelo_a_snapshot); broken.books['opportunity:369'].rows[0].bc.facts = { bad: 'maybe' }; assert.throws( () => readAcquisitionStore(JSON.stringify(broken)), /CondiçõesB\/C/, ); if (process.env.IVA_L2BC_CALCULATED) fs.writeFileSync( process.env.IVA_L2BC_CALCULATED, JSON.stringify(recovered), ); }); void test('beverages13(2) uses current c/d/h source and deduction-only scope without granting direct exemption or refund', () => { for (const treatment of [ 'onboard_seagoing_ship', 'onboard_international_aircraft', 'onboard_rescue_coastal_ship', 'onboard_departing_warship', ]) { const { draft, row } = bcFixture(); const ops = salesBook(draft); const rule = operationTreatments.find((t) => t.id === treatment); ops.rows.push({ ...newSalesOperation('beverages', '2026-12', 'MZN'), description: 'SYNTHETIC QA bebidas de bordo', establishment: 'Manica', amount: '100', basis: 'net', treatment, supplyCategory: 'beverages', confirmed: rule.conditions.map((_, i) => i), evidence: 'SYNTHETIC QA meio,destino,utilização e embarque', }); draft.modelo_a_snapshot = saveSalesBook(draft, recordSales(draft, ops)); const r = row( 'beverages', {}, { expense: 'beverages', beveragePath: 'deduction', facts: { beverageSpecial: 'yes', onlyDeduction: 'yes', notCoastalFishing: 'yes', }, }, ); r.deductionLink = { ...createAcquisitionRightLink(draft, 'beverages'), scopeConfirmed: 'yes', allocationRef: 'SYNTHETIC QA parcela e operação', noExcludedPayments: 'yes', }; assert.equal( evaluateAcquisition(r, 'MZN', 'yes', draft).deductible, treatment === 'onboard_departing_warship' ? null : '16.00', treatment, ); assert.equal( evaluateAcquisition( { ...r, bc: { ...r.bc, beveragePath: 'refund' } }, 'MZN', 'yes', draft, ).deductible, treatment === 'onboard_departing_warship' ? null : '0.00', ); assert.equal( evaluateAcquisition( { ...r, bc: { ...r.bc, facts: { ...r.bc.facts, onlyDeduction: '' }, }, }, 'MZN', 'yes', draft, ).deductible, null, ); if (treatment === 'onboard_rescue_coastal_ship') assert.equal( evaluateAcquisition( { ...r, bc: { ...r.bc, facts: { ...r.bc.facts, notCoastalFishing: 'no' }, }, }, 'MZN', 'yes', draft, ).deductible, null, ); } });