user('web'); abort_unless($actor instanceof User && $actor->hasFunctions(['admin', 'supply_read', 'supply_prepare', 'supply_review']), 403); $prepare = app(SupplyPlanning::class)->allows($actor, 'supply_prepare'); $ready = $service->ready(); $planning = app(SupplyPlanning::class); $filters = $request->validate(['rule_id' => ['nullable', 'integer', 'min:1', Rule::exists('supply_records', 'id')->where('tenant_id', $actor->tenant_id)->where('kind', 'auto_rule')], 'need_state' => 'nullable|in:all,pending,created,covered,satisfied', 'rules_page' => 'nullable|integer|min:1|max:1000000', 'needs_page' => 'nullable|integer|min:1|max:1000000', 'history_page' => 'nullable|integer|min:1|max:1000000', 'work_page' => 'nullable|integer|min:1|max:1000000']); $focus = isset($filters['rule_id']) ? SupplyRecord::query()->where('kind', 'auto_rule')->findOrFail((int) $filters['rule_id']) : null; $rules = $planning->latest('auto_rule')->when($focus !== null, fn ($query) => $query->where('record_key', $focus->record_key)); $latestFocus = $focus === null ? null : (clone $rules)->first(); $needs = $planning->latest('auto_need'); if (($filters['need_state'] ?? 'all') !== 'all') { $needs->where('state', $filters['need_state']); } Inertia::encryptHistory(); $response = Inertia::render('stock/replenishment', [ 'ready' => $ready, 'canPrepare' => $prepare, 'canReview' => $planning->allows($actor, 'supply_review'), 'filters' => ['need_state' => $filters['need_state'] ?? 'all'], 'focusRuleId' => $focus->id ?? null, 'focusChanged' => $focus !== null && $latestFocus?->id !== $focus->id, 'rules' => $ready ? $rules->latest('id')->paginate(20, ['*'], 'rules_page')->withQueryString()->through(fn (SupplyRecord $rule) => [...$rule->toArray(), 'canApprove' => $service->canReview($actor, $rule), 'canSuspend' => $service->canReview($actor, $rule, 'suspend')]) : null, 'needs' => $ready ? $needs->orderByRaw("CASE WHEN state = 'pending' THEN 0 ELSE 1 END")->oldest('id')->paginate(20, ['*'], 'needs_page')->withQueryString() : null, 'history' => $ready ? SupplyRecord::query()->whereIn('kind', ['auto_rule', 'auto_need'])->latest('id')->paginate(30, ['*'], 'history_page')->withQueryString() : null, ...app(ReplenishmentQueue::class)->status($actor), 'workItems' => app(ReplenishmentQueue::class)->ready() ? DB::table('replenishment_work as w')->join('stock_items as i', 'i.id', '=', 'w.stock_item_id')->join('warehouses as a', 'a.id', '=', 'w.warehouse_id')->where('w.tenant_id', $actor->tenant_id)->where('i.tenant_id', $actor->tenant_id)->where('a.tenant_id', $actor->tenant_id)->where(fn ($q) => $q->whereColumn('w.generation', '>', 'w.processed_generation')->orWhere('w.failures', '>', 0))->orderBy('w.due_at')->orderBy('w.id')->paginate(20, ['w.id', 'i.code', 'i.name', 'a.name as warehouse', 'w.last_error', 'w.due_at', 'w.failures'], 'work_page')->withQueryString() : null, 'policies' => Schema::hasTable('supply_records') && $prepare ? $planning->latest('policy')->where('state', 'approved')->where('data->purpose', 'internal')->get() : [], 'requesters' => $prepare ? User::query()->where('tenant_id', $actor->tenant_id)->get(['id', 'name', 'department_id', 'purchasing_role', 'tenant_id'])->filter(fn ($u) => $service->eligibleRequester($u))->map(fn ($u) => $u->only(['id', 'name', 'department_id']))->values() : [], 'centers' => $prepare ? CostCenter::query()->orderBy('code')->get(['id', 'department_id', 'code', 'name']) : [], 'equipment' => $prepare ? Equipment::query()->orderBy('code')->get(['id', 'code', 'description', 'department_id']) : [], 'catalogueTypes' => $prepare && Schema::hasTable('requisition_catalogue') ? DB::table('requisition_catalogue')->where('tenant_id', $actor->tenant_id)->where('published', true)->pluck('purchase_type', 'stock_item_id') : [], ])->toResponse($request); $response->headers->set('Cache-Control', 'private, no-store, max-age=0'); return $response; } public function save(Request $request, AutomaticPurchases $service): RedirectResponse { $service->save($request->user('web'), $request->all()); return redirect('/stock/reposicao'); } public function evaluate(Request $request, int $id, AutomaticPurchases $service): RedirectResponse { $actor = $request->user('web'); abort_unless($actor instanceof User && ($actor->hasFunctions(['supply_prepare', 'supply_review'])) && ! app(OrganizationAccess::class)->maintenanceOnly($actor), 403); $need = SupplyRecord::query()->where('kind', 'auto_need')->findOrFail($id); if (app(ReplenishmentQueue::class)->ready()) { $service->signal($actor, $need->stock_item_id, $need->warehouse_id); } else { $service->evaluate($actor, $need->stock_item_id, $need->warehouse_id); } return redirect('/stock/reposicao'); } public function recover(Request $request, int $id, AutomaticPurchases $service): RedirectResponse { $actor = $request->user('web'); abort_unless($actor instanceof User && $actor->hasFunctions(['supply_prepare', 'supply_review']) && ! app(OrganizationAccess::class)->maintenanceOnly($actor), 403); $work = DB::table('replenishment_work')->where('tenant_id', $actor->tenant_id)->where('id', $id)->firstOrFail(); $service->signal($actor, $work->stock_item_id, $work->warehouse_id); return redirect('/stock/reposicao'); } }