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

190 lines
6.8 KiB
JavaScript

import test from 'node:test';
import assert from 'node:assert/strict';
import fs from 'node:fs';
import {
newImportExemption,
evaluateImportExemption,
recordImportExemptions,
saveImportExemptionBook,
importExemptionBook,
importExemptionCurrent,
importExemptionRules,
importSupplySource,
} from '../../resources/js/lib/iva-import-exemptions.ts';
import { createProjectDossierReport } from '../../resources/js/lib/project-dossier-report.ts';
const frozen = JSON.parse(
fs.readFileSync(
new URL('./fixtures/iva-offers-inputs.json', import.meta.url),
'utf8',
),
);
const rules = importExemptionRules.filter((r) => r.branch === 'P052');
const row = (rule) => ({
...newImportExemption('g6e-' + rule.id, 'MZN'),
treatment: rule.id,
description: 'SYNTHETIC QA ' + rule.label,
period: '2026-12',
declaredValue: '5000',
importer: 'SYNTHETIC QA importador',
documentRef: 'SYNTHETIC QA G6E ' + rule.id,
documentDate: '2026-11-14',
evidence:
'SYNTHETIC QA tipo de abastecimento, embarcação/avião e navegação internacional, percurso e datas normais identificados; pressuposto expresso, não documento real',
conditions: Object.fromEntries(
rule.conditions.map(([key]) => [key, 'yes']),
),
});
const draft = () => ({
...structuredClone(frozen),
context_opportunity: 'opportunity:335',
project_title: 'SYNTHETIC QA — G6E / Abastecimentos importados',
});
void test('P052 eight profiles have own navigation/goods/window/onboard conditions;every failed or missing condition prevents zero', () => {
assert.equal(rules.length, 8);
assert.match(importSupplySource, /12\(3\)/);
for (const rule of rules) {
const input = row(rule);
assert.equal(evaluateImportExemption(input, 'MZN').importVat, '0.00');
for (const [key] of rule.conditions)
for (const value of ['', 'unknown', 'no']) {
const result = evaluateImportExemption(
{
...input,
conditions: { ...input.conditions, [key]: value },
},
'MZN',
);
assert.equal(
result.status,
value === 'no' ? 'not_applicable' : 'indeterminate',
);
assert.equal(result.importVat, null);
}
for (const patch of [
{ period: '2025-12' },
{ currency: 'USD' },
{ documentRef: '' },
{ documentDate: '2026-02-30' },
{ evidence: '' },
])
assert.equal(
evaluateImportExemption({ ...input, ...patch }, 'MZN')
.importVat,
null,
);
}
});
void test('12(3) exclusions are applied only to own goods/navigation profile;P053/P054 confirmations cannot substitute', () => {
const ship = rules.find((r) => r.id === 'ship_provisions_import'),
air = rules.find((r) => r.id === 'aircraft_provisions_import');
const exclusions = [
'supplyNoDismantleOtherUse',
'supplyNoFloatingHospitality',
'supplyNoRecreation',
'supplyNoCoastalFishing',
];
for (const key of exclusions) {
assert.ok(ship.conditions.some((c) => c[0] === key));
assert.ok(!air.conditions.some((c) => c[0] === key));
assert.equal(
evaluateImportExemption(
{
...row(ship),
conditions: { ...row(ship).conditions, [key]: 'no' },
},
'MZN',
).status,
'not_applicable',
);
}
for (const rule of rules)
assert.equal(
rule.conditions.some(([key]) => key === 'supplyNormalTanks'),
rule.id.includes('_fuel_'),
);
const fuel = rules.find((r) => r.id === 'ship_fuel_import');
assert.equal(
evaluateImportExemption(
{
...row(fuel),
conditions: {
...row(fuel).conditions,
supplyNormalTanks: 'no',
},
},
'MZN',
).importVat,
null,
);
assert.ok(!fuel.conditions.some(([key]) => exclusions.includes(key)));
const input = row(air);
delete input.conditions.supplyInternationalAircraft;
input.conditions.eligibleAircraft = 'yes';
assert.equal(evaluateImportExemption(input, 'MZN').status, 'indeterminate');
const switched = { ...row(ship), treatment: 'ship_fuel_import' };
assert.equal(
evaluateImportExemption(switched, 'MZN').status,
'indeterminate',
);
assert.equal(switched.documentRef, row(ship).documentRef);
});
void test('P052 save/recover/report preserve26fiscalbooks and two offer drafts exactly;archive unknown/failed and keep old keys current', () => {
const d = draft(),
prior = JSON.parse(frozen.modelo_a_snapshot);
let book = recordImportExemptions(d, {
rows: rules.map((rule) => ({ ...row(rule), conditions: {} })),
});
book = recordImportExemptions(d, {
...book,
rows: rules.map((rule) => ({
...row(rule),
conditions: { ...row(rule).conditions, supplyImportWindow: 'no' },
})),
});
book = recordImportExemptions(d, { ...book, rows: rules.map(row) });
assert.equal(book.history.length, 2);
assert.ok(
book.history.every((h) => h.rows.every((r) => r.importVat === null)),
);
d.modelo_a_snapshot = saveImportExemptionBook(d, book);
assert.deepEqual(importExemptionBook(JSON.parse(JSON.stringify(d))), book);
assert.ok(importExemptionCurrent(d, book));
assert.match(book.result.sourceKey, /import-onboard-supplies\/1/);
const next = JSON.parse(d.modelo_a_snapshot);
for (const key of ['salesOperations', 'books', 'offerPreparations'])
assert.deepEqual(next[key], prior[key]);
for (const [scope, previous] of Object.entries(prior.importExemptions)) {
assert.deepEqual(next.importExemptions[scope], previous);
assert.ok(
importExemptionCurrent(
{ ...d, context_opportunity: scope },
previous,
),
);
}
assert.equal(
next.books['opportunity:329'].result.periods[0].fields['11'],
null,
);
const report = JSON.stringify(
createProjectDossierReport(d, {
selectedSections: new Set(['finance']),
version: 'QA G6E',
}),
);
for (const token of [
'P052',
'opportunity:335',
'Manica',
'2026-12',
'SYNTHETIC QA G6E',
'0.00',
'12(1)(g)',
'campo11',
...rules.map((r) => r.id),
])
assert.ok(report.includes(token), token);
if (process.env.IVA_G6E_CALCULATED)
fs.writeFileSync(process.env.IVA_G6E_CALCULATED, JSON.stringify(d));
});