authorizeMaintenanceAccess('maintenance.materials.view'); $business = $this->maintenanceUtil->getBusiness(); $list = $this->materialService->getOrCreateList($business, $sourceType, $sourceId, auth()->user()); $panelData = $this->materialService->getPanelData($business, $sourceType, $sourceId, auth()->user()); return view('maintenance::materials.panel', array_merge($panelData, [ 'spare_parts' => $this->maintenanceUtil->getSparePartsDropdown($business->id), 'can_manage' => auth()->user()->can('maintenance.materials.manage'), 'can_procure' => auth()->user()->can('maintenance.materials.procure'), ])); } public function updateDestination(Request $request, string $sourceType, int $sourceId) { $this->authorizeMaintenanceAccess('maintenance.materials.manage'); $business = $this->maintenanceUtil->getBusiness(); $list = $this->materialService->getOrCreateList($business, $sourceType, $sourceId); $data = $request->validate([ 'destination_location_id' => 'nullable|integer|exists:business_locations,id', ]); $this->materialService->updateDestination($list, $data['destination_location_id'] ?? null); return $this->maintenanceUtil->jsonOrRedirect($request, true, __('maintenance::lang.mat_destination_updated')); } public function storeLine(Request $request, string $sourceType, int $sourceId) { $this->authorizeMaintenanceAccess('maintenance.materials.manage'); $business = $this->maintenanceUtil->getBusiness(); $list = $this->materialService->getOrCreateList($business, $sourceType, $sourceId); $data = $request->validate([ 'spare_part_id' => 'nullable|exists:maintenance_spare_parts,id', 'part_name' => 'nullable|string|max:255', 'line_type' => 'nullable|in:supply,repair', 'quantity_required' => 'required|numeric|min:0.001', 'notes' => 'nullable|string', ]); try { $this->materialService->addLine($list, $data); } catch (\InvalidArgumentException $e) { return $this->maintenanceUtil->jsonOrRedirect($request, false, $e->getMessage()); } return $this->maintenanceUtil->jsonOrRedirect($request, true, __('maintenance::lang.mat_line_added')); } public function destroyLine(Request $request, int $lineId) { $this->authorizeMaintenanceAccess('maintenance.materials.manage'); $business_id = $this->maintenanceUtil->getBusinessId(); $line = MaterialLine::where('business_id', $business_id)->findOrFail($lineId); try { $this->materialService->deleteLine($line); } catch (\InvalidArgumentException $e) { return $this->maintenanceUtil->jsonOrRedirect($request, false, $e->getMessage()); } return $this->maintenanceUtil->jsonOrRedirect($request, true, __('maintenance::lang.mat_line_deleted')); } public function importBom(Request $request, string $sourceType, int $sourceId) { $this->authorizeMaintenanceAccess('maintenance.materials.manage'); $business = $this->maintenanceUtil->getBusiness(); $list = $this->materialService->getOrCreateList($business, $sourceType, $sourceId); $equipmentId = $request->input('equipment_id') ?: $this->materialService->resolveEquipmentId($sourceType, $sourceId, $business->id); if (! $equipmentId) { return $this->maintenanceUtil->jsonOrRedirect($request, false, __('maintenance::lang.mat_no_equipment')); } $count = $this->materialService->importFromEquipmentBom($list, (int) $equipmentId); return $this->maintenanceUtil->jsonOrRedirect( $request, true, __('maintenance::lang.mat_bom_imported', ['count' => $count]) ); } public function requestTransfer(Request $request, int $lineId) { $this->authorizeMaintenanceAccess('maintenance.materials.procure'); $business = $this->maintenanceUtil->getBusiness(); $line = MaterialLine::where('business_id', $business->id)->with('materialList')->findOrFail($lineId); $data = $request->validate([ 'source_location_id' => 'required|integer|exists:business_locations,id', 'quantity' => 'required|numeric|min:0.001', ]); try { $procurement = $this->materialService->requestTransfer( $line->materialList, $line, (int) $data['source_location_id'], (float) $data['quantity'], auth()->user() ); } catch (\InvalidArgumentException $e) { return $this->maintenanceUtil->jsonOrRedirect($request, false, $e->getMessage()); } $ref = $procurement->meta['ref_no'] ?? ''; return $this->maintenanceUtil->jsonOrRedirect( $request, true, __('maintenance::lang.mat_transfer_created', ['ref' => $ref]) ); } public function createPurchaseRequisition(Request $request, string $sourceType, int $sourceId) { $this->authorizeMaintenanceAccess('maintenance.materials.procure'); $business = $this->maintenanceUtil->getBusiness(); $list = $this->materialService->getOrCreateList($business, $sourceType, $sourceId); $data = $request->validate([ 'lines' => 'required|array|min:1', 'lines.*.line_id' => 'required|integer', 'lines.*.supplier_id' => 'nullable|integer', 'lines.*.quantity' => 'nullable|numeric|min:0.001', ]); try { $transaction = $this->materialService->createPurchaseRequisition( $list, $data['lines'], auth()->user() ); } catch (\InvalidArgumentException $e) { return $this->maintenanceUtil->jsonOrRedirect($request, false, $e->getMessage()); } return $this->maintenanceUtil->jsonOrRedirect( $request, true, __('maintenance::lang.mat_requisition_created', ['ref' => $transaction->ref_no]) ); } public function createPurchaseOrders(Request $request, string $sourceType, int $sourceId) { $this->authorizeMaintenanceAccess('maintenance.materials.procure'); $business = $this->maintenanceUtil->getBusiness(); $list = $this->materialService->getOrCreateList($business, $sourceType, $sourceId); $data = $request->validate([ 'lines' => 'required|array|min:1', 'lines.*.line_id' => 'required|integer', 'lines.*.supplier_id' => 'required|integer', 'lines.*.quantity' => 'nullable|numeric|min:0.001', ]); try { $orders = $this->materialService->createPurchaseOrders( $list, $data['lines'], auth()->user() ); } catch (\InvalidArgumentException $e) { return $this->maintenanceUtil->jsonOrRedirect($request, false, $e->getMessage()); } $refs = $orders->pluck('ref_no')->implode(', '); return $this->maintenanceUtil->jsonOrRedirect( $request, true, __('maintenance::lang.mat_po_created', ['refs' => $refs]) ); } public function supplierSuggestions(int $lineId) { $this->authorizeMaintenanceAccess('maintenance.materials.view'); $business_id = $this->maintenanceUtil->getBusinessId(); $line = MaterialLine::where('business_id', $business_id)->findOrFail($lineId); if (! $line->variation_id) { return response()->json(['success' => true, 'data' => []]); } $suggestions = $this->suggestionService->suggestSuppliers($business_id, (int) $line->variation_id); return response()->json(['success' => true, 'data' => $suggestions]); } }