Qué dice GoCardless
| Dónde | Reason o causa | Texto de GoCardless |
|---|---|---|
API, al crear un cobro (invalid_state) | mandate_replaced | Mandate has been replaced. Check links[new_mandate] in the error or on the mandate itself. |
| mandates · replaced | scheme_identifier_changed | The creditor has changed to a different scheme identifier, so this mandate has been cancelled and replaced by a new one. |
La documentación de eventos lo explica así: «The mandate has been cancelled and replaced by a new mandate (for example, because the creditor has moved to a new Service User Number).». Y lo que trae el evento: «The event will include links[new_mandate] with the ID of the new mandate.».
mandate_replaced es un error invalid_state: la acción no vale en el estado actual del recurso. Para esos errores GoCardless pide avisar al usuario y no reintentar («invalid_state → inform the end user, do not allow retry.»).

Cuándo aparece
El cambio no lo provoca el cliente ni su banco: el evento replaced tiene origen gocardless, y la causa documentada es que el acreedor, la cuenta con la que cobras en GoCardless, ha pasado a otro identificador de esquema. GoCardless cancela el mandato viejo y crea uno nuevo en su lugar.
mandate_replaced solo aparece si Odoo intenta cobrar con el mandato viejo: el cobro de una suscripción que se renueva, o un pago registrado con el método de pago guardado del cliente, antes de que Odoo haya aplicado el evento.
Lo que hace Odoo con el conector
Con el evento replaced:
- Toma el mandato nuevo de
links.new_mandate. - Pasa a ese mandato el método de pago guardado del cliente y lo da por bueno, en vez de darlo por perdido. Si el método estaba archivado, lo reactiva; Odoo 17 no deja desarchivar un método de pago, y ahí el conector crea uno nuevo para el mandato nuevo.
- Lo escribe en la ficha del cliente: «El mandato de GoCardless se puede volver a usar (replaced).».
Esa nota la escribe el conector al aplicar el evento, sin nadie delante. En una base de datos creada en castellano sale así; en una creada en inglés y pasada después a castellano, en inglés: «The GoCardless mandate is usable again (replaced).».
Con mandate_replaced en un cobro, el conector no hace nada especial: al crear un cobro solo trata aparte mandate_is_inactive. La transacción pasa a «Error» con «GoCardless rechazó la solicitud.» y, debajo, el mensaje de GoCardless con mandate_replaced y el request_id entre corchetes. El mandato nuevo lo toma del evento, no del error. Ese mensaje sale en el idioma de quien lanza el cobro; si lo lanza una tarea programada, en una base creada en inglés y pasada después a castellano sale en inglés: «GoCardless rejected the request.».

Qué hacer
- Si un cobro se queda en error con
mandate_replaced, abre la transacción desde la factura, con el botón «Transacción de pago» de arriba; el menú de transacciones solo sale en modo desarrollador, y en Odoo 20 no existe. - Mira en la ficha del cliente si ya está la nota de que el mandato se puede volver a usar (replaced). Si está, el método de pago ya apunta al mandato nuevo.
- Si no está, el evento aún no ha llegado. La tarea que cada hora recupera los eventos perdidos lo trae; si tarda más de eso, revisa que los webhooks de GoCardless lleguen a Odoo.
- Con el método de pago al día, vuelve a cobrar la factura.
¿Hay que pedir al cliente que firme otra vez?
No para seguir cobrando con el conector: el mandato nuevo lo crea GoCardless y el conector pasa a él el método de pago guardado.
¿Qué pasa en Odoo 17?
Lo mismo, con una diferencia: si el método de pago viejo estaba archivado, Odoo 17 no deja reactivarlo, así que el conector crea uno nuevo para el mandato nuevo. En 18, 19 y 20 reactiva el que había.
Con nuestro conector
En Odoo 17, 18, 19 y 20 el conector sigue al mandato nuevo en cuanto GoCardless avisa de la sustitución: el cliente conserva su método de pago y la siguiente factura se cobra con el mandato que GoCardless dejó en su lugar.
Sigue leyendo
Comprobado en el código del conector (versión 17.0, 18.0, 19.0 y 20.0) y en las fuentes enlazadas
Fuentes
- docs.gocardless.com/docs/api-reference/responses-and-errors
- docs.gocardless.com/docs/api-reference/events/mandate
- Código del módulo: flexigo_payment_gocardless: models/payment_token.py, línea 72 en 17.0 (d203ee6), línea 72 en 18.0 (e2ab18b), línea 72 en 19.0 (ce7f5a3) y línea 71 en 20.0 (688d86b)
- Código del módulo: flexigo_payment_gocardless: const.py, línea 150 en 17.0 (d203ee6), 18.0 (e2ab18b), 19.0 (ce7f5a3) y 20.0 (688d86b)
- Código del módulo: flexigo_payment_gocardless: const.py, línea 158 en 17.0 (d203ee6), 18.0 (e2ab18b), 19.0 (ce7f5a3) y 20.0 (688d86b)
- Código del módulo: flexigo_payment_gocardless: models/payment_token.py, línea 77 en 17.0 (d203ee6), línea 77 en 18.0 (e2ab18b), línea 77 en 19.0 (ce7f5a3) y línea 76 en 20.0 (688d86b)
- Código del módulo: flexigo_payment_gocardless: models/payment_token.py, línea 96 en 17.0 (d203ee6), línea 96 en 18.0 (e2ab18b), línea 96 en 19.0 (ce7f5a3) y línea 95 en 20.0 (688d86b)
- Código del módulo: flexigo_payment_gocardless: i18n/es.po, línea 1250 en 17.0 (d203ee6), línea 1250 en 18.0 (e2ab18b), línea 1250 en 19.0 (ce7f5a3) y línea 1261 en 20.0 (688d86b)
- Código del módulo: flexigo_payment_gocardless: models/payment_transaction.py, línea 278 en 17.0 (d203ee6), línea 278 en 18.0 (e2ab18b), línea 278 en 19.0 (ce7f5a3) y línea 289 en 20.0 (688d86b)
- Código del módulo: flexigo_payment_gocardless: models/payment_transaction.py, línea 281 en 17.0 (d203ee6), línea 281 en 18.0 (e2ab18b), línea 281 en 19.0 (ce7f5a3) y línea 292 en 20.0 (688d86b)
- Código del módulo: flexigo_payment_gocardless: models/payment_provider.py, línea 397 en 17.0 (d203ee6), 18.0 (e2ab18b), 19.0 (ce7f5a3) y 20.0 (688d86b)
- Código del módulo: flexigo_payment_gocardless: models/payment_provider.py, línea 462 en 17.0 (d203ee6), 18.0 (e2ab18b), 19.0 (ce7f5a3) y 20.0 (688d86b)
- Código del módulo: flexigo_payment_gocardless: i18n/es.po, línea 560 en 17.0 (d203ee6), línea 560 en 18.0 (e2ab18b), línea 560 en 19.0 (ce7f5a3) y línea 565 en 20.0 (688d86b)
- Código del módulo: flexigo_payment_gocardless: const.py, línea 117 en 17.0 (d203ee6), 18.0 (e2ab18b), 19.0 (ce7f5a3) y 20.0 (688d86b)
- Código del módulo: flexigo_payment_gocardless: models/payment_transaction.py, línea 247 en 17.0 (d203ee6), línea 247 en 18.0 (e2ab18b), línea 247 en 19.0 (ce7f5a3) y línea 258 en 20.0 (688d86b)
- github.com/odoo/odoo/blob/20.0/addons/payment/i18n/es.po
- github.com/odoo/odoo/blob/20.0/addons/account_payment/views/account_move_views.xml
- github.com/odoo/odoo/blob/17.0/odoo/http.py
- Código del módulo: flexigo_payment_gocardless: __manifest__.py, línea 31 en 17.0 (d203ee6), 18.0 (e2ab18b), 19.0 (ce7f5a3) y 20.0 (688d86b)
