40 lines
4.4 KiB
JavaScript
40 lines
4.4 KiB
JavaScript
import test from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import fs from 'node:fs';
|
|
import { exportBeneficiaryTreatments as rules } from '../../resources/js/lib/iva-export-beneficiaries.ts';
|
|
import { newSalesOperation, evaluateSalesOperation, recordSales, saveSalesBook, salesBook, salesCurrent } from '../../resources/js/lib/iva-operations.ts';
|
|
import { createProjectDossierReport } from '../../resources/js/lib/project-dossier-report.ts';
|
|
const frozen=JSON.parse(fs.readFileSync(new URL('./fixtures/iva-g4d-inputs.json',import.meta.url),'utf8'));
|
|
const row=(rule,i)=>({...newSalesOperation(`g4e-${i}`,'2026-12','MZN'),description:`SYNTHETIC QA — ${rule.label}`,establishment:'SYNTHETIC QA estabelecimento',amount:'100',basis:i%2?'included':'net',treatment:rule.id,confirmed:rule.conditions.map((_,n)=>n),evidence:'SYNTHETIC QA — pressuposto expresso de projecção: intervenientes, destino/saída e regulamentação própria (b); acordo aplicável, disposição, âmbito/período e reconhecimento (j/k); reconhecimento do organismo e prévio direito (l). Sem certificação real.'});
|
|
function fixture(){
|
|
const draft={...structuredClone(frozen),context_opportunity:'opportunity:327',project_title:'SYNTHETIC QA — G4E / Exportações e beneficiários'};
|
|
const book=recordSales(draft,{currency:'MZN',rows:rules.map(row),periods:[{period:'2026-12',complete:true}]});draft.modelo_a_snapshot=saveSalesBook(draft,book);return{draft,book};
|
|
}
|
|
test('four distinct branches require every applicable condition; missing treaty/recognition/private-use exclusion never produces zero',()=>{
|
|
assert.equal(rules.length,4);
|
|
for(const[i,rule]of rules.entries()){
|
|
const input=row(rule,i),result=evaluateSalesOperation(input,'MZN');assert.equal(result.field,'05');assert.equal(result.vat,'0.00');assert.equal(result.net,'100.00');assert.equal(result.gross,'100.00');
|
|
for(const missing of input.confirmed){const incomplete=evaluateSalesOperation({...input,confirmed:input.confirmed.filter(n=>n!==missing)},'MZN');assert.equal(incomplete.vat,null);assert.equal(incomplete.net,null);}
|
|
for(const patch of [{amount:''},{evidence:''},{sourceCurrency:'USD'},{period:'2027-01'},{basis:''},{description:''},{establishment:''}])assert.equal(evaluateSalesOperation({...input,...patch},'MZN').vat,null);
|
|
}
|
|
assert.match(rules[0].conditions.join(' '),/uso privado/);assert.match(rules[0].conditions.join(' '),/regulamentação própria/);
|
|
for(const rule of rules.slice(1,3))assert.match(rule.conditions.join(' '),/acordo ou convénio/);
|
|
assert.match(rules[3].conditions.join(' '),/Prévio reconhecimento do direito/);
|
|
});
|
|
test('editing legal support preserves price/context/history and makes totals indeterminate until conditions are reviewed',()=>{
|
|
const{draft,book}=fixture();assert.equal(book.result.periods[0].fields['05'],'400.00');
|
|
for(let i=0;i<4;i++){
|
|
const changed=recordSales(draft,{...book,rows:book.rows.map((r,n)=>n===i?{...r,evidence:'Documento/pressuposto revisto; condições por reconfirmar',confirmed:[]}:r)});
|
|
assert.equal(changed.rows[i].amount,'100');assert.equal(changed.rows[i].sourceCurrency,'MZN');assert.equal(changed.rows[i].period,'2026-12');assert.equal(changed.result.periods[0].fields['05'],null);assert.deepEqual(changed.history.at(-1),book.result);
|
|
const edited={...draft,modelo_a_snapshot:saveSalesBook(draft,{...book,rows:changed.rows})};assert.equal(salesCurrent(edited,salesBook(edited)),false);
|
|
}
|
|
});
|
|
test('snapshot/report retain sources,assumptions,opportunity;18 previous books are identical/current without recalculation',()=>{
|
|
const{draft,book}=fixture();assert.ok(salesCurrent(draft,book));assert.deepEqual(salesBook(JSON.parse(JSON.stringify(draft))),JSON.parse(JSON.stringify(book)));
|
|
const before=JSON.parse(frozen.modelo_a_snapshot).salesOperations,after=JSON.parse(draft.modelo_a_snapshot).salesOperations;assert.equal(Object.keys(before).length,18);
|
|
for(const[context,original]of Object.entries(before)){assert.deepEqual(after[context],original);assert.ok(salesCurrent({...draft,context_opportunity:context},after[context]));}
|
|
const report=JSON.stringify(createProjectDossierReport(draft,{selectedSections:new Set(['finance']),version:'QA G4E'}));
|
|
for(const token of ['opportunity:327','Manica','2026-12','400.00','13(1)(b)','13(1)(j)','13(1)(k)','13(1)(l)','pressuposto expresso','QA G4E'])assert.ok(report.includes(token),token);
|
|
if(process.env.IVA_G4E_CALCULATED)fs.writeFileSync(process.env.IVA_G4E_CALCULATED,JSON.stringify(draft));
|
|
});
|