15 lines
6.3 KiB
JavaScript
15 lines
6.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')),root=run.root+'/private/receipt-composition-cc50a276c10c',file=root+'/stock-completion-http-20261110.json',progress=fs.existsSync(file)?JSON.parse(fs.readFileSync(file)):{operations:{},checks:[]},save=()=>fs.writeFileSync(file,JSON.stringify(progress,null,2));
|
|
const clients={warehouse:await session('purchasing:validator','stock'),review:await session('sgf:workshop_verify','stock'),prepare:await session('sgf:accounting_prepare','accounting'),accountReview:await session('sgf:accounting_review','accounting')};
|
|
const ok=(v,label)=>{assert(v,label);if(!progress.checks.includes(label))progress.checks.push(label);save();};
|
|
const state=async(role,family='policy')=>{const r=await clients[role].get('/api/stock-completion?'+new URLSearchParams({family,per_page:100}));assert.equal(r.status,200,await r.clone().text());return r.json();};
|
|
const step=async(name,role,family,action,data={},record=null,version=0)=>{let op=progress.operations[name];if(!op){op=progress.operations[name]={role,family,action,data,record,version,key:crypto.randomUUID()};save();}assert.deepEqual({role,family,action,data,record,version},{role:op.role,family:op.family,action:op.action,data:op.data,record:op.record,version:op.version});if(op.result)return op.result;
|
|
let r=await clients[role].get('/api/stock-completion/receipts/'+op.key);if(r.status===200){op.result=(await r.json()).result;save();return op.result;}assert.equal(r.status,404);const current=await state(role,family);const p=await clients[role].command('/api/stock-completion/preview',{family,action,data,record_key:record,version,operation_key:op.key,revision:current.revision,reason:'Decisão individual do bloco QA autorizado: '+name+'.'});assert.equal(p.status,200,JSON.stringify(p.value));r=await clients[role].command('/api/stock-completion/confirm',{preview:p.value.preview});assert.equal(r.status,201,JSON.stringify(r.value));op.result=r.value;save();const again=await clients[role].command('/api/stock-completion/confirm',{preview:p.value.preview});ok(again.status===200&&again.value.replayed&&again.value.record_id===r.value.record_id,name+' replays one original result');return op.result;};
|
|
const ledger=async(name,role,path,body)=>{let op=progress.operations[name];if(!op){op=progress.operations[name]={role,path,body,key:crypto.randomUUID()};save();}assert.deepEqual({role,path,body},{role:op.role,path:op.path,body:op.body});if(op.result)return op.result;const r=await clients[role].command(path,body,op.key);assert.equal(r.status,200,JSON.stringify(r.value));op.result=r.value;save();return op.result;};
|
|
let r=await clients.warehouse.get('/stock/completion',{headers:{Accept:'text/html'}});ok(r.status===200&&(await r.text()).includes('sgf-stock-completion.mjs'),'authenticated Stock screen available');const initial=await state('warehouse');const item=initial.basis.item.id,warehouse=initial.basis.warehouse.id;
|
|
const policy=await step('politica-minimos','warehouse','policy','save',{stock_item_id:item,warehouse_id:warehouse,forecast_method:'manual',purpose:'internal',origin:'local',safety_milli:2000,minimum_stock_milli:5000,target_milli:10000,maximum_milli:20000,daily_milli:1000,lead_days:2,approval_days:1,horizon_days:14,minimum_milli:1000,pack_milli:1000,basis:'Quantidades QA e prazo conhecido, sem regra de compra automática.'});await step('aprovar-politica','review','policy','approve',{},policy.record_key,1);
|
|
const draft=await step('preparar-devolucao2UN','warehouse','supplier_return','save',{kind:'supplier_return',stock_item_id:item,warehouse_id:warehouse,receipt_item_id:initial.receipt_item_id,quantity:'2.000',reference:'QA-DEV-FORN-8085-20261110'});await step('aprovar-devolucao','review','supplier_return','approve',{},draft.record_key,1);const done=await step('executar-devolucao','warehouse','supplier_return','execute',{event_on:'2026-11-10',evidence:'QA-GUIA-FORNECEDOR-8085-20261110, saída física2UN.'},draft.record_key,2);ok(done.impact.after_milli===8000&&!done.impact.financial_credit_created,'one native physical return leaves8UN without credit');
|
|
r=await clients.prepare.get('/api/general-ledger');assert.equal(r.status,200,await r.clone().text());let data=await r.json();const book=data.stock.find(s=>s.book.stock_item_id===item);assert(book);const rate=await ledger('taxa20','prepare','/api/general-ledger/stock/rate-prepare',{book_id:book.book.id,version:0,unit_minor:2000,reason:'Taxa QA20MZN por UN para novo artigo de devolução.'});await ledger('rever-taxa20','accountReview','/api/general-ledger/stock/rate-review',{rate_id:rate.rate_id,version:1,decision:'approved',reason:'Revisão distinta do artigo, origem e taxa20MZN.'});
|
|
for(const row of book.rows){const m=row.movement,kind={receipt_in:'stock.receipt',supplier_return:'stock.supplier_return'}[m.movement_type];assert(kind);const p=await ledger(kind+'-preparar','prepare','/api/general-ledger/effect-prepare',{effect_type:kind,source_id:m.id,journal_on:'2026-11-10',period_key:'QA-2026-INTEGRADO',rule_key:kind,reason:'Valorização individual da origem física efectiva: '+kind+'.'});await ledger(kind+'-rever','accountReview','/api/general-ledger/validate',{proposal_id:p.proposal_id,revision:p.revision,decision:'approved',reason:'Conferência distinta da origem física, aprovação e taxa20.'});await ledger(kind+'-aplicar','prepare','/api/general-ledger/post',{proposal_id:p.proposal_id,revision:p.revision,reason:'Aplicação única da origem QA revista no mesmo diário.'});}
|
|
r=await clients.prepare.get('/api/general-ledger');data=await r.json();ok(r.status===200&&data.journals.length===20,'same ledger now20 journals including only two new Stock facts');ok(data.totals.debit_minor===data.totals.credit_minor,'same ledger remains balanced');const current=data.stock.find(s=>s.book.stock_item_id===item);ok(current.physical_balance_milli===8000&¤t.rows.every(row=>row.source&&!row.pending),'new article8UN reconciles with valued source facts');const history=await state('review','supplier_return');ok(history.records.total===1&&history.records.data[0].version===3&&history.records.data[0].state==='executed','one return process retains reviewed execution version');progress.passed=true;progress.browser_visual_review=false;save();console.log(JSON.stringify({passed:true,checks:progress.checks.length,proof:file}));
|