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

227 lines
8.0 KiB
JavaScript

import test from 'node:test';
import assert from 'node:assert/strict';
import fs from 'node:fs';
import {
newOwnName,
switchOwnNameTreatment,
ownNameConditions,
ownNameSpecificConditions,
ownNameTreatments,
evaluateOwnName,
recordOwnNames,
saveOwnNameBook,
ownNameBook,
ownNameCurrent,
ownNameReportRows,
} from '../../resources/js/lib/iva-own-name.ts';
const frozen = JSON.parse(
fs.readFileSync(
'tests/frontend/fixtures/iva-g10-own-name-preserved.json',
'utf8',
),
);
const draft = {
...frozen,
currency: 'MZN',
context_opportunity: 'opportunity:352',
project_title: 'SYNTHETIC QA — G10 nome próprio / Manica',
};
function row(t) {
return {
...newOwnName(t, 'MZN'),
treatment: t,
description: 'SYNTHETIC QA ' + t,
period: '2026-12',
origin: 'projected',
operationDate: '2026-12-12',
operationRef: 'SYNTHETIC QA operação',
documentRef: 'SYNTHETIC QA documento/pressuposto',
documentDate: '2026-12-12',
principalRef: 'SYNTHETIC QA comitente/mandante A',
agentRef: 'SYNTHETIC QA agente B',
thirdPartyRef: 'SYNTHETIC QA terceiro C',
contractRef: 'SYNTHETIC QA contrato/mandato',
subjectRef: 'SYNTHETIC QA objecto da operação',
firstAmount: '1000.25',
secondAmount: '1100.75',
firstLegRef: 'SYNTHETIC QA relação1',
secondLegRef: 'SYNTHETIC QA relação2',
existingBaseRef: 'SYNTHETIC QA referênciaP091preservada',
scope: 'SYNTHETIC QA partes/objecto/operação/período',
evidence: 'SYNTHETIC QA pressupostos expressos',
conditions: Object.fromEntries(
[...ownNameConditions, ...ownNameSpecificConditions(t)].map(
([key]) => [key, 'yes'],
),
),
};
}
for (const rule of ownNameTreatments)
void test(
rule.branch +
'/' +
rule.id +
' direction,own facts and original separate amounts',
() => {
const r = row(rule.id),
result = evaluateOwnName(r, 'MZN');
assert.equal(result.status, 'determined');
assert.equal(result.legs.length, 2);
assert.deepEqual(
result.legs.map((l) => [l.supplier, l.acquirer]),
rule.direction === 'sale'
? [
[r.principalRef, r.agentRef],
[r.agentRef, r.thirdPartyRef],
]
: [
[r.thirdPartyRef, r.agentRef],
[r.agentRef, r.principalRef],
],
);
assert.deepEqual(
result.legs.map((l) => l.consideration),
['1000.25', '1100.75'],
);
assert.deepEqual(
['baseAmount', 'vat', 'rate'].map((k) => result[k]),
[null, null, null],
);
for (const [key] of [
...ownNameConditions,
...ownNameSpecificConditions(rule.id),
]) {
const missing = structuredClone(r);
delete missing.conditions[key];
assert.equal(
evaluateOwnName(missing, 'MZN').status,
'indeterminate',
);
missing.conditions[key] = 'no';
assert.equal(
evaluateOwnName(missing, 'MZN').status,
'not_applicable',
);
assert.equal(evaluateOwnName(missing, 'MZN').legs.length, 0);
}
for (const field of [
'description',
'operationRef',
'documentRef',
'contractRef',
'subjectRef',
'principalRef',
'agentRef',
'thirdPartyRef',
'firstLegRef',
'secondLegRef',
'firstAmount',
'secondAmount',
'scope',
'evidence',
])
assert.equal(
evaluateOwnName({ ...r, [field]: '' }, 'MZN').status,
'indeterminate',
field,
);
for (const patch of [
{ operationDate: '2026-11-12' },
{ documentDate: '2026-02-30' },
{ period: '2025-12' },
{ currency: 'USD' },
{ firstAmount: '1e3' },
{ secondAmount: '-1' },
])
assert.equal(
evaluateOwnName({ ...r, ...patch }, 'MZN').status,
'indeterminate',
);
assert.equal(
evaluateOwnName({ ...r, currency: 'USD' }, 'USD').legs[0]
.currency,
'USD',
);
assert.equal(
evaluateOwnName({ ...r, firstAmount: '0' }, 'MZN').legs[0]
.consideration,
'0',
);
assert.equal(
evaluateOwnName({ ...r, existingBaseRef: '' }, 'MZN').status,
'determined',
);
assert.match(
result.reason,
rule.kind === 'goods'
? /comissário considerado comprador|comitente considerado comprador/
: /adquirente eprestador/,
);
},
);
void test('Changing direction/kind keeps references and values but requires own confirmations', () => {
const original = row('goods_sale_commission');
const changed = switchOwnNameTreatment(
original,
'service_purchase_mandate',
);
assert.equal(changed.firstAmount, original.firstAmount);
assert.equal(changed.secondAmount, original.secondAmount);
assert.equal(changed.existingBaseRef, original.existingBaseRef);
assert.equal(changed.principalRef, original.principalRef);
assert.equal(changed.conditions.directionConfirmed, undefined);
assert.equal(evaluateOwnName(changed, 'MZN').status, 'indeterminate');
changed.conditions = {
...changed.conditions,
...Object.fromEntries(
ownNameSpecificConditions(changed.treatment).map(([k]) => [
k,
'yes',
]),
),
};
const result = evaluateOwnName(changed, 'MZN');
assert.equal(result.status, 'determined');
assert.equal(result.legs[0].supplier, original.thirdPartyRef);
assert.match(result.reason, /Não transformar/);
});
void test('Four circuits save/recover/history/report;P091 and all prior books unchanged', () => {
const rows = ownNameTreatments.map((t) => row(t.id));
let book = recordOwnNames(draft, { rows });
book = recordOwnNames(draft, book);
assert.equal(book.history.length, 1);
assert.notEqual(book.result.inputs, book.rows);
const next = { ...draft, modelo_a_snapshot: saveOwnNameBook(draft, book) };
assert.deepEqual(ownNameBook(next), book);
assert.ok(ownNameCurrent(next, book));
assert.equal(ownNameCurrent({ ...next, currency: 'USD' }, book), false);
assert.equal(
ownNameCurrent({ ...next, context_opportunity: 'other' }, book),
false,
);
assert.equal(ownNameReportRows(next).length, 4);
assert.ok(
ownNameReportRows(next).every((r) =>
r[2].includes('sem soma das duas relações'),
),
);
const store = JSON.parse(next.modelo_a_snapshot);
delete store.ownNames;
assert.deepEqual(store, JSON.parse(frozen.modelo_a_snapshot));
assert.throws(() => recordOwnNames(next, { rows: [rows[0], rows[0]] }));
assert.throws(() =>
ownNameBook({
...next,
modelo_a_snapshot: JSON.stringify({
...JSON.parse(next.modelo_a_snapshot),
ownNames: [],
}),
}),
);
if (process.env.IVA_OWN_NAME_FIXTURE)
fs.writeFileSync(
process.env.IVA_OWN_NAME_FIXTURE,
JSON.stringify(next, null, 2) + '\n',
);
});