true,'modules.contracted'=>['purchasing','accounting'],'modules.companies.'.$scope['tenant_id'].':'.$scope['company_id']=>['contracted'=>['purchasing','accounting'],'enabled'=>['purchasing','accounting']]]); $enter=function(string $role)use($f,$scope):User{$u=User::findOrFail($f['actors'][$role]);auth()->setUser($u);app(CompanyContext::class)->selectFor($u->id,$scope['tenant_id'],$scope['company_id'],$scope['unit_id']);return $u;}; $ledger=app(GeneralLedger::class); $command=fn(string $role,string $action,array $body,?string $key=null,?Closure $fault=null)=>$ledger->engine($enter($role),$fault)->command($action,$body,$key??(string)Str::uuid()); $financialFingerprint=function():string{$h=hash_init('sha256');foreach(['pa_imported_sources','pa_source_histories','pa_sources','pa_proposals','pa_obligations','pa_history_imports','pa_imported_payments','pa_events','pa_commands','pa_access','permission_grants','company_memberships'] as $table){hash_update($h,$table."\n");$q=DB::table($table);if($table==='company_memberships')$q->orderBy('tenant_id')->orderBy('company_id')->orderBy('user_id');else $q->orderBy('id');foreach($q->cursor() as $r)hash_update($h,Payables::canonical((array)$r)."\n");}return hash_final($h);}; if($phase==='ledger-setup-recover'){ LedgerSchema::assertSynthetic(DB::connection()); foreach(LedgerSchema::TABLES as $table)if(!DB::getSchemaBuilder()->hasTable($table)||DB::table($table)->count()!==(in_array($table,['gl_accounts'],true)?2:(in_array($table,['gl_periods','gl_rules'],true)?1:0)))throw new LogicException('Unexpected setup state; no repair performed'); if(DB::table('permission_grants')->where('permission','like','general_ledger.%')->count()!==6||DB::table('pa_obligations')->count()!==1)throw new LogicException('Unexpected isolated grants/source'); $local=DB::table('pa_imported_sources')->whereRaw("payload->>'number' = ?",['QA-LEDGER-SOURCE-60'])->value('id');$obligation=DB::table('pa_obligations')->first(); $g=['obligation_id'=>$obligation->id,'local_source_id'=>$local,'debit_account'=>DB::table('gl_accounts')->where('code','QA-CONTRAPARTIDA')->value('id'),'credit_account'=>DB::table('gl_accounts')->where('code','QA-FORNECEDOR')->value('id'),'body'=>['obligation_id'=>$obligation->id,'journal_on'=>'2026-10-29','period_key'=>'QA-2026-10','rule_key'=>'QA-PAYABLE-JOURNAL','reason'=>'Individual synthetic journal preparation.'],'financial_fingerprint'=>$financialFingerprint()]; file_put_contents($s['root'].'/ledger-fixture.json',json_encode($g,JSON_PRETTY_PRINT|JSON_THROW_ON_ERROR));echo "Existing fresh QA setup checked read-only; fixture manifest recovered without repeating schema, grants or recognition.\n";exit; } if(in_array($phase,['ledger-setup','ledger-flow-setup','ledger-cycle-setup'],true)){ LedgerSchema::install(DB::connection()); DB::statement('ALTER TABLE permission_grants DROP CONSTRAINT permission_grants_scope_check'); DB::statement("ALTER TABLE permission_grants ADD CONSTRAINT permission_grants_scope_check CHECK ((unit_id IS NULL AND permission='company.view') OR (unit_id IS NOT NULL AND permission IN ('unit.view','supplier_payables.view','general_ledger.view','general_ledger.prepare','general_ledger.validate','general_ledger.post')))"); foreach(['prepare'=>['view','prepare','post'],'validate'=>['view','validate'],'read'=>['view']] as $role=>$actions)foreach($actions as $action)DB::table('permission_grants')->insert($scope+['user_id'=>$f['actors'][$role],'permission'=>'general_ledger.'.$action,'created_at'=>now(),'updated_at'=>now()]); $debit=DB::table('gl_accounts')->insertGetId($scope+['code'=>'QA-CONTRAPARTIDA','label'=>'Contrapartida artificial de ensaio','is_movement'=>true,'currency'=>'MZN']); $credit=DB::table('gl_accounts')->insertGetId($scope+['code'=>'QA-FORNECEDOR','label'=>'Fornecedor artificial de ensaio','is_movement'=>true,'currency'=>'MZN']); $common=['created_by'=>$f['actors']['prepare'],'reason'=>'Explicitly authorised artificial QA configuration.','created_at'=>now()]; DB::table('gl_periods')->insert($scope+$common+['period_key'=>'QA-2026-10','version'=>1,'starts_on'=>'2026-10-01','ends_on'=>'2026-10-31','status'=>'open']); DB::table('gl_rules')->insert($scope+$common+['rule_key'=>'QA-PAYABLE-JOURNAL','version'=>1,'policy'=>PayableJournal::POLICY,'effect_type'=>'supplier_payable.recognised','currency'=>'MZN','valid_from'=>'2026-10-01','valid_to'=>'2026-10-31','debit_account_id'=>$debit,'credit_account_id'=>$credit]); $finance=app(SupplierPayables::class);$doc=$finance->document($enter('prepare'),$f['source_id']);unset($doc['local_id']);$doc['document']=270001;$doc['number']='QA-LEDGER-SOURCE-60';$doc['payment_count']=0;$payload=Payables::canonical($doc); $local=DB::table('pa_imported_sources')->insertGetId($scope+['payload'=>$payload,'receipt_hash'=>hash('sha256',$payload)]); $o=['obligation_id'=>null]; if(in_array($phase,['ledger-setup','ledger-cycle-setup'],true)){ $p=$finance->engine($enter('prepare'))->command('prepare',$local,'Recognised source for the first ledger QA scenario.',(string)Str::uuid()); $o=$finance->engine($enter('validate'))->command('validate',$p['proposal_id'],'Independent recognition of explicit synthetic source.',(string)Str::uuid()); } $g=['integrated_flow'=>$phase==='ledger-flow-setup','obligation_id'=>$o['obligation_id'],'local_source_id'=>$local,'debit_account'=>$debit,'credit_account'=>$credit,'body'=>['obligation_id'=>$o['obligation_id'],'journal_on'=>'2026-10-29','period_key'=>'QA-2026-10','rule_key'=>'QA-PAYABLE-JOURNAL','reason'=>'Individual synthetic journal preparation.'],'financial_fingerprint'=>$financialFingerprint()]; if($phase==='ledger-cycle-setup'){require __DIR__.'/ledger-cycle-setup.php';$g['cycle_enabled']=true;} file_put_contents($s['root'].'/ledger-fixture.json',json_encode($g,JSON_PRETTY_PRINT|JSON_THROW_ON_ERROR));echo "Ledger QA installed in new database: explicit 60 MZN source, two artificial accounts, period and six explicit grants covering four rights. No journal yet.\n";exit; } $g=json_decode(file_get_contents($s['root'].'/ledger-fixture.json'),true,64,JSON_THROW_ON_ERROR); if($phase==='ledger-reports-isolation'){require __DIR__.'/ledger-reports-isolation.php';exit;} if(in_array($phase,['ledger-reports-seed','ledger-reports-cases'],true)){require __DIR__.'/ledger-reports-proof.php';exit;} if($g['cycle_enabled']??false)config(['general_ledger.cycle_enabled'=>true]); if(in_array($phase,['ledger-cycle-cases','ledger-cycle-workflow','ledger-cycle-race-prepare'],true)){require __DIR__.'/ledger-cycle-cases.php';exit;} if(in_array($phase,['ledger-cycle-race','ledger-cycle-worker'],true)){require __DIR__.'/ledger-cycle-race.php';exit;} if($phase==='ledger-cycle-security'){require __DIR__.'/ledger-cycle-security.php';exit;} if($phase==='ledger-cycle-final'){require __DIR__.'/ledger-cycle-final.php';exit;} if($phase==='ledger-flow-cases'){require __DIR__.'/ledger-flow-cases.php';exit;} if($phase==='ledger-flow-focus-cases'){require __DIR__.'/ledger-flow-focus-cases.php';exit;} if($phase==='ledger-cases'){require __DIR__.'/ledger-cases.php';exit;} if(in_array($phase,['ledger-race','ledger-worker'],true)){require __DIR__.'/ledger-race.php';exit;} if($phase==='ledger-http'){require __DIR__.'/ledger-http-entry.php';exit;} if($phase==='ledger-ui-state'){ $data=$ledger->listing($enter('prepare'));$html=view('accounting.general-ledger',['data'=>$data])->render(); if(count($data['proposals'])!==1||!$data['proposals'][0]->journal_id||!str_contains($html,'Aplicada uma vez no lançamento #')||str_contains($html,'data-action="post"'))throw new LogicException('Posted proposal must show its receipt without another apply form'); file_put_contents($s['root'].'/ledger-ui-state.json',json_encode(['passed'=>true,'posted_proposal_has_journal_reference'=>true,'no_duplicate_apply_form'=>true],JSON_PRETTY_PRINT));echo "Posted proposal links its immutable journal and offers no second apply form.\n";exit; } if($phase==='ledger-demo-state'){ DB::beginTransaction();DB::statement('SET TRANSACTION READ ONLY');try{ if($financialFingerprint()!==$g['financial_fingerprint']||DB::table('gl_journals')->count()||DB::table('gl_proposals')->count())throw new LogicException('Team fixture must be pristine and separate from regression'); file_put_contents($s['root'].'/ledger-demo-state.json',json_encode(['passed'=>true,'read_only'=>true,'financial_fingerprint_equal'=>true,'journals'=>0,'proposals'=>0,'ready_for_team_workflow'=>true,'qa_grants'=>DB::table('permission_grants')->where('permission','like','general_ledger.%')->count()],JSON_PRETTY_PRINT)); }finally{DB::rollBack();}echo "Independent team fixture retains one recognised source and no proposals/journals.\n";exit; } if($phase==='ledger-integrity'){ $data=$ledger->listing($enter('prepare'),['period_key'=>'QA-2026-10']);$html=view('accounting.general-ledger',['data'=>$data])->render(); if(!str_contains($html,'Fotografia imutável da origem, regra e período aplicados')||str_contains($html,'data-action="post"')||$data['totals']!==['debit_minor'=>6000,'credit_minor'=>6000,'net_minor'=>0])throw new LogicException('Final interface or totals differ'); DB::beginTransaction();DB::statement('SET TRANSACTION READ ONLY');try{ $definition=DB::selectOne("SELECT pg_get_functiondef('gl_assert_balanced(bigint)'::regprocedure) AS definition")->definition; $trigger=DB::selectOne("SELECT tgdeferrable,tginitdeferred FROM pg_trigger WHERE tgname='gl_balanced_journal' AND tgrelid='gl_journals'::regclass"); if(!$trigger->tgdeferrable||!$trigger->tginitdeferred||!str_contains($definition,'GL_REVIEW_OR_SOURCE_MISMATCH')||$financialFingerprint()!==$g['financial_fingerprint'])throw new LogicException('Final schema/source proof differs'); $names=DB::getSchemaBuilder()->getTableListing();$notExercised=['stock'=>!array_filter($names,fn($n)=>str_contains($n,'stock_movements')),'budget'=>!array_filter($names,fn($n)=>str_contains($n,'budget_entries'))]; file_put_contents($s['root'].'/ledger-integrity.json',json_encode(['passed'=>true,'balance_function_sha256'=>hash('sha256',$definition),'deferred_balance_constraint'=>true,'review_source_account_checks_in_database'=>true,'final_blade_rendered'=>true,'financial_fingerprint_equal'=>true,'absent_domain_tables_not_exercised'=>$notExercised],JSON_PRETTY_PRINT|JSON_THROW_ON_ERROR)); }finally{DB::rollBack();}echo "Final schema balance/review guards, immutable source display and original financial fingerprint verified.\n";exit; } if($phase==='ledger-http-input'){ $race=json_decode(file_get_contents($s['root'].'/ledger-race.json'),true,64,JSON_THROW_ON_ERROR); $prepareKey=DB::table('gl_commands')->where('actor_id',$f['actors']['prepare'])->where('result->state','prepared')->value('command_key');$reviewKey=DB::table('gl_commands')->where('actor_id',$f['actors']['validate'])->where('result->state','approved')->value('command_key'); file_put_contents($s['root'].'/ledger-http-input.json',json_encode(['prepare'=>['key'=>$prepareKey,'body'=>$g['body']],'validate'=>['key'=>$reviewKey,'body'=>['proposal_id'=>$race['proposal_id'],'revision'=>$race['revision'],'decision'=>'approved','reason'=>'Independent exact version for concurrency.']],'post'=>['key'=>$race['post_key'],'body'=>$race['post_body']],'journal_id'=>$race['journal_id']],JSON_PRETTY_PRINT|JSON_THROW_ON_ERROR));echo "Private recovery inputs prepared from existing receipts.\n";exit; } if($phase==='ledger-post'){ DB::beginTransaction();DB::statement('SET TRANSACTION READ ONLY');try{ if($financialFingerprint()!==$g['financial_fingerprint']||DB::table('gl_journals')->count()!==1||DB::table('gl_lines')->count()!==2||DB::table('gl_reviews')->where('decision','approved')->count()!==1||DB::table('gl_events')->where('kind','journal.posted')->count()!==1)throw new LogicException('Ledger preservation or single effect differs'); DB::select('SELECT gl_assert_balanced(id) FROM gl_journals'); $j=DB::table('gl_journals')->first();file_put_contents($s['root'].'/ledger-post.json',json_encode(['passed'=>true,'read_only'=>true,'financial_fingerprint_equal'=>true,'financial_fingerprint'=>$g['financial_fingerprint'],'journals'=>1,'lines'=>2,'debit_minor'=>(int)$j->debit_minor,'credit_minor'=>(int)$j->credit_minor,'posting_events'=>1,'synthetic_rights_only'=>true,'default_flag'=>(require $c['root'].'/config/general_ledger.php')['synthetic_enabled']],JSON_PRETTY_PRINT|JSON_THROW_ON_ERROR)); }finally{DB::rollBack();}echo "Final ledger: one balanced journal, two lines, one posting event; financial source and rights unchanged.\n";exit; } throw new LogicException('Unknown ledger phase');