hasFunctions(['requester','procurement','finance','department_head'])&&RequisitionAccess::allowed($id,$binding),403); return Requisition::visibleTo($actor)->find($id)??abort(403,'Requisição fora do contexto autorizado.'); } private function page($query,array $columns,string $name,array $input):array { $page=$query->orderBy('id')->paginate(25,$columns,$name,(int)($input[$name]??1)); return ['accessible'=>true,'data'=>$page->items(),'pagination'=>['page'=>$page->currentPage(),'last_page'=>$page->lastPage(),'total'=>$page->total(),'per_page'=>25]]; } public function screen(Request $r,ReceiptRuntime $runtime) { $this->guard();$runtime->run('purchasing_requests.view',function($a){abort_unless($a->hasFunctions(['requester','procurement','finance','department_head']),403);}); return response()->view('purchasing-dossier',['context'=>$r->session()->get('company_context.token')]); } public function index(Request $r,ReceiptRuntime $runtime) { $this->guard();$d=$r->validate(['page'=>'sometimes|integer|min:1|max:10000','status'=>'sometimes|in:draft,pending,approved,rejected','search'=>'sometimes|string|max:100']);abort_if(array_diff(array_keys($r->query()),array_keys($d)),422); return $runtime->run('purchasing_requests.view',function($a,$b)use($d){abort_unless($a->hasFunctions(['requester','procurement','finance','department_head']),403);$q=Requisition::visibleTo($a)->whereIn('id',RequisitionAccess::ids($b));if(isset($d['status']))$q->where('status',$d['status']);if(isset($d['search']))$q->whereRaw('position(lower(?) in lower(number))>0',[$d['search']]);return response()->json($q->orderBy('id')->paginate(25,['id','number','status','process_version'],'page',(int)($d['page']??1)))->header('Cache-Control','no-store');}); } public function show(int $id,Request $r,ReceiptRuntime $runtime) { $this->guard();$rules=[];foreach(['quotes','awards','orders','receipts','invoices','obligations','events']as$key)$rules[$key.'_page']='sometimes|integer|min:1|max:10000';$d=$r->validate($rules);abort_if(array_diff(array_keys($r->query()),array_keys($d)),422); $host=DB::connection();$c=app(\App\Shared\Context\CompanyContext::class);$scope=$c->identifiers()+['unit_id'=>$c->unitId(),'user_id'=>$c->userId()]; return $runtime->run('purchasing_requests.view',function($a,$b,$fingerprint)use($id,$d,$host,$scope){ $request=$this->source($id,$b,$a);$allowed=[]; foreach(['sourcing','orders','receipts','invoices','obligations']as$stage){$flag=$stage==='receipts'?'enabled':$stage.'_enabled';$allowed[$stage]=config('receipt_qa.'.$flag)===true&&$host->table('permission_grants')->where($scope)->where('permission','purchasing_'.$stage.'.view')->lockForUpdate()->first()!==null;} $viewer=$a->hasFunctions(['admin','procurement','finance','department_head']);$finance=$a->hasFunctions(['admin','finance']);$allowed['sourcing']=$allowed['sourcing']&&$viewer;$allowed['orders']=$allowed['orders']&&$viewer;$allowed['receipts']=$allowed['receipts']&&Gate::allows('viewAny',GoodsReceipt::class);$allowed['invoices']=$allowed['invoices']&&$finance;$allowed['obligations']=$allowed['obligations']&&$finance; $orders=fn()=>PurchaseOrder::where('tenant_id',$a->tenant_id)->where('requisition_id',$id)->select('id'); $invoices=fn()=>Invoice::where('tenant_id',$a->tenant_id)->whereIn('purchase_order_id',$orders()); $restricted=['accessible'=>false];$stages=['quotes'=>$restricted,'awards'=>$restricted,'orders'=>$restricted,'receipts'=>$restricted,'invoices'=>$restricted,'obligations'=>$restricted];$patterns=['requisition.%','sgf.request.command']; if($allowed['sourcing']){$stages['quotes']=$this->page(Quotation::where('requisition_id',$id),['id','reference','supplier_id','total_minor','created_by','created_at'],'quotes_page',$d);$stages['awards']=$this->page(PurchaseAward::where('requisition_id',$id),['id','quotation_id','status','total_minor','created_by','created_at'],'awards_page',$d);array_push($patterns,'quotation.%','award.%','sgf.sourcing.command');} if($allowed['orders']){$stages['orders']=$this->page(PurchaseOrder::visibleTo($a)->where('requisition_id',$id),['id','number','status','total_minor','issued_by','issued_at'],'orders_page',$d);array_push($patterns,'order.%','sgf.order.command');} if($allowed['receipts']){$stages['receipts']=$this->page(GoodsReceipt::whereIn('purchase_order_id',$orders()),['id','number','purchase_order_id','status','received_on','received_by','confirmed_at'],'receipts_page',$d);array_push($patterns,'receipt.%','sgf.receipt.command','sgf.receipt.document','sgf.receipt.document_downloaded');} if($allowed['invoices']){$stages['invoices']=$this->page($invoices(),['id','number','purchase_order_id','status','total_minor','created_by','validated_by','validated_at'],'invoices_page',$d);array_push($patterns,'invoice.%','sgf.invoice.command');} if($allowed['obligations']){ $service=app(SupplierPayables::class);$service->readContext($a); // The window is on source invoices, not the complete financial universe. $window=$invoices()->orderBy('id')->paginate(25,['id'],'obligations_page',(int)($d['obligations_page']??1)); $positions=$service->engine($a)->positionsPage($window->getCollection()->pluck('id')->map(fn($v)=>(int)$v)->all()); $stages['obligations']=['accessible'=>true,'data'=>$positions['obligations'],'pagination'=>['page'=>$window->currentPage(),'last_page'=>$window->lastPage(),'total_sources'=>$window->total(),'per_page'=>25],'source_window'=>true];$patterns[]='sgf.obligation.command'; } $events=AuditLog::where('requisition_id',$id)->where(function($q)use($patterns){foreach($patterns as$pattern)$q->orWhere('action','like',$pattern);});$history=$this->page($events,['id','user_id','action','created_at'],'events_page',$d); $view=['request'=>$request->only(['id','number','status','process_version','requester_id','total_minor']),'stages'=>$stages,'events'=>$history,'read_only'=>true,'revision_scope'=>'visible_pages_only']; $view=app(ProcessNavigation::class)->decorate($view,$allowed,$id); $view['view_revision']=hash('sha256',Payables::canonical([$fingerprint,$view])); return response()->json($view)->header('Cache-Control','no-store'); }); } }