20 lines
5.3 KiB
JavaScript
20 lines
5.3 KiB
JavaScript
import fs from 'node:fs';import assert from 'node:assert/strict';import {session} from './sgf-single-http.mjs';
|
|
const run=JSON.parse(fs.readFileSync('C:/laragon/data/sgf-tempo/run/modular-regression-current.json'));const root=run.root+'/private/receipt-composition-cc50a276c10c',path=root+'/single-corrections-http-progress.json';const progress=fs.existsSync(path)?JSON.parse(fs.readFileSync(path)):{operations:{}};const save=()=>fs.writeFileSync(path,JSON.stringify(progress,null,2));
|
|
const clients={};for(const [role,module]of [['finance_prepare','finance'],['finance_review','finance'],['accounting_prepare','accounting'],['accounting_review','accounting']])clients[role]=await session('sgf:'+role,module);
|
|
const step=async(name,role,url,body)=>{let op=progress.operations[name];if(!op){op=progress.operations[name]={key:crypto.randomUUID(),role,url,body};save();}assert.deepEqual({role:op.role,url:op.url,body:op.body},{role,url,body});if(op.result)return op.result;const r=await clients[role].command(url,body,op.key);assert.equal(r.status,200,name+': '+JSON.stringify(r.value));op.result=r.value;save();return r.value;};
|
|
const direct=JSON.parse(fs.readFileSync(root+'/single-direct-cost.json')),industry=JSON.parse(fs.readFileSync(root+'/single-industrial.json')),prior=JSON.parse(fs.readFileSync(root+'/single-financial-http-progress.json'));
|
|
const rate=await step('direct-rate60','finance_prepare',`/api/direct-costs/orders/${direct.order}/rates`,{entry_id:direct.material,entry_version:1,identifier:'QA-INTEGRADO-material',version:2,previous_id:direct.rates.material,currency:'MZN',unit:'UN',amount:'60',evidence:'Taxa sucessora QA60 para duas unidades, autorizada em10/11/2026.'});
|
|
await step('direct-rate-review','finance_review',`/api/direct-costs/orders/${direct.order}/decisions`,{kind:'rate',id:rate.id,version:2,decision:'approved',reason:'Validação distinta da taxa sucessora60 por unidade.'});
|
|
const calc=await step('direct295','finance_prepare',`/api/direct-costs/orders/${direct.order}/calculations`,{currency:'MZN',version:2,previous_id:direct.calculation.id,lines:[{entry_id:direct.material,entry_version:1,rate_id:rate.id,rate_version:2},{entry_id:direct.time,entry_version:1,rate_id:direct.rates.time,rate_version:1}]});
|
|
await step('direct295-review','finance_review',`/api/direct-costs/orders/${direct.order}/decisions`,{kind:'calculation',id:calc.id,version:2,decision:'approved',reason:'Custo295 actual completo, material120 mais trabalho175, validado distintamente.'});
|
|
// Current input payload is obtained from the original authorised fixture references.
|
|
const current=await clients.finance_prepare.get('/api/industrial-costs');assert.equal(current.status,200);const industrialData=await current.json();
|
|
const findInput=node=>{if(!node||typeof node!=='object')return null;if(node.id===industry.refs.material_rate.id&&node.source_ref&&node.data)return node;for(const value of Object.values(node)){const found=findInput(value);if(found)return found;}return null;};
|
|
const old=findInput(industrialData);assert(old,'Original industrial material rate must be visible to the authorised finance profile');const oldData=typeof old.data==='string'?JSON.parse(old.data):old.data;
|
|
const ir=await step('industrial-rate51','finance_prepare',`/api/industrial-costs/lots/${industry.lot}/inputs`,{kind:'material_rate',source_ref:old.source_ref,version:2,previous_id:old.id,data:{...oldData,amount:'51'},evidence:'Taxa sucessora51 para20KG, mantendo trabalho500/CIF300 e residual300.'});
|
|
await step('industrial-rate-review','finance_review',`/api/industrial-costs/lots/${industry.lot}/decisions`,{type:'input',id:ir.id,version:2,decision:'approved',reason:'Revisão independente da taxa artificial51 para20KG.'});
|
|
const refs={...industry.refs,material_rate:{id:ir.id,version:2}};const result=await step('industrial1820','finance_prepare',`/api/industrial-costs/lots/${industry.lot}/calculations`,{currency:'MZN',version:2,previous_id:industry.calculation.id,refs});
|
|
await step('industrial1820-review','finance_review',`/api/industrial-costs/lots/${industry.lot}/decisions`,{type:'result',id:result.id,version:2,decision:'approved',reason:'Resultado1820 validado distintamente, mantendo residual300 separado.'});
|
|
for(const name of ['direct275','industrial1800']){const journal=prior.operations[name+'-post'].result.journal_id;const c=await step(name+'-correction','accounting_prepare','/api/general-ledger/correct-prepare',{journal_id:journal,journal_on:'2026-11-10',period_key:'QA-2026-INTEGRADO',reason:'Par indivisível de estorno e substituição do original autorizado: '+name+'.'});await step(name+'-correction-review','accounting_review','/api/general-ledger/correct-validate',{correction_id:c.correction_id,revision:c.revision,decision:'approved',reason:'Conferência independente dos dois impactos e da origem actual: '+name+'.'});await step(name+'-correction-post','accounting_prepare','/api/general-ledger/correct-post',{correction_id:c.correction_id,revision:c.revision,reason:'Aplicar o par revisto atomicamente, preservando o original.'});}
|
|
const response=await clients.accounting_prepare.get('/api/general-ledger');assert.equal(response.status,200);const ledger=await response.json();assert.equal(ledger.journals.length,13);assert.equal(ledger.totals.debit_minor,ledger.totals.credit_minor);progress.passed=true;progress.journals=13;save();console.log(JSON.stringify({passed:true,journals:13,proof:path,browser_visual_review:false}));
|