Files
SGF/scripts/ledger-cost-coexistence.php
2026-11-04 09:37:20 +02:00

17 lines
6.1 KiB
PHP

<?php
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use App\Modules\Purchasing\SupplierPayables;
use Tempo\Finance\Payables\Payables;
$output=$s['root'].'/cost-coexistence.json';if(file_exists($output)||DB::table('pa_obligations')->exists()||DB::table('gl_proposals')->exists())throw new LogicException('Fresh mixed cost/supplier fixture required');$costBefore=app(App\Modules\Accounting\CostLedgerSource::class)->source($enter('read'),$g['order_id']);$outboxBefore=DB::table('dc_outbox')->orderBy('event_id')->get()->toJson();
DB::statement('CREATE TABLE pa_imported_sources(id bigserial PRIMARY KEY,tenant_id bigint,company_id bigint,unit_id bigint,payload jsonb,receipt_hash varchar(64))');$def=DB::selectOne("SELECT pg_get_constraintdef(oid) d FROM pg_constraint WHERE conrelid='permission_grants'::regclass AND conname='permission_grants_scope_check'")->d;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 ((".substr($def,6).") OR (unit_id IS NOT NULL AND permission='supplier_payables.view'))");
foreach(['prepare','validate','read'] as $role){$actor=$g['actors'][$role];Tests\Support\IdentityFixture::grant($actor,$scope['tenant_id'],$scope['company_id'],'supplier_payables.view',$scope['unit_id']);if($role!=='read')DB::table('pa_access')->insert($scope+['user_id'=>$actor,'action'=>$role==='prepare'?'prepare':'validate','person'=>'cost-qa-person-'.$actor]);}
$accounts=[];foreach(['QA-CONTRAPARTIDA','QA-FORNECEDOR'] as $code)$accounts[$code]=DB::table('gl_accounts')->insertGetId($scope+['code'=>$code,'label'=>'Conta artificial para coexistência com custo','is_movement'=>true,'currency'=>'MZN']);DB::table('gl_rules')->insert($scope+['created_by'=>$g['actors']['prepare'],'reason'=>'Explicit existing supplier60 rule alongside selected cost275.','created_at'=>now(),'rule_key'=>'QA-PAYABLE-JOURNAL','version'=>1,'policy'=>Tempo\Finance\GeneralLedger\PayableJournal::POLICY,'effect_type'=>'supplier_payable.recognised','currency'=>'MZN','valid_from'=>'2026-10-01','valid_to'=>'2026-10-31','debit_account_id'=>$accounts['QA-CONTRAPARTIDA'],'credit_account_id'=>$accounts['QA-FORNECEDOR']]);
$bundle=json_decode(file_get_contents($s['root'].'/source.json'),true,64,JSON_THROW_ON_ERROR);$doc=$bundle['source'];unset($doc['local_id']);$doc['document']=990002;$doc['number']='QA-COST-MIXED-SUPPLIER-60';$doc['payment_count']=0;$payload=Payables::canonical($doc);$local=DB::table('pa_imported_sources')->insertGetId($scope+['payload'=>$payload,'receipt_hash'=>hash('sha256',$payload)]);$payable=app(SupplierPayables::class);$p=$payable->engine($enter('prepare'))->command('prepare',$local,'Explicit controlled synthetic supplier receipt reused for integration regression.',(string)Str::uuid());$o=$payable->engine($enter('validate'))->command('validate',$p['proposal_id'],'Independent existing supplier60 recognition in separate integration fixture.',(string)Str::uuid());if($o['obligation_id']!==$g['order_id'])throw new LogicException('Fresh fixture must exercise coinciding supplier obligation/order IDs');
$post=function($p)use($command){$command('validate','validate',['proposal_id'=>$p['proposal_id'],'revision'=>$p['revision'],'decision'=>'approved','reason'=>'Independent exact typed source review.']);return $command('prepare','post',['proposal_id'=>$p['proposal_id'],'revision'=>$p['revision'],'reason'=>'Apply typed source once in shared synthetic book.']);};$cost=$post($command('prepare','effect-prepare',$body));$supplier=$post($command('prepare','prepare',['obligation_id'=>$o['obligation_id'],'journal_on'=>'2026-10-29','period_key'=>'QA-2026-10','rule_key'=>'QA-PAYABLE-JOURNAL','reason'=>'Capture approved supplier60 alongside independent technical cost275.']));
$costBook=$ledger->listing($enter('read'),['cost_order_id'=>$g['order_id']]);$supplierBook=$ledger->listing($enter('read'),['obligation_id'=>$o['obligation_id']]);$report=$ledger->report($enter('read'),'trial-balance',['from_on'=>'2026-10-01','to_on'=>'2026-10-31']);
if(count($costBook['journals'])!==1||count($costBook['events'])!==3||$costBook['totals']['debit_minor']!==27500||count($supplierBook['journals'])!==1||count($supplierBook['events'])!==3||$supplierBook['totals']['debit_minor']!==6000||$report['totals']['debit_minor']!==33500||DB::table('gl_journals')->count()!==2||DB::table('gl_lines')->count()!==4)throw new LogicException('Cost and supplier namespaces mixed or reports unreconciled');
$p=$command('prepare','period-prepare',['period_key'=>'QA-2026-10','reason'=>'Joint completeness of selected cost and independently recognised supplier effect.']);$command('validate','period-validate',['check_id'=>$p['check_id'],'revision'=>$p['revision'],'decision'=>'approved','reason'=>'Independent joint source conference.']);$command('prepare','period-close',['check_id'=>$p['check_id'],'revision'=>$p['revision'],'reason'=>'Close both source families once.']);
if(Payables::canonical(app(App\Modules\Accounting\CostLedgerSource::class)->source($enter('read'),$g['order_id']))!==Payables::canonical($costBefore)||DB::table('dc_outbox')->orderBy('event_id')->get()->toJson()!==$outboxBefore||$payable->engine($enter('read'))->positionForSource($local)['balance_minor']!==6000)throw new LogicException('Accounting changed authoritative cost/outbox or supplier balance');DB::select('SELECT gl_assert_balanced(id) FROM gl_journals');
file_put_contents($output,json_encode(['passed'=>true,'coinciding_order_supplier_obligation_ids'=>true,'one_writer'=>true,'cost_filter_journals'=>1,'cost_filter_events'=>3,'supplier_filter_journals'=>1,'supplier_filter_events'=>3,'journals'=>2,'lines'=>4,'debit_minor'=>33500,'credit_minor'=>33500,'actual_selected_cost_minor'=>27500,'supplier_balance_minor'=>6000,'cost_source_and_outbox_unchanged'=>true,'joint_qa_period_closed'=>true,'supplier_receipt_controlled_synthetic_not_live_import'=>true,'no_payment_or_stock_effect'=>true],JSON_PRETTY_PRINT|JSON_THROW_ON_ERROR));echo "Mixed cost/supplier book: coinciding IDs isolated,275+60=335MZN, two journals/four lines and one joint period close; authority preserved.\n";