From 25d0f37edfddc072b0be2f7845d554bfa42eecc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Taymans?= Date: Tue, 3 Jun 2025 17:20:40 +0200 Subject: [PATCH 1/8] [ADD] pos_donation Allow to generate donation tax receipt from donation encoded via point of sale. --- pos_donation/README.rst | 88 ++++ pos_donation/__init__.py | 4 + pos_donation/__manifest__.py | 25 + pos_donation/demo/donation.xml | 16 + pos_donation/models/__init__.py | 7 + pos_donation/models/donation.py | 36 ++ pos_donation/models/donation_line.py | 22 + pos_donation/models/pos_order.py | 65 +++ pos_donation/models/product_template.py | 55 +++ pos_donation/readme/CONTRIBUTORS.rst | 3 + pos_donation/readme/DESCRIPTION.rst | 3 + pos_donation/static/description/index.html | 430 ++++++++++++++++++ pos_donation/views/donation_views.xml | 34 ++ pos_donation/views/product_template_views.xml | 22 + setup/pos_donation/odoo/addons/pos_donation | 1 + setup/pos_donation/setup.py | 6 + 16 files changed, 817 insertions(+) create mode 100644 pos_donation/README.rst create mode 100644 pos_donation/__init__.py create mode 100644 pos_donation/__manifest__.py create mode 100644 pos_donation/demo/donation.xml create mode 100644 pos_donation/models/__init__.py create mode 100644 pos_donation/models/donation.py create mode 100644 pos_donation/models/donation_line.py create mode 100644 pos_donation/models/pos_order.py create mode 100644 pos_donation/models/product_template.py create mode 100644 pos_donation/readme/CONTRIBUTORS.rst create mode 100644 pos_donation/readme/DESCRIPTION.rst create mode 100644 pos_donation/static/description/index.html create mode 100644 pos_donation/views/donation_views.xml create mode 100644 pos_donation/views/product_template_views.xml create mode 120000 setup/pos_donation/odoo/addons/pos_donation create mode 100644 setup/pos_donation/setup.py diff --git a/pos_donation/README.rst b/pos_donation/README.rst new file mode 100644 index 0000000000..a5fae79bfe --- /dev/null +++ b/pos_donation/README.rst @@ -0,0 +1,88 @@ +============ +POS Donation +============ + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:1713b6df7104e011ddce866123a3db0e673ac9c2dbfb2fae5c4739824e3e7543 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |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 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fpos-lightgray.png?logo=github + :target: https://github.com/OCA/pos/tree/16.0/pos_donation + :alt: OCA/pos +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/pos-16-0/pos-16-0-pos_donation + :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=16.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +When a donation product is sold in the POS, this module creates a +donation related to the POS Order in draft state. This donation can be +validated in order to generate a tax receipt for this donation. + +**Table of contents** + +.. contents:: + :local: + +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 +~~~~~~~ + +* Coop IT Easy SC + +Contributors +~~~~~~~~~~~~ + +* `Coop IT Easy SC `_: + + * Rémy Taymans + +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. + +.. |maintainer-remytms| image:: https://github.com/remytms.png?size=40px + :target: https://github.com/remytms + :alt: remytms + +Current `maintainer `__: + +|maintainer-remytms| + +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_donation/__init__.py b/pos_donation/__init__.py new file mode 100644 index 0000000000..d053ed4fe3 --- /dev/null +++ b/pos_donation/__init__.py @@ -0,0 +1,4 @@ +# SPDX-FileCopyrightText: 2025 Coop IT Easy SC +# +# SPDX-License-Identifier: AGPL-3.0-or-later +from . import models diff --git a/pos_donation/__manifest__.py b/pos_donation/__manifest__.py new file mode 100644 index 0000000000..4fda1abbf0 --- /dev/null +++ b/pos_donation/__manifest__.py @@ -0,0 +1,25 @@ +# SPDX-FileCopyrightText: 2025 Coop IT Easy SC +# +# SPDX-License-Identifier: AGPL-3.0-or-later + +{ + "name": "POS Donation", + "summary": "Generate donation for donation sold in POS.", + "version": "16.0.1.0.0", + "category": "POS", + "website": "https://github.com/OCA/pos", + "author": "Coop IT Easy SC, Odoo Community Association (OCA)", + "maintainers": ["remytms"], + "license": "AGPL-3", + "depends": [ + "donation", + "point_of_sale", + ], + "data": [ + "views/donation_views.xml", + "views/product_template_views.xml", + ], + "demo": [ + "demo/donation.xml", + ], +} diff --git a/pos_donation/demo/donation.xml b/pos_donation/demo/donation.xml new file mode 100644 index 0000000000..459fe23a4b --- /dev/null +++ b/pos_donation/demo/donation.xml @@ -0,0 +1,16 @@ + + + + POS Donation + POS-DON + + + + 0 + donation_in_pos + + This donation item that can be sold in POS and is eligible for a tax receipt. + + diff --git a/pos_donation/models/__init__.py b/pos_donation/models/__init__.py new file mode 100644 index 0000000000..f7b8ffcf35 --- /dev/null +++ b/pos_donation/models/__init__.py @@ -0,0 +1,7 @@ +# SPDX-FileCopyrightText: 2025 Coop IT Easy SC +# +# SPDX-License-Identifier: AGPL-3.0-or-later +from . import donation +from . import donation_line +from . import product_template +from . import pos_order diff --git a/pos_donation/models/donation.py b/pos_donation/models/donation.py new file mode 100644 index 0000000000..167cb22907 --- /dev/null +++ b/pos_donation/models/donation.py @@ -0,0 +1,36 @@ +# SPDX-FileCopyrightText: 2025 Coop IT Easy SC +# +# SPDX-License-Identifier: AGPL-3.0-or-later + +from odoo import _, fields, models + + +class DonationDonation(models.Model): + _inherit = "donation.donation" + + pos_order_id = fields.Many2one( + string="POS Order", + comodel_name="pos.order", + ) + + def action_view_pos_order_id(self): + return { + "type": "ir.actions.act_window", + "name": _("POS Order"), + "res_model": "pos.order", + "view_mode": "tree,form", + "domain": [("id", "in", self.pos_order_id.ids)], + } + + def validate(self): + """Keep payment_mode_id for donation_in_pos""" + payment_modes = {} + for donation in self: + payment_modes[donation.id] = donation.payment_mode_id + res = super().validate() + for donation in self: + if "donation_in_pos" in donation.line_ids.product_id.mapped( + "detailed_type" + ): + donation.payment_mode_id = payment_modes[donation.id] + return res diff --git a/pos_donation/models/donation_line.py b/pos_donation/models/donation_line.py new file mode 100644 index 0000000000..8e7b0c1250 --- /dev/null +++ b/pos_donation/models/donation_line.py @@ -0,0 +1,22 @@ +# SPDX-FileCopyrightText: 2025 Coop IT Easy SC +# +# SPDX-License-Identifier: AGPL-3.0-or-later + +from odoo import models + + +class DonationLine(models.Model): + _inherit = "donation.line" + + def _compute_in_kind(self): + """Donation in POS should be considered as donation in-kind. + These donation should not generate account move, + because account move has already been generated by the POS. + """ + res = super()._compute_in_kind() + for line in self: + # If line is not already considered a an in-kind donation, + # then we must check if it’s a pos_donation + if not line.in_kind: + line.in_kind = line.product_id.detailed_type == "donation_in_pos" + return res diff --git a/pos_donation/models/pos_order.py b/pos_donation/models/pos_order.py new file mode 100644 index 0000000000..90f149426f --- /dev/null +++ b/pos_donation/models/pos_order.py @@ -0,0 +1,65 @@ +# SPDX-FileCopyrightText: 2025 Coop IT Easy SC +# +# SPDX-License-Identifier: AGPL-3.0-or-later + +import logging + +from odoo import Command, models +from odoo.exceptions import UserError + +_logger = logging.getLogger(__name__) + + +class PosOrder(models.Model): + _inherit = "pos.order" + + def _get_donation_vals(self): + """Return value to create a donation if there is donation + product in the pos.order. It return None if there is no + donation product in the pos.order. + """ + # ensure_one because used in an ensure_one method + self.ensure_one() + donations = self.lines.filtered(lambda rec: rec.product_id.is_donation) + payment_mode_id = donations.product_id.default_payment_mode_id + tax_receipt_option = donations.product_id.default_tax_receipt_option + company_id = donations.product_id.company_id + vals = None + if donations: + vals = { + "pos_order_id": self.id, + "partner_id": self.partner_id.id, + "donation_date": self.date_order, + "payment_mode_id": payment_mode_id[0].id if payment_mode_id else False, + "company_id": company_id[0].id if company_id else False, + "payment_ref": self.pos_reference, + "tax_receipt_option": tax_receipt_option, + "line_ids": [], + } + for line in donations: + vals["line_ids"].append( + Command.create( + { + "product_id": line.product_id.id, + "quantity": line.qty, + "unit_price": line.price_unit, + } + ) + ) + return vals + + def action_pos_order_paid(self): + # ensure_one ! + res = super().action_pos_order_paid() + donation_vals = self._get_donation_vals() + if donation_vals: + donation = self.env["donation.donation"].create(donation_vals) + try: + donation.validate() + except UserError: + _logger.warning( + "Cannot validate donation {donation} based on pos.order {pos_order}".format( + donation=donation, pos_order=self + ) + ) + return res diff --git a/pos_donation/models/product_template.py b/pos_donation/models/product_template.py new file mode 100644 index 0000000000..f67b585369 --- /dev/null +++ b/pos_donation/models/product_template.py @@ -0,0 +1,55 @@ +# SPDX-FileCopyrightText: 2025 Coop IT Easy SC +# +# SPDX-License-Identifier: AGPL-3.0-or-later + +from odoo import _, fields, models + + +class ProductTemplate(models.Model): + _inherit = "product.template" + + detailed_type = fields.Selection( + selection_add=[ + ("donation_in_pos", "Donation in POS"), + ], + ondelete={ + "donation_in_pos": "set consu", + }, + ) + default_payment_mode_id = fields.Many2one( + "account.payment.mode", + domain="[('company_id', '=', company_id), ('donation', '=', True)]", + tracking=True, + default=lambda self: self.env.user.context_donation_payment_mode_id, + ) + default_tax_receipt_option = fields.Selection( + [ + ("none", "None"), + ("each", "For Each Donation"), + ("annual", "Annual Tax Receipt"), + ], + tracking=True, + ) + + _sql_constraints = [ + ( + "check_company_id_for_donation_in_pos", + """CHECK ( + (detailed_type='donation_in_pos' AND company_id IS NOT NULL) + OR detailed_type!='donation_in_pos' + )""", + _( + "Product for donation in pos must belong to a company " + "in ordrer to set default payment mode." + ), + ) + ] + + def _detailed_type_mapping(self): + res = super()._detailed_type_mapping() + res.update( + { + "donation_in_pos": "consu", + } + ) + return res diff --git a/pos_donation/readme/CONTRIBUTORS.rst b/pos_donation/readme/CONTRIBUTORS.rst new file mode 100644 index 0000000000..31498d2661 --- /dev/null +++ b/pos_donation/readme/CONTRIBUTORS.rst @@ -0,0 +1,3 @@ +* `Coop IT Easy SC `_: + + * Rémy Taymans diff --git a/pos_donation/readme/DESCRIPTION.rst b/pos_donation/readme/DESCRIPTION.rst new file mode 100644 index 0000000000..e8c139061f --- /dev/null +++ b/pos_donation/readme/DESCRIPTION.rst @@ -0,0 +1,3 @@ +When a donation product is sold in the POS, this module creates a +donation related to the POS Order in draft state. This donation can be +validated in order to generate a tax receipt for this donation. diff --git a/pos_donation/static/description/index.html b/pos_donation/static/description/index.html new file mode 100644 index 0000000000..336e4ed39b --- /dev/null +++ b/pos_donation/static/description/index.html @@ -0,0 +1,430 @@ + + + + + +POS Donation + + + +
+

POS Donation

+ + +

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

+

When a donation product is sold in the POS, this module creates a +donation related to the POS Order in draft state. This donation can be +validated in order to generate a tax receipt for this donation.

+

Table of contents

+ +
+

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

+
    +
  • Coop IT Easy SC
  • +
+
+
+

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.

+

Current maintainer:

+

remytms

+

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_donation/views/donation_views.xml b/pos_donation/views/donation_views.xml new file mode 100644 index 0000000000..f0697c42ff --- /dev/null +++ b/pos_donation/views/donation_views.xml @@ -0,0 +1,34 @@ + + + + + donation.form.pos.order + donation.donation + + +
+ +
+
+
+ + + donation.tree.pos.order + donation.donation + + + + show + + + + +
diff --git a/pos_donation/views/product_template_views.xml b/pos_donation/views/product_template_views.xml new file mode 100644 index 0000000000..d397c741c9 --- /dev/null +++ b/pos_donation/views/product_template_views.xml @@ -0,0 +1,22 @@ + + + + + donation.pos.product.template.form + product.template + + + + + + + + + + diff --git a/setup/pos_donation/odoo/addons/pos_donation b/setup/pos_donation/odoo/addons/pos_donation new file mode 120000 index 0000000000..ddc271953e --- /dev/null +++ b/setup/pos_donation/odoo/addons/pos_donation @@ -0,0 +1 @@ +../../../../pos_donation \ No newline at end of file diff --git a/setup/pos_donation/setup.py b/setup/pos_donation/setup.py new file mode 100644 index 0000000000..28c57bb640 --- /dev/null +++ b/setup/pos_donation/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +) From 5e8535700a74c1526b8a854efc91fa6416e47975 Mon Sep 17 00:00:00 2001 From: Simon Hick Date: Mon, 14 Jul 2025 16:07:09 +0200 Subject: [PATCH 2/8] [IMP] compute payment method to display --- pos_donation/demo/donation.xml | 1 + pos_donation/models/donation.py | 23 +++++++++++++++++-- pos_donation/models/pos_order.py | 8 +++++-- pos_donation/models/product_template.py | 20 ---------------- pos_donation/views/donation_views.xml | 23 +++++++++++++++++++ pos_donation/views/product_template_views.xml | 5 +--- 6 files changed, 52 insertions(+), 28 deletions(-) diff --git a/pos_donation/demo/donation.xml b/pos_donation/demo/donation.xml index 459fe23a4b..7fe5ec678f 100644 --- a/pos_donation/demo/donation.xml +++ b/pos_donation/demo/donation.xml @@ -9,6 +9,7 @@ 0 donation_in_pos + This donation item that can be sold in POS and is eligible for a tax receipt. diff --git a/pos_donation/models/donation.py b/pos_donation/models/donation.py index 167cb22907..13e9eab3e0 100644 --- a/pos_donation/models/donation.py +++ b/pos_donation/models/donation.py @@ -2,16 +2,35 @@ # # SPDX-License-Identifier: AGPL-3.0-or-later -from odoo import _, fields, models +from odoo import _, api, fields, models class DonationDonation(models.Model): _inherit = "donation.donation" pos_order_id = fields.Many2one( - string="POS Order", + string="PoS Order", comodel_name="pos.order", ) + pos_payment_ids = fields.Many2many( + string="PoS payment methods", comodel_name="pos.payment" + ) + displayed_payment_mode = fields.Char( + string="Payment Mode", + compute="_compute_displayed_payment_mode", + ) + + @api.depends("pos_payment_ids", "payment_mode_id") + def _compute_displayed_payment_mode(self): + for donation in self: + if len(donation.pos_payment_ids) > 1: + donation.displayed_payment_mode = _("Various") + elif len(donation.pos_payment_ids) == 1: + donation.displayed_payment_mode = ( + donation.pos_payment_ids.payment_method_id.name + ) + else: + donation.displayed_payment_mode = donation.payment_mode_id.name def action_view_pos_order_id(self): return { diff --git a/pos_donation/models/pos_order.py b/pos_donation/models/pos_order.py index 90f149426f..bf498b9baf 100644 --- a/pos_donation/models/pos_order.py +++ b/pos_donation/models/pos_order.py @@ -21,7 +21,10 @@ def _get_donation_vals(self): # ensure_one because used in an ensure_one method self.ensure_one() donations = self.lines.filtered(lambda rec: rec.product_id.is_donation) - payment_mode_id = donations.product_id.default_payment_mode_id + pos_payment_ids = [ + pos_payment_line.payment_method_id.id + for pos_payment_line in self.payment_ids + ] tax_receipt_option = donations.product_id.default_tax_receipt_option company_id = donations.product_id.company_id vals = None @@ -30,7 +33,8 @@ def _get_donation_vals(self): "pos_order_id": self.id, "partner_id": self.partner_id.id, "donation_date": self.date_order, - "payment_mode_id": payment_mode_id[0].id if payment_mode_id else False, + "payment_mode_id": False, + "pos_payment_ids": [Command.set(pos_payment_ids)], "company_id": company_id[0].id if company_id else False, "payment_ref": self.pos_reference, "tax_receipt_option": tax_receipt_option, diff --git a/pos_donation/models/product_template.py b/pos_donation/models/product_template.py index f67b585369..982a1f38f2 100644 --- a/pos_donation/models/product_template.py +++ b/pos_donation/models/product_template.py @@ -16,12 +16,6 @@ class ProductTemplate(models.Model): "donation_in_pos": "set consu", }, ) - default_payment_mode_id = fields.Many2one( - "account.payment.mode", - domain="[('company_id', '=', company_id), ('donation', '=', True)]", - tracking=True, - default=lambda self: self.env.user.context_donation_payment_mode_id, - ) default_tax_receipt_option = fields.Selection( [ ("none", "None"), @@ -31,20 +25,6 @@ class ProductTemplate(models.Model): tracking=True, ) - _sql_constraints = [ - ( - "check_company_id_for_donation_in_pos", - """CHECK ( - (detailed_type='donation_in_pos' AND company_id IS NOT NULL) - OR detailed_type!='donation_in_pos' - )""", - _( - "Product for donation in pos must belong to a company " - "in ordrer to set default payment mode." - ), - ) - ] - def _detailed_type_mapping(self): res = super()._detailed_type_mapping() res.update( diff --git a/pos_donation/views/donation_views.xml b/pos_donation/views/donation_views.xml index f0697c42ff..ec8ccc6ecc 100644 --- a/pos_donation/views/donation_views.xml +++ b/pos_donation/views/donation_views.xml @@ -17,6 +17,23 @@ + + + {'invisible': ['|', ('pos_payment_ids', '=', True), ('state', '=', 'done')]} + + + + + + @@ -28,6 +45,12 @@ show + + True + + + + diff --git a/pos_donation/views/product_template_views.xml b/pos_donation/views/product_template_views.xml index d397c741c9..7fa5b11487 100644 --- a/pos_donation/views/product_template_views.xml +++ b/pos_donation/views/product_template_views.xml @@ -11,10 +11,7 @@ name="default_tax_receipt_option" attrs="{'invisible': ['|', ('is_donation', '=', False), ('tax_receipt_ok', '=', False)], 'required': [('detailed_type', '=', 'donation_in_pos'), ('tax_receipt_ok', '=', True)]}" /> - + From 6a14a9a255b19207456bdfcfae694af3dbf7173b Mon Sep 17 00:00:00 2001 From: Simon Hick Date: Mon, 14 Jul 2025 16:08:34 +0200 Subject: [PATCH 3/8] [I18N] add french localization files --- pos_donation/i18n/en_US.po | 132 +++++++++++++++++++++++++++++++++++ pos_donation/i18n/fr_FR.pot | 133 ++++++++++++++++++++++++++++++++++++ 2 files changed, 265 insertions(+) create mode 100644 pos_donation/i18n/en_US.po create mode 100644 pos_donation/i18n/fr_FR.pot diff --git a/pos_donation/i18n/en_US.po b/pos_donation/i18n/en_US.po new file mode 100644 index 0000000000..67ef19206f --- /dev/null +++ b/pos_donation/i18n/en_US.po @@ -0,0 +1,132 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * pos_donation +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2025-07-13 07:26+0000\n" +"PO-Revision-Date: 2025-07-13 07:26+0000\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_donation +#: model:ir.model.fields,help:pos_donation.field_product_product__detailed_type +#: model:ir.model.fields,help:pos_donation.field_product_template__detailed_type +msgid "" +"A storable product is a product for which you manage stock. The Inventory app has to be installed.\n" +"A consumable product is a product for which stock is not managed.\n" +"A service is a non-material product you provide." +msgstr "" + +#. module: pos_donation +#: model:ir.model.fields.selection,name:pos_donation.selection__product_template__default_tax_receipt_option__annual +msgid "Annual Tax Receipt" +msgstr "" + +#. module: pos_donation +#: model:ir.model.fields,field_description:pos_donation.field_product_product__default_tax_receipt_option +#: model:ir.model.fields,field_description:pos_donation.field_product_template__default_tax_receipt_option +msgid "Default Tax Receipt Option" +msgstr "" + +#. module: pos_donation +#: model:ir.model,name:pos_donation.model_donation_donation +msgid "Donation" +msgstr "" + +#. module: pos_donation +#: model:ir.model,name:pos_donation.model_donation_line +msgid "Donation Lines" +msgstr "" + +#. module: pos_donation +#: model:ir.model.fields.selection,name:pos_donation.selection__product_template__detailed_type__donation_in_pos +msgid "Donation in POS" +msgstr "" + +#. module: pos_donation +#: model:ir.model.fields.selection,name:pos_donation.selection__product_template__default_tax_receipt_option__each +msgid "For Each Donation" +msgstr "" + +#. module: pos_donation +#: model:ir.model.fields.selection,name:pos_donation.selection__product_template__default_tax_receipt_option__none +msgid "None" +msgstr "" + +#. module: pos_donation +#: model:product.template,name:pos_donation.product_product_donation_pos_product_template +msgid "POS Donation" +msgstr "" + +#. module: pos_donation +#. odoo-python +#: code:addons/pos_donation/models/donation.py:0 +#: code:addons/pos_donation/models/donation.py:0 +#: code:addons/src/oca/pos/pos_donation/models/donation.py:0 +#: model_terms:ir.ui.view,arch_db:pos_donation.donation_form +#, python-format +msgid "POS Order" +msgstr "" + +#. module: pos_donation +#: model:ir.model.fields,field_description:pos_donation.field_donation_donation__displayed_payment_mode +msgid "Payment Mode" +msgstr "" + +#. module: pos_donation +#: model:ir.model.fields,field_description:pos_donation.field_donation_donation__pos_order_id +msgid "PoS Order" +msgstr "" + +#. module: pos_donation +#: model:ir.model.fields,field_description:pos_donation.field_donation_donation__pos_payment_ids +msgid "PoS payment methods" +msgstr "" + +#. module: pos_donation +#: model:ir.model,name:pos_donation.model_pos_order +msgid "Point of Sale Orders" +msgstr "" + +#. module: pos_donation +#: model:ir.model,name:pos_donation.model_product_template +msgid "Product" +msgstr "" + +#. module: pos_donation +#: model:ir.model.fields,field_description:pos_donation.field_product_product__detailed_type +#: model:ir.model.fields,field_description:pos_donation.field_product_template__detailed_type +msgid "Product Type" +msgstr "" + +#. module: pos_donation +#. odoo-python +#: code:addons/pos_donation/models/product_template.py:0 +#: code:addons/pos_donation/models/product_template.py:0 +#: code:addons/src/oca/pos/pos_donation/models/product_template.py:0 +#: model:ir.model.constraint,message:pos_donation.constraint_product_template_check_company_id_for_donation_in_pos +#, python-format +msgid "" +"Product for donation in pos must belong to a company." +msgstr "" + +#. module: pos_donation +#: model_terms:product.template,description:pos_donation.product_product_donation_pos_product_template +msgid "" +"This donation item that can be sold in POS and is eligible for a tax " +"receipt." +msgstr "" + +#. module: pos_donation +#. odoo-python +#: code:addons/pos_donation/models/donation.py:0 +#, python-format +msgid "Various" +msgstr "" diff --git a/pos_donation/i18n/fr_FR.pot b/pos_donation/i18n/fr_FR.pot new file mode 100644 index 0000000000..6565af9282 --- /dev/null +++ b/pos_donation/i18n/fr_FR.pot @@ -0,0 +1,133 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * pos_donation +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2025-07-13 07:27+0000\n" +"PO-Revision-Date: 2025-07-13 07:27+0000\n" +"Last-Translator: Simon Hick\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_donation +#: model:ir.model.fields,help:pos_donation.field_product_product__detailed_type +#: model:ir.model.fields,help:pos_donation.field_product_template__detailed_type +msgid "" +"A storable product is a product for which you manage stock. The Inventory app has to be installed.\n" +"A consumable product is a product for which stock is not managed.\n" +"A service is a non-material product you provide." +msgstr "" + +#. module: pos_donation +#: model:ir.model.fields.selection,name:pos_donation.selection__product_template__default_tax_receipt_option__annual +msgid "Annual Tax Receipt" +msgstr "" + +#. module: pos_donation +#: model:ir.model.fields,field_description:pos_donation.field_product_product__default_tax_receipt_option +#: model:ir.model.fields,field_description:pos_donation.field_product_template__default_tax_receipt_option +msgid "Default Tax Receipt Option" +msgstr "" + +#. module: pos_donation +#: model:ir.model,name:pos_donation.model_donation_donation +msgid "Donation" +msgstr "" + +#. module: pos_donation +#: model:ir.model,name:pos_donation.model_donation_line +msgid "Donation Lines" +msgstr "" + +#. module: pos_donation +#: model:ir.model.fields.selection,name:pos_donation.selection__product_template__detailed_type__donation_in_pos +msgid "Donation in POS" +msgstr "" + +#. module: pos_donation +#: model:ir.model.fields.selection,name:pos_donation.selection__product_template__default_tax_receipt_option__each +msgid "For Each Donation" +msgstr "" + +#. module: pos_donation +#: model:ir.model.fields.selection,name:pos_donation.selection__product_template__default_tax_receipt_option__none +msgid "None" +msgstr "" + +#. module: pos_donation +#: model:product.template,name:pos_donation.product_product_donation_pos_product_template +msgid "POS Donation" +msgstr "" + +#. module: pos_donation +#. odoo-python +#: code:addons/pos_donation/models/donation.py:0 +#: code:addons/pos_donation/models/donation.py:0 +#: code:addons/src/oca/pos/pos_donation/models/donation.py:0 +#: model_terms:ir.ui.view,arch_db:pos_donation.donation_form +#, python-format +msgid "POS Order" +msgstr "" + +#. module: pos_donation +#: model:ir.model.fields,field_description:pos_donation.field_donation_donation__displayed_payment_mode +msgid "Payment Mode" +msgstr "" + +#. module: pos_donation +#: model:ir.model.fields,field_description:pos_donation.field_donation_donation__pos_order_id +msgid "PoS Order" +msgstr "" + +#. module: pos_donation +#: model:ir.model.fields,field_description:pos_donation.field_donation_donation__pos_payment_ids +msgid "PoS payment methods" +msgstr "" + +#. module: pos_donation +#: model:ir.model,name:pos_donation.model_pos_order +msgid "Point of Sale Orders" +msgstr "" + +#. module: pos_donation +#: model:ir.model,name:pos_donation.model_product_template +msgid "Product" +msgstr "" + +#. module: pos_donation +#: model:ir.model.fields,field_description:pos_donation.field_product_product__detailed_type +#: model:ir.model.fields,field_description:pos_donation.field_product_template__detailed_type +msgid "Product Type" +msgstr "" + +#. module: pos_donation +#. odoo-python +#: code:addons/pos_donation/models/product_template.py:0 +#: code:addons/pos_donation/models/product_template.py:0 +#: code:addons/src/oca/pos/pos_donation/models/product_template.py:0 +#: model:ir.model.constraint,message:pos_donation.constraint_product_template_check_company_id_for_donation_in_pos +#, python-format +msgid "" +"Product for donation in pos must belong to a company." +msgstr "Un produit représentant une donation doit appartenir à une entreprise" + +#. module: pos_donation +#: model_terms:product.template,description:pos_donation.product_product_donation_pos_product_template +msgid "" +"This donation item that can be sold in POS and is eligible for a tax " +"receipt." +msgstr "Ce produit est une donation, il peut être vendu en PdV et est éligible " +"pour un reçu fiscal." + +#. module: pos_donation +#. odoo-python +#: code:addons/pos_donation/models/donation.py:0 +#, python-format +msgid "Various" +msgstr "Divers" From e16c0694871848dc2cb77c96e902cd3c975595d1 Mon Sep 17 00:00:00 2001 From: hugues de keyzer Date: Tue, 15 Jul 2025 14:59:43 +0200 Subject: [PATCH 4/8] [FIX] use the order company_id for the donation --- pos_donation/demo/donation.xml | 3 +-- pos_donation/models/pos_order.py | 17 ++++++++++------- pos_donation/models/product_template.py | 2 +- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/pos_donation/demo/donation.xml b/pos_donation/demo/donation.xml index 7fe5ec678f..7d0f73100e 100644 --- a/pos_donation/demo/donation.xml +++ b/pos_donation/demo/donation.xml @@ -1,7 +1,7 @@ - POS Donation + PoS Donation POS-DON @@ -9,7 +9,6 @@ 0 donation_in_pos - This donation item that can be sold in POS and is eligible for a tax receipt. diff --git a/pos_donation/models/pos_order.py b/pos_donation/models/pos_order.py index bf498b9baf..7be07744b4 100644 --- a/pos_donation/models/pos_order.py +++ b/pos_donation/models/pos_order.py @@ -21,21 +21,24 @@ def _get_donation_vals(self): # ensure_one because used in an ensure_one method self.ensure_one() donations = self.lines.filtered(lambda rec: rec.product_id.is_donation) - pos_payment_ids = [ - pos_payment_line.payment_method_id.id - for pos_payment_line in self.payment_ids - ] - tax_receipt_option = donations.product_id.default_tax_receipt_option - company_id = donations.product_id.company_id vals = None if donations: + pos_payment_ids = [ + pos_payment_line.payment_method_id.id + for pos_payment_line in self.payment_ids + ] + # FIXME: this will fail if there are multiple products. the + # default_tax_receipt_option should not be defined on the + # product.template but on a more global record, like the + # pos.config. + tax_receipt_option = donations.product_id.default_tax_receipt_option vals = { "pos_order_id": self.id, "partner_id": self.partner_id.id, "donation_date": self.date_order, "payment_mode_id": False, "pos_payment_ids": [Command.set(pos_payment_ids)], - "company_id": company_id[0].id if company_id else False, + "company_id": self.company_id.id, "payment_ref": self.pos_reference, "tax_receipt_option": tax_receipt_option, "line_ids": [], diff --git a/pos_donation/models/product_template.py b/pos_donation/models/product_template.py index 982a1f38f2..dbfbe29f6c 100644 --- a/pos_donation/models/product_template.py +++ b/pos_donation/models/product_template.py @@ -2,7 +2,7 @@ # # SPDX-License-Identifier: AGPL-3.0-or-later -from odoo import _, fields, models +from odoo import fields, models class ProductTemplate(models.Model): From a185d6b67ca638b91d0c6efea8d86b24d4ed6efe Mon Sep 17 00:00:00 2001 From: Simon Hick Date: Tue, 15 Jul 2025 19:18:16 +0200 Subject: [PATCH 5/8] [FIX] rename localization files --- pos_donation/i18n/{fr_FR.pot => fr.po} | 0 pos_donation/i18n/{en_US.po => pos_donation.pot} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename pos_donation/i18n/{fr_FR.pot => fr.po} (100%) rename pos_donation/i18n/{en_US.po => pos_donation.pot} (100%) diff --git a/pos_donation/i18n/fr_FR.pot b/pos_donation/i18n/fr.po similarity index 100% rename from pos_donation/i18n/fr_FR.pot rename to pos_donation/i18n/fr.po diff --git a/pos_donation/i18n/en_US.po b/pos_donation/i18n/pos_donation.pot similarity index 100% rename from pos_donation/i18n/en_US.po rename to pos_donation/i18n/pos_donation.pot From fa0c1c55d584c9d1456cfa24686346a90b0fc375 Mon Sep 17 00:00:00 2001 From: hugues de keyzer Date: Wed, 16 Jul 2025 17:51:09 +0200 Subject: [PATCH 6/8] [FIX] fix and improve multiple things * replace the donation.donation.pos_payment_ids field by pos_payment_method_ids to be able to access the pos payment methods directly. * fix donation creation error: the code was trying to store pos.payment.method ids in a many2many to pos.payment. * make donation.donation.pos_payment_method_ids a computed field. * avoid error in pos if no partner is selected. * remove useless code. * rename "POS" to "PoS" in multiple places. * update i18n files. * update readme. --- pos_donation/README.rst | 24 +++++++-- pos_donation/__manifest__.py | 6 +-- pos_donation/demo/donation.xml | 8 +-- pos_donation/i18n/fr.po | 60 +++++++++------------- pos_donation/i18n/pos_donation.pot | 52 ++++++------------- pos_donation/models/donation.py | 49 +++++++++--------- pos_donation/models/donation_line.py | 4 +- pos_donation/models/pos_order.py | 32 ++++++++---- pos_donation/models/product_template.py | 2 +- pos_donation/readme/DESCRIPTION.rst | 4 +- pos_donation/readme/ROADMAP.rst | 5 ++ pos_donation/readme/USAGE.rst | 5 ++ pos_donation/static/description/index.html | 47 +++++++++++------ pos_donation/views/donation_views.xml | 8 +-- 14 files changed, 165 insertions(+), 141 deletions(-) create mode 100644 pos_donation/readme/ROADMAP.rst create mode 100644 pos_donation/readme/USAGE.rst diff --git a/pos_donation/README.rst b/pos_donation/README.rst index a5fae79bfe..20598d3754 100644 --- a/pos_donation/README.rst +++ b/pos_donation/README.rst @@ -1,5 +1,5 @@ ============ -POS Donation +PoS Donation ============ .. @@ -28,15 +28,31 @@ POS Donation |badge1| |badge2| |badge3| |badge4| |badge5| -When a donation product is sold in the POS, this module creates a -donation related to the POS Order in draft state. This donation can be -validated in order to generate a tax receipt for this donation. +When a donation product is sold in the PoS, this module creates a donation related to the PoS order and validates it. **Table of contents** .. contents:: :local: +Usage +===== + +To create donations from the PoS, a donation product must be sold. +This product must have the "Donation in PoS" product type. +This is important: the normal "Donation" product type will not work, as this would generate accounting entries two times. + +The price of the product on the PoS order line defines the price of the donation. + +Known issues / Roadmap +====================== + +* If there is no partner set on the PoS order, a donation is not created. + There should be a user warning in the PoS to avoid this. +* If there are multiple donation products used in the same PoS order, a donation is not created. + This is because the ``default_tax_receipt_option`` is currently defined on the ``product.template``. + It would be better to define it on on a more global record, like the ``pos.config``. + Bug Tracker =========== diff --git a/pos_donation/__manifest__.py b/pos_donation/__manifest__.py index 4fda1abbf0..2d5806d9f4 100644 --- a/pos_donation/__manifest__.py +++ b/pos_donation/__manifest__.py @@ -3,10 +3,10 @@ # SPDX-License-Identifier: AGPL-3.0-or-later { - "name": "POS Donation", - "summary": "Generate donation for donation sold in POS.", + "name": "PoS Donation", + "summary": "Generate donation for donation sold in PoS", "version": "16.0.1.0.0", - "category": "POS", + "category": "Sales/Point of Sale", "website": "https://github.com/OCA/pos", "author": "Coop IT Easy SC, Odoo Community Association (OCA)", "maintainers": ["remytms"], diff --git a/pos_donation/demo/donation.xml b/pos_donation/demo/donation.xml index 7d0f73100e..26fa0ff303 100644 --- a/pos_donation/demo/donation.xml +++ b/pos_donation/demo/donation.xml @@ -5,12 +5,14 @@ POS-DON - 0 - donation_in_pos + donation_in_pos + + True + none This donation item that can be sold in POS and is eligible for a tax receipt. + >Donation item that can be sold in PoS and that is eligible for a tax receipt diff --git a/pos_donation/i18n/fr.po b/pos_donation/i18n/fr.po index 6565af9282..1f427f6f60 100644 --- a/pos_donation/i18n/fr.po +++ b/pos_donation/i18n/fr.po @@ -10,6 +10,7 @@ msgstr "" "PO-Revision-Date: 2025-07-13 07:27+0000\n" "Last-Translator: Simon Hick\n" "Language-Team: \n" +"Language: fr\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: \n" @@ -19,7 +20,8 @@ msgstr "" #: model:ir.model.fields,help:pos_donation.field_product_product__detailed_type #: model:ir.model.fields,help:pos_donation.field_product_template__detailed_type msgid "" -"A storable product is a product for which you manage stock. The Inventory app has to be installed.\n" +"A storable product is a product for which you manage stock. The Inventory " +"app has to be installed.\n" "A consumable product is a product for which stock is not managed.\n" "A service is a non-material product you provide." msgstr "" @@ -47,9 +49,16 @@ msgstr "" #. module: pos_donation #: model:ir.model.fields.selection,name:pos_donation.selection__product_template__detailed_type__donation_in_pos -msgid "Donation in POS" +msgid "Donation in PoS" msgstr "" +#. module: pos_donation +#: model_terms:product.template,description:pos_donation.product_product_donation_pos_product_template +msgid "" +"Donation item that can be sold in PoS and that is eligible for a tax receipt" +msgstr "" +"Don qui peut être vendu en PdV et qui est éligible pour un reçu fiscal" + #. module: pos_donation #: model:ir.model.fields.selection,name:pos_donation.selection__product_template__default_tax_receipt_option__each msgid "For Each Donation" @@ -60,34 +69,28 @@ msgstr "" msgid "None" msgstr "" +#. module: pos_donation +#: model:ir.model.fields,field_description:pos_donation.field_donation_donation__displayed_payment_mode +msgid "Payment Mode" +msgstr "" + #. module: pos_donation #: model:product.template,name:pos_donation.product_product_donation_pos_product_template -msgid "POS Donation" +msgid "PoS Donation" msgstr "" #. module: pos_donation #. odoo-python #: code:addons/pos_donation/models/donation.py:0 -#: code:addons/pos_donation/models/donation.py:0 -#: code:addons/src/oca/pos/pos_donation/models/donation.py:0 +#: model:ir.model.fields,field_description:pos_donation.field_donation_donation__pos_order_id #: model_terms:ir.ui.view,arch_db:pos_donation.donation_form #, python-format -msgid "POS Order" -msgstr "" - -#. module: pos_donation -#: model:ir.model.fields,field_description:pos_donation.field_donation_donation__displayed_payment_mode -msgid "Payment Mode" -msgstr "" - -#. module: pos_donation -#: model:ir.model.fields,field_description:pos_donation.field_donation_donation__pos_order_id msgid "PoS Order" msgstr "" #. module: pos_donation -#: model:ir.model.fields,field_description:pos_donation.field_donation_donation__pos_payment_ids -msgid "PoS payment methods" +#: model:ir.model.fields,field_description:pos_donation.field_donation_donation__pos_payment_method_ids +msgid "PoS Payment Methods" msgstr "" #. module: pos_donation @@ -106,28 +109,13 @@ msgstr "" msgid "Product Type" msgstr "" -#. module: pos_donation -#. odoo-python -#: code:addons/pos_donation/models/product_template.py:0 -#: code:addons/pos_donation/models/product_template.py:0 -#: code:addons/src/oca/pos/pos_donation/models/product_template.py:0 -#: model:ir.model.constraint,message:pos_donation.constraint_product_template_check_company_id_for_donation_in_pos -#, python-format -msgid "" -"Product for donation in pos must belong to a company." -msgstr "Un produit représentant une donation doit appartenir à une entreprise" - -#. module: pos_donation -#: model_terms:product.template,description:pos_donation.product_product_donation_pos_product_template -msgid "" -"This donation item that can be sold in POS and is eligible for a tax " -"receipt." -msgstr "Ce produit est une donation, il peut être vendu en PdV et est éligible " -"pour un reçu fiscal." - #. module: pos_donation #. odoo-python #: code:addons/pos_donation/models/donation.py:0 #, python-format msgid "Various" msgstr "Divers" + +#~ msgid "Product for donation in pos must belong to a company." +#~ msgstr "" +#~ "Un produit représentant une donation doit appartenir à une entreprise" diff --git a/pos_donation/i18n/pos_donation.pot b/pos_donation/i18n/pos_donation.pot index 67ef19206f..2a8a2c4a47 100644 --- a/pos_donation/i18n/pos_donation.pot +++ b/pos_donation/i18n/pos_donation.pot @@ -6,8 +6,6 @@ msgid "" msgstr "" "Project-Id-Version: Odoo Server 16.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-07-13 07:26+0000\n" -"PO-Revision-Date: 2025-07-13 07:26+0000\n" "Last-Translator: \n" "Language-Team: \n" "MIME-Version: 1.0\n" @@ -47,7 +45,13 @@ msgstr "" #. module: pos_donation #: model:ir.model.fields.selection,name:pos_donation.selection__product_template__detailed_type__donation_in_pos -msgid "Donation in POS" +msgid "Donation in PoS" +msgstr "" + +#. module: pos_donation +#: model_terms:product.template,description:pos_donation.product_product_donation_pos_product_template +msgid "" +"Donation item that can be sold in PoS and that is eligible for a tax receipt" msgstr "" #. module: pos_donation @@ -60,34 +64,28 @@ msgstr "" msgid "None" msgstr "" +#. module: pos_donation +#: model:ir.model.fields,field_description:pos_donation.field_donation_donation__displayed_payment_mode +msgid "Payment Mode" +msgstr "" + #. module: pos_donation #: model:product.template,name:pos_donation.product_product_donation_pos_product_template -msgid "POS Donation" +msgid "PoS Donation" msgstr "" #. module: pos_donation #. odoo-python #: code:addons/pos_donation/models/donation.py:0 -#: code:addons/pos_donation/models/donation.py:0 -#: code:addons/src/oca/pos/pos_donation/models/donation.py:0 +#: model:ir.model.fields,field_description:pos_donation.field_donation_donation__pos_order_id #: model_terms:ir.ui.view,arch_db:pos_donation.donation_form #, python-format -msgid "POS Order" -msgstr "" - -#. module: pos_donation -#: model:ir.model.fields,field_description:pos_donation.field_donation_donation__displayed_payment_mode -msgid "Payment Mode" -msgstr "" - -#. module: pos_donation -#: model:ir.model.fields,field_description:pos_donation.field_donation_donation__pos_order_id msgid "PoS Order" msgstr "" #. module: pos_donation -#: model:ir.model.fields,field_description:pos_donation.field_donation_donation__pos_payment_ids -msgid "PoS payment methods" +#: model:ir.model.fields,field_description:pos_donation.field_donation_donation__pos_payment_method_ids +msgid "PoS Payment Methods" msgstr "" #. module: pos_donation @@ -106,24 +104,6 @@ msgstr "" msgid "Product Type" msgstr "" -#. module: pos_donation -#. odoo-python -#: code:addons/pos_donation/models/product_template.py:0 -#: code:addons/pos_donation/models/product_template.py:0 -#: code:addons/src/oca/pos/pos_donation/models/product_template.py:0 -#: model:ir.model.constraint,message:pos_donation.constraint_product_template_check_company_id_for_donation_in_pos -#, python-format -msgid "" -"Product for donation in pos must belong to a company." -msgstr "" - -#. module: pos_donation -#: model_terms:product.template,description:pos_donation.product_product_donation_pos_product_template -msgid "" -"This donation item that can be sold in POS and is eligible for a tax " -"receipt." -msgstr "" - #. module: pos_donation #. odoo-python #: code:addons/pos_donation/models/donation.py:0 diff --git a/pos_donation/models/donation.py b/pos_donation/models/donation.py index 13e9eab3e0..fdc3e4b63c 100644 --- a/pos_donation/models/donation.py +++ b/pos_donation/models/donation.py @@ -12,44 +12,43 @@ class DonationDonation(models.Model): string="PoS Order", comodel_name="pos.order", ) - pos_payment_ids = fields.Many2many( - string="PoS payment methods", comodel_name="pos.payment" + pos_payment_method_ids = fields.Many2many( + "pos.payment.method", + string="PoS Payment Methods", + compute="_compute_pos_payment_method_ids", ) displayed_payment_mode = fields.Char( - string="Payment Mode", + # non-breaking space here to avoid warning (because this is done on + # purpose): Two fields (displayed_payment_mode, payment_mode_id) of + # donation.donation() have the same label: Payment Mode. [Modules: + # pos_donation and donation] + string="Payment Mode", compute="_compute_displayed_payment_mode", ) - @api.depends("pos_payment_ids", "payment_mode_id") + @api.depends("pos_order_id.payment_ids.payment_method_id") + def _compute_pos_payment_method_ids(self): + for rec in self: + rec.pos_payment_method_ids = rec.pos_order_id.payment_ids.payment_method_id + + @api.depends("pos_order_id.payment_ids.payment_method_id", "payment_mode_id") def _compute_displayed_payment_mode(self): for donation in self: - if len(donation.pos_payment_ids) > 1: - donation.displayed_payment_mode = _("Various") - elif len(donation.pos_payment_ids) == 1: - donation.displayed_payment_mode = ( - donation.pos_payment_ids.payment_method_id.name - ) + if donation.pos_payment_method_ids: + if len(donation.pos_payment_method_ids) > 1: + donation.displayed_payment_mode = _("Various") + else: + donation.displayed_payment_mode = ( + donation.pos_payment_method_ids.name + ) else: donation.displayed_payment_mode = donation.payment_mode_id.name def action_view_pos_order_id(self): return { "type": "ir.actions.act_window", - "name": _("POS Order"), + "name": _("PoS Order"), "res_model": "pos.order", "view_mode": "tree,form", - "domain": [("id", "in", self.pos_order_id.ids)], + "domain": [("id", "=", self.pos_order_id.id)], } - - def validate(self): - """Keep payment_mode_id for donation_in_pos""" - payment_modes = {} - for donation in self: - payment_modes[donation.id] = donation.payment_mode_id - res = super().validate() - for donation in self: - if "donation_in_pos" in donation.line_ids.product_id.mapped( - "detailed_type" - ): - donation.payment_mode_id = payment_modes[donation.id] - return res diff --git a/pos_donation/models/donation_line.py b/pos_donation/models/donation_line.py index 8e7b0c1250..2f9c62f232 100644 --- a/pos_donation/models/donation_line.py +++ b/pos_donation/models/donation_line.py @@ -9,9 +9,9 @@ class DonationLine(models.Model): _inherit = "donation.line" def _compute_in_kind(self): - """Donation in POS should be considered as donation in-kind. + """Donation in PoS should be considered as donation in-kind. These donation should not generate account move, - because account move has already been generated by the POS. + because account move has already been generated by the PoS. """ res = super()._compute_in_kind() for line in self: diff --git a/pos_donation/models/pos_order.py b/pos_donation/models/pos_order.py index 7be07744b4..b2d8fc6c87 100644 --- a/pos_donation/models/pos_order.py +++ b/pos_donation/models/pos_order.py @@ -23,21 +23,34 @@ def _get_donation_vals(self): donations = self.lines.filtered(lambda rec: rec.product_id.is_donation) vals = None if donations: - pos_payment_ids = [ - pos_payment_line.payment_method_id.id - for pos_payment_line in self.payment_ids - ] - # FIXME: this will fail if there are multiple products. the + # FIXME: this should be checked in pos + if not self.partner_id: + _logger.warning( + ( + "Cannot create donation for pos.order {pos_order} " + "because there is no partner linked to the order." + ).format(pos_order=self) + ) + return None + # FIXME: having multiple products is currently not supported. the # default_tax_receipt_option should not be defined on the # product.template but on a more global record, like the # pos.config. + if len(donations.product_id) > 1: + _logger.warning( + ( + "Cannot create donation for pos.order {pos_order} " + "because there are multiple donation products in the " + "order." + ).format(pos_order=self) + ) + return None tax_receipt_option = donations.product_id.default_tax_receipt_option vals = { "pos_order_id": self.id, "partner_id": self.partner_id.id, "donation_date": self.date_order, "payment_mode_id": False, - "pos_payment_ids": [Command.set(pos_payment_ids)], "company_id": self.company_id.id, "payment_ref": self.pos_reference, "tax_receipt_option": tax_receipt_option, @@ -65,8 +78,9 @@ def action_pos_order_paid(self): donation.validate() except UserError: _logger.warning( - "Cannot validate donation {donation} based on pos.order {pos_order}".format( - donation=donation, pos_order=self - ) + ( + "Cannot validate donation {donation} based on " + "pos.order {pos_order}." + ).format(donation=donation, pos_order=self) ) return res diff --git a/pos_donation/models/product_template.py b/pos_donation/models/product_template.py index dbfbe29f6c..dc122698a3 100644 --- a/pos_donation/models/product_template.py +++ b/pos_donation/models/product_template.py @@ -10,7 +10,7 @@ class ProductTemplate(models.Model): detailed_type = fields.Selection( selection_add=[ - ("donation_in_pos", "Donation in POS"), + ("donation_in_pos", "Donation in PoS"), ], ondelete={ "donation_in_pos": "set consu", diff --git a/pos_donation/readme/DESCRIPTION.rst b/pos_donation/readme/DESCRIPTION.rst index e8c139061f..13d3a8c744 100644 --- a/pos_donation/readme/DESCRIPTION.rst +++ b/pos_donation/readme/DESCRIPTION.rst @@ -1,3 +1 @@ -When a donation product is sold in the POS, this module creates a -donation related to the POS Order in draft state. This donation can be -validated in order to generate a tax receipt for this donation. +When a donation product is sold in the PoS, this module creates a donation related to the PoS order and validates it. diff --git a/pos_donation/readme/ROADMAP.rst b/pos_donation/readme/ROADMAP.rst new file mode 100644 index 0000000000..c0c35d9702 --- /dev/null +++ b/pos_donation/readme/ROADMAP.rst @@ -0,0 +1,5 @@ +* If there is no partner set on the PoS order, a donation is not created. + There should be a user warning in the PoS to avoid this. +* If there are multiple donation products used in the same PoS order, a donation is not created. + This is because the ``default_tax_receipt_option`` is currently defined on the ``product.template``. + It would be better to define it on on a more global record, like the ``pos.config``. diff --git a/pos_donation/readme/USAGE.rst b/pos_donation/readme/USAGE.rst new file mode 100644 index 0000000000..cd386b4d90 --- /dev/null +++ b/pos_donation/readme/USAGE.rst @@ -0,0 +1,5 @@ +To create donations from the PoS, a donation product must be sold. +This product must have the "Donation in PoS" product type. +This is important: the normal "Donation" product type will not work, as this would generate accounting entries two times. + +The price of the product on the PoS order line defines the price of the donation. diff --git a/pos_donation/static/description/index.html b/pos_donation/static/description/index.html index 336e4ed39b..5c3f87e425 100644 --- a/pos_donation/static/description/index.html +++ b/pos_donation/static/description/index.html @@ -3,7 +3,7 @@ -POS Donation +PoS Donation