Skip to content

Commit

Permalink
[14.0][ADD] sale_coupon_criteria_order_based
Browse files Browse the repository at this point in the history
  • Loading branch information
diga committed May 28, 2022
1 parent 2fbfb06 commit 9684f68
Show file tree
Hide file tree
Showing 16 changed files with 259 additions and 0 deletions.
35 changes: 35 additions & 0 deletions sale_coupon_criteria_order_based/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
**This file is going to be generated by oca-gen-addon-readme.**

*Manual changes will be overwritten.*

Please provide content in the ``readme`` directory:

* **DESCRIPTION.rst** (required)
* INSTALL.rst (optional)
* CONFIGURE.rst (optional)
* **USAGE.rst** (optional, highly recommended)
* DEVELOP.rst (optional)
* ROADMAP.rst (optional)
* HISTORY.rst (optional, recommended)
* **CONTRIBUTORS.rst** (optional, highly recommended)
* CREDITS.rst (optional)

Content of this README will also be drawn from the addon manifest,
from keys such as name, authors, maintainers, development_status,
and license.

A good, one sentence summary in the manifest is also highly recommended.


Automatic changelog generation
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

`HISTORY.rst` can be auto generated using `towncrier <https://pypi.org/project/towncrier>`_.

Just put towncrier compatible changelog fragments into `readme/newsfragments`
and the changelog file will be automatically generated and updated when a new fragment is added.

Please refer to `towncrier` documentation to know more.

NOTE: the changelog will be automatically generated when using `/ocabot merge $option`.
If you need to run it manually, refer to `OCA/maintainer-tools README <https://github.com/OCA/maintainer-tools>`_.
1 change: 1 addition & 0 deletions sale_coupon_criteria_order_based/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import models
16 changes: 16 additions & 0 deletions sale_coupon_criteria_order_based/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Copyright 2022 Ooops404
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

{
"name": "Sales Coupon based on Sales Order values",
"version": "14.0.1.0.0",
"summary": "Allows to set a sales order related domain for coupon",
"author": "Ooops404, Cetmix, Odoo Community Association (OCA)",
"contributors": "Ooops404, Cetmix",
"license": "AGPL-3.0",
"category": "Sale",
"website": "https://github.com/OCA/sale-promotion",
"depends": ["sale_coupon"],
"external_dependencies": {},
"data": ["views/coupon_program_view.xml"],
}
3 changes: 3 additions & 0 deletions sale_coupon_criteria_order_based/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from . import coupon_rule
from . import coupon_program
from . import coupon_coupon
14 changes: 14 additions & 0 deletions sale_coupon_criteria_order_based/models/coupon_coupon.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Copyright 2022 Ooops404
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

from odoo import _, models


class CouponCoupon(models.Model):
_inherit = "coupon.coupon"

def _check_coupon_code(self, order):
message = super()._check_coupon_code(order)
if not self.program_id._is_valid_order(order):
message = {"error": _("The order doesn't have access to this reward.")}
return message
59 changes: 59 additions & 0 deletions sale_coupon_criteria_order_based/models/coupon_program.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Copyright 2022 Ooops404
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

import ast

from odoo import _, api, fields, models


class CouponProgram(models.Model):
_inherit = "coupon.program"

rule_order_domain = fields.Char(
string="Based on Order",
help="Coupon program will work for the order with selected domain only",
)

def _is_valid_order(self, order):
"""
Check that we can apply the coupon for current order
"""
if self.rule_order_domain and self.rule_order_domain != "[]":
domain = ast.literal_eval(self.rule_order_domain)
return bool(order.filtered_domain(domain))
else:
return True

def _check_promo_code(self, order, coupon_code):
message = super()._check_promo_code(order, coupon_code)
if not self._is_valid_order(order):
message = {"error": _("The order doesn't have access to this reward.")}
return message

@api.model
def _filter_programs_from_common_rules(self, order, next_order=False):
programs = super()._filter_programs_from_common_rules(
order, next_order=next_order
)

# Order requirement should not be checked if the coupon got generated by
# a promotion program
# (the requirement should have only be checked to generate the coupon)
if not next_order and programs:
programs = programs._filter_programs_on_order(order)

programs_curr_order = programs.filtered(
lambda p: p.promo_applicability == "on_current_order"
)
programs = programs.filtered(lambda p: p.promo_applicability == "on_next_order")
if programs_curr_order:
# Checking if rewards are in the SO should not be performed for
# rewards on_next_order
programs += programs_curr_order._filter_not_ordered_reward_programs(order)
return programs

def _filter_programs_on_order(self, order):
"""
Filter all programs by order based domain
"""
return self.filtered(lambda program: program._is_valid_order(order))
13 changes: 13 additions & 0 deletions sale_coupon_criteria_order_based/models/coupon_rule.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Copyright 2022 Ooops404
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

from odoo import fields, models


class CouponRule(models.Model):
_inherit = "coupon.rule"

rule_order_domain = fields.Char(
string="Based on Order",
help="Coupon program will work for the order with selected domain only",
)
2 changes: 2 additions & 0 deletions sale_coupon_criteria_order_based/readme/CONTRIBUTORS.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
* Ooops404 <https://www.ooops404.com/>
* Cetmix <https://cetmix.com/>
4 changes: 4 additions & 0 deletions sale_coupon_criteria_order_based/readme/DESCRIPTION.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
This module add and option to configure your coupon conditions based on
the Sales Order values.

Example: "If Sales Team is 'Europe' apply the following discount'
5 changes: 5 additions & 0 deletions sale_coupon_criteria_order_based/readme/USAGE.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Open or create a new Promotion Program in the **Sales/Products/Promotion Programs** menu.

In *Conditions* section the following new option is available:

* **Based on Order** configure an order-based domain to apply the promotion
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions sale_coupon_criteria_order_based/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import test_sale_coupon_criteria_order_based
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# Copyright 2022 Ooops404
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

from odoo.addons.sale_coupon.tests.common import TestSaleCouponCommon


class TestSaleCouponCriteriaOrderBased(TestSaleCouponCommon):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.env = cls.env(context=dict(cls.env.context, tracking_disable=True))

def test_program_rules_order_based(self):
"""
Check program rules based on order domain
"""
partner_test = self.env["res.partner"].create(
{
"name": "Test",
"email": "[email protected]",
}
)
user_test = (
self.env["res.users"]
.with_context(no_reset_password=True)
.create(
{
"login": "test",
"password": "test",
"partner_id": partner_test.id,
"groups_id": [(6, 0, [self.env.ref("base.group_user").id])],
}
)
)
# Update program order domain. The program should be applied for order
# if Salesperson of the order is 'Test' user
self.immediate_promotion_program.write(
{"rule_order_domain": "[('user_id.id', '=', %s)]" % (user_test.id)}
)
order = self.empty_order
order.write(
{
"order_line": [
(
0,
False,
{
"product_id": self.product_A.id,
"name": "1 Product A",
"product_uom": self.uom_unit.id,
"product_uom_qty": 1.0,
},
),
(
0,
False,
{
"product_id": self.product_B.id,
"name": "2 Product B",
"product_uom": self.uom_unit.id,
"product_uom_qty": 1.0,
},
),
]
}
)
order.recompute_coupon_lines()
self.assertEqual(
len(order.order_line.ids),
2,
"The promo offer shouldn't have been applied.",
)
order.user_id = user_test.id
order.recompute_coupon_lines()
self.assertEqual(
len(order.order_line.ids),
3,
"The promo offer should have been applied.",
)
20 changes: 20 additions & 0 deletions sale_coupon_criteria_order_based/views/coupon_program_view.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>

<record id="coupon_program_view_promo_program_form" model="ir.ui.view">
<field name="name">coupon.program.view.form</field>
<field name="model">coupon.program</field>
<field name="inherit_id" ref="coupon.coupon_program_view_promo_program_form" />
<field name="arch" type="xml">
<field name="rule_partners_domain" position="after">
<field
name="rule_order_domain"
placeholder="Select order"
widget="domain"
options="{'model': 'sale.order', 'in_dialog': true}"
/>
</field>
</field>
</record>

</odoo>
6 changes: 6 additions & 0 deletions setup/sale_coupon_criteria_order_based/setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import setuptools

setuptools.setup(
setup_requires=['setuptools-odoo'],
odoo_addon=True,
)

0 comments on commit 9684f68

Please sign in to comment.