286 lines
11 KiB
JavaScript
286 lines
11 KiB
JavaScript
import test from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import { economicCase } from './helpers/irpc-economic-case.mjs';
|
|
import {
|
|
normalBook,
|
|
calculateNormal,
|
|
recordNormal,
|
|
saveNormalBook,
|
|
normalCurrent,
|
|
normalHtml,
|
|
} from '../../resources/js/lib/irpc-normal.ts';
|
|
import { calculateAnnual } from '../../resources/js/lib/irpc-annual-settlement.ts';
|
|
import {
|
|
prepareEconomicInclusion,
|
|
calculateEconomicInclusions,
|
|
} from '../../resources/js/lib/irpc-normal-economic.ts';
|
|
import { createProjectDossierReport } from '../../resources/js/lib/project-dossier-report.ts';
|
|
|
|
function caseInput() {
|
|
const c = economicCase();
|
|
const source = structuredClone(c.b.economicCredits.rows[0]);
|
|
Object.assign(source, {
|
|
incomeIncluded: 'no',
|
|
incomeReference: 'SYNTHETIC not yet included',
|
|
grossUpIncluded: '0',
|
|
grossUpReference: 'SYNTHETIC no gross-up yet',
|
|
});
|
|
return {
|
|
...c,
|
|
normal: normalBook(c.d),
|
|
inclusion: {
|
|
source,
|
|
profitAlreadyIncluded: '0',
|
|
creditAlreadyIncluded: '0',
|
|
reference:
|
|
'SYNTHETIC QA complete reconciliation before this map, not a real accounting assertion',
|
|
},
|
|
};
|
|
}
|
|
void test('economic inclusion adds only the missing profits and derived60percent to current L6', () => {
|
|
const c = caseInput(),
|
|
old = structuredClone(c.normal.result);
|
|
const b = prepareEconomicInclusion(c.normal, c.inclusion),
|
|
m = calculateNormal(c.d, b);
|
|
assert.deepEqual(m.economicInclusions.pending, []);
|
|
assert.deepEqual(m.economicInclusions.net, {
|
|
numerator: '112',
|
|
denominator: '1',
|
|
});
|
|
assert.deepEqual(m.taxableProfit, { numerator: '6812', denominator: '1' });
|
|
assert.deepEqual(m.taxableBase, { numerator: '4512', denominator: '1' });
|
|
assert.deepEqual(m.colecta, { numerator: '36096', denominator: '25' });
|
|
assert.deepEqual(c.normal.result, old);
|
|
});
|
|
void test('economic inclusion is repeatable and replaces the same parcel instead of accumulating corrections', () => {
|
|
const c = caseInput(),
|
|
once = prepareEconomicInclusion(c.normal, c.inclusion);
|
|
assert.deepEqual(prepareEconomicInclusion(once, c.inclusion), once);
|
|
const alias = structuredClone(c.inclusion);
|
|
alias.source.distributionDocument =
|
|
' ' + alias.source.distributionDocument.toLowerCase() + ' ';
|
|
assert.equal(
|
|
prepareEconomicInclusion(once, alias).economicInclusions.rows.length,
|
|
1,
|
|
);
|
|
const changed = structuredClone(c.inclusion);
|
|
changed.source.income = '200';
|
|
const next = prepareEconomicInclusion(once, changed);
|
|
assert.equal(next.economicInclusions.rows.length, 1);
|
|
assert.equal(next.profit.topics.incomeCorrections.amount, '212.00');
|
|
assert.deepEqual(calculateNormal(c.d, next).taxableProfit, {
|
|
numerator: '6912',
|
|
denominator: '1',
|
|
});
|
|
});
|
|
void test('economic inclusion does not add amounts already considered and can correct documented over-inclusion', () => {
|
|
const c = economicCase(),
|
|
source = c.b.economicCredits.rows[0],
|
|
b = normalBook(c.d);
|
|
const row = {
|
|
source,
|
|
profitAlreadyIncluded: '100',
|
|
creditAlreadyIncluded: '12',
|
|
reference: 'SYNTHETIC already included once',
|
|
};
|
|
assert.deepEqual(
|
|
calculateNormal(c.d, prepareEconomicInclusion(b, row)).colecta,
|
|
b.result.model.colecta,
|
|
);
|
|
const correction = structuredClone(row);
|
|
correction.profitAlreadyIncluded = '150';
|
|
correction.creditAlreadyIncluded = '20';
|
|
correction.source.grossUpIncluded = '20';
|
|
const m = calculateNormal(c.d, prepareEconomicInclusion(b, correction));
|
|
assert.deepEqual(m.economicInclusions.net, {
|
|
numerator: '-58',
|
|
denominator: '1',
|
|
});
|
|
assert.deepEqual(m.taxableProfit, { numerator: '6642', denominator: '1' });
|
|
});
|
|
void test('economic inclusion rejects contradictory prior inclusion, duplicate origins, different taxpayers and invalid underlying amounts', () => {
|
|
const c = caseInput();
|
|
const contradiction = structuredClone(c.inclusion);
|
|
contradiction.source.incomeIncluded = 'yes';
|
|
assert.throws(
|
|
() => prepareEconomicInclusion(c.normal, contradiction),
|
|
/declara os lucros/,
|
|
);
|
|
const duplicate = calculateEconomicInclusions(
|
|
{
|
|
version: 1,
|
|
rows: [
|
|
c.inclusion,
|
|
{
|
|
...c.inclusion,
|
|
source: { ...c.inclusion.source, id: 'another-id' },
|
|
},
|
|
],
|
|
},
|
|
c.normal.base.subjectNuit,
|
|
'2026',
|
|
);
|
|
assert.ok(duplicate.pending.some((e) => e.includes('repetida')));
|
|
const other = structuredClone(c.inclusion);
|
|
other.source.subjectNuit = '987654321';
|
|
assert.throws(() => prepareEconomicInclusion(c.normal, other));
|
|
const partial = structuredClone(c.inclusion);
|
|
partial.source.taxAmount = '-20.01';
|
|
partial.source.proofAmount = '-20.01';
|
|
assert.throws(() => prepareEconomicInclusion(c.normal, partial));
|
|
});
|
|
void test('economic inclusion keeps recovery, previous result and reports while making the old L8 origin stale', () => {
|
|
const c = caseInput(),
|
|
previous = structuredClone(c.normal.result);
|
|
const b = recordNormal(
|
|
c.d,
|
|
prepareEconomicInclusion(c.normal, c.inclusion),
|
|
'2026-11-10T15:00:00+02:00',
|
|
);
|
|
const d = JSON.parse(
|
|
JSON.stringify({ ...c.d, modelo_a_snapshot: saveNormalBook(c.d, b) }),
|
|
);
|
|
const recovered = normalBook(d);
|
|
assert.equal(normalCurrent(d, recovered), true);
|
|
assert.deepEqual(recovered.history.at(-1), previous);
|
|
assert.deepEqual(
|
|
calculateNormal(d, recovered).economicInclusions,
|
|
recovered.result.model.economicInclusions,
|
|
);
|
|
assert.match(normalHtml(d), /IRPC-economic-inclusion\/1/);
|
|
assert.match(
|
|
JSON.stringify(
|
|
createProjectDossierReport(d, {
|
|
selectedSections: new Set(['finance']),
|
|
generatedAt: '2026-11-10T15:00:00+02:00',
|
|
}),
|
|
),
|
|
/IRPC-economic-inclusion\/1/,
|
|
);
|
|
assert.equal(calculateAnnual(d, c.b).arithmeticBalance, null);
|
|
});
|
|
|
|
void test('special inclusion reconciles the whole taxable partilha once but keeps only its eligible component in the credit', () => {
|
|
const c = caseInput();
|
|
Object.assign(c.inclusion.source, {
|
|
kind: 'liquidation',
|
|
income: '150',
|
|
liquidation: {
|
|
attributed: '200',
|
|
paidInCapital: '100',
|
|
reference:
|
|
'SYNTHETIC capital component100 and gain50 included in taxable income150',
|
|
},
|
|
});
|
|
const b = prepareEconomicInclusion(c.normal, c.inclusion),
|
|
m = calculateNormal(c.d, b);
|
|
assert.deepEqual(m.economicInclusions.net, {
|
|
numerator: '162',
|
|
denominator: '1',
|
|
});
|
|
assert.deepEqual(m.taxableBase, { numerator: '4562', denominator: '1' });
|
|
assert.match(m.economicInclusions.effects[0].reason, /mais-valia 50.00/);
|
|
assert.deepEqual(prepareEconomicInclusion(b, c.inclusion), b);
|
|
const already = structuredClone(c.inclusion);
|
|
Object.assign(already, {
|
|
profitAlreadyIncluded: '150',
|
|
creditAlreadyIncluded: '12',
|
|
});
|
|
Object.assign(already.source, {
|
|
incomeIncluded: 'yes',
|
|
grossUpIncluded: '12',
|
|
});
|
|
assert.deepEqual(
|
|
calculateNormal(c.d, prepareEconomicInclusion(c.normal, already))
|
|
.colecta,
|
|
c.normal.result.model.colecta,
|
|
);
|
|
});
|
|
void test('association inclusion requires its specific evidence and does not infer effective taxation', () => {
|
|
const c = caseInput();
|
|
Object.assign(c.inclusion.source, {
|
|
kind: 'association',
|
|
association: {
|
|
kind: 'participation',
|
|
effectivelyTaxed: '',
|
|
reference: 'SYNTHETIC contract',
|
|
},
|
|
});
|
|
assert.throws(
|
|
() => prepareEconomicInclusion(c.normal, c.inclusion),
|
|
/efectivamente tributados/,
|
|
);
|
|
c.inclusion.source.association.effectivelyTaxed = 'yes';
|
|
assert.deepEqual(
|
|
calculateNormal(c.d, prepareEconomicInclusion(c.normal, c.inclusion))
|
|
.economicInclusions.net,
|
|
{ numerator: '112', denominator: '1' },
|
|
);
|
|
});
|
|
|
|
void test('fractional-cent economic inclusion keeps exact base and collection and does not accumulate on repeat', () => {
|
|
const c = caseInput();
|
|
c.inclusion.source.taxAmount = c.inclusion.source.proofAmount = '20.01';
|
|
const b = prepareEconomicInclusion(c.normal, c.inclusion),
|
|
m = calculateNormal(c.d, b);
|
|
assert.equal(b.profit.topics.incomeCorrections.amount, '112.006');
|
|
assert.deepEqual(m.economicInclusions.net, {
|
|
numerator: '56003',
|
|
denominator: '500',
|
|
});
|
|
assert.deepEqual(m.taxableBase, {
|
|
numerator: '2256003',
|
|
denominator: '500',
|
|
});
|
|
assert.deepEqual(m.colecta, { numerator: '4512006', denominator: '3125' });
|
|
assert.deepEqual(prepareEconomicInclusion(b, c.inclusion), b);
|
|
assert.match(
|
|
m.economicInclusions.effects[1].reason,
|
|
/IRPC-economic-inclusion-exact\/1/,
|
|
);
|
|
});
|
|
void test('fractional economic reconciliation cannot treat0.006 as zero or accept a truncated topic amount', () => {
|
|
const c = caseInput();
|
|
Object.assign(c.inclusion.source, {
|
|
income: '1',
|
|
incomeIncluded: 'yes',
|
|
taxAmount: '0.01',
|
|
proofAmount: '0.01',
|
|
attributionReference:
|
|
'SYNTHETIC tax0.01 actually corresponding to included income1',
|
|
});
|
|
c.inclusion.profitAlreadyIncluded = '1';
|
|
const b = prepareEconomicInclusion(c.normal, c.inclusion);
|
|
assert.equal(b.profit.topics.incomeCorrections.amount, '0.006');
|
|
assert.deepEqual(calculateNormal(c.d, b).economicInclusions.net, {
|
|
numerator: '3',
|
|
denominator: '500',
|
|
});
|
|
b.profit.topics.incomeCorrections.amount = '0.00';
|
|
assert.equal(calculateNormal(c.d, b).taxableProfit, null);
|
|
});
|
|
void test('documented prior rational additions and repeating fractions recover without decimal rounding', () => {
|
|
const c = caseInput();
|
|
c.inclusion.source.taxAmount = c.inclusion.source.proofAmount = '20.01';
|
|
c.inclusion.creditAlreadyIncluded = '1/3';
|
|
c.inclusion.source.grossUpIncluded = '1/3';
|
|
c.inclusion.source.grossUpReference =
|
|
'SYNTHETIC previous exact1/3 already added to fiscal base';
|
|
const b = prepareEconomicInclusion(c.normal, c.inclusion);
|
|
assert.equal(b.profit.topics.incomeCorrections.amount, '167509/1500');
|
|
const d = {
|
|
...c.d,
|
|
modelo_a_snapshot: saveNormalBook(
|
|
c.d,
|
|
recordNormal(c.d, b, '2026-11-10T18:10:00+02:00'),
|
|
),
|
|
},
|
|
back = normalBook(d);
|
|
assert.equal(normalCurrent(d, back), true);
|
|
assert.deepEqual(
|
|
calculateNormal(d, back).economicInclusions,
|
|
back.result.model.economicInclusions,
|
|
);
|
|
assert.match(normalHtml(d), /IRPC-economic-inclusion-exact\/1/);
|
|
});
|