Files
brahman/examples/nakui-modules/crm/module.json
T
sergio e187ab4cd3 feat(nakui-ui): CRM como ERP — UiModule con listas y formularios
examples/nakui-modules/crm/module.json: el módulo crm se ve ahora como
un ERP en nakui-ui (sidebar + listas + formularios), no sólo como el
timeline del event log. 7 vistas — lista+form de Clientes, Oportunidades
e Interacciones — con los formularios de morfismo Abrir/Mover/Registrar
que disparan los morfismos reales del kernel (nakui_module_dir engancha
el módulo crm). 2 tests verifican parseo, validación y carga por el
camino brahman_cards.

Correr: NAKUI_MODULES_DIR=examples/nakui-modules cargo run -p nakui-ui

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-21 18:35:35 +00:00

172 lines
7.6 KiB
JSON

{
"id": "crm",
"label": "CRM",
"description": "CRM conectado al módulo nakui-core 'crm': clientes, oportunidades que recorren un pipeline de ventas e interacciones. Los formularios «Abrir», «Mover» y «Registrar» disparan morfismos reales con validación del kernel.",
"nakui_module_dir": "../../../crates/modules/nakui/modules/crm",
"entities": [
{
"name": "Cliente",
"label": "Cliente",
"fields": [
{ "name": "id", "label": "ID", "kind": "text" },
{ "name": "nombre", "label": "Nombre", "kind": "text", "required": true },
{ "name": "email", "label": "Email", "kind": "text", "required": true },
{ "name": "empresa", "label": "Empresa", "kind": "text" }
]
},
{
"name": "Oportunidad",
"label": "Oportunidad",
"fields": [
{ "name": "id", "label": "ID", "kind": "text" },
{ "name": "cliente_id", "label": "Cliente ref", "kind": "text" },
{ "name": "titulo", "label": "Título", "kind": "text" },
{ "name": "monto", "label": "Monto", "kind": "number" },
{ "name": "currency", "label": "Moneda", "kind": "text" },
{ "name": "etapa", "label": "Etapa", "kind": "text" },
{ "name": "timestamp", "label": "Fecha", "kind": "text" }
]
},
{
"name": "Interaccion",
"label": "Interacción",
"fields": [
{ "name": "id", "label": "ID", "kind": "text" },
{ "name": "cliente_id", "label": "Cliente ref", "kind": "text" },
{ "name": "canal", "label": "Canal", "kind": "text" },
{ "name": "nota", "label": "Nota", "kind": "multiline" },
{ "name": "timestamp", "label": "Fecha", "kind": "text" }
]
}
],
"menu": [
{ "label": "Clientes", "view": "cliente_list", "icon": "👤" },
{ "label": "+ Cliente", "view": "cliente_form", "icon": "✚" },
{ "label": "Oportunidades", "view": "oportunidad_list", "icon": "🎯" },
{ "label": "Abrir oportunidad", "view": "abrir_form", "icon": "✚" },
{ "label": "Mover oportunidad", "view": "mover_form", "icon": "⏩" },
{ "label": "Interacciones", "view": "interaccion_list", "icon": "💬" },
{ "label": "Registrar interacción", "view": "interaccion_form", "icon": "✚" }
],
"views": {
"cliente_list": {
"kind": "list",
"title": "Clientes",
"entity": "Cliente",
"columns": [
{ "field": "nombre", "label": "Nombre", "weight": 2.0 },
{ "field": "email", "label": "Email", "weight": 2.5 },
{ "field": "empresa", "label": "Empresa", "weight": 2.0 }
],
"actions": [
{ "kind": "open_view", "view": "cliente_form", "label": "✚ Nuevo cliente" }
],
"search_in": ["nombre", "email", "empresa"]
},
"cliente_form": {
"kind": "form",
"title": "Nuevo cliente",
"entity": "Cliente",
"fields": [
{ "name": "id", "label": "ID interno", "kind": "text", "help": "Opcional; el runtime genera el UUID de la entity. Dejar vacío está bien." },
{ "name": "nombre", "label": "Nombre", "kind": "text", "required": true },
{ "name": "email", "label": "Email", "kind": "text", "required": true },
{ "name": "empresa", "label": "Empresa", "kind": "text" }
],
"on_submit": {
"kind": "seed_entity",
"entity": "Cliente",
"next_view": "cliente_list"
}
},
"oportunidad_list": {
"kind": "list",
"title": "Oportunidades",
"entity": "Oportunidad",
"columns": [
{ "field": "titulo", "label": "Título", "weight": 2.5 },
{ "field": "etapa", "label": "Etapa", "weight": 1.2 },
{ "field": "monto", "label": "Monto", "weight": 1.0 },
{ "field": "currency", "label": "Moneda", "weight": 0.6 },
{ "field": "cliente_id", "label": "Cliente ref", "weight": 1.5 }
],
"actions": [
{ "kind": "open_view", "view": "abrir_form", "label": "✚ Abrir oportunidad" },
{ "kind": "open_view", "view": "mover_form", "label": "⏩ Mover etapa" }
],
"search_in": ["titulo", "etapa"]
},
"abrir_form": {
"kind": "form",
"title": "Abrir oportunidad (morphism)",
"entity": "Oportunidad",
"fields": [
{ "name": "cliente_ref", "label": "Cliente", "kind": "entity_ref", "ref_entity": "Cliente", "required": true, "help": "Click en un cliente de la lista para seleccionarlo." },
{ "name": "oportunidad_id", "label": "Oportunidad UUID", "kind": "text", "required": true, "help": "UUID nuevo por cada intento (idempotencia)." },
{ "name": "titulo", "label": "Título", "kind": "text", "required": true },
{ "name": "monto", "label": "Monto", "kind": "number", "required": true, "default": "0" },
{ "name": "currency", "label": "Moneda", "kind": "text", "default": "USD" },
{ "name": "timestamp", "label": "Fecha ISO", "kind": "text", "required": true, "default": "2026-05-21T12:00:00Z" }
],
"on_submit": {
"kind": "morphism",
"name": "abrir_oportunidad",
"inputs": { "cliente": "cliente_ref" },
"params": ["oportunidad_id", "titulo", "monto", "currency", "timestamp"],
"next_view": "oportunidad_list"
}
},
"mover_form": {
"kind": "form",
"title": "Mover oportunidad (morphism)",
"entity": "Oportunidad",
"fields": [
{ "name": "oportunidad_ref", "label": "Oportunidad", "kind": "entity_ref", "ref_entity": "Oportunidad", "required": true, "help": "Click en una oportunidad de la lista." },
{ "name": "etapa", "label": "Etapa destino", "kind": "text", "required": true, "help": "prospecto | calificado | propuesta | negociacion | ganada | perdida" },
{ "name": "timestamp", "label": "Fecha ISO", "kind": "text", "required": true, "default": "2026-05-21T12:00:00Z" }
],
"on_submit": {
"kind": "morphism",
"name": "mover_oportunidad",
"inputs": { "oportunidad": "oportunidad_ref" },
"params": ["etapa", "timestamp"],
"next_view": "oportunidad_list"
}
},
"interaccion_list": {
"kind": "list",
"title": "Interacciones",
"entity": "Interaccion",
"columns": [
{ "field": "canal", "label": "Canal", "weight": 1.0 },
{ "field": "nota", "label": "Nota", "weight": 3.0 },
{ "field": "cliente_id", "label": "Cliente ref", "weight": 1.5 },
{ "field": "timestamp", "label": "Fecha", "weight": 1.2 }
],
"actions": [
{ "kind": "open_view", "view": "interaccion_form", "label": "✚ Registrar interacción" }
],
"search_in": ["canal", "nota"]
},
"interaccion_form": {
"kind": "form",
"title": "Registrar interacción (morphism)",
"entity": "Interaccion",
"fields": [
{ "name": "cliente_ref", "label": "Cliente", "kind": "entity_ref", "ref_entity": "Cliente", "required": true, "help": "Click en un cliente de la lista." },
{ "name": "interaccion_id", "label": "Interacción UUID", "kind": "text", "required": true, "help": "UUID nuevo por cada intento (idempotencia)." },
{ "name": "canal", "label": "Canal", "kind": "text", "required": true, "help": "llamada | email | reunion" },
{ "name": "nota", "label": "Nota", "kind": "multiline" },
{ "name": "timestamp", "label": "Fecha ISO", "kind": "text", "required": true, "default": "2026-05-21T12:00:00Z" }
],
"on_submit": {
"kind": "morphism",
"name": "registrar_interaccion",
"inputs": { "cliente": "cliente_ref" },
"params": ["interaccion_id", "canal", "nota", "timestamp"],
"next_view": "interaccion_list"
}
}
}
}