Documentación de settings
This commit is contained in:
parent
a0bd39c2a5
commit
4b041db8da
614
docs/settings/frontend-erp-settings-module-integration-design.md
Normal file
614
docs/settings/frontend-erp-settings-module-integration-design.md
Normal file
@ -0,0 +1,614 @@
|
|||||||
|
# Frontend ERP – Integración de módulos con Settings
|
||||||
|
|
||||||
|
## 1. Propósito
|
||||||
|
|
||||||
|
Este documento complementa **Frontend ERP – Sistema modular de Settings** y define cómo debe integrarse un módulo funcional con `/settings` sin acoplarse al shell de aplicación ni a otros módulos.
|
||||||
|
|
||||||
|
Aplica a módulos actuales y futuros que necesiten exponer configuración de la empresa activa.
|
||||||
|
|
||||||
|
Ejemplos:
|
||||||
|
|
||||||
|
```txt
|
||||||
|
customer-invoices
|
||||||
|
→ VeriFactu
|
||||||
|
|
||||||
|
document-series
|
||||||
|
→ Series documentales
|
||||||
|
|
||||||
|
identity/company
|
||||||
|
→ Datos de empresa
|
||||||
|
|
||||||
|
módulo de certificados
|
||||||
|
→ Certificados
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Principio operativo
|
||||||
|
|
||||||
|
```txt
|
||||||
|
Módulo
|
||||||
|
→ declara metadata de Settings
|
||||||
|
→ registra su propia route
|
||||||
|
→ implementa su propia Page
|
||||||
|
→ mantiene su propia persistencia
|
||||||
|
```
|
||||||
|
|
||||||
|
El shell únicamente descubre y presenta la opción.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Separación de responsabilidades
|
||||||
|
|
||||||
|
### Settings shell
|
||||||
|
|
||||||
|
Conoce:
|
||||||
|
|
||||||
|
```txt
|
||||||
|
id de sección
|
||||||
|
label
|
||||||
|
descripción
|
||||||
|
orden
|
||||||
|
path
|
||||||
|
permiso
|
||||||
|
```
|
||||||
|
|
||||||
|
No conoce:
|
||||||
|
|
||||||
|
```txt
|
||||||
|
DTO
|
||||||
|
Entity
|
||||||
|
Controller
|
||||||
|
formulario
|
||||||
|
endpoint
|
||||||
|
reglas de negocio
|
||||||
|
```
|
||||||
|
|
||||||
|
### Módulo
|
||||||
|
|
||||||
|
Conoce:
|
||||||
|
|
||||||
|
```txt
|
||||||
|
routing concreto
|
||||||
|
Page/Page Controller
|
||||||
|
controllers
|
||||||
|
shared/api
|
||||||
|
shared/adapters
|
||||||
|
shared/entities
|
||||||
|
shared/hooks
|
||||||
|
validación
|
||||||
|
persistencia
|
||||||
|
reglas de negocio
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Flujo completo
|
||||||
|
|
||||||
|
```txt
|
||||||
|
Module manifest
|
||||||
|
│
|
||||||
|
│ settings contribution
|
||||||
|
▼
|
||||||
|
SettingsRegistry
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
SettingsNavigation
|
||||||
|
│
|
||||||
|
│ usuario navega
|
||||||
|
▼
|
||||||
|
/settings/<section>/<entry>
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
Route del módulo
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
Settings Page del módulo
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
Page Controller
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
Controller
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
shared/hooks
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
shared/api
|
||||||
|
```
|
||||||
|
|
||||||
|
La cadena de datos del módulo sigue siendo:
|
||||||
|
|
||||||
|
```txt
|
||||||
|
API → DTO → Adapter → Entity → Hook → Controller → Page Controller → UI
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Metadata mínima del módulo
|
||||||
|
|
||||||
|
Contrato conceptual:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
export interface ModuleSettingsSectionContribution {
|
||||||
|
id: string;
|
||||||
|
labelKey: string;
|
||||||
|
order?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ModuleSettingsEntryContribution {
|
||||||
|
id: string;
|
||||||
|
sectionId: string;
|
||||||
|
|
||||||
|
labelKey: string;
|
||||||
|
descriptionKey?: string;
|
||||||
|
|
||||||
|
path: string;
|
||||||
|
|
||||||
|
order?: number;
|
||||||
|
permission?: string;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Ejemplo conceptual:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
export const customerInvoicesManifest = {
|
||||||
|
settings: {
|
||||||
|
sections: [
|
||||||
|
{
|
||||||
|
id: "billing",
|
||||||
|
labelKey: "settings.sections.billing",
|
||||||
|
order: 200,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
entries: [
|
||||||
|
{
|
||||||
|
id: "verifactu",
|
||||||
|
sectionId: "billing",
|
||||||
|
labelKey: "customerInvoices.settings.verifactu.title",
|
||||||
|
descriptionKey: "customerInvoices.settings.verifactu.description",
|
||||||
|
path: "/settings/billing/verifactu",
|
||||||
|
order: 100,
|
||||||
|
permission: "customerInvoices.settings.verifactu.manage",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
El shape definitivo debe adaptarse al manifest real del repositorio.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. Regla de routing
|
||||||
|
|
||||||
|
Una contribución de Settings no debe registrar un componente React directamente.
|
||||||
|
|
||||||
|
Incorrecto:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
{
|
||||||
|
id: "verifactu",
|
||||||
|
component: VerifactuSettingsPage,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Correcto conceptualmente:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
{
|
||||||
|
id: "verifactu",
|
||||||
|
path: "/settings/billing/verifactu",
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Y en el routing propio del módulo:
|
||||||
|
|
||||||
|
```txt
|
||||||
|
/settings/billing/verifactu
|
||||||
|
→ VerifactuSettingsPage
|
||||||
|
```
|
||||||
|
|
||||||
|
El shell y el módulo se acoplan únicamente mediante una ruta estable.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. Ubicación de código dentro del módulo
|
||||||
|
|
||||||
|
La ubicación concreta debe seguir la estructura real del módulo.
|
||||||
|
|
||||||
|
Dirección conceptual recomendada:
|
||||||
|
|
||||||
|
```txt
|
||||||
|
[module]/
|
||||||
|
├── manifest.ts
|
||||||
|
├── [module]-routes.tsx
|
||||||
|
├── shared/
|
||||||
|
│ ├── api/
|
||||||
|
│ ├── adapters/
|
||||||
|
│ ├── entities/
|
||||||
|
│ └── hooks/
|
||||||
|
│
|
||||||
|
└── settings/
|
||||||
|
└── [setting]/
|
||||||
|
├── controllers/
|
||||||
|
├── entities/
|
||||||
|
├── ui/
|
||||||
|
└── index.ts
|
||||||
|
```
|
||||||
|
|
||||||
|
No introducir esta estructura si el módulo real ya tiene una convención equivalente mejor establecida.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. Page Controller
|
||||||
|
|
||||||
|
Una página de settings debe seguir la misma regla que el resto del ERP.
|
||||||
|
|
||||||
|
Responsabilidades del Page Controller:
|
||||||
|
|
||||||
|
```txt
|
||||||
|
integrar contexto externo
|
||||||
|
componer controllers
|
||||||
|
integrar navegación si aplica
|
||||||
|
exponer API estructurada a la Page
|
||||||
|
```
|
||||||
|
|
||||||
|
No debe:
|
||||||
|
|
||||||
|
```txt
|
||||||
|
transportar DTO
|
||||||
|
realizar llamadas API directas
|
||||||
|
contener lógica visual
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 9. Controller
|
||||||
|
|
||||||
|
Responsable de:
|
||||||
|
|
||||||
|
```txt
|
||||||
|
estado del caso de uso
|
||||||
|
formulario
|
||||||
|
submit
|
||||||
|
validaciones de flujo
|
||||||
|
side effects
|
||||||
|
coordinación con hooks de shared
|
||||||
|
```
|
||||||
|
|
||||||
|
No debe:
|
||||||
|
|
||||||
|
```txt
|
||||||
|
usar useParams/useNavigate directamente
|
||||||
|
usar DTO
|
||||||
|
conocer el SettingsRegistry
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 10. Shared
|
||||||
|
|
||||||
|
Una configuración de módulo reutiliza las reglas generales de `shared/`.
|
||||||
|
|
||||||
|
```txt
|
||||||
|
shared/api
|
||||||
|
→ transporte remoto
|
||||||
|
|
||||||
|
shared/adapters
|
||||||
|
→ DTO ↔ Entity cuando corresponda
|
||||||
|
|
||||||
|
shared/entities
|
||||||
|
→ contratos frontend
|
||||||
|
|
||||||
|
shared/hooks
|
||||||
|
→ React Query
|
||||||
|
```
|
||||||
|
|
||||||
|
El hecho de que la UI aparezca bajo `/settings` no cambia estas responsabilidades.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 11. Persistencia
|
||||||
|
|
||||||
|
Cada módulo decide su persistencia.
|
||||||
|
|
||||||
|
No utilizar por defecto un almacenamiento genérico de Settings.
|
||||||
|
|
||||||
|
Ejemplos:
|
||||||
|
|
||||||
|
```txt
|
||||||
|
VeriFactu
|
||||||
|
→ configuración persistida del dominio correspondiente
|
||||||
|
|
||||||
|
Series documentales
|
||||||
|
→ agregado DocumentSeries
|
||||||
|
|
||||||
|
Datos de empresa
|
||||||
|
→ Company/Identity
|
||||||
|
```
|
||||||
|
|
||||||
|
La navegación compartida no implica almacenamiento compartido.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 12. Empresa activa
|
||||||
|
|
||||||
|
Toda configuración integrada en `/settings` pertenece a la empresa activa.
|
||||||
|
|
||||||
|
Un módulo no debe introducir su propio selector de empresa si la aplicación ya dispone de contexto global.
|
||||||
|
|
||||||
|
La query/mutation debe usar la infraestructura existente para resolver la empresa activa.
|
||||||
|
|
||||||
|
Cuando cambie la empresa activa:
|
||||||
|
|
||||||
|
```txt
|
||||||
|
los datos visibles deben corresponder a la nueva empresa
|
||||||
|
```
|
||||||
|
|
||||||
|
La implementación exacta depende de cómo estén construidas actualmente las query keys, headers y mecanismos de invalidación.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 13. Permisos
|
||||||
|
|
||||||
|
La contribución puede declarar:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
permission?: string;
|
||||||
|
```
|
||||||
|
|
||||||
|
El permiso solo controla la disponibilidad de la navegación frontend.
|
||||||
|
|
||||||
|
La operación backend debe seguir autorizándose independientemente.
|
||||||
|
|
||||||
|
Un módulo no debe implementar un segundo sistema de permisos para Settings.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 14. i18n
|
||||||
|
|
||||||
|
La metadata debe usar claves de traducción.
|
||||||
|
|
||||||
|
Ejemplo:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
labelKey: "customerInvoices.settings.verifactu.title";
|
||||||
|
descriptionKey: "customerInvoices.settings.verifactu.description";
|
||||||
|
```
|
||||||
|
|
||||||
|
El módulo mantiene sus traducciones.
|
||||||
|
|
||||||
|
La sección compartida puede usar una key común del shell si el diseño final establece un catálogo global de secciones.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 15. UI
|
||||||
|
|
||||||
|
La página del módulo debe usar el sistema visual Rdx vigente.
|
||||||
|
|
||||||
|
El shell proporciona:
|
||||||
|
|
||||||
|
```txt
|
||||||
|
layout
|
||||||
|
navegación
|
||||||
|
título general de Configuración
|
||||||
|
```
|
||||||
|
|
||||||
|
El módulo proporciona:
|
||||||
|
|
||||||
|
```txt
|
||||||
|
título específico
|
||||||
|
contenido
|
||||||
|
formularios
|
||||||
|
acciones
|
||||||
|
loading/error states
|
||||||
|
```
|
||||||
|
|
||||||
|
Evitar duplicar dentro del módulo el sidebar global de Settings.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 16. Guardado
|
||||||
|
|
||||||
|
Cada setting debe guardar de forma independiente.
|
||||||
|
|
||||||
|
Ejemplo:
|
||||||
|
|
||||||
|
```txt
|
||||||
|
VeriFactu
|
||||||
|
[Cancelar] [Guardar]
|
||||||
|
```
|
||||||
|
|
||||||
|
No existe un submit global de `/settings`.
|
||||||
|
|
||||||
|
Si la pantalla tiene varios bloques pero forman una única configuración transaccional, el módulo puede resolverlos con un único formulario/controlador.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 17. Loading y errores
|
||||||
|
|
||||||
|
El módulo conserva responsabilidad sobre:
|
||||||
|
|
||||||
|
```txt
|
||||||
|
loading inicial
|
||||||
|
error inicial
|
||||||
|
refetch error
|
||||||
|
submit error
|
||||||
|
validation errors
|
||||||
|
retry
|
||||||
|
```
|
||||||
|
|
||||||
|
El shell no interpreta errores de dominio.
|
||||||
|
|
||||||
|
Debe reutilizarse el patrón consolidado de `PageErrorState`, `ErrorAlert` y errores de formulario cuando corresponda.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 18. Unsaved changes
|
||||||
|
|
||||||
|
Cada módulo es responsable de avisar o bloquear navegación cuando existan cambios no guardados.
|
||||||
|
|
||||||
|
No crear un estado dirty global dentro del Settings shell.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 19. Deep linking
|
||||||
|
|
||||||
|
Una entrada debe ser accesible directamente por URL.
|
||||||
|
|
||||||
|
Ejemplo:
|
||||||
|
|
||||||
|
```txt
|
||||||
|
/settings/billing/verifactu
|
||||||
|
```
|
||||||
|
|
||||||
|
El módulo no debe depender de que el usuario haya visitado antes `/settings`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 20. Varias contribuciones a una misma sección
|
||||||
|
|
||||||
|
Ejemplo:
|
||||||
|
|
||||||
|
### customer-invoices
|
||||||
|
|
||||||
|
```txt
|
||||||
|
billing
|
||||||
|
└── VeriFactu
|
||||||
|
```
|
||||||
|
|
||||||
|
### document-series
|
||||||
|
|
||||||
|
```txt
|
||||||
|
billing
|
||||||
|
└── Series documentales
|
||||||
|
```
|
||||||
|
|
||||||
|
Resultado:
|
||||||
|
|
||||||
|
```txt
|
||||||
|
Facturación
|
||||||
|
├── VeriFactu
|
||||||
|
└── Series documentales
|
||||||
|
```
|
||||||
|
|
||||||
|
Los módulos no se importan entre sí.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 21. Caso piloto: VeriFactu
|
||||||
|
|
||||||
|
El primer setting real será VeriFactu.
|
||||||
|
|
||||||
|
Su contribución debe limitarse a metadata:
|
||||||
|
|
||||||
|
```txt
|
||||||
|
section
|
||||||
|
entry
|
||||||
|
path
|
||||||
|
orden
|
||||||
|
permiso si existe
|
||||||
|
```
|
||||||
|
|
||||||
|
La implementación funcional de VeriFactu debe documentarse en un documento específico posterior.
|
||||||
|
|
||||||
|
Este documento específico deberá explicar:
|
||||||
|
|
||||||
|
```txt
|
||||||
|
estado/configuración de la empresa
|
||||||
|
onboarding inicial
|
||||||
|
valores por defecto de facturación
|
||||||
|
certificados si pertenecen al mismo dominio
|
||||||
|
snapshot de IssuedInvoice
|
||||||
|
API
|
||||||
|
DTOs
|
||||||
|
Entities
|
||||||
|
controllers
|
||||||
|
UI
|
||||||
|
```
|
||||||
|
|
||||||
|
sin redefinir el framework de Settings.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 22. Checklist para añadir un setting nuevo
|
||||||
|
|
||||||
|
### Manifest
|
||||||
|
|
||||||
|
- [ ] Declara sección si es necesaria.
|
||||||
|
- [ ] Declara entry con `id` estable.
|
||||||
|
- [ ] Usa `labelKey`.
|
||||||
|
- [ ] Usa `descriptionKey` si aporta valor.
|
||||||
|
- [ ] Declara `path` estable.
|
||||||
|
- [ ] Declara `order` cuando importe el orden semántico.
|
||||||
|
- [ ] Declara `permission` solo si existe permiso real.
|
||||||
|
|
||||||
|
### Routing
|
||||||
|
|
||||||
|
- [ ] La route pertenece al módulo.
|
||||||
|
- [ ] Funciona mediante deep-link.
|
||||||
|
- [ ] No requiere estado previo del shell.
|
||||||
|
|
||||||
|
### Arquitectura
|
||||||
|
|
||||||
|
- [ ] API → DTO → Adapter → Entity → Hook → Controller → Page Controller → UI.
|
||||||
|
- [ ] No hay DTO en UI/controller.
|
||||||
|
- [ ] No hay routing en controller.
|
||||||
|
- [ ] No hay dependencia del SettingsRegistry en dominio/shared.
|
||||||
|
|
||||||
|
### UI
|
||||||
|
|
||||||
|
- [ ] Usa sistema visual Rdx.
|
||||||
|
- [ ] No duplica SettingsNavigation.
|
||||||
|
- [ ] Soporta teclado y focus-visible.
|
||||||
|
- [ ] Maneja loading/error/empty correctamente.
|
||||||
|
|
||||||
|
### Empresa
|
||||||
|
|
||||||
|
- [ ] Usa la empresa activa existente.
|
||||||
|
- [ ] No introduce un selector paralelo.
|
||||||
|
- [ ] El cambio de empresa no deja datos stale de la anterior.
|
||||||
|
|
||||||
|
### Seguridad
|
||||||
|
|
||||||
|
- [ ] La navegación respeta permisos frontend.
|
||||||
|
- [ ] El backend valida autorización de forma independiente.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 23. Anti-patterns
|
||||||
|
|
||||||
|
No hacer:
|
||||||
|
|
||||||
|
```txt
|
||||||
|
importar SettingsPage desde el shell
|
||||||
|
registrar componentes React como metadata principal
|
||||||
|
crear un GenericSettingsForm
|
||||||
|
crear un GenericSettingsRepository
|
||||||
|
usar localStorage para configuración de negocio
|
||||||
|
crear otro selector de company
|
||||||
|
hacer imports entre módulos para agrupar settings
|
||||||
|
usar un switch central por setting
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 24. Regla mental final
|
||||||
|
|
||||||
|
```txt
|
||||||
|
El módulo declara que su setting existe.
|
||||||
|
El shell decide cómo descubrirlo y mostrarlo.
|
||||||
|
El router decide cómo llegar.
|
||||||
|
El módulo decide cómo funciona.
|
||||||
|
```
|
||||||
|
|
||||||
|
Criterio de validación:
|
||||||
|
|
||||||
|
```txt
|
||||||
|
Si para añadir una nueva configuración hay que modificar SettingsPage,
|
||||||
|
SettingsNavigation o un switch central, la integración está mal diseñada.
|
||||||
|
```
|
||||||
1382
docs/settings/frontend-erp-settings-system-design.md
Normal file
1382
docs/settings/frontend-erp-settings-system-design.md
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user