Entrega condicionada al pago

En los flujos de venta con pago anticipado (una factura proforma, un anticipo, o cualquier otro acuerdo de «pagar primero, enviar después»), los bienes no deben salir físicamente del almacén antes de que el dinero haya llegado realmente. La entrega condicionada al pago retiene la entrega saliente de un pedido de venta mientras el pedido esté sin pagar: bloquea tanto la reserva de existencias como el botón Validar, y se libera de forma automática en cuanto todas las facturas están saldadas. Un usuario con privilegios puede anular la retención y enviar antes de tiempo, y esa anulación queda completamente registrada en el chatter.

Ver también

screenshot: payment-gated-delivery-order-banner
menu
Sales ‣ Orders ‣ Orders
shows
A confirmed sales order with the banner warning that the delivery is held until the order is paid.
highlight
The banner (red frame).
module
sale_stock_payment_gate
notes
English UI, light theme, 1440px width.

El mecanismo reutilizable de «En espera»

La entrega condicionada al pago se construye sobre un mecanismo de retención genérico que reside en el módulo base eyssen_stock y está disponible en todos los traslados, con independencia de las ventas o los pagos:

  • un interruptor Retener y un campo Motivo de la retención de solo lectura en stock.picking;

  • una cinta roja de En espera en el formulario del traslado siempre que Retener esté marcado, además de los filtros En espera / Sin retener en el panel de búsqueda de la lista de traslados; y

  • los métodos action_set_hold(reason) y action_release_hold(), que activan o desactivan a la vez Retener y Motivo de la retención.

Activar Retener anula de inmediato la reserva de los movimientos de existencias del traslado; al liberarlo, se vuelve a activar la reserva (_action_assign), de modo que el traslado recupera de forma automática las existencias disponibles. Cualquier módulo, no solo sale_stock_payment_gate, puede poner un traslado en retención de esta forma y esperar que la reserva permanezca desactivada hasta que se libere.

Nota

Por sí solo, el Retener genérico solo detiene la reserva. No bloquea Validar; esa protección adicional y más estricta es específica de la barrera de pago que se describe a continuación.

El indicador del plazo de pago

screenshot: payment-gated-delivery-payment-term-toggle
shows
Payment term form with the Require payment before delivery checkbox.
module
sale_stock_payment_gate
notes
English UI, light theme, 1440px width.

Si un pedido queda condicionado o no lo decide su plazo de pago. La casilla Requerir pago antes de la entrega, añadida al formulario del plazo de pago, marca un plazo como «pagar antes de enviar». Los pedidos que utilizan un plazo de pago con la casilla desactivada, por ejemplo un plazo de pago contra entrega, nunca se retienen. Los pedidos sin ningún plazo de pago tampoco se retienen nunca.

Retener la entrega al confirmar el pedido

Cuando se confirma un pedido de venta y su plazo de pago requiere el pago antes de la entrega, todos los traslados salientes de ese pedido que aún no estén hechos ni cancelados se ponen en retención en un solo paso: se marca Retener, se establece Motivo de la retención en «Esperando el pago de la entrega», y también se activa el propio campo Retenido por pago de la barrera. Si el pedido ya está pagado por completo en el momento de la confirmación (por ejemplo, se liquidó una proforma o un anticipo antes de confirmar), no se aplica ninguna retención y la entrega continúa con normalidad.

screenshot: payment-gated-delivery-picking-on-hold
shows
Delivery transfer showing the On Hold ribbon and the payment hold reason.
module
sale_stock_payment_gate
notes
English UI, light theme, 1440px width.

La barrera estricta: sin reserva y sin validación

Una entrega retenida por pago se bloquea por partida doble, de modo que no puede colarse ni por la vía automática ni por la manual:

  • Sin reserva. La barrera anula la reserva de movimientos de existencias, de modo que se omite cualquier movimiento que pertenezca a un traslado retenido por pago, tanto cuando Odoo asigna existencias de forma automática al confirmar como cuando un usuario hace clic en Comprobar disponibilidad. Esta comprobación se basa en el propio indicador Retenido por pago de la barrera, por lo que se mantiene aunque el interruptor genérico Retener se desactive por separado.

  • Sin validación. Hacer clic en Validar en una entrega retenida por pago genera un error en lugar de enviar los bienes, e indica al usuario el botón Liberar para entrega descrito a continuación.

screenshot: payment-gated-delivery-validate-blocked-error
shows
Error dialog blocking validation of a payment-held delivery.
module
sale_stock_payment_gate
notes
English UI, light theme, 1440px width.

Importante

Escribir directamente Retenido por pago = desmarcado en un traslado está bloqueado para cualquier usuario que no pertenezca al grupo Entregar sin pago. Solo el botón Liberar para entrega de ese grupo (o una escritura privilegiada o del sistema) puede levantar la barrera; una simple llamada a write() desde otro flujo no puede eludirla de forma silenciosa.

Liberación automática cuando se paga el pedido

screenshot: payment-gated-delivery-auto-release-paid-invoice
shows
Fully paid customer invoice next to its now-released delivery.
module
sale_stock_payment_gate
notes
English UI, light theme, 1440px width.

Un pedido se considera pagado para la entrega en cuanto todas las facturas de cliente contabilizadas vinculadas a él alcanzan el estado de pago Pagado o En proceso de pago. Una regla de base.automation vigila el campo Estado de pago de las facturas de cliente (account.move, out_invoice) y, en cada creación o escritura que lo modifique, vuelve a evaluar todos los traslados salientes y sin hacer de los pedidos relacionados:

  • si el pedido ya está pagado por completo, se libera cualquier traslado que siga en retención por pago: se desactivan Retenido por pago, Retener y Motivo de la retención, y la reserva se vuelve a ejecutar de forma automática; y

  • si el pedido no está pagado por completo y un traslado no está actualmente retenido (y no se liberó manualmente; vea más abajo), se vuelve a retener con el motivo «Pago revertido: entrega bloqueada de nuevo».

Nota

En proceso de pago se cuenta como pagado porque representa un cobro completo cuya conciliación con el extracto bancario todavía está pendiente. Un pago parcial nunca libera la retención. La barrera asume que la factura o facturas vinculadas cubren el importe total del pedido; con un anticipo parcial nativo, una factura parcial pagada por completo liberaría toda la entrega antes de tiempo, y ese escenario queda explícitamente fuera del alcance.

Nuevo bloqueo al revertir el pago

Como la misma automatización vuelve a evaluar el pedido ante cada cambio en Estado de pago, revertir un pago (por ejemplo, desconciliar o cancelar un pago de forma que la factura vuelva a Sin pagar) vuelve a aplicar automáticamente la retención a cualquier entrega sin hacer de ese pedido, siempre que un usuario con privilegios no la haya liberado manualmente.

Truco

La barrera solo lee los campos estándar account.move / payment_state de las facturas de cliente contabilizadas. No depende de ninguna localización: la misma lógica libera la entrega tanto si el pedido se liquidó mediante una factura proforma / díjbekérő de la NAV húngara, como mediante una factura de anticipo normal, o mediante cualquier otro módulo que termine contabilizando y pagando una factura de cliente contra el pedido.

Anulación manual: liberar una entrega antes del pago

screenshot: payment-gated-delivery-release-button
shows
Release for delivery button on a held transfer, with its confirmation prompt.
module
sale_stock_payment_gate
notes
English UI, light theme, 1440px width.

A veces una entrega realmente necesita enviarse antes de que el pedido esté pagado por completo (envío de cortesía, cliente de confianza, acuerdo manual). El botón Liberar para entrega de la cabecera del traslado hace precisamente esto:

  • solo es visible cuando el traslado está en retención por pago, y únicamente para los usuarios del grupo de seguridad Entregar sin pago;

  • al hacer clic se pide confirmación, y después se desactivan Retenido por pago, Retener y Motivo de la retención, y se activa Liberado manualmente para entrega para dejar constancia de la anulación; y

  • un mensaje en el chatter registra quién liberó la entrega y cuándo.

screenshot: payment-gated-delivery-release-chatter
shows
Chatter entry logging the manual release of a delivery.
module
sale_stock_payment_gate
notes
English UI, light theme, 1440px width.

Una entrega marcada como Liberado manualmente para entrega no vuelve a retenerse mediante la sincronización automática descrita anteriormente, aunque el pedido resulte estar sin pagar de nuevo más adelante; la decisión manual se respeta hasta que alguien vuelva a aplicar una retención a mano.

Las entregas parciales heredan la retención

Si una entrega retenida por pago (o previamente liberada) se envía solo parcialmente y Odoo crea una entrega pendiente para el resto, esta se reevalúa según la misma regla que la entrega original: si el pedido todavía requiere el pago antes de la entrega y aún no está totalmente pagado, la nueva transferencia de la entrega pendiente se retiene de nuevo, con el mismo motivo «Pendiente de pago para la entrega» — incluso si la transferencia original se había liberado manualmente.

screenshot: payment-gated-delivery-backorder-rehold
shows
Backorder transfer automatically re-held for payment.
module
sale_stock_payment_gate
notes
English UI, light theme, 1440px width.

Visibilidad a nivel de pedido

El formulario del pedido de venta muestra un aviso — «La entrega está retenida hasta que se pague este pedido.» — encima de las líneas del pedido siempre que alguna de las entregas del pedido esté actualmente retenida por pago. Esto se controla mediante el campo calculado Entrega retenida por pago, de modo que el personal de ventas ve el estado de retención de un vistazo sin necesidad de abrir la transferencia.

Configuración

  1. Asegúrese de que sale_stock_payment_gate esté instalado. Este módulo instala automáticamente eyssen_stock, sale_stock, account y base_automation.

  2. Vaya a Aplicación de Contabilidad/Facturación ‣ Configuración ‣ Términos de pago, abra (o cree) el término de pago utilizado para ventas prepagadas/proforma y marque Requerir pago antes de la entrega. Deje la casilla sin marcar en términos como el pago contra reembolso.

  3. Conceda el grupo Entregar sin pago (categoría Inventario) a los usuarios autorizados a saltarse la retención — por ejemplo, los responsables de almacén — a través de Aplicación de Ajustes ‣ Usuarios y compañías ‣ Usuarios. Este grupo también necesita el acceso habitual de lectura/escritura de inventario para poder ver y liberar la transferencia.

screenshot: payment-gated-delivery-deliver-without-payment-group
shows
Assigning the Deliver without payment group to a user.
module
sale_stock_payment_gate
notes
English UI, light theme, 1440px width.

No se requiere ninguna configuración adicional: la regla base.automation y la lógica de retención/liberación se activan en cuanto el módulo está instalado y al menos un término de pago tiene el indicador habilitado.

Uso

  1. Confirme un pedido de venta que utilice un término de pago con retención. Su entrega saliente se crea y se retiene de inmediato, a menos que el pedido ya esté totalmente pagado.

  2. El formulario del pedido muestra el aviso La entrega está retenida hasta que se pague este pedido., y la transferencia de entrega muestra la cinta En espera con Motivo de la retención = «Pendiente de pago para la entrega.» Comprobar disponibilidad no reserva existencias, y Validar se niega a ejecutarse.

  3. Cree y contabilice la factura del cliente (proforma, anticipo o factura normal) para el pedido y, a continuación, registre el pago completo. En cuanto el Estado de pago de la factura alcanza Pagado o En proceso de pago, la automatización libera la entrega: se elimina la retención y las existencias vuelven a reservarse.

  4. Valide con normalidad la entrega ya liberada.

  5. Si el envío anticipado es inevitable, un usuario con el grupo Entregar sin pago puede abrir la transferencia retenida y hacer clic en Liberar para entrega en lugar de esperar el pago. Esta anulación queda registrada en el chatter y se mantiene ante cambios posteriores del estado de pago; si más tarde se crea una entrega pendiente para la cantidad restante de ese mismo pedido, esta se retiene de nuevo automáticamente, salvo que para entonces el pedido ya esté totalmente pagado.

Alcance y módulos

Esta funcionalidad se implementa mediante dos módulos:

  • eyssen_stock — el elemento genérico y reutilizable En espera / Motivo de la retención en las transferencias (cinta, interruptor, filtros de búsqueda y la lógica de bloqueo/nueva reserva), utilizado aquí como bloque base.

  • sale_stock_payment_gate — la propia retención por pago: el indicador Requerir pago antes de la entrega del término de pago, la lógica de retención al confirmar, el bloqueo estricto de reserva/validación, la liberación y el nuevo bloqueo automáticos impulsados por base.automation ante cambios de pago, el grupo Entregar sin pago con su botón Liberar para entrega y su registro en el chatter, la nueva retención de las entregas pendientes, y el aviso a nivel de pedido.