ensurePortalAccess(); $contactId = $this->contactId(); $businessId = $this->businessId(); $rfqIds = RfqResponse::where('contact_id', $contactId) ->pluck('rfq_id'); $rfqs = RfqRequest::forBusiness($businessId) ->whereIn('id', $rfqIds) ->whereIn('status', ['open', 'awarded', 'closed']) ->with(['lines', 'responses' => fn ($q) => $q->where('contact_id', $contactId)]) ->latest('id') ->paginate(20); return view('supplychain::portal.rfq.index', compact('rfqs', 'contactId')); } public function show($id) { $this->ensurePortalAccess(); $contactId = $this->contactId(); $rfq = $this->findSupplierRfq((int) $id, $contactId); return view('supplychain::portal.rfq.show', compact('rfq', 'contactId')); } public function submitQuote($id, Request $request, RfqService $rfqService) { $this->ensurePortalAccess(); $contactId = $this->contactId(); $rfq = $this->findSupplierRfq((int) $id, $contactId); if ($rfq->status !== 'open') { return redirect()->back()->with('status', ['success' => 0, 'msg' => __('supplychain::lang.rfq_not_open')]); } $validated = $request->validate([ 'quoted_price' => 'required|numeric|min:0', 'lead_days' => 'required|integer|min:1', 'notes' => 'nullable|string|max:2000', ]); $rfqService->submitResponse( $rfq, $contactId, (float) $validated['quoted_price'], (int) $validated['lead_days'], $validated['notes'] ?? null ); return redirect()->action([self::class, 'show'], [$rfq->id]) ->with('status', ['success' => 1, 'msg' => __('supplychain::lang.portal_quote_submitted')]); } protected function findSupplierRfq(int $id, int $contactId): RfqRequest { $hasInvite = RfqResponse::where('rfq_id', $id) ->where('contact_id', $contactId) ->exists(); if (! $hasInvite) { abort(404); } return RfqRequest::forBusiness($this->businessId()) ->with(['lines', 'responses' => fn ($q) => $q->where('contact_id', $contactId)]) ->findOrFail($id); } }