FactuGES_ERP/modules/companies
2026-09-22 16:48:56 +02:00
..
src fix: reducir el tamaño de los íconos en varios componentes 2026-09-22 16:48:56 +02:00
package.json actualizar versión a 0.10.10 en todos los módulos y archivos de configuración 2026-09-21 19:12:44 +02:00
README.md feat(companies): implement update current company use case and associated controllers 2026-08-17 15:49:11 +02:00
tsconfig.json feat: update TypeScript configurations and add frontend testing documentation 2026-08-19 10:39:15 +02:00

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
  • defaultPaymentTermId
  • slug
  • status

Separación arquitectónica:

  • modules/identity: autenticación, cuentas, memberships, acceso account-company
  • modules/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/available no usa requireIdentityTenant(params)
  • GET /companies/current y PATCH /companies/current usan auth de identity + requireCompanyContext(...) cableado con companyAccessChecker de identity y publicFinder propio de companies
  • los endpoints legacy por :company_id siguen tenant-scoped y comparan req.user.companyId con :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

  • CompanyMembership vive en identity.
  • No mover memberships a companies.
  • No usar customers para representar la empresa tenant.
  • companySlug no debe venir de token, X-Company-Slug ni req.user.companySlug.