9. CRM
CRM_ENABLED=false en el .env del servidor apaga todas las rutas /crm/*. Los controladores (CrmObjectTypeController, CrmRecordController, CrmViewController, WorkflowController) y las vistas existen en el código fuente, pero no son accesibles desde este panel. Esta sección documenta la funcionalidad a partir del código y debe validarse cuando la sección se reactive.
Introducción
El módulo CRM (Customer Relationship Management) del panel permite modelar tipos de objeto personalizados (clientes, leads, socios, contactos comerciales, candidatos, etc.), definir vistas para consultarlos (lista, kanban, calendario), añadir registros manualmente o de forma automática desde formularios, y configurar workflows que disparan acciones cuando se cumplen ciertas condiciones.
La idea es no atar el panel a un modelo de datos fijo: en lugar de tener una entidad "Lead" y otra "Cliente" hardcoded, el administrador define sus propios tipos de objeto con sus campos y relaciones, y el sistema genera automáticamente la UI para gestionarlos.
Acceso rápido
- En este despliegue: no hay entrada en el menú lateral. Cualquier acceso a
/crm/*devuelve 404 o respuesta vacía porque el router salta todo el grupo de rutas cuandoCRM_ENABLED=false. - Con la sección habilitada (referencia):
- Tipos de objeto:
/crm/object-types - Vistas:
/crm/views - Workflows:
/crm/workflows - Registros de un tipo concreto:
/crm/object-types/{slug}/records
- Tipos de objeto:
Pantalla principal
No hay captura disponible: la sección está deshabilitada en este despliegue. La descripción que sigue se basa en el código fuente de los controladores (CrmObjectTypeController, CrmRecordController, CrmViewController, WorkflowController) y debe validarse visualmente cuando la sección se reactive.
La pantalla principal del CRM, accesible en /crm cuando el módulo está activo, es un dashboard resumen con:
- Tarjetas de acceso rápido: Tipos de objeto, Vistas, Workflows.
- Contadores agregados: número de tipos definidos, número de vistas, número de workflows activos, número total de registros.
- Listado de los últimos registros creados (mezclando todos los tipos).
- Listado de workflows con su estado (activo / pausado / con errores).
Tareas habituales
9.1 Crear un tipo de objeto con sus campos
El primer paso para usar el CRM es definir los tipos de objeto (lo que en otros CRMs sería "entidades" o "módulos"). Por ejemplo: Lead, Cliente, Socio, Contacto de prensa.
- Entra en
/crm/object-types. - Pulsa Nuevo tipo de objeto.
- Rellena:
- Nombre singular / plural (etiquetas que verá el usuario, localizadas).
- Slug (identificador URL, en minúsculas y sin espacios). Será parte de las rutas internas.
- Descripción opcional.
- Icono (sprite SVG del spritemap del sitio, ver sección 4).
- En la pestaña Campos, añade los campos del tipo. Por cada campo defines:
- Nombre interno (slug) y etiqueta.
- Tipo de campo (ver tipos disponibles).
- Obligatorio: sí / no.
- Único: sí / no (útil para emails, DNIs, códigos).
- Valor por defecto.
- Opciones en caso de
selectomultiselect. - Relación en caso de
relation(qué tipo de objeto se relaciona, cardinalidad).
- Guarda. El sistema generará automáticamente la tabla correspondiente en la base de datos, las rutas CRUD, y la entrada en el menú lateral del CRM.
9.2 Crear vistas (lista, kanban, calendario)
Una vez definido el tipo de objeto, se pueden crear vistas para consultar los registros. El sistema soporta tres tipos de vista:
- Lista (table): tabla con columnas configurables, filtros, ordenación, paginación y, opcionalmente, exportación CSV.
- Kanban: columnas que representan una fase o estado (configurable), con las tarjetas de los registros arrastables entre columnas. Útil para pipelines comerciales (Nuevo → Contactado → Cualificado → Ganado → Perdido).
- Calendario: muestra los registros en un calendario mensual/semanal, posicionándolos según un campo de tipo fecha. Útil para citas, eventos, fechas de renovación, etc.
Para crear una vista:
- Entra en
/crm/views. - Pulsa Nueva vista.
- Elige el tipo de objeto sobre el que aplica la vista.
- Elige el tipo de vista (lista, kanban, calendario).
- Configura las columnas / campos visibles, los filtros por defecto, el orden y la agrupación (en kanban).
- Guarda. La vista aparece en el submenú del tipo de objeto correspondiente.
9.3 Añadir registros manualmente
Los registros se pueden crear desde la UI del panel o de forma automática (a través de un formulario público, de una integración, o de un workflow). Para añadir uno a mano:
- Entra en el tipo de objeto correspondiente, p. ej.
/crm/object-types/lead/records. - Pulsa Nuevo registro.
- Rellena los campos. Los obligatorios aparecen marcados; el sistema valida también los tipos (email, número, etc.) y la unicidad.
- Añade archivos adjuntos si el tipo tiene campos de tipo
file. - Guarda. El registro aparece en las vistas asociadas al tipo.
Desde la ficha de un registro se puede:
- Ver y editar todos sus campos.
- Ver el historial de cambios (quién cambió qué y cuándo).
- Ver registros relacionados (si el tipo tiene relaciones con otros tipos).
- Ver las ejecuciones de workflows que ha disparado ese registro.
- Lanzar acciones manuales (botones configurables que llaman a un workflow ad-hoc).
- Eliminar el registro (acción destructiva, auditable).
9.4 Crear workflows (disparador → condiciones → acciones)
Los workflows automatizan tareas recurrentes. La estructura es siempre la misma: un disparador (cuándo se ejecuta), unas condiciones (filtros sobre el registro o el evento) y unas acciones (qué se hace).
- Entra en
/crm/workflows. - Pulsa Nuevo workflow.
- Asigna nombre y descripción.
- Elige el disparador. Tipos habituales:
record.created— al crear un registro.record.updated— al modificar un registro.record.field_changed— cuando un campo concreto cambia de valor (por ejemplo,statuspasa denuevoacualificado).schedule.daily/schedule.weekly— ejecución periódica (útil para recordatorios).form.submitted— al recibir un envío de un formulario específico.
- Añade condiciones (todas deben cumplirse para que el workflow continúe). Ejemplos:
- El campo
sourceesweb. - El campo
countryestá en la lista["ES","FR","PT"]. - El campo
amountes mayor que1000.
- El campo
- Añade una o varias acciones (ver acciones disponibles). Las acciones se ejecutan en orden. Si una falla, las siguientes no se ejecutan (a menos que se active "continuar aunque falle").
- Guarda. Activa el workflow (botón Activar). A partir de ese momento, cada vez que se cumpla el disparador y las condiciones, se ejecutarán las acciones.
Referencia técnica (webmasters)
Tipos de campo disponibles
Al definir los campos de un tipo de objeto se puede elegir entre los siguientes tipos (los nombres exactos dependen de la versión del código):
- text: cadena corta (nombre, asunto, código).
- textarea: texto largo (descripción, notas).
- richtext: editor WYSIWYG (HTML, para campos con formato).
- number: numérico (entero o decimal según configuración).
- boolean: casilla de verificación (sí / no).
- date: fecha (sin hora).
- datetime: fecha y hora.
- email: dirección de correo (validada y única opcional).
- phone: teléfono (validación de formato laxa).
- url: enlace (validado).
- select: valor único entre opciones predefinidas.
- multiselect: varios valores entre opciones predefinidas.
- file: archivo adjunto (PDF, imagen, etc.). Se almacena en el sistema de archivos y se sirve por una URL firmada.
- json: valor JSON libre (útil para datos estructurados que no encajan en un campo simple).
- relation: enlace a otro registro (de cualquier tipo). Puede ser
one-to-one,one-to-manyomany-to-many. - formula: campo calculado a partir de otros campos (no editable; se recalcula al guardar).
Acciones de workflow disponibles
Las acciones que un workflow puede ejecutar son, entre otras:
- set_field: asignar un valor (fijo o calculado) a un campo del registro.
- send_email: enviar un email (con plantilla, a la dirección del registro o a una lista fija).
- create_record: crear un registro nuevo en otro tipo de objeto relacionado.
- update_record: modificar un registro relacionado.
- create_task: crear una tarea interna asignada a un usuario o equipo del panel.
- notify_user: notificación interna (dentro del panel) a un usuario o equipo.
- webhook_call: llamada HTTP a una URL externa (POST/GET con payload del registro). Útil para integraciones con servicios de terceros.
- delay: espera N minutos/horas/días antes de continuar con la siguiente acción (útil para secuencias tipo "esperar 1 día y luego enviar recordatorio").
- branch: bifurcación condicional (if / else if / else) para tomar caminos distintos según el valor de un campo.
- stop: detener la ejecución del workflow (útil dentro de una rama de un
branchpara abortar).
Integraciones y extensibilidad
El CRM se integra con el resto del panel:
- Formularios: un formulario (ver sección 6) puede estar vinculado a un tipo de objeto. Cada envío crea automáticamente un registro (el formulario actúa como lead form).
- Mailing: los contactos del mailing (ver sección 8) son un tipo de objeto especial del CRM; las campañas pueden usar segmentos basados en campos CRM.
- Webhooks salientes: las acciones
webhook_callpermiten enviar el registro a un servicio externo (Slack, un ERP, una herramienta de marketing, etc.). - Permisos: cada tipo de objeto puede tener un control de acceso por equipo. Por defecto, los registros son visibles para todos los administradores; se puede restringir por equipo o por propietario.
Rutas internas relevantes
Estas rutas existen en el código fuente, pero no son accesibles en este despliegue (todas responden vacío/404 mientras CRM_ENABLED=false):
GET /crm— dashboard del CRM.GET /crm/object-types— listado de tipos de objeto.GET/POST /crm/object-types/create— alta de tipo de objeto.GET/POST /crm/object-types/{slug}/edit— edición (incluye gestión de campos).DELETE /crm/object-types/{slug}— eliminar tipo (acción destructiva, requiere confirmación).GET /crm/object-types/{slug}/records— registros del tipo (aplica la vista por defecto).GET/POST /crm/object-types/{slug}/records/create— alta de registro.GET/POST /crm/object-types/{slug}/records/{id}/edit— edición de registro.GET /crm/views— listado de vistas.GET/POST /crm/views/create— alta de vista.GET/POST /crm/workflows— listado y alta/edición de workflows.POST /crm/workflows/{id}/activate//deactivate— activar/desactivar.GET /crm/workflows/{id}/executions— log de ejecuciones del workflow.
Errores frecuentes
- No encuentro la sección CRM en el menú: comportamiento esperado en este despliegue. La variable
CRM_ENABLED=falseoculta todas las entradas del CRM. Para habilitarla hay que: (1) cambiarCRM_ENABLED=falseaCRM_ENABLED=trueen el.env, (2) reiniciar el servidor (PHP-FPM, apache, etc.) para que recargue la configuración, y (3) si procede, ejecutar las migraciones de base de datos asociadas al módulo. - El workflow no se dispara: revisa: (1) que el workflow está activado (no en borrador ni pausado), (2) que el disparador coincide con el evento (por ejemplo, si el disparador es
record.field_changedsobre el campostatus, el workflow solo se ejecuta cuandostatuscambia, no en cualquier actualización), (3) que las condiciones se cumplen para el registro en cuestión (muchas veces el problema es una condición mal escrita o que usa un valor antiguo), y (4) que el worker de la cola está corriendo (sin él, los workflows no se ejecutan). - La vista no muestra datos: revisa los filtros por defecto de la vista: si filtras por un campo que no existe en este tipo de objeto, o por un valor que no coincide, la vista aparece vacía. Quita los filtros uno a uno para localizar el que rompe.
- Error al crear un registro: típicamente por un campo obligatorio sin rellenar, un campo único que ya existe (por ejemplo, email duplicado), o un campo de tipo relación que apunta a un registro inexistente. El mensaje de error del backend indica el campo concreto.
- El workflow ejecuta acciones pero los emails no llegan: el módulo CRM delega el envío en el sistema de mailing; revisa la sección 8 (errores frecuentes de SMTP) y comprueba que la plantilla de email existe y está bien referenciada.
- Al eliminar un tipo de objeto, los registros asociados se quedan huérfanos: el sistema pide confirmación, pero si confirmas, los registros y su historial se eliminan. Asegúrate de que no hay workflows o vistas referenciando el tipo antes de eliminarlo.
- El log de ejecuciones del workflow muestra "Failed": abre la ejecución fallida para ver el detalle. Las causas más habituales son: timeout en una llamada
webhook_call, plantilla de email inexistente, o un campo del registro que cambió de tipo y la acción espera un valor en otro formato.