Saltar a contenido

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). Ver frontend/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 BPBankAccounts del proveedor (regla U_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 = GLAccount de HouseBankAccounts según U_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 del VendorPayment.
  • 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 vincula CardCode en la fila de BankPages.
  • La lista muestra: fecha, monto, memo (beneficiario | RUC | banco | cuenta), referencia; filtrable por monto/fecha/texto. Los datos del Memo permiten sugerir la fila correcta (RUC del proveedor seleccionado).
  • Si es otro banco: sin lista de extracto; TransferReference y 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 (PurchaseInvoices con 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 → PaymentDrafts outgoing (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 VendorPayment hereda Reference2 (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:

  1. Sección bancaria: lista de egresos de BankPages de la cuenta correspondiente a la moneda del pago (la cuenta de salida ya quedó fijada al solicitar):
  2. Preselección automática si la operación bancaria está FINALIZADO (match comprobante → Reference, doc 03 §G4b) — Tesorería solo verifica.
  3. Sin preselección: lista asistida — resaltar filas con monto igual y RUC del proveedor en el Memo; filtros por fecha/monto/texto.
  4. La fila elegida completa TransferReference y fecha contable (visibles, solo lectura una vez seleccionada la fila).
  5. 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.
  6. Confirmar → POST /request/:id/confirm (el backend re-valida saldos y ejecuta el batch). Éxito → la vista pasa a modo Ver detalle con estado Confirmado, mostrando DocNum real del pago.
  7. 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.