Skip to content

Feat/implementación del módulo de órdenes#22

Merged
Abisaac1809 merged 6 commits into
developmentfrom
feat/implementación-del-módulo-de-órdenes
Jun 2, 2026

Hidden character warning

The head ref may contain hidden characters: "feat/implementaci\u00f3n-del-m\u00f3dulo-de-\u00f3rdenes"
Merged

Feat/implementación del módulo de órdenes#22
Abisaac1809 merged 6 commits into
developmentfrom
feat/implementación-del-módulo-de-órdenes

Conversation

@Abisaac1809

@Abisaac1809 Abisaac1809 commented Jun 1, 2026

Copy link
Copy Markdown
Collaborator

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 por authorizeEventRole('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 mediante ITransactionManager. Las validaciones del frontend están alineadas con los esquemas Zod de @eventflow/shared.


🛠️ Cambios Implementados

1. Base de Datos (packages/api)

  • Migración de Prisma (add_sales_module):
    • Nuevo modelo Customer con campos: id, idNumber (único), fullName, phone?, email?, createdAt, updatedAt.
    • Nuevo modelo Order con campos: id, eventId (FK), customerId (FK), soldById (FK → User), exchangeRateId (FK → ExchangeRate), currency, totalAmount (Decimal), createdAt. Relaciones items y payments.
    • Nuevo modelo OrderItem con campos: id, orderId (FK), ticketTypeId (FK → TicketType), quantity, unitPrice (Decimal), currency, subtotal (Decimal).
    • Nuevo modelo Payment con campos: id, orderId (FK), paymentMethodId (FK → PaymentMethod), amount (Decimal), currency, reference?, receiptUrl?, status (default APPROVED), verifiedById (FK → User), verifiedAt.
    • Relaciones nuevas en modelos existentes: orders en Event, ExchangeRate y Customer; orderItems en TicketType; payments en PaymentMethod; ordersSold y paymentsVerified en User.

2. Esquemas y Tipos Compartidos (@eventflow/shared)

  • SalePaymentSchema: campos paymentMethodId, amount, currency (USD | VES | EUR), reference?, receiptUrl?.
  • SaleToCreateSchema: campos ticketTypeId, quantity, customer (objeto con idNumber, fullName, phone?, email?), payments (array mínimo 1 elemento).
  • Tipos de lectura: OrderSummaryType, OrderDetailType, OrderItemSummaryType, PaymentSummaryType, OrderCustomerType, ListOrdersResponse.
  • Utilidades de moneda en utils/currency.ts: convertToUSD() y sumPaymentsInUSD() 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 con runInTransaction<T>(fn).
  • PrismaTransactionManager — implementación que ejecuta prisma.$transaction().
  • prismaTransactionHelper.ts — extrae el cliente Prisma del contexto opaco en la capa de infraestructura.

Módulo sales

  • POST /api/events/:eventId/sales — registra una nueva venta. Lógica de negocio:
    1. Verifica que exista tasa de cambio vigente (NoActiveExchangeRateError 400).
    2. Valida que el TicketType exista, esté activo y dentro del período de venta (TicketTypeNotFoundError 404, TicketTypeNotSellableError 400).
    3. Convierte el precio a USD y calcula el total; verifica que el monto pagado cubra el total (InsufficientPaymentError 400).
    4. Dentro de la transacción: upsert del cliente por idNumber, decremento atómico de soldQuantity con verificación de stock disponible (InsufficientTicketsError 409), creación de Order, OrderItem y Payment.
  • GET /api/events/:eventId/sales — lista paginada de órdenes con filtros opcionales: idNumber, startDate, endDate, ticketTypeId. Retorna ListOrdersResponse (orders, total, page, limit).
  • GET /api/events/:eventId/sales/:orderId — detalle completo de una orden con cliente, items y pagos (OrderNotFoundError 404).
  • Acceso protegido por 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

  • Entidades: Customer, Order (con items, payments, soldByName, exchangeRate desnormalizados para mapeo).
  • Interfaces: ICustomerRepository (con upsertByIdNumber), IOrderRepository (con create, findById, findAndCount), ITicketTypeRepository extendida con decrementSoldQuantityAtomic.
  • Implementaciones: PrismaCustomerRepository, PrismaOrderRepository, PrismaTicketTypeRepository (actualizado).
  • SalesMapper — convierte entidades Order a OrderSummaryType y OrderDetailType.
  • container.ts actualizado con PrismaCustomerRepository, PrismaOrderRepository, PrismaTransactionManager y el módulo events/:eventId/sales.

4. Frontend / Web (packages/web)

  • Servicio: salesService con createSale(), listOrders() (con parámetros de filtro y paginación) y getOrderDetail().
  • Hook useCurrentExchangeRate: carga la tasa vigente del evento con soporte de cancelación de efecto y método refetch. Usado en Layout.tsx para mostrar la tasa en tiempo real en el sidebar (reemplaza el valor hardcodeado 36.50 Bs.). Muestra "Cargando...", la tasa formateada con fecha, o "Sin tasa activa" según el estado.
  • SalesPage reemplaza EventPlaceholderPage en la ruta sales. Estructura en dos vistas:
    • Vista de lista: tabla de órdenes con columnas cliente, CI, tipo de entrada, cantidad, total, vendido por, métodos de pago y fecha. Barra de filtros por cédula, rango de fechas y tipo de entrada. Paginación con LIMIT = 15. Fila clickeable que abre el modal de detalle. Estados de carga, vacío y error.
    • Modal de detalle (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 ×.
    • Formulario de nueva venta (wizard de 3 pasos):
      • Paso 1 — Seleccionar entrada: cards de tipos de entrada disponibles con precio en USD y Bs., cantidad disponible, período de venta. Tipos no vendibles aparecen deshabilitados con razón. Selector de cantidad.
      • Paso 2 — Datos del cliente: react-hook-form + SaleToCreateSchema vía zodResolver. Campos idNumber, fullName, phone?, email?.
      • Paso 3 — Pagos: useFieldArray para 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 (usando sumPaymentsInUSD), monto pagado y diferencia. El botón "Confirmar venta" se habilita cuando el monto cubierto ≥ total.
    • Al completar la venta el formulario se reinicia al paso 1, la lista de órdenes se recarga y se muestra el detalle de la orden creada.
    • isSellable() helper para validar disponibilidad de un tipo de entrada en el cliente.

closes #12

Copilot AI review requested due to automatic review settings June 1, 2026 23:14
@Abisaac1809 Abisaac1809 linked an issue Jun 1, 2026 that may be closed by this pull request
31 tasks

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread packages/web/src/features/events/hooks/useCurrentExchangeRate.ts
Comment thread packages/web/src/features/events/hooks/useCurrentExchangeRate.ts Outdated
Comment thread packages/web/src/components/Layout.tsx Outdated
Comment thread packages/api/src/infrastructure/repositories/PrismaOrderRepository.ts Outdated
Comment thread packages/api/src/infrastructure/repositories/PrismaOrderRepository.ts Outdated
Comment thread packages/api/src/infrastructure/repositories/PrismaOrderRepository.ts Outdated
Abisaac1809 and others added 2 commits June 1, 2026 19:24
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@Abisaac1809 Abisaac1809 requested a review from cristian907 June 2, 2026 01:40

@cristian907 cristian907 left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@Abisaac1809 Abisaac1809 merged commit 617ef56 into development Jun 2, 2026
1 check passed
@Abisaac1809 Abisaac1809 deleted the feat/implementación-del-módulo-de-órdenes branch June 2, 2026 02:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

FEAT: Implementación del Módulo de Órdenes

3 participants