Appearance
Endpoint de Capacidades del Tenant CRM
⚠️ DOCUMENTACION RETROSPECTIVA — Generada a partir de codigo implementado el 2026-05-18
Modulo: crm Tipo: Process Estado: Implementado Fecha: 2026-05-18
Descripcion
El endpoint GET /mod-crm/features permite que el frontend descubra en tiempo de ejecucion que modulos opcionales estan disponibles en el tenant (schema) actual, consultando information_schema.tables con current_schema().
Esto resuelve el problema de mostrar funcionalidades en la UI que dependen de tablas que solo existen en algunos tenants (ver patron guard: Guard 42P01 — Tablas Opcionales).
Endpoint
| Campo | Valor |
|---|---|
| Metodo | GET |
| Ruta | /mod-crm/features |
| Autenticacion | JWT requerido (middleware estandar del grupo /mod-crm) |
| Schema | El del tenant activo (X-Schema header) |
Respuesta exitosa (200)
json
{
"status": 200,
"message": "OK",
"data": {
"has_prefa": true
}
}El campo has_prefa indica si la tabla budget_prefa existe en el schema actual. Cuando es false, el boton "Generar Prefactura" no se muestra en la lista de presupuestos.
Arquitectura de capas
| Capa | Archivo | Responsabilidad |
|---|---|---|
| Route | Modules/Crm/Infrastructure/Http/Routes/CrmRoutes.php | Primera ruta del grupo, antes de los subgrupos |
| Controller | Modules/Crm/Infrastructure/Http/Controllers/CrmFeaturesController.php | Manejo HTTP, delega al service |
| Service | Modules/Crm/Application/Services/CrmFeaturesService.php | Llama al model, retorna mapa de flags |
| Model | Modules/Crm/Infrastructure/Persistence/Models/CrmFeatures.php | Consulta information_schema.tables con current_schema() |
El Model no usa guard 42P01 porque consulta information_schema (siempre disponible), no las tablas opcionales directamente.
Deteccion de tablas
El Model consulta information_schema.tables filtrando por table_schema = current_schema() y el nombre de la tabla. Retorna bool.
El Service mapea cada tabla a un flag semantico del dominio:
| Flag | Tabla consultada | Significado |
|---|---|---|
has_prefa | budget_prefa | El modulo de prefactura desde presupuesto CRM esta disponible |
Uso desde el frontend
Hook useCrmFeatures
Archivo: ts/crm/hooks/useCrmFeatures.ts
Usa TanStack Query con perfil COLD (stale time alto, se refresca raramente). Expone { hasPrefa: boolean }. Si la query no cargo todavia, retorna false como default seguro.
Propagacion via prop drilling
El hook se llama en PresupuestosOrchestrator y el resultado se pasa como canConvertToPrefa a PresupuestosList.
PresupuestosList acepta canConvertToPrefa?: boolean (default false). El boton "Generar Prefactura" se renderiza solo si se cumplen las tres condiciones simultaneamente:
canConvertToPrefa === true- El presupuesto tiene
aprobado === true - El presupuesto no tiene
prefaId(aun no fue convertido)
Query key
Registrada en ts/crm/config/queryKeys.ts:
crmQueryKeys.features()Estructura: [nroSistema, schema, 'crm', 'features'] — aislada por tenant gracias a createTenantQueryKey.
Extensibilidad
Para agregar un nuevo flag al endpoint:
- Agregar el nombre de la tabla al metodo
getFeatures()enCrmFeaturesService, usando el metodotableExists()del Model. - Agregar el campo al tipo
CrmFeaturesents/crm/services/crmFeatures.service.tsy al mapeo defetchCrmFeatures(). - Consumir el nuevo flag desde el hook
useCrmFeatures().
Criterio para agregar un flag: cuando una feature de UI depende de una tabla que no existe en todos los tenants.
Relacion con el patron guard
El endpoint y el guard son complementarios:
- El guard protege el backend de crashes cuando el frontend llama a endpoints que internamente tocan tablas opcionales.
- El endpoint de features evita que el frontend llame a esa logica cuando el modulo no esta disponible.
Ambas capas de proteccion son necesarias porque el frontend podria estar cacheando un has_prefa: false desactualizado mientras la migracion ya corrio. El guard es la red de seguridad final.
Ver: Guard 42P01 — Tablas Opcionales
⚠️ NOTA IMPORTANTE: Validar con stakeholders antes de considerar final. Este documento fue generado retrospectivamente a partir del codigo implementado. La lista de flags puede crecer a medida que se agreguen nuevos modulos opcionales.