model->newQuery()->with(['fournisseur', 'category']); // Apply filters if (!empty($filters['search'])) { $query->where(function ($q) use ($filters) { $q->where('nom', 'like', '%' . $filters['search'] . '%') ->orWhere('reference', 'like', '%' . $filters['search'] . '%') ->orWhere('fabricant', 'like', '%' . $filters['search'] . '%'); }); } if (!empty($filters['categorie'])) { $query->where('categorie_id', $filters['categorie']); } if (!empty($filters['fournisseur_id'])) { $query->where('fournisseur_id', $filters['fournisseur_id']); } if (isset($filters['low_stock'])) { $query->whereRaw('stock_actuel <= stock_minimum'); } if (isset($filters['expiring_soon'])) { $query->where('date_expiration', '<=', now()->addDays(30)->toDateString()) ->where('date_expiration', '>=', now()->toDateString()); } // Apply sorting $sortField = $filters['sort_by'] ?? 'created_at'; $sortDirection = $filters['sort_direction'] ?? 'desc'; $query->orderBy($sortField, $sortDirection); return $query->paginate($perPage); } /** * Get products with low stock */ public function getLowStockProducts(int $perPage = 15): LengthAwarePaginator { return $this->model->newQuery() ->with(['fournisseur', 'category']) ->whereRaw('stock_actuel <= stock_minimum') ->orderBy('stock_actuel', 'asc') ->paginate($perPage); } /** * Search products by name */ public function searchByName(string $name, int $perPage = 15, bool $exactMatch = false) { $query = $this->model->newQuery()->with(['fournisseur', 'category']); if ($exactMatch) { $query->where('nom', $name); } else { $query->where('nom', 'like', '%' . $name . '%'); } return $query->paginate($perPage); } /** * Get products by category */ public function getByCategory(int $categoryId, int $perPage = 15): LengthAwarePaginator { return $this->model->newQuery() ->with(['fournisseur', 'category']) ->where('categorie_id', $categoryId) ->orderBy('nom') ->paginate($perPage); } /** * Get products by fournisseur */ public function getProductsByFournisseur(int $fournisseurId): LengthAwarePaginator { return $this->model->newQuery() ->where('fournisseur_id', $fournisseurId) ->orderBy('nom') ->paginate(15); } /** * Update stock quantity */ public function updateStock(int $productId, float $newQuantity): bool { return $this->model->where('id', $productId) ->update(['stock_actuel' => $newQuantity]) > 0; } /** * Get product statistics */ public function getStatistics(): array { $totalProducts = $this->model->count(); $lowStockProducts = $this->model->whereRaw('stock_actuel <= stock_minimum')->count(); $expiringProducts = $this->model->where('date_expiration', '<=', now()->addDays(30)->toDateString()) ->where('date_expiration', '>=', now()->toDateString()) ->count(); $totalValue = $this->model->sum(\DB::raw('stock_actuel * prix_unitaire')); return [ 'total_products' => $totalProducts, 'low_stock_products' => $lowStockProducts, 'expiring_products' => $expiringProducts, 'total_value' => $totalValue, ]; } }