diff --git a/README.md b/README.md index ac2391b1ff..593de361ab 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,7 @@ addon | version | maintainers | summary [pos_margin](pos_margin/) | 18.0.1.0.0 | legalsylvain | Margin on PoS Order [pos_order_remove_line](pos_order_remove_line/) | 18.0.1.0.0 | robyf70 | Add button to remove POS order line. [pos_order_to_sale_order](pos_order_to_sale_order/) | 18.0.1.0.0 | legalsylvain | PoS Order To Sale Order +[pos_payment_method_cashdro](pos_payment_method_cashdro/) | 18.0.1.0.1 | | Allows to pay with CashDro Terminals on the Point of Sale [pos_product_display_default_code](pos_product_display_default_code/) | 18.0.1.0.0 | | pos: display product default code before product name [pos_product_multi_barcode](pos_product_multi_barcode/) | 18.0.1.0.0 | | Make product multi barcodes usable in the point of sale [pos_report_session_summary](pos_report_session_summary/) | 18.0.1.0.0 | | Adds a Session Summary PDF report on the POS session diff --git a/pos_payment_method_cashdro/README.rst b/pos_payment_method_cashdro/README.rst new file mode 100644 index 0000000000..f301b4a165 --- /dev/null +++ b/pos_payment_method_cashdro/README.rst @@ -0,0 +1,133 @@ +.. image:: https://odoo-community.org/readme-banner-image + :target: https://odoo-community.org/get-involved?utm_source=readme + :alt: Odoo Community Association + +========================== +PoS Payment Method CashDro +========================== + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:f15a0167b57fe8cf8a3cb61c33b1f9731c54ab8f613e8ccc572773550c949c32 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |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/license-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fpos-lightgray.png?logo=github + :target: https://github.com/OCA/pos/tree/18.0/pos_payment_method_cashdro + :alt: OCA/pos +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/pos-18-0/pos-18-0-pos_payment_method_cashdro + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png + :target: https://runboat.odoo-community.org/builds?repo=OCA/pos&target_branch=18.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module allows to make payments with a Cashdro +(https://www.cashdro.com) terminal on the Point of Sale frontend. + +**Table of contents** + +.. contents:: + :local: + +Configuration +============= + +To add a Cashdro payment terminal: + +1. Go to *Point of Sale > Configuration > Payment Methods* +2. Choose a cash payment method or create a new one. +3. Select *Cashdro* in the *Use a Payment Terminal* field. +4. Configure the Cashdro terminal hostname and credentials. +5. Configure the desired, Cashdro terminal in the proper PoS + configurations. + +Note that if a single payment method was used for cash in different +stores, it should be splitted in as many phisical stores there are. + +Usage +===== + +With the proper configuration made: + +1. Make a new PoS order and choose the cash payment method configured + with the Cashdro settings. +2. Click on *Send* to send the request to the Cashdro terminal that will + ask the customer for the amount to pay. +3. The cashier can cancel the amount request discarding the line + clicking on the (x) symbol. +4. When the customer pays the sale amount in the terminal, the Cashdro + reports the amount received and change delivered back. +5. The Point of Sale reflects it in the payment line and thus the order + can be validated now. + +Known issues / Roadmap +====================== + +- Integrate cash control (money inputs / outputs). +- This module should be evaluated during the migration to 19.0, since + Odoo has integrated similar functionality into the core (pos_cashdro + addon). It may no longer be necessary to maintain this module + separately, and deprecation or consolidation should be considered. + https://github.com/odoo/odoo/tree/19.0/addons/pos_cashdro + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +------- + +* Tecnativa + +Contributors +------------ + +- `Acysos S.L. `__: + + - Ignacio Ibeas + +- `Tecnativa `__ + + - David Vidal + - Eduardo Ezerouali + +- `ACSONE SA/NV `__: + + - Bejaoui Souheil + +Maintainers +----------- + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +This module is part of the `OCA/pos `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/pos_payment_method_cashdro/__init__.py b/pos_payment_method_cashdro/__init__.py new file mode 100644 index 0000000000..0650744f6b --- /dev/null +++ b/pos_payment_method_cashdro/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/pos_payment_method_cashdro/__manifest__.py b/pos_payment_method_cashdro/__manifest__.py new file mode 100644 index 0000000000..f88c3d88df --- /dev/null +++ b/pos_payment_method_cashdro/__manifest__.py @@ -0,0 +1,20 @@ +# Copyright 2021 Tecnativa - David Vidal +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +{ + "name": "PoS Payment Method CashDro", + "summary": "Allows to pay with CashDro Terminals on the Point of Sale", + "version": "18.0.1.0.1", + "category": "Point Of Sale", + "website": "https://github.com/OCA/pos", + "author": "Tecnativa, Odoo Community Association (OCA)", + "license": "AGPL-3", + "depends": [ + "point_of_sale", + ], + "data": [ + "views/pos_payment_method_views.xml", + ], + "assets": { + "point_of_sale._assets_pos": ["pos_payment_method_cashdro/static/src/**/*"], + }, +} diff --git a/pos_payment_method_cashdro/i18n/it.po b/pos_payment_method_cashdro/i18n/it.po new file mode 100644 index 0000000000..8f13d7c8b2 --- /dev/null +++ b/pos_payment_method_cashdro/i18n/it.po @@ -0,0 +1,56 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * pos_payment_method_cashdro +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 14.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2024-03-05 14:40+0000\n" +"Last-Translator: mymage \n" +"Language-Team: none\n" +"Language: it\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.17\n" + +#. module: pos_payment_method_cashdro +#: model:ir.model.fields,field_description:pos_payment_method_cashdro.field_pos_payment_method__cashdro_password +msgid "Cashdro Password" +msgstr "Password Cashdro" + +#. module: pos_payment_method_cashdro +#: model:ir.model.fields,field_description:pos_payment_method_cashdro.field_pos_payment_method__cashdro_host +msgid "Cashdro Terminal Host Name or IP address" +msgstr "Nome host terminale Cashdro o indirizzo IP" + +#. module: pos_payment_method_cashdro +#: model:ir.model.fields,field_description:pos_payment_method_cashdro.field_pos_payment_method__cashdro_user +msgid "Cashdro User" +msgstr "Utente Cashdro" + +#. module: pos_payment_method_cashdro +#: model:ir.model.fields,help:pos_payment_method_cashdro.field_pos_payment_method__cashdro_host +msgid "It must be reachable by the PoS in the store" +msgstr "Deve essere raggiungibile dal POS nel negozio" + +#. module: pos_payment_method_cashdro +#: model:ir.model,name:pos_payment_method_cashdro.model_pos_payment_method +msgid "Point of Sale Payment Methods" +msgstr "Metodi di pagamento punto vendita" + +#. module: pos_payment_method_cashdro +#: model:ir.model,name:pos_payment_method_cashdro.model_pos_session +msgid "Point of Sale Session" +msgstr "Sessione punto vendita" + +#~ msgid "Display Name" +#~ msgstr "Nome visualizzato" + +#~ msgid "ID" +#~ msgstr "ID" + +#~ msgid "Last Modified on" +#~ msgstr "Ultima modifica il" diff --git a/pos_payment_method_cashdro/i18n/pos_payment_method_cashdro.pot b/pos_payment_method_cashdro/i18n/pos_payment_method_cashdro.pot new file mode 100644 index 0000000000..9ddad47842 --- /dev/null +++ b/pos_payment_method_cashdro/i18n/pos_payment_method_cashdro.pot @@ -0,0 +1,56 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * pos_payment_method_cashdro +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 18.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: pos_payment_method_cashdro +#. odoo-javascript +#: code:addons/pos_payment_method_cashdro/static/src/js/payment_cashdro.esm.js:0 +msgid "An error occurred while connecting to the cashdro." +msgstr "" + +#. module: pos_payment_method_cashdro +#: model:ir.model.fields,field_description:pos_payment_method_cashdro.field_pos_payment_method__cashdro_password +msgid "Cashdro Password" +msgstr "" + +#. module: pos_payment_method_cashdro +#: model:ir.model.fields,field_description:pos_payment_method_cashdro.field_pos_payment_method__cashdro_host +msgid "Cashdro Terminal Host Name or IP address" +msgstr "" + +#. module: pos_payment_method_cashdro +#: model:ir.model.fields,field_description:pos_payment_method_cashdro.field_pos_payment_method__cashdro_user +msgid "Cashdro User" +msgstr "" + +#. module: pos_payment_method_cashdro +#. odoo-javascript +#: code:addons/pos_payment_method_cashdro/static/src/js/payment_cashdro.esm.js:0 +msgid "Error" +msgstr "" + +#. module: pos_payment_method_cashdro +#: model:ir.model.fields,help:pos_payment_method_cashdro.field_pos_payment_method__cashdro_host +msgid "It must be reachable by the PoS in the store" +msgstr "" + +#. module: pos_payment_method_cashdro +#: model:ir.model,name:pos_payment_method_cashdro.model_pos_payment_method +msgid "Point of Sale Payment Methods" +msgstr "" + +#. module: pos_payment_method_cashdro +#: model:ir.model,name:pos_payment_method_cashdro.model_pos_session +msgid "Point of Sale Session" +msgstr "" diff --git a/pos_payment_method_cashdro/models/__init__.py b/pos_payment_method_cashdro/models/__init__.py new file mode 100644 index 0000000000..604d90cb18 --- /dev/null +++ b/pos_payment_method_cashdro/models/__init__.py @@ -0,0 +1,2 @@ +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 new file mode 100644 index 0000000000..285984a90f --- /dev/null +++ b/pos_payment_method_cashdro/models/pos_payment_method.py @@ -0,0 +1,35 @@ +# Copyright 2021 Tecnativa - David Vidal +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +from odoo import fields, models + + +class PosPaymentMethod(models.Model): + _inherit = "pos.payment.method" + + def _get_payment_terminal_selection(self): + return super()._get_payment_terminal_selection() + [("cashdro", "Cashdro")] + + cashdro_host = fields.Char( + string="Cashdro Terminal Host Name or IP address", + help="It must be reachable by the PoS in the store", + ) + cashdro_user = fields.Char() + cashdro_password = fields.Char() + + 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 + the method when it's needed""" + res = super()._onchange_journal_id() + if self.use_payment_terminal != "cashdro" and not self.is_cash_count: + return res + self.use_payment_terminal = "cashdro" + + def _compute_hide_use_payment_terminal(self): + """Now that we have the option to choose a payment terminal for the cashdro + payments, we can show the terminal options for cash payment types.""" + cash_payment_types = self.filtered(lambda x: x.type == "cash") + cash_payment_types.hide_use_payment_terminal = False + return super( + PosPaymentMethod, self - cash_payment_types + )._compute_hide_use_payment_terminal() diff --git a/pos_payment_method_cashdro/models/pos_session.py b/pos_payment_method_cashdro/models/pos_session.py new file mode 100644 index 0000000000..6123090956 --- /dev/null +++ b/pos_payment_method_cashdro/models/pos_session.py @@ -0,0 +1,14 @@ +# 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/pyproject.toml b/pos_payment_method_cashdro/pyproject.toml new file mode 100644 index 0000000000..4231d0cccb --- /dev/null +++ b/pos_payment_method_cashdro/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/pos_payment_method_cashdro/readme/CONFIGURE.md b/pos_payment_method_cashdro/readme/CONFIGURE.md new file mode 100644 index 0000000000..6cb370544e --- /dev/null +++ b/pos_payment_method_cashdro/readme/CONFIGURE.md @@ -0,0 +1,11 @@ +To add a Cashdro payment terminal: + +1. Go to *Point of Sale \> Configuration \> Payment Methods* +2. Choose a cash payment method or create a new one. +3. Select *Cashdro* in the *Use a Payment Terminal* field. +4. Configure the Cashdro terminal hostname and credentials. +5. Configure the desired, Cashdro terminal in the proper PoS + configurations. + +Note that if a single payment method was used for cash in different +stores, it should be splitted in as many phisical stores there are. diff --git a/pos_payment_method_cashdro/readme/CONTRIBUTORS.md b/pos_payment_method_cashdro/readme/CONTRIBUTORS.md new file mode 100644 index 0000000000..76bab88ddf --- /dev/null +++ b/pos_payment_method_cashdro/readme/CONTRIBUTORS.md @@ -0,0 +1,7 @@ +- [Acysos S.L.](https://www.acysos.com): + - Ignacio Ibeas +- [Tecnativa](https://www.tecnativa.com) + - David Vidal + - Eduardo Ezerouali +- [ACSONE SA/NV](https://acsone.eu): + - Bejaoui Souheil \ No newline at end of file diff --git a/pos_payment_method_cashdro/readme/DESCRIPTION.md b/pos_payment_method_cashdro/readme/DESCRIPTION.md new file mode 100644 index 0000000000..6596ffcd35 --- /dev/null +++ b/pos_payment_method_cashdro/readme/DESCRIPTION.md @@ -0,0 +1,2 @@ +This module allows to make payments with a Cashdro +() terminal on the Point of Sale frontend. diff --git a/pos_payment_method_cashdro/readme/ROADMAP.md b/pos_payment_method_cashdro/readme/ROADMAP.md new file mode 100644 index 0000000000..431dd1f876 --- /dev/null +++ b/pos_payment_method_cashdro/readme/ROADMAP.md @@ -0,0 +1,2 @@ +- Integrate cash control (money inputs / outputs). +- This module should be evaluated during the migration to 19.0, since Odoo has integrated similar functionality into the core (pos_cashdro addon). It may no longer be necessary to maintain this module separately, and deprecation or consolidation should be considered. https://github.com/odoo/odoo/tree/19.0/addons/pos_cashdro \ No newline at end of file diff --git a/pos_payment_method_cashdro/readme/USAGE.md b/pos_payment_method_cashdro/readme/USAGE.md new file mode 100644 index 0000000000..76b794c3ed --- /dev/null +++ b/pos_payment_method_cashdro/readme/USAGE.md @@ -0,0 +1,12 @@ +With the proper configuration made: + +1. Make a new PoS order and choose the cash payment method configured + with the Cashdro settings. +2. Click on *Send* to send the request to the Cashdro terminal that + will ask the customer for the amount to pay. +3. The cashier can cancel the amount request discarding the line + clicking on the (x) symbol. +4. When the customer pays the sale amount in the terminal, the Cashdro + reports the amount received and change delivered back. +5. The Point of Sale reflects it in the payment line and thus the order + can be validated now. diff --git a/pos_payment_method_cashdro/static/description/icon.png b/pos_payment_method_cashdro/static/description/icon.png new file mode 100644 index 0000000000..3a0328b516 Binary files /dev/null and b/pos_payment_method_cashdro/static/description/icon.png differ diff --git a/pos_payment_method_cashdro/static/description/index.html b/pos_payment_method_cashdro/static/description/index.html new file mode 100644 index 0000000000..170144b035 --- /dev/null +++ b/pos_payment_method_cashdro/static/description/index.html @@ -0,0 +1,486 @@ + + + + + +README.rst + + + +
+ + + +Odoo Community Association + +
+

PoS Payment Method CashDro

+ +

Beta License: AGPL-3 OCA/pos Translate me on Weblate Try me on Runboat

+

This module allows to make payments with a Cashdro +(https://www.cashdro.com) terminal on the Point of Sale frontend.

+

Table of contents

+ +
+

Configuration

+

To add a Cashdro payment terminal:

+
    +
  1. Go to Point of Sale > Configuration > Payment Methods
  2. +
  3. Choose a cash payment method or create a new one.
  4. +
  5. Select Cashdro in the Use a Payment Terminal field.
  6. +
  7. Configure the Cashdro terminal hostname and credentials.
  8. +
  9. Configure the desired, Cashdro terminal in the proper PoS +configurations.
  10. +
+

Note that if a single payment method was used for cash in different +stores, it should be splitted in as many phisical stores there are.

+
+
+

Usage

+

With the proper configuration made:

+
    +
  1. Make a new PoS order and choose the cash payment method configured +with the Cashdro settings.
  2. +
  3. Click on Send to send the request to the Cashdro terminal that will +ask the customer for the amount to pay.
  4. +
  5. The cashier can cancel the amount request discarding the line +clicking on the (x) symbol.
  6. +
  7. When the customer pays the sale amount in the terminal, the Cashdro +reports the amount received and change delivered back.
  8. +
  9. The Point of Sale reflects it in the payment line and thus the order +can be validated now.
  10. +
+
+
+

Known issues / Roadmap

+
    +
  • Integrate cash control (money inputs / outputs).
  • +
  • This module should be evaluated during the migration to 19.0, since +Odoo has integrated similar functionality into the core (pos_cashdro +addon). It may no longer be necessary to maintain this module +separately, and deprecation or consolidation should be considered. +https://github.com/odoo/odoo/tree/19.0/addons/pos_cashdro
  • +
+
+
+

Bug Tracker

+

Bugs are tracked on GitHub Issues. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +feedback.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Authors

+
    +
  • Tecnativa
  • +
+
+
+

Contributors

+ +
+
+

Maintainers

+

This module is maintained by the OCA.

+ +Odoo Community Association + +

OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use.

+

This module is part of the OCA/pos project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+
+ + diff --git a/pos_payment_method_cashdro/static/description/logo.png b/pos_payment_method_cashdro/static/description/logo.png new file mode 100644 index 0000000000..e12c033db5 Binary files /dev/null and b/pos_payment_method_cashdro/static/description/logo.png differ diff --git a/pos_payment_method_cashdro/static/src/js/models.esm.js b/pos_payment_method_cashdro/static/src/js/models.esm.js new file mode 100644 index 0000000000..d228f08d16 --- /dev/null +++ b/pos_payment_method_cashdro/static/src/js/models.esm.js @@ -0,0 +1,33 @@ +/* Copyright 2021 Tecnativa - David Vidal + License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).*/ +import {PaymentCashdro} from "./payment_cashdro.esm"; +import {patch} from "@web/core/utils/patch"; +import {PosOrder} from "@point_of_sale/app/models/pos_order"; +import {register_payment_method} from "@point_of_sale/app/store/pos_store"; + +register_payment_method("cashdro", PaymentCashdro); + +patch(PosOrder.prototype, { + setup() { + super.setup(...arguments); + this.in_cashdro_transaction = false; + }, + /** + * @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 && + line.payment_method.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/static/src/js/payment_cashdro.esm.js b/pos_payment_method_cashdro/static/src/js/payment_cashdro.esm.js new file mode 100644 index 0000000000..2397a80dcf --- /dev/null +++ b/pos_payment_method_cashdro/static/src/js/payment_cashdro.esm.js @@ -0,0 +1,196 @@ +/* Copyright 2021 Tecnativa - David Vidal + License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).*/ + +import {AlertDialog} from "@web/core/confirmation_dialog/confirmation_dialog"; +import {PaymentInterface} from "@point_of_sale/app/payment/payment_interface"; +import {_t} from "@web/core/l10n/translation"; +export class PaymentCashdro extends PaymentInterface { + /** + * @override + */ + setup() { + super.setup(...arguments); + this.enable_reversals(); + } + + /** + * @override + */ + send_payment_reversal() { + super.send_payment_reversal(...arguments); + const order = this.pos.get_order(); + const line = order.get_selected_paymentline(); + line.set_payment_status("reversing"); + return this.cashdro_send_payment_request(order); + } + + /** + * @override + */ + send_payment_cancel() { + super.send_payment_cancel(...arguments); + const operation = this.pos.get_order().cashdro_operation; + if (!operation) { + return Promise.resolve(); + } + return this.cashdro_finish_operation(operation); + } + /** + * @override + */ + send_payment_request() { + super.send_payment_request(...arguments); + const order = this.pos.get_order(); + const line = order.get_selected_paymentline(); + line.set_payment_status("waiting"); + return this.cashdro_send_payment_request(order); + } + + // -------------------------------------------------------------------------- + // Private + // -------------------------------------------------------------------------- + + async cashdro_send_payment_request(order) { + // The payment is done in three concatenated steps: + // 1. The POS send a payment request, to which the Cashdro respondes + // with an operation id. + // 2. Then the POS has to acknowledge that such operation id has + // been received. + // 3. Once acknowledged the POS has to send a payment request to the + // cashdro. Once the Cashdro responses with a "F" state (for + // finished) we'll get the response and fill the tendered money + // for the payment line. + const payment_line = order.get_selected_paymentline(); + try { + // Cashdro treats decimals as positions in an integer we also have + // to deal with floating point computing to avoid decimals at the + // end or the drawer will reject our request. + const amount = Math.round(order.get_due(payment_line) * 100); + const res = await this._cashdro_request( + this._cashdro_payment_url({amount: amount}) + ); + const operation_id = res.data || ""; + this.pos.get_order().cashdro_operation = operation_id; + // Acknowledge the operation + var ack_url = this._cashdro_ack_url(operation_id); + await this._cashdro_request(ack_url); + var ask_url = this._cashdro_ask_url(operation_id); + const operation_data = await this._cashdro_request_payment(ask_url); + var data = JSON.parse(operation_data.data); + payment_line.cashdro_operation_data = data; + var tendered = data.operation.totalin / 100; + payment_line.set_amount(tendered); + } catch { + // We wan't to be able to retry after any error. + // TODO: catch specific exceptions + payment_line.set_payment_status("retry"); + this.env.services.dialog.add(AlertDialog, { + title: _t("Error"), + body: _t("An error occurred while connecting to the cashdro."), + }); + return false; + } + return true; + } + + async cashdro_finish_operation(operation) { + // Finish the Cashdro running operation + var order = this.pos.get_order(); + if (operation) { + await this._cashdro_request(this._cashdro_finish_url(operation)); + order.cashdro_operation = false; + } + } + + // API communication methods + + _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 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; + } + + _cashdro_payment_url(parameters) { + // Compose the url for a sale report to Cashdro + const user = this.pos.get_cashier().id || this.pos.user.id; + // Type 4 for payment, 3 for refund + const operationType = parameters.amount > 0 ? 4 : 3; + parameters = {...parameters, amount: Math.abs(parameters.amount)}; + let url = `${this._cashdro_url()}&operation=startOperation&type=${operationType}`; + url += `&posid=pos-${this.pos.pos_session.name}`; + url += `&posuser=${user}`; + url += `¶meters=${encodeURIComponent(JSON.stringify(parameters))}`; + return url; + } + + _cashdro_ack_url(operation_id) { + // Compose the url for a sale report to Cashdro + var url = this._cashdro_url(); + url += "&operation=acknowledgeOperationId"; + url += "&operationId=" + operation_id; + return url; + } + + _cashdro_ask_url(operation_id) { + // Compose the url for to report a sale to Cashdro + var url = this._cashdro_url(); + url += "&operation=askOperation"; + url += "&operationId=" + operation_id; + return url; + } + + _cashdro_finish_url(operation_id) { + // Compose the url for a sale report to Cashdro + var url = this._cashdro_url(); + url += "&operation=finishOperation&type=2"; + url += "&operationId=" + operation_id; + return url; + } + + _cashdro_request(url) { + // We'll use it for regular requests + return $.ajax({ + url: url, + method: "GET", + async: true, + success: function (response) { + return response; + }, + }); + } + + /** + * This is a special request, as we keep requesting the CashDro until we get + * the *finished* state that will give us the amount received in the cashdrawer. + * + * @param {String} request_url + * @returns promise + */ + _cashdro_request_payment(request_url) { + var def = $.Deferred(); + var _request_payment = (url) => { + $.ajax({ + url: url, + method: "GET", + success: (response) => { + var data = JSON.parse(response.data); + if (data.operation.state === "F") { + def.resolve(response); + } else { + _request_payment(url); + } + }, + }); + }; + _request_payment(request_url); + return def; + } +} diff --git a/pos_payment_method_cashdro/views/pos_payment_method_views.xml b/pos_payment_method_cashdro/views/pos_payment_method_views.xml new file mode 100644 index 0000000000..79e43a8ff2 --- /dev/null +++ b/pos_payment_method_cashdro/views/pos_payment_method_views.xml @@ -0,0 +1,27 @@ + + + + pos.payment.method + + + + + + + + + + diff --git a/setup/_metapackage/pyproject.toml b/setup/_metapackage/pyproject.toml index 1ddcc45ceb..c3ec4e0959 100644 --- a/setup/_metapackage/pyproject.toml +++ b/setup/_metapackage/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "odoo-addons-oca-pos" -version = "18.0.20260408.0" +version = "18.0.20260410.0" dependencies = [ "odoo-addon-pos_barcode_rule_priced_with_change_rate==18.0.*", "odoo-addon-pos_blind_session_closing==18.0.*", @@ -13,6 +13,7 @@ dependencies = [ "odoo-addon-pos_margin==18.0.*", "odoo-addon-pos_order_remove_line==18.0.*", "odoo-addon-pos_order_to_sale_order==18.0.*", + "odoo-addon-pos_payment_method_cashdro==18.0.*", "odoo-addon-pos_product_display_default_code==18.0.*", "odoo-addon-pos_product_multi_barcode==18.0.*", "odoo-addon-pos_report_session_summary==18.0.*",