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