Appearance
RC-CRM: Modelo de Datos
| Campo | Detalle |
|---|---|
| Estado | Borrador |
| Documento padre | RC-crm-tickets.md |
| Reuniones fuente | 2026-03-09, 2026-03-10-p2 |
| Clasificación | Proyecto Customware para Reccius (no es módulo de Tu Magistral) |
1. Implementación en Twenty CRM
Twenty CRM utiliza un sistema de objetos personalizables (Custom Objects) que se almacenan en PostgreSQL. Esto permite modelar las entidades del CRM de Reccius aprovechando tanto los objetos nativos de Twenty como objetos custom adicionales.
Mapeo de entidades a objetos de Twenty
| Entidad del modelo | Objeto en Twenty | Tipo | Detalle |
|---|---|---|---|
| Contacto | People (nativo) + campos custom | Nativo | Twenty incluye People con nombre, email, teléfono, empresa. Se agregan campos custom: RUT, tipo (paciente/médico/farmacia/institución/proveedor), notas |
| Organización | Companies (nativo) + campos custom | Nativo | Twenty incluye Companies con nombre, dirección, email. Se agregan campos custom: RUT, tipo (farmacia/clínica/hospital/convenio) |
| Ticket | Custom Object "Ticket" | Custom | Objeto personalizado con campos: número, asunto, descripción, estado, prioridad, canal de origen, timestamps |
| Interacción | Activities (nativo) + campos custom | Nativo | Twenty incluye Activities con timeline. Se agregan campos custom: tipo de canal, dirección (entrante/saliente/interna), adjuntos |
| Pipeline | Pipeline (nativo) | Nativo | Twenty incluye pipeline views configurables con etapas y kanban |
| EtapaTicket | Gestionado por el pipeline nativo de Twenty | Nativo | Twenty registra automáticamente el movimiento entre etapas del pipeline |
| Usuario | Workspace Members (nativo) | Nativo | Twenty gestiona usuarios del workspace con roles y permisos |
| Alerta | Custom Object "Alerta" o workflows | Custom | Se puede implementar como objeto custom o mediante workflows automáticos de Twenty |
Consideraciones de compatibilidad
- Twenty usa PostgreSQL como base de datos, lo cual es compatible con Supabase si en el futuro se necesita integrar con Tu Magistral.
- La API GraphQL de Twenty permite acceder y manipular todos los objetos (nativos y custom) de forma programática.
- Los Custom Objects en Twenty se crean desde la interfaz de administración o vía API, sin necesidad de modificar el código fuente.
2. Diagrama entidad-relación
Nota: El siguiente diagrama ER representa el modelo lógico de datos. En Twenty CRM, este modelo se implementa mediante una combinación de objetos nativos (People, Companies, Activities, Pipeline) y Custom Objects (Ticket, Alerta). Las relaciones se configuran como campos de relación (Relation fields) en Twenty.
3. Descripción de entidades
Contacto
Representa a cualquier persona o entidad con la que Reccius tiene comunicación. Un contacto puede ser un paciente individual, un médico prescriptor, una farmacia, una institución de salud o un proveedor.
En Twenty: se implementa como People (objeto nativo) con campos personalizados adicionales.
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
| id | UUID | Sí | Identificador único |
| nombre | String | Sí | Nombre completo o razón social |
| rut | String | No | RUT chileno (único si se ingresa) |
| String | No | Email principal de contacto | |
| teléfono | String | No | Teléfono principal (puede ser WhatsApp) |
| tipo | Enum | Sí | paciente, médico, farmacia, institución, proveedor |
| organizacion_id | UUID (FK) | No | Organización a la que pertenece (si aplica) |
| notas | Text | No | Notas generales sobre el contacto |
| created_at | Timestamp | Sí | Fecha de creación del registro |
| updated_at | Timestamp | Sí | Fecha de última modificación |
Nota: Un contacto puede existir sin organización (ej: paciente individual) o estar asociado a una (ej: médico de una clínica).
Organización
Agrupa contactos bajo una entidad común. Ejemplos: Farmacia Salco (convenio), Clínica Santa Gemita (convenio), Hospital X.
En Twenty: se implementa como Companies (objeto nativo) con campos personalizados adicionales.
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
| id | UUID | Sí | Identificador único |
| nombre | String | Sí | Nombre de la organización |
| rut | String | No | RUT de la organización (único si se ingresa) |
| tipo | Enum | Sí | farmacia, clínica, hospital, convenio |
| dirección | String | No | Dirección física |
| teléfono | String | No | Teléfono principal |
| String | No | Email institucional | |
| notas | Text | No | Notas sobre la organización |
| created_at | Timestamp | Sí | Fecha de creación |
| updated_at | Timestamp | Sí | Fecha de última modificación |
Ticket
Unidad fundamental de trabajo del CRM. Cada solicitud, consulta, reclamo o gestión se representa como un ticket. Se origina desde cualquier canal y tiene un ciclo de vida definido.
En Twenty: se implementa como Custom Object "Ticket" con todos los campos definidos a continuación.
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
| id | UUID | Sí | Identificador único |
| número | String | Sí | Número legible de ticket (ej: TK-20260325-001), único |
| asunto | String | Sí | Título breve de la solicitud |
| descripción | Text | No | Descripción detallada |
| estado | Enum | Sí | nuevo, asignado, en_gestion, esperando_respuesta, escalado, resuelto, cerrado |
| prioridad | Enum | Sí | baja, media, alta, urgente |
| canal_origen | Enum | Sí | email, whatsapp, teléfono, web, presencial |
| contacto_id | UUID (FK) | Sí | Contacto que originó la solicitud |
| organizacion_id | UUID (FK) | No | Organización asociada (si aplica) |
| asignado_a | UUID (FK) | No | Usuario responsable del ticket |
| pipeline_id | UUID (FK) | No | Pipeline al que pertenece (si aplica) |
| created_at | Timestamp | Sí | Fecha de creación del ticket |
| updated_at | Timestamp | Sí | Fecha de última modificación |
| primera_respuesta_at | Timestamp | No | Fecha de la primera respuesta al contacto |
| resuelto_at | Timestamp | No | Fecha en que se marcó como resuelto |
| cerrado_at | Timestamp | No | Fecha de cierre definitivo |
Nota sobre número de ticket: El formato sugerido es TK-YYYYMMDD-NNN (ej: TK-20260325-001). Permite identificación rápida y comunicación con el contacto ("su ticket es el TK-20260325-001").
Interacción
Cada comunicación registrada en un ticket. Puede ser un email enviado o recibido, un mensaje WhatsApp, una llamada telefónica, una nota interna o una visita presencial.
En Twenty: se implementa mediante Activities (objeto nativo) con campos personalizados para canal, dirección y adjuntos.
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
| id | UUID | Sí | Identificador único |
| ticket_id | UUID (FK) | Sí | Ticket al que pertenece |
| tipo | Enum | Sí | email, whatsapp, teléfono, nota_interna, presencial |
| contenido | Text | Sí | Texto de la interacción |
| dirección | Enum | Sí | entrante (del contacto), saliente (de Reccius), interna (nota entre equipo) |
| autor_id | UUID (FK) | Sí | Usuario que registró o envió la interacción |
| adjuntos | JSON | No | Lista de archivos adjuntos (fotos de receta, documentos, etc.) |
| created_at | Timestamp | Sí | Fecha y hora de la interacción |
Nota sobre adjuntos: El campo JSON contiene un arreglo de objetos con: nombre_archivo, url_almacenamiento, tipo_mime, tamano_bytes.
Pipeline
Flujo de trabajo configurable que define las etapas por las que pasa un ticket según su tipo. Permite personalizar el proceso para cotizaciones, reclamos, seguimientos, etc.
En Twenty: se implementa mediante Pipeline (funcionalidad nativa) con vistas kanban configurables.
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
| id | UUID | Sí | Identificador único |
| nombre | String | Sí | Nombre del pipeline (ej: "Cotización", "Reclamo") |
| etapas | JSON | Sí | Arreglo ordenado de etapas con nombre y configuración |
| activo | Boolean | Sí | Si el pipeline está disponible para uso |
| created_at | Timestamp | Sí | Fecha de creación |
| updated_at | Timestamp | Sí | Fecha de última modificación |
Ejemplo del campo etapas (JSON):
json
[
{"nombre": "Recibida", "orden": 1, "color": "#3B82F6"},
{"nombre": "En análisis", "orden": 2, "color": "#F59E0B"},
{"nombre": "Cotizada", "orden": 3, "color": "#8B5CF6"},
{"nombre": "Esperando confirmación", "orden": 4, "color": "#EF4444"},
{"nombre": "Confirmada", "orden": 5, "color": "#10B981"},
{"nombre": "Cerrada", "orden": 6, "color": "#6B7280"}
]EtapaTicket
Registro histórico de las etapas por las que ha pasado un ticket dentro de un pipeline. Permite calcular tiempo en cada etapa e identificar cuellos de botella.
En Twenty: gestionado automáticamente por el pipeline nativo de Twenty.
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
| id | UUID | Sí | Identificador único |
| ticket_id | UUID (FK) | Sí | Ticket que está en el pipeline |
| pipeline_id | UUID (FK) | Sí | Pipeline al que pertenece |
| etapa_nombre | String | Sí | Nombre de la etapa (coincide con Pipeline.etapas) |
| entered_at | Timestamp | Sí | Fecha y hora en que el ticket entró a esta etapa |
| exited_at | Timestamp | No | Fecha y hora en que el ticket salió de esta etapa (null si es la etapa actual) |
Usuario
Miembro del equipo de Reccius que opera el CRM. Cada usuario tiene un rol que define sus permisos.
En Twenty: se implementa mediante Workspace Members (funcionalidad nativa) con roles configurables.
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
| id | UUID | Sí | Identificador único |
| nombre | String | Sí | Nombre completo |
| String | Sí | Email corporativo (único) | |
| rol | Enum | Sí | ejecutiva, dirección, gerencia, administrador |
| activo | Boolean | Sí | Si el usuario está activo en el sistema |
| created_at | Timestamp | Sí | Fecha de creación |
| updated_at | Timestamp | Sí | Fecha de última modificación |
Roles y permisos:
| Rol | Crear tickets | Gestionar tickets | Escalar | Ver métricas | Configurar pipelines | Administrar usuarios |
|---|---|---|---|---|---|---|
| ejecutiva | Sí | Solo asignados | Sí | No | No | No |
| dirección | Sí | Todos | Sí | Parcial | No | No |
| gerencia | Sí | Todos | Sí | Todos | Sí | Sí |
| administrador | Sí | Todos | Sí | Todos | Sí | Sí |
Alerta
Notificación programada o generada automáticamente por el sistema para informar a un usuario sobre una situación que requiere atención.
En Twenty: se puede implementar como Custom Object "Alerta" o mediante workflows automáticos de Twenty con triggers.
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
| id | UUID | Sí | Identificador único |
| ticket_id | UUID (FK) | Sí | Ticket relacionado |
| usuario_id | UUID (FK) | Sí | Usuario destinatario de la alerta |
| tipo | Enum | Sí | inactividad, sla, escalamiento, reasignación, mención, recordatorio |
| mensaje | String | Sí | Texto descriptivo de la alerta |
| programada_para | Timestamp | Sí | Fecha y hora en que debe dispararse la alerta |
| enviada | Boolean | Sí | Si la alerta ya fue enviada |
| enviada_at | Timestamp | No | Fecha y hora en que se envió (null si no enviada) |
| created_at | Timestamp | Sí | Fecha de creación |
4. Índices recomendados
Nota: Twenty CRM gestiona los índices de sus objetos nativos automáticamente. Los índices listados a continuación aplican para los Custom Objects y como referencia para optimización si se accede directamente a PostgreSQL.
| Tabla | Columnas | Tipo | Propósito |
|---|---|---|---|
| Contacto | rut | Único | Búsqueda rápida por RUT |
| Contacto | Índice | Búsqueda rápida por email | |
| Contacto | teléfono | Índice | Búsqueda por teléfono (WhatsApp) |
| Contacto | nombre | GIN | Búsqueda de texto parcial por nombre |
| Contacto | organizacion_id | Índice | Listar contactos de una organización |
| Ticket | número | Único | Búsqueda por número de ticket |
| Ticket | estado | Índice | Filtrar tickets por estado |
| Ticket | asignado_a | Índice | Bandeja de tickets por ejecutiva |
| Ticket | contacto_id | Índice | Historial de tickets por contacto |
| Ticket | organizacion_id | Índice | Tickets por organización |
| Ticket | pipeline_id, estado | Compuesto | Vista de pipeline con filtro de estado |
| Ticket | created_at | Índice | Ordenamiento cronológico |
| Interacción | ticket_id, created_at | Compuesto | Timeline de interacciones por ticket |
| EtapaTicket | ticket_id, pipeline_id | Compuesto | Historial de etapas por ticket |
| Alerta | usuario_id, enviada | Compuesto | Alertas pendientes por usuario |
| Alerta | programada_para, enviada | Compuesto | Alertas pendientes de envío (cron job) |
5. Volumetría estimada
Basado en el diagnóstico de Reccius (reunión 2026-03-09 y 2026-03-10-p2):
| Entidad | Volumen inicial estimado | Crecimiento mensual estimado |
|---|---|---|
| Contacto | 2.000 - 5.000 | 100 - 200 |
| Organización | 50 - 100 | 5 - 10 |
| Ticket | 0 (nuevo) | 500 - 1.000 |
| Interacción | 0 (nuevo) | 2.000 - 5.000 |
| Pipeline | 4 - 5 | Raro (configuración) |
| Usuario | 6 - 8 | Raro |
| Alerta | 0 (nuevo) | 200 - 500 |
Nota: Reccius procesa aproximadamente 40.000 recetas al año (mencionado por Andro en reunión 2026-03-10-p2), lo que equivale a ~3.300 recetas mensuales. No todas generarán ticket en el CRM, pero da una referencia de volumen operativo. Este volumen es perfectamente manejable por una instancia self-hosted de Twenty en un VPS modesto.
6. Consideraciones técnicas
Almacenamiento de adjuntos
Los archivos adjuntos (fotos de receta, documentos) no se almacenan en la base de datos. Se utiliza almacenamiento de objetos (ej: S3, Supabase Storage) y en la tabla Interacción se guarda solo la referencia (URL y metadatos). Twenty soporta almacenamiento de archivos de forma nativa.
Soft delete
Los contactos, organizaciones y tickets no se eliminan físicamente. Se marcan como inactivos o archivados para mantener la trazabilidad histórica. Twenty maneja soft delete de forma nativa en sus objetos.
Auditoría
Toda modificación a un ticket (cambio de estado, reasignación, edición) genera un registro de auditoría con: quién hizo el cambio, qué cambió, cuándo, valor anterior y valor nuevo. Twenty registra automáticamente las actividades en el timeline de cada objeto.
Zona horaria
Todos los timestamps se almacenan en UTC. La presentación en la interfaz se convierte a la zona horaria de Chile (America/Santiago). Twenty maneja zonas horarias de forma nativa.
Compatibilidad con PostgreSQL
Twenty utiliza PostgreSQL como base de datos. Si en el futuro se necesita integrar con Supabase (para Tu Magistral u otros servicios), la compatibilidad de base de datos facilita la conexión directa o replicación.
Historial de cambios
| Fecha | Reunión | Cambio |
|---|---|---|
| 2026-03-25 | -- | Creación del modelo de datos basado en requerimientos RC-CRM |
| 2026-03-25 | -- | Actualización: se agrega sección de implementación en Twenty CRM con mapeo de entidades a objetos nativos y custom; se agregan notas de Twenty en cada entidad; se corrigen tildes |