44 lines
8.2 KiB
JavaScript
44 lines
8.2 KiB
JavaScript
import test from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import fs from 'node:fs';
|
|
import {newValueReview,switchValueReview,switchPriceContext,switchValueOrigin,valueReviewTreatments,priceContexts,valueReviewConditions,evaluateValueReview,recordValueReviews,saveValueReviewBook,valueReviewBook,valueReviewCurrent,valueReviewReportRows} from '../../resources/js/lib/iva-value-review.ts';
|
|
import {exclusionCurrent} from '../../resources/js/lib/iva-exclusion-base.ts';
|
|
import {compositionCurrent} from '../../resources/js/lib/iva-composition-base.ts';
|
|
import {createProjectDossierReport} from '../../resources/js/lib/project-dossier-report.ts';
|
|
const frozen=JSON.parse(fs.readFileSync(new URL('./fixtures/iva-g7h-preserved-inputs.json',import.meta.url),'utf8'));
|
|
const row=(treatment='price_comparison')=>({...newValueReview('g7h-'+treatment,'MZN'),treatment,priceContext:'retail',description:'SYNTHETIC QA operação A',period:'2026-12',operationRef:'SYNTHETIC QA operação A',documentRef:'SYNTHETIC QA G7H '+treatment,documentDate:'2026-12-12',declaredAmount:'1000.25',referenceAmount:'1500.50',referenceRef:'SYNTHETIC QA preço corrente A',referenceScope:'SYNTHETIC QA bens A,retalho,dezembro2026,Manica e condições comparáveis',compositionRef:'SYNTHETIC QA composição equivalente15(5)/(6),sem próprioIVA',evidence:'SYNTHETIC QA pressupostos expressos,não documento real',correctedAmount:'1400.75',correctionRef:'SYNTHETIC QA pressuposto condicionado correcção A',correctionScope:'SYNTHETIC QA bens A/operação A/dezembro2026/condições A',correctionDate:'2026-12-20',correctionApplies:'yes',conditions:Object.fromEntries(valueReviewConditions.map(([key])=>[key,'yes']))});
|
|
const draft=()=>({...structuredClone(frozen),context_opportunity:'opportunity:346',project_title:'SYNTHETIC QA — G7H / Comparação e correcção'});
|
|
|
|
test('P103 contexts and ownconditions/references;below comparison never replaces declaredbase automatically',()=>{
|
|
for(const context of priceContexts){const input={...row(),priceContext:context.id};assert.equal(evaluateValueReview(input,'MZN').baseAmount,'1000.25');assert.equal(evaluateValueReview(input,'MZN').comparison,'below');
|
|
for(const[key]of valueReviewConditions)for(const value of ['','unknown','no']){const r=evaluateValueReview({...input,conditions:{...input.conditions,[key]:value}},'MZN');assert.equal(r.status,value==='no'?'not_applicable':'indeterminate');assert.equal(r.baseAmount,null);assert.equal(r.vat,null);}
|
|
for(const patch of [{description:''},{operationRef:''},{documentRef:''},{documentDate:'2026-02-30'},{referenceRef:''},{referenceScope:''},{compositionRef:''},{evidence:''},{period:'2025-12'},{currency:'USD'},{priceContext:'unknown'},{treatment:''},{declaredAmount:''},{referenceAmount:''}])assert.equal(evaluateValueReview({...input,...patch},'MZN').baseAmount,null);
|
|
}
|
|
for(const referenceAmount of ['1000.25','500.00']){const r=evaluateValueReview({...row(),referenceAmount},'MZN');assert.equal(r.comparison,'not_below');assert.equal(r.baseAmount,'1000.25');}
|
|
});
|
|
|
|
test('correction amount/reference/scope required;scenario distinct fromeffective;no maximum/default reference;exactdecimal and switches',()=>{
|
|
const input=row('referenced_correction'),ok=evaluateValueReview(input,'MZN');assert.equal(ok.baseAmount,'1400.75');assert.equal(ok.comparison,'below');assert.match(ok.reason,/Cenário condicionado/);assert.equal(ok.vat,null);assert.equal(ok.rate,null);assert.match(evaluateValueReview({...input,origin:'effective'},'MZN').reason,/dados efectivos declarados/);
|
|
for(const patch of [{correctedAmount:''},{correctionRef:''},{correctionScope:''},{correctionDate:'2026-02-30'},{correctionApplies:''}]){const r=evaluateValueReview({...input,...patch},'MZN');assert.equal(r.baseAmount,null);assert.equal(r.comparison,'below');}
|
|
assert.equal(evaluateValueReview({...input,correctionApplies:'no'},'MZN').status,'not_applicable');assert.equal(evaluateValueReview({...input,referenceAmount:'500'},'MZN').status,'not_applicable');
|
|
for(const correctedAmount of ['0','900.15','999999999999999.999999'])assert.equal(evaluateValueReview({...input,correctedAmount},'MZN').baseAmount,correctedAmount==='0'?'0.00':correctedAmount);
|
|
for(const correctedAmount of ['-1','NaN','0.0000001'])assert.equal(evaluateValueReview({...input,correctedAmount},'MZN').baseAmount,null);
|
|
assert.equal(evaluateValueReview({...row(),declaredAmount:'0',referenceAmount:'0'},'MZN').baseAmount,'0.00');assert.equal(evaluateValueReview({...row(),declaredAmount:'1.000001',referenceAmount:'1.000002'},'MZN').comparison,'below');
|
|
for(const changed of [switchValueReview(input,'price_comparison'),switchPriceContext(input,'wholesale'),switchValueOrigin(input,'effective')]){assert.equal(changed.correctionApplies,'');for(const field of ['declaredAmount','referenceAmount','correctedAmount','correctionRef','correctionScope'])assert.equal(changed[field],input[field]);}
|
|
assert.equal(evaluateValueReview(switchValueOrigin(input,'effective'),'MZN').baseAmount,null);assert.equal(evaluateValueReview(switchPriceContext(input,'wholesale'),'MZN').baseAmount,null);
|
|
});
|
|
|
|
test('save/recovery/history/report preserve all85 delivered books/currentkeys including P102/P101/P095',()=>{
|
|
const d=draft(),prior=JSON.parse(d.modelo_a_snapshot);assert.deepEqual(valueReviewBook(d),{rows:[]});assert.deepEqual(valueReviewReportRows(d),[]);
|
|
let book=recordValueReviews(d,{rows:valueReviewTreatments.map(t=>({...row(t.id),conditions:{}}))});book=recordValueReviews(d,{...book,rows:valueReviewTreatments.map(t=>({...row(t.id),conditions:{...row(t.id).conditions,referenceCorresponds:'no'}}))});book=recordValueReviews(d,{...book,rows:valueReviewTreatments.map(t=>row(t.id))});assert.equal(book.history.length,2);assert.ok(book.history.every(h=>h.rows.every(r=>r.baseAmount===null&&r.vat===null)));assert.ok(valueReviewCurrent(d,book));
|
|
for(const field of ['priceContext','declaredAmount','referenceAmount','referenceScope','correctedAmount','correctionRef','correctionScope','correctionApplies','origin'])assert.ok(!valueReviewCurrent(d,{...book,rows:book.rows.map(r=>({...r,[field]:'changed'}))}));for(const patch of [{context_opportunity:'opportunity:347'},{currency:'USD'},{selection_labels:{province_id:'Maputo'}}])assert.ok(!valueReviewCurrent({...d,...patch},book));
|
|
d.modelo_a_snapshot=saveValueReviewBook(d,book);assert.deepEqual(valueReviewBook(JSON.parse(JSON.stringify(d))),book);const next=JSON.parse(d.modelo_a_snapshot);const{valueReviews,...untouched}=next;assert.deepEqual(untouched,prior);for(const[scope,previous]of Object.entries(prior.considerationExclusions))assert.ok(exclusionCurrent({...d,context_opportunity:scope},previous));for(const[scope,previous]of Object.entries(prior.considerationCompositions))assert.ok(compositionCurrent({...d,context_opportunity:scope},previous));
|
|
assert.equal(next.considerationExclusions['opportunity:345'].result.rows[0].baseAmount,'799.70');assert.equal(next.considerationCompositions['opportunity:344'].result.rows[0].baseAmount,'1150.60');assert.equal(next.regulatedFuelBases['opportunity:342'].result.rows[0].baseAmount,'1400.15');assert.equal(next.books['opportunity:329'].result.periods[0].fields['11'],null);
|
|
const report=JSON.stringify(createProjectDossierReport(d,{selectedSections:new Set(['finance']),version:'QA G7H'}));for(const token of ['Base P103','1000.25','1400.75','1500.50','IVA: Indeterminado','opportunity:346','Manica','2026-12','15(7)','condicionado','correcção A','campo11'])assert.ok(report.includes(token),token);assert.deepEqual(valueReviewReportRows({...d,context_opportunity:'opportunity:347'}),[]);
|
|
if(process.env.IVA_G7H_CALCULATED)fs.writeFileSync(process.env.IVA_G7H_CALCULATED,JSON.stringify(d));
|
|
});
|
|
|
|
test('corrupt review rows/store cannot overwrite originals;duplicateoperationids cannotbe recorded',()=>{
|
|
const d=draft(),original=d.modelo_a_snapshot;for(const patch of [{declaredAmount:4},{conditions:[]},{correctionScope:null}])assert.throws(()=>saveValueReviewBook(d,{rows:[{...row(),...patch}]}),/originais preservados/);assert.equal(d.modelo_a_snapshot,original);assert.throws(()=>recordValueReviews(d,{rows:[row(),row()]}),/distintos/);assert.throws(()=>recordValueReviews(d,{rows:[]}),/distintos/);assert.throws(()=>valueReviewBook({...d,modelo_a_snapshot:JSON.stringify({...JSON.parse(original),valueReviews:[]})}),/originais preservados/);
|
|
});
|