Files
SGF/scripts/sgf-workshop-equipment-orders-proof.php
T
2026-11-11 09:00:17 +02:00

13 lines
6.3 KiB
PHP

<?php
use Illuminate\Support\Facades\Auth;use Illuminate\Support\Str;use App\Shared\Context\CompanyContext;use App\Modules\Workshop\{WorkshopOrderRead,WorkshopWorkflow};
require __DIR__.'/sgf-ledger-proof-bootstrap.php';
set_exception_handler(function($e){echo json_encode(['passed'=>false,'type'=>get_class($e),'message'=>$e->getMessage()]).PHP_EOL;exit(1);});
$select=function($role)use($profiles,$f,$app){Auth::forgetGuards();Auth::shouldUse('web');$u=App\Models\User::findOrFail($profiles[$role]['user_id']);Auth::guard('web')->setUser($u);$r=Illuminate\Http\Request::create('/api/workshop/orders','GET');$r->attributes->set('sgf_module','workshop');$r->setUserResolver(fn()=>$u);$session=app('session')->driver();$session->start();$session->put('company_context',$f['scope']+['module_id'=>'workshop','token'=>'orders-'.$role]);$r->setLaravelSession($session);$app->instance('request',$r);app(CompanyContext::class)->selectFor($u->id,1,2,2);return $u->id;};
$reject=function($fn,$status,$name)use($ok){$actual=null;try{$fn();}catch(Symfony\Component\HttpKernel\Exception\HttpExceptionInterface$e){$actual=$e->getStatusCode();}catch(Illuminate\Validation\ValidationException){$actual=422;}$ok($actual===$status,$name);};
config(['workshop_catalogue.enabled'=>true]);
$before=[];foreach(['wo_equipment','wo_orders','wo_entries','wo_decisions','wo_commands','wo_events','permission_grants']as$t)$before[$t]=$host->table($t)->orderBy('id')->get()->toJson();$host->beginTransaction();try{
$actor=$select('workshop_manage');$reader=app(WorkshopOrderRead::class);$template=(array)$host->table('wo_orders')->where($f['scope'])->first();unset($template['id']);$equipment=(array)$host->table('wo_equipment')->find($template['equipment_id']);$equipmentId=$equipment['id'];unset($equipment['id']);$prefix='QA-EQUIPMENT-'.Str::uuid();$equipment['identifier']=$prefix;$equipment['description']='Fixture de consulta, não cadastro pelo workflow';$equipment['actor_id']=$actor;$otherEquipment=$host->table('wo_equipment')->insertGetId($equipment);$ids=[];for($i=0;$i<27;$i++)$ids[]=$host->table('wo_orders')->insertGetId(array_replace($template,['reference'=>$prefix.'-'.$i,'created_at'=>'2026-11-10 12:00:00+00']));$otherOrder=$host->table('wo_orders')->insertGetId(array_replace($template,['reference'=>$prefix.'-OTHER','equipment_id'=>$otherEquipment,'created_at'=>'2026-11-10 12:00:00+00']));$query=['equipment_id'=>$equipmentId,'search'=>$prefix];$p1=$reader->listing($actor,$query+['per_page'=>25]);$p2=$reader->listing($actor,$query+['per_page'=>25,'page'=>2]);$p100=$reader->listing($actor,$query+['per_page'=>100]);$ok($p1['orders']->total()===27&&count($p1['orders']->items())===25&&count($p2['orders']->items())===2,'equipment filter before pagination25+2');$ok(array_merge($p1['orders']->pluck('id')->all(),$p2['orders']->pluck('id')->all())===$p100['orders']->pluck('id')->all(),'ordered equipment pages equal100');$ok($p100['orders']->getCollection()->every(fn($r)=>$r->equipment_id===$equipmentId)&&!in_array($otherOrder,$p100['orders']->pluck('id')->all(),true),'sibling equipment order excluded');$ok($p1['equipment']['id']===$equipmentId&&isset($p1['equipment']['client_name']),'current selected equipment metadata explicit');$period=$reader->listing($actor,$query+['from'=>'2026-11-10','to'=>'2026-11-10','state'=>'open']);$ok($period['orders']->total()===27&&$period['equipment']['id']===$equipmentId,'equipment combines period state and search');$empty=$reader->listing($actor,$query+['from'=>'2099-01-01','to'=>'2099-01-01']);$ok($empty['orders']->total()===0&&$empty['equipment']['id']===$equipmentId,'empty period retains selected equipment without fallback');$all=$reader->listing($actor,['search'=>$prefix]);$ok($all['orders']->total()===28&&$all['equipment']===null,'unfiltered old list still includes both equipment sources');$far=$reader->listing($actor,$query+['page'=>100000]);$ok($far['orders']->items()===[]&&$far['equipment']['id']===$equipmentId,'far page no different equipment fallback');$reject(fn()=>$reader->listing($actor,['equipment_id'=>2147483647]),403,'foreign or unavailable equipment refused');$reject(fn()=>$reader->listing($actor,['equipment_id'=>0]),422,'invalid equipment identifier refused');$reject(fn()=>$reader->listing($actor,$query+['tenant_id'=>2]),422,'scope override refused');
$techId=$profiles['workshop_record']['user_id'];$add=function($order)use($host,$actor,$techId){$revision=(int)$host->selectOne('SELECT sgf_wo_revision(?) v',[$order])->v;$host->table('wo_entries')->insert(['order_id'=>$order,'kind'=>'assignment','origin'=>(string)Str::uuid(),'version'=>1,'revision'=>$revision,'outside_authority'=>false,'technician_id'=>$techId,'data'=>json_encode(['policy'=>WorkshopWorkflow::POLICY,'description'=>'Fixture de atribuição apenas para consulta']),'actor_id'=>$actor,'created_at'=>now()]);};$add($ids[0]);$tech=$select('workshop_record');$visible=$reader->listing($tech,$query);$ok($visible['orders']->total()===1&&$visible['orders']->items()[0]->id===$ids[0],'technician equipment view shows only its assigned order');$reject(fn()=>$reader->listing($tech,['equipment_id'=>$otherEquipment]),403,'unassigned equipment hidden from technician before counts');$actor=$select('workshop_manage');$add($otherOrder);$tech=$select('workshop_record');$now=$reader->listing($tech,['equipment_id'=>$otherEquipment]);$ok($now['orders']->total()===1&&$now['equipment']['id']===$otherEquipment,'new observed assignment grants only original permitted read scope');$actor=$select('workshop_manage');config(['workshop_catalogue.enabled'=>false]);$reject(fn()=>$reader->listing($actor,$query),404,'disabled catalogue cannot resolve hidden equipment');config(['workshop_catalogue.enabled'=>true]);request()->attributes->set('sgf_module','finance');$reject(fn()=>$reader->listing($actor,$query),403,'wrong module cannot read equipment orders');
}finally{while($host->transactionLevel()>0)$host->rollBack();}
foreach($before as$t=>$json)$ok($host->table($t)->orderBy('id')->get()->toJson()===$json,'original '.$t.' unchanged');file_put_contents($work.'/equipment-orders-result.json',json_encode(['passed'=>true,'checks'=>$checks,'sql_fixture_orders'=>28,'sql_fixture_equipment'=>1,'fixtures_rolled_back'=>true,'business_commands'=>0,'new_rights'=>0],JSON_PRETTY_PRINT));echo json_encode(['passed'=>true,'checks'=>count($checks),'proof'=>$work.'/equipment-orders-result.json']).PHP_EOL;