FactuGES_ERP/docs/catalogs/payment-methods-design.md

142 lines
4.1 KiB
Markdown
Raw Normal View History

# Payment Methods Backend Design
## Scope
`PaymentMethod` es un catálogo `company-scoped` del módulo `catalogs`.
## Shape
Campos persistidos y expuestos para administración:
- `id`
- `company_id`
- `name`
- `description`
- `is_active`
- `is_system`
- `is_default`
- `system_key`
- `created_at`
- `updated_at`
- `deleted_at`
## System vs custom
Reglas:
- `is_system = true` implica `system_key != null`
- `is_system = false` implica `system_key = null`
- `is_system = true` no se puede editar, desactivar ni eliminar
Identidad estable de métodos del sistema:
- `cash`
- `bank_transfer`
- `card`
- `direct_debit`
## Active and default
Reglas:
- `is_default = true` implica `is_active = true`
- un método `default` no se puede desactivar
- un método `default` no se puede eliminar
- el cambio de default solo se realiza mediante `PATCH /catalogs/payment-methods/:payment_method_id/default`
La unicidad del default se garantiza mediante servicio transaccional y bloqueo por empresa. No se fuerza con constraint SQL adicional para evitar una solución opaca en MariaDB.
## Bootstrap
Endpoint explícito e idempotente:
- `POST /catalogs/payment-methods/bootstrap-system`
Comportamiento:
- crea los cuatro métodos del sistema que falten
- restaura un system method soft-deleted si ya existía por `system_key`
- resincroniza `name`, `is_system`, `is_active`, `is_default = false` y `system_key`
- si la empresa no tiene default, establece `cash` como default inicial
Métodos creados:
- `Efectivo`
- `Transferencia bancaria`
- `Tarjeta`
- `Domiciliación bancaria`
## Delete policy
Un método solo puede eliminarse si:
- `is_system === false`
- `is_default === false`
- no está referenciado por consumidores vivos
Bloqueos actuales:
- `customers.payment_method_id`
- `proformas.payment_method_id`
- `supplier_invoices.payment_method_id`
No se bloquea por `issued_invoices`, porque ese módulo mantiene snapshot histórico suficiente del método de pago emitido.
## Reference protection
La arquitectura ideal sería mediante public services consumidores, pero `catalogs` ya es dependencia de `customers` y `customer-invoices`. Para evitar un ciclo de módulos, la protección referencial se implementa en `catalogs` con un checker de infraestructura específico contra los modelos registrados en Sequelize.
## Consumers
Consumidores actuales auditados:
- `customers`
- `customer-invoices/proformas`
- `customer-invoices/issued-invoices`
- `supplier-invoices`
- `factuges`
`factuges` no bloquea delete porque resuelve métodos de pago durante la importación y no mantiene una referencia persistente viva auditada en este flujo.
## Emision de Proformas
`customer-invoices` consume `PaymentMethod` mediante servicios publicos de `catalogs`.
Semantica vigente en emision:
- la Proforma mantiene una referencia viva `paymentMethodId`;
- la Issued Invoice persiste un snapshot historico del metodo de pago emitido;
- si `paymentMethodId` no existe dentro de la company activa, la emision falla;
- si el metodo existe pero esta inactivo, la emision falla;
- este bloqueo aplica solo al boundary de emision y no convierte automaticamente `paymentMethodId` en obligatorio durante create draft.
Datos copiados al snapshot historico de `issued_invoices`:
- `payment_method_id`
- `payment_method_name`
- `payment_method_description`
Tras emitir, el detalle historico no depende del catalogo vivo para representar la forma de pago usada.
## Frontend Settings
La gestión administrativa frontend vive en:
- `/settings/general/payment-methods`
- módulo técnico `catalogs`
Características:
- listado administrativo con activos e inactivos
- create/edit mediante dialogs
- cambio de default mediante radio por fila
- activación/desactivación con endpoints específicos
- protección visual para `system` y `default`
- confirmación de delete con manejo de conflicto `in use`
Compatibilidad:
- el listado administrativo reutiliza el catálogo compartido de `payment-methods`
- los selectores existentes siguen filtrando por `isActive=true` donde ya lo hacían
- esta fase no aplica el default automáticamente en Proformas ni Customers