Skip to main content

Estructura Lógica de Productos: Canal → Producto → Paquete → Variante → Cobertura

Este documento explica la estructura jerárquica de productos en InsureHero, detallando qué se configura en cada nivel (precios, reglas, moneda).

Vista General de la Estructura

Vista General de la Estructura

Diagrama jerárquico mostrando la relación entre Canal, Producto, Paquete, Variante y Cobertura.

Zoom: 100%

💡 Usa la rueda del mouse para hacer zoom. Arrastra con el botón izquierdo para mover el diagrama.

Estructura Jerárquica InsureHero1:N1:NN:MN:M1:N1:Nusa💰 MONEDACurrency🌍 PAÍSCountryopera enusa🔵 CANALMoneda (currency_id)País (country_id)API KeyStatusEmailTimezone (IANA) · reportes/skills🟣 PRODUCTOCódigo (code)Pricing (JSONB)Features (JSONB)Lifecycle (JSONB)Overrides (JSONB)🟠 PAQUETENombreDescripciónPricing Rules (JSONB)Tipo: one_time/recurring🟢 VARIANTEGross Price (expresión)Taxes (JSONB)Markup (JSONB)Pricing RulesSubject SchemaClaim Schema🔴 COBERTURANombreTipoNúmero AseguradoraMetadata (JSONB)Leyenda de Relaciones1:N - Uno a MuchosN:M - Muchos a Muchos1:1 - Uno a Uno--- - Relación directa

Diagramas de Estructura

Las vistas siguientes son diagramas interactivos (zoom y arrastre). No mostramos aquí el código fuente de los gráficos: solo el diagrama, para una lectura más clara.

Diagrama de Relaciones (Entity Relationship)

Diagrama de Relaciones (Entity Relationship)

Este diagrama muestra todas las tablas de la base de datos, sus campos, tipos de datos y las relaciones entre ellas. Las relaciones están etiquetadas con su cardinalidad (1:N, N:M, N:1).

Zoom: 100%

💡 Usa la rueda del mouse para hacer zoom. Arrastra con el botón izquierdo para mover el diagrama.

Modelo de Datos - InsureHerotiene(1:N)tiene(1:N)tiene(1:N)tiene(1:N)usa(N:1)opera_en(N:1)contiene(1:N)pertenece_a(1:N)incluye(1:N)pertenece_a(1:N)tiene(1:N)🔵 CHANNEL🔑 id: uuid🔗 currency_id: uuid - 🔑 Moneda (no modificable)CURRENCY🔗 country_id: uuid - 🌍 País (no modificable)COUNTRYname: textapi_key: uuidstatus: textemail: texttimezone: text - 🕐 IANA · ventanas locales (reportes, skills)phone_number: textis_broker: booleanallow_handshake: booleanallow_ia: boolean🟣 PRODUCT🔑 id: uuid🔗 channel_id: uuidCHANNELcode: text - Código únicopricing: jsonb - 💰 Configuración de preciosfeatures: jsonb - ⚙️ Característicaslifecycle: jsonb - 🔄 Ciclo de vidaoverrides: jsonb - 🔧 Modificaciones🟠 PACKAGE🔑 id: uuid🔗 channel_id: uuidCHANNELname: textdescription: textpricing_rules: jsonb - 📋 Reglas de precios🔷 PRODUCT_PACKAGE🔑 id: uuid🔗 product_id: uuidPRODUCT🔗 package_id: uuidPACKAGE🔗 channel_id: uuidCHANNEL🟢 VARIANT🔑 id: uuid🔗 channel_id: uuidCHANNEL🔗 coverage_id: uuidCOVERAGEname: textgross_price: text - 💰 Expresión matemáticataxes: jsonb - 💸 Impuestospricing_rules: jsonb - 📋 Reglas de preciospricing_type: text - one_time | recurringmarkup: jsonb - 📈 Margen de gananciacoverage_limits: numericdeductible: textconditions: textexclusions: textsubject_schema: jsonb - 📝 Esquema del sujetoclaim_schema: jsonb - 📋 Esquema de reclamos🔴 COVERAGE🔑 id: uuid🔗 channel_id: uuidCHANNEL🔗 insurer_id: uuidINSURERname: textdescription: textinsurer_coverage_number: texttype: textmetadata: jsonb🔶 PACKAGE_VARIANT🔑 id: uuid🔗 package_id: uuidPACKAGE🔗 variant_id: uuidVARIANT🔗 channel_id: uuidCHANNEL💰 CURRENCY🔑 id: uuidcode: textname: textsymbol: text🌍 COUNTRY🔑 id: uuidcode: textname: textLeyenda🔑 - Primary Key (PK)🔗 - Foreign Key (FK)1:N - Uno a MuchosN:M - Muchos a MuchosN:1 - Muchos a Uno--- - Relación con CURRENCY/COUNTRY

Descripción de Relaciones

  • CHANNEL → PRODUCT (1:N): Un canal puede tener múltiples productos.
  • CHANNEL → PACKAGE (1:N): Un canal puede tener múltiples paquetes.
  • CHANNEL → VARIANT (1:N): Un canal puede tener múltiples variantes.
  • CHANNEL → COVERAGE (1:N): Un canal puede tener múltiples coberturas.
  • CHANNEL → CURRENCY (N:1): Un canal usa una moneda específica (no modificable después de la creación).
  • CHANNEL → COUNTRY (N:1): Un canal opera en un país específico (no modificable después de la creación).
  • PRODUCT ↔ PACKAGE (N:M): Un producto puede tener múltiples paquetes y un paquete puede pertenecer a múltiples productos (a través de PRODUCT_PACKAGE).
  • PACKAGE ↔ VARIANT (N:M): Un paquete puede incluir múltiples variantes y una variante puede pertenecer a múltiples paquetes (a través de PACKAGE_VARIANT).
  • COVERAGE → VARIANT (1:N): Una cobertura puede tener múltiples variantes.

Diagrama de Jerarquía Visual

Diagrama de Jerarquía Visual

Vista gráfica de la estructura jerárquica mostrando las relaciones entre los diferentes niveles.

Zoom: 100%

💡 Usa la rueda del mouse para hacer zoom. Arrastra con el botón izquierdo para mover el diagrama.

Jerarquía Visual - InsureHero1:N1:N1:N1:Nusaopera_enN:MN:M1:N🔵 CANAL🟣 PRODUCTO🟠 PAQUETE🟢 VARIANTE🔴 COBERTURA💰 MONEDA🌍 PAÍS

Diagrama de Flujo de Configuración

Diagrama de Flujo de Configuración

Flujo paso a paso para crear y configurar un producto completo en InsureHero.

Zoom: 100%

💡 Usa la rueda del mouse para hacer zoom. Arrastra con el botón izquierdo para mover el diagrama.

Flujo de Configuración de ProductosInicio: Crear Producto🔵 CANALMoneda (currency_id)País (country_id)Timezone IANA (reportes/skills)🟣 PRODUCTOCódigoPricing JSONBFeaturesLifecycleOverrides🟠 PAQUETENombreDescripciónPricing Rules🟢 VARIANTEGross PriceTaxesMarkupPricing RulesSubject SchemaClaim Schema🔴 COBERTURANombreTipoNúmero AseguradoraProducto Completo

Diagrama de Cálculo de Precios

Diagrama de Cálculo de Precios

Proceso paso a paso para calcular el precio final de un producto, desde el sujeto asegurado hasta el precio neto y bruto.

Zoom: 100%

💡 Usa la rueda del mouse para hacer zoom. Arrastra con el botón izquierdo para mover el diagrama.

Cálculo de Precios - InsureHeroSujeto Aseguradosubject_schemaEvaluargross_priceexpresión matemáticaPrecio BaseEj: 1000 + age*50AplicarImpuestostaxes JSONBPrecio + ImpuestosAplicarMarkupmarkup JSONB💰 Precio Final BrutoPrecio NetoBruto - Impuestos

Diagrama de Campos por Nivel

Diagrama de Campos por Nivel

Vista de todos los campos organizados por nivel jerárquico en la estructura de InsureHero.

Zoom: 100%

💡 Usa la rueda del mouse para hacer zoom. Arrastra con el botón izquierdo para mover el diagrama.

Campos por Nivel - Estructura InsureHeroEstructuraInsureHero🔵 CANALcurrency_id 🔑country_id 🌍nameapi_keystatusemailtimezone 🕐 IANA🟣 PRODUCTOcodepricing JSONB 💰features JSONB ⚙️lifecycle JSONB 🔄overrides JSONB 🔧🟠 PAQUETEnamedescriptionpricing_rules JSONB 📋pricing_typeintervalbilling_cycle🟢 VARIANTEgross_price 💰taxes JSONB 💸markup JSONB 📈pricing_rules JSONBcoverage_limitsdeductibleconditionsexclusionssubject_schema 📝claim_schema 📋🔴 COVERAGEnametypeinsurer_coverage_numbermetadata JSONB

Descripción Detallada por Nivel

1. CANAL (Channel)

El Canal es el nivel más alto de la jerarquía y representa una entidad que vende seguros a través de la plataforma InsureHero.

Configuración en este nivel:

  • Moneda (currency_id):

    • La moneda base para todas las transacciones del canal
    • Se establece al crear el canal y no puede modificarse después
    • Referencia a la tabla currencies
  • País (country_id):

    • El país donde opera el canal
    • Se establece al crear el canal y no puede modificarse después
    • Referencia a la tabla countries
  • Configuración General:

    • name: Nombre del canal
    • api_key: Clave API única para integraciones
    • status: Estado del canal (ACTIVE, INACTIVE)
    • email: Email del canal (también usado como remitente en ciertos envíos desde Edge Functions)
    • phone_number: Número de teléfono
    • timezone: Zona horaria en formato IANA (p. ej. America/Mexico_City). Se usa para interpretar ventanas de tiempo “locales” en reportes y skills (p. ej. correo agregado de errores de emisión junto con pg_cron). Detalle: Notificaciones, skills y Supabase Edge.
    • is_broker: Indica si el canal es un broker
    • allow_handshake: Permite handshake
    • allow_ia: Habilita agente de IA
    • Configuración de chatbot (opcional)

Tabla en Base de Datos:

CREATE TABLE "channels" (
id uuid PRIMARY KEY,
currency_id uuid NOT NULL, -- Moneda del canal
country_id uuid NOT NULL, -- País del canal
name text NOT NULL,
api_key uuid NOT NULL,
status text DEFAULT 'ACTIVE',
email text,
timezone text, -- IANA: hora local para reportes / skills (ver Edge + cron)
-- ... otros campos
);

2. PRODUCTO (Product)

El Producto agrupa uno o más paquetes y define características generales del producto de seguro.

Configuración en este nivel:

  • Código del Producto (code):

    • Identificador único del producto dentro del canal
  • Precios (pricing - JSONB):

    • Configuración de precios a nivel de producto
    • Puede contener reglas de precios generales
    • Estructura flexible en formato JSON
  • Características (features - JSONB):

    • Características y funcionalidades del producto
    • Configuración de características especiales
  • Ciclo de Vida (lifecycle - JSONB):

    • Configuración del ciclo de vida del producto
    • Define estados y transiciones del producto
  • Modificaciones (overrides - JSONB):

    • Permite sobrescribir configuraciones heredadas
    • Personalización específica del producto

Tabla en Base de Datos:

CREATE TABLE "products" (
id uuid PRIMARY KEY,
channel_id uuid NOT NULL,
code text NOT NULL,
pricing jsonb NOT NULL, -- Configuración de precios
features jsonb NOT NULL, -- Características
lifecycle jsonb NOT NULL, -- Ciclo de vida
overrides jsonb NOT NULL, -- Modificaciones
-- ... otros campos
);

Relación con Paquetes:

  • Un producto puede tener múltiples paquetes (relación N:M a través de products_packages)
  • Un paquete puede pertenecer a múltiples productos

3. PAQUETE (Package)

El Paquete agrupa variantes relacionadas y define reglas de precios a nivel de paquete.

Configuración en este nivel:

  • Nombre (name):

    • Nombre descriptivo del paquete
  • Descripción (description):

    • Descripción detallada del paquete
  • Reglas de Precios (pricing_rules - JSONB):

    • Tipo de precio (pricing_type):
      • one_time: Pago único
      • recurring: Pago recurrente
    • Intervalo (interval) (solo para recurring):
      • day: Diario
      • week: Semanal
      • month: Mensual
      • year: Anual
    • Intervalo de conteo (interval_count):
      • Número de intervalos (ej: cada 2 meses)
    • Ciclo de facturación (billing_cycle):
      • start_of_month: Inicio del mes
      • end_of_month: Fin del mes
      • anniversary: Aniversario
    • Período de gracia (grace_period) (opcional):
      • Días de gracia para pagos
    • Período de prueba (trial_period) (opcional):
      • Días de período de prueba

Tabla en Base de Datos:

CREATE TABLE "packages" (
id uuid PRIMARY KEY,
channel_id uuid NOT NULL,
name text NOT NULL,
description text,
pricing_rules jsonb DEFAULT '{}', -- Reglas de precios
-- ... otros campos
);

Ejemplo de pricing_rules:

{
"pricing_type": "recurring",
"interval": "month",
"interval_count": "1",
"billing_cycle": "start_of_month",
"grace_period": "7",
"trial_period": "30"
}

Relación con Variantes:

  • Un paquete puede tener múltiples variantes (relación N:M a través de packages_variants)
  • Una variante puede pertenecer a múltiples paquetes

4. VARIANTE (Variant)

La Variante es el nivel donde se define el precio específico y las condiciones detalladas de la cobertura.

Configuración en este nivel:

  • Nombre (name):

    • Nombre de la variante
  • Precio Bruto (gross_price):

    • Precio base de la variante
    • Puede ser una expresión matemática que se evalúa dinámicamente
    • Ejemplo: "100 + (age * 2)" donde age viene del subject_schema
  • Impuestos (taxes - JSONB):

    • Array de impuestos aplicables
    • Cada impuesto puede ser:
      • Tipo rate: Porcentaje sobre el precio bruto
      • Tipo value: Valor fijo
    • Ejemplo:
      [
      {
      "name": "IVA",
      "rate": "0.16",
      "type": "rate"
      },
      {
      "name": "Tasa fija",
      "value": "50",
      "type": "value"
      }
      ]
  • Reglas de Precios (pricing_rules - JSONB):

    • Similar a las reglas del paquete, pero específicas de la variante
    • Pueden sobrescribir las reglas del paquete
  • Tipo de Precio (pricing_type):

    • one_time o recurring
    • Puede heredar del paquete o definirse específicamente
  • Markup (markup - JSONB):

    • Margen de ganancia adicional
    • Puede contener múltiples niveles de markup
    • Cada entrada tiene un owner (channel / platform / insurer / broker) que identifica al actor que cobra el margen. En el pricing de la orden los markups se agregan por owner (markups_details) y se mantienen separados de los impuestos legales (taxes_details).
    • Cada entrada puede ser un monto fijo o una tasa (is_rate: true, porcentaje sobre el gross_price de la variante).
    • Ejemplo:
      [
      {
      "name": "Markup Canal",
      "owner": "channel",
      "gross_price": "50"
      }
      ]
  • Límites de Cobertura (coverage_limits):

    • Límite máximo de cobertura en valor numérico
  • Deducible (deductible):

    • Monto del deducible como texto (puede ser expresión)
  • Condiciones (conditions):

    • Texto descriptivo de las condiciones de la variante
  • Exclusiones (exclusions):

    • Texto descriptivo de las exclusiones
  • Esquema del Sujeto (subject_schema - JSONB):

    • Define los campos requeridos para el sujeto asegurado
    • Se usa para validar y calcular precios dinámicos
    • Ejemplo:
      {
      "age": {
      "type": "number",
      "required": true,
      "label": "Edad"
      },
      "vehicle_value": {
      "type": "number",
      "required": true,
      "label": "Valor del vehículo"
      }
      }
  • Esquema de Reclamos (claim_schema - JSONB):

    • Define los campos requeridos para presentar un reclamo
    • Estructura similar a subject_schema

Tabla en Base de Datos:

CREATE TABLE "variants" (
id uuid PRIMARY KEY,
channel_id uuid NOT NULL,
coverage_id uuid NOT NULL, -- Relación con cobertura
name text NOT NULL,
gross_price text NOT NULL, -- Expresión matemática
taxes jsonb NOT NULL, -- Array de impuestos
pricing_rules jsonb, -- Reglas de precios
pricing_type text, -- Tipo de precio
markup jsonb NOT NULL, -- Margen de ganancia
coverage_limits numeric DEFAULT 0,
deductible text,
conditions text NOT NULL,
exclusions text NOT NULL,
subject_schema jsonb NOT NULL, -- Esquema del sujeto
claim_schema jsonb, -- Esquema de reclamos
-- ... otros campos
);

Cálculo de Precios:

El precio final se calcula:

  1. Se evalúa gross_price usando los valores del subject_schema
  2. Se aplican los impuestos (taxes)
  3. Se aplica el markup (markup)
  4. El precio neto = precio bruto - impuestos

5. COBERTURA (Coverage)

La Cobertura es el nivel más bajo y representa el tipo de seguro base proporcionado por una aseguradora.

Configuración en este nivel:

  • Nombre (name):

    • Nombre de la cobertura
  • Descripción (description):

    • Descripción detallada de la cobertura
  • Número de Cobertura del Asegurador (insurer_coverage_number):

    • Identificador de la cobertura en el sistema de la aseguradora
  • Tipo (type):

    • Tipo de cobertura (ej: "Vida", "Salud", "Auto", etc.)
  • Metadatos (metadata - JSONB):

    • Información adicional flexible en formato JSON

Tabla en Base de Datos:

CREATE TABLE "coverages" (
id uuid PRIMARY KEY,
channel_id uuid NOT NULL,
insurer_id uuid, -- Relación con aseguradora
name text NOT NULL,
description text,
insurer_coverage_number text NOT NULL,
type text,
metadata jsonb DEFAULT '{}',
-- ... otros campos
);

Relación con Variantes:

  • Una cobertura puede tener múltiples variantes (1:N)
  • Cada variante pertenece a una única cobertura

Flujo de Configuración de Precios

Herencia y Precedencia

  1. Moneda: Se establece a nivel de Canal y se aplica a todos los niveles inferiores
  2. Reglas de Precio:
    • Se pueden definir en Paquete y Variante
    • Las reglas de Variante tienen precedencia sobre las de Paquete
  3. Precio Base: Se define en Variante (gross_price)
  4. Impuestos: Se aplican en Variante sobre el precio bruto
  5. Markup: Se aplica en Variante después de impuestos

Ejemplo de Cálculo de Precio Final

Canal: Moneda = USD

Variante:
- gross_price = "1000 + (age * 50)"
- taxes = [{"rate": "0.16", "type": "rate"}]
- markup = [{"gross_price": "100"}]

Sujeto asegurado: age = 30

Cálculo:
1. Precio base = 1000 + (30 * 50) = 2500 USD
2. Impuesto (16%) = 2500 * 0.16 = 400 USD
3. Precio con impuesto = 2500 + 400 = 2900 USD
4. Markup = 100 USD
5. Precio final bruto = 2900 + 100 = 3000 USD
6. Precio neto = 3000 - 400 = 2600 USD

Resumen de Configuraciones por Nivel

NivelMonedaPreciosReglasEsquemasOtros
Canal✅ (currency_id)País, API Key, Configuración general
Producto❌ (hereda)✅ (pricing JSONB)Código, Features, Lifecycle, Overrides
Paquete❌ (hereda)✅ (pricing_rules JSONB)Nombre, Descripción
Variante❌ (hereda)✅ (gross_price, taxes, markup)✅ (pricing_rules JSONB)✅ (subject_schema, claim_schema)Límites, Deducible, Condiciones, Exclusiones
Cobertura❌ (hereda)Nombre, Tipo, Número de aseguradora

Notas Importantes

  1. Moneda: Una vez establecida en el Canal, no puede modificarse. Esto asegura consistencia en todas las transacciones.

  2. Expresiones Matemáticas: El gross_price en Variantes puede usar expresiones que se evalúan dinámicamente usando valores del subject_schema.

  3. Relaciones N:M:

    • Productos ↔ Paquetes (a través de products_packages)
    • Paquetes ↔ Variantes (a través de packages_variants)
  4. Validaciones:

    • Los UIDs deben ser únicos dentro del mismo canal
    • Los esquemas (subject_schema, claim_schema) tienen palabras reservadas que no pueden usarse
  5. Soft Delete: Todas las tablas principales tienen deleted_at para implementar eliminación lógica.


Del catálogo a la operación: risk items

La jerarquía anterior describe qué puedes vender. En la operación diaria, las ventas, integraciones y el portal del titular trabajan sobre risk items: la instancia concreta vinculada a un canal, un paquete, titular y variantes. Resumen conceptual y enlaces a APIs: Risk item (concepto central).


Referencias en el Código

  • Migración de Base de Datos: apps/next/supabase/migrations/20250204211512_remote_schema.sql
  • Validaciones: apps/next/src/validations/
  • Routers TRPC: apps/next/src/trpc/
  • Utilidades de Paquetes: apps/next/src/utils/package.utils.ts
  • Cálculo de Precios: apps/next/src/utils/processPayment.utils.ts