import {ispcEligibilityBook,saveIspcEligibilityBook}from '../../resources/js/lib/ispc-eligibility.ts'; import test from 'node:test';import assert from 'node:assert/strict';import fs from 'node:fs'; import {ispcResidualBook,saveIspcResidualBook,recordIspcResidual,ispcResidualCurrent,ispcResidualReportRows,ispcFormalPreparationHtml}from '../../resources/js/lib/ispc-residuals.ts'; import {ispcWithholdingBook,saveIspcWithholdingBook}from '../../resources/js/lib/ispc-withholding.ts'; import {createProjectDossierReport}from '../../resources/js/lib/project-dossier-report.ts'; const seed=JSON.parse(fs.readFileSync(new URL('./fixtures/ispc-quarter-preserved.json',import.meta.url),'utf8')); function own(p={}){const d=structuredClone(seed),b=ispcResidualBook(d,'occasional');b.input={...b.input,personType:'singular',currency:'MZN',origin:'projected',operationDate:'2026-06-15',quarter:'2',noHabitual:'yes',territory:'yes',sporadic:'yes',activity:'agriculture',reference:'SYNTHETIC QA colheita não reiterada',amount:'100000',allQuarterOperations:'yes',priorYearTurnover:'0',priorYearRef:'SYNTHETIC QA2025zeroexpresso',organizedRequired:'no',option:'preparation',optionRef:'',optionDate:'',settlement:'self',annual2026:'100000',annualOrigin:'forecast',annualRef:'SYNTHETIC QA2026',priorInYear:'0',...p};return{d,b};} function acq(p={},wpatch={}){const d=structuredClone(seed),w=ispcWithholdingBook(d);w.input={...w.input,applicable:'yes',quarter:'2',base:'200000',priorAnnualPurchases:'2400000',naturalOccasional:'yes',unregistered:'yes',related:'yes',activity:'agriculture',reference:'SYNTHETIC QA aquisição/ordem e acumulado',...wpatch};d.modelo_a_snapshot=saveIspcWithholdingBook(d,w);const b=ispcResidualBook(d,'acquisitions');b.input={...b.input,...p};return{d,b};} const calc=({d,b})=>recordIspcResidual(d,b,'2026-10-25T15:40:00Z');const number=x=>x?Number(x.numerator)/Number(x.denominator):null; test('positive ownoccasional agricultural isolated8h route;self3/4/5 andnoautomaticIRPS20',()=>{for(const[annual,n]of [['100000',3],['2000000',4],['3000000',5]]){const r=calc(own({annual2026:annual})).result;assert.equal(r.status,'calculated',r.missing.join(';'));assert.equal(number(r.amounts.tax),1000*n);assert.match(r.source,/8\(3h,4\)/);assert.equal(r.details.IRPS.includes('Não se infere'),true);}}); test('unknown notnonapplicable;known exclusions andactivityfamilyownscope',()=>{assert.equal(calc(own({personType:''})).result.status,'indeterminate');for(const p of [{personType:'collective'},{noHabitual:'no'},{sporadic:'no'},{territory:'no'},{activity:'other'}])assert.equal(calc(own(p)).result.status,'not_applicable');for(const p of [{territory:''},{currency:'USD'},{quarter:'3'},{reference:''},{priorYearTurnover:''},{organizedRequired:''}])assert.equal(calc(own(p)).result.status,'indeterminate');}); test('ownminimum500withoutlosingdeclaration;zeroexplicit and4mexcessnotreused',()=>{let r=calc(own({amount:'1000'})).result;assert.equal(number(r.amounts.tax),30);assert.equal(number(r.amounts.payment),0);assert.match(r.details.declaration,/Mantida/);r=calc(own({amount:'0'})).result;assert.equal(number(r.amounts.tax),0);assert.equal(calc(own({amount:''})).result.status,'indeterminate');r=calc(own({amount:'200000',priorInYear:'3900000',annual2026:'4100000'})).result;assert.equal(number(r.amounts.ordinary),100000);assert.equal(number(r.amounts.excess),100000);assert.equal(number(r.amounts.tax),25000);}); test('documentedliberatory5meansno secondselftax;smallwithholdingnotminimum500;divergenceunknown',()=>{const p={settlement:'withheld',origin:'effective',buyerIspc:'yes',unregistered:'yes',buyerAnnualPurchases:'200000',withheldActual:'5000',withheldRef:'SYNTHETIC QA recibo5'};let r=calc(own(p)).result;assert.equal(r.status,'settled_by_withholding',r.missing.join(';'));assert.equal(number(r.amounts.withheld),5000);assert.equal(r.amounts.payment,undefined);assert.match(r.reason,/não somar nova liquidação/);r=calc(own({...p,amount:'100',withheldActual:'5'})).result;assert.equal(r.status,'settled_by_withholding');assert.equal(number(r.amounts.tax),5);assert.equal(calc(own({...p,withheldActual:'4000'})).result.status,'indeterminate');assert.equal(calc(own({...p,buyerAnnualPurchases:'2500000.000001'})).result.status,'indeterminate');}); test('selfeffective requiresapplicableoption;forecastcannot masqueradeasactual;nonoptionnoISPC',()=>{assert.equal(calc(own({origin:'effective'})).result.status,'indeterminate');assert.equal(calc(own({option:'not_opted'})).result.status,'not_applicable');const r=calc(own({origin:'effective',operationDate:'2026-12-31',quarter:'4',option:'opted',optionRef:'QA opção',optionDate:'2026-01-01',annualOrigin:'closed_year'})).result;assert.equal(r.status,'calculated',r.missing.join(';'));assert.equal(calc(own({origin:'effective',option:'opted',optionRef:'QA',optionDate:'2026-07-01'})).result.status,'indeterminate');}); test('above2.5m splits100kcovered/100kexcess;5kknownbuttotalnullwithunknownroute',()=>{const r=calc(acq()).result;assert.equal(r.status,'partial');assert.equal(number(r.amounts.covered),100000);assert.equal(number(r.amounts.coveredTax),5000);assert.equal(number(r.amounts.excess),100000);assert.equal(r.amounts.excessTax,null);assert.equal(r.amounts.total,null);}); test('positiveIRPS57k20onidentifiedgrossact—separatefromISPCexcess20andownbuyerpayment',()=>{const p={route:'irps_isolated',noIspcOnExcess:'yes',isolatedAct:'yes',incomeInMoz:'yes',grossExcess:'100000',grossRef:'SYNTHETIC QA base ilíquida',reference:'SYNTHETIC QA8h/57k sem opção5'};const r=calc(acq(p)).result;assert.equal(r.status,'calculated',r.missing.join(';'));assert.equal(number(r.amounts.excessTax),20000);assert.equal(number(r.amounts.total),25000);assert.match(r.reason,/não são crédito/);for(const patch of [{grossExcess:''},{grossExcess:'80000'},{noIspcOnExcess:''},{isolatedAct:''},{incomeInMoz:'no'},{reference:''}]){const r=calc(acq({...p,...patch})).result;assert.equal(r.status,'partial');assert.equal(r.amounts.total,null);}}); test('supplierISPCnotautomaticallyIRPS;crossingexactboundaryandprioroverlimit;noimplicit5onexcess',()=>{let r=calc(acq({route:'ispc_supplier',supplierOptionRef:'QA opção aplicável'})).result;assert.equal(r.status,'partial');assert.equal(r.amounts.excessTax,null);assert.match(r.reason,/art5impede/);r=calc(acq({}, {base:'100000'})).result;assert.equal(r.status,'not_applicable');assert.equal(number(r.amounts.excess),0);r=calc(acq({}, {priorAnnualPurchases:'2500001'})).result;assert.equal(number(r.amounts.covered),0);assert.equal(number(r.amounts.coveredTax),0);assert.equal(number(r.amounts.excess),200000);}); test('newbooks preservehabitualandL3exactly;dependenciesstale withoutrewritingfrozenresults',()=>{let{d,b}=acq();const old=JSON.parse(d.modelo_a_snapshot);b=calc({d,b});d.modelo_a_snapshot=saveIspcResidualBook(d,b);for(const[k,v]of Object.entries(old))assert.deepEqual(JSON.parse(d.modelo_a_snapshot)[k],v);assert.equal(ispcResidualCurrent(d,b),true);const w=ispcWithholdingBook(d);w.input.base='300000';d.modelo_a_snapshot=saveIspcWithholdingBook(d,w);assert.equal(ispcResidualCurrent(d,b),false);assert.equal(number(b.result.amounts.excess),100000);const next=recordIspcResidual(d,b);assert.equal(next.history.length,1);assert.equal(number(next.result.amounts.excess),200000);assert.equal(number(next.history[0].amounts.excess),100000);}); test('formalBGeneral mappingfromexistingcurrentquarterwithoutrecalculation;monthnotinferred;old30notused',()=>{const d=structuredClone(seed),b=ispcResidualBook(d,'formalities'),before=d.modelo_a_snapshot;const result=recordIspcResidual(d,b);assert.equal(result.result.status,'partial');assert.equal(number(result.result.amounts.tax),24000);assert.equal(number(result.result.amounts.payment),24000);assert.match(result.result.details.formPeriod,/Indeterminado/);assert.equal(result.result.details.paymentMonth,'Julho2026');assert.equal(result.input.formMonth,'');d.modelo_a_snapshot=saveIspcResidualBook(d,result);const html=ispcFormalPreparationHtml(d);assert.match(html,/24000.00/);assert.match(html,/Quadro8/);assert.match(html,/Quadro10/);assert.match(html,/não é formulário oficial/);assert.deepEqual(JSON.parse(d.modelo_a_snapshot).ispcQuarters,JSON.parse(before).ispcQuarters);}); test('formalinputsguardedandexternalactsdeclaredonly;signed/officialareasnotautofilled;HTMLescaped',()=>{let d=structuredClone(seed),b=ispcResidualBook(d,'formalities');b.input={...b.input,name:'QA ',nuit:'123456789',fiscalArea:'QAUGC',address:'QAendereço',formMonth:'06',formYear:'2026',formPeriodRef:'SYNTHETIC QA correspondência período',interestSituation:'none',interestRef:'SYNTHETIC QA sem juros'};b=recordIspcResidual(d,b);assert.equal(b.result.status,'calculated',b.result.missing.join(';'));d.modelo_a_snapshot=saveIspcResidualBook(d,b);const html=ispcFormalPreparationHtml(d);assert.ok(html.includes('<script>'));assert.ok(!html.includes('