77 lines
2.8 KiB
PHP
77 lines
2.8 KiB
PHP
<?php
|
|
|
|
namespace App\Services;
|
|
|
|
use App\Models\Inventory;
|
|
use App\Models\SaleDetail;
|
|
use Illuminate\Support\Facades\DB;
|
|
|
|
class ReportService
|
|
{
|
|
/**
|
|
* Obtener el producto más vendido
|
|
*
|
|
* @param string|null $fromDate Fecha inicial (formato: Y-m-d)
|
|
* @param string|null $toDate Fecha final (formato: Y-m-d)
|
|
* @return array|null Retorna el producto más vendido o null si no hay ventas
|
|
*/
|
|
public function getTopSellingProduct(?string $fromDate = null, ?string $toDate = null): ?array
|
|
{
|
|
$query = SaleDetail::query()
|
|
->selectRaw('
|
|
inventories.id,
|
|
inventories.name,
|
|
inventories.sku,
|
|
categories.name as category_name,
|
|
SUM(sale_details.quantity) as total_quantity_sold,
|
|
SUM(sale_details.subtotal) as total_revenue,
|
|
COUNT(DISTINCT sale_details.sale_id) as times_sold,
|
|
MAX(sales.created_at) as last_sale_date,
|
|
inventories.created_at as added_date
|
|
')
|
|
->join('inventories', 'sale_details.inventory_id', '=', 'inventories.id')
|
|
->join('categories', 'inventories.category_id', '=', 'categories.id')
|
|
->join('sales', 'sale_details.sale_id', '=', 'sales.id')
|
|
->where('sales.status', 'completed')
|
|
->whereNull('sales.deleted_at');
|
|
|
|
// Aplicar filtro de fechas si se proporcionan ambas
|
|
if ($fromDate && $toDate) {
|
|
$query->whereBetween(DB::raw('DATE(sales.created_at)'), [$fromDate, $toDate]);
|
|
}
|
|
|
|
$result = $query
|
|
->groupBy('inventories.id', 'inventories.name', 'inventories.sku',
|
|
'categories.name', 'inventories.created_at')
|
|
->orderByDesc('total_quantity_sold')
|
|
->first();
|
|
|
|
return $result ? $result->toArray() : null;
|
|
}
|
|
|
|
/**
|
|
* Obtener productos sin movimiento
|
|
*/
|
|
public function getProductsWithoutMovement(?string $fromDate = null, ?string $toDate = null)
|
|
{
|
|
// Obtener IDs de productos que SÍ tienen ventas
|
|
$inventoriesWithSales = SaleDetail::query()
|
|
->join('sales', 'sale_details.sale_id', '=', 'sales.id')
|
|
->where('sales.status', 'completed')
|
|
->whereNull('sales.deleted_at')
|
|
->whereBetween(DB::raw('DATE(sales.created_at)'), [$fromDate, $toDate])
|
|
->distinct()
|
|
->pluck('sale_details.inventory_id')
|
|
->toArray();
|
|
|
|
// Construir query para productos SIN ventas usando relaciones de Eloquent
|
|
$query = Inventory::query()
|
|
->with(['category', 'price'])
|
|
->where('is_active', true)
|
|
->whereNotIn('id', $inventoriesWithSales)
|
|
->orderBy('created_at');
|
|
|
|
return $query->paginate(config('app.pagination', 10));
|
|
}
|
|
}
|