Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[17.0][MIG] sale_coupon_criteria_order_based #228

Open
wants to merge 17 commits into
base: 17.0
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 102 additions & 0 deletions sale_loyalty_criteria_order_based/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
========================================
Sales Coupon based on Sales Order values
========================================

..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:979b0c094347147f5111cfc8288b9cc8e5881d909d64fb41c068cc4f2ab4f187
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

.. |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/17.0/sale_loyalty_criteria_order_based
: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-17-0/sale-promotion-17-0-sale_loyalty_criteria_order_based
: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/sale-promotion&target_branch=17.0
:alt: Try me on Runboat

|badge1| |badge2| |badge3| |badge4| |badge5|

This module adds an option to configure your **Loyalty Program** and add
additional constraints based on **Sales Order** values.

Example: "If Sales Team is 'Europe' grant one point for the program"

**Table of contents**

.. contents::
:local:

Usage
=====

Open or create a new Loyalty Program in the **Sales/Products/Discount &
Loyalty** menu.

There's two ways to add a condition based on orders:

- On the program itself, allowing to define ``global`` conditions (valid
for all rules)
→ Find and edit the **Based on Order** field on the **Loyalty
Program** form view.
- On the rule, allowing to define conditions valid for a given rule only
→ Open or create a new **Loyalty Rule**, and edit the **Based on
Order** field.

Bug Tracker
===========

Bugs are tracked on `GitHub Issues <https://github.com/OCA/sale-promotion/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 <https://github.com/OCA/sale-promotion/issues/new?body=module:%20sale_loyalty_criteria_order_based%0Aversion:%2017.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.

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

Credits
=======

Authors
-------

* Ooops404
* Cetmix

Contributors
------------

- Ooops404 <https://www.ooops404.com/>
- Cetmix <https://cetmix.com/>
- `Tecnativa <https://www.tecnativa.com>`__

- Pilar Vargas

- MmeQuignon <[email protected]>

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 <https://github.com/OCA/sale-promotion/tree/17.0/sale_loyalty_criteria_order_based>`_ project on GitHub.

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
1 change: 1 addition & 0 deletions sale_loyalty_criteria_order_based/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import models
18 changes: 18 additions & 0 deletions sale_loyalty_criteria_order_based/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Copyright 2022 Ooops404
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

{
"name": "Sales Coupon based on Sales Order values",
"version": "17.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",
"category": "Sale",
"website": "https://github.com/OCA/sale-promotion",
"depends": ["sale_loyalty"],
"data": [
"views/loyalty_program.xml",
"views/loyalty_rule.xml",
],
}
3 changes: 3 additions & 0 deletions sale_loyalty_criteria_order_based/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from . import sale_order
from . import loyalty_rule
from . import loyalty_program
34 changes: 34 additions & 0 deletions sale_loyalty_criteria_order_based/models/loyalty_program.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Copyright 2022 Ooops404
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

import ast

from odoo import _, api, fields, models
from odoo.exceptions import UserError
from odoo.osv.expression import expression


class LoyaltyProgram(models.Model):
_inherit = "loyalty.program"

rule_order_domain = fields.Char(string="Based on Order", default="[]")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where are you going to apply the criteria? At the rule level or at the program level?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't it make more sense to use a M2o on ir.filter in order to make it reusable between different programs?


@api.constrains("rule_order_domain")
def _constrain_rule_order_domain(self):
model = self.env["sale.order"]
for program in self:
try:
domain = ast.literal_eval(program.rule_order_domain)
# Ensuring that domain is valid for sale.order
expression(domain, model)
except Exception as e:
raise UserError(_("Invalid domain on program")) from e

def _is_valid_order(self, order):
"""Check that we can apply the program on current order"""
self.ensure_one()
order.ensure_one()
domain = ast.literal_eval(self.rule_order_domain)
if domain:
return bool(order.filtered_domain(domain))
return True
35 changes: 35 additions & 0 deletions sale_loyalty_criteria_order_based/models/loyalty_rule.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Copyright 2022 Ooops404
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
# Copyright 2024 Camptocamp SA
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import ast

from odoo import _, api, fields, models
from odoo.exceptions import UserError
from odoo.osv.expression import expression


class LoyaltyRule(models.Model):
_inherit = "loyalty.rule"

rule_order_domain = fields.Char(string="Based on Order", default="[]")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where are you going to apply the criteria? At the rule level or at the program level?


@api.constrains("rule_order_domain")
def _constrain_rule_order_domain(self):
model = self.env["sale.order"]
for rule in self:
try:
domain = ast.literal_eval(rule.rule_order_domain)
# Ensuring that domain is valid for sale.order
expression(domain, model)
except Exception as e:
raise UserError(_("Invalid domain on rule")) from e

def _is_valid_order(self, order):
"""Check that we can apply the rule on current order"""
self.ensure_one()
order.ensure_one()
domain = ast.literal_eval(self.rule_order_domain)
if domain:
return bool(order.filtered_domain(domain))
return True
28 changes: 28 additions & 0 deletions sale_loyalty_criteria_order_based/models/sale_order.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Copyright 2024 Camptocamp SA
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)

from odoo import _, models
from odoo.osv.expression import AND


class SaleOrder(models.Model):
_inherit = "sale.order"

def _try_apply_code(self, code):
self.ensure_one()
base_domain = self._get_trigger_domain()
domain = AND([base_domain, [("mode", "=", "with_code"), ("code", "=", code)]])
rule = self.env["loyalty.rule"].search(domain)

Check warning on line 15 in sale_loyalty_criteria_order_based/models/sale_order.py

View check run for this annotation

Codecov / codecov/patch

sale_loyalty_criteria_order_based/models/sale_order.py#L12-L15

Added lines #L12 - L15 were not covered by tests
if rule and rule._is_valid_order(self):
return super()._try_apply_code(code)
return {

Check warning on line 18 in sale_loyalty_criteria_order_based/models/sale_order.py

View check run for this annotation

Codecov / codecov/patch

sale_loyalty_criteria_order_based/models/sale_order.py#L17-L18

Added lines #L17 - L18 were not covered by tests
"error": _(
"This code (%(code)s) is not available for this order.", code=code
)
}

def _try_apply_program(self, program, coupon):
self.ensure_one()

Check warning on line 25 in sale_loyalty_criteria_order_based/models/sale_order.py

View check run for this annotation

Codecov / codecov/patch

sale_loyalty_criteria_order_based/models/sale_order.py#L25

Added line #L25 was not covered by tests
if program and program._is_valid_order(self):
return super()._try_apply_program(program, coupon)
return {"error": _("The program is not available for this order.")}

Check warning on line 28 in sale_loyalty_criteria_order_based/models/sale_order.py

View check run for this annotation

Codecov / codecov/patch

sale_loyalty_criteria_order_based/models/sale_order.py#L27-L28

Added lines #L27 - L28 were not covered by tests
3 changes: 3 additions & 0 deletions sale_loyalty_criteria_order_based/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[build-system]
requires = ["whool"]
build-backend = "whool.buildapi"
5 changes: 5 additions & 0 deletions sale_loyalty_criteria_order_based/readme/CONTRIBUTORS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
- Ooops404 \<<https://www.ooops404.com/>\>
- Cetmix \<<https://cetmix.com/>\>
- [Tecnativa](https://www.tecnativa.com)
- Pilar Vargas
- MmeQuignon \<[email protected]\>
3 changes: 3 additions & 0 deletions sale_loyalty_criteria_order_based/readme/DESCRIPTION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
This module adds an option to configure your **Loyalty Program** and add additional constraints based on **Sales Order** values.

Example: "If Sales Team is 'Europe' grant one point for the program"
7 changes: 7 additions & 0 deletions sale_loyalty_criteria_order_based/readme/USAGE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Open or create a new Loyalty Program in the **Sales/Products/Discount & Loyalty** menu.

There's two ways to add a condition based on orders:
- On the program itself, allowing to define `global` conditions (valid for all rules)\
&rarr; Find and edit the **Based on Order** field on the **Loyalty Program** form view.
- On the rule, allowing to define conditions valid for a given rule only\
&rarr; Open or create a new **Loyalty Rule**, and edit the **Based on Order** field.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading