Módulo de Pagos a Proveedores — Requerimientos de UI (Frontend)¶
Estado: Completo (2026-07-09) — formulario único con modos, bandeja unificada y detalle con línea de tiempo. Maqueta visual:
07-maqueta-ui.html(en_borradores/, no publicado) — wireframes de baja fidelidad de las 4 vistas (abrir en el navegador). Base: 01-requerimientos ·04-diseno-tecnico(en_borradores/, no publicado) (contrato REST §3) Stack: el del frontend OMS (Next.js + MUI v7, Formik + Yup, TanStack Query, CASL para roles). Verfrontend/CLAUDE.md.
1. Pantallas: Solicitud de pago y Registro de pago efectuado¶
Son dos pantallas hermanas sobre la misma entidad (mismos datos de base, mismo formulario troncal). Difieren en quién las usa, el manejo del banco de salida y el vínculo con el extracto bancario.
| Aspecto | A) Solicitud de pago | B) Registro de pago efectuado |
|---|---|---|
| Rol | Compras | Tesorería |
| Resultado | PaymentDraft (+ carga en banco si es transferencia) |
VendorPayment directo, sin draft |
| Endpoint | POST /outgoing-payments/request |
POST /outgoing-payments |
| Banco de salida | Fijo: Banco Continental (visible, no editable) | Seleccionable |
| Vínculo con extracto | No (el egreso aún no existe) | Sí, si el banco de salida es Continental |
| Uso típico | Circuito normal: solicitar → autorizar en banco → confirmar | Pago ya ejecutado por otro canal que no pasó por solicitud |
1.1 Formulario troncal (común a ambas)¶
- Proveedor (búsqueda por nombre/RUC —
CardType: cSupplier). - Moneda (GS / USD) y monto.
- Fecha del pago.
- Medio de pago (alcance MVP: transferencia y efectivo; estructura lista para cheque).
- Facturas a aplicar (ver §1.4).
- Observaciones (remarks).
- Adjunto opcional (PDF/PNG/JPEG, máx. 10 MB).
Validaciones visibles en el formulario (espejo de las del backend, doc 04 §5):
- Monto aplicado por factura ≤ saldo (
DocTotal − PaidToDate), mostrado por línea. - Suma de aplicaciones = monto del pago.
- Si es transferencia: proveedor con cuenta bancaria en la moneda del pago (ver §1.2); si no la tiene, error accionable ("cargar la cuenta bancaria del proveedor en SAP").
1.2 Pantalla A — Solicitud de pago (Compras)¶
- Si el medio es transferencia, la UI exige los datos de la transferencia al proveedor:
- Cuenta destino: resuelta por la moneda del pago contra
BPBankAccountsdel proveedor (reglaU_Moneda, doc 03 §6b): única → se muestra ya seleccionada; varias → selector; ninguna → error accionable. - Se muestran (solo lectura) los datos que viajarán al banco: titular, banco destino, RUC/CI — para que el solicitante verifique.
- Banco de salida: "Banco Continental" fijo y visible ("el pago saldrá de la cuenta
Banco Continental
"). No editable: la decisión no es del solicitante; por ahora se modela un único banco de salida. - Efecto en el payload: el draft lleva la cuenta contable del banco de salida
(
TransferAccount=GLAccountdeHouseBankAccountssegúnU_MonedaPago). - Evolución prevista: si a futuro se levanta la simplificación de banco único, el selector de banco de salida aparecería en la confirmación de Tesorería, no en la solicitud. Se reanalizará si ocurre.
- Al enviar: respuesta con
docEntry+bankTicket; mostrar el ticket al usuario (es su referencia de seguimiento). - Si la carga en el banco falla, la solicitud igual queda creada (doc 04 §5b D1): la UI lo informa sin ambigüedad —"la solicitud se guardó, pero no se pudo cargar en el banco"— y la deja en la bandeja como Carga bancaria fallida, con la acción de reintento. No se pide al usuario rehacer el formulario.
1.3 Pantalla B — Registro de pago efectuado (Tesorería)¶
- Selector de banco de salida: fuente
HouseBankAccounts(DSC1) — hoy Continental GS/USD e Itaú GS/USD. Lo que interesa del banco elegido es su cuenta contable (GLAccount) para el origen contable delVendorPayment. - Los códigos contables son estáticos: se cargan una vez y se cachean (patrón de cobros con sus cuentas estáticas); no se consultan en cada solicitud.
- Si el banco de salida es Continental: la UI muestra la lista de egresos del
extracto (
GET /outgoing-payments/bank-movements?currency=..., datos de BankPages) para seleccionar el movimiento y asignarlo al pago: - La fila elegida aporta
TransferReference(=Reference/comprobante), fecha contable, y el backend vinculaCardCodeen la fila de BankPages. - La lista muestra: fecha, monto, memo (beneficiario | RUC | banco | cuenta), referencia;
filtrable por monto/fecha/texto. Los datos del
Memopermiten sugerir la fila correcta (RUC del proveedor seleccionado). - Si es otro banco: sin lista de extracto;
TransferReferencey fecha se cargan manualmente. - No genera draft ni carga bancaria: el pago ya ocurrió por otro canal.
1.4 Regla común — facturas o anticipo (Def. 4)¶
- Selector de facturas abiertas del proveedor (
PurchaseInvoicescon saldo), con aplicación parcial o total por factura. Siempre disponible si existen facturas. - Si no se selecciona ninguna factura: la UI lo hace explícito — se creará un
anticipo (
PurchaseDownPayment) vinculado al Draft/VendorPayment por el valor del pago, para aplicarlo después contra la factura futura (la factura se creará en SAP con fecha posterior al pago). No existe el "pago suelto". - Texto guía sugerido: "Sin factura seleccionada: se registrará como anticipo a proveedor, a aplicar contra una factura futura."
2. Bandeja de pagos — vista unificada de solicitudes y confirmados¶
2.1 Principio de abstracción¶
El usuario no debe conocer los objetos SAP involucrados. Para él existe un solo
concepto — el Pago a proveedor — que atraviesa estados: se solicita → se confirma.
Que por debajo sean dos entidades distintas (PaymentDraft para la solicitud,
VendorPayment para el pago efectuado) es un detalle que el sistema abstrae.
La abstracción es viable sin ambigüedad por una propiedad del modelo (doc 02 §B5): al
confirmarse, el draft queda Cancelled: 'tYES' y sale del conjunto de pendientes,
"reemplazado" por su VendorPayment. Por lo tanto:
Bandeja = PaymentDrafts pendientes (Cancelled tNO) ∪ VendorPayments (Cancelled tNO)
└── estado: variantes de "Solicitado" └── estado: "Confirmado"
La unión nunca duplica un pago y cubre el ciclo de vida completo.
2.2 Estados de cara al usuario¶
| Estado (chip) | Entidad subyacente | Condición |
|---|---|---|
| Solicitado | Draft pendiente | Medio no bancario (efectivo/cheque), o transferencia con la carga en curso |
| Carga bancaria fallida | Draft pendiente sin ticket, medio transferencia | La operación no llegó a cargarse en el banco (doc 04 §5b). Requiere reintento; es el único estado con esa acción |
| Esperando autorización del banco | Draft pendiente + ticket | Consulta por ticket: PENDIENTE |
| Transferencia ejecutada — por confirmar | Draft pendiente + ticket | Consulta por ticket: FINALIZADO (la auto-confirmación lo tomará; visible si está en fallback manual) |
| Rechazado / anulado en banco | Draft pendiente + ticket | motivoRechazo ≠ null o anulada — requiere decisión humana (confirmar por otra vía o borrar) |
| Confirmado | VendorPayment |
Pago efectuado con asiento contable |
| Anulado (opcional, filtro) | VendorPayment Cancelled: tYES |
Anulado por contabilidad en SAP (Def. 5); oculto por defecto |
Los subestados que dependen de la consulta por ticket (Esperando autorización, Transferencia ejecutada, Rechazado/anulado) llegan del backend en la fase 3 del plan; mientras esa fase no exista, esos drafts se muestran como Solicitado.
Carga bancaria fallida es la excepción: se deriva de datos que el draft ya tiene
(transferencia con Reference2 vacío), sin consultar al banco, y por eso está disponible
desde la fase 2 — que es cuando empieza a poder fallar la carga. Es también el único
estado pendiente que no distingue entre "no se cargó" y "se cargó y se perdió el
ticket": esa distinción la hace el guard al reintentar, no la bandeja (doc 04 §5b).
2.3 La bandeja (listado único)¶
- Una sola pantalla "Pagos a proveedores", con pestañas o chips de filtro por
estado:
Pendientes(default) ·Confirmados·Todos. Las pestañas son filtros sobre el mismo concepto, no dos módulos. - Columnas idénticas en todos los estados (mismo shape de fila): proveedor (nombre + RUC) · fecha · monto + moneda · medio de pago · estado (chip) · solicitante · referencia (ticket bancario o nro. de comprobante según estado) · nro. de documento SAP.
- Acciones por fila según estado y rol: ver detalle (siempre); borrar (solo pendientes, Compras/Tesorería); confirmar manualmente (solo pendientes, Tesorería, cuando aplique); reintentar carga bancaria (solo estado Carga bancaria fallida, Compras/Tesorería). El reintento pasa por el guard del backend (doc 04 §5b D4) y puede terminar en tres desenlaces, todos que la UI debe saber mostrar: cargado (aparece el ticket), ya estaba cargado (se recuperó el ticket, no se duplicó), o bloqueado (no se pudo verificar contra el banco — se muestra el motivo y no se reintenta).
- Actualización en vivo: la bandeja se suscribe a los eventos WS
(
new_outgoing_payment_draft,outgoing_payment_confirmed,OUTGOING_CANCELLED) para refrescar sin recarga.
2.4 Implicación para el backend (vista normalizada)¶
El frontend no debe fusionar entidades: el backend expone un DTO normalizado de
listado (OutgoingPaymentListItemDto) con estado y un discriminador interno
(source: 'draft' | 'payment' + docEntry), sirviendo:
Pendientes→PaymentDraftsoutgoing (Cancelled eq 'tNO').Confirmados→VendorPayments(Cancelled eq 'tNO').Todos→ fusión ordenada por fecha (paginación por fusión en backend).
El detalle se abre con source + docEntry; el DTO de detalle también es normalizado.
(Agregado al contrato REST del doc 04 §3.)
2.5 Detalle: una sola plantilla con línea de tiempo¶
El detalle usa la misma plantilla para cualquier estado, con una línea de tiempo del ciclo de vida que hace visible el modelo mental sin exponer entidades:
● Solicitado por <creador> — <fecha> (draft: U_SalesPersonID + DocDate)
● Cargado en el banco — ticket <nro> (Reference2; si transferencia)
● Autorizado en el banco — por <autoriza> (consulta por ticket, fase 3)
● Confirmado — <fecha> · doc <DocNum> · asiento (VendorPayment; manual o automático)
Secciones del detalle: datos del pago · facturas aplicadas (o anticipo) · datos de la transferencia (cuenta destino; y comprobante/extracto una vez confirmado) · adjunto.
2.6 Continuidad de referencias¶
- El identificador estable de cara al usuario durante el ciclo es el ticket bancario (transferencias) y, tras la confirmación, el DocNum del pago.
- El
VendorPaymentheredaReference2(ticket) del draft en la conversión → es la clave de continuidad que permite a la UI unir la historia completa en el detalle.
3. Confirmación manual — el formulario único de Pago, por modos¶
3.1 Principio: un solo formulario, cuatro modos¶
Las pantallas del §1 (crear solicitud, registrar pago efectuado), la confirmación manual y la visualización de detalle son el mismo formulario de Pago a proveedor. Lo que cambia es el modo, derivado de estado del pago + rol del usuario + intención:
| Modo | Rol | Estado de los campos | Acción principal |
|---|---|---|---|
| Crear solicitud (§1.2) | Compras | Todo editable; banco de salida fijo Continental | "Solicitar pago" → POST /request |
| Registrar pago efectuado (§1.3) | Tesorería | Todo editable; banco de salida seleccionable; extracto si Continental | "Registrar pago" → POST /outgoing-payments |
| Confirmar solicitud | Tesorería | Datos del pago solo lectura (vienen de la solicitud); editable únicamente la sección bancaria (selección de egreso) y observaciones | "Confirmar pago" → POST /request/:id/confirm |
| Ver detalle (§2.5) | Ambos | Todo solo lectura + línea de tiempo | — |
Beneficios: un solo componente que mantener, cero divergencia visual entre "lo que se solicitó" y "lo que se confirma", y el usuario percibe siempre el mismo objeto.
3.2 Modo Confirmar (fallback manual del flujo automático)¶
Se abre desde la bandeja sobre un pago pendiente (acción visible solo para Tesorería). Es el formulario del §1.3 precargado y bloqueado con los datos de la solicitud (proveedor, monto, moneda, facturas/anticipo, adjunto); lo único que falta —y lo único editable— es el vínculo con el extracto:
- Sección bancaria: lista de egresos de
BankPagesde la cuenta correspondiente a la moneda del pago (la cuenta de salida ya quedó fijada al solicitar): - Preselección automática si la operación bancaria está
FINALIZADO(matchcomprobante→Reference, doc 03 §G4b) — Tesorería solo verifica. - Sin preselección: lista asistida — resaltar filas con monto igual y RUC del
proveedor en el
Memo; filtros por fecha/monto/texto. - La fila elegida completa
TransferReferencey fecha contable (visibles, solo lectura una vez seleccionada la fila). - Contexto para decidir: si la fase de estado bancario está activa, el modo muestra
el estado de la operación por ticket y, cuando aplique, por qué no se
auto-confirmó (operación no finalizada,
motivoRechazo, monto distinto, fila no encontrada) — es la información que Tesorería necesita para resolver el fallback. - Confirmar →
POST /request/:id/confirm(el backend re-valida saldos y ejecuta el batch). Éxito → la vista pasa a modo Ver detalle con estadoConfirmado, mostrandoDocNumreal del pago. - Acción secundaria: Borrar solicitud (con la advertencia del doc 04 §7 si tiene ticket bancario vivo).
Con la auto-confirmación activa (Etapa 2 de producción), este modo se usa solo para los casos que el matching determinista no resolvió; en la Etapa 1 (doc 03 §G4c) es el único camino de confirmación.
Estado del documento¶
Las cuatro superficies de UI del módulo quedan especificadas: formulario único con modos (§1, §3), bandeja unificada (§2) y detalle con línea de tiempo (§2.5). Sin pendientes de pantallas; los pendientes funcionales del módulo están en doc 04 §14.
Historial¶
| Fecha | Cambio |
|---|---|
| 2026-07-09 | Sección 1: pantallas de Solicitud de pago y Registro de pago efectuado — formulario troncal, banco de salida fijo (A) vs. seleccionable (B), vínculo con extracto en B, regla facturas/anticipo. |
| 2026-07-09 | Sección 2: bandeja unificada — principio de abstracción (un solo concepto "Pago" con estados), tabla de estados, listado único con filtros, DTO normalizado en backend, detalle con línea de tiempo, continuidad por ticket. |
| 2026-07-09 | Sección 3: formulario único con cuatro modos (crear solicitud / registrar pago / confirmar / ver); modo Confirmar como fallback manual con preselección por comprobante y contexto de por qué no se auto-confirmó. Documento completo. |
| 2026-07-09 | Maqueta visual 07-maqueta-ui.html: wireframes low-fi de bandeja, crear solicitud, confirmar y detalle, con anotaciones referenciando las secciones de este documento. |
| 2026-08-06 | Estado Carga bancaria fallida en la bandeja (§2.2) con su acción de reintento y los tres desenlaces posibles (§2.3); §1.2: la solicitud sobrevive al fallo de carga y no se pide rehacer el formulario. Decisiones en doc 04 §5b. |