get('per_page', 15); $filters = [ 'search' => $request->get('search'), 'categorie' => $request->get('categorie_id'), 'fournisseur_id' => $request->get('fournisseur_id'), 'low_stock' => $request->get('low_stock'), 'expiring_soon' => $request->get('expiring_soon'), 'sort_by' => $request->get('sort_by', 'created_at'), 'sort_direction' => $request->get('sort_direction', 'desc'), ]; // Remove null filters $filters = array_filter($filters, function ($value) { return $value !== null && $value !== ''; }); $products = $this->productRepository->paginate($perPage, $filters); return new ProductCollection($products); } catch (\Exception $e) { Log::error('Error fetching products: ' . $e->getMessage(), [ 'exception' => $e, 'trace' => $e->getTraceAsString(), ]); return response()->json([ 'message' => 'Une erreur est survenue lors de la récupération des produits.', 'error' => config('app.debug') ? $e->getMessage() : null, ], 500); } } /** * Store a newly created product. */ public function store(StoreProductRequest $request): ProductResource|JsonResponse { try { $validatedData = $request->validated(); // Handle image upload if ($request->hasFile('image')) { // Create product without image first $product = $this->productRepository->create($validatedData); // Upload and attach image $imagePath = $product->uploadImage($request->file('image')); // Refresh product to get updated data $product = $this->productRepository->find($product->id); } else { $product = $this->productRepository->create($validatedData); } return new ProductResource($product); } catch (\Exception $e) { Log::error('Error creating product: ' . $e->getMessage(), [ 'exception' => $e, 'trace' => $e->getTraceAsString(), 'data' => $request->validated(), ]); return response()->json([ 'message' => 'Une erreur est survenue lors de la création du produit.', 'error' => config('app.debug') ? $e->getMessage() : null, ], 500); } } /** * Display the specified product. */ public function show(string $id): ProductResource|JsonResponse { try { $product = $this->productRepository->find($id); if (!$product) { return response()->json([ 'message' => 'Produit non trouvé.', ], 404); } return new ProductResource($product); } catch (\Exception $e) { Log::error('Error fetching product: ' . $e->getMessage(), [ 'exception' => $e, 'trace' => $e->getTraceAsString(), 'product_id' => $id, ]); return response()->json([ 'message' => 'Une erreur est survenue lors de la récupération du produit.', 'error' => config('app.debug') ? $e->getMessage() : null, ], 500); } } /** * Search products by name. */ public function searchBy(Request $request): JsonResponse { try { $name = $request->get('name', ''); $exact = $request->boolean('exact', false); if (empty($name)) { return response()->json([ 'message' => 'Le paramètre "name" est requis.', ], 400); } $products = $this->productRepository->searchByName($name, 15, $exact); return response()->json([ 'data' => $products, 'count' => $products->count(), 'message' => $products->count() > 0 ? 'Produits trouvés avec succès.' : 'Aucun produit trouvé.', ], 200); } catch (\Exception $e) { Log::error('Error searching products by name: ' . $e->getMessage(), [ 'exception' => $e, 'trace' => $e->getTraceAsString(), 'search_term' => $name, ]); return response()->json([ 'message' => 'Une erreur est survenue lors de la recherche des produits.', 'error' => config('app.debug') ? $e->getMessage() : null, ], 500); } } /** * Get products with low stock. */ public function lowStock(Request $request): ProductCollection|JsonResponse { try { $perPage = $request->get('per_page', 15); $products = $this->productRepository->getLowStockProducts($perPage); return new ProductCollection($products); } catch (\Exception $e) { Log::error('Error fetching low stock products: ' . $e->getMessage(), [ 'exception' => $e, 'trace' => $e->getTraceAsString(), ]); return response()->json([ 'message' => 'Une erreur est survenue lors de la récupération des produits à stock faible.', 'error' => config('app.debug') ? $e->getMessage() : null, ], 500); } } /** * Get products by category. */ public function byCategory(Request $request): ProductCollection|JsonResponse { try { $categoryId = $request->get('category_id'); $perPage = $request->get('per_page', 15); if (empty($categoryId)) { return response()->json([ 'message' => 'Le paramètre "category_id" est requis.', ], 400); } $products = $this->productRepository->getByCategory($categoryId, $perPage); return new ProductCollection($products); } catch (\Exception $e) { Log::error('Error fetching products by category: ' . $e->getMessage(), [ 'exception' => $e, 'trace' => $e->getTraceAsString(), 'category_id' => $categoryId, ]); return response()->json([ 'message' => 'Une erreur est survenue lors de la récupération des produits par catégorie.', 'error' => config('app.debug') ? $e->getMessage() : null, ], 500); } } /** * Get products statistics. */ public function statistics(): JsonResponse { try { $stats = $this->productRepository->getStatistics(); return response()->json([ 'data' => $stats, 'message' => 'Statistiques des produits récupérées avec succès.', ], 200); } catch (\Exception $e) { Log::error('Error fetching product statistics: ' . $e->getMessage(), [ 'exception' => $e, 'trace' => $e->getTraceAsString(), ]); return response()->json([ 'message' => 'Une erreur est survenue lors de la récupération des statistiques.', 'error' => config('app.debug') ? $e->getMessage() : null, ], 500); } } /** * Update the specified product. */ public function update(UpdateProductRequest $request, string $id): ProductResource|JsonResponse { try { $validatedData = $request->validated(); $product = $this->productRepository->find($id); if (!$product) { return response()->json([ 'message' => 'Produit non trouvé.', ], 404); } // Handle image upload/removal if ($request->boolean('remove_image')) { // Remove existing image $product->deleteImage(); } elseif ($request->hasFile('image')) { // Upload new image $product->uploadImage($request->file('image')); } // Remove image-related fields from validated data before updating other fields unset($validatedData['image'], $validatedData['remove_image']); // Update other product fields $updated = $this->productRepository->update($id, $validatedData); if (!$updated) { return response()->json([ 'message' => 'Produit non trouvé ou échec de la mise à jour.', ], 404); } $product = $this->productRepository->find($id); return new ProductResource($product); } catch (\Exception $e) { Log::error('Error updating product: ' . $e->getMessage(), [ 'exception' => $e, 'trace' => $e->getTraceAsString(), 'product_id' => $id, 'data' => $request->validated(), ]); return response()->json([ 'message' => 'Une erreur est survenue lors de la mise à jour du produit.', 'error' => config('app.debug') ? $e->getMessage() : null, ], 500); } } /** * Remove the specified product. */ public function destroy(string $id): JsonResponse { try { $deleted = $this->productRepository->delete($id); if (!$deleted) { return response()->json([ 'message' => 'Produit non trouvé ou échec de la suppression.', ], 404); } return response()->json([ 'message' => 'Produit supprimé avec succès.', ], 200); } catch (\Exception $e) { Log::error('Error deleting product: ' . $e->getMessage(), [ 'exception' => $e, 'trace' => $e->getTraceAsString(), 'product_id' => $id, ]); return response()->json([ 'message' => 'Une erreur est survenue lors de la suppression du produit.', 'error' => config('app.debug') ? $e->getMessage() : null, ], 500); } } /** * Update stock quantity for a product. */ public function updateStock(Request $request, string $id): JsonResponse { try { $request->validate([ 'stock_actuel' => 'required|numeric|min:0', ]); $updated = $this->productRepository->updateStock((int) $id, $request->stock_actuel); if (!$updated) { return response()->json([ 'message' => 'Produit non trouvé ou échec de la mise à jour du stock.', ], 404); } $product = $this->productRepository->find($id); return response()->json([ 'data' => new ProductResource($product), 'message' => 'Stock mis à jour avec succès.', ], 200); } catch (\Exception $e) { Log::error('Error updating product stock: ' . $e->getMessage(), [ 'exception' => $e, 'trace' => $e->getTraceAsString(), 'product_id' => $id, 'stock_data' => $request->all(), ]); return response()->json([ 'message' => 'Une erreur est survenue lors de la mise à jour du stock.', 'error' => config('app.debug') ? $e->getMessage() : null, ], 500); } } }