Preserve verified 275 MZN and incomplete 175 MZN demonstrations. Keep 090000 and four real cost grants unapplied; real costing and fiscal blocks remain intact.
27 lines
4.5 KiB
PHP
27 lines
4.5 KiB
PHP
<?php
|
|
require __DIR__.'/../vendor/autoload.php';$app=require __DIR__.'/../bootstrap/app.php';$app->make(\Illuminate\Contracts\Console\Kernel::class)->bootstrap();
|
|
use App\Modules\Workshop\DirectCosts;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Str;
|
|
use Symfony\Component\Process\Process;
|
|
DirectCosts::guard();$f=json_decode(file_get_contents('C:/laragon/data/sgf-tempo/secrets/browser-fixture.json'),true,32,JSON_THROW_ON_ERROR);$fx=$f['direct_costs'];$proof=[];$key=fn()=>(string)Str::uuid();
|
|
$base=['tenant'=>$f['tenant'],'company'=>$f['company'],'unit'=>$f['unit'],'order'=>$fx['order']];
|
|
$pair=function($one,$two)use($base){
|
|
$a=new Process([PHP_BINARY,'scripts/direct-cost-worker.php','--env=testing'],base_path(),null,json_encode($one+$base+['pause'=>true]));$b=new Process([PHP_BINARY,'scripts/direct-cost-worker.php','--env=testing'],base_path(),null,json_encode($two+$base));
|
|
$a->start();if(!$a->waitUntil(fn($t,$v)=>str_contains($v,'LOCK_HELD')))throw new RuntimeException('Concurrent lock not observed.');$b->start();$a->wait();$b->wait();$out=[];
|
|
foreach([$a,$b] as $p){if(!$p->isSuccessful())throw new RuntimeException('Cost worker failed.');$lines=array_values(array_filter(explode("\n",trim($p->getOutput())),fn($v)=>str_starts_with($v,'{')));$out[]=json_decode(end($lines),true,32,JSON_THROW_ON_ERROR);}return $out;
|
|
};
|
|
$check=function($out,bool $replay){if($out[0]['status']!==200||$out[1]['status']!==($replay?200:409)||($replay&&(!$out[1]['result']['replayed']||$out[0]['result']['id']!==$out[1]['result']['id'])))throw new RuntimeException('Unexpected concurrent outcome.');};
|
|
$rate=['method'=>'rate','actor'=>$f['manager_id'],'key'=>$key(),'input'=>['entry_id'=>$fx['material'],'entry_version'=>1,'identifier'=>'TEST-CONCURRENT-'.Str::uuid(),'version'=>1,'previous_id'=>null,'currency'=>'MZN','unit'=>'UN','amount'=>'1','evidence'=>'Taxa sintética concorrente.']];
|
|
$out=$pair($rate,$rate);$check($out,true);$proof['rate_repetition_one_version']=true;$rid=$out[0]['result']['id'];
|
|
$decision=['method'=>'decide','actor'=>$f['reader_id'],'key'=>$key(),'input'=>['kind'=>'rate','id'=>$rid,'version'=>1,'decision'=>'approved','reason'=>'Validação sintética concorrente.']];$check($pair($decision,$decision),true);$proof['decision_repetition_one_effect']=true;
|
|
$one=$rate;$one['key']=$key();$one['input']['version']=2;$one['input']['previous_id']=$rid;$two=$one;$two['key']=$key();$two['input']['amount']='2';$check($pair($one,$two),false);$proof['competing_rate_versions_one_winner']=true;
|
|
$rates=DB::table('dc_rates')->where('order_id',$fx['order'])->whereIn('identifier',['TEST-TRABALHO','TEST-MATERIAL'])->get()->keyBy('identifier');
|
|
$lines=[['entry_id'=>$fx['time'],'entry_version'=>1,'rate_id'=>$rates['TEST-TRABALHO']->id,'rate_version'=>1],['entry_id'=>$fx['material'],'entry_version'=>1,'rate_id'=>$rates['TEST-MATERIAL']->id,'rate_version'=>1]];
|
|
$last=DB::table('dc_calculations')->where('order_id',$fx['order'])->orderByDesc('version')->first();
|
|
$calc=['method'=>'calculate','actor'=>$f['manager_id'],'key'=>$key(),'input'=>['currency'=>'MZN','version'=>$last->version+1,'previous_id'=>$last->id,'lines'=>$lines]];$out=$pair($calc,$calc);$check($out,true);$proof['calculation_repetition_one_snapshot']=true;
|
|
$last=DB::table('dc_calculations')->where('order_id',$fx['order'])->orderByDesc('version')->first();$calc['key']=$key();$calc['input']['version']=$last->version+1;$calc['input']['previous_id']=$last->id;$calc['input']['lines'][1]['rate_id']=null;$calc['input']['lines'][1]['rate_version']=null;$two=$calc;$two['key']=$key();$two['input']['lines']=$lines;$two['input']['lines'][0]['rate_id']=null;$two['input']['lines'][0]['rate_version']=null;$out=$pair($calc,$two);$check($out,false);$proof['competing_calculations_one_revision']=true;
|
|
$last=DB::table('dc_calculations')->where('order_id',$fx['order'])->orderByDesc('version')->first();$calc['key']=$key();$calc['input']['version']=$last->version+1;$calc['input']['previous_id']=$last->id;$calc['input']['lines']=$lines;
|
|
$oldDecision=['method'=>'decide','actor'=>$f['reader_id'],'key'=>$key(),'input'=>['kind'=>'calculation','id'=>$last->id,'version'=>$last->version,'decision'=>'approved','reason'=>'Decisão de uma versão agora antiga.']];$check($pair($calc,$oldDecision),false);$proof['new_calculation_refuses_old_approval']=true;
|
|
file_put_contents(base_path('docs/proofs/direct-cost-concurrency.json'),json_encode(['database'=>'sgf_tempo_test','overlapping_processes_per_case'=>2,'checks'=>$proof,'synthetic_only'=>true],JSON_PRETTY_PRINT|JSON_THROW_ON_ERROR));echo "Six overlapping-process direct cost scenarios passed.\n";
|