import test from 'node:test'; import assert from 'node:assert/strict'; import fs from 'node:fs'; import { newGoodsAllocation, switchAllocationTreatment, switchAllocationValuation, goodsAllocationConditions, allocationSpecificConditions, goodsAllocationTreatments, evaluateGoodsAllocation, recordGoodsAllocations, saveGoodsAllocationBook, goodsAllocationBook, goodsAllocationCurrent, goodsAllocationReportRows, } from '../../resources/js/lib/iva-goods-allocation.ts'; const frozen = JSON.parse( fs.readFileSync( 'tests/frontend/fixtures/iva-goods-allocation-preserved.json', 'utf8', ), ); const draft = { ...frozen, currency: 'MZN', context_opportunity: 'opportunity:353', project_title: 'SYNTHETIC QA — Afectação de bens / Manica', }; function row(t) { const cost = ['free_goods_transfer', 'fixed_asset_20a'].includes(t); return { ...newGoodsAllocation(t, 'MZN'), treatment: t, description: 'SYNTHETIC QA ' + t, period: '2026-12', origin: 'projected', operationDate: '2026-12-12', operationRef: 'SYNTHETIC QA operação', documentRef: 'SYNTHETIC QA documento/pressuposto', documentDate: '2026-12-12', goodsRef: 'SYNTHETIC QA conjunto de bens/elementos', deductionRef: 'SYNTHETIC QA dedução histórica parcial,bens/elementos identificados', destinationRef: 'SYNTHETIC QA destino/finalidade/sector/activo eâmbito', exceptionRef: 'SYNTHETIC QA factos fora da excepção de amostras/ofertas,não limiar inventado', asset20aRef: 'SYNTHETIC QA bens20(1)a/activoimobilizado', valuationMode: cost ? 'cost' : 'acquisition', acquisitionPrice: '1000.25', acquisitionRef: 'SYNTHETIC QA preço aquisição reportado ao momento', currentCost: '800.15', costRef: 'SYNTHETIC QA custo reportado ao momento', valuationDate: '2026-12-12', valuationScope: 'SYNTHETIC QA conjunto identificado/preço ao momento,semIVA', evidence: 'SYNTHETIC QA pressupostos expressos', conditions: { ...Object.fromEntries( [ ...goodsAllocationConditions, ...allocationSpecificConditions(t), ].map(([key]) => [key, 'yes']), ), valuationConfirmed: 'yes', acquisitionUnavailable: 'yes', }, }; } for (const rule of goodsAllocationTreatments) void test( 'P124/P088 ' + rule.id + ' ownfacts,historicaldeduction and base', () => { const r = row(rule.id), result = evaluateGoodsAllocation(r, 'MZN'); assert.equal(result.status, 'determined'); assert.equal(result.classification, 'assimilated_goods'); assert.equal( result.baseAmount, r.valuationMode === 'cost' ? '800.15' : '1000.25', ); assert.equal(result.vat, null); assert.equal(result.rate, null); for (const [key] of [ ...goodsAllocationConditions, ...allocationSpecificConditions(rule.id), ]) { const missing = structuredClone(r); delete missing.conditions[key]; assert.equal( evaluateGoodsAllocation(missing, 'MZN').classification, 'indeterminate', ); missing.conditions[key] = 'no'; assert.equal( evaluateGoodsAllocation(missing, 'MZN').status, 'not_applicable', ); assert.equal( evaluateGoodsAllocation(missing, 'MZN').baseAmount, null, ); } for (const field of [ 'description', 'operationRef', 'documentRef', 'goodsRef', 'deductionRef', 'destinationRef', 'evidence', ...(rule.clause === 'e' ? ['exceptionRef'] : []), ...(rule.id === 'fixed_asset_20a' ? ['asset20aRef'] : []), ]) assert.equal( evaluateGoodsAllocation({ ...r, [field]: '' }, 'MZN') .classification, 'indeterminate', field, ); for (const patch of [ { operationDate: '2026-11-12' }, { documentDate: '2026-02-30' }, { period: '2025-12' }, ]) assert.equal( evaluateGoodsAllocation({ ...r, ...patch }, 'MZN').status, 'indeterminate', ); }, ); void test('P124classification independentof missingP088base;no newdeduction and no temporaryservice substitution', () => { const r = row('permanent_private_goods'); for (const patch of [ { valuationMode: '' }, { acquisitionPrice: '' }, { valuationDate: '2026-12-11' }, { valuationScope: '' }, { currency: 'USD' }, { acquisitionRef: '' }, ]) { const result = evaluateGoodsAllocation({ ...r, ...patch }, 'MZN'); assert.equal(result.status, 'indeterminate'); assert.equal(result.classification, 'assimilated_goods'); assert.equal(result.baseAmount, null); } assert.match(evaluateGoodsAllocation(r, 'MZN').reason, /não nova dedução/); assert.match(evaluateGoodsAllocation(r, 'MZN').reason, /P089/); const noPrior = structuredClone(r); noPrior.conditions.priorDeduction = 'no'; assert.equal( evaluateGoodsAllocation(noPrior, 'MZN').classification, 'not_applicable', ); assert.equal(evaluateGoodsAllocation(noPrior, 'MZN').baseAmount, null); }); void test('P088costfallback explicit,currentmoment,hidden retention and exact amounts', () => { const r = row('free_goods_transfer'); for (const flag of ['', 'no']) { const result = evaluateGoodsAllocation( { ...r, conditions: { ...r.conditions, acquisitionUnavailable: flag }, }, 'MZN', ); assert.equal(result.classification, 'assimilated_goods'); assert.equal(result.baseAmount, null); } assert.equal( evaluateGoodsAllocation({ ...r, acquisitionPrice: '999999' }, 'MZN') .baseAmount, '800.15', ); assert.equal( evaluateGoodsAllocation({ ...r, currentCost: '0' }, 'MZN').baseAmount, '0.00', ); assert.equal( evaluateGoodsAllocation({ ...r, currentCost: '0.000001' }, 'MZN') .baseAmount, '0.000001', ); for (const v of ['', '-1', '1e3', '1,5']) assert.equal( evaluateGoodsAllocation({ ...r, currentCost: v }, 'MZN').baseAmount, null, ); const acquisition = switchAllocationValuation(r, 'acquisition'); assert.equal(acquisition.currentCost, r.currentCost); assert.equal(acquisition.acquisitionPrice, r.acquisitionPrice); assert.equal(acquisition.conditions.valuationConfirmed, ''); assert.equal(evaluateGoodsAllocation(acquisition, 'MZN').baseAmount, null); acquisition.conditions.valuationConfirmed = 'yes'; assert.equal( evaluateGoodsAllocation(acquisition, 'MZN').baseAmount, '1000.25', ); const changed = switchAllocationTreatment(r, 'fixed_asset_20a'); assert.equal(changed.exceptionRef, r.exceptionRef); assert.equal(changed.asset20aRef, r.asset20aRef); assert.equal(changed.conditions.fixedAsset, undefined); assert.equal( evaluateGoodsAllocation(changed, 'MZN').classification, 'indeterminate', ); }); void test('Sharedoperation under2requirements persists once;all previous books/history/report preserved', () => { const rows = goodsAllocationTreatments.map((t) => row(t.id)); let book = recordGoodsAllocations(draft, { rows }); book = recordGoodsAllocations(draft, book); assert.equal(book.history.length, 1); assert.notEqual(book.result.inputs, book.rows); const next = { ...draft, modelo_a_snapshot: saveGoodsAllocationBook(draft, book), }; assert.deepEqual(goodsAllocationBook(next), book); assert.ok(goodsAllocationCurrent(next, book)); assert.equal( goodsAllocationCurrent({ ...next, currency: 'USD' }, book), false, ); assert.equal( goodsAllocationCurrent({ ...next, context_opportunity: 'other' }, book), false, ); assert.equal(goodsAllocationReportRows(next).length, 4); assert.ok( goodsAllocationReportRows(next).every((r) => r[1].includes('P124/baseP088'), ), ); const store = JSON.parse(next.modelo_a_snapshot); delete store.regulatedGoodsAllocations; assert.deepEqual(store, JSON.parse(frozen.modelo_a_snapshot)); assert.throws(() => recordGoodsAllocations(next, { rows: [rows[0], rows[0]] }), ); assert.throws(() => goodsAllocationBook({ ...next, modelo_a_snapshot: JSON.stringify({ ...JSON.parse(next.modelo_a_snapshot), regulatedGoodsAllocations: [], }), }), ); if (process.env.IVA_ALLOCATION_FIXTURE) fs.writeFileSync( process.env.IVA_ALLOCATION_FIXTURE, JSON.stringify(next, null, 2) + '\n', ); });