orderBy('created_at', 'desc'); if ($request->has('q') && $request->q){ $query->whereHas('inventory', function($qy) use ($request){ $qy->where('name', 'like', "%{$request->q}%") ->orWhere('sku', 'like', "%{$request->q}%") ->orWhere('barcode', $request->q); }); } if ($request->has('movement_type')) { $query->where('movement_type', $request->movement_type); } if ($request->has('inventory_id')) { $query->where('inventory_id', $request->inventory_id); } if ($request->has('warehouse_id')) { $query->where(function ($q) use ($request) { $q->where('warehouse_from_id', $request->warehouse_id) ->orWhere('warehouse_to_id', $request->warehouse_id); }); } if ($request->has('from_date')) { $query->whereDate('created_at', '>=', $request->from_date); } if ($request->has('to_date')) { $query->whereDate('created_at', '<=', $request->to_date); } $movements = $query->paginate($request->get('per_page', 15)); return ApiResponse::OK->response(['movements' => $movements]); } /** * Ver detalle de un movimiento */ public function show(int $id) { $movement = InventoryMovement::with(['inventory', 'warehouseFrom', 'warehouseTo', 'user', 'supplier', 'serials']) ->find($id); if (!$movement) { return ApiResponse::NOT_FOUND->response([ 'message' => 'Movimiento no encontrado' ]); } return ApiResponse::OK->response([ 'movement' => $movement ]); } /** * Editar movimiento de inventario * Revierte el movimiento original y aplica el nuevo */ public function update(InventoryMovementUpdateRequest $request, int $id) { try { $movement = $this->movementService->updateMovement( $id, $request->validated() ); return ApiResponse::OK->response([ 'message' => 'Movimiento actualizado correctamente', 'movement' => $movement, ]); } catch (\Exception $e) { return ApiResponse::BAD_REQUEST->response([ 'message' => $e->getMessage() ]); } } /** * Registrar entrada de inventario */ public function entry(InventoryEntryRequest $request) { try { $validated = $request->validated(); if(isset($validated['products'])){ $movements = $this->movementService->bulkEntry($validated); return ApiResponse::CREATED->response([ 'message' => 'Entrada registrada correctamente', 'movement' => $movements, 'total_products' => count($movements), ]); } else { $movement = $this->movementService->entry($validated); return ApiResponse::CREATED->response([ 'message' => 'Entrada registrada correctamente', 'movement' => $movement->load(['inventory', 'warehouseTo']), ]); } } catch (\Exception $e) { return ApiResponse::BAD_REQUEST->response([ 'message' => $e->getMessage() ]); } } /** * Registrar salida de inventario */ public function exit(InventoryExitRequest $request) { try { $validated = $request->validated(); if(isset($validated['products'])){ $movements = $this->movementService->bulkExit($validated); return ApiResponse::CREATED->response([ 'message' => 'Salidas registradas correctamente', 'movements' => $movements, 'total_products' => count($movements), ]); } else { $movement = $this->movementService->exit($validated); return ApiResponse::CREATED->response([ 'message' => 'Salida registrada correctamente', 'movement' => $movement->load(['inventory', 'warehouseFrom']), ]); } } catch (\Exception $e) { return ApiResponse::BAD_REQUEST->response([ 'message' => $e->getMessage() ]); } } /** * Registrar traspaso entre almacenes */ public function transfer(InventoryTransferRequest $request) { try { $validated = $request->validated(); if(isset($validated['products'])){ $movements = $this->movementService->bulkTransfer($validated); return ApiResponse::CREATED->response([ 'message' => 'Traspasos registrados correctamente', 'movements' => $movements, 'total_products' => count($movements), ]); } else { $movement = $this->movementService->transfer($validated); return ApiResponse::CREATED->response([ 'message' => 'Traspaso registrado correctamente', 'movement' => $movement->load(['inventory', 'warehouseFrom', 'warehouseTo']), ]); } } catch (\Exception $e) { return ApiResponse::BAD_REQUEST->response([ 'message' => $e->getMessage() ]); } } }