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

417 lines
15 KiB
JavaScript

import test from 'node:test';
import assert from 'node:assert/strict';
import fs from 'node:fs';
import {
recordSales,
saveSalesBook,
} from '../../resources/js/lib/iva-operations.ts';
import {
recordAcquisitions,
saveAcquisitionBook,
acquisitionBook,
acquisitionCurrent,
} from '../../resources/js/lib/iva-acquisitions.ts';
import {
closureBook,
closureSources,
newClosure,
newClosureCredit,
recordClosure,
saveClosureBook,
adoptPreviousCredit,
closureCurrent,
closureReportRows,
} from '../../resources/js/lib/iva-closure.ts';
const preserved = JSON.parse(
fs.readFileSync(
new URL('./fixtures/iva-l3ab-preserved.json', import.meta.url),
'utf8',
),
);
export function closureFixture() {
const draft = {
...structuredClone(preserved),
context_opportunity: 'opportunity:373',
project_title: 'SYNTHETIC QA — L3-A/B fecho do IVA',
};
const s = JSON.parse(draft.modelo_a_snapshot),
base = s.books['opportunity:370'];
const sales = ['2026-01', '2026-02', '2026-03'].map((period, i) => ({
...structuredClone(s.salesOperations['opportunity:370'].rows[0]),
id: 'sale-' + i,
period,
amount: i === 1 ? '500' : '1000',
sourcePeriod: period,
}));
draft.modelo_a_snapshot = saveSalesBook(
draft,
recordSales(draft, {
currency: 'MZN',
rows: sales,
periods: sales.map((r) => ({ period: r.period, complete: true })),
}),
);
const purchase = {
...structuredClone(base.rows[0]),
id: 'purchase-Jan',
period: '2026-01',
documentDate: '2026-01-10',
documentRef: 'SYNTHETIC QA aquisiçãoJaneiro',
net: '1625',
vat: '260',
gross: '1885',
d: {
...structuredClone(base.rows[0].d),
numerator: '1',
denominator: '1',
},
};
const acquisitions = recordAcquisitions(draft, {
currency: 'MZN',
taxpayerRegistered: 'yes',
rows: [purchase],
periods: sales.map((r) => ({
period: r.period,
complete: true,
importsComplete: true,
absent: ['12', '13'],
})),
});
draft.modelo_a_snapshot = saveAcquisitionBook(draft, acquisitions);
const make = (period) => ({
...newClosure(
'close-' + period,
closureSources(draft).find((s) => s.period === period),
'SYNTHETIC QA entidade373',
),
firstDeclaration: 'yes',
creditsComplete: 'yes',
filing: 'timely',
submissionDate: `2026-${String(Number(period.slice(5)) + 1).padStart(2, '0')}-15`,
filingRef: 'SYNTHETIC QA entrega em prazo assumida',
interest: 'none',
interestRef: 'SYNTHETIC QA pressuposto sem juros',
destination: 'report',
});
const jan = make('2026-01');
jan.credits = [
{
...newClosureCredit('opening', 'opening'),
period: '2025-12',
reference: 'SYNTHETIC QA saldoabertura',
amount: '50',
},
];
let book = recordClosure(draft, { version: 1, rows: [jan] });
const feb = make('2026-02');
feb.credits = [
adoptPreviousCredit(
newClosureCredit('carry-Feb', 'previous'),
book.result.rows[0],
),
];
book = recordClosure(draft, { ...book, rows: [jan, feb] });
const mar = make('2026-03');
mar.credits = [
adoptPreviousCredit(
newClosureCredit('carry-Mar', 'previous'),
book.result.rows[1],
),
{
...newClosureCredit('communication', 'communication'),
period: '2026-02',
reference: 'SYNTHETIC QA comunicaçãoAT20',
date: '2026-03-10',
amount: '20',
},
];
mar.interest = 'documented';
mar.interestAmount = '2';
mar.interestRef = 'SYNTHETIC QA jurosidentificados';
mar.payments = [
{
id: 'payment1',
reference: 'SYNTHETIC QA reciboP1',
date: '2026-04-16',
amount: '30',
},
];
book = recordClosure(draft, { ...book, rows: [jan, feb, mar] });
return { draft, book, make, acquisitions };
}
const amount = (r, f) =>
r.fields[f] && `${r.fields[f].numerator}/${r.fields[f].denominator}`;
void test('three periods reconcile opening credit,carry,communicated credit,interest and payment without double deduction', () => {
const { draft, book } = closureFixture();
assert.deepEqual(
book.result.rows.map((r) => r.status),
['determined', 'determined', 'determined'],
);
assert.deepEqual(
book.result.rows.map((r) => amount(r, '26')),
['150/1', '70/1', '0/1'],
);
const mar = book.result.rows[2];
assert.equal(amount(mar, '19'), '70/1');
assert.equal(amount(mar, '20'), '20/1');
assert.equal(amount(mar, '22'), '70/1');
assert.equal(amount(mar, '24'), '72/1');
assert.deepEqual(mar.paid, { numerator: '30', denominator: '1' });
assert.deepEqual(mar.outstanding, { numerator: '42', denominator: '1' });
assert.equal(mar.fields['21'], null);
assert.equal(amount(mar, '27'), '0/1');
assert.ok(acquisitionCurrent(draft, acquisitionBook(draft)));
assert.equal(book.history.length, 2);
});
void test('origin,coverage,deadline and unsupported paths remain explicit;unknown never becomes zero', () => {
const { draft, book } = closureFixture();
for (const patch of [
{ creditsComplete: '' },
{ filing: '' },
{ filing: 'late' },
{ firstDeclaration: 'no' },
{ entityRef: '' },
{ submissionDate: '' },
{ destination: 'refund' },
]) {
const changed = structuredClone(book);
changed.rows[0] = { ...changed.rows[0], ...patch };
const r = recordClosure(draft, changed).result.rows;
assert.equal(r[0].status, 'indeterminate', JSON.stringify(patch));
assert.equal(r[1].status, 'indeterminate');
}
const interest = structuredClone(book);
interest.rows[2].interest = '';
const r = recordClosure(draft, interest).result.rows[2];
assert.equal(amount(r, '22'), '70/1');
assert.equal(r.fields['24'], null);
const future = structuredClone(book);
future.rows[2].credits[1].date = '2026-05-01';
assert.equal(
recordClosure(draft, future).result.rows[2].fields['20'],
null,
);
const effective = structuredClone(book);
effective.rows[0].origin = 'effective';
assert.match(
recordClosure(draft, effective).result.rows[0].reason,
/projectados/,
);
});
void test('duplicate documents,opening versus communication and payment references cannot create duplicate use', () => {
const { draft, book } = closureFixture();
const b = structuredClone(book);
b.rows[0].credits.push({ ...b.rows[0].credits[0], id: 'copy' });
assert.equal(recordClosure(draft, b).result.rows[0].fields['19'], null);
const cross = structuredClone(book);
cross.rows[0].credits.push({
...cross.rows[0].credits[0],
id: 'copy',
kind: 'communication',
date: '2026-01-05',
});
assert.equal(recordClosure(draft, cross).result.rows[0].fields['19'], null);
const payments = structuredClone(book);
payments.rows[2].payments.push({
...payments.rows[2].payments[0],
id: 'copy',
});
const p = recordClosure(draft, payments).result.rows[2];
assert.equal(p.paid, null);
assert.equal(amount(p, '26'), '0/1');
assert.equal(amount(p, '24'), '72/1');
const opening = structuredClone(book);
opening.rows[1].credits = [
{ ...opening.rows[0].credits[0], id: 'new-opening', period: '2026-01' },
];
assert.match(
recordClosure(draft, opening).result.rows[1].reason,
/reutilize26/,
);
});
void test('changing a predecessor preserves historical results and requires explicit carry adoption;payment edit does not change carry', () => {
const { draft, book } = closureFixture();
const first = structuredClone(book.result);
let changed = structuredClone(book);
changed.rows[0].credits[0].amount = '60';
assert.equal(closureCurrent(draft, changed), false);
changed = recordClosure(draft, changed);
assert.equal(amount(changed.result.rows[0], '26'), '160/1');
assert.equal(changed.result.rows[1].status, 'indeterminate');
assert.deepEqual(changed.history.at(-1), first);
changed.rows[1].credits[0] = adoptPreviousCredit(
changed.rows[1].credits[0],
changed.result.rows[0],
);
changed = recordClosure(draft, changed);
assert.equal(amount(changed.result.rows[1], '26'), '80/1');
assert.equal(changed.result.rows[2].status, 'indeterminate');
changed.rows[2].credits[0] = adoptPreviousCredit(
changed.rows[2].credits[0],
changed.result.rows[1],
);
changed = recordClosure(draft, changed);
assert.equal(amount(changed.result.rows[2], '22'), '60/1');
const pay = structuredClone(book);
pay.rows[0].payments = [
{
id: 'unexpected',
reference: 'SYNTHETIC QA pagamentoanterior',
date: '2026-02-16',
amount: '1',
},
];
const v = recordClosure(draft, pay);
assert.equal(v.result.rows[0].carryKey, first.rows[0].carryKey);
assert.equal(v.result.rows[1].status, 'determined');
});
void test('overpayment remains a payment fact and does not create credit20/25/26', () => {
const { draft, book } = closureFixture();
book.rows[2].payments[0].amount = '100';
const r = recordClosure(draft, book).result.rows[2];
assert.deepEqual(r.overpayment, { numerator: '28', denominator: '1' });
assert.equal(amount(r, '20'), '20/1');
assert.equal(amount(r, '25'), '0/1');
assert.equal(amount(r, '26'), '0/1');
});
void test('carry between periods preserves exact fractions instead of adding rounded presentation', () => {
const { draft, book } = closureFixture();
let a = acquisitionBook(draft);
a.rows[0].net = '3125';
a.rows[0].vat = '500';
a.rows[0].gross = '3625';
a.rows[0].d.denominator = '3';
a = recordAcquisitions(draft, a);
draft.modelo_a_snapshot = saveAcquisitionBook(draft, a);
book.rows[0].source = closureSources(draft).find(
(s) => s.revision === a.result.revision && s.period === '2026-01',
);
let b = recordClosure(draft, book);
assert.deepEqual(b.result.rows[0].fields['26'], {
numerator: '170',
denominator: '3',
});
b.rows[1].credits[0] = adoptPreviousCredit(
b.rows[1].credits[0],
b.result.rows[0],
);
b = recordClosure(draft, b);
assert.deepEqual(b.result.rows[1].fields['22'], {
numerator: '70',
denominator: '3',
});
});
void test('recovered opportunities keep scenarios separate and expose collisions of effective scope', () => {
const { draft, book } = closureFixture();
const other = structuredClone(book);
const store = JSON.parse(draft.modelo_a_snapshot);
store.ivaClosures = { 'opportunity:other': other };
draft.modelo_a_snapshot = JSON.stringify(store);
assert.equal(
recordClosure(draft, book).result.rows[0].status,
'determined',
'projected scenarios do not consume each other',
);
book.rows[0].origin = 'effective';
other.rows[0].origin = 'effective';
store.ivaClosures['opportunity:other'] = other;
draft.modelo_a_snapshot = JSON.stringify(store);
assert.match(
recordClosure(draft, book).result.rows[0].reason,
/noutra oportunidade/,
);
});
void test('frozen L2 sources are reused exactly and incomplete or fabricated sources cannot close balances', () => {
const { draft, book } = closureFixture();
const b = structuredClone(book);
b.rows[0].source.credit = { numerator: '999', denominator: '1' };
assert.equal(
recordClosure(draft, b).result.rows[0].status,
'indeterminate',
);
const removed = { ...draft };
const s = JSON.parse(draft.modelo_a_snapshot);
delete s.books['opportunity:373'].result;
removed.modelo_a_snapshot = JSON.stringify(s);
assert.equal(
recordClosure(removed, book).result.rows[0].fields['18'],
null,
);
assert.deepEqual(
acquisitionBook(draft).result.periods.map((p) => [
p.fields['17'],
p.fields['18'],
]),
[
['0.00', '100.00'],
['80.00', '0.00'],
['160.00', '0.00'],
],
);
const unchanged = recordAcquisitions(draft, acquisitionBook(draft));
const extraVersion = {
...draft,
modelo_a_snapshot: saveAcquisitionBook(draft, unchanged),
};
assert.ok(
closureCurrent(extraVersion, book),
'adding an unrelated L2 version does not rewrite or stale the selected frozen results',
);
});
void test('save recovery and report preserve every prior L1/L2 map,values and closure histories', () => {
let { draft, book } = closureFixture();
const before = JSON.parse(preserved.modelo_a_snapshot);
const acquired = structuredClone(acquisitionBook(draft));
draft.modelo_a_snapshot = saveClosureBook(draft, book);
const recovered = JSON.parse(JSON.stringify(draft));
assert.deepEqual(closureBook(recovered), book);
assert.ok(closureCurrent(recovered, book));
assert.ok(acquisitionCurrent(recovered, acquisitionBook(recovered)));
assert.deepEqual(acquisitionBook(recovered), acquired);
const after = JSON.parse(recovered.modelo_a_snapshot);
for (const [k, map] of Object.entries(before)) {
if (k === 'version') continue;
for (const [id, v] of Object.entries(map))
assert.deepEqual(after[k][id], v, k + id);
}
const report = JSON.stringify(closureReportRows(recovered));
for (const token of [
'2026-01',
'2026-02',
'2026-03',
'150/1',
'70/1',
'72/1',
'30/1',
'42/1',
'saldoabertura',
'comunicaçãoAT20',
'reciboP1',
'opportunity:373',
])
assert.ok(report.includes(token), token);
const malformed = JSON.parse(recovered.modelo_a_snapshot);
malformed.ivaClosures = null;
assert.throws(
() =>
closureBook({
...recovered,
modelo_a_snapshot: JSON.stringify(malformed),
}),
/não recuperável/,
);
book.rows[0].credits[0].amount = '999';
const edited = {
...recovered,
modelo_a_snapshot: saveClosureBook(recovered, book),
};
assert.equal(closureCurrent(edited, book), false);
assert.match(JSON.stringify(closureReportRows(edited)), /50/);
assert.equal(book.result.inputs[0].credits[0].amount, '50');
if (process.env.IVA_L3AB_CALCULATED)
fs.writeFileSync(
process.env.IVA_L3AB_CALCULATED,
JSON.stringify(recovered),
);
});