Files
Investidor-V2/tests/frontend/irpc-international-credit.test.mjs
T

408 lines
16 KiB
JavaScript

import test from 'node:test';
import assert from 'node:assert/strict';
import fs from 'node:fs';
import crypto from 'node:crypto';
import { countryIsoCodes } from '../../resources/js/lib/country-iso-codes.ts';
import { internationalCase } from './helpers/irpc-international-case.mjs';
import {
calculateAnnual,
annualBook,
recordAnnual,
saveAnnualBook,
annualCurrent,
annualHtml,
annualReportRows,
prepareInternationalBook,
} from '../../resources/js/lib/irpc-annual-settlement.ts';
import { createProjectDossierReport } from '../../resources/js/lib/project-dossier-report.ts';
const value = (v) => (v ? Number(v.numerator) / Number(v.denominator) : null);
const now = '2026-10-27T17:00:00+02:00';
const calc = ({ d, b }) => calculateAnnual(d, b);
const pending = (c) => {
const m = calc(c);
assert.equal(m.status, 'indeterminate', JSON.stringify(m.pending));
assert.equal(m.arithmeticBalance, null);
assert.equal(m.internationalCredit.deducted, null);
assert.equal(m.pecDeduction.deducted, null);
return m;
};
const position = (c) => c.b.internationalCredits.positions[0];
const proof = (c) => position(c).payments[0];
void test('country code projection exactly reuses the existing master and its source hash', () => {
const raw = Buffer.from(
fs
.readFileSync(
new URL('../../resources/data/iso3166.tab', import.meta.url),
'utf8',
)
.replace(/\r\n/g, '\n'),
);
const codes = raw
.toString('utf8')
.split(/\r?\n/)
.filter((l) => l && !l.startsWith('#'))
.map((l) => l.split('\t')[0]);
assert.deepEqual(countryIsoCodes, codes);
const source = fs.readFileSync(
new URL('../../resources/js/lib/country-iso-codes.ts', import.meta.url),
'utf8',
);
assert.ok(
source.includes(crypto.createHash('sha256').update(raw).digest('hex')),
);
});
void test('10 paid capped at documented national8 precedes PEC200/PPC500:1408-8-200-500=700', () => {
const m = calc(internationalCase());
assert.deepEqual(m.pending, []);
const p = m.internationalCredit.positions[0];
assert.equal(value(p.paid), 10);
assert.equal(value(p.eligible), 8);
assert.equal(value(p.aboveLimit), 2);
assert.equal(value(m.internationalCredit.deducted), 8);
assert.equal(value(m.internationalCredit.afterCredit), 1400);
assert.equal(value(m.pecDeduction.deducted), 200);
assert.equal(value(m.payable), 700);
assert.equal(m.internationalCredit.carryCreated, false);
assert.equal(m.officialBalancesConsumed, false);
});
void test('documented treaty limit6 caps credit without country-based automatic entitlement', () => {
const c = internationalCase();
Object.assign(position(c), {
treaty: 'yes',
treatyLimit: '6',
treatyReference:
'SYNTHETIC QA convention/article/exercise/limit, not real treaty data',
});
const m = calc(c);
assert.equal(value(m.internationalCredit.deducted), 6);
assert.equal(value(m.payable), 702);
assert.equal(value(m.internationalCredit.positions[0].aboveLimit), 4);
position(c).treatyLimit = '';
pending(c);
position(c).treatyLimit = '6';
position(c).treatyReference = '';
pending(c);
});
void test('multiple actual receipts share one country limit;two countries keep separate limits', () => {
const c = internationalCase();
proof(c).amount = '6';
proof(c).proofAmount = '6';
position(c).payments.push({
...proof(c),
id: 'foreign-second',
document: 'OTHER-RECEIPT',
amount: '4',
proofAmount: '4',
});
assert.equal(value(calc(c).internationalCredit.deducted), 8);
const other = structuredClone(position(c));
other.id = 'country-pt';
other.country = 'PT';
other.qualificationCountry = 'PT';
other.nationalLimit = '4';
other.payments = [
{
...other.payments[0],
id: 'pt-tax',
document: 'PT-OTHER-RECEIPT',
proofAmount: '5',
amount: '5',
},
];
c.b.internationalCredits.positions.push(other);
assert.equal(value(calc(c).internationalCredit.deducted), 12);
assert.equal(value(calc(c).payable), 696);
});
void test('same country cannot multiply the national fraction across positions or other context maps', () => {
const a = internationalCase(),
copy = structuredClone(position(a));
copy.id = 'duplicate-country';
copy.payments[0].id = 'other-proof';
copy.payments[0].document = 'OTHER';
a.b.internationalCredits.positions.push(copy);
assert.match(pending(a).pending.join(' '), /país\/exercício/);
const b = internationalCase(),
other = structuredClone(b.b);
other.internationalCredits.positions[0].payments[0].id = 'elsewhere';
other.internationalCredits.positions[0].payments[0].document =
'ELSEWHERE-RECEIPT';
const s = JSON.parse(b.d.modelo_a_snapshot);
s.irpcAnnual = { 'opportunity:other': other };
b.d.modelo_a_snapshot = JSON.stringify(s);
assert.match(pending(b).pending.join(' '), /noutro mapa/);
});
void test('actual previous credit use reduces eligible credit,not gross tax or simulated history', () => {
const c = internationalCase();
position(c).previousUse.amount = '3';
let m = calc(c);
assert.equal(value(m.internationalCredit.positions[0].eligible), 8);
assert.equal(value(m.internationalCredit.positions[0].available), 5);
assert.equal(value(m.payable), 703);
position(c).previousUse.amount = '9';
assert.match(pending(c).pending.join(' '), /excede/);
position(c).previousUse = {
state: 'absent',
amount: '',
reference: 'QA no actual previous use',
};
assert.equal(value(calc(c).payable), 700);
});
void test('lack of collecta is separated from tax above eligibility limits and never refunds credit or PEC', () => {
const c = internationalCase('2000', '2000', '200', '0'),
m = calc(c);
assert.equal(m.status, 'balanced');
assert.equal(value(m.internationalCredit.deducted), 1408);
assert.equal(value(m.internationalCredit.insufficientCollecta), 592);
assert.equal(value(m.internationalCredit.positions[0].aboveLimit), 0);
assert.equal(value(m.pecDeduction.deducted), 0);
assert.equal(value(m.pecDeduction.remaining), 200);
assert.equal(value(m.recoverable), 0);
assert.equal(m.internationalCredit.countryAllocationCreated, false);
c.b.ppc = { ...internationalCase().b.ppc };
const recovered = calc(c);
assert.equal(value(recovered.recoverable), 500);
assert.equal(
value(recovered.internationalCredit.insufficientCollecta),
592,
);
assert.equal(recovered.internationalCredit.carryCreated, false);
});
void test('known zero,declared absence and missing retain distinct inputs and outcomes', () => {
const zero = internationalCase('0');
assert.equal(value(calc(zero).internationalCredit.deducted), 0);
assert.equal(value(calc(zero).payable), 708);
const a = internationalCase();
a.b.internationalCredits.state = 'absent';
a.b.internationalCredits.positions = [];
assert.equal(value(calc(a).payable), 708);
a.b.internationalCredits.state = '';
pending(a);
a.b.internationalCredits.state = 'known';
pending(a);
const b = internationalCase();
b.b.internationalCredits.state = 'absent';
pending(b);
position(b).previousUse = {
state: 'absent',
amount: '0',
reference: 'QA contradiction',
};
pending(b);
});
void test('country,entity,year,inclusion,current assessment,domestic fraction and convention require support', () => {
for (const patch of [
{ country: 'MZ' },
{ country: 'ZZ' },
{ country: '' },
{ country: 'PT' },
{ qualificationCountry: '' },
{ subjectNuit: '999999999' },
{ year: '2025' },
{ incomeIncluded: '' },
{ incomeIncluded: 'no' },
{ incomeAmount: '' },
{ incomeAmount: '0' },
{ incomeReference: '' },
{ nationalLimit: '' },
{ nationalLimitReference: '' },
{ assessmentKey: 'stale' },
{ treaty: '' },
{ treaty: 'no', treatyLimit: '0' },
{ treatyReference: '' },
]) {
const c = internationalCase();
Object.assign(position(c), patch);
pending(c);
}
for (const patch of [{ state: '' }, { amount: '' }, { reference: '' }]) {
const c = internationalCase();
Object.assign(position(c).previousUse, patch);
pending(c);
}
});
void test('actual foreign income tax proof is required,not projections,other taxes,wrong exercise or unsupported currency', () => {
for (const patch of [
{ effective: '' },
{ effective: 'no' },
{ incomeTax: '' },
{ incomeTax: 'no' },
{ taxReference: '' },
{ document: '' },
{ issuer: '' },
{ reference: '' },
{ subjectNuit: '999999999' },
{ year: '2025' },
{ date: '2026-02-30' },
{ date: '2025-09-30' },
{ currency: 'USD' },
{ amount: '10.01' },
{ amount: '0.001' },
]) {
const c = internationalCase();
Object.assign(proof(c), patch);
pending(c);
}
const c = internationalCase();
position(c).payments = [];
pending(c);
});
void test('payment date differs from income exercise only with explicit correspondence,never an automatic carry', () => {
const c = internationalCase();
proof(c).date = '2027-01-15';
pending(c);
proof(c).exerciseReference =
'SYNTHETIC QA own-exercise2026 assessment and payment relation';
const m = calc(c);
assert.equal(value(m.payable), 700);
assert.equal(m.internationalCredit.carryCreated, false);
});
void test('same physical foreign receipt cannot be duplicated,re-dated or used as PPC/PEC/RF', () => {
const a = internationalCase();
position(a).payments.push({
...proof(a),
id: 'other-date',
date: '2026-10-01',
});
pending(a);
for (const kind of ['ppc', 'pec', 'rf']) {
const c = internationalCase(
'10',
'8',
'200',
'500',
kind === 'rf' ? '300' : '0',
);
const physical =
kind === 'ppc'
? c.b.ppc.rows[0]
: kind === 'pec'
? c.b.pecPayments.rows[0]
: {
issuer: 'QA AT',
document: 'QA-RF-PEC-2026',
proofAmount: '300',
};
Object.assign(proof(c), {
issuer: physical.issuer,
document: physical.document,
proofAmount: physical.proofAmount,
});
assert.match(pending(c).pending.join(' '), /naturez|comprovativo/i);
}
});
void test('a foreign receipt cannot move country/entity across context maps;external changes invalidate current result', () => {
const c = internationalCase(),
other = structuredClone(c.b);
other.ppc.rows = [];
other.ppc.state = 'absent';
other.pecPayments.rows = [];
other.pecPayments.state = 'absent';
other.internationalCredits.positions[0].country = 'PT';
const s = JSON.parse(c.d.modelo_a_snapshot);
s.irpcAnnual = { 'opportunity:other': other };
c.d.modelo_a_snapshot = JSON.stringify(s);
pending(c);
other.internationalCredits.positions[0].payments[0].document = 'OTHER-PT';
c.d.modelo_a_snapshot = JSON.stringify(s);
assert.equal(value(calc(c).payable), 700);
c.d.modelo_a_snapshot = saveAnnualBook(c.d, recordAnnual(c.d, c.b, now));
const saved = annualBook(c.d);
assert.equal(annualCurrent(c.d, saved), true);
const edit = JSON.parse(c.d.modelo_a_snapshot);
edit.irpcAnnual[
'opportunity:other'
].internationalCredits.positions[0].country = 'ZA';
c.d.modelo_a_snapshot = JSON.stringify(edit);
assert.equal(annualCurrent(c.d, saved), false);
pending({ ...c, b: saved });
});
void test('economic/benefit positive or missing states block only the dependent annual balance,not known eligibility', () => {
for (const kind of ['economic', 'benefits'])
for (const patch of [
{ state: '' },
{ state: 'known', amount: '1' },
{ reference: '' },
]) {
const c = internationalCase();
Object.assign(c.b.internationalCredits[kind], patch);
const m = pending(c);
assert.equal(value(m.internationalCredit.positions[0].eligible), 8);
assert.equal(value(m.assessment.colecta), 1408);
}
});
void test('exact decimals and withholding are included once after credit and PEC', () => {
const c = internationalCase('10.25', '8.15', '200', '500', '300');
position(c).previousUse.amount = '3.01';
const m = calc(c);
assert.deepEqual(m.internationalCredit.deducted, {
numerator: '257',
denominator: '50',
});
assert.equal(value(m.payable), 402.86);
assert.equal(value(m.knownWithholdings), 300);
});
void test('documented fractional ceilings retain exact arithmetic without assumed tax rounding', () => {
const c = internationalCase('10', '1/3');
const m = calc(c);
assert.deepEqual(m.internationalCredit.deducted, {
numerator: '1',
denominator: '3',
});
assert.deepEqual(m.payable, { numerator: '2123', denominator: '3' });
position(c).nationalLimit = '1/0';
pending(c);
});
void test('prepare preserves deliberate prior summary and history;save/recover/report appends frozen records', () => {
const c = internationalCase(),
detail = structuredClone(c.b.internationalCredits);
delete c.b.internationalCredits;
const original = JSON.parse(c.d.modelo_a_snapshot),
plan = c.d.business_plan_snapshot;
c.d.modelo_a_snapshot = saveAnnualBook(c.d, recordAnnual(c.d, c.b, now));
const prior = structuredClone(annualBook(c.d).result);
assert.equal(value(prior.model.payable), 708);
let next = prepareInternationalBook(annualBook(c.d));
next.internationalCredits = detail;
c.d.modelo_a_snapshot = saveAnnualBook(c.d, recordAnnual(c.d, next, now));
const back = annualBook(JSON.parse(JSON.stringify(c.d)));
assert.deepEqual(back.history, [prior]);
assert.equal(annualCurrent(c.d, back), true);
assert.equal(value(back.result.model.payable), 700);
assert.deepEqual(back.credits, {
state: 'known',
amount: '0',
reference: 'QA créditos precedentes conhecidos zero',
});
const after = JSON.parse(c.d.modelo_a_snapshot);
delete after.irpcAnnual;
assert.deepEqual(after, original);
assert.equal(c.d.business_plan_snapshot, plan);
const html = annualHtml(c.d);
assert.match(html, /Crédito internacional — antes do PEC/);
assert.match(html, /700.00/);
assert.match(html, /1400.00/);
assert.match(
JSON.stringify(
createProjectDossierReport(c.d, {
selectedSections: new Set(['finance']),
}),
),
/Crédito internacional — ZA/,
);
const frozen = structuredClone(back.result);
back.internationalCredits.positions[0].nationalLimit = '7';
c.d.modelo_a_snapshot = saveAnnualBook(c.d, back);
assert.equal(annualCurrent(c.d, back), false);
assert.deepEqual(back.result, frozen);
assert.match(annualReportRows(c.d).flat().join(' '), /Histórico/);
assert.throws(() => annualHtml(c.d), /fontes actuais/);
});
void test('malformed optional international detail never resets existing snapshots', () => {
const c = internationalCase(),
snapshot = c.d.modelo_a_snapshot;
proof(c).incomeTax = null;
assert.throws(() => saveAnnualBook(c.d, c.b), /não recuperável/);
assert.equal(c.d.modelo_a_snapshot, snapshot);
});