authorizeSupplyChain('supplychain.rfq.view'); $businessId = $this->supplyChainUtil->getBusinessId(); if ($request->ajax()) { $rfqs = RfqRequest::forBusiness($businessId) ->withCount(['lines', 'responses']) ->orderByDesc('id'); return DataTables::of($rfqs) ->editColumn('due_date', fn ($row) => $row->due_date?->format('Y-m-d') ?? '—') ->addColumn('status_badge', function ($row) { $class = $this->supplyChainUtil->rfqStatusBadgeClass($row->status); return ''.__('supplychain::lang.rfq_status_'.$row->status).''; }) ->addColumn('action', function ($row) { return ''; }) ->rawColumns(['status_badge', 'action']) ->make(true); } return view('supplychain::rfq.index'); } public function create() { $this->authorizeSupplyChain('supplychain.rfq.create'); return view('supplychain::rfq.create', [ 'suppliers' => $this->supplyChainUtil->getSuppliersDropdown(), 'products' => $this->supplyChainUtil->getProductsDropdown(), ]); } public function store(Request $request) { $this->authorizeSupplyChain('supplychain.rfq.create'); $businessId = $this->supplyChainUtil->getBusinessId(); $data = $request->validate([ 'title' => 'required|string|max:255', 'due_date' => 'nullable|date', 'holding_entity_id' => 'nullable|integer', 'notes' => 'nullable|string', 'status' => 'nullable|in:draft,open', 'supplier_ids' => 'nullable|array', 'supplier_ids.*' => 'integer', 'lines' => 'required|array|min:1', 'lines.*.product_id' => 'required|integer', 'lines.*.variation_id' => 'nullable|integer', 'lines.*.qty' => 'required|numeric|min:0.0001', 'lines.*.specs' => 'nullable|string', ]); $rfq = $this->rfqService->create( $businessId, $data, $data['lines'], $data['supplier_ids'] ?? null, auth()->id() ); if (($data['status'] ?? 'draft') === 'open') { $this->rfqService->open($rfq); } return $this->supplyChainUtil->jsonOrRedirect( $request, true, __('supplychain::lang.rfq_created'), action([self::class, 'show'], $rfq->id) ); } public function show($id) { $this->authorizeSupplyChain('supplychain.rfq.view'); $businessId = $this->supplyChainUtil->getBusinessId(); $rfq = RfqRequest::forBusiness($businessId) ->with(['lines.product', 'lines.variation', 'responses.contact']) ->findOrFail($id); return view('supplychain::rfq.show', [ 'rfq' => $rfq, 'suppliers' => $this->supplyChainUtil->getSuppliersDropdown(), ]); } public function open(Request $request, $id) { $this->authorizeSupplyChain('supplychain.rfq.update'); $businessId = $this->supplyChainUtil->getBusinessId(); $rfq = RfqRequest::forBusiness($businessId)->findOrFail($id); $this->rfqService->open($rfq); return $this->supplyChainUtil->jsonOrRedirect($request, true, __('supplychain::lang.rfq_opened')); } public function close(Request $request, $id) { $this->authorizeSupplyChain('supplychain.rfq.update'); $businessId = $this->supplyChainUtil->getBusinessId(); $rfq = RfqRequest::forBusiness($businessId)->findOrFail($id); $this->rfqService->close($rfq); return $this->supplyChainUtil->jsonOrRedirect($request, true, __('supplychain::lang.rfq_closed')); } public function submitResponse(Request $request, $id) { $this->authorizeSupplyChain('supplychain.rfq.update'); $businessId = $this->supplyChainUtil->getBusinessId(); $rfq = RfqRequest::forBusiness($businessId)->findOrFail($id); $data = $request->validate([ 'contact_id' => 'required|integer', 'quoted_price' => 'required|numeric|min:0', 'lead_days' => 'required|integer|min:0', 'notes' => 'nullable|string', ]); $this->rfqService->submitResponse( $rfq, (int) $data['contact_id'], (float) $data['quoted_price'], (int) $data['lead_days'], $data['notes'] ?? null ); return $this->supplyChainUtil->jsonOrRedirect($request, true, __('supplychain::lang.response_submitted')); } public function award(Request $request, $id) { $this->authorizeSupplyChain('supplychain.rfq.update'); $businessId = $this->supplyChainUtil->getBusinessId(); $rfq = RfqRequest::forBusiness($businessId)->findOrFail($id); $data = $request->validate(['contact_id' => 'required|integer']); $this->rfqService->award($rfq, (int) $data['contact_id']); return $this->supplyChainUtil->jsonOrRedirect($request, true, __('supplychain::lang.rfq_awarded')); } public function createFromMrp(Request $request) { $this->authorizeSupplyChain('supplychain.rfq.create'); $businessId = $this->supplyChainUtil->getBusinessId(); $data = $request->validate([ 'mrp_run_id' => 'required|integer', 'supplier_ids' => 'nullable|array', 'supplier_ids.*' => 'integer', ]); $rfqId = $this->integrationService->createRfqFromMrpRun( $businessId, (int) $data['mrp_run_id'], $data['supplier_ids'] ?? null ); if (! $rfqId) { return $this->supplyChainUtil->jsonOrRedirect($request, false, __('supplychain::lang.mrp_rfq_failed')); } return $this->supplyChainUtil->jsonOrRedirect( $request, true, __('supplychain::lang.rfq_created'), action([self::class, 'show'], $rfqId) ); } }