import test from 'node:test'; import assert from 'node:assert/strict'; import fs from 'node:fs'; import { newPropertyTransfer, transferConditions, propertyTransferTreatments, evaluatePropertyTransfer, recordPropertyTransfers, savePropertyTransferBook, propertyTransferBook, propertyTransferCurrent, propertyTransferReportRows, switchPropertyTreatment, } from '../../resources/js/lib/iva-property-transfers.ts'; const frozen = JSON.parse( fs.readFileSync( 'tests/frontend/fixtures/iva-property-transfers-preserved.json', 'utf8', ), ); const draft = { ...frozen, currency: 'MZN', context_opportunity: 'opportunity:356', project_title: 'SYNTHETIC QA — Transmissões de propriedade / Manica', }; function row(t) { return { ...newPropertyTransfer(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 identificado', scope: 'SYNTHETIC QA bens/operação/período', evidence: 'SYNTHETIC QA factos/pressupostos expressos', contractRef: 'SYNTHETIC QA contrato/cessão', propertyClauseRef: 'SYNTHETIC QA cláusula vinculante ambas as partes', acquirerRef: 'SYNTHETIC QA adquirente2(1)a', autonomousRef: 'SYNTHETIC QA ramo independente', activitiesRef: 'SYNTHETIC QA operações com direito à dedução', consideration: '1250.123456', considerationRef: 'SYNTHETIC QA composição obtida/a obter,sem próprioIVA', compositionConfirmed: 'yes', conditions: Object.fromEntries( transferConditions(t).map(([k]) => [k, 'yes']), ), }; } for (const rule of propertyTransferTreatments) void test(rule.branch + ' ' + rule.id + ' own facts and references', () => { const r = row(rule.id), v = evaluatePropertyTransfer(r, 'MZN'); assert.equal(v.status, 'determined'); assert.equal( v.classification, rule.id === 'binding_lease' ? 'goods_transmission' : 'tax_not_exigible_3_5', ); assert.equal( v.baseAmount, rule.id === 'binding_lease' ? '1250.123456' : null, ); assert.equal(v.vat, null); assert.equal(v.rate, null); for (const [k] of transferConditions(rule.id)) { const missing = structuredClone(r); delete missing.conditions[k]; assert.equal( evaluatePropertyTransfer(missing, 'MZN').status, 'indeterminate', ); missing.conditions[k] = 'no'; assert.equal( evaluatePropertyTransfer(missing, 'MZN').status, 'not_applicable', ); } for (const field of [ 'description', 'operationRef', 'documentRef', 'goodsRef', 'scope', 'evidence', 'contractRef', ...(rule.id === 'binding_lease' ? ['propertyClauseRef'] : ['acquirerRef', 'autonomousRef', 'activitiesRef']), ]) assert.equal( evaluatePropertyTransfer({ ...r, [field]: '' }, 'MZN').status, 'indeterminate', field, ); for (const patch of [ { operationDate: '2026-02-30' }, { documentDate: '2026-02-30' }, { period: '2025-12' }, { period: '2026-11' }, ]) assert.equal( evaluatePropertyTransfer({ ...r, ...patch }, 'MZN').status, 'indeterminate', ); }); void test('P087 classification separatefrom missingbase,exact consideration and no double subtraction', () => { const r = row('binding_lease'); for (const patch of [ { consideration: '' }, { consideration: '-1' }, { consideration: '1e3' }, { consideration: '1.1234567' }, { compositionConfirmed: '' }, { compositionConfirmed: 'no' }, { considerationRef: '' }, { currency: 'USD' }, ]) { const v = evaluatePropertyTransfer({ ...r, ...patch }, 'MZN'); assert.equal(v.status, 'indeterminate'); assert.equal(v.classification, 'goods_transmission'); assert.equal(v.baseAmount, null); } assert.equal( evaluatePropertyTransfer({ ...r, consideration: '0' }, 'MZN') .baseAmount, '0.00', ); assert.equal( evaluatePropertyTransfer( { ...r, consideration: '900719925474099.123456' }, 'MZN', ).baseAmount, '900719925474099.123456', ); assert.match(evaluatePropertyTransfer(r, 'MZN').reason, /15\(1\)/); }); void test('P127 no exigibility is neitherzero nor genericexemption;switchretainsdata', () => { for (const t of ['business_onerous', 'business_free']) { const v = evaluatePropertyTransfer( { ...row(t), consideration: '', currency: 'USD', compositionConfirmed: '', }, 'MZN', ); assert.equal(v.classification, 'tax_not_exigible_3_5'); assert.equal(v.baseAmount, null); assert.match(v.reason, /não é isenção genérica/i); } const r = row('binding_lease'), sw = switchPropertyTreatment(r, 'business_free'); assert.equal(sw.consideration, r.consideration); assert.equal(sw.propertyClauseRef, r.propertyClauseRef); assert.deepEqual(sw.conditions, {}); assert.equal(sw.compositionConfirmed, ''); }); void test('draft/report/history and allpriorbooks preserved', () => { const rows = propertyTransferTreatments.map((t) => row(t.id)), first = recordPropertyTransfers(draft, { rows }); const next = { ...draft, modelo_a_snapshot: savePropertyTransferBook(draft, first), }; const second = recordPropertyTransfers(next, first); next.modelo_a_snapshot = savePropertyTransferBook(next, second); assert.equal(second.history.length, 1); assert.deepEqual(second.history[0].inputs, rows); assert.equal(propertyTransferCurrent(next, second), true); assert.equal( propertyTransferCurrent({ ...next, currency: 'USD' }, second), false, ); assert.equal(propertyTransferReportRows(next).length, 3); assert.deepEqual( propertyTransferBook({ ...next, context_opportunity: 'opportunity:357', }), { rows: [] }, ); const store = JSON.parse(next.modelo_a_snapshot); delete store.propertyTransfers; assert.deepEqual(store, JSON.parse(frozen.modelo_a_snapshot)); assert.throws(() => recordPropertyTransfers(next, { rows: [rows[0], rows[0]] }), ); assert.throws(() => propertyTransferBook({ ...next, modelo_a_snapshot: JSON.stringify({ ...store, propertyTransfers: [], }), }), ); if (process.env.IVA_PROPERTY_TRANSFERS_FIXTURE) fs.writeFileSync( process.env.IVA_PROPERTY_TRANSFERS_FIXTURE, JSON.stringify(next, null, 2) + '\n', ); });