Files
Investidor-V2/tests/frontend/ispc-quarter.test.mjs
T

304 lines
10 KiB
JavaScript

import { createProjectDossierReport } from '../../resources/js/lib/project-dossier-report.ts';
import test from 'node:test';
import assert from 'node:assert/strict';
import fs from 'node:fs';
import {
newIspcEligibilityInput,
recordIspcEligibility,
saveIspcEligibilityBook,
} from '../../resources/js/lib/ispc-eligibility.ts';
import {
newIspcQuarterInput,
ispcQuarterBook,
recordIspcQuarter,
saveIspcQuarterBook,
ispcQuarterCurrent,
ispcQuarterReportRows,
} from '../../resources/js/lib/ispc-quarter.ts';
const seed = JSON.parse(
fs.readFileSync(
new URL('./fixtures/iva-l3e-preserved.json', import.meta.url),
'utf8',
),
);
function fixture(ep = {}, qp = {}) {
let d = {
...structuredClone(seed),
context_opportunity: 'opportunity:375',
project_title: 'SYNTHETIC QA — L4 ISPC',
fiscal_component: 'ispc',
currency: 'MZN',
person_type: 'collective',
fiscal_activity: 'SYNTHETIC QA canalização',
fiscal_establishments: '1',
};
const input = {
...newIspcEligibilityInput(d),
activities: ['services12'],
territory: 'yes',
basis: 'previous_year',
referenceYear: '2025',
annualReference: '1000000',
annualReferenceRef: 'SYNTHETIC QA acesso2025',
organizedRequired: 'no',
sharesInIspc: 'no',
sharesAnonymous: 'no',
otherActivities: 'no',
generalRegimeChosen: 'no',
unlistedServices: 'no',
...ep,
};
const e = recordIspcEligibility(
d,
{ version: 1, input },
'2026-10-25T12:00:00Z',
);
d.modelo_a_snapshot = saveIspcEligibilityBook(d, e);
const b = {
version: 1,
input: {
...newIspcQuarterInput(),
sales: ['100000', '', '', ''],
salesRefs: ['SYNTHETIC QA T1', '', '', ''],
coverage: 'all_taxpayer_activity',
...qp,
},
};
return { d, b };
}
const calc = (ep = {}, qp = {}) => {
const { d, b } = fixture(ep, qp);
return recordIspcQuarter(d, b, '2026-10-25T12:01:00Z').result;
};
const decimal = (x) => Number(x.numerator) / Number(x.denominator);
void test('quarterly services12 andliberal15;highest mixed rate applied to entire quarterly base;no costs or VAT deduction', () => {
assert.equal(decimal(calc().tax), 12000);
assert.equal(
decimal(calc({ activities: ['commerce', 'services12'] }).tax),
12000,
);
assert.equal(
decimal(
calc({
activities: ['services12', 'liberal15'],
liberalDaysSameEntity: '100',
liberalClientRef: 'QA',
}).tax,
),
15000,
);
assert.equal(calc().projected, true);
});
void test('annual goods tiers applied to quarter without splitting annual limits or using previous-year accessvolume', () => {
for (const [annual, rate] of [
['1000000', 3],
['1000000.000001', 4],
['2500000', 4],
['2500000.000001', 5],
['4000000', 5],
]) {
const r = calc(
{ activities: ['commerce'] },
{
annualBandVolume: annual,
annualBandOrigin: 'forecast',
annualBandRef: 'QAannual2026',
},
);
assert.equal(r.status, 'calculated', r.reason);
assert.equal(r.rate, rate);
assert.equal(decimal(r.tax), 1000 * rate);
}
assert.equal(calc({ activities: ['commerce'] }).status, 'indeterminate');
});
void test('20percent only newly crossed excess;prior quarters prevent repeating same excess;no threshold divided byfour', () => {
const q = {
quarter: '3',
sales: ['2000000', '1900000', '200000', ''],
salesRefs: ['QA1', 'QA2', 'QA3', ''],
};
const r = calc({}, q);
assert.equal(decimal(r.ordinary), 100000);
assert.equal(decimal(r.excess), 100000);
assert.equal(decimal(r.tax), 32000);
const next = calc(
{},
{
...q,
quarter: '4',
sales: ['2000000', '1900000', '200000', '100000'],
salesRefs: ['QA1', 'QA2', 'QA3', 'QA4'],
},
);
assert.equal(decimal(next.ordinary), 0);
assert.equal(decimal(next.tax), 20000);
});
void test('minimum500:below no payment,declaration stays;exact500 payable;explicitzero distinct from missing', () => {
let r = calc(
{
activities: ['liberal15'],
liberalDaysSameEntity: '100',
liberalClientRef: 'QA',
},
{ sales: ['3000', '', '', ''] },
);
assert.equal(decimal(r.tax), 450);
assert.equal(decimal(r.payment), 0);
assert.equal(r.declaration, true);
r = calc(
{ activities: ['commerce'] },
{
sales: ['16666.666667', '', '', ''],
annualBandVolume: '1000000',
annualBandOrigin: 'forecast',
annualBandRef: 'QA',
},
);
assert.ok(decimal(r.payment) > 500);
r = calc({}, { sales: ['0', '', '', ''] });
assert.equal(r.status, 'calculated');
assert.equal(decimal(r.tax), 0);
assert.equal(calc({}, { sales: ['', '', '', ''] }).status, 'indeterminate');
const exact = calc(
{ activities: ['commerce'] },
{
sales: ['12500', '', '', ''],
annualBandVolume: '2000000',
annualBandOrigin: 'forecast',
annualBandRef: 'QA',
},
);
assert.equal(decimal(exact.payment), 500);
});
void test('effective tax needs recorded option;notopted and incompatible are notapplicable;preparation remains scenario only', () => {
assert.equal(calc({ origin: 'effective' }).status, 'indeterminate');
assert.equal(calc({ option: 'not_opted' }).status, 'not_applicable');
assert.equal(calc({ organizedRequired: 'yes' }).status, 'not_applicable');
const r = calc({
origin: 'effective',
option: 'opted',
optionDate: '2026-01-01',
optionReference: 'QA opção',
});
assert.equal(r.status, 'calculated');
assert.equal(r.projected, false);
assert.equal(
calc({
origin: 'effective',
assessmentDate: '2026-10-25',
option: 'opted',
optionDate: '2026-10-01',
optionReference: 'QA opção',
}).status,
'indeterminate',
);
});
void test('missing prior quarter,scope,year,source andannual mismatch do not produce zero', () => {
for (const p of [
{ year: '2025' },
{ quarter: '5' },
{ coverage: '' },
{ salesRefs: ['', '', '', ''] },
{ quarter: '2', sales: ['', '1000', '', ''] },
])
assert.equal(calc({}, p).status, 'indeterminate');
assert.equal(
calc(
{ activities: ['commerce'] },
{
annualBandVolume: '99999',
annualBandOrigin: 'forecast',
annualBandRef: 'QA',
},
).status,
'indeterminate',
);
});
void test('closed-yearannual mustequalallfourquarters;quarter amount is not annual base', () => {
const q = {
quarter: '4',
sales: ['100000', '200000', '300000', '400000'],
salesRefs: ['QA1', 'QA2', 'QA3', 'QA4'],
annualBandVolume: '1000000',
annualBandOrigin: 'closed_year',
annualBandRef: 'QA2026',
};
assert.equal(decimal(calc({ activities: ['commerce'] }, q).tax), 12000);
assert.equal(
calc(
{ activities: ['commerce'] },
{ ...q, annualBandVolume: '1000001' },
).status,
'indeterminate',
);
assert.equal(
decimal(calc({ activities: ['commerce'] }, { ...q, quarter: '1' }).tax),
3000,
);
});
void test('eligibility edits invalidate dependent calculation;save recovery freezesinput andretainsotherbooks/history', () => {
let { d, b } = fixture();
const old = JSON.parse(d.modelo_a_snapshot);
b = recordIspcQuarter(d, b);
d.modelo_a_snapshot = saveIspcQuarterBook(d, b);
assert.deepEqual(JSON.parse(d.modelo_a_snapshot).books, old.books);
assert.equal(ispcQuarterCurrent(d, ispcQuarterBook(d)), true);
const recovered = ispcQuarterBook(JSON.parse(JSON.stringify(d)));
recovered.input.sales[0] = '200000';
assert.equal(ispcQuarterCurrent(d, recovered), false);
assert.equal(decimal(recovered.result.tax), 12000);
const next = recordIspcQuarter(d, recovered);
assert.equal(decimal(next.result.tax), 24000);
assert.equal(next.history.length, 1);
assert.equal(decimal(next.history[0].tax), 12000);
const s = JSON.parse(d.modelo_a_snapshot);
s.ispcEligibility['opportunity:375'].input.activityDescription = 'edited';
d.modelo_a_snapshot = JSON.stringify(s);
assert.equal(recordIspcQuarter(d, next).result.status, 'indeterminate');
});
void test('invalidstoredmaps andambiguouscontext remainpreservederrors', () => {
let { d, b } = fixture();
const s = JSON.parse(d.modelo_a_snapshot);
s.ispcQuarters = [];
assert.throws(() =>
ispcQuarterBook({ ...d, modelo_a_snapshot: JSON.stringify(s) }),
);
assert.throws(() =>
saveIspcQuarterBook(d, { ...b, input: { ...b.input, sales: ['1'] } }),
);
});
void test('export completeeligibilityoptioncalculationfixture andreport from recovereddata', () => {
let { d, b } = fixture(
{
origin: 'effective',
assessmentDate: '2026-10-25',
option: 'opted',
optionDate: '2026-01-01',
optionReference: 'SYNTHETIC QA opção ISPC2026',
},
{
quarter: '2',
sales: ['100000', '200000', '', ''],
salesRefs: ['SYNTHETIC QA T1', 'SYNTHETIC QA T2', '', ''],
},
);
b = recordIspcQuarter(d, b, '2026-10-25T12:01:00Z');
d.modelo_a_snapshot = saveIspcQuarterBook(d, b);
const recovered = JSON.parse(JSON.stringify(d));
assert.equal(decimal(ispcQuarterBook(recovered).result.tax), 24000);
assert.equal(ispcQuarterBook(recovered).result.projected, false);
assert.match(JSON.stringify(ispcQuarterReportRows(recovered)), /24000.00/);
const report = createProjectDossierReport(recovered, {
selectedSections: new Set(['finance']),
version: 'QA ISPC',
generatedAt: '2026-10-25T12:02:00Z',
});
assert.match(JSON.stringify(report.sections), /24000.00/);
assert.match(JSON.stringify(report.sections), /opção ISPC2026/);
if (process.env.L4_ISPC_OUTPUT)
fs.writeFileSync(
process.env.L4_ISPC_OUTPUT,
JSON.stringify(recovered, null, 2),
);
});