import test from 'node:test'; import assert from 'node:assert/strict'; import fs from 'node:fs'; import { newReturnee, returneeConditions, returneeTreatments, evaluateReturnee, recordReturnees, saveReturneeBook, returneeBook, returneeCurrent, returneeReportRows, } from '../../resources/js/lib/iva-returnees.ts'; const frozen = JSON.parse( fs.readFileSync( 'tests/frontend/fixtures/iva-returnees-preserved.json', 'utf8', ), ), prior = JSON.parse(frozen.modelo_a_snapshot), draft = { ...frozen, context_opportunity: 'opportunity:363', project_title: 'SYNTHETIC QA — Regresso definitivo / Manica', }; function row(treatment, id = treatment) { return { ...newReturnee(id, 'MZN'), treatment, description: 'SYNTHETIC QA veículo ' + id, beneficiary: 'SYNTHETIC QA beneficiário ' + id, period: '2026-10', origin: 'projected', scope: 'SYNTHETIC QA veículo/operação/período', evidence: 'SYNTHETIC QA pressupostos expressos', documentRef: 'SYNTHETIC QA propriedade/residência/declaração uso', arrival: '2026-09-01', request: '2026-09-20', stayStart: '2024-09-01', stayEnd: '2026-08-31', ownershipAssessment: '2026-09-01', ownedSince: treatment === 'owned' ? '2025-01-01' : '2026-08-01', importDate: '2026-10-10', previous: 'none', historyRef: 'SYNTHETIC QA histórico completo incluindo outros dossiers', decisionRef: 'SYNTHETIC QA pressuposto de substituição63(3)b', normalVat: '160.123456', normalVatRef: 'SYNTHETIC QA IVA normal informado', conditions: { ...Object.fromEntries(returneeConditions.map(([k]) => [k, 'yes'])), substitution: 'yes', }, }; } const rows = returneeTreatments .filter((t) => ['owned', 'recent', 'separate'].includes(t.id)) .map((t) => row(t.id)); for (const r of rows) void test( 'P058 veículo ' + r.treatment + ' sem dedução nem taxa presumida', () => { const v = evaluateReturnee(r, 'MZN'); assert.equal( v.status, r.treatment === 'owned' ? 'exempt' : 'reduced', ); assert.equal( v.importVat, { owned: '0.00', recent: '32.0246912', separate: '80.061728' }[ r.treatment ], ); assert.equal(v.deduction, null); }, ); void test('P058 desconhecido,âmbito e condições recusadas conservam distinção', () => { const r = rows[0]; for (const patch of [ { period: '2025-10' }, { currency: 'USD' }, { importDate: '2026-02-30' }, { description: '' }, { documentRef: '' }, { historyRef: '' }, { scope: '' }, { evidence: '' }, { previous: '' }, { conditions: { ...r.conditions, national: '' } }, ]) assert.equal( evaluateReturnee({ ...r, ...patch }, 'MZN').status, 'indeterminate', ); for (const [k] of returneeConditions) assert.equal( evaluateReturnee( { ...r, conditions: { ...r.conditions, [k]: 'no' } }, 'MZN', ).status, 'not_applicable', ); }); void test('P058 prazo60/90dias e excepções referenciadas distintas do regime mineiros', () => { const r = rows[0]; assert.equal( evaluateReturnee({ ...r, request: '2026-10-31' }, 'MZN').status, 'exempt', ); assert.equal( evaluateReturnee({ ...r, request: '2026-11-01' }, 'MZN').status, 'indeterminate', ); const extended = { ...r, request: '2026-11-30', extensionRef: 'SYNTHETIC QA prazo concedido', conditions: { ...r.conditions, extension: 'yes' }, }; assert.equal(evaluateReturnee(extended, 'MZN').status, 'exempt'); assert.equal( evaluateReturnee({ ...extended, request: '2026-12-01' }, 'MZN').status, 'indeterminate', ); assert.equal( evaluateReturnee({ ...extended, extensionRef: '' }, 'MZN').status, 'indeterminate', ); const sep = rows[2]; const exceptional = { ...sep, stayStart: '2026-02-01', exceptionRef: 'SYNTHETIC QA Ministro/âmbito', conditions: { ...sep.conditions, exception: 'yes' }, }; assert.equal(evaluateReturnee(exceptional, 'MZN').status, 'reduced'); assert.equal( evaluateReturnee({ ...exceptional, exceptionRef: '' }, 'MZN').status, 'indeterminate', ); assert.equal( evaluateReturnee({ ...sep, decisionRef: '' }, 'MZN').status, 'indeterminate', ); assert.equal( evaluateReturnee({ ...r, stayStart: '2025-08-31' }, 'MZN').status, 'indeterminate', ); }); void test('P058 propriedade180dias sem preencher lacuna e redução80% não é taxa deIVA', () => { const r = rows[0]; const d = new Date(r.arrival + 'T00:00:00Z'); d.setUTCDate(d.getUTCDate() - 180); assert.equal( evaluateReturnee( { ...r, ownedSince: d.toISOString().slice(0, 10) }, 'MZN', ).status, 'indeterminate', ); assert.equal( evaluateReturnee({ ...r, ownedSince: '2026-08-01' }, 'MZN').status, 'not_applicable', ); assert.equal( evaluateReturnee({ ...rows[1], normalVat: '0.000001' }, 'MZN') .importVat, '0.0000002', ); assert.equal( evaluateReturnee({ ...rows[1], normalVatRef: '' }, 'MZN').status, 'indeterminate', ); }); void test('P058 histórico global e um veículo em cinco anos;sem dupla utilização', () => { const r = rows[0]; assert.equal( evaluateReturnee( { ...r, previous: 'known', previousDate: '2021-10-10' }, 'MZN', ).status, 'exempt', ); assert.equal( evaluateReturnee( { ...r, previous: 'known', previousDate: '2021-10-11' }, 'MZN', ).status, 'indeterminate', ); const b = recordReturnees(draft, { rows: [r, { ...r, id: 'duplicate', treatment: 'separate' }], }); assert.deepEqual( b.result.rows.map((r) => r.status), ['indeterminate', 'indeterminate'], ); assert.equal(b.rows.length, 2); }); void test('P058 gravação/histórico/recuperação/relatório conservam127fechos e limitações', () => { let book = recordReturnees(draft, { rows }); assert.equal(returneeCurrent(draft, book), true); const changed = { ...book, rows: book.rows.map((r, i) => i ? r : { ...r, scope: 'SYNTHETIC QA âmbito revisto' }, ), }; assert.equal(returneeCurrent(draft, changed), false); book = recordReturnees(draft, changed); draft.modelo_a_snapshot = saveReturneeBook(draft, book); assert.deepEqual(returneeBook(draft), book); assert.equal(book.history.length, 1); assert.equal( returneeBook({ ...draft, context_opportunity: 'opportunity:999' }).rows .length, 0, ); assert.deepEqual( prior, Object.fromEntries( Object.entries(JSON.parse(draft.modelo_a_snapshot)).filter( ([k]) => k !== 'returneeImports', ), ), ); assert.throws(() => returneeBook({ ...draft, modelo_a_snapshot: '{"version":1,"books":{},"returneeImports":[]}', }), ); assert.match(returneeReportRows(draft)[0][3], /versão2/); if (process.env.IVA_RETURNEE_FIXTURE) fs.writeFileSync( 'tests/frontend/fixtures/iva-returnees.json', JSON.stringify(draft), ); });