- Removed authentication and company context guards from multiple controllers in the customer, proforma, document series, and supplier modules. - Consolidated guard registration logic in routes to enforce company ID restrictions globally. - Cleaned up imports and ensured consistent error handling across controllers. |
||
|---|---|---|
| .. | ||
| src | ||
| package.json | ||
| README.md | ||
| tsconfig.json | ||
modules/companies
companies es el módulo independiente y fuente de verdad de la ficha operativa de empresa.
Responsabilidades
Gestiona la entidad Company funcional del ERP:
- datos legales
- datos operativos básicos
defaultPaymentTermIdslugstatus
Separación arquitectónica:
modules/identity: autenticación, cuentas, memberships, acceso account-companymodules/companies: ficha real de empresa y validación de company activa
Tabla companies
Campos actuales:
id
legal_name
trade_name
tin
slug
email
phone
website
default_payment_term_id
status
created_at
updated_at
Índices esperados:
UNIQUE(slug)
INDEX(status)
INDEX(tin)
Servicios públicos
El módulo expone:
companies:general
Responsabilidad:
- validar existencia y estado activo de la company
- devolver datos públicos/operativos de empresa
No debe asumir:
- memberships
- autenticación por cuenta
- roles/permisos de identity
Dependencias
modules/companies depende de identity y catalogs.
Uso actual:
- sus endpoints usan
requireIdentityAuthenticated(params) GET /companies/availableno usarequireIdentityTenant(params)GET /companies/currentyPATCH /companies/currentusan auth deidentity+requireCompanyContext(...)cableado concompanyAccessCheckerdeidentityypublicFinderpropio decompanies- los endpoints legacy por
:company_idsiguen tenant-scoped y comparanreq.user.companyIdcon:company_id
Endpoints relevantes
POST /companies
GET /companies/available
GET /companies/current
PATCH /companies/current
GET /companies/:company_id
PATCH /companies/:company_id
POST /companies/:company_id/enable
POST /companies/:company_id/disable
Settings de empresa activa
/settings/company/details consume:
GET /companies/current
PATCH /companies/current
Resolución real del target:
Authorization
+ X-Company-Id
+ requireCompanyContext(...)
=> req.user.companyId
El cliente no selecciona la empresa a editar mediante companyId en URL, body ni query.
Política V1 de autorización
En la V1 cualquier miembro activo de la compañía puede editar sus datos generales mediante:
PATCH /companies/current
Política real:
usuario autenticado
+ X-Company-Id válido
+ membership activa en esa company
+ company activa
No existe todavía enforcement real de RBAC ni permisos granulares en runtime.
identity:companies:update puede existir como código futuro de catálogo, pero no representa autorización aplicada hoy.
Campos editables actuales
PATCH /companies/current admite solo:
legal_name
trade_name
tin
email
phone
website
default_payment_term_id
En frontend, la feature:
/settings/company/details
modela esos mismos campos como ficha editable de la company activa.
La UI actual agrupa la edición en tres secciones:
Datos generales
→ legalName
→ tradeName
→ tin
Datos de contacto
→ email
→ phone
→ website
Condiciones comerciales
→ defaultPaymentTermId
Semántica PATCH esperada en la pantalla:
propiedad omitida -> conservar valor actual
propiedad presente con valor -> actualizar
propiedad nullable presente con null -> limpiar
Flujo de guardado esperado en frontend:
GET /companies/current
→ hydrata formulario
editar campos dirty
→ construir PATCH parcial
PATCH /companies/current
→ respuesta servidor como SSOT
→ updateActiveCompany(...)
→ reset del formulario con la respuesta
Política de errores frontend en esta pantalla:
fallo inicial sin datos utilizables
→ PageErrorState
error de refetch con datos previos
→ mantener formulario
→ ErrorAlert inline
cancelled
→ sin pantalla bloqueante
422 con paths mapeables
→ errores de campo en RHF
error general de guardado
→ toast
→ sin reset del formulario
La UI no debe seleccionar el target mediante companyId.
Fuera de alcance de esta API:
slug
status
fiscalidad avanzada
VeriFactu
document series
payment methods
branding
bank accounts
defaultPaymentMethodId
defaultPaymentTermId
Contrato actual:
omitido -> mantener
null -> desvincular
UUID -> validar dentro de la company activa
La referencia es:
nullable
company-scoped
validada mediante catalogs
Semántica HTTP actual:
UUID activo de la misma company -> 200
UUID de otra company -> 422
UUID inactivo -> 422
El error de asignación es deliberadamente opaco:
Default payment term is not assignable to the active company.
No expone si el problema concreto es:
- inexistente
- cross-company
- inactivo
El PATCH es transaccional:
- si falla
default_payment_term_id - no se persisten otros cambios del mismo request
Limitaciones V1 de Company Details
Fuera del alcance funcional actual:
- RBAC granular
- address
- country
- language
- currency
- timezone
- branding
- logo
- bank accounts
- fiscalidad avanzada
- VeriFactu
- series documentales
defaultPaymentMethodId
Reglas
CompanyMembershipvive enidentity.- No mover memberships a
companies. - No usar
customerspara representar la empresa tenant. companySlugno debe venir de token,X-Company-Slugnireq.user.companySlug.