Skip to content

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

CampoValor
MetodoGET
Ruta/mod-crm/features
AutenticacionJWT requerido (middleware estandar del grupo /mod-crm)
SchemaEl 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

CapaArchivoResponsabilidad
RouteModules/Crm/Infrastructure/Http/Routes/CrmRoutes.phpPrimera ruta del grupo, antes de los subgrupos
ControllerModules/Crm/Infrastructure/Http/Controllers/CrmFeaturesController.phpManejo HTTP, delega al service
ServiceModules/Crm/Application/Services/CrmFeaturesService.phpLlama al model, retorna mapa de flags
ModelModules/Crm/Infrastructure/Persistence/Models/CrmFeatures.phpConsulta 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:

FlagTabla consultadaSignificado
has_prefabudget_prefaEl 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:

  1. Agregar el nombre de la tabla al metodo getFeatures() en CrmFeaturesService, usando el metodo tableExists() del Model.
  2. Agregar el campo al tipo CrmFeatures en ts/crm/services/crmFeatures.service.ts y al mapeo de fetchCrmFeatures().
  3. 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.