Files
Investidor-V2/tests/frontend/iva-returnees.test.mjs
T

240 lines
7.7 KiB
JavaScript

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),
);
});