59 lines
9.4 KiB
Markdown
59 lines
9.4 KiB
Markdown
# 02 — Plantillas y Aplicación
|
|
|
|
## Dos ámbitos distintos
|
|
|
|
**CONFIRMADO:** ResourceCatalog es un agregado global (`catalogKey='global'`), con ResourceDefinition de tipo `field` o `template`; cada definición tiene `companyId: Maybe<UniqueID>`. NULL en `resource_definitions.companyId` ya significa definición global. `ResourceCatalog.visible(company)` combina globales y locales de esa compañía. `resource_availability` ajusta disponibilidad de definiciones globales por compañía. Esto no convierte en global a un Resource registrado con ellas. [catalog: resource-catalog.aggregate.ts:14](../../../modules/resources/src/api/domain/resource-catalog.aggregate.ts#L14) [catalogSQL: resource-catalog.model.ts:48](../../../modules/resources/src/api/infrastructure/persistence/resource-catalog.model.ts#L48) [visible: resource-catalog.aggregate.ts:41](../../../modules/resources/src/api/domain/resource-catalog.aggregate.ts#L41).
|
|
|
|
| Elemento | Persistencia | Ámbito/propiedad | Reglas |
|
|
| --- | --- | --- | --- |
|
|
| ResourceCatalog | resource_catalogs | Raíz global única por catalogKey | Composición explícita |
|
|
| ResourceDefinition | resource_definitions | Global o compañía | UUID propio; stockKey nullable y unique; active |
|
|
| Campo | definición kind=field + resource_field_choices | Global/local | text, number, date, boolean, choice; tipo fijo; no retirar opciones existentes |
|
|
| Plantilla | definición kind=template | Global/local | 1..100 bindings, 0..30 secciones opcionales; usage opcional |
|
|
| TemplateField | resource_template_fields | Propiedad de plantilla | ID propio, fieldId, required, position, sectionId |
|
|
| TemplateSection | resource_template_sections | Propiedad de plantilla | ID, nombre, descripción, orden |
|
|
| CatalogAvailability | resource_availability | Compañía + definición | active nullable: heredar, habilitar, deshabilitar; par unique |
|
|
|
|
Fuentes: [definition: resource-definition.ts:23](../../../modules/resources/src/api/domain/resource-definition.ts#L23) [definitionEntity: resource-definition.entity.ts:35](../../../modules/resources/src/api/domain/resource-definition.entity.ts#L35) [catalogSQL: resource-catalog.model.ts:48](../../../modules/resources/src/api/infrastructure/persistence/resource-catalog.model.ts#L48). Una plantilla global admite solo campos globales; una local admite globales y propios. Son configurables en ejecución mediante HTTP, no herencia de clases. Una copia es otra definición, no herencia viva. `usage` queda fijo al actualizar. No hay número de versión de plantilla; las especificaciones de recursos y sus revisiones proporcionan instantáneas. [catalog: resource-catalog.aggregate.ts:14](../../../modules/resources/src/api/domain/resource-catalog.aggregate.ts#L14) [propagation: prepare-resource-template-updates.ts:15](../../../modules/resources/src/api/infrastructure/persistence/prepare-resource-template-updates.ts#L15).
|
|
|
|
## Identificación real de Aplicación
|
|
|
|
**CONFIRMADO:** el seed busca `stockKey='template:application'`; el UUID se genera/preserva en la instalación. No debe fijarse un UUID universal ni filtrar por el texto «Aplicación». Transporte expone `builtinKey` y el indicador `builtin`. `ResourceInventoryService.resourceUsage` reconoce la clave de serie, y para plantillas propias usa `definition.usage`. El selector de perfiles aplica `builtinKey === 'template:application' || usage === 'application'`. [seed: resource-catalog-seed.ts:140](../../../modules/resources/src/api/domain/resource-catalog-seed.ts#L140) [usage: resource-inventory.service.ts:54](../../../modules/resources/src/api/application/resource-inventory.service.ts#L54) [catalogDTO: index.ts:19](../../../modules/resources/src/common/index.ts#L19) [applicationOptions: application-configuration-form-values.ts:8](../../../modules/companies/src/web/application-configurations/shared/helpers/application-configuration-form-values.ts#L8).
|
|
|
|
La plantilla de serie Aplicación no necesita persistir `usage='application'` para ser reconocida: su stockKey lo determina. `resourceTemplateCapability` solo devuelve capacidades para dominio Windows y carpeta SMB; **no existe** una capability de aplicación en esa función. Clasificación operativa `usage`, `stockKey`, propiedad `companyId` y `capability` cumplen responsabilidades diferentes. [capability: resource-capabilities.ts:2](../../../modules/resources/src/common/resource-capabilities.ts#L2).
|
|
|
|
## Campos del producto disponibles
|
|
|
|
**CONFIRMADO:** plantilla inicial Aplicación: `provider`, `url`, `description`, todos opcionales. Tipos text, sin unidad ni opciones. Nombre comercial es `values.name`, actividad `values.active` y observaciones `values.notes`, comunes a Resource. Seed actual declara 22 campos y 9 plantillas; la mención «20 campos y seis plantillas» de `docs/recursos-campos-y-plantillas.md` está desactualizada respecto al código y no se corrigió fuera del alcance. [seedfields: resource-catalog-seed.ts:9](../../../modules/resources/src/api/domain/resource-catalog-seed.ts#L9) [seed: resource-catalog-seed.ts:140](../../../modules/resources/src/api/domain/resource-catalog-seed.ts#L140).
|
|
|
|
| Candidato | Existe realmente | Semántica/validación | Decisión propuesta |
|
|
| --- | --- | --- | --- |
|
|
| Nombre comercial | values.name | Name, 1..100, UUID independiente | Reutilizar |
|
|
| Fabricante | field:provider → UUID dinámico | Texto libre, etiqueta Proveedor | Reutilizar; filtro textual sin entidad Manufacturer implícita |
|
|
| Descripción | field:description | Texto ≤10000 por valor | Reutilizar |
|
|
| Sitio oficial | field:url | Texto; no validador URL específico | Reutilizar, definir validación de URL si se necesita |
|
|
| Estado | values.active | Boolean | Reutilizar |
|
|
| Categoría | No en Aplicación de serie | Campo configurable posible | No prometer filtro hasta aprobar campo/semántica |
|
|
| Familia de producto | No en serie | No relación canónica | Posponer hasta necesidad real |
|
|
| Identificador externo | No tipado/único | field:reference existe en catálogo, no ligado aquí | No usar nombre como ID canónico; diseño externo pendiente |
|
|
| Plataforma/SO compatible | No en Aplicación de serie | No colección/relación tipada | Decidir cardinalidad antes de ampliar; no JSON por comodidad |
|
|
|
|
Campos de serie pueden haberse editado en una instalación: el seed no restablece de forma destructiva el catálogo. **NO CONFIRMADO:** contenido efectivo de plantillas en una BD no consultada. [catalog: resource-catalog.aggregate.ts:14](../../../modules/resources/src/api/domain/resource-catalog.aggregate.ts#L14).
|
|
|
|
Versión instalada pertenece a SoftwareInstallation; versión y delivery por perfil a ApplicationConfiguration; licencia, cantidad, caducidad y renovación a Resource de uso license local; fechas de instalación y política corporativa no se presuponen implementadas. No trasladar estados de preparación/retirada ni credenciales al producto global. [softwareInput: software-installation-values.ts:5](../../../modules/companies/src/api/domain/software-installation-values.ts#L5) [applicationInput: application-configuration-values.ts:5](../../../modules/companies/src/api/domain/application-configuration-values.ts#L5).
|
|
|
|
## Propagación y disponibilidad
|
|
|
|
`prepareResourceTemplateUpdates` detecta plantillas/campos cambiados, enumera compañías con Resource de esas plantillas, bloquea compañías y reconstruye especificación. Conserva valores de campos retirados según sincronización; no inventa obligatorios nuevos. Cada recurso modificado incorpora revisión. El bucle presupone `companyId: string`: con NULL se debe añadir una rama global explícita, mantener lock order y evitar validar campos globales en un contexto local equivocado. [propagation: prepare-resource-template-updates.ts:15](../../../modules/resources/src/api/infrastructure/persistence/prepare-resource-template-updates.ts#L15).
|
|
|
|
Desactivar una definición impide altas según `captureResourceSpecification`, sin invalidar automáticamente recursos ya creados. No confundir esa disponibilidad de plantilla con `Resource.values.active`. Propuesta: bloqueo local de una plantilla puede impedir nuevas selecciones, pero nunca ocultar referencias históricas. Decidir esta política expresamente. [capture: resource-input.mapper.ts:69](../../../modules/resources/src/api/application/resource-input.mapper.ts#L69).
|
|
|
|
## Qué plantillas admitir
|
|
|
|
| Alternativa | Ventajas | Costes y riesgos | Compatibilidad |
|
|
| --- | --- | --- | --- |
|
|
| Solo Aplicación de serie | Alcance mínimo, clave estable, campos globales controlados | No engloba inmediatamente todas las plantillas propias | Recomendación de lanzamiento; permitir locales existentes en selectores |
|
|
| Scope genérico habilitable por plantilla | Extensible a otras definiciones reutilizables | Requiere contrato globalEligible, validación de campos/integ./consumidores y administración | Diseñar discriminación genérica, habilitar después de auditar cada uso |
|
|
|
|
**PROPUESTO:** representación de ámbito reutilizable en Resource, con allowlist inicial de `template:application`, sin integración mailbox/access ni proyecciones operativas. Una plantilla propia de compañía nunca puede producir un Resource global. Una plantilla global personalizada con uso application solo se habilitaría mediante decisión posterior explícita; `usage` por sí solo no acredita que sus datos sean públicos. Copias locales siguen produciendo recursos de compañía. No globalizar OS, support, certificate, license, SMB o dominios por ampliar el tipo. Véase [09](09-alternativas-arquitectonicas.md).
|