Files
Investidor-V2/tests/frontend/iva-reduced-bases.test.mjs
T

29 lines
5.8 KiB
JavaScript

import test from 'node:test';
import assert from 'node:assert/strict';
import fs from 'node:fs';
import {newReducedBase,switchReducedTreatment,reducedBaseConditions,ownReducedConditions,reducedBaseTreatments,publicWorkCategories,evaluateReducedBase,recordReducedBases,saveReducedBaseBook,reducedBaseBook,reducedBaseCurrent,reducedBaseReportRows} from '../../resources/js/lib/iva-reduced-bases.ts';
const frozen=JSON.parse(fs.readFileSync('tests/frontend/fixtures/iva-g7-reduced-preserved.json','utf8'));const draft={...frozen,currency:'MZN',context_opportunity:'opportunity:351',project_title:'SYNTHETIC QA — G7 bases reduzidas / Manica'};
function row(t){const rule=reducedBaseTreatments.find(x=>x.id===t);return{...newReducedBase(t,'MZN'),treatment:t,description:'SYNTHETIC QA '+rule.branch,period:'2026-12',origin:'projected',operationDate:'2026-12-12',documentRef:'SYNTHETIC QA documento/pressuposto',documentDate:'2026-12-12',priceScope:'SYNTHETIC QA objecto/operação/local/período',priceRef:'SYNTHETIC QA preço/taxa aplicável',priceFrom:'2026-01-01',priceTo:'2026-12-31',consideration:'1000.25',compositionRef:'SYNTHETIC QA total antes redução,semIVA,15(1)/(5)/(6)',evidence:'SYNTHETIC QA pressupostos expressos',projectRef:'SYNTHETIC QA projecto público/contrato',workCategory:'roads',conditions:Object.fromEntries([...reducedBaseConditions,...ownReducedConditions(t)].map(([key])=>[key,'yes']))};}
const expected=['620.155','850.2125','400.10','750.1875'];
for(const [i,rule] of reducedBaseTreatments.entries())test(rule.branch+' ownconditions,exact base and separate deduction proportion',()=>{
const r=row(rule.id),result=evaluateReducedBase(r,'MZN');assert.equal(result.status,'determined');assert.equal(result.baseAmount,expected[i]);assert.equal(result.deductionProportion,rule.percent+'%');assert.equal(result.vat,null);assert.equal(result.rate,null);
for(const [key] of [...reducedBaseConditions,...ownReducedConditions(rule.id)]){const missing=structuredClone(r);delete missing.conditions[key];assert.equal(evaluateReducedBase(missing,'MZN').status,'indeterminate');missing.conditions[key]='no';assert.equal(evaluateReducedBase(missing,'MZN').status,'not_applicable');assert.equal(evaluateReducedBase(missing,'MZN').baseAmount,null);assert.equal(evaluateReducedBase(missing,'MZN').deductionProportion,null);}
for(const field of ['description','documentRef','priceScope','compositionRef','evidence','consideration'])assert.equal(evaluateReducedBase({...r,[field]:''},'MZN').status,'indeterminate',field);
for(const patch of [{operationDate:'2026-11-12'},{documentDate:'2026-02-30'},{period:'2025-12'},{currency:'USD'},{consideration:'1,5'},{consideration:'-1'},{consideration:'1e3'}])assert.equal(evaluateReducedBase({...r,...patch},'MZN').status,'indeterminate');assert.equal(evaluateReducedBase(r,'USD').status,'indeterminate');
assert.equal(evaluateReducedBase({...r,consideration:'0'},'MZN').baseAmount,'0.00');
if(rule.id==='public_works'){assert.equal(evaluateReducedBase({...r,priceRef:'',priceFrom:'',priceTo:''},'MZN').baseAmount,expected[i]);for(const c of publicWorkCategories)assert.equal(evaluateReducedBase({...r,workCategory:c.id},'MZN').status,'determined');assert.equal(evaluateReducedBase({...r,workCategory:'private_work'},'MZN').status,'indeterminate');assert.equal(evaluateReducedBase({...r,projectRef:''},'MZN').status,'indeterminate');assert.match(result.reason,/base40%/);}
else{for(const patch of [{priceRef:''},{priceFrom:''},{priceFrom:'2027-01-01'},{priceTo:'2026-11-30'},{priceTo:'2025-12-31'}])assert.equal(evaluateReducedBase({...r,...patch},'MZN').status,'indeterminate');assert.equal(evaluateReducedBase({...r,priceTo:''},'MZN').status,'determined');}
});
test('Exactfraction retained,no 60percent works base,no duplicate reduction and no automatic deduction',()=>{
assert.equal(evaluateReducedBase({...row('regulated_energy'),consideration:'0.000001'},'MZN').baseAmount,'0.00000062');assert.equal(evaluateReducedBase({...row('public_works'),consideration:'0.000001'},'MZN').baseAmount,'0.0000004');
assert.equal(evaluateReducedBase({...row('public_water'),consideration:'999999999999999.999999'},'MZN').baseAmount,'749999999999999.99999925');
const reduced=row('public_works');reduced.conditions.fullNetInvoice='no';assert.equal(evaluateReducedBase(reduced,'MZN').baseAmount,null);
const changed=switchReducedTreatment(row('regulated_energy'),'public_works');assert.equal(changed.priceRef,row('regulated_energy').priceRef);assert.equal(changed.projectRef,row('regulated_energy').projectRef);assert.equal(changed.conditions.publicWorks,undefined);assert.equal(evaluateReducedBase(changed,'MZN').status,'indeterminate');
});
test('Four branches save/recover/history/report and all previous books are preserved',()=>{
const rows=reducedBaseTreatments.map(t=>row(t.id));let book=recordReducedBases(draft,{rows});book=recordReducedBases(draft,book);assert.equal(book.history.length,1);assert.notEqual(book.result.inputs,book.rows);
const next={...draft,modelo_a_snapshot:saveReducedBaseBook(draft,book)};assert.deepEqual(reducedBaseBook(next),book);assert.ok(reducedBaseCurrent(next,book));assert.equal(reducedBaseCurrent({...next,currency:'USD'},book),false);assert.equal(reducedBaseCurrent({...next,context_opportunity:'other'},book),false);assert.equal(reducedBaseReportRows(next).length,4);for(const t of reducedBaseTreatments)assert.ok(reducedBaseReportRows(next).some(r=>r[1].includes(t.branch)));
const store=JSON.parse(next.modelo_a_snapshot);delete store.regulatedReducedBases;assert.deepEqual(store,JSON.parse(frozen.modelo_a_snapshot));assert.throws(()=>recordReducedBases(next,{rows:[rows[0],rows[0]]}));assert.throws(()=>reducedBaseBook({...next,modelo_a_snapshot:JSON.stringify({...JSON.parse(next.modelo_a_snapshot),regulatedReducedBases:[]})}));
if(process.env.IVA_REDUCED_FIXTURE)fs.writeFileSync(process.env.IVA_REDUCED_FIXTURE,JSON.stringify(next,null,2)+'\n');
});