406 lines
13 KiB
JavaScript
406 lines
13 KiB
JavaScript
import test from 'node:test';
|
||
import assert from 'node:assert/strict';
|
||
import fs from 'node:fs';
|
||
import {
|
||
minerTreatments,
|
||
minerCommon,
|
||
newMiner,
|
||
evaluateMiner,
|
||
recordMiners,
|
||
saveMinerBook,
|
||
minerBook,
|
||
minerCurrent,
|
||
minerReportRows,
|
||
} from '../../resources/js/lib/iva-miners.ts';
|
||
const frozen = JSON.parse(
|
||
fs.readFileSync(
|
||
'tests/frontend/fixtures/iva-miners-preserved.json',
|
||
'utf8',
|
||
),
|
||
),
|
||
prior = JSON.parse(frozen.modelo_a_snapshot),
|
||
draft = {
|
||
...frozen,
|
||
context_opportunity: 'opportunity:362',
|
||
project_title: 'SYNTHETIC QA — Mineiros / Manica',
|
||
};
|
||
function row(treatment, id = treatment, patch = {}) {
|
||
const rule = minerTreatments.find((t) => t.id === treatment);
|
||
return {
|
||
...newMiner(id, 'MZN'),
|
||
treatment,
|
||
description: 'SYNTHETIC QA bens ' + id,
|
||
period: '2026-10',
|
||
beneficiary: 'SYNTHETIC QA mineiro ' + id,
|
||
contractRef: 'SYNTHETIC QA contrato/visto',
|
||
documentRef: 'SYNTHETIC QA documento/previsão',
|
||
documentDate: '2026-10-01',
|
||
scope: 'SYNTHETIC QA bens/direito/operação identificados',
|
||
evidence: 'SYNTHETIC QA factos ou pressupostos expressos',
|
||
importDate: '2026-10-10',
|
||
route: 'accompanied',
|
||
customsRef: 'SYNTHETIC QA DU/registo/pressuposto',
|
||
customsScope: 'SYNTHETIC QA direito e bens desta importação',
|
||
rightHolder: 'miner',
|
||
conditions: Object.fromEntries(
|
||
[...minerCommon, ...(rule?.conditions ?? [])].map(([k]) => [
|
||
k,
|
||
'yes',
|
||
]),
|
||
),
|
||
quantity: '1',
|
||
kind: treatment === 'appliance' ? 'frigorífico' : 'vehicle',
|
||
quotaRef:
|
||
'SYNTHETIC QA histórico global,inclui esta e operações externas',
|
||
previousBenefit: 'none',
|
||
value: '15000',
|
||
periodTotal: '15000',
|
||
accumulationStart: '2026-05',
|
||
accumulationMonths: '6',
|
||
arrivalDate: '2026-09-01',
|
||
requestDate: '2026-09-20',
|
||
stayStart: '2024-09-01',
|
||
stayEnd: '2026-08-31',
|
||
normalVat: '160.123456',
|
||
normalVatRef: 'SYNTHETIC QA IVA normal informado',
|
||
...patch,
|
||
};
|
||
}
|
||
const rows = minerTreatments.map((t) => row(t.id));
|
||
rows.find((r) => r.treatment === 'accumulated').periodTotal = '90000';
|
||
for (const r of rows)
|
||
void test(
|
||
'P059 ' +
|
||
r.treatment +
|
||
' scoped entitlement without duties or deduction',
|
||
() => {
|
||
const v = evaluateMiner(r, 'MZN');
|
||
assert.equal(
|
||
v.status,
|
||
r.treatment === 'separate_vehicle' ? 'reduced' : 'exempt',
|
||
);
|
||
assert.equal(
|
||
v.importVat,
|
||
r.treatment === 'separate_vehicle' ? '80.061728' : '0.00',
|
||
);
|
||
assert.equal(v.deduction, null);
|
||
assert.match(v.source, /arts1–4PDF1/);
|
||
assert.match(v.source, /PDF2–3\/p152–153/);
|
||
},
|
||
);
|
||
void test('P059 unknowns never become exemption; alcohol/tobacco and other failed facts remain distinct', () => {
|
||
const r = rows[0];
|
||
for (const patch of [
|
||
{ currency: 'USD' },
|
||
{ period: '2025-10' },
|
||
{ importDate: '2026-11-10' },
|
||
{ importDate: '2026-02-30' },
|
||
{ beneficiary: '' },
|
||
{ contractRef: '' },
|
||
{ documentRef: '' },
|
||
{ documentDate: '' },
|
||
{ scope: '' },
|
||
{ evidence: '' },
|
||
{ customsRef: '' },
|
||
{ customsScope: '' },
|
||
{ rightHolder: '' },
|
||
{ route: '' },
|
||
{ conditions: { ...r.conditions, rsa: '' } },
|
||
{ treatment: 'temporary_vehicle' },
|
||
]) {
|
||
const v = evaluateMiner({ ...r, ...patch }, 'MZN');
|
||
assert.equal(v.status, 'indeterminate');
|
||
assert.equal(v.importVat, null);
|
||
}
|
||
for (const [k] of [...minerCommon, ...minerTreatments[0].conditions])
|
||
assert.equal(
|
||
evaluateMiner(
|
||
{ ...r, conditions: { ...r.conditions, [k]: 'no' } },
|
||
'MZN',
|
||
).status,
|
||
'not_applicable',
|
||
);
|
||
for (const r of rows)
|
||
for (const [k] of [
|
||
...minerCommon,
|
||
...minerTreatments.find((t) => t.id === r.treatment).conditions,
|
||
])
|
||
assert.equal(
|
||
evaluateMiner(
|
||
{ ...r, conditions: { ...r.conditions, [k]: '' } },
|
||
'MZN',
|
||
).status,
|
||
'indeterminate',
|
||
);
|
||
});
|
||
void test('P059 monthly amount and accumulated window including year boundary,without reuse of expired months', () => {
|
||
const m = row('monthly');
|
||
for (const patch of [
|
||
{ value: '' },
|
||
{ periodTotal: '' },
|
||
{ value: '15001', periodTotal: '15000' },
|
||
{ quotaRef: '' },
|
||
{ periodTotal: '15000.000001' },
|
||
])
|
||
assert.equal(
|
||
evaluateMiner({ ...m, ...patch }, 'MZN').status,
|
||
'indeterminate',
|
||
);
|
||
const a = rows.find((r) => r.treatment === 'accumulated');
|
||
assert.equal(
|
||
evaluateMiner({ ...a, periodTotal: '90000.000001' }, 'MZN').status,
|
||
'indeterminate',
|
||
);
|
||
for (const patch of [
|
||
{ accumulationStart: '2026-04' },
|
||
{ accumulationMonths: '7' },
|
||
{ accumulationMonths: '0' },
|
||
{ accumulationStart: '' },
|
||
])
|
||
assert.equal(
|
||
evaluateMiner({ ...a, ...patch }, 'MZN').status,
|
||
'indeterminate',
|
||
);
|
||
const year = {
|
||
...a,
|
||
period: '2026-01',
|
||
importDate: '2026-01-10',
|
||
accumulationStart: '2025-08',
|
||
};
|
||
assert.equal(evaluateMiner(year, 'MZN').status, 'exempt');
|
||
});
|
||
void test('P059 appliance and five-year vehicle entitlement use identified external history,not dossier absence', () => {
|
||
const a = row('appliance');
|
||
for (const patch of [{ kind: '' }, { quantity: '2' }, { quotaRef: '' }])
|
||
assert.equal(
|
||
evaluateMiner({ ...a, ...patch }, 'MZN').status,
|
||
'indeterminate',
|
||
);
|
||
const v = row('vehicle');
|
||
for (const patch of [
|
||
{ kind: '' },
|
||
{ kind: 'boat' },
|
||
{ previousBenefit: '' },
|
||
{ quantity: '0' },
|
||
{ quotaRef: '' },
|
||
{ previousBenefit: 'known', previousBenefitDate: '' },
|
||
])
|
||
assert.equal(
|
||
evaluateMiner({ ...v, ...patch }, 'MZN').status,
|
||
'indeterminate',
|
||
);
|
||
assert.equal(
|
||
evaluateMiner(
|
||
{
|
||
...v,
|
||
previousBenefit: 'known',
|
||
previousBenefitDate: '2021-10-10',
|
||
},
|
||
'MZN',
|
||
).status,
|
||
'exempt',
|
||
);
|
||
assert.equal(
|
||
evaluateMiner(
|
||
{
|
||
...v,
|
||
previousBenefit: 'known',
|
||
previousBenefitDate: '2021-10-11',
|
||
},
|
||
'MZN',
|
||
).status,
|
||
'not_applicable',
|
||
);
|
||
assert.equal(
|
||
evaluateMiner(
|
||
{
|
||
...v,
|
||
previousBenefit: 'known',
|
||
previousBenefitDate: '2026-10-11',
|
||
},
|
||
'MZN',
|
||
).status,
|
||
'not_applicable',
|
||
);
|
||
});
|
||
void test('P059 return deadlines and one-year stay; exceptions are referenced,never presumed', () => {
|
||
const v = row('return_vehicle');
|
||
assert.equal(
|
||
evaluateMiner({ ...v, requestDate: '2026-11-30' }, 'MZN').status,
|
||
'exempt',
|
||
);
|
||
assert.equal(
|
||
evaluateMiner({ ...v, requestDate: '2026-12-01' }, 'MZN').status,
|
||
'indeterminate',
|
||
);
|
||
const ext = {
|
||
...v,
|
||
requestDate: '2027-03-01',
|
||
extensionRef: 'SYNTHETIC QA prorrogação',
|
||
conditions: { ...v.conditions, deadlineExtension: 'yes' },
|
||
};
|
||
assert.equal(evaluateMiner(ext, 'MZN').status, 'exempt');
|
||
assert.equal(
|
||
evaluateMiner({ ...ext, requestDate: '2027-03-02' }, 'MZN').status,
|
||
'indeterminate',
|
||
);
|
||
assert.equal(
|
||
evaluateMiner({ ...v, stayStart: '2026-02-01' }, 'MZN').status,
|
||
'indeterminate',
|
||
);
|
||
assert.equal(
|
||
evaluateMiner({ ...v, stayEnd: '2026-09-02' }, 'MZN').status,
|
||
'indeterminate',
|
||
);
|
||
const sep = row('separate_vehicle');
|
||
const except = {
|
||
...sep,
|
||
stayStart: '2026-02-01',
|
||
exceptionRef: 'SYNTHETIC QA âmbito/autorização6(7)',
|
||
conditions: { ...sep.conditions, stayException: 'yes' },
|
||
};
|
||
assert.equal(evaluateMiner(except, 'MZN').status, 'reduced');
|
||
assert.equal(
|
||
evaluateMiner({ ...except, exceptionRef: '' }, 'MZN').status,
|
||
'indeterminate',
|
||
);
|
||
for (const patch of [
|
||
{ normalVat: '' },
|
||
{ normalVat: '-1' },
|
||
{ normalVatRef: '' },
|
||
])
|
||
assert.equal(
|
||
evaluateMiner({ ...sep, ...patch }, 'MZN').status,
|
||
'indeterminate',
|
||
);
|
||
assert.equal(
|
||
evaluateMiner({ ...sep, normalVat: '0.000001' }, 'MZN').importVat,
|
||
'0.0000005',
|
||
);
|
||
});
|
||
void test('P059 heirs:unused right,goods acquired alive and request within one year;not automatic succession', () => {
|
||
const r = row('baggage', 'heir', {
|
||
rightHolder: 'heir',
|
||
heirRef: 'SYNTHETIC QA herdeiro/direito',
|
||
deathDate: '2025-10-01',
|
||
requestDate: '2026-10-01',
|
||
});
|
||
r.conditions = {
|
||
...r.conditions,
|
||
heir: 'yes',
|
||
unusedRight: 'yes',
|
||
acquiredAlive: 'yes',
|
||
};
|
||
assert.equal(evaluateMiner(r, 'MZN').status, 'exempt');
|
||
for (const patch of [
|
||
{ requestDate: '2026-10-02' },
|
||
{ requestDate: '2025-09-30' },
|
||
{ heirRef: '' },
|
||
{ deathDate: '' },
|
||
{ conditions: { ...r.conditions, acquiredAlive: '' } },
|
||
])
|
||
assert.notEqual(
|
||
evaluateMiner({ ...r, ...patch }, 'MZN').status,
|
||
'exempt',
|
||
);
|
||
assert.equal(
|
||
evaluateMiner(
|
||
{ ...r, conditions: { ...r.conditions, unusedRight: 'no' } },
|
||
'MZN',
|
||
).status,
|
||
'not_applicable',
|
||
);
|
||
});
|
||
void test('P059 saved scope detects double annual/vehicle rights and overlapping monthly balances without deleting lines', () => {
|
||
for (const t of ['appliance', 'vehicle', 'monthly', 'accumulated']) {
|
||
const first = row(t, 'first'),
|
||
second = { ...first, id: 'second' };
|
||
if (t === 'accumulated') {
|
||
first.periodTotal = '90000';
|
||
second.periodTotal = '90000';
|
||
}
|
||
const b = recordMiners(draft, { rows: [first, second] });
|
||
assert.deepEqual(
|
||
b.result.rows.map((r) => r.status),
|
||
['indeterminate', 'indeterminate'],
|
||
);
|
||
assert.equal(b.rows.length, 2);
|
||
}
|
||
const first = row('monthly', 'm1', { value: '5000' }),
|
||
second = { ...first, id: 'm2', value: '10000' };
|
||
assert.deepEqual(
|
||
recordMiners(draft, { rows: [first, second] }).result.rows.map(
|
||
(r) => r.status,
|
||
),
|
||
['exempt', 'exempt'],
|
||
);
|
||
second.value = '';
|
||
assert.equal(
|
||
recordMiners(draft, { rows: [first, second] }).result.rows[0].status,
|
||
'indeterminate',
|
||
);
|
||
const v = row('vehicle', 'v1'),
|
||
later = { ...v, id: 'v2', kind: 'tractor' };
|
||
assert.deepEqual(
|
||
recordMiners(draft, { rows: [v, later] }).result.rows.map(
|
||
(r) => r.status,
|
||
),
|
||
['exempt', 'exempt'],
|
||
);
|
||
});
|
||
const heir = row('baggage', 'heir', {
|
||
rightHolder: 'heir',
|
||
heirRef: 'SYNTHETIC QA herdeiro/direito',
|
||
deathDate: '2025-10-01',
|
||
requestDate: '2026-10-01',
|
||
});
|
||
heir.conditions = {
|
||
...heir.conditions,
|
||
heir: 'yes',
|
||
unusedRight: 'yes',
|
||
acquiredAlive: 'yes',
|
||
};
|
||
rows.push(heir);
|
||
let book = recordMiners(draft, { rows });
|
||
draft.modelo_a_snapshot = saveMinerBook(draft, book);
|
||
void test('P059 history,opportunity isolation,P046 QA and all125 accepted books retained', () => {
|
||
assert.equal(minerCurrent(draft, book), true);
|
||
const changed = {
|
||
...book,
|
||
rows: book.rows.map((r, i) => (i ? r : { ...r, scope: 'changed' })),
|
||
};
|
||
assert.equal(minerCurrent(draft, changed), false);
|
||
book = recordMiners(draft, changed);
|
||
draft.modelo_a_snapshot = saveMinerBook(draft, book);
|
||
assert.equal(book.history.length, 1);
|
||
assert.equal(
|
||
minerBook({ ...draft, context_opportunity: 'opportunity:999' }).rows
|
||
.length,
|
||
0,
|
||
);
|
||
assert.deepEqual(
|
||
prior,
|
||
Object.fromEntries(
|
||
Object.entries(JSON.parse(draft.modelo_a_snapshot)).filter(
|
||
([k]) => k !== 'minerImports',
|
||
),
|
||
),
|
||
);
|
||
assert.throws(() =>
|
||
minerBook({
|
||
...draft,
|
||
modelo_a_snapshot: '{"version":1,"books":{},"minerImports":[]}',
|
||
}),
|
||
);
|
||
assert.match(minerReportRows(draft)[0][3], /versão2/);
|
||
assert.doesNotMatch(minerReportRows(draft)[0][3], /IVA normal/);
|
||
assert.match(
|
||
minerReportRows(draft).find((r) =>
|
||
r[1].includes('separate_vehicle'),
|
||
)[3],
|
||
/IVA normal/,
|
||
);
|
||
if (process.env.IVA_MINER_FIXTURE)
|
||
fs.writeFileSync(process.env.IVA_MINER_FIXTURE, JSON.stringify(draft));
|
||
});
|