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

281 lines
9.4 KiB
JavaScript

import test from 'node:test';
import assert from 'node:assert/strict';
import fs from 'node:fs';
import {
newForeignOperation,
evaluateForeignOperation,
foreignSources,
foreignEvents,
recordForeignOperations,
saveForeignOperationBook,
foreignOperationBook,
foreignOperationCurrent,
foreignOperationReportRows,
switchForeignSource,
} from '../../resources/js/lib/iva-foreign-operations.ts';
import {
recordGoodsLocations,
saveGoodsLocationBook,
goodsLocationBook,
} from '../../resources/js/lib/iva-goods-location.ts';
import {
recordServiceLocations,
saveServiceLocationBook,
} from '../../resources/js/lib/iva-service-location.ts';
import {
recordListedServices,
saveListedServiceBook,
} from '../../resources/js/lib/iva-listed-services.ts';
import {
recordCurrencyEvents,
saveCurrencyEventBook,
} from '../../resources/js/lib/iva-currency-events.ts';
const frozen = JSON.parse(
fs.readFileSync(
'tests/frontend/fixtures/iva-foreign-operations-preserved.json',
'utf8',
),
),
original = JSON.parse(frozen.modelo_a_snapshot);
function seed() {
const d = {
...frozen,
context_opportunity: 'opportunity:358',
project_title: 'SYNTHETIC QA — Operações no estrangeiro / Manica',
};
for (const [map, record, save] of [
['goodsLocations', recordGoodsLocations, saveGoodsLocationBook],
['serviceLocations', recordServiceLocations, saveServiceLocationBook],
['listedServices', recordListedServices, saveListedServiceBook],
]) {
const rows = structuredClone(Object.values(original[map])[0].rows).map(
(r) => ({ ...r, operationRef: 'SYNTHETIC QA op ' + r.id }),
);
if (map === 'serviceLocations') {
const r = structuredClone(
rows.find((x) => x.id === 'transport_service-MZ'),
);
rows.push({
...r,
id: 'transport_partial',
operationRef: 'SYNTHETIC QA op transport_partial',
departure: 'MZ',
arrival: 'foreign',
nationalDistance: '20',
totalDistance: '100',
});
}
d.modelo_a_snapshot = save(d, record(d, { rows }));
}
const event = structuredClone(
original.currencyEvents['opportunity:357'].rows.find(
(r) => r.treatment === 'goods_available',
),
);
event.operationRef = 'SYNTHETIC QA op g8a-goods_without_transport';
d.modelo_a_snapshot = saveCurrencyEventBook(
d,
recordCurrencyEvents(d, { rows: [event] }),
);
return d;
}
const draft = seed();
function row(id, kind, source) {
return {
...newForeignOperation(id),
sourceKind: kind,
sourceRowId: source,
territorialPart: 'outside',
hypotheticalTaxable: 'yes',
hypotheticalRef:
'SYNTHETIC QA hipótese interna/natureza tributável e19(2),fundamento identificado',
excluded19_2: 'no',
scope: 'SYNTHETIC QA conjunto/parcela exterior/período identificado',
evidence: 'SYNTHETIC QA factos/pressupostos expressos',
};
}
const cases = [
row('foreign_goods', 'goods', 'g8a-goods_without_transport'),
row('foreign_services', 'services', 'general_service-foreign'),
row('foreign_listed', 'listed', 'rights_service-outbound'),
row('foreign_transport_part', 'services', 'transport_partial'),
];
cases[0].eventRowId = 'goods_available';
for (const r of cases)
void test(
'P002 ' + r.id + ' reuses delivered territoriality and potential19only',
() => {
const v = evaluateForeignOperation(draft, r);
assert.equal(v.status, 'determined');
assert.equal(v.relation19, 'potential');
assert.equal(
v.territory,
r.id === 'foreign_transport_part'
? 'outside_portion'
: 'outside',
);
assert.equal(v.deduction, null);
assert.equal(v.vat, null);
assert.equal(v.baseAmount, null);
assert.equal(v.source.id, r.sourceRowId);
assert.equal(v.source.current, true);
if (r.eventRowId) assert.equal(v.event.eventDate, '2026-12-10');
},
);
void test('P002 unknown/national/partial do not imply foreign or exemption', () => {
assert.equal(
evaluateForeignOperation(draft, { ...cases[0], sourceRowId: '' })
.status,
'indeterminate',
);
assert.equal(
evaluateForeignOperation(draft, {
...cases[0],
sourceRowId: 'g8a-goods_with_transport',
}).status,
'not_applicable',
);
assert.equal(
evaluateForeignOperation(draft, { ...cases[3], territorialPart: '' })
.status,
'indeterminate',
);
assert.equal(
evaluateForeignOperation(draft, {
...cases[3],
territorialPart: 'national',
}).status,
'not_applicable',
);
for (const patch of [
{ scope: '' },
{ evidence: '' },
{ hypotheticalRef: '' },
{ hypotheticalTaxable: '' },
{ excluded19_2: '' },
])
assert.equal(
evaluateForeignOperation(draft, { ...cases[0], ...patch }).status,
'indeterminate',
);
const no = evaluateForeignOperation(draft, {
...cases[0],
hypotheticalTaxable: 'no',
});
assert.equal(no.relation19, 'not_demonstrated');
assert.equal(no.deduction, null);
const excluded = evaluateForeignOperation(draft, {
...cases[0],
excluded19_2: 'yes',
});
assert.equal(excluded.relation19, 'excluded_19_2');
assert.equal(excluded.deduction, null);
});
void test('P002 stale source and event scope mismatch never overwrite prior acceptance', () => {
const b = goodsLocationBook(draft),
changed = {
...draft,
modelo_a_snapshot: saveGoodsLocationBook(draft, {
...b,
rows: b.rows.map((r) =>
r.id === cases[0].sourceRowId
? { ...r, placeCountry: 'MZ' }
: r,
),
}),
};
assert.equal(
evaluateForeignOperation(changed, cases[0]).status,
'indeterminate',
);
assert.equal(
evaluateForeignOperation(
{ ...draft, context_opportunity: 'opportunity:359' },
cases[0],
).status,
'indeterminate',
);
assert.equal(
evaluateForeignOperation(draft, {
...cases[1],
eventRowId: 'goods_available',
}).status,
'indeterminate',
);
const sw = switchForeignSource(
cases[0],
'services',
'general_service-foreign',
);
assert.equal(sw.hypotheticalRef, cases[0].hypotheticalRef);
assert.equal(sw.hypotheticalTaxable, '');
assert.equal(sw.eventRowId, '');
assert.equal(foreignEvents(draft).length, 1);
assert.equal(foreignSources(draft, 'goods').length, 3);
});
void test('P002 dependency changes invalidate new analysis while snapshot/history stay immutable', () => {
const a = recordForeignOperations(draft, { rows: cases }),
d = { ...draft, modelo_a_snapshot: saveForeignOperationBook(draft, a) };
assert.equal(foreignOperationCurrent(d, a), true);
const b = goodsLocationBook(d),
changed = {
...d,
modelo_a_snapshot: saveGoodsLocationBook(
d,
recordGoodsLocations(d, b),
),
};
assert.equal(foreignOperationCurrent(changed, a), false);
assert.deepEqual(a.result.inputs, cases);
assert.equal(foreignOperationReportRows(d).length, 4);
});
void test('P002 private save/recovery/report preserve 120delivered books and P104currency facts', () => {
const rows = [
...cases,
row('national', 'goods', 'g8a-goods_with_transport'),
{
...cases[1],
id: 'hypothesis_not_taxable',
hypotheticalTaxable: 'no',
},
{ ...cases[2], id: 'exclusion19_2', excluded19_2: 'yes' },
],
a = recordForeignOperations(draft, { rows }),
d = { ...draft, modelo_a_snapshot: saveForeignOperationBook(draft, a) },
b = recordForeignOperations(d, a);
d.modelo_a_snapshot = saveForeignOperationBook(d, b);
assert.equal(b.history.length, 1);
assert.equal(foreignOperationReportRows(d).length, 7);
const store = JSON.parse(d.modelo_a_snapshot);
delete store.foreignOperations;
for (const name of [
'goodsLocations',
'serviceLocations',
'listedServices',
'currencyEvents',
])
delete store[name]['opportunity:358'];
assert.deepEqual(store, original);
assert.deepEqual(
foreignOperationBook({ ...d, context_opportunity: 'opportunity:359' }),
{ rows: [] },
);
assert.throws(() =>
recordForeignOperations(d, { rows: [rows[0], rows[0]] }),
);
assert.throws(() =>
foreignOperationBook({
...d,
modelo_a_snapshot: JSON.stringify({
...store,
foreignOperations: [],
}),
}),
);
if (process.env.IVA_FOREIGN_OPERATIONS_FIXTURE)
fs.writeFileSync(
process.env.IVA_FOREIGN_OPERATIONS_FIXTURE,
JSON.stringify(d, null, 2) + '\n',
);
});