Feat/implementación del módulo de órdenes#22
Merged
Abisaac1809 merged 6 commits intoJun 2, 2026
Hidden character warning
The head ref may contain hidden characters: "feat/implementaci\u00f3n-del-m\u00f3dulo-de-\u00f3rdenes"
Conversation
31 tasks
There was a problem hiding this comment.
Pull request overview
Este PR implementa el módulo de órdenes/ventas de extremo a extremo (API + modelos Prisma + UI web), habilitando registrar ventas, listar órdenes y consultar detalles por evento, además de mostrar la tasa vigente en el layout del evento.
Changes:
- Se agrega el módulo de Sales/Orders en API (rutas, servicio, mapper, repositorios y errores de negocio) y su persistencia en Prisma (Customer/Order/OrderItem/Payment).
- Se incorpora en Web la SalesPage con wizard para crear venta, listado paginado, filtros y modal de detalle.
- Se añade un hook para tasa de cambio actual y se actualizan permisos de rutas (admin vs collaborator) para ticket-types/payment-methods/exchange-rates.
Reviewed changes
Copilot reviewed 35 out of 35 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/web/src/features/events/services/salesService.ts | Cliente HTTP para crear ventas y consultar órdenes/detalles. |
| packages/web/src/features/events/pages/SalesPage.tsx | UI completa: wizard de venta, listado, filtros, paginación y modales. |
| packages/web/src/features/events/hooks/useCurrentExchangeRate.ts | Hook para cargar/refresh de la tasa vigente del evento. |
| packages/web/src/components/Layout.tsx | Indicador de tasa USD/Bs dinámica en el layout del evento. |
| packages/web/src/App.tsx | Reemplaza placeholder por la SalesPage real en la ruta sales. |
| packages/shared/src/utils/currency.ts | Utilidades compartidas para conversión/suma de pagos en USD. |
| packages/shared/src/types/sale.types.ts | Tipos compartidos para ventas/órdenes y respuestas de listado. |
| packages/shared/src/types/index.ts | Exporta los nuevos tipos de sales. |
| packages/shared/src/schemas/sale.schemas.ts | Esquemas Zod para validar creación de venta. |
| packages/shared/src/schemas/index.ts | Exporta los nuevos schemas de sales. |
| packages/shared/src/index.ts | Exporta utilidades de moneda. |
| packages/api/src/modules/ticket-types/ticket-types.routes.ts | Ajusta autorización: listado/detalle para admin+collaborator; mutaciones solo admin. |
| packages/api/src/modules/sales/sales.service.ts | Lógica de negocio de ventas (tasa vigente, validaciones, atomic decrement, creación de orden). |
| packages/api/src/modules/sales/sales.routes.ts | Rutas de sales con auth y authorize por evento. |
| packages/api/src/modules/sales/sales.mapper.ts | Mapeo de entidad Order a DTOs compartidos (summary/detail). |
| packages/api/src/modules/sales/sales.controller.ts | Controlador HTTP para crear/listar/detallar órdenes. |
| packages/api/src/modules/sales/index.ts | Wiring del módulo Sales (service/controller/routes). |
| packages/api/src/modules/payment-methods/payment-methods.routes.ts | Ajusta autorización: list para admin+collaborator; mutaciones solo admin. |
| packages/api/src/modules/exchange-rates/exchange-rates.routes.ts | Ajusta autorización: lectura para admin+collaborator; creación solo admin. |
| packages/api/src/infrastructure/repositories/prismaTransactionHelper.ts | Helper para usar TransactionClient o PrismaClient según contexto. |
| packages/api/src/infrastructure/repositories/PrismaTicketTypeRepository.ts | Agrega decremento atómico de soldQuantity soportando transacciones. |
| packages/api/src/infrastructure/repositories/PrismaOrderRepository.ts | Nuevo repo para crear/consultar órdenes con relaciones. |
| packages/api/src/infrastructure/repositories/PrismaCustomerRepository.ts | Nuevo repo para upsert/búsqueda de clientes por cédula. |
| packages/api/src/infrastructure/PrismaTransactionManager.ts | Implementación de transaction manager con Prisma. |
| packages/api/src/infrastructure/container.ts | Registra repositorios nuevos y monta el módulo events/:eventId/sales. |
| packages/api/src/core/interfaces/repositories/ITicketTypeRepository.ts | Extiende interfaz con decrementSoldQuantityAtomic. |
| packages/api/src/core/interfaces/repositories/IOrderRepository.ts | Interfaz para persistencia/consulta de órdenes. |
| packages/api/src/core/interfaces/repositories/ICustomerRepository.ts | Interfaz para persistencia/consulta de clientes. |
| packages/api/src/core/interfaces/ITransactionManager.ts | Contrato para ejecutar callbacks en transacción. |
| packages/api/src/core/interfaces/ITransactionContext.ts | Tipo “brand” para representar contexto transaccional. |
| packages/api/src/core/errors/BusinessErrors.ts | Nuevos errores de negocio para ventas/órdenes. |
| packages/api/src/core/entities/Order.ts | Nueva entidad de dominio Order con items y payments. |
| packages/api/src/core/entities/Customer.ts | Nueva entidad de dominio Customer. |
| packages/api/prisma/schema.prisma | Nuevos modelos Customer/Order/OrderItem/Payment y relaciones. |
| packages/api/prisma/migrations/20260601223134_add_sales_module/migration.sql | Migración SQL que crea las tablas/índices/FKs del módulo de ventas. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
PR: Implementación del Módulo de Ventas / Órdenes
Descripción
Este PR implementa completamente el Módulo de Ventas / Órdenes, reemplazando el placeholder existente en
/events/:eventId/sales. Permite registrar ventas con soporte multi-pago, búsqueda y filtrado de órdenes, y visualización de detalle. Los endpoints están protegidos porauthorizeEventRole('admin', 'collaborator'). Toda la lógica transaccional (decremento atómico de stock, upsert de cliente, creación de orden y pagos) corre dentro de una única transacción Prisma medianteITransactionManager. Las validaciones del frontend están alineadas con los esquemas Zod de@eventflow/shared.🛠️ Cambios Implementados
1. Base de Datos (
packages/api)add_sales_module):Customercon campos:id,idNumber(único),fullName,phone?,email?,createdAt,updatedAt.Ordercon campos:id,eventId(FK),customerId(FK),soldById(FK →User),exchangeRateId(FK →ExchangeRate),currency,totalAmount(Decimal),createdAt. Relacionesitemsypayments.OrderItemcon campos:id,orderId(FK),ticketTypeId(FK →TicketType),quantity,unitPrice(Decimal),currency,subtotal(Decimal).Paymentcon campos:id,orderId(FK),paymentMethodId(FK →PaymentMethod),amount(Decimal),currency,reference?,receiptUrl?,status(defaultAPPROVED),verifiedById(FK →User),verifiedAt.ordersenEvent,ExchangeRateyCustomer;orderItemsenTicketType;paymentsenPaymentMethod;ordersSoldypaymentsVerifiedenUser.2. Esquemas y Tipos Compartidos (
@eventflow/shared)SalePaymentSchema: campospaymentMethodId,amount,currency(USD | VES | EUR),reference?,receiptUrl?.SaleToCreateSchema: camposticketTypeId,quantity,customer(objeto conidNumber,fullName,phone?,email?),payments(array mínimo 1 elemento).OrderSummaryType,OrderDetailType,OrderItemSummaryType,PaymentSummaryType,OrderCustomerType,ListOrdersResponse.utils/currency.ts:convertToUSD()ysumPaymentsInUSD()para normalizar pagos multi-moneda a USD usando la tasa de cambio vigente.3. Backend / API (
packages/api)Infraestructura transaccional
ITransactionContext— tipo opaco que encapsula el contexto de transacción sin exponer tipos de Prisma al dominio.ITransactionManager— interfaz conrunInTransaction<T>(fn).PrismaTransactionManager— implementación que ejecutaprisma.$transaction().prismaTransactionHelper.ts— extrae el cliente Prisma del contexto opaco en la capa de infraestructura.Módulo
salesPOST /api/events/:eventId/sales— registra una nueva venta. Lógica de negocio:NoActiveExchangeRateError400).TicketTypeexista, esté activo y dentro del período de venta (TicketTypeNotFoundError404,TicketTypeNotSellableError400).InsufficientPaymentError400).idNumber, decremento atómico desoldQuantitycon verificación de stock disponible (InsufficientTicketsError409), creación deOrder,OrderItemyPayment.GET /api/events/:eventId/sales— lista paginada de órdenes con filtros opcionales:idNumber,startDate,endDate,ticketTypeId. RetornaListOrdersResponse(orders,total,page,limit).GET /api/events/:eventId/sales/:orderId— detalle completo de una orden con cliente, items y pagos (OrderNotFoundError404).authorizeEventRole('admin', 'collaborator').Nuevos errores de negocio (
BusinessErrors.ts)InsufficientTicketsError(409) — stock insuficiente.NoActiveExchangeRateError(400) — sin tasa de cambio vigente.InsufficientPaymentError(400) — monto pagado no cubre el total; incluye los montos en el mensaje.OrderNotFoundError(404) — orden no encontrada por ID.TicketTypeNotSellableError(400) — tipo de entrada inactivo o fuera del período de venta.Capa de dominio e infraestructura
Customer,Order(conitems,payments,soldByName,exchangeRatedesnormalizados para mapeo).ICustomerRepository(conupsertByIdNumber),IOrderRepository(concreate,findById,findAndCount),ITicketTypeRepositoryextendida condecrementSoldQuantityAtomic.PrismaCustomerRepository,PrismaOrderRepository,PrismaTicketTypeRepository(actualizado).SalesMapper— convierte entidadesOrderaOrderSummaryTypeyOrderDetailType.container.tsactualizado conPrismaCustomerRepository,PrismaOrderRepository,PrismaTransactionManagery el móduloevents/:eventId/sales.4. Frontend / Web (
packages/web)salesServiceconcreateSale(),listOrders()(con parámetros de filtro y paginación) ygetOrderDetail().useCurrentExchangeRate: carga la tasa vigente del evento con soporte de cancelación de efecto y métodorefetch. Usado enLayout.tsxpara mostrar la tasa en tiempo real en el sidebar (reemplaza el valor hardcodeado36.50 Bs.). Muestra"Cargando...", la tasa formateada con fecha, o"Sin tasa activa"según el estado.SalesPagereemplazaEventPlaceholderPageen la rutasales. Estructura en dos vistas:LIMIT = 15. Fila clickeable que abre el modal de detalle. Estados de carga, vacío y error.OrderDetailModal): muestra cliente (nombre, CI, teléfono, email), entradas (lista de items con subtotales) y pagos (monto, moneda, referencia, método). Cierra al hacer clic en el fondo o en el botón ×.SaleToCreateSchemavíazodResolver. CamposidNumber,fullName,phone?,email?.useFieldArraypara lista dinámica de pagos. Cada pago tiene selector de método, monto, moneda y referencia opcional. Resumen en tiempo real del total en USD (usandosumPaymentsInUSD), monto pagado y diferencia. El botón "Confirmar venta" se habilita cuando el monto cubierto ≥ total.isSellable()helper para validar disponibilidad de un tipo de entrada en el cliente.closes #12