Propósito
El módulo de Contract Addons permite agregar complementos a un contrato existente, como bloques adicionales de invitados. Cada addon se registra como una línea independiente vinculada al contrato, con recálculo automático del monto total.
Modelo ContractAddon
El modelo Prisma ContractAddon rastrea cada complemento como un registro independiente:
model ContractAddon {
id String @id @default(uuid())
contractId String
addonType AddonType
description String?
quantity Int
unitPrice Decimal
totalPrice Decimal
metadata Json?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
contract Contract @relation(fields: [contractId], references: [id])
}
enum AddonType {
EXTRA_GUESTS
}
Campos clave
| Campo | Tipo | Descripción |
|---|---|---|
| addonType | AddonType | Tipo de complemento. Actualmente solo EXTRA_GUESTS, extensible a futuro |
| quantity | Int | Cantidad de unidades (ej: 50, 100, 200 invitados extra) |
| unitPrice | Decimal | Precio por unidad del bloque |
| totalPrice | Decimal | Monto total del addon (quantity * unitPrice) |
| metadata | Json? | Datos adicionales flexibles (ej: tipo de bloque seleccionado) |
Relación con Contract
El modelo Contract tiene una relación one-to-many con ContractAddon:
model Contract {
// ... campos existentes
addons ContractAddon[]
}
El monto total del contrato se calcula como:
totalAmount = basePackagePrice + sum(addons.totalPrice) - adjustments
Endpoints REST
Addons de un contrato
Contract Addons
/v1Capacidad de invitados
Guest Capacity
/v1Flujo de validación de invitados
El límite de invitados se valida en 3 puntos del sistema:
1. Agregar invitado individual
Cuando se agrega un invitado desde el formulario, el servicio verifica que currentGuests no exceda totalCapacity (maxGuests del plan + invitados extra de addons). Si se excede, retorna un error 400 con el mensaje de capacidad.
2. Carga masiva Excel/CSV
Durante la importación masiva, el sistema calcula previamente cuántos invitados se van a agregar y verifica contra la capacidad disponible antes de insertar registros. Si el lote excede la capacidad, retorna un error con el detalle de cuántos invitados se pueden agregar vs cuántos se intentaron importar.
3. Indicador visual
La lista de invitados en el admin muestra un indicador visual con:
- Número de invitados actuales vs capacidad total
- Barra de progreso con color (verde, amarillo, rojo)
- Botón para adquirir bloques adicionales cuando se acerca al límite
Recálculo automático del contrato
Cada vez que se agrega o elimina un ContractAddon, el sistema recalcula el monto total del contrato:
async recalculateContractAmount(contractId: string): Promise<Contract> {
const contract = await this.prisma.contract.findUnique({
where: { id: contractId },
include: { addons: true, package: true },
});
const basePrice = contract.package.price;
const addonsTotal = contract.addons.reduce(
(sum, addon) => sum + Number(addon.totalPrice),
0,
);
const adjustments = Number(contract.adjustments ?? 0);
const newTotal = basePrice + addonsTotal - adjustments;
return this.prisma.contract.update({
where: { id: contractId },
data: { totalAmount: newTotal },
});
}
Bloques de invitados por paquete
El tamaño y precio del bloque adicional de invitados depende del paquete contratado por el evento. No es un menú de opciones — cada paquete tiene un único bloque definido en su configuración (extraGuestBlockSize y extraGuestBlockPrice en ServicePackage).
| Paquete | Bloque | Precio | Costo/invitado |
|---|---|---|---|
| Básico | +50 invitados | $199 MXN | $3.98 |
| Essential | +100 invitados | $349 MXN | $3.49 |
| Plus | +100 invitados | $349 MXN | $3.49 |
| Premium | +100 invitados | $599 MXN | $5.99 |
| VIP | +200 invitados | $599 MXN | $3.00 |
| Enterprise | Ilimitados | — | — |
| Personalizado | +50 invitados | $199 MXN | $3.98 |
Si el organizador necesita más capacidad, compra múltiples bloques del mismo tamaño. Por ejemplo, un evento con Plan Básico que necesita 80 invitados extra comprará 2 bloques de 50 = 100 invitados adicionales por $398 MXN.
El costo variable real por invitado (comunicaciones) es de ~$1.28 MXN, por lo que el margen de los bloques es cercano al 98%. Los valores de extraGuestBlockSize y extraGuestBlockPrice se pueden ajustar por paquete desde la base de datos.
Extensibilidad
El enum AddonType está diseñado para crecer. Posibles tipos futuros:
| AddonType | Descripción | Estado |
|---|---|---|
EXTRA_GUESTS | Bloques adicionales de invitados | Implementado |
CUSTOM_DOMAIN | Dominio personalizado para la invitación | Futuro |
PRIORITY_SUPPORT | Soporte prioritario | Futuro |
EXTRA_STORAGE | Almacenamiento adicional para multimedia | Futuro |
Referencias
- ContractAddon model:
prisma/schema.prisma-- Modelo y enum AddonType - ContractsService:
src/modules/contracts/contracts.service.ts-- Lógica de addons y recálculo - ContractsController:
src/modules/contracts/contracts.controller.ts-- Endpoints REST - GuestsService:
src/modules/guests/guests.service.ts-- Validación de capacidad - Paquetes y Precios: Paquetes y Precios -- Planes, límites y bloques