142 lines
5.2 KiB
JavaScript
142 lines
5.2 KiB
JavaScript
import test from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import { internationalCase } from './helpers/irpc-international-case.mjs';
|
|
import {
|
|
calculateAnnual,
|
|
annualBook,
|
|
annualCurrent,
|
|
recordAnnual,
|
|
saveAnnualBook,
|
|
annualHtml,
|
|
annualReportRows,
|
|
} from '../../resources/js/lib/irpc-annual-settlement.ts';
|
|
import { createProjectDossierReport } from '../../resources/js/lib/project-dossier-report.ts';
|
|
|
|
export function nationalCase(income = '100') {
|
|
const c = internationalCase('100');
|
|
Object.assign(c.b.internationalCredits.positions[0], {
|
|
nationalMethod: 'proportional',
|
|
incomeAmount: income,
|
|
nationalBasisReference:
|
|
'SYNTHETIC QA: net taxable foreign component, costs/losses/deductions allocated and included in this L6 base; not a real tax determination',
|
|
});
|
|
return c;
|
|
}
|
|
const position = (c) => c.b.internationalCredits.positions[0];
|
|
|
|
void test('national fraction aggregate cannot allocate more than the current base across countries', () => {
|
|
const c = nationalCase('3000');
|
|
const second = structuredClone(position(c));
|
|
Object.assign(second, {
|
|
id: 'country-pt',
|
|
country: 'PT',
|
|
qualificationCountry: 'PT',
|
|
});
|
|
Object.assign(second.payments[0], {
|
|
id: 'tax-pt',
|
|
document: 'SYNTHETIC foreign-tax-pt',
|
|
});
|
|
c.b.internationalCredits.positions.push(second);
|
|
const m = calculateAnnual(c.d, c.b);
|
|
assert.equal(m.arithmeticBalance, null);
|
|
assert.ok(m.pending.some((message) => message.includes('em conjunto')));
|
|
});
|
|
|
|
void test('national fraction derives 1408 x 100 / 4400 before credits and retains the manual entry', () => {
|
|
const c = nationalCase();
|
|
const m = calculateAnnual(c.d, c.b);
|
|
assert.deepEqual(m.pending, []);
|
|
const p = m.internationalCredit.positions[0];
|
|
assert.deepEqual(p.nationalLimit, { numerator: '32', denominator: '1' });
|
|
assert.equal(p.input.nationalLimit, '8');
|
|
assert.equal(
|
|
p.nationalDerivation.reference,
|
|
position(c).nationalBasisReference,
|
|
);
|
|
assert.deepEqual(m.payable, { numerator: '676', denominator: '1' });
|
|
assert.equal(m.internationalCredit.officialBalancesConsumed, false);
|
|
});
|
|
|
|
void test('national fraction calculation survives serialization, retrieval and both existing report renderers', () => {
|
|
const c = nationalCase('0.01');
|
|
const historical = structuredClone(c.b.result);
|
|
const b = recordAnnual(c.d, c.b, '2026-11-10T13:00:00+02:00');
|
|
const saved = { ...c.d, modelo_a_snapshot: saveAnnualBook(c.d, b) };
|
|
const back = JSON.parse(JSON.stringify(saved));
|
|
const recovered = annualBook(back);
|
|
assert.equal(annualCurrent(back, recovered), true);
|
|
assert.deepEqual(
|
|
recovered.result.model.internationalCredit.positions[0].nationalLimit,
|
|
{ numerator: '2', denominator: '625' },
|
|
);
|
|
assert.deepEqual(
|
|
calculateAnnual(back, recovered).internationalCredit,
|
|
recovered.result.model.internationalCredit,
|
|
);
|
|
assert.deepEqual(c.b.result, historical);
|
|
assert.match(annualHtml(back), /2\/625/);
|
|
assert.match(
|
|
JSON.stringify(annualReportRows(back)),
|
|
/IRPC-national-fraction\/1/,
|
|
);
|
|
assert.match(
|
|
JSON.stringify(
|
|
createProjectDossierReport(back, {
|
|
selectedSections: new Set(['finance']),
|
|
generatedAt: '2026-11-10T13:00:00+02:00',
|
|
}),
|
|
),
|
|
/2\/625/,
|
|
);
|
|
});
|
|
|
|
void test('national fraction leaves a case indeterminate without net-income correspondence or with too much income', () => {
|
|
for (const patch of [
|
|
{ nationalBasisReference: '' },
|
|
{ incomeAmount: '4400.01' },
|
|
{ nationalMethod: 'unknown' },
|
|
]) {
|
|
const c = nationalCase();
|
|
Object.assign(position(c), patch);
|
|
if (patch.nationalMethod)
|
|
assert.throws(() => calculateAnnual(c.d, c.b));
|
|
else {
|
|
const m = calculateAnnual(c.d, c.b);
|
|
assert.equal(m.status, 'indeterminate');
|
|
assert.equal(m.arithmeticBalance, null);
|
|
}
|
|
}
|
|
});
|
|
|
|
void test('national fraction rejects stale assessment binding and still applies a documented treaty ceiling', () => {
|
|
const c = nationalCase();
|
|
Object.assign(position(c), {
|
|
treaty: 'yes',
|
|
treatyLimit: '6',
|
|
treatyReference:
|
|
'SYNTHETIC QA case-specific ceiling, no actual treaty assertion',
|
|
});
|
|
assert.deepEqual(calculateAnnual(c.d, c.b).payable, {
|
|
numerator: '702',
|
|
denominator: '1',
|
|
});
|
|
position(c).assessmentKey = 'obsolete';
|
|
assert.equal(calculateAnnual(c.d, c.b).arithmeticBalance, null);
|
|
});
|
|
|
|
void test('national fraction keeps historical documented mode unchanged when the optional method is absent', () => {
|
|
const c = internationalCase();
|
|
const original = calculateAnnual(c.d, c.b);
|
|
position(c).nationalMethod = 'documented';
|
|
const m = calculateAnnual(c.d, c.b);
|
|
assert.deepEqual(
|
|
m.internationalCredit.deducted,
|
|
original.internationalCredit.deducted,
|
|
);
|
|
assert.deepEqual(m.payable, { numerator: '700', denominator: '1' });
|
|
assert.equal(
|
|
m.internationalCredit.positions[0].nationalDerivation,
|
|
undefined,
|
|
);
|
|
});
|