add: reportes por rango de fecha
This commit is contained in:
parent
d5665f0448
commit
40bc2b5735
@ -15,22 +15,22 @@ public function __construct(
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Obtener el producto más vendido
|
* Obtener el producto más vendido
|
||||||
*
|
|
||||||
* @param Request $request
|
|
||||||
* @return \Illuminate\Http\JsonResponse
|
|
||||||
*/
|
*/
|
||||||
public function topSellingProduct(Request $request)
|
public function topSellingProduct(Request $request)
|
||||||
{
|
{
|
||||||
$request->validate([
|
$request->validate([
|
||||||
|
'include_stock_value' => ['nullable', 'boolean'],
|
||||||
'from_date' => ['nullable', 'date_format:Y-m-d'],
|
'from_date' => ['nullable', 'date_format:Y-m-d'],
|
||||||
'to_date' => ['nullable', 'date_format:Y-m-d', 'after_or_equal:from_date', 'required_with:from_date'],
|
'to_date' => ['nullable', 'date_format:Y-m-d', 'after_or_equal:from_date', 'required_with:from_date'],
|
||||||
], [
|
], [
|
||||||
|
'include_stock_value.boolean' => 'El parámetro de valor de stock debe ser verdadero o falso.',
|
||||||
'from_date.date_format' => 'La fecha inicial debe tener el formato Y-m-d (ejemplo: 2025-01-01).',
|
'from_date.date_format' => 'La fecha inicial debe tener el formato Y-m-d (ejemplo: 2025-01-01).',
|
||||||
'to_date.date_format' => 'La fecha final debe tener el formato Y-m-d (ejemplo: 2025-01-31).',
|
'to_date.date_format' => 'La fecha final debe tener el formato Y-m-d (ejemplo: 2025-01-31).',
|
||||||
'to_date.after_or_equal' => 'La fecha final debe ser igual o posterior a la fecha inicial.',
|
'to_date.after_or_equal' => 'La fecha final debe ser igual o posterior a la fecha inicial.',
|
||||||
'to_date.required_with' => 'La fecha final es obligatoria cuando se proporciona fecha inicial.',
|
'to_date.required_with' => 'La fecha final es obligatoria cuando se proporciona fecha inicial.',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$product = $this->reportService->getTopSellingProduct(
|
$product = $this->reportService->getTopSellingProduct(
|
||||||
fromDate: $request->input('from_date'),
|
fromDate: $request->input('from_date'),
|
||||||
@ -57,25 +57,27 @@ public function topSellingProduct(Request $request)
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Obtener productos sin movimiento
|
* Obtener productos sin movimiento
|
||||||
*
|
|
||||||
* @param Request $request
|
|
||||||
* @return \Illuminate\Http\JsonResponse
|
|
||||||
*/
|
*/
|
||||||
public function productsWithoutMovement(Request $request)
|
public function productsWithoutMovement(Request $request)
|
||||||
{
|
{
|
||||||
$request->validate([
|
$request->validate([
|
||||||
'days_threshold' => ['nullable', 'integer', 'min:1'],
|
|
||||||
'include_stock_value' => ['nullable', 'boolean'],
|
'include_stock_value' => ['nullable', 'boolean'],
|
||||||
|
'from_date' => ['required', 'date_format:Y-m-d'],
|
||||||
|
'to_date' => ['required', 'date_format:Y-m-d', 'after_or_equal:from_date'],
|
||||||
], [
|
], [
|
||||||
'days_threshold.integer' => 'El umbral de días debe ser un número entero.',
|
|
||||||
'days_threshold.min' => 'El umbral de días debe ser al menos 1.',
|
|
||||||
'include_stock_value.boolean' => 'El parámetro de valor de stock debe ser verdadero o falso.',
|
'include_stock_value.boolean' => 'El parámetro de valor de stock debe ser verdadero o falso.',
|
||||||
|
'from_date.required' => 'La fecha inicial es obligatoria.',
|
||||||
|
'from_date.date_format' => 'La fecha inicial debe tener el formato Y-m-d (ejemplo: 2025-01-01).',
|
||||||
|
'to_date.required' => 'La fecha final es obligatoria.',
|
||||||
|
'to_date.date_format' => 'La fecha final debe tener el formato Y-m-d (ejemplo: 2025-01-31).',
|
||||||
|
'to_date.after_or_equal' => 'La fecha final debe ser igual o posterior a la fecha inicial.',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$products = $this->reportService->getProductsWithoutMovement(
|
$products = $this->reportService->getProductsWithoutMovement(
|
||||||
daysThreshold: (int)($request->input('days_threshold', 30)),
|
includeStockValue: (bool)($request->input('include_stock_value', true)),
|
||||||
includeStockValue: (bool)($request->input('include_stock_value', true))
|
fromDate: $request->input('from_date'),
|
||||||
|
toDate: $request->input('to_date')
|
||||||
);
|
);
|
||||||
|
|
||||||
return ApiResponse::OK->response([
|
return ApiResponse::OK->response([
|
||||||
|
|||||||
@ -56,13 +56,14 @@ public function getTopSellingProduct(?string $fromDate = null, ?string $toDate =
|
|||||||
* @param bool $includeStockValue Incluir valor del inventario (default: true)
|
* @param bool $includeStockValue Incluir valor del inventario (default: true)
|
||||||
* @return array Lista de productos sin ventas
|
* @return array Lista de productos sin ventas
|
||||||
*/
|
*/
|
||||||
public function getProductsWithoutMovement(int $daysThreshold = 30, bool $includeStockValue = true): array
|
public function getProductsWithoutMovement(bool $includeStockValue = true, ?string $fromDate = null, ?string $toDate = null): array
|
||||||
{
|
{
|
||||||
// Obtener IDs de productos que SÍ tienen ventas
|
// Obtener IDs de productos que SÍ tienen ventas
|
||||||
$inventoriesWithSales = SaleDetail::query()
|
$inventoriesWithSales = SaleDetail::query()
|
||||||
->join('sales', 'sale_details.sale_id', '=', 'sales.id')
|
->join('sales', 'sale_details.sale_id', '=', 'sales.id')
|
||||||
->where('sales.status', 'completed')
|
->where('sales.status', 'completed')
|
||||||
->whereNull('sales.deleted_at')
|
->whereNull('sales.deleted_at')
|
||||||
|
->whereBetween(DB::raw('DATE(sales.created_at)'), [$fromDate, $toDate])
|
||||||
->distinct()
|
->distinct()
|
||||||
->pluck('sale_details.inventory_id')
|
->pluck('sale_details.inventory_id')
|
||||||
->toArray();
|
->toArray();
|
||||||
@ -76,7 +77,6 @@ public function getProductsWithoutMovement(int $daysThreshold = 30, bool $includ
|
|||||||
inventories.stock,
|
inventories.stock,
|
||||||
categories.name as category_name,
|
categories.name as category_name,
|
||||||
inventories.created_at as date_added,
|
inventories.created_at as date_added,
|
||||||
DATEDIFF(NOW(), inventories.created_at) as days_without_movement,
|
|
||||||
prices.retail_price
|
prices.retail_price
|
||||||
');
|
');
|
||||||
|
|
||||||
@ -93,7 +93,6 @@ public function getProductsWithoutMovement(int $daysThreshold = 30, bool $includ
|
|||||||
->where('inventories.is_active', true)
|
->where('inventories.is_active', true)
|
||||||
->whereNull('inventories.deleted_at')
|
->whereNull('inventories.deleted_at')
|
||||||
->whereNotIn('inventories.id', $inventoriesWithSales)
|
->whereNotIn('inventories.id', $inventoriesWithSales)
|
||||||
->havingRaw('DATEDIFF(NOW(), inventories.created_at) >= ?', [$daysThreshold])
|
|
||||||
->orderBy('inventories.created_at')
|
->orderBy('inventories.created_at')
|
||||||
->get()
|
->get()
|
||||||
->toArray();
|
->toArray();
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user