feat(nakui): Fase 7 del ERP — pulido (cierra el plan maestro)
1{
2 "id": "crm",
3 "label": "CRM",
4 "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.",
5 "nakui_module_dir": "../../../crates/modules/nakui/modules/crm",
6 "entities": [
7 {
8 "name": "Cliente",
9 "label": "Cliente",
10 "fields": [
11 { "name": "id", "label": "ID", "kind": "text" },
12 { "name": "nombre", "label": "Nombre", "kind": "text", "required": true },
13 { "name": "email", "label": "Email", "kind": "text", "required": true },
14 { "name": "empresa", "label": "Empresa", "kind": "text" }
15 ]
16 },
17 {
18 "name": "Oportunidad",
19 "label": "Oportunidad",
20 "fields": [
21 { "name": "id", "label": "ID", "kind": "text" },
22 { "name": "cliente_id", "label": "Cliente", "kind": "entity_ref", "ref_entity": "Cliente" },
23 { "name": "titulo", "label": "Título", "kind": "text" },
24 { "name": "monto", "label": "Monto", "kind": "number" },
25 { "name": "currency", "label": "Moneda", "kind": "text" },
26 { "name": "etapa", "label": "Etapa", "kind": "text" },
27 { "name": "timestamp", "label": "Fecha", "kind": "text" }
28 ]
29 },
30 {
31 "name": "Interaccion",
32 "label": "Interacción",
33 "fields": [
34 { "name": "id", "label": "ID", "kind": "text" },
35 { "name": "cliente_id", "label": "Cliente", "kind": "entity_ref", "ref_entity": "Cliente" },
36 { "name": "canal", "label": "Canal", "kind": "text" },
37 { "name": "nota", "label": "Nota", "kind": "multiline" },
38 { "name": "timestamp", "label": "Fecha", "kind": "text" }
39 ]
40 }
41 ],
42 "menu": [
43 { "label": "Panorama", "view": "panorama", "icon": "📊" },
44 { "label": "Clientes", "view": "cliente_list", "icon": "👤" },
45 { "label": "+ Cliente", "view": "cliente_form", "icon": "✚" },
46 { "label": "Oportunidades", "view": "oportunidad_list", "icon": "🎯" },
47 { "label": "Abrir oportunidad", "view": "abrir_form", "icon": "✚" },
48 { "label": "Mover oportunidad", "view": "mover_form", "icon": "⏩" },
49 { "label": "Interacciones", "view": "interaccion_list", "icon": "💬" },
50 { "label": "Registrar interacción", "view": "interaccion_form", "icon": "✚" }
51 ],
52 "views": {
53 "panorama": {
54 "kind": "dashboard",
55 "title": "Panorama del CRM",
56 "cards": [
57 { "label": "Clientes", "entity": "Cliente", "metric": { "kind": "count" } },
58 { "label": "Oportunidades", "entity": "Oportunidad", "metric": { "kind": "count" } },
59 {
60 "label": "Pipeline (monto total)",
61 "entity": "Oportunidad",
62 "metric": { "kind": "sum", "field": "monto" },
63 "format": { "kind": "currency", "symbol": "$" }
64 },
65 {
66 "label": "Oportunidades ganadas",
67 "entity": "Oportunidad",
68 "metric": { "kind": "count" },
69 "filter": { "field": "etapa", "equals": "ganada" }
70 },
71 {
72 "label": "Monto ganado",
73 "entity": "Oportunidad",
74 "metric": { "kind": "sum", "field": "monto" },
75 "filter": { "field": "etapa", "equals": "ganada" },
76 "format": { "kind": "currency", "symbol": "$" }
77 },
78 {
79 "label": "Oportunidades por etapa",
80 "entity": "Oportunidad",
81 "metric": { "kind": "group_by", "field": "etapa" }
82 },
83 {
84 "label": "Interacciones por canal",
85 "entity": "Interaccion",
86 "metric": { "kind": "group_by", "field": "canal" }
87 }
88 ]
89 },
90 "cliente_list": {
91 "kind": "list",
92 "title": "Clientes",
93 "entity": "Cliente",
94 "columns": [
95 { "field": "nombre", "label": "Nombre", "weight": 2.0 },
96 { "field": "email", "label": "Email", "weight": 2.5 },
97 { "field": "empresa", "label": "Empresa", "weight": 2.0 }
98 ],
99 "actions": [
100 { "kind": "open_view", "view": "cliente_form", "label": "✚ Nuevo cliente" }
101 ],
102 "search_in": ["nombre", "email", "empresa"],
103 "row_detail": "cliente_detail"
104 },
105 "cliente_form": {
106 "kind": "form",
107 "title": "Nuevo cliente",
108 "entity": "Cliente",
109 "fields": [
110 { "name": "nombre", "label": "Nombre", "kind": "text", "required": true },
111 { "name": "email", "label": "Email", "kind": "text", "required": true },
112 { "name": "empresa", "label": "Empresa", "kind": "text" }
113 ],
114 "on_submit": {
115 "kind": "seed_entity",
116 "entity": "Cliente",
117 "next_view": "cliente_list"
118 }
119 },
120 "oportunidad_list": {
121 "kind": "list",
122 "title": "Oportunidades",
123 "entity": "Oportunidad",
124 "columns": [
125 { "field": "titulo", "label": "Título", "weight": 2.5 },
126 { "field": "etapa", "label": "Etapa", "weight": 1.2 },
127 { "field": "monto", "label": "Monto", "weight": 1.2, "format": { "kind": "currency", "symbol": "$" } },
128 { "field": "cliente_id", "label": "Cliente", "weight": 2.0, "ref_entity": "Cliente" }
129 ],
130 "actions": [
131 { "kind": "open_view", "view": "abrir_form", "label": "✚ Abrir oportunidad" },
132 { "kind": "open_view", "view": "mover_form", "label": "⏩ Mover etapa" }
133 ],
134 "search_in": ["titulo", "etapa"],
135 "row_detail": "oportunidad_detail"
136 },
137 "abrir_form": {
138 "kind": "form",
139 "title": "Abrir oportunidad (morphism)",
140 "entity": "Oportunidad",
141 "fields": [
142 { "name": "cliente_ref", "label": "Cliente", "kind": "entity_ref", "ref_entity": "Cliente", "required": true, "section": "Oportunidad", "help": "Click en un cliente de la lista para seleccionarlo." },
143 { "name": "oportunidad_id", "label": "ID de la oportunidad", "kind": "auto_id", "section": "Oportunidad" },
144 { "name": "titulo", "label": "Título", "kind": "text", "required": true, "section": "Oportunidad" },
145 { "name": "monto", "label": "Monto", "kind": "number", "required": true, "default": "0", "section": "Importe y fecha" },
146 { "name": "currency", "label": "Moneda", "kind": "text", "default": "USD", "section": "Importe y fecha" },
147 { "name": "timestamp", "label": "Fecha ISO", "kind": "text", "required": true, "default": "2026-05-21T12:00:00Z", "section": "Importe y fecha" }
148 ],
149 "on_submit": {
150 "kind": "morphism",
151 "name": "abrir_oportunidad",
152 "inputs": { "cliente": "cliente_ref" },
153 "params": ["oportunidad_id", "titulo", "monto", "currency", "timestamp"],
154 "next_view": "oportunidad_list"
155 }
156 },
157 "mover_form": {
158 "kind": "form",
159 "title": "Mover oportunidad (morphism)",
160 "entity": "Oportunidad",
161 "fields": [
162 { "name": "oportunidad_ref", "label": "Oportunidad", "kind": "entity_ref", "ref_entity": "Oportunidad", "required": true, "help": "Click en una oportunidad de la lista." },
163 {
164 "name": "etapa", "label": "Etapa destino", "kind": "select", "required": true,
165 "options": [
166 { "value": "prospecto", "label": "Prospecto" },
167 { "value": "calificado", "label": "Calificado" },
168 { "value": "propuesta", "label": "Propuesta" },
169 { "value": "negociacion", "label": "Negociación" },
170 { "value": "ganada", "label": "Ganada" },
171 { "value": "perdida", "label": "Perdida" }
172 ]
173 },
174 { "name": "timestamp", "label": "Fecha ISO", "kind": "text", "required": true, "default": "2026-05-21T12:00:00Z" }
175 ],
176 "on_submit": {
177 "kind": "morphism",
178 "name": "mover_oportunidad",
179 "inputs": { "oportunidad": "oportunidad_ref" },
180 "params": ["etapa", "timestamp"],
181 "next_view": "oportunidad_list"
182 }
183 },
184 "interaccion_list": {
185 "kind": "list",
186 "title": "Interacciones",
187 "entity": "Interaccion",
188 "columns": [
189 { "field": "canal", "label": "Canal", "weight": 1.0 },
190 { "field": "nota", "label": "Nota", "weight": 3.0 },
191 { "field": "cliente_id", "label": "Cliente", "weight": 2.0, "ref_entity": "Cliente" },
192 { "field": "timestamp", "label": "Fecha", "weight": 1.2 }
193 ],
194 "actions": [
195 { "kind": "open_view", "view": "interaccion_form", "label": "✚ Registrar interacción" }
196 ],
197 "search_in": ["canal", "nota"]
198 },
199 "interaccion_form": {
200 "kind": "form",
201 "title": "Registrar interacción (morphism)",
202 "entity": "Interaccion",
203 "fields": [
204 { "name": "cliente_ref", "label": "Cliente", "kind": "entity_ref", "ref_entity": "Cliente", "required": true, "help": "Click en un cliente de la lista." },
205 { "name": "interaccion_id", "label": "ID de la interacción", "kind": "auto_id" },
206 {
207 "name": "canal", "label": "Canal", "kind": "select", "required": true,
208 "options": [
209 { "value": "llamada", "label": "Llamada" },
210 { "value": "email", "label": "Email" },
211 { "value": "reunion", "label": "Reunión" }
212 ]
213 },
214 { "name": "nota", "label": "Nota", "kind": "multiline" },
215 { "name": "timestamp", "label": "Fecha ISO", "kind": "text", "required": true, "default": "2026-05-21T12:00:00Z" }
216 ],
217 "on_submit": {
218 "kind": "morphism",
219 "name": "registrar_interaccion",
220 "inputs": { "cliente": "cliente_ref" },
221 "params": ["interaccion_id", "canal", "nota", "timestamp"],
222 "next_view": "interaccion_list"
223 }
224 },
225 "cliente_detail": {
226 "kind": "detail",
227 "title": "Ficha del cliente",
228 "entity": "Cliente",
229 "fields": [
230 { "field": "nombre", "label": "Nombre" },
231 { "field": "email", "label": "Email" },
232 { "field": "empresa", "label": "Empresa" }
233 ],
234 "related": [
235 {
236 "title": "Oportunidades",
237 "entity": "Oportunidad",
238 "via_field": "cliente_id",
239 "columns": [
240 { "field": "titulo", "label": "Título", "weight": 2.5 },
241 { "field": "etapa", "label": "Etapa", "weight": 1.2 },
242 { "field": "monto", "label": "Monto", "weight": 1.2, "format": { "kind": "currency", "symbol": "$" } }
243 ]
244 },
245 {
246 "title": "Interacciones",
247 "entity": "Interaccion",
248 "via_field": "cliente_id",
249 "columns": [
250 { "field": "canal", "label": "Canal", "weight": 1.0 },
251 { "field": "nota", "label": "Nota", "weight": 3.0 },
252 { "field": "timestamp", "label": "Fecha", "weight": 1.2 }
253 ]
254 }
255 ]
256 },
257 "oportunidad_detail": {
258 "kind": "detail",
259 "title": "Ficha de la oportunidad",
260 "entity": "Oportunidad",
261 "fields": [
262 { "field": "titulo", "label": "Título" },
263 { "field": "etapa", "label": "Etapa" },
264 { "field": "monto", "label": "Monto", "format": { "kind": "currency", "symbol": "$" } },
265 { "field": "currency", "label": "Moneda" },
266 { "field": "cliente_id", "label": "Cliente", "ref_entity": "Cliente" },
267 { "field": "timestamp", "label": "Fecha" }
268 ]
269 }
270 }
271}