Files
SGF/scripts/sgf-fiscal-obligations-http.mjs
2026-11-11 09:00:17 +02:00

10 lines
7.9 KiB
JavaScript

import fs from 'node:fs';import assert from 'node:assert/strict';import crypto from 'node:crypto';import {session} from './sgf-single-http.mjs';import {checkedObligations,obligationsPageCsv} from '../resources/js/fiscal-obligations-view.js';
const root=JSON.parse(fs.readFileSync('C:/laragon/data/sgf-tempo/run/modular-regression-current.json')).root+'/private/receipt-composition-cc50a276c10c',progress=root+'/fiscal-obligations-http-progress.json',saved=fs.existsSync(progress)?JSON.parse(fs.readFileSync(progress)):{record_key:crypto.randomUUID()},save=()=>fs.writeFileSync(progress,JSON.stringify(saved)),checks=[],ok=(v,n)=>{assert(v,n);checks.push(n);};save();const prep=await session('sgf:finance_prepare','accounting'),review=await session('sgf:finance_review','accounting'),read=await session('sgf:read_only','accounting'),base='/api/fiscal-obligations',query={reference_on:'2026-12-15',page:1,per_page:25};const get=async(s=read,q=query)=>{const r=await s.get(base+'?'+new URLSearchParams(q));assert.equal(r.status,200);return checkedObligations(await r.json(),q);};let state=await get(),source=state.source;assert(source);ok(prep.identity.context.fiscal_obligations_enabled===true,'feature exposed only in selected context');const grantNames=s=>s.identity.context.grants.filter(g=>g.permission.startsWith('fiscal_obligations.')).map(g=>g.permission).sort();ok(JSON.stringify(grantNames(prep))===JSON.stringify(['fiscal_obligations.prepare','fiscal_obligations.view']),'preparer exact two rights');ok(JSON.stringify(grantNames(review))===JSON.stringify(['fiscal_obligations.review','fiscal_obligations.view']),'reviewer exact two rights');ok(JSON.stringify(grantNames(read))===JSON.stringify(['fiscal_obligations.view']),'reader exact one right');
if(!saved.sourceExportVerified){const r=await prep.get('/api/fiscal-assessments/forms/'+source.form_id+'/export');assert.equal(r.status,200);const bytes=Buffer.from(await r.arrayBuffer());assert.equal(crypto.createHash('sha256').update(bytes).digest('hex'),source.export_sha256);assert.equal(r.headers.get('x-content-sha256'),source.export_sha256);saved.sourceExportVerified=true;save();}ok(saved.sourceExportVerified,'actual existing map export bytes and SHA verified');
const data={operation:'establish',form_id:source.form_id,period:source.period,responsible_id:13,due_on:'2026-12-15',evidence:'QA prazo artificial15/12/2026 do mapa interno; sem fundamento de prazo legal.',export_sha256:null},input=(action,version,data)=>({action,record_key:saved.record_key,version,data,reason:'Decisão QA individual fundamentada, sem tributo, pagamento ou transmissão à AT.'});
async function perform(name,s,incoming){saved[name]??={key:crypto.randomUUID()};save();const step=saved[name];if(step.result)return step.result;const old=await s.get(base+'/receipts/'+step.key);if(old.status===200){step.result=(await old.json()).result;save();return step.result;}assert.equal(old.status,404);const cut=await s.command(base+'/preview',incoming,step.key);assert.equal(cut.status,200,JSON.stringify(cut.value));step.cut=cut.value;save();const out=await s.command(base+'/confirm',{preview:cut.value.preview},step.key);assert.equal(out.status,200,JSON.stringify(out.value));step.result=out.value;save();return out.value;}
const v1=await perform('prepare',prep,input('prepare',0,data));ok(v1.version===1&&v1.state==='prepared','actual intention v1');if(!saved.replayChecked){const same=await prep.command(base+'/confirm',{preview:saved.prepare.cut.preview},saved.prepare.key);assert.equal(same.status,200);assert(same.value.replayed);saved.replayChecked=true;save();}ok(saved.replayChecked,'same confirmation recovers without duplication');const v2=await perform('review',review,input('review',1,{decision:'approved'}));ok(v2.version===2&&v2.state==='approved','distinct review v2');const delivery={...data,operation:'delivery',export_sha256:source.export_sha256,evidence:'QA ENTREGA APENAS SIMULADA: referência da exportação interna mapa#'+source.form_id+', sem envio ou aceite da AT.'};const v3=await perform('deliveryPrepare',prep,input('prepare',2,delivery));ok(v3.version===3&&v3.impact.after.effective.administrative_status==='active','delivery preparation does not fulfil obligation');const v4=await perform('deliveryReview',review,input('review',3,{decision:'approved'}));ok(v4.version===4&&v4.impact.after.effective.administrative_status==='delivery_simulated','distinct delivery review v4');state=await get();const row=state.records.data.find(r=>r.record_key===saved.record_key);ok(state.records.total===1&&row.version===4&&row.effective.delivery_evidence.export_sha256===source.export_sha256,'one obligation four decisions correct SHA');ok(row.days_overdue===0,'same artificial deadline no delay');const next=await get(read,{...query,reference_on:'2026-12-16'});ok(next.records.data[0].days_overdue===1&&next.official_submission===false&&next.tax_payable===null,'next day classification independent of simulated delivery');const history=await get(read,{...query,record_key:saved.record_key});ok(history.records.total===4&&JSON.stringify(history.records.data.map(r=>r.version))==='[4,3,2,1]','full individual audit history ordered');const large=await get(read,{...query,record_key:saved.record_key,per_page:100});ok(JSON.stringify(large.records.data)===JSON.stringify(history.records.data),'history25/100 equivalent');ok((await get(read,{...query,due_from:'2026-12-16',due_to:'2026-12-16'})).records.total===0,'server deadline range no matching record');ok((await get(read,{...query,status:'delivery_simulated',period:source.period})).records.total===1,'server status and period filter');ok((await get(read,{...query,page:100000})).records.data.length===0,'far page no fallback');
const bad=await read.command(base+'/preview',input('prepare',4,{...data,operation:'amend'}));ok(bad.status===403,'reader cannot prepare');const own=await prep.command(base+'/preview',input('review',4,{decision:'approved'}));ok(own.status===403,'preparer cannot review');const sameMap=await prep.command(base+'/preview',{...input('prepare',0,data),record_key:crypto.randomUUID()});ok(sameMap.status===409,'same reviewed map cannot generate duplicate obligation');for(const q of [{...query,tenant_id:2},{...query,per_page:1000}]){const r=await read.get(base+'?'+new URLSearchParams(q));ok(r.status===422,'protected query refused '+JSON.stringify(q));}const other=await session('sgf:finance_prepare','finance');let r=await other.get(base+'?'+new URLSearchParams(query));ok([403,409].includes(r.status),'other module refused');r=await review.get(base+'/receipts/'+saved.prepare.key);ok(r.status===404,'another actor receipt refused');const fresh=await session('sgf:finance_prepare','accounting');r=await fresh.get(base+'/receipts/'+saved.prepare.key);const receipt=await r.json();ok(r.status===200&&receipt.historical_receipt_only&&!receipt.operation_executed&&receipt.result.id===v1.id,'own receipt recoverable fresh authorized session');ok(obligationsPageCsv(state,query).includes('SEM PRAZO LEGAL OU SUBMISSAO')&&obligationsPageCsv(state,query).includes(saved.record_key),'actual page CSV honest administrative evidence');
const manifest=JSON.parse(fs.readFileSync(root+'/app/public/build/manifest.json'));for(const e of Object.values(manifest).filter(v=>v.isEntry||v.file.includes('FiscalObligationsWorkspace'))){r=await fetch('http://127.0.0.1:8085/build/'+e.file);const bytes=Buffer.from(await r.arrayBuffer());ok(r.status===200&&/javascript/.test(r.headers.get('content-type'))&&crypto.createHash('sha256').update(bytes).digest('hex')===crypto.createHash('sha256').update(fs.readFileSync(root+'/app/public/build/'+e.file)).digest('hex'),'actual JS delivery '+e.file);}
fs.writeFileSync(root+'/fiscal-obligations-sample-private.json',JSON.stringify(state));const file=root+'/fiscal-obligations-http-20261110.json';fs.writeFileSync(file,JSON.stringify({passed:true,checks,actual_administrative_commands:4,map_recreated:false,financial_effects:0,new_demo:false,browser_visual_review:false},null,2));console.log(JSON.stringify({passed:true,checks:checks.length,proof:file}));