[ADD] pos_payment_method_cashdro_flow_fix: fix the CashDro payment flow on 18.0

`_cashdro_payment_url()` builds the startOperation url with
`this.pos.pos_session.name`. 18.0 replaced that accessor by the `session`
getter of PosStore, so reading `.name` on the resulting `undefined` raises a
TypeError on every single payment, before any request leaves the browser.
`cashdro_send_payment_request` catches it with a bare `catch` that neither
logs nor rethrows and shows the generic "error connecting to the cashdro",
which is why the failure looked like a problem with the machine.

`pos_payment_method_cashdro_fix` only covers the data loading, so this goes
in a module of its own: it has a longer life than that temporary patch, and
it supersedes its `_cashdro_url()` override.

Along with the blocking one, the flow gets:

* the real error logged and shown in the dialog, so a wrong host, a busy
  drawer and a dead network stop being the same sentence,
* a missing host raised instead of the boolean `false` travelling into
  `fetch`, where it resolves against the Odoo server,
* `finishOperation` always sent on failure, or the drawer keeps the operation
  open and refuses every later payment of the session,
* polling on a 700ms interval with a 5 minute deadline, stopped by a cancel
  or by leaving the payment screen, instead of a tight unbounded loop,
* `send_payment_cancel()` returning whether the drawer took it, so the line
  no longer sticks in `waitingCard`,
* reversals sending the amount of the line negated: `get_due()` only
  discounts the payments already done, so the base module asked the drawer to
  collect the money a second time instead of dispensing it,
* the `uuid` of the line honoured instead of the selected one,
* the CashDro answers validated (HTTP status, JSON body, operation id).

`_cashdro_amount()` is split out as the single hook for the amount, which
`pos_payment_method_cashdro_rounding` uses.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
GitHub Copilot 2026-08-31 17:43:25 +02:00
parent 40c92613d9
commit 7ae10abda8
Signed by: snt
GPG key ID: A9FD34930EADBE71
8 changed files with 675 additions and 0 deletions

View file

@ -0,0 +1,53 @@
There is nothing to configure: installing the module is enough.
Before anything else, check the payment method
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
18.0 added the ``payment_method_type`` field (*Integration*) to
``pos.payment.method``, and core clears ``use_payment_terminal`` whenever it is
saved as *None required*. On **Point of Sale ‣ Configuration ‣ Payment
Methods**, the CashDro method must have:
* **Integration** = *Terminal*
* **Integrate with** = *Cashdro*
* the terminal host, user and password filled in
With *Integration* left at *None required* the terminal is not wired at all:
clicking the payment method just adds a plain cash line, and nothing is ever
sent to the drawer — no dialog, no error, no traffic.
On site
~~~~~~~
#. Open a PoS session, add a product and go to the payment screen.
#. Select the CashDro payment method. The payment line must show **0**, not the
due amount (that one comes from ``pos_payment_method_cashdro_fix``).
#. The drawer must start the operation and ask for the amount.
If it still fails, the dialog now carries the reason instead of the generic
sentence, and the browser console has the full error under ``[CASHDRO]``. What
to expect:
``The CashDro payment method '...' has no terminal host configured.``
The credentials did not reach the front end. Either the fields are empty on
the payment method, or ``pos_payment_method_cashdro_fix`` is not installed.
``TypeError: Failed to fetch`` / ``NetworkError``
The browser cannot reach ``cashdro_host``. Check the host and that the till
is on the same network as the drawer. A PoS served over HTTPS also blocks a
plain ``http://`` drawer as mixed content, which shows up here.
``The CashDro answered 401/403/500 ...``
The drawer is reachable and answering: wrong user or password, or the
CashDro3WS service is failing.
``The CashDro did not return an operation id: ...``
The drawer refused ``startOperation``. Its own envelope is in the message —
usually a busy drawer with an operation still open from a previous failure.
``The CashDro did not finish the operation in time.``
``startOperation`` was accepted but the drawer never reached the finished
state within five minutes.
There are no automated tests: the flow needs a CashDro terminal answering on the
network, which is also why none of this is caught by the OCA CI.