From 7c4e5ac76099e138a99afb00cad81ff74ee16ddb Mon Sep 17 00:00:00 2001 From: David Date: Thu, 16 Feb 2023 17:15:43 +0100 Subject: [PATCH] [ADD] sale_coupon_order_pending: New module TT41520 --- sale_coupon_order_pending/README.rst | 87 ++++ sale_coupon_order_pending/__init__.py | 1 + sale_coupon_order_pending/__manifest__.py | 13 + sale_coupon_order_pending/models/__init__.py | 2 + .../models/coupon_coupon.py | 33 ++ .../models/sale_order.py | 54 +++ .../readme/CONTRIBUTORS.rst | 3 + .../readme/DESCRIPTION.rst | 2 + sale_coupon_order_pending/readme/USAGE.rst | 7 + .../static/description/icon.png | Bin 0 -> 7296 bytes .../static/description/index.html | 435 ++++++++++++++++++ sale_coupon_order_pending/tests/__init__.py | 1 + .../tests/test_sale_coupon_order_pending.py | 45 ++ .../views/coupon_coupon_views.xml | 50 ++ .../views/sale_order_views.xml | 25 + .../odoo/addons/sale_coupon_order_pending | 1 + setup/sale_coupon_order_pending/setup.py | 6 + 17 files changed, 765 insertions(+) create mode 100644 sale_coupon_order_pending/README.rst create mode 100644 sale_coupon_order_pending/__init__.py create mode 100644 sale_coupon_order_pending/__manifest__.py create mode 100644 sale_coupon_order_pending/models/__init__.py create mode 100644 sale_coupon_order_pending/models/coupon_coupon.py create mode 100644 sale_coupon_order_pending/models/sale_order.py create mode 100644 sale_coupon_order_pending/readme/CONTRIBUTORS.rst create mode 100644 sale_coupon_order_pending/readme/DESCRIPTION.rst create mode 100644 sale_coupon_order_pending/readme/USAGE.rst create mode 100644 sale_coupon_order_pending/static/description/icon.png create mode 100644 sale_coupon_order_pending/static/description/index.html create mode 100644 sale_coupon_order_pending/tests/__init__.py create mode 100644 sale_coupon_order_pending/tests/test_sale_coupon_order_pending.py create mode 100644 sale_coupon_order_pending/views/coupon_coupon_views.xml create mode 100644 sale_coupon_order_pending/views/sale_order_views.xml create mode 120000 setup/sale_coupon_order_pending/odoo/addons/sale_coupon_order_pending create mode 100644 setup/sale_coupon_order_pending/setup.py diff --git a/sale_coupon_order_pending/README.rst b/sale_coupon_order_pending/README.rst new file mode 100644 index 000000000..e0873a481 --- /dev/null +++ b/sale_coupon_order_pending/README.rst @@ -0,0 +1,87 @@ +=============== +Pending Coupons +=============== + +.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |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%2Fsale--promotion-lightgray.png?logo=github + :target: https://github.com/OCA/sale-promotion/tree/13.0/sale_coupon_order_pending + :alt: OCA/sale-promotion +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/sale-promotion-13-0/sale-promotion-13-0-sale_coupon_order_pending + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png + :target: https://runbot.odoo-community.org/runbot/296/13.0 + :alt: Try me on Runbot + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module allows the salesmen to tell if there are pending coupons that customer can +enjoy in his sales order. + +**Table of contents** + +.. contents:: + :local: + +Usage +===== + +To use this module, you need to: + +#. Generate some coupons for your partner. +#. Go to a quotation/sales order from that partner and a smart button will show that + there are pending coupons. +#. Click on the smart button and you'll be able to apply those which conditions are met + by the order. + +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 smashing it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +~~~~~~~ + +* Tecnativa + +Contributors +~~~~~~~~~~~~ + +* `Tecnativa `_: + + * David Vidal + +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/sale-promotion `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/sale_coupon_order_pending/__init__.py b/sale_coupon_order_pending/__init__.py new file mode 100644 index 000000000..0650744f6 --- /dev/null +++ b/sale_coupon_order_pending/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/sale_coupon_order_pending/__manifest__.py b/sale_coupon_order_pending/__manifest__.py new file mode 100644 index 000000000..bd2ed9552 --- /dev/null +++ b/sale_coupon_order_pending/__manifest__.py @@ -0,0 +1,13 @@ +# Copyright 2023 Tecnativa - David Vidal +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +{ + "name": "Pending Coupons", + "summary": "Show partner's pending coupons in sale order", + "version": "13.0.1.0.0", + "author": "Tecnativa, Odoo Community Association (OCA)", + "license": "AGPL-3", + "category": "Sales Management", + "website": "https://github.com/OCA/sale-promotion", + "depends": ["sale_coupon"], + "data": ["views/sale_order_views.xml", "views/coupon_coupon_views.xml"], +} diff --git a/sale_coupon_order_pending/models/__init__.py b/sale_coupon_order_pending/models/__init__.py new file mode 100644 index 000000000..e9646a849 --- /dev/null +++ b/sale_coupon_order_pending/models/__init__.py @@ -0,0 +1,2 @@ +from . import coupon_coupon +from . import sale_order diff --git a/sale_coupon_order_pending/models/coupon_coupon.py b/sale_coupon_order_pending/models/coupon_coupon.py new file mode 100644 index 000000000..761b571ab --- /dev/null +++ b/sale_coupon_order_pending/models/coupon_coupon.py @@ -0,0 +1,33 @@ +# Copyright 2023 Tecnativa - David Vidal +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +from odoo import api, fields, models + + +class SaleCoupon(models.Model): + _inherit = "sale.coupon" + + can_be_applied_to_order = fields.Boolean( + compute="_compute_can_be_applied_to_order", compute_sudo=True, + ) + + @api.depends_context("active_id") + def _compute_can_be_applied_to_order(self): + self.can_be_applied_to_order = False + if self.env.context.get("active_model", "") != "sale.order": + return + order = self.env["sale.order"].browse(self.env.context.get("active_id")) + for coupon in self: + if not coupon._check_coupon_code(order): + self.can_be_applied_to_order = True + + def action_apply_partner_coupon(self): + if self.env.context.get("active_model", "") != "sale.order": + return + self.env["sale.coupon.apply.code"].sudo().new( + {"coupon_code": self.code} + ).process_coupon() + return ( + self.env["sale.order"] + .browse(self.env.context.get("active_id")) + .get_formview_action() + ) diff --git a/sale_coupon_order_pending/models/sale_order.py b/sale_coupon_order_pending/models/sale_order.py new file mode 100644 index 000000000..47cf1f1bd --- /dev/null +++ b/sale_coupon_order_pending/models/sale_order.py @@ -0,0 +1,54 @@ +# Copyright 2023 Tecnativa - David Vidal +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +from odoo import _, api, fields, models +from odoo.osv import expression + + +class SaleOrder(models.Model): + _inherit = "sale.order" + + pending_partner_coupon_count = fields.Integer( + compute="_compute_pending_partner_coupon_count", compute_sudo=True, + ) + + def _partner_coupon_domain(self): + """For compatibility with sale_coupon_apply_commercial_partner""" + return [("partner_id", "=", self.partner_id.id)] + + def _pending_coupon_domain(self): + """Override to do a broader search""" + return expression.AND( + [ + [("state", "=", "new"), ("order_id", "!=", self.id)], + self._partner_coupon_domain(), + ] + ) + + @api.depends("partner_id") + def _compute_pending_partner_coupon_count(self): + """Give a hint to the salesman about pending coupons for this parnter""" + self.pending_partner_coupon_count = 0 + for sale in self.filtered("partner_id"): + sale.pending_partner_coupon_count = self.env["sale.coupon"].search_count( + sale._pending_coupon_domain() + ) + + def action_view_pending_partner_coupons(self): + """View partner pending coupons""" + self.ensure_one() + coupon_obj = self.env["sale.coupon"] + # Done for compatibility sake with sales_team_security + if self.user_has_groups("sales_team.group_sale_salesman"): + coupon_obj = coupon_obj.sudo() + pending_partner_coupon_ids = coupon_obj._search(self._pending_coupon_domain()) + return { + "type": "ir.actions.act_window", + "name": _( + "Coupons pending for %(customer)s" % {"customer": self.partner_id.name} + ), + "view_mode": "kanban,form", + "res_model": "sale.coupon", + "target": "current", + "context": {"active_id": self.id, "active_model": "sale.order"}, + "domain": [("id", "in", pending_partner_coupon_ids)], + } diff --git a/sale_coupon_order_pending/readme/CONTRIBUTORS.rst b/sale_coupon_order_pending/readme/CONTRIBUTORS.rst new file mode 100644 index 000000000..94b6ba953 --- /dev/null +++ b/sale_coupon_order_pending/readme/CONTRIBUTORS.rst @@ -0,0 +1,3 @@ +* `Tecnativa `_: + + * David Vidal diff --git a/sale_coupon_order_pending/readme/DESCRIPTION.rst b/sale_coupon_order_pending/readme/DESCRIPTION.rst new file mode 100644 index 000000000..6e5d46c8a --- /dev/null +++ b/sale_coupon_order_pending/readme/DESCRIPTION.rst @@ -0,0 +1,2 @@ +This module allows the salesmen to tell if there are pending coupons that customer can +enjoy in his sales order. diff --git a/sale_coupon_order_pending/readme/USAGE.rst b/sale_coupon_order_pending/readme/USAGE.rst new file mode 100644 index 000000000..f164379ce --- /dev/null +++ b/sale_coupon_order_pending/readme/USAGE.rst @@ -0,0 +1,7 @@ +To use this module, you need to: + +#. Generate some coupons for your partner. +#. Go to a quotation/sales order from that partner and a smart button will show that + there are pending coupons. +#. Click on the smart button and you'll be able to apply those which conditions are met + by the order. diff --git a/sale_coupon_order_pending/static/description/icon.png b/sale_coupon_order_pending/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ceb4e97a3807d994433d12cc5ba91a81b885259f GIT binary patch literal 7296 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 a>Hh(wcnJoRs!V?X0000 + + + + + +Pending Coupons + + + +
+

Pending Coupons

+ + +

Beta License: AGPL-3 OCA/sale-promotion Translate me on Weblate Try me on Runbot

+

This module allows the salesmen to tell if there are pending coupons that customer can +enjoy in his sales order.

+

Table of contents

+ +
+

Usage

+

To use this module, you need to:

+
    +
  1. Generate some coupons for your partner.
  2. +
  3. Go to a quotation/sales order from that partner and a smart button will show that +there are pending coupons.
  4. +
  5. Click on the smart button and you’ll be able to apply those which conditions are met +by the order.
  6. +
+
+
+

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 smashing 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/sale-promotion project on GitHub.

+

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

+
+
+
+ + diff --git a/sale_coupon_order_pending/tests/__init__.py b/sale_coupon_order_pending/tests/__init__.py new file mode 100644 index 000000000..91fe46186 --- /dev/null +++ b/sale_coupon_order_pending/tests/__init__.py @@ -0,0 +1 @@ +from . import test_sale_coupon_order_pending diff --git a/sale_coupon_order_pending/tests/test_sale_coupon_order_pending.py b/sale_coupon_order_pending/tests/test_sale_coupon_order_pending.py new file mode 100644 index 000000000..da15b7b19 --- /dev/null +++ b/sale_coupon_order_pending/tests/test_sale_coupon_order_pending.py @@ -0,0 +1,45 @@ +# Copyright 2023 Tecnativa - David Vidal +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +from odoo.tests import Form, SavepointCase + + +class TestSaleCouponOrderPending(SavepointCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.partner = cls.env["res.partner"].create({"name": "Mr. Odoo"}) + cls.other_partner = cls.partner.copy({"name": "Mr. OCA"}) + coupon_program_form = Form( + cls.env["sale.coupon.program"], + view="sale_coupon.sale_coupon_program_view_form", + ) + coupon_program_form.name = "Test Pending Coupons" + cls.code_promotion_program = coupon_program_form.save() + cls.env["sale.coupon.generate"].with_context( + active_id=cls.code_promotion_program.id + ).create( + { + "generation_type": "nbr_customer", + "partners_domain": ( + f"[('id', 'in', {(cls.partner + cls.other_partner).ids})]" + ), + } + ).generate_coupon() + cls.product_1 = cls.env["product.product"].create( + {"name": "Test 1", "sale_ok": True, "list_price": 50} + ) + sale_form = Form(cls.env["sale.order"]) + sale_form.partner_id = cls.partner + with sale_form.order_line.new() as line_form: + line_form.product_id = cls.product_1 + line_form.product_uom_qty = 2 + cls.sale = sale_form.save() + + def test_coupon_order_pending(self): + self.assertEqual(self.sale.pending_partner_coupon_count, 1) + action = self.sale.action_view_pending_partner_coupons() + pending_coupon = self.env["sale.coupon"].search(action["domain"]) + pending_coupon = pending_coupon.with_context(action["context"]) + self.assertTrue(pending_coupon.can_be_applied_to_order) + pending_coupon.action_apply_partner_coupon() + self.assertEqual(self.sale.applied_coupon_ids, pending_coupon) diff --git a/sale_coupon_order_pending/views/coupon_coupon_views.xml b/sale_coupon_order_pending/views/coupon_coupon_views.xml new file mode 100644 index 000000000..97ad55fd5 --- /dev/null +++ b/sale_coupon_order_pending/views/coupon_coupon_views.xml @@ -0,0 +1,50 @@ + + + + sale.coupon + + + + + + + + +
+
+
+ + + + +
+
+
+
+ Discount:
+
+
+ +
+
+
+
+
+
+
diff --git a/sale_coupon_order_pending/views/sale_order_views.xml b/sale_coupon_order_pending/views/sale_order_views.xml new file mode 100644 index 000000000..5d538fc58 --- /dev/null +++ b/sale_coupon_order_pending/views/sale_order_views.xml @@ -0,0 +1,25 @@ + + + + + sale.order + + + + + + + + diff --git a/setup/sale_coupon_order_pending/odoo/addons/sale_coupon_order_pending b/setup/sale_coupon_order_pending/odoo/addons/sale_coupon_order_pending new file mode 120000 index 000000000..d383db8d2 --- /dev/null +++ b/setup/sale_coupon_order_pending/odoo/addons/sale_coupon_order_pending @@ -0,0 +1 @@ +../../../../sale_coupon_order_pending \ No newline at end of file diff --git a/setup/sale_coupon_order_pending/setup.py b/setup/sale_coupon_order_pending/setup.py new file mode 100644 index 000000000..28c57bb64 --- /dev/null +++ b/setup/sale_coupon_order_pending/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +)