# Dominio Sale ## Propósito Provee consultas administrativas y exportaciones de ventas confirmadas, además del historial de modificaciones auditadas. ## Componentes - `AdminAppSaleService`: pagina ventas, calcula totales y obtiene colecciones para exportación; también consulta modificaciones. - `AdminAppSalePdfService`: genera descargas PDF de ventas y de cambios. - `AdminAppSaleExcelService`: genera descargas Excel de ventas y de cambios. - `AdminAppSaleIndexRequest`: valida filtros del listado y la exportación de ventas. - `AdminAppSaleModificationIndexRequest`: valida los filtros compartidos por el historial y sus exportaciones. - `SaleResource` y `SaleModificationResource`: representan ventas e historial para AdminApp. - `SaleController`: entrada HTTP del panel. ## Endpoints Bajo `/v1/adminapp/tenant`, protegidos por `auth:sanctum` y `adminapp.tenant`: - `GET /sales`, `GET /sales/pdf` y `GET /sales/excel`. - `GET /sales/modifications`, `GET /sales/modifications/pdf` y `GET /sales/modifications/excel`. ## Dependencias Consume compras de `Purchase`, datos del tenant y entradas de `Logging`. No es dueño del estado de una compra; cualquier mutación debe ejecutarse en `Purchase`. ## Consideraciones La consulta paginada y la colección de exportación deben aplicar los mismos filtros para evitar diferencias entre pantalla, PDF y Excel. Cuando el usuario autenticado tiene `event_id`, el controlador lo pasa al servicio como alcance obligatorio para ventas, totales, historial y exportaciones. El alcance se combina con el tenant y no se obtiene de los filtros enviados por el cliente. Los administradores sin `event_id` conservan el alcance del tenant. El detalle, los tickets de una venta, la confirmación y la cancelación buscan la compra dentro del mismo alcance. Una venta de otro evento o sin evento devuelve 404 para un administrador con `event_id`, antes de ejecutar cualquier acción en `CheckoutService`. El historial comparte con ventas los filtros de búsqueda, ID, fecha de venta y estado. En el historial, el estado se evalúa sobre `ValueChange.new_value`: representa el resultado de esa modificación y no el estado actual de la venta.