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

10 lines
6.3 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';
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+'/fiscal-rules-http-20261110.json';let progress=fs.existsSync(file)?JSON.parse(fs.readFileSync(file)):{operations:{},checks:[]};if(progress.passed){console.log(JSON.stringify({passed:true,reused:true,proof:file}));process.exit();}const save=()=>fs.writeFileSync(file,JSON.stringify(progress,null,2));const ok=(v,n)=>{assert(v,n);if(!progress.checks.includes(n))progress.checks.push(n);save();};const prep=await session('sgf:finance_prepare','accounting'),review=await session('sgf:finance_review','accounting');const get=async(s=prep,q='')=>{const r=await s.get('/api/fiscal-rules'+q);assert.equal(r.status,200);return r.json();};const state=await get();ok(prep.identity.context.fiscal_rules_qa_enabled===true,'feature in actual context');ok(state.fixtures.not_tax_law===true&&state.fixtures.cases.length===2,'pinned artificial source loaded');
const command=async(name,s,input)=>{if(progress.operations[name]?.result)return progress.operations[name].result;let op=progress.operations[name];if(!op){op=progress.operations[name]={key:crypto.randomUUID(),input};save();}if(!op.cut){const p=await s.command('/api/fiscal-rules/preview',op.input,op.key);assert.equal(p.status,200,JSON.stringify(p.value));op.cut=p.value.preview;ok(p.value.impact.new_journals===0&&p.value.impact.legal_activation===false,'preview excludes financial/legal activation');save();}const r=await s.command('/api/fiscal-rules/confirm',{preview:op.cut});assert.equal(r.status,200,JSON.stringify(r.value));op.result=r.value;save();const replay=await s.command('/api/fiscal-rules/confirm',{preview:op.cut});ok(replay.status===200&&replay.value.replayed&&replay.value.id===r.value.id,'repeat '+name+' no duplication');return r.value;};
const rule=(action,revision,data,target)=>({action,rule_key:'QA-RATE-TRANSVERSAL',revision,...(target?{target_id:target}:{}),data,reason:'Conferência QA individual de fonte, vigência e revisão exacta da regra artificial.'});const calc=(id,date)=>({action:'calculate',revision:0,data:{rule_event_id:id,date,base:'1000',currency:'MZN'},reason:'Ensaio artificial autorizado, regra e data escolhidas explicitamente, sem efeitos financeiros.'});const def=i=>({...state.fixtures.cases[i].definition,source_sha256:state.fixtures.sha256});
const p1=await command('prepare-v1',prep,rule('prepare',0,def(0)));const r1=await command('review-v1',review,rule('review',1,{decision:'reviewed'},p1.id));const c1=await command('calculate-november',prep,calc(r1.id,'2026-11-30'));let response=await prep.get('/api/fiscal-rules/records/'+c1.id+'?type=calculation');const first=await response.json();ok(response.status===200&&first.result.tax_exact==='160'&&first.result.tax_document==='160.00'&&first.result.total==='1160.00','actual Nov30 case160/1160');
const p2=await command('prepare-v2',prep,rule('prepare',2,def(1)));const r2=await command('review-v2',review,rule('review',3,{decision:'reviewed'},p2.id));const c2=await command('calculate-december',prep,calc(r2.id,'2026-12-01'));response=await prep.get('/api/fiscal-rules/records/'+c2.id+'?type=calculation');const second=await response.json();ok(response.status===200&&second.result.tax_exact==='170'&&second.result.total==='1170.00','actual Dec1 case170/1170');response=await prep.get('/api/fiscal-rules/records/'+c1.id+'?type=calculation');const historical=await response.json();ok(JSON.stringify(historical.result)===JSON.stringify(first.result)&&historical.current_evaluation.tax_document==='160.00','successor leaves historical first calculation unchanged');
const oldDate=await prep.command('/api/fiscal-rules/preview',calc(r2.id,'2026-11-30'));ok(oldDate.status===200&&oldDate.value.impact.result.state==='pending'&&oldDate.value.impact.result.tax_document===null,'future rule not automatically applied early');const missing=await prep.command('/api/fiscal-rules/preview',calc(null,'2026-12-01'));ok(missing.status===200&&missing.value.impact.result.state==='pending','missing selection pending never zero');
const read=await session('sgf:read_only','accounting'),catalogue=await get(read,'?per_page=100&family=qa&state=reviewed');ok(catalogue.records.total===2&&!catalogue.capabilities.prepare&&!catalogue.capabilities.review,'both dated versions visible to read-only role');const history=await get(read,'?view=history&rule_key=QA-RATE-TRANSVERSAL');ok(history.records.total===4&&history.stream_revision===4,'four rule events in paged history');const calculations=await get(read,'?view=calculations&per_page=100');ok(calculations.records.total===2,'only two saved QA calculations');const denied=await read.command('/api/fiscal-rules/preview',rule('prepare',4,def(1)));ok(denied.status===403,'read-only write refused');const foreign=await prep.command('/api/fiscal-rules/preview',calc(2147483647,'2026-12-01'));ok(foreign.status===403,'unscoped selected ID refused');response=await prep.get('/api/fiscal-rules?tenant_id=2');ok(response.status===422,'tenant override rejected');const wrong=await session('sgf:finance_prepare','finance');response=await wrong.get('/api/fiscal-rules');ok([403,409].includes(response.status),'wrong module rejected');
const fresh=await session('sgf:finance_prepare','accounting');response=await fresh.get('/api/fiscal-rules/receipts/'+progress.operations['calculate-november'].key);const recovered=await response.json();ok(response.status===200&&recovered.result.id===c1.id&&recovered.operation_executed===false,'historical own receipt recovered in fresh session');response=await review.get('/api/fiscal-rules/receipts/'+progress.operations['calculate-november'].key);ok(response.status===404,'other actor cannot recover key');response=await read.get('/fiscal/rules',{headers:{Accept:'text/html'}});ok(response.status===200&&(await response.text()).includes('sem activação legal'),'actual screen available with explicit artificial notice');progress.passed=true;progress.business_confirmations=6;progress.rule_events_retained=4;progress.calculations_retained=2;progress.new_journals=0;progress.browser_visual_review=false;save();console.log(JSON.stringify({passed:true,checks:progress.checks.length,proof:file}));