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

470 lines
18 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,
} from '../../resources/js/lib/iva-acquisitions.ts';
import {
closureBook,
closureSources,
newClosure,
recordClosure,
saveClosureBook,
adoptPreviousCredit,
newClosureCredit,
closureCurrent,
} from '../../resources/js/lib/iva-closure.ts';
import {
substitutionBook,
substitutionCurrent,
} from '../../resources/js/lib/iva-substitution.ts';
import {
refundBook,
refundSources,
newRefund,
recordRefund,
saveRefundBook,
refundCurrent,
refundReportRows,
} from '../../resources/js/lib/iva-refund.ts';
const seed = JSON.parse(
fs.readFileSync(
new URL('./fixtures/iva-l3d-preserved.json', import.meta.url),
'utf8',
),
),
older = JSON.parse(
fs.readFileSync(
new URL('./fixtures/iva-l3ab-preserved.json', import.meta.url),
'utf8',
),
);
function fixture() {
const d = structuredClone(seed),
base = JSON.parse(older.modelo_a_snapshot),
s = JSON.parse(d.modelo_a_snapshot);
for (const [k, v] of Object.entries(base))
if (k !== 'version') s[k] = { ...v, ...s[k] };
d.modelo_a_snapshot = JSON.stringify(s);
d.context_opportunity = 'opportunity:374';
const sales = structuredClone(s.salesOperations['opportunity:373']);
d.modelo_a_snapshot = saveSalesBook(d, recordSales(d, sales));
const b = structuredClone(s.books['opportunity:373']);
b.rows[0].net = '5001000';
b.rows[0].vat = '800160';
b.rows[0].gross = '5801160';
delete b.result;
delete b.history;
d.modelo_a_snapshot = saveAcquisitionBook(
d,
recordAcquisitions(d, b, '2026-10-25T13:00:00Z'),
);
const row = {
...newClosure(
'refund-Jan',
closureSources(d).find((s) => s.period === '2026-01'),
'SYNTHETIC QA entidade374',
),
firstDeclaration: 'yes',
filing: 'timely',
submissionDate: '2026-02-15',
filingRef: 'SYNTHETIC QA prazo declarado',
creditsComplete: 'yes',
interest: 'none',
interestRef: 'SYNTHETIC QA sem juros',
destination: 'refund',
refundAmount: '600000',
};
const ab = recordClosure(
d,
{ version: 1, rows: [row] },
'2026-10-25T13:01:00Z',
);
d.modelo_a_snapshot = saveClosureBook(d, ab);
assert.equal(
ab.result.rows[0].status,
'determined',
ab.result.rows[0].reason,
);
const input = {
...newRefund('refund1', refundSources(d)[0]),
ground: 'high_credit',
originPeriod: '2026-01',
entitlementDate: '2026-01-10',
groundRef:
'SYNTHETIC QA extractos/origem800000 e créditos mais antigos',
factsConfirmed: 'yes',
oldestFirst: 'yes',
requestReference: 'SYNTHETIC QA pedidoR1',
requestDate: '2026-02-15',
stage: 'submitted',
decision: 'partial',
decisionReference: 'SYNTHETIC QA decisãoD1',
decisionDate: '2026-03-01',
decisionIssuer: 'SYNTHETIC QA entidade emitente declarada',
approvedAmount: '550000',
receipts: [
{
id: 'receipt1',
reference: 'SYNTHETIC QA recebimentoR1a',
date: '2026-03-05',
amount: '200000',
},
{
id: 'receipt2',
reference: 'SYNTHETIC QA recebimentoR1b',
date: '2026-03-10',
amount: '250000',
},
],
};
return { d, b: { version: 1, rows: [input] } };
}
const n = (v) => v && `${v.numerator}/${v.denominator}`;
void test('25 is allocated once between26 and27;requested,approved,received and waiting remain distinct', () => {
const { d, b } = fixture(),
ab = closureBook(d).result.rows[0];
assert.equal(n(ab.fields['25']), '800000/1');
assert.equal(n(ab.fields['26']), '200000/1');
assert.equal(n(ab.fields['27']), '600000/1');
const r = recordRefund(d, b).result.rows[0];
assert.equal(r.status, 'determined', r.reason);
assert.equal(r.eligibility, 'compatible');
assert.equal(n(r.requested), '600000/1');
assert.equal(n(r.reported), '200000/1');
assert.equal(n(r.approved), '550000/1');
assert.equal(n(r.received), '450000/1');
assert.equal(n(r.awaitingReceipt), '100000/1');
assert.equal(n(r.notGranted), '50000/1');
});
void test('preparation,presented pending,approval and rejection do not automatically create receipt or release credit', () => {
const { d, b } = fixture();
for (const stage of ['preparation', 'submitted']) {
const v = structuredClone(b);
Object.assign(v.rows[0], { stage, decision: 'pending', receipts: [] });
const r = recordRefund(d, v).result.rows[0];
assert.equal(r.status, 'determined');
assert.equal(r.approved, null);
assert.equal(r.received, null);
}
const full = structuredClone(b);
Object.assign(full.rows[0], {
decision: 'approved',
approvedAmount: '600000',
receipts: [],
});
let r = recordRefund(d, full).result.rows[0];
assert.equal(n(r.received), '0/1');
assert.equal(n(r.awaitingReceipt), '600000/1');
const rejected = structuredClone(b);
Object.assign(rejected.rows[0], {
decision: 'rejected',
approvedAmount: '0',
receipts: [],
});
r = recordRefund(d, rejected).result.rows[0];
assert.equal(r.status, 'determined');
assert.equal(n(r.notGranted), '600000/1');
assert.equal(n(closureBook(d).result.rows[0].fields['26']), '200000/1');
});
void test('source,request and decision details are required;unknown never becomes entitlement or cash', () => {
const { d, b } = fixture();
for (const patch of [
{ source: null },
{ requestReference: '' },
{ requestDate: '' },
{ decisionReference: '' },
{ decisionDate: '2026-02-01' },
{ decisionIssuer: '' },
{ approvedAmount: '' },
{ stage: 'preparation' },
]) {
const v = structuredClone(b);
Object.assign(v.rows[0], patch);
assert.equal(
recordRefund(d, v).result.rows[0].status,
'indeterminate',
JSON.stringify(patch),
);
}
const forged = structuredClone(b);
forged.rows[0].source.requested = { numerator: '700000', denominator: '1' };
assert.equal(recordRefund(d, forged).result.rows[0].requested, null);
});
void test('a documented external decision is recorded without turning an unimplemented/unknown basis into a new approval gate', () => {
const { d, b } = fixture();
for (const patch of [
{ ground: '' },
{ factsConfirmed: '' },
{ oldestFirst: '' },
{ entitlementDate: '' },
{ groundRef: '' },
]) {
const v = structuredClone(b);
Object.assign(v.rows[0], patch);
const r = recordRefund(d, v).result.rows[0];
assert.equal(r.status, 'determined', r.reason);
assert.equal(r.eligibility, 'not_demonstrated');
assert.equal(n(r.approved), '550000/1');
assert.equal(n(r.received), '450000/1');
v.rows[0].decision = 'pending';
v.rows[0].receipts = [];
const pending = recordRefund(d, v).result.rows[0];
assert.equal(pending.status, 'indeterminate');
assert.equal(pending.approved, null);
}
});
void test('current four-month/high-credit conditions and ten-year limit are applied without obsolete50percent rule', () => {
const { d, b } = fixture();
const v = structuredClone(b);
Object.assign(v.rows[0], {
ground: 'four_months',
originPeriod: '2025-09',
entitlementDate: '2025-09-10',
});
assert.equal(recordRefund(d, v).result.rows[0].eligibility, 'compatible');
v.rows[0].originPeriod = '2025-10';
v.rows[0].entitlementDate = '2025-10-10';
assert.equal(recordRefund(d, v).result.rows[0].eligibility, 'incompatible');
v.rows[0].originPeriod = '2015-01';
v.rows[0].entitlementDate = '2015-01-10';
assert.equal(recordRefund(d, v).result.rows[0].eligibility, 'incompatible');
const cessation = structuredClone(b);
Object.assign(cessation.rows[0], {
ground: 'cessation',
cessationDate: '2026-01-31',
});
assert.equal(
recordRefund(d, cessation).result.rows[0].eligibility,
'compatible',
);
cessation.rows[0].cessationDate = '2026-03-01';
assert.equal(
recordRefund(d, cessation).result.rows[0].eligibility,
'incompatible',
);
});
void test('thresholds are strictly greater;fractional credit remains exact after allocation', () => {
for (const [vat, request, ground, expected] of [
['500160', '100000', 'high_credit', 'incompatible'],
['100160', '50000', 'four_months', 'incompatible'],
['500161', '100000', 'high_credit', 'compatible'],
]) {
const { d, b } = fixture(),
acq = acquisitionBook(d);
acq.rows[0].vat = vat;
acq.rows[0].gross = String(Number(acq.rows[0].net) + Number(vat));
d.modelo_a_snapshot = saveAcquisitionBook(
d,
recordAcquisitions(d, acq),
);
const ab = closureBook(d);
ab.rows[0].source = closureSources(d)
.filter((s) => s.period === '2026-01')
.at(-1);
ab.rows[0].refundAmount = request;
d.modelo_a_snapshot = saveClosureBook(d, recordClosure(d, ab));
Object.assign(b.rows[0], {
source: refundSources(d)[0],
ground,
originPeriod: '2025-09',
entitlementDate: '2025-09-10',
stage: 'preparation',
decision: 'pending',
receipts: [],
});
assert.equal(recordRefund(d, b).result.rows[0].eligibility, expected);
}
const { d } = fixture(),
acq = acquisitionBook(d);
acq.rows[0].vat = '800161';
acq.rows[0].gross = '5801161';
acq.rows[0].d.numerator = '1';
acq.rows[0].d.denominator = '3';
d.modelo_a_snapshot = saveAcquisitionBook(d, recordAcquisitions(d, acq));
const ab = closureBook(d);
ab.rows[0].source = closureSources(d)
.filter((s) => s.period === '2026-01')
.at(-1);
ab.rows[0].refundAmount = '200000';
const result = recordClosure(d, ab);
assert.equal(n(result.result.rows[0].fields['25']), '799681/3');
assert.equal(n(result.result.rows[0].fields['26']), '199681/3');
assert.equal(n(result.result.rows[0].fields['27']), '200000/1');
});
void test('request/receipt duplication,over-receipt and decisions beyond request are refused', () => {
const { d, b } = fixture();
const copy = structuredClone(b);
copy.rows.push({ ...structuredClone(copy.rows[0]), id: 'copy' });
assert.ok(
recordRefund(d, copy).result.rows.every((r) => r.requested === null),
);
for (const patch of [
{ approvedAmount: '600001' },
{ decision: 'approved', approvedAmount: '550000' },
{ decision: 'rejected', approvedAmount: '1' },
{ decision: 'pending' },
]) {
const v = structuredClone(b);
Object.assign(v.rows[0], patch);
assert.equal(recordRefund(d, v).result.rows[0].status, 'indeterminate');
}
const receipt = structuredClone(b);
receipt.rows[0].receipts.push({
...receipt.rows[0].receipts[0],
id: 'copy',
});
assert.equal(recordRefund(d, receipt).result.rows[0].received, null);
const over = structuredClone(b);
over.rows[0].receipts[0].amount = '400000';
assert.equal(recordRefund(d, over).result.rows[0].status, 'indeterminate');
});
void test('submitted refund locks the allocation even after current preparation is removed;histories are not erased', () => {
const { d, b } = fixture();
const book = recordRefund(d, b);
d.modelo_a_snapshot = saveRefundBook(d, book);
const ab = closureBook(d);
ab.rows[0].destination = 'report';
assert.match(recordClosure(d, ab).result.rows[0].reason, /Crédito ligado/);
const removed = recordRefund(d, { ...book, rows: [] });
d.modelo_a_snapshot = saveRefundBook(d, removed);
assert.match(recordClosure(d, ab).result.rows[0].reason, /Crédito ligado/);
assert.ok(removed.history.length);
});
void test('only residual26 travels to next month;old whole-credit carry requires explicit adoption', () => {
const { d, b } = fixture();
let ab = closureBook(d);
const full = structuredClone(ab);
full.rows[0].destination = 'report';
const before = recordClosure(d, full);
const feb = {
...newClosure(
'refund-Feb',
closureSources(d).find((s) => s.period === '2026-02'),
'SYNTHETIC QA entidade374',
),
firstDeclaration: 'yes',
filing: 'timely',
submissionDate: '2026-03-15',
filingRef: 'SYNTHETIC QA prazo',
creditsComplete: 'yes',
interest: 'none',
interestRef: 'SYNTHETIC QA sem juros',
destination: 'report',
credits: [
adoptPreviousCredit(
newClosureCredit('carry', 'previous'),
before.result.rows[0],
),
],
};
ab = recordClosure(d, { ...ab, rows: [...ab.rows, feb] });
assert.equal(ab.result.rows[1].status, 'indeterminate');
d.modelo_a_snapshot = saveClosureBook(d, ab);
assert.deepEqual(refundSources(d), []);
ab.rows[1].credits[0] = adoptPreviousCredit(
ab.rows[1].credits[0],
ab.result.rows[0],
);
ab = recordClosure(d, ab);
assert.equal(n(ab.result.rows[1].fields['19']), '200000/1');
assert.equal(n(ab.result.rows[1].fields['26']), '199920/1');
d.modelo_a_snapshot = saveClosureBook(d, ab);
assert.equal(recordRefund(d, b).result.rows[0].status, 'determined');
});
void test('effective carry already used in a later declaration cannot be reallocated retroactively for a refund', () => {
const { d } = fixture(),
acq = acquisitionBook(d);
acq.rows[0].origin = 'effective';
d.modelo_a_snapshot = saveAcquisitionBook(d, recordAcquisitions(d, acq));
let ab = closureBook(d);
Object.assign(ab.rows[0], {
origin: 'effective',
source: closureSources(d)
.filter((s) => s.period === '2026-01')
.at(-1),
destination: 'report',
});
ab = recordClosure(d, ab);
assert.equal(ab.result.rows[0].status, 'determined');
const feb = {
...structuredClone(ab.rows[0]),
id: 'actual-Feb',
period: '2026-02',
source: closureSources(d)
.filter((s) => s.period === '2026-02')
.at(-1),
submissionDate: '2026-03-15',
credits: [
adoptPreviousCredit(
newClosureCredit('actual-carry', 'previous'),
ab.result.rows[0],
),
],
};
ab = recordClosure(d, { ...ab, rows: [...ab.rows, feb] });
assert.equal(ab.result.rows[1].status, 'determined');
d.modelo_a_snapshot = saveClosureBook(d, ab);
ab.rows[0].destination = 'refund';
ab.rows[0].refundAmount = '600000';
const changed = recordClosure(d, ab);
assert.match(
changed.result.rows[0].reason,
/Reporte efectivo já utilizado/,
);
assert.equal(changed.result.rows[0].status, 'indeterminate');
});
void test('unsubmitted allocation may be changed explicitly,but old reported credit cannot fund the old request', () => {
const { d, b } = fixture();
b.rows[0].stage = 'preparation';
b.rows[0].decision = 'pending';
b.rows[0].receipts = [];
let book = recordRefund(d, b);
d.modelo_a_snapshot = saveRefundBook(d, book);
const ab = closureBook(d);
ab.rows[0].destination = 'report';
d.modelo_a_snapshot = saveClosureBook(d, recordClosure(d, ab));
assert.equal(refundCurrent(d, book), false);
assert.equal(recordRefund(d, book).result.rows[0].requested, null);
});
void test('save/recover preserves all prior L1/L2/AB/C maps and frozen report;recalculation appends history', () => {
const { d, b } = fixture(),
before = JSON.parse(d.modelo_a_snapshot);
let book = recordRefund(d, b);
d.modelo_a_snapshot = saveRefundBook(d, book);
const after = JSON.parse(d.modelo_a_snapshot);
for (const [k, v] of Object.entries(before))
assert.deepEqual(after[k], v, k);
assert.ok(refundCurrent(d, refundBook(d)));
const cDraft = { ...d, context_opportunity: 'opportunity:373' };
assert.ok(substitutionCurrent(cDraft, substitutionBook(cDraft)));
assert.ok(closureCurrent(cDraft, closureBook(cDraft)));
book.rows[0].requestReference = 'deliberate edit';
assert.equal(refundCurrent(d, book), false);
d.modelo_a_snapshot = saveRefundBook(d, book);
assert.doesNotMatch(
refundReportRows(d)
.map((r) => r.join(' '))
.join(' '),
/deliberate edit/,
);
const prior = structuredClone(book.result);
book = recordRefund(d, book);
assert.deepEqual(book.history.at(-1), prior);
});
void test('export synthetic frozen refund reconciliation for guardedAPI and actual component proof', () => {
const { d, b } = fixture();
const first = recordRefund(d, b, '2026-10-25T13:02:00Z'),
book = recordRefund(d, first, '2026-10-25T13:03:00Z');
d.modelo_a_snapshot = saveRefundBook(d, book);
assert.ok(refundCurrent(d, book));
if (process.env.IVA_L3D_CALCULATED)
fs.writeFileSync(process.env.IVA_L3D_CALCULATED, JSON.stringify(d));
});