From 72d3cd5dce946d1387439254d617273403818832 Mon Sep 17 00:00:00 2001 From: GitHub Copilot Date: Tue, 11 Aug 2026 12:54:34 +0200 Subject: [PATCH 1/4] =?UTF-8?q?a=C3=B1adir=20carpetas=20ocultas?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index ef4d893..7a15db1 100644 --- a/.gitignore +++ b/.gitignore @@ -132,4 +132,7 @@ dmypy.json .pyre/ tmp/ -.claude/settings.json +.claude/ +.vscode/ +.github + From fb5b3d1f7ebad5d3ea6b28b3540a51a7e977be1a Mon Sep 17 00:00:00 2001 From: GitHub Copilot Date: Tue, 11 Aug 2026 13:30:49 +0200 Subject: [PATCH 2/4] [ADD] pos_payment_method_cashdro_rounding: migration to 18.0 Migrated from the 17.0 branch (4fbf328). APIs that no longer exist in 18.0: * `order.selected_paymentline` -> `order.get_selected_paymentline()` * `ErrorPopup` + `env.services.popup` -> `AlertDialog` + `env.services.dialog` * `/** @odoo-module */`, implicit in `.esm.js` since 17.0 The rounding itself needed a different approach: `get_rounding_applied()` now reads `taxTotals.order_rounding`, only computed over payments that are already `is_done()`. The CashDro line is still `waiting` when the amount is requested, so a literal port would always have added 0. `getDefaultAmountDueToPayIn()` is the 18.0 equivalent: it applies `getRoundedRemaining()` honouring both `cash_rounding` and `only_round_cash_method`, and is what core itself uses for the default amount of a payment line. Only `_cashdro_payment_url()` is patched now, instead of duplicating the whole `cashdro_send_payment_request()`, so the request flow, the acknowledge, the polling and the error handling stay in the base module. With no cash rounding configured the patch delegates to `super` and changes nothing. Co-Authored-By: Claude Opus 5 --- .../__init__.py | 2 + .../__manifest__.py | 18 +++++++++ .../static/src/js/cashdro_rounding.esm.js | 37 +++++++++++++++++++ 3 files changed, 57 insertions(+) create mode 100644 pos_payment_method_cashdro_rounding/__init__.py create mode 100644 pos_payment_method_cashdro_rounding/__manifest__.py create mode 100644 pos_payment_method_cashdro_rounding/static/src/js/cashdro_rounding.esm.js diff --git a/pos_payment_method_cashdro_rounding/__init__.py b/pos_payment_method_cashdro_rounding/__init__.py new file mode 100644 index 0000000..9f3f569 --- /dev/null +++ b/pos_payment_method_cashdro_rounding/__init__.py @@ -0,0 +1,2 @@ +# Copyright Criptomart +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). diff --git a/pos_payment_method_cashdro_rounding/__manifest__.py b/pos_payment_method_cashdro_rounding/__manifest__.py new file mode 100644 index 0000000..a16b1e3 --- /dev/null +++ b/pos_payment_method_cashdro_rounding/__manifest__.py @@ -0,0 +1,18 @@ +{ + "name": "POS CashDro Rounding", + "version": "18.0.1.0.0", + "summary": "Apply cash/currency rounding to CashDro payment request amount.", + "category": "Point of Sale", + "license": "AGPL-3", + "author": "Criptomart", + "depends": [ + "point_of_sale", + "pos_payment_method_cashdro", + ], + "assets": { + "point_of_sale._assets_pos": [ + "pos_payment_method_cashdro_rounding/static/src/js/cashdro_rounding.esm.js", + ], + }, + "installable": True, +} diff --git a/pos_payment_method_cashdro_rounding/static/src/js/cashdro_rounding.esm.js b/pos_payment_method_cashdro_rounding/static/src/js/cashdro_rounding.esm.js new file mode 100644 index 0000000..eb01842 --- /dev/null +++ b/pos_payment_method_cashdro_rounding/static/src/js/cashdro_rounding.esm.js @@ -0,0 +1,37 @@ +/* Copyright Criptomart + License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + + Apply the PoS cash rounding to the amount requested to the CashDro, keeping + the OCA integration flow untouched. +*/ + +import { PaymentCashdro } from "@pos_payment_method_cashdro/js/payment_cashdro.esm"; +import { patch } from "@web/core/utils/patch"; + +patch(PaymentCashdro.prototype, { + /** + * @override + * The base module asks the CashDro for the plain due amount, which ignores + * the cash rounding configured in the PoS. As the drawer can only give back + * change with the coins it holds, we request the amount the customer is + * really expected to pay: the due amount with the cash rounding applied, + * which is the very same amount core defaults a payment line to. + * + * Only the url builder is patched so the rest of the payment flow of the + * base module (request, acknowledge, polling and error handling) is kept. + */ + _cashdro_payment_url(parameters) { + const order = this.pos.get_order(); + const line = order.get_selected_paymentline(); + if (!line || !order.shouldRound(line.payment_method_id)) { + return super._cashdro_payment_url(...arguments); + } + // CashDro treats decimals as positions in an integer, so we round the + // product to avoid the trailing decimals of the floating point + // computation or the drawer would reject our request. + const amount = Math.round( + order.getDefaultAmountDueToPayIn(line.payment_method_id) * 100 + ); + return super._cashdro_payment_url({ ...parameters, amount }); + }, +}); From 4615da6daee5d4994bd6e2a9fff04520e53d52bb Mon Sep 17 00:00:00 2001 From: GitHub Copilot Date: Tue, 11 Aug 2026 13:31:11 +0200 Subject: [PATCH 3/4] [ADD] pos_payment_method_cashdro_fix: 17.0 API leftovers in the OCA base module The 18.0 migration of `pos_payment_method_cashdro` (OCA/pos@6a4c251d) kept three uses of APIs removed in 18.0. The module has no tests nor tours and needs a physical drawer to be exercised, so the OCA CI can't catch them: * `_cashdro_url()` reads `order.selected_paymentline`, so `.payment_method` on the resulting `undefined` throws a TypeError on every payment, swallowed into a generic "An error occurred while connecting to the cashdro" dialog. * The `add_paymentline()` patch checks `line.payment_method`, renamed to `payment_method_id`, so the line keeps the default due amount instead of waiting for the amount the customer inserts. * `_loader_params_pos_payment_method()` is the 17.0 loading API, replaced by `_load_pos_data_fields()`. Dead code, so the CashDro credentials never reach the front end. Patched from the outside, as OCA sources are not to be modified. Written to stay harmless once fixed upstream: the Python override only adds the missing fields and the JS patches are idempotent against the fixed code. `upstream/pos_payment_method_cashdro-18.0-fixes.patch` holds the same fixes as a ready to send `git format-patch`, verified with `git apply --check`. This module is temporary and should be removed once that lands in OCA/pos. Co-Authored-By: Claude Opus 5 --- pos_payment_method_cashdro_fix/README.rst | 86 +++++++++++ pos_payment_method_cashdro_fix/__init__.py | 3 + .../__manifest__.py | 23 +++ .../models/__init__.py | 1 + .../models/pos_payment_method.py | 26 ++++ .../readme/CONTRIBUTORS.rst | 3 + .../readme/DESCRIPTION.rst | 22 +++ .../readme/ROADMAP.rst | 10 ++ .../readme/USAGE.rst | 21 +++ .../static/src/js/models_fix.esm.js | 31 ++++ .../static/src/js/payment_cashdro_fix.esm.js | 33 +++++ .../tests/__init__.py | 1 + .../tests/test_load_pos_data_fields.py | 33 +++++ ...os_payment_method_cashdro-18.0-fixes.patch | 133 ++++++++++++++++++ 14 files changed, 426 insertions(+) create mode 100644 pos_payment_method_cashdro_fix/README.rst create mode 100644 pos_payment_method_cashdro_fix/__init__.py create mode 100644 pos_payment_method_cashdro_fix/__manifest__.py create mode 100644 pos_payment_method_cashdro_fix/models/__init__.py create mode 100644 pos_payment_method_cashdro_fix/models/pos_payment_method.py create mode 100644 pos_payment_method_cashdro_fix/readme/CONTRIBUTORS.rst create mode 100644 pos_payment_method_cashdro_fix/readme/DESCRIPTION.rst create mode 100644 pos_payment_method_cashdro_fix/readme/ROADMAP.rst create mode 100644 pos_payment_method_cashdro_fix/readme/USAGE.rst create mode 100644 pos_payment_method_cashdro_fix/static/src/js/models_fix.esm.js create mode 100644 pos_payment_method_cashdro_fix/static/src/js/payment_cashdro_fix.esm.js create mode 100644 pos_payment_method_cashdro_fix/tests/__init__.py create mode 100644 pos_payment_method_cashdro_fix/tests/test_load_pos_data_fields.py create mode 100644 pos_payment_method_cashdro_fix/upstream/pos_payment_method_cashdro-18.0-fixes.patch diff --git a/pos_payment_method_cashdro_fix/README.rst b/pos_payment_method_cashdro_fix/README.rst new file mode 100644 index 0000000..9854e0a --- /dev/null +++ b/pos_payment_method_cashdro_fix/README.rst @@ -0,0 +1,86 @@ +====================== +POS CashDro 18.0 Fixes +====================== + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 + +|badge1| |badge2| + +The 18.0 migration of ``pos_payment_method_cashdro`` +(`OCA/pos@6a4c251d `_) left three +uses of the 17.0 API that stop the CashDro integration from working. The module +has no tests nor tours and needs a physical drawer to be exercised, so nothing +in the OCA CI catches them. + +This module patches the three of them from the outside, without touching the +OCA sources: + +#. ``_cashdro_url()`` reads ``order.selected_paymentline``, replaced in 18.0 by + ``order.get_selected_paymentline()``. Reading ``.payment_method`` on the + resulting ``undefined`` raises a ``TypeError`` on every payment, which the + caller swallows into a generic *"An error occurred while connecting to the + cashdro"* message. +#. The ``add_paymentline`` patch checks ``line.payment_method``, renamed to + ``line.payment_method_id`` in 18.0. The condition is never true, so the + payment line keeps the default due amount instead of waiting for the amount + the customer inserts in the drawer. +#. ``pos.session._loader_params_pos_payment_method`` is the 17.0 loading API, + replaced in 18.0 by ``_load_pos_data_fields`` on each model. The override is + dead code, so ``cashdro_host``, ``cashdro_user`` and ``cashdro_password`` + never reach the front end. + +**Table of contents** + +.. contents:: + :local: + +Usage +===== + +There is nothing to configure: installing the module is enough. + +To check the three fixes on a PoS with a CashDro terminal: + +#. 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 (fix 2). +#. The drawer must start the operation and ask for the amount, instead of the + *"An error occurred while connecting to the cashdro"* dialog (fixes 1 and 3). +#. With no CashDro at hand, the browser console tells fix 1 from fix 3 apart: + without this module the failure is a ``TypeError: Cannot read properties of + undefined (reading 'payment_method')``; with it, a network error against the + configured host. + +The Python side is covered by the tests. The base module lives outside this +repo, so the OCA sources have to be on the addons path (see +``docker-compose.override.yml``, which is local and untracked):: + + docker-compose run --rm odoo odoo -c /etc/odoo/odoo.conf \ + --addons-path=/mnt/extra-addons,/mnt/oca/pos,/usr/lib/python3/dist-packages/odoo/addons \ + -d odoo -u pos_payment_method_cashdro_fix --test-enable --stop-after-init + +Known issues / Roadmap +====================== + +This module is meant to be temporary. The fixes are proposed upstream in +``upstream/pos_payment_method_cashdro-18.0-fixes.patch``; once they are merged +in ``OCA/pos`` this module can be uninstalled and removed. + +It is written to stay harmless in the meantime: the Python override only adds +the credential fields that are missing from the loader, and the JavaScript +patches are idempotent with respect to the fixed upstream code. + +The JavaScript side can't be covered by automated tests, as it needs a CashDro +terminal answering on the network. + +Contributors +============ + +* `Criptomart `_: + + * Criptomart diff --git a/pos_payment_method_cashdro_fix/__init__.py b/pos_payment_method_cashdro_fix/__init__.py new file mode 100644 index 0000000..8f9e965 --- /dev/null +++ b/pos_payment_method_cashdro_fix/__init__.py @@ -0,0 +1,3 @@ +# Copyright 2026 - Today Criptomart +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +from . import models diff --git a/pos_payment_method_cashdro_fix/__manifest__.py b/pos_payment_method_cashdro_fix/__manifest__.py new file mode 100644 index 0000000..bbe4598 --- /dev/null +++ b/pos_payment_method_cashdro_fix/__manifest__.py @@ -0,0 +1,23 @@ +# Copyright 2026 - Today Criptomart +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +{ + "name": "POS CashDro 18.0 Fixes", + "version": "18.0.1.0.0", + "summary": "Fix the 17.0 API leftovers that break pos_payment_method_cashdro on 18.0", + "category": "Point of Sale", + "license": "AGPL-3", + "author": "Criptomart", + "maintainers": ["Criptomart"], + "website": "https://git.criptomart.net/criptomart/addons-cm", + "depends": [ + "point_of_sale", + "pos_payment_method_cashdro", + ], + "assets": { + "point_of_sale._assets_pos": [ + "pos_payment_method_cashdro_fix/static/src/js/payment_cashdro_fix.esm.js", + "pos_payment_method_cashdro_fix/static/src/js/models_fix.esm.js", + ], + }, + "installable": True, +} diff --git a/pos_payment_method_cashdro_fix/models/__init__.py b/pos_payment_method_cashdro_fix/models/__init__.py new file mode 100644 index 0000000..58690ef --- /dev/null +++ b/pos_payment_method_cashdro_fix/models/__init__.py @@ -0,0 +1 @@ +from . import pos_payment_method diff --git a/pos_payment_method_cashdro_fix/models/pos_payment_method.py b/pos_payment_method_cashdro_fix/models/pos_payment_method.py new file mode 100644 index 0000000..8ec6d8d --- /dev/null +++ b/pos_payment_method_cashdro_fix/models/pos_payment_method.py @@ -0,0 +1,26 @@ +# Copyright 2026 - Today Criptomart +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +from odoo import api +from odoo import models + +CASHDRO_FIELDS = ["cashdro_host", "cashdro_user", "cashdro_password"] + + +class PosPaymentMethod(models.Model): + _inherit = "pos.payment.method" + + @api.model + def _load_pos_data_fields(self, config_id): + """Send the CashDro credentials to the PoS front end. + + `pos_payment_method_cashdro` still declares them through + `_loader_params_pos_payment_method`, the 17.0 loading API, which 18.0 + replaced by this method. That override is dead code, so the front end + never receives the host and can't build the CashDro url. + + Only the missing fields are added, so this module stays harmless once + the base one is fixed upstream. + """ + fields = super()._load_pos_data_fields(config_id) + fields.extend(field for field in CASHDRO_FIELDS if field not in fields) + return fields diff --git a/pos_payment_method_cashdro_fix/readme/CONTRIBUTORS.rst b/pos_payment_method_cashdro_fix/readme/CONTRIBUTORS.rst new file mode 100644 index 0000000..16df929 --- /dev/null +++ b/pos_payment_method_cashdro_fix/readme/CONTRIBUTORS.rst @@ -0,0 +1,3 @@ +* `Criptomart `_: + + * Criptomart diff --git a/pos_payment_method_cashdro_fix/readme/DESCRIPTION.rst b/pos_payment_method_cashdro_fix/readme/DESCRIPTION.rst new file mode 100644 index 0000000..c5f2de1 --- /dev/null +++ b/pos_payment_method_cashdro_fix/readme/DESCRIPTION.rst @@ -0,0 +1,22 @@ +The 18.0 migration of ``pos_payment_method_cashdro`` +(`OCA/pos@6a4c251d `_) left three +uses of the 17.0 API that stop the CashDro integration from working. The module +has no tests nor tours and needs a physical drawer to be exercised, so nothing +in the OCA CI catches them. + +This module patches the three of them from the outside, without touching the +OCA sources: + +#. ``_cashdro_url()`` reads ``order.selected_paymentline``, replaced in 18.0 by + ``order.get_selected_paymentline()``. Reading ``.payment_method`` on the + resulting ``undefined`` raises a ``TypeError`` on every payment, which the + caller swallows into a generic *"An error occurred while connecting to the + cashdro"* message. +#. The ``add_paymentline`` patch checks ``line.payment_method``, renamed to + ``line.payment_method_id`` in 18.0. The condition is never true, so the + payment line keeps the default due amount instead of waiting for the amount + the customer inserts in the drawer. +#. ``pos.session._loader_params_pos_payment_method`` is the 17.0 loading API, + replaced in 18.0 by ``_load_pos_data_fields`` on each model. The override is + dead code, so ``cashdro_host``, ``cashdro_user`` and ``cashdro_password`` + never reach the front end. diff --git a/pos_payment_method_cashdro_fix/readme/ROADMAP.rst b/pos_payment_method_cashdro_fix/readme/ROADMAP.rst new file mode 100644 index 0000000..bab1608 --- /dev/null +++ b/pos_payment_method_cashdro_fix/readme/ROADMAP.rst @@ -0,0 +1,10 @@ +This module is meant to be temporary. The fixes are proposed upstream in +``upstream/pos_payment_method_cashdro-18.0-fixes.patch``; once they are merged +in ``OCA/pos`` this module can be uninstalled and removed. + +It is written to stay harmless in the meantime: the Python override only adds +the credential fields that are missing from the loader, and the JavaScript +patches are idempotent with respect to the fixed upstream code. + +The JavaScript side can't be covered by automated tests, as it needs a CashDro +terminal answering on the network. See ``USAGE`` for the manual check. diff --git a/pos_payment_method_cashdro_fix/readme/USAGE.rst b/pos_payment_method_cashdro_fix/readme/USAGE.rst new file mode 100644 index 0000000..6499224 --- /dev/null +++ b/pos_payment_method_cashdro_fix/readme/USAGE.rst @@ -0,0 +1,21 @@ +There is nothing to configure: installing the module is enough. + +To check the three fixes on a PoS with a CashDro terminal: + +#. 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 (fix 2). +#. The drawer must start the operation and ask for the amount, instead of the + *"An error occurred while connecting to the cashdro"* dialog (fixes 1 and 3). +#. With no CashDro at hand, the browser console tells fix 1 from fix 3 apart: + without this module the failure is a ``TypeError: Cannot read properties of + undefined (reading 'payment_method')``; with it, a network error against the + configured host. + +The Python side is covered by the tests. The base module lives outside this +repo, so the OCA sources have to be on the addons path (see +``docker-compose.override.yml``, which is local and untracked):: + + docker-compose run --rm odoo odoo -c /etc/odoo/odoo.conf \ + --addons-path=/mnt/extra-addons,/mnt/oca/pos,/usr/lib/python3/dist-packages/odoo/addons \ + -d odoo -u pos_payment_method_cashdro_fix --test-enable --stop-after-init diff --git a/pos_payment_method_cashdro_fix/static/src/js/models_fix.esm.js b/pos_payment_method_cashdro_fix/static/src/js/models_fix.esm.js new file mode 100644 index 0000000..51598ff --- /dev/null +++ b/pos_payment_method_cashdro_fix/static/src/js/models_fix.esm.js @@ -0,0 +1,31 @@ +/* Copyright 2026 - Today Criptomart + License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + + The `add_paymentline` patch of `pos_payment_method_cashdro` checks + `line.payment_method`, renamed to `payment_method_id` in 18.0, so the + condition is never met and the line keeps the default due amount instead of + waiting for the amount the customer actually inserts in the drawer. +*/ + +import { PosOrder } from "@point_of_sale/app/models/pos_order"; +import { patch } from "@web/core/utils/patch"; + +patch(PosOrder.prototype, { + /** + * @override + * Set the amount to 0 as it's going to be filled by the Cashdro response. + */ + add_paymentline() { + const line = super.add_paymentline(...arguments); + if (!line) { + return line; + } + if ( + line.payment_method_id?.use_payment_terminal === "cashdro" && + line.amount > 0 // For refund transactions we need to keep the amount + ) { + line.set_amount(0); + } + return line; + }, +}); diff --git a/pos_payment_method_cashdro_fix/static/src/js/payment_cashdro_fix.esm.js b/pos_payment_method_cashdro_fix/static/src/js/payment_cashdro_fix.esm.js new file mode 100644 index 0000000..3410747 --- /dev/null +++ b/pos_payment_method_cashdro_fix/static/src/js/payment_cashdro_fix.esm.js @@ -0,0 +1,33 @@ +/* Copyright 2026 - Today Criptomart + License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + + `_cashdro_url` was left with the 17.0 API in the 18.0 migration of + `pos_payment_method_cashdro`: `order.selected_paymentline` no longer exists, + so reading `.payment_method` on it throws a TypeError that the caller + swallows as a generic connection error. Rewritten with the 18.0 accessors. +*/ + +import { PaymentCashdro } from "@pos_payment_method_cashdro/js/payment_cashdro.esm"; +import { patch } from "@web/core/utils/patch"; + +patch(PaymentCashdro.prototype, { + /** + * @override + * The whole body has to be replaced: the very first statement is the one + * that breaks, so there is nothing left to delegate to `super`. + */ + _cashdro_url() { + // Cashdro machines don't support safe POST calls, so we're sending + // all the data quite unsafely constantly... + const order = this.pos.get_order(); + const method = order.get_selected_paymentline()?.payment_method_id; + const host = method && method.cashdro_host; + if (!host) { + return false; + } + let url = `${host}/Cashdro3WS/index.php`; + url += `?name=${method.cashdro_user}`; + url += `&password=${method.cashdro_password}`; + return url; + }, +}); diff --git a/pos_payment_method_cashdro_fix/tests/__init__.py b/pos_payment_method_cashdro_fix/tests/__init__.py new file mode 100644 index 0000000..02c4d2e --- /dev/null +++ b/pos_payment_method_cashdro_fix/tests/__init__.py @@ -0,0 +1 @@ +from . import test_load_pos_data_fields diff --git a/pos_payment_method_cashdro_fix/tests/test_load_pos_data_fields.py b/pos_payment_method_cashdro_fix/tests/test_load_pos_data_fields.py new file mode 100644 index 0000000..ebee5e4 --- /dev/null +++ b/pos_payment_method_cashdro_fix/tests/test_load_pos_data_fields.py @@ -0,0 +1,33 @@ +# Copyright 2026 - Today Criptomart +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo.tests import tagged +from odoo.tests.common import TransactionCase + +from ..models.pos_payment_method import CASHDRO_FIELDS + + +@tagged("post_install", "-at_install") +class TestLoadPosDataFields(TransactionCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.payment_method = cls.env["pos.payment.method"] + # Nothing dereferences it, but we pass a real config when there's one + cls.config_id = cls.env["pos.config"].search([], limit=1).id + + def test_cashdro_credentials_are_loaded(self): + """The front end can't build the CashDro url without them.""" + fields = self.payment_method._load_pos_data_fields(self.config_id) + for field in CASHDRO_FIELDS: + self.assertIn(field, fields) + + def test_no_duplicated_fields(self): + """Once the base module is fixed upstream we must not add them twice.""" + fields = self.payment_method._load_pos_data_fields(self.config_id) + self.assertEqual(sorted(fields), sorted(set(fields))) + + def test_fields_exist_on_the_model(self): + """Guard against a rename of the credentials in the base module.""" + for field in CASHDRO_FIELDS: + self.assertIn(field, self.payment_method._fields) diff --git a/pos_payment_method_cashdro_fix/upstream/pos_payment_method_cashdro-18.0-fixes.patch b/pos_payment_method_cashdro_fix/upstream/pos_payment_method_cashdro-18.0-fixes.patch new file mode 100644 index 0000000..84ca58f --- /dev/null +++ b/pos_payment_method_cashdro_fix/upstream/pos_payment_method_cashdro-18.0-fixes.patch @@ -0,0 +1,133 @@ +From 11c65e8000282b9a761346f1fbff16e09581fc17 Mon Sep 17 00:00:00 2001 +From: Criptomart +Date: Tue, 11 Aug 2026 13:21:28 +0200 +Subject: [PATCH] [FIX] pos_payment_method_cashdro: leftovers of the 17.0 API + +The 18.0 migration kept three uses of APIs that no longer exist, and the +module has neither tests nor tours (it needs a physical drawer), so the CI +can't catch them. + +* `_cashdro_url()` reads `order.selected_paymentline`, replaced by + `order.get_selected_paymentline()` in 18.0. Reading `.payment_method` on + the resulting `undefined` throws a TypeError on every payment, which + `cashdro_send_payment_request()` swallows into a generic "An error occurred + while connecting to the cashdro" dialog. + +* The `add_paymentline()` patch checks `line.payment_method`, renamed to + `line.payment_method_id` in 18.0, so the payment line is never zeroed and + keeps the default due amount instead of the amount the customer inserts. + +* `_loader_params_pos_payment_method()` is the 17.0 loading API, replaced in + 18.0 by `_load_pos_data_fields()` on each model. The override is dead code + and the CashDro credentials never reach the front end, so `_cashdro_url()` + has no host to build the url with. +--- + pos_payment_method_cashdro/__manifest__.py | 2 +- + pos_payment_method_cashdro/models/__init__.py | 1 - + .../models/pos_payment_method.py | 11 ++++++++++- + pos_payment_method_cashdro/models/pos_session.py | 14 -------------- + .../static/src/js/models.esm.js | 4 ++-- + .../static/src/js/payment_cashdro.esm.js | 3 ++- + 6 files changed, 15 insertions(+), 20 deletions(-) + delete mode 100644 pos_payment_method_cashdro/models/pos_session.py + +diff --git a/pos_payment_method_cashdro/__manifest__.py b/pos_payment_method_cashdro/__manifest__.py +index 708aac5..c19a642 100644 +--- a/pos_payment_method_cashdro/__manifest__.py ++++ b/pos_payment_method_cashdro/__manifest__.py +@@ -3,7 +3,7 @@ + { + "name": "PoS Payment Method CashDro", + "summary": "Allows to pay with CashDro Terminals on the Point of Sale", +- "version": "18.0.1.0.2", ++ "version": "18.0.1.0.3", + "category": "Point Of Sale", + "website": "https://github.com/OCA/pos", + "author": "Tecnativa, Odoo Community Association (OCA)", +diff --git a/pos_payment_method_cashdro/models/__init__.py b/pos_payment_method_cashdro/models/__init__.py +index 604d90c..58690ef 100644 +--- a/pos_payment_method_cashdro/models/__init__.py ++++ b/pos_payment_method_cashdro/models/__init__.py +@@ -1,2 +1 @@ + from . import pos_payment_method +-from . import pos_session +diff --git a/pos_payment_method_cashdro/models/pos_payment_method.py b/pos_payment_method_cashdro/models/pos_payment_method.py +index 285984a..08a64a1 100644 +--- a/pos_payment_method_cashdro/models/pos_payment_method.py ++++ b/pos_payment_method_cashdro/models/pos_payment_method.py +@@ -1,6 +1,6 @@ + # Copyright 2021 Tecnativa - David Vidal + # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +-from odoo import fields, models ++from odoo import api, fields, models + + + class PosPaymentMethod(models.Model): +@@ -16,6 +16,15 @@ class PosPaymentMethod(models.Model): + cashdro_user = fields.Char() + cashdro_password = fields.Char() + ++ @api.model ++ def _load_pos_data_fields(self, config_id): ++ """The front end needs the credentials to build the CashDro url""" ++ return super()._load_pos_data_fields(config_id) + [ ++ "cashdro_host", ++ "cashdro_user", ++ "cashdro_password", ++ ] ++ + def _onchange_journal_id(self): + """Cash payment method force the `use_payment_terminal` to `False` as + it's assumed that a cash journal can't have a payment terminal. Let's keep +diff --git a/pos_payment_method_cashdro/models/pos_session.py b/pos_payment_method_cashdro/models/pos_session.py +deleted file mode 100644 +index 6123090..0000000 +--- a/pos_payment_method_cashdro/models/pos_session.py ++++ /dev/null +@@ -1,14 +0,0 @@ +-# Copyright 2024 Tecnativa - David Vidal +-# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +-from odoo import models +- +- +-class PosSession(models.Model): +- _inherit = "pos.session" +- +- def _loader_params_pos_payment_method(self): +- result = super()._loader_params_pos_payment_method() +- result["search_params"]["fields"].extend( +- ["cashdro_host", "cashdro_user", "cashdro_password"] +- ) +- return result +diff --git a/pos_payment_method_cashdro/static/src/js/models.esm.js b/pos_payment_method_cashdro/static/src/js/models.esm.js +index d228f08..d1ee2f7 100644 +--- a/pos_payment_method_cashdro/static/src/js/models.esm.js ++++ b/pos_payment_method_cashdro/static/src/js/models.esm.js +@@ -22,8 +22,8 @@ patch(PosOrder.prototype, { + return line; + } + if ( +- line.payment_method && +- line.payment_method.use_payment_terminal === "cashdro" && ++ line.payment_method_id && ++ line.payment_method_id.use_payment_terminal === "cashdro" && + line.amount > 0 // For refund transactions we need to keep the amount + ) { + line.set_amount(0); +diff --git a/pos_payment_method_cashdro/static/src/js/payment_cashdro.esm.js b/pos_payment_method_cashdro/static/src/js/payment_cashdro.esm.js +index 0c0bdf2..2c618bf 100644 +--- a/pos_payment_method_cashdro/static/src/js/payment_cashdro.esm.js ++++ b/pos_payment_method_cashdro/static/src/js/payment_cashdro.esm.js +@@ -107,7 +107,8 @@ export class PaymentCashdro extends PaymentInterface { + _cashdro_url() { + // Cashdro machines don't support safe POST calls, so we're sending + // all the data quite unsafely constantly... +- const method = this.pos.get_order().selected_paymentline.payment_method; ++ const order = this.pos.get_order(); ++ const method = order.get_selected_paymentline()?.payment_method_id; + const host = method && method.cashdro_host; + if (!host) { + return false; +-- +2.43.0 + From 2b1cabbb4359a864220046cfc8fb6282666a45a3 Mon Sep 17 00:00:00 2001 From: GitHub Copilot Date: Tue, 11 Aug 2026 13:32:36 +0200 Subject: [PATCH 4/4] [REM] CLAUDE.md: untrack it, ignored like the rest of the agent config Joins `.claude/`, `.vscode/` and `.github` in the .gitignore. The file stays on disk, only out of version control, so its contents (including the path to the OCB and OCA sources) are now local to each machine. Co-Authored-By: Claude Opus 5 --- .gitignore | 2 +- CLAUDE.md | 91 ------------------------------------------------------ 2 files changed, 1 insertion(+), 92 deletions(-) delete mode 100644 CLAUDE.md diff --git a/.gitignore b/.gitignore index 7a15db1..7db909f 100644 --- a/.gitignore +++ b/.gitignore @@ -135,4 +135,4 @@ tmp/ .claude/ .vscode/ .github - +CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md deleted file mode 100644 index b49667d..0000000 --- a/CLAUDE.md +++ /dev/null @@ -1,91 +0,0 @@ -# Kidekoop — Odoo 18.0 Custom Addons - -Odoo 18.0 (OCB community) addons repo. Code in **English**. - -## ⚠️ Critical rules (non-negotiable) - -- **DO NOT modify** the OCB core (`ocb/`) nor these original OCA addons (reference/inheritance only): - `product_main_seller`, `account_invoice_triple_discount`, `product_get_price_helper`, - `product_price_category`, `purchase_triple_discount`, `base_bank_from_iban`, `l10n_es_partner`. - All changes go in our own custom addons. -- **Do NOT use `_()` in field definitions** (triggers import-time warnings). Only in methods/executable code. -- **Business logic ALWAYS on `product.product`** (variants), never on `product.template` (use `related` there). - Avoids issues with pricelists and reports that operate at the variant level. -- **No logic in QWeb**: prepare all data in the Python controller; templates only do simple attribute access. -- **No business logic in JavaScript**: UI/events only. -- Translations: edit `.po` files with `polib` (append). **`msgmerge` corrupts the files** — do not use it. - -## Stack - -Odoo 18.0 · Python 3.10+ · PostgreSQL · Docker Compose · XML/QWeb/JS. -Formatting: `black` (line 88) + `isort` (black profile) + `flake8` + `pylint-odoo`. Pre-commit active. - -## Commands - -```bash -docker-compose up -d # env (8070=web, 8073=longpolling) -docker-compose run odoo odoo -d odoo --test-enable --stop-after-init -u # tests (run, NOT exec: avoids cache) -docker-compose exec odoo odoo -d odoo -u --stop-after-init # update addon -docker-compose logs -f odoo # logs -docker-compose exec db psql -U odoo -d odoo # postgres -make lint | make format | make check-format | make flake8 | make pylint-required -pre-commit run --all-files -``` - -## Odoo conventions - -- Models `snake.case` · classes `PascalCase` · files `snake_case.py` · XML IDs `module.name`. -- Manifest always `__manifest__.py`, version `18.0.X.Y.Z`, `depends` alphabetically ordered. -- Views: 4 spaces, explicit `position` in XPath, groups via `module.xml_id`, `sequence` for ordering. -- Bulk: prefer `search().write()` over loops; `create([vals, ...])` for bulk create. -- Notifications: `ir.actions.client` + `display_notification`. -- Detailed logging in price/discount computations: `_logger.info("[PRICE] ...", ...)`. - -## Custom addons - -Pricing & products: - -- `product_sale_price_from_pricelist` — auto-computes sale price from last purchase price + pricelist. - Requires taxes on the product and `last_purchase_price_compute_type != "manual_update"`. - Also applies supplier discounts from `supplierinfo`. -- `product_pricelist_total_margin` — total margin computed additively (Markup or Commercial Margin), with global limits. -- `product_price_category_supplier` — price categories per supplier. -- `product_origin_char` — free-text origin field per product (template-based). -- `account_invoice_triple_discount_readonly` — fix for triple-discount accumulation bug (always use it). - -Sales & website: - -- `website_sale_aplicoop` — Eskaera: collaborative purchasing for consumer co-ops (group orders, - per-member carts, cutoff/pickup dates, lazy loading, multi-language). -- `website_sale_disable_cart` — turns `/shop` into a read-only catalog: hides the cart UI and - redirects the standard `/shop/cart*` routes to a configurable URL (default `/shop`). -- `portal_event_registration` — portal users view their event registrations + upload attachments to chatter. - -Membership: - -- `membership_monthly_invoicing` — auto-creates a monthly membership invoice per active member (cron-driven). -- `membership_expiry_reminder` — automated renewal-reminder emails near expiry, with online renew link. - -Logistics & accounting: - -- `stock_picking_batch_custom` — batch picking extras: extra detailed-op columns, ordering by - category/product/partner, and a full-screen operator (Basket Assembly) view. -- `account_banking_mandate_batch` — contextual action to bulk-create/validate SEPA mandates for selected partners. -- `l10n_es_edi_tbai_reagyp_recibidas` — TicketBAI fix: REAGYP vendor-bill regime key 19 → 02. - -## Documentation - -- Per-addon details: its `README.rst` (OCA) or `README_DEV.md` (technical). -- Global patterns: `.github/copilot-instructions.md` (extended version of this file). -- Guides: `docs/QWEB_BEST_PRACTICES.md`, `docs/OCA_DOCUMENTATION.md`, `docs/LAZY_LOADING.md`. -- OCA `readme/` structure (DESCRIPTION, INSTALL, CONFIGURE, USAGE, CONTRIBUTORS, CREDITS). - Credits: Criptomart (author). - -## Commits - -`[TAG] module: description` — tags: `[ADD] [FIX] [IMP] [REF] [REM] [I18N] [DOC]`. - -## Available skills - -Per-language skills (`odoo-python`, `odoo-xml-views`, `odoo-qweb-html`, `odoo-javascript`) and the -OpenSpec workflow (`openspec-explore/propose/apply-change/archive-change`, `/opsx:*` commands) live in `.claude/`.