pdv.backend/app/Http/Controllers/App/InvoiceRequestController.php

199 lines
6.5 KiB
PHP

<?php
namespace App\Http\Controllers\App;
use App\Http\Controllers\Controller;
use App\Http\Requests\App\InvoiceRequestProcessRequest;
use App\Http\Requests\App\InvoiceRequestRejectRequest;
use App\Models\InvoiceRequest;
use Illuminate\Http\Request;
use Notsoweb\ApiResponse\Enums\ApiResponse;
/**
* Controlador para gestión administrativa de solicitudes de factura
*/
class InvoiceRequestController extends Controller
{
/**
* Listar todas las solicitudes de factura con filtros y paginación
*/
public function index(Request $request)
{
$query = InvoiceRequest::with([
'sale:id,invoice_number,subtotal,tax,total,payment_method,status,created_at',
'sale.user:id,name,email',
'client:id,name,client_number,email,phone,rfc,razon_social',
'processedBy:id,name,email'
]);
// Filtro por estado
if ($request->has('status') && $request->status !== '') {
$query->where('status', $request->status);
}
// Filtro por rango de fechas
if ($request->has('date_from')) {
$query->whereDate('requested_at', '>=', $request->date_from);
}
if ($request->has('date_to')) {
$query->whereDate('requested_at', '<=', $request->date_to);
}
// Búsqueda por folio de venta
if ($request->has('invoice_number') && $request->invoice_number !== '') {
$query->whereHas('sale', function ($q) use ($request) {
$q->where('invoice_number', 'like', '%' . $request->invoice_number . '%');
});
}
// Búsqueda por cliente
if ($request->has('client_search') && $request->client_search !== '') {
$query->whereHas('client', function ($q) use ($request) {
$q->where('name', 'like', '%' . $request->client_search . '%')
->orWhere('rfc', 'like', '%' . $request->client_search . '%')
->orWhere('email', 'like', '%' . $request->client_search . '%');
});
}
// Ordenamiento
$sortBy = $request->get('sort_by', 'requested_at');
$sortOrder = $request->get('sort_order', 'desc');
$query->orderBy($sortBy, $sortOrder);
// Paginación
$perPage = $request->get('per_page', 15);
$invoiceRequests = $query->paginate($perPage);
return ApiResponse::OK->response([
'invoice_requests' => $invoiceRequests
]);
}
/**
* Mostrar detalles de una solicitud específica
*/
public function show($id)
{
$invoiceRequest = InvoiceRequest::with([
'sale.user:id,name,email',
'sale.details:id,sale_id,inventory_id,product_name,quantity,unit_price,subtotal,discount_percentage,discount_amount',
'sale.details:inventory_id.category_id,name',
'sale.details.inventory:id,category_id,name,sku',
'sale.details.inventory.category:id,name',
'sale.details.serials:id,inventory_id,sale_detail_id,serial_number,status',
'client',
'processedBy:id,name,email'
])->find($id);
if (!$invoiceRequest) {
return ApiResponse::NOT_FOUND->response([
'message' => 'Solicitud de factura no encontrada'
]);
}
return ApiResponse::OK->response([
'invoice_request' => $invoiceRequest
]);
}
/**
* Marcar una solicitud como procesada
*
*/
public function process(InvoiceRequestProcessRequest $request, $id)
{
$invoiceRequest = InvoiceRequest::find($id);
if (!$invoiceRequest) {
return ApiResponse::NOT_FOUND->response([
'message' => 'Solicitud de factura no encontrada'
]);
}
if ($invoiceRequest->status !== InvoiceRequest::STATUS_PENDING) {
return ApiResponse::BAD_REQUEST->response([
'message' => 'Solo se pueden procesar solicitudes pendientes',
'current_status' => $invoiceRequest->status
]);
}
$invoiceRequest->markAsProcessed(
$request->user()->id,
$request->notes
);
$invoiceRequest->load([
'sale:id,invoice_number,total',
'client:id,name,rfc,email',
'processedBy:id,name'
]);
return ApiResponse::OK->response([
'message' => 'Solicitud marcada como procesada correctamente',
'invoice_request' => $invoiceRequest
]);
}
/**
* Rechazar una solicitud
*
*/
public function reject(InvoiceRequestRejectRequest $request, $id)
{
$invoiceRequest = InvoiceRequest::find($id);
if (!$invoiceRequest) {
return ApiResponse::NOT_FOUND->response([
'message' => 'Solicitud de factura no encontrada'
]);
}
if ($invoiceRequest->status !== InvoiceRequest::STATUS_PENDING) {
return ApiResponse::BAD_REQUEST->response([
'message' => 'Solo se pueden rechazar solicitudes pendientes',
'current_status' => $invoiceRequest->status
]);
}
$invoiceRequest->markAsRejected(
$request->user()->id,
$request->notes
);
$invoiceRequest->load([
'sale:id,invoice_number,total',
'client:id,name,rfc,email',
'processedBy:id,name'
]);
return ApiResponse::OK->response([
'message' => 'Solicitud rechazada correctamente',
'invoice_request' => $invoiceRequest
]);
}
/**
* Obtener estadísticas de solicitudes de factura
*/
public function stats()
{
$stats = [
'pending' => InvoiceRequest::where('status', InvoiceRequest::STATUS_PENDING)->count(),
'processed' => InvoiceRequest::where('status', InvoiceRequest::STATUS_PROCESSED)->count(),
'rejected' => InvoiceRequest::where('status', InvoiceRequest::STATUS_REJECTED)->count(),
'total' => InvoiceRequest::count(),
'today_pending' => InvoiceRequest::where('status', InvoiceRequest::STATUS_PENDING)
->whereDate('requested_at', today())
->count(),
'this_month' => InvoiceRequest::whereMonth('requested_at', now()->month)
->whereYear('requested_at', now()->year)
->count(),
];
return ApiResponse::OK->response([
'stats' => $stats
]);
}
}