import test from 'node:test'; import assert from 'node:assert/strict'; import fs from 'node:fs'; import { acquisitionTreatmentIssue, continueWithoutFormerExploration, formerExplorationSource, } from '../../resources/js/lib/iva-acquisition-continuity.ts'; import { newAcquisition, evaluateAcquisition, recordAcquisitions, acquisitionBook, acquisitionCurrent, saveAcquisitionBook, acquisitionReportRows, } from '../../resources/js/lib/iva-acquisitions.ts'; import { salesCurrent } from '../../resources/js/lib/iva-operations.ts'; import { createProjectDossierReport } from '../../resources/js/lib/project-dossier-report.ts'; const frozen = JSON.parse( fs.readFileSync( new URL('./fixtures/iva-g5a-inputs.json', import.meta.url), 'utf8', ), ); const row = () => ({ ...newAcquisition('g5b-0', '2026-12', 'MZN'), field: '10', net: '100', vat: '16', gross: '116', documentType: 'invoice', documentRef: 'SYNTHETIC QA G5B 001', documentDate: '2026-12-10', supplier: 'SYNTHETIC QA fornecedor', supplierRegistered: 'yes', legalDocument: 'yes', held: 'yes', domestic: 'yes', allocation: 'taxable_only', exclusion: 'none', integrity: 'yes', description: 'SYNTHETIC QA — serviço de pesquisa; antiga referência14(2)(c)', acquisitionTreatment: 'former_exploration_exemption', }); function fixture() { const draft = { ...structuredClone(frozen), context_opportunity: 'opportunity:329', project_title: 'SYNTHETIC QA — G5B / Continuidade da aquisição', }; const prior = recordAcquisitions(draft, { currency: 'MZN', taxpayerRegistered: 'yes', rows: [row()], periods: [{ period: '2026-12', complete: true, absent: [] }], }); draft.modelo_a_snapshot = saveAcquisitionBook(draft, prior); return { draft, prior }; } void test('2017 rectification prevents former14(2)(c) exemption in2026,including explicit zero;unknown is not a normal treatment', () => { assert.match(formerExplorationSource, /BR89/); assert.match( acquisitionTreatmentIssue('former_exploration_exemption'), /eliminada/, ); for (const vat of ['16', '0', '']) { const input = { ...row(), vat, gross: vat === '0' ? '100' : '116' }, result = evaluateAcquisition(input, 'MZN', 'yes'); assert.equal(result.deductible, null); assert.match(result.reason, /Não se aplica nesta cobertura2026/); assert.equal(input.net, '100'); } assert.equal( evaluateAcquisition( { ...row(), acquisitionTreatment: 'unknown' }, 'MZN', 'yes', ).deductible, null, ); assert.match( evaluateAcquisition({ ...row(), period: '2016-12' }, 'MZN', 'yes') .reason, /fora do âmbito/, ); }); void test('explicit continuation keeps values,document,answers and source;normal deduction requires existing conditions', () => { const input = row(), next = continueWithoutFormerExploration(input); for (const key of Object.keys(input).filter( (k) => k !== 'acquisitionTreatment', )) assert.deepEqual(next[key], input[key], key); assert.equal(input.acquisitionTreatment, 'former_exploration_exemption'); assert.equal(next.acquisitionTreatment, 'normal'); assert.equal( next.acquisitionTreatmentOrigin.id, 'former_exploration_exemption', ); assert.equal(evaluateAcquisition(next, 'MZN', 'yes').deductible, '16.00'); for (const patch of [ { held: '' }, { allocation: 'mixed' }, { legalDocument: '' }, { sourceCurrency: 'USD' }, { vat: '', gross: '' }, { domestic: 'no' }, { documentDate: '2026-11-10' }, ]) assert.equal( evaluateAcquisition({ ...next, ...patch }, 'MZN', 'yes').deductible, null, ); assert.throws( () => continueWithoutFormerExploration({ ...input, acquisitionTreatment: 'normal', }), /antiga referência/, ); }); void test('manual purchase month does not require sales;previous classification remains in history and incomplete totals remain unknown', () => { const { draft, prior } = fixture(); assert.equal(draft.monthly_iva_settings, undefined); assert.equal(prior.result.rows[0].deductible, null); assert.equal(prior.result.periods[0].fields['10'], null); const next = recordAcquisitions(draft, { ...prior, rows: [continueWithoutFormerExploration(prior.rows[0])], }); assert.deepEqual(next.history, [prior.result]); assert.equal(next.result.rows[0].deductible, '16.00'); assert.equal(next.result.periods[0].fields['10'], '16.00'); for (const f of ['01', '02', '11', '14', '15', '16', '17', '18']) assert.equal(next.result.periods[0].fields[f], null, f); assert.throws( () => recordAcquisitions(draft, { ...next, periods: [] }), /meses aplicáveis/, ); assert.throws( () => recordAcquisitions(draft, { ...next, periods: [...next.periods, ...next.periods], }), /meses aplicáveis/, ); assert.throws( () => recordAcquisitions(draft, { ...next, rows: [ { ...next.rows[0], sourceMonth: 1, sourceAmount: '100', sourceBasis: 'net', }, ], }), /orçamentos do plano mudaram/, ); }); void test('save/recovery/report retain rectification,continuation and history;all20 prior sales books stay identical/current', () => { const { draft, prior } = fixture(); const book = recordAcquisitions(draft, { ...prior, rows: [continueWithoutFormerExploration(prior.rows[0])], }); draft.modelo_a_snapshot = saveAcquisitionBook(draft, book); assert.ok(acquisitionCurrent(draft, book)); assert.deepEqual( acquisitionBook(JSON.parse(JSON.stringify(draft))), JSON.parse(JSON.stringify(book)), ); const before = JSON.parse(frozen.modelo_a_snapshot), after = JSON.parse(draft.modelo_a_snapshot); assert.equal(Object.keys(before.salesOperations).length, 20); assert.deepEqual(after.salesOperations, before.salesOperations); assert.deepEqual(Object.keys(after.books), ['opportunity:329']); for (const [context, original] of Object.entries(before.salesOperations)) assert.ok( salesCurrent({ ...draft, context_opportunity: context }, original), ); const report = JSON.stringify( createProjectDossierReport(draft, { selectedSections: new Set(['finance']), version: 'QA G5B', }), ); for (const token of [ 'opportunity:329', 'Manica', '2026-12', '16.00', 'BR89', 'Continuidade14(2)(c)', 'eliminado', 'expressamente escolhida', ]) assert.ok(report.includes(token), token); assert.match( JSON.stringify(acquisitionReportRows(draft)), /antiga isenção/, ); if (process.env.IVA_G5B_CALCULATED) fs.writeFileSync(process.env.IVA_G5B_CALCULATED, JSON.stringify(draft)); });