2025-10-31 15:19:04 +03:00

139 lines
4.2 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Repositories;
use App\Models\Product;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
class ProductRepository extends BaseRepository implements ProductRepositoryInterface
{
public function __construct(Product $model)
{
parent::__construct($model);
}
/**
* Get paginated products with filters
*/
public function paginate(int $perPage = 15, array $filters = []): LengthAwarePaginator
{
$query = $this->model->newQuery()->with('fournisseur');
// Apply filters
if (!empty($filters['search'])) {
$query->where(function ($q) use ($filters) {
$q->where('nom', 'like', '%' . $filters['search'] . '%')
->orWhere('reference', 'like', '%' . $filters['search'] . '%')
->orWhere('categorie', 'like', '%' . $filters['search'] . '%')
->orWhere('fabricant', 'like', '%' . $filters['search'] . '%');
});
}
if (!empty($filters['categorie'])) {
$query->where('categorie', $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')
->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');
if ($exactMatch) {
$query->where('nom', $name);
} else {
$query->where('nom', 'like', '%' . $name . '%');
}
return $query->paginate($perPage);
}
/**
* Get products by category
*/
public function getByCategory(string $category, int $perPage = 15): LengthAwarePaginator
{
return $this->model->newQuery()
->with('fournisseur')
->where('categorie', $category)
->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,
];
}
}