32 lines
5.8 KiB
JavaScript
32 lines
5.8 KiB
JavaScript
import test from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import fs from 'node:fs';
|
|
import {newGoodsPresumption,presumptionConditions,goodsPresumptionTreatments,evaluateGoodsPresumption,recordGoodsPresumptions,saveGoodsPresumptionBook,goodsPresumptionBook,goodsPresumptionCurrent,goodsPresumptionReportRows,switchPresumptionTreatment} from '../../resources/js/lib/iva-goods-presumptions.ts';
|
|
const frozen=JSON.parse(fs.readFileSync('tests/frontend/fixtures/iva-goods-presumptions-preserved.json','utf8'));
|
|
const draft={...frozen,context_opportunity:'opportunity:355',project_title:'SYNTHETIC QA — Consignação e presunções / Manica'};
|
|
function row(t){return{...newGoodsPresumption(t),treatment:t,description:'SYNTHETIC QA '+t,period:'2026-12',origin:'projected',operationDate:'2026-12-12',operationRef:'SYNTHETIC QA operação/conferência',documentRef:'SYNTHETIC QA documento/pressuposto',documentDate:'2026-12-12',goodsRef:'SYNTHETIC QA conjunto individual',scope:'SYNTHETIC QA todos os estabelecimentos/período/conjunto',evidence:'SYNTHETIC QA factos/pressupostos expressos',deliveryDate:'2026-06-01',recipientRef:'SYNTHETIC QA destinatário/entrega',inventoryRef:'SYNTHETIC QA levantamento todos estabelecimentos',productionRef:'SYNTHETIC QA volume de produção/comparação',quantity:'125.123456',quantityUnit:'kg',contraryProof:'no',contraryProofRef:'',conditions:Object.fromEntries(presumptionConditions(t).map(([k])=>[k,'yes']))};}
|
|
for(const rule of goodsPresumptionTreatments)test(rule.branch+' '+rule.id+' own facts/references and no fiscal amount',()=>{
|
|
const r=row(rule.id),result=evaluateGoodsPresumption(r);assert.equal(result.status,'determined');assert.equal(result.classification,rule.id==='consignment_180'?'consignment_transmission':rule.id==='found_goods'?'presumed_acquisition':'presumed_transmission');assert.equal(result.baseAmount,null);assert.equal(result.vat,null);assert.equal(result.rate,null);
|
|
for(const[k]of presumptionConditions(rule.id)){const missing=structuredClone(r);delete missing.conditions[k];assert.equal(evaluateGoodsPresumption(missing).status,'indeterminate');missing.conditions[k]='no';assert.equal(evaluateGoodsPresumption(missing).status,'not_applicable');}
|
|
for(const field of ['description','operationRef','documentRef','goodsRef','scope','evidence',...(rule.id==='consignment_180'?['deliveryDate','recipientRef']:['inventoryRef']),...(rule.id==='excess_consumption'?['productionRef','quantity','quantityUnit']:[])])assert.equal(evaluateGoodsPresumption({...r,[field]:''}).status,'indeterminate',field);
|
|
for(const patch of [{operationDate:'2026-02-30'},{documentDate:'2026-02-30'},{period:'2025-12'},{period:'2026-11'}])assert.equal(evaluateGoodsPresumption({...r,...patch}).status,'indeterminate');
|
|
});
|
|
test('P123 exact180-day boundary,yearcrossing and chronology',()=>{
|
|
const r=row('consignment_180');const day=n=>new Date(Date.parse(r.deliveryDate+'T00:00:00Z')+n*86400000).toISOString().slice(0,10);
|
|
for(const n of [179,180,181]){const d=day(n),v=evaluateGoodsPresumption({...r,operationDate:d,period:d.slice(0,7)});assert.equal(v.elapsedDays,n);assert.equal(v.deadline,day(180));assert.equal(v.status,n>180?'determined':'not_applicable');}
|
|
assert.equal(evaluateGoodsPresumption({...r,deliveryDate:'2025-12-31',operationDate:'2026-06-30',period:'2026-06'}).elapsedDays,181);
|
|
assert.equal(evaluateGoodsPresumption({...r,deliveryDate:'2026-12-13'}).status,'indeterminate');
|
|
const returned=structuredClone(r);returned.conditions.notReturned='no';assert.equal(evaluateGoodsPresumption(returned).status,'not_applicable');
|
|
});
|
|
test('P126 rebuttable presumption,unknown proof and scope retained',()=>{
|
|
for(const t of ['missing_goods','excess_consumption','found_goods']){const r=row(t);assert.equal(evaluateGoodsPresumption({...r,contraryProof:''}).status,'indeterminate');assert.equal(evaluateGoodsPresumption({...r,contraryProof:'yes'}).status,'indeterminate');const v=evaluateGoodsPresumption({...r,contraryProof:'yes',contraryProofRef:'SYNTHETIC QA prova/conjunto/período'});assert.equal(v.classification,'rebutted');assert.equal(v.baseAmount,null);assert.equal(v.vat,null);}
|
|
for(const quantity of ['','0','-1','1e3','1.1234567'])assert.equal(evaluateGoodsPresumption({...row('excess_consumption'),quantity}).status,'indeterminate');
|
|
const switched=switchPresumptionTreatment({...row('excess_consumption'),contraryProof:'yes',contraryProofRef:'retained'},'consignment_180');assert.equal(switched.productionRef,row('excess_consumption').productionRef);assert.equal(switched.contraryProofRef,'retained');assert.equal(switched.contraryProof,'');assert.deepEqual(switched.conditions,{});
|
|
});
|
|
test('private draft/report/history preserve allpreviousbooks and opportunity',()=>{
|
|
const rows=goodsPresumptionTreatments.map(t=>row(t.id)),first=recordGoodsPresumptions(draft,{rows});const next={...draft,modelo_a_snapshot:saveGoodsPresumptionBook(draft,first)};const second=recordGoodsPresumptions(next,first);next.modelo_a_snapshot=saveGoodsPresumptionBook(next,second);
|
|
assert.equal(second.history.length,1);assert.deepEqual(second.history[0].inputs,rows);assert.equal(goodsPresumptionCurrent(next,second),true);assert.equal(goodsPresumptionCurrent(next,{...second,rows:rows.map((r,i)=>i? r:{...r,scope:'changed'})}),false);assert.equal(goodsPresumptionReportRows(next).length,4);assert.deepEqual(goodsPresumptionBook({...next,context_opportunity:'opportunity:356'}),{rows:[]});
|
|
const store=JSON.parse(next.modelo_a_snapshot);delete store.goodsPresumptions;assert.deepEqual(store,JSON.parse(frozen.modelo_a_snapshot));assert.throws(()=>recordGoodsPresumptions(next,{rows:[rows[0],rows[0]]}));assert.throws(()=>goodsPresumptionBook({...next,modelo_a_snapshot:JSON.stringify({...store,goodsPresumptions:[]})}));
|
|
if(process.env.IVA_GOODS_PRESUMPTIONS_FIXTURE)fs.writeFileSync(process.env.IVA_GOODS_PRESUMPTIONS_FIXTURE,JSON.stringify(next,null,2)+'\n');
|
|
});
|