with(['user', 'supplier', 'stockEntries.statusHistory.status', 'files']); // Apply filters if provided if ($request->has('search')) { $search = $request->search; $query->whereHas('physicalItem', function($q) use ($search) { $q->where('name', 'like', "%{$search}%"); }); } // Sort $sortField = $request->input('sort_field', 'updated_at'); $sortDirection = $request->input('sort_direction', 'desc'); $query->orderBy($sortField, $sortDirection); // Paginate $perPage = $request->input('per_page', 10); $page = $request->input('page', 1); $entries = $query->paginate($perPage, ['*'], 'page', $page); return response()->json([ 'data' => $entries->items(), 'meta' => [ 'total' => $entries->total(), 'per_page' => $entries->perPage(), 'current_page' => $entries->currentPage(), 'last_page' => $entries->lastPage(), ], ]); } /** * Store a newly created stock batch, with multiple files. */ public function addData(Request $request) { try { $validator = Validator::make($request->all(), [ 'supplier_id' => 'nullable|integer', 'tracking_number' => 'nullable|string', 'arrival_date' => 'nullable|date', 'files.*' => 'file', 'file_types' => 'array', 'file_types.*' => 'in:invoice,label,other', ]); if ($validator->fails()) { return response()->json(['errors' => $validator->errors()], 422); } // create the batch $batch = StockBatch::create([ 'user_id' => auth()->id() ?? 1, 'supplier_id' => $request->input('supplier_id'), 'tracking_number' => $request->input('tracking_number'), 'arrival_date' => $request->input('arrival_date'), ]); // attach each uploaded file if ($request->hasFile('files')) { foreach ($request->file('files') as $i => $upload) { $batch->files()->create([ 'filename' => $upload->getClientOriginalName(), 'file_data' => file_get_contents($upload->getRealPath()), 'file_type' => $request->input("file_types.{$i}", 'other'), 'user_id' => auth()->id() ?? 1, ]); } } return response()->json([ 'message' => 'Stock batch created successfully', 'data' => $batch->load(['supplier', 'user', 'files', 'stockEntries']), ], 201); } catch (\Exception $e) { return response()->json(['errors' => $e->getMessage()], 500); } } /** * Display the specified stock batch, with its files & entries. */ public function show($id) { $batch = StockBatch::with(['user','supplier','files','stockEntries']) ->findOrFail($id); return response()->json(['data' => $batch]); } /** * Update the specified stock batch and optionally add new files. */ public function updateData(Request $request, $id) { $validator = Validator::make($request->all(), [ 'supplier_id' => 'nullable|integer|exists:supplier,id', 'tracking_number' => 'nullable|integer', 'arrival_date' => 'nullable|date', 'files.*' => 'file', 'file_types' => 'array', 'file_types.*' => 'in:invoice,label,other', ]); if ($validator->fails()) { return response()->json(['errors' => $validator->errors()], 422); } $batch = StockBatch::findOrFail($id); $batch->update($request->only(['supplier_id','tracking_number','arrival_date']) + [ 'updated_at' => now(), ]); // if there are new files, attach them if ($request->hasFile('files')) { foreach ($request->file('files') as $i => $upload) { $batch->files()->create([ 'filename' => $upload->getClientOriginalName(), 'file_data' => file_get_contents($upload->getRealPath()), 'file_type' => $request->input("file_types.{$i}", 'other'), 'user_id' => auth()->id() ?? 1, ]); } } return response()->json([ 'message' => 'Stock batch updated successfully', 'data' => $batch->fresh(['supplier','user','files','stockEntries']), ]); } /** * Remove the specified stock batch (and its files). */ public function destroy($id) { $batch = StockBatch::with('files')->findOrFail($id); // delete related files first if you need to clean up storage foreach ($batch->files as $file) { $file->delete(); } $batch->delete(); return response()->json([ 'message' => 'Stock batch deleted successfully', ]); } /** * Get options for dropdown lists. * * @return \Illuminate\Http\JsonResponse */ public function getOptions() { $stockPositions = StockSection::doesntHave('entries') ->with('position.shelf.rack.line.room') ->get() ->map(function (StockSection $section) { $pos = $section->position; $shelf = $pos->shelf; $rack = $shelf->rack; $line = $rack->line; $room = $line->room; return [ 'id' => $section->section_id, 'name' => sprintf( '%s-%s-%s-%s-%s-%s', $room->room_symbol, $line->line_symbol, $rack->rack_symbol, $shelf->shelf_symbol, $pos->position_symbol, $section->section_symbol ), ]; }); // Get suppliers from warehouse DB $suppliers = Supplier::select('id', 'name')->get(); // Get physical items from warehouse DB $countriesOrigin = OriginCountry::select('id', 'code as name')->get(); return response()->json([ 'stockPositions' => $stockPositions, 'suppliers' => $suppliers, 'countriesOrigin' => $countriesOrigin, ]); } /** * Get options for dropdown lists. * * @return \Illuminate\Http\JsonResponse */ public function getItems(Request $request) { // Get physical items from warehouse DB $physicalItems = PhysicalItem::select('id', 'name') ->where('name', 'like', '%' . $request->input('item_name', '') . '%') ->get(); return response()->json([ 'physicalItems' => $physicalItems, ]); } /** * Get options for dropdown lists. * * @return \Illuminate\Http\JsonResponse */ public function getEntries(Request $request, $id) { // Get physical items from warehouse DB $stockEntries = StockEntry::with(['physicalItem', 'supplier', 'sections', 'statusHistory'])->where('stock_batch_id', $id)->get(); return response()->json([ "data" => $stockEntries ]); } public function addEntries(Request $request, $id) { // Get physical items from warehouse DB $stockEntries = StockEntry::whereIn('id', $request->get('ids'))->get(); foreach ($stockEntries as $entry) { $entry->update([ 'stock_batch_id' => $id, 'on_the_way' => false, ]); } return response()->json([ 'message' => 'Batch entries updated successfully', 'data' => $entry->fresh(), ]); } }