pdv.backend/app/Services/ReportService.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));
}
}