Skip to content

Commit

Permalink
[MIG] sale_coupon_multi_gift>sale_loyalty_multi_gift: Migration to 16.0
Browse files Browse the repository at this point in the history
TT44348
  • Loading branch information
pilarvargas-tecnativa committed Jan 10, 2024
1 parent c865151 commit 088c1f7
Show file tree
Hide file tree
Showing 14 changed files with 228 additions and 298 deletions.
19 changes: 10 additions & 9 deletions sale_loyalty_multi_gift/README.rst
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
===========================
Coupons multi gift in sales
===========================
=======================
Sale Loyalty Multi Gift
=======================

..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:7f3497a24d35eeb0b15943041a8537f46b4eb32153e9451598ca64a9e5bf4e54
!! source digest: sha256:28e58ffa1dce31e6123f0ae20b41b27ef347e241906cf2a913f9d9163e5673bf
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
Expand All @@ -17,13 +17,13 @@ Coupons multi gift in sales
: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/15.0/sale_coupon_multi_gift
:target: https://github.com/OCA/sale-promotion/tree/16.0/sale_loyalty_multi_gift
: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-15-0/sale-promotion-15-0-sale_coupon_multi_gift
:target: https://translation.odoo-community.org/projects/sale-promotion-16-0/sale-promotion-16-0-sale_loyalty_multi_gift
: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=15.0
:target: https://runboat.odoo-community.org/builds?repo=OCA/sale-promotion&target_branch=16.0
:alt: Try me on Runboat

|badge1| |badge2| |badge3| |badge4| |badge5|
Expand Down Expand Up @@ -56,7 +56,7 @@ 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_coupon_multi_gift%0Aversion:%2015.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
`feedback <https://github.com/OCA/sale-promotion/issues/new?body=module:%20sale_loyalty_multi_gift%0Aversion:%2016.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.

Expand All @@ -74,6 +74,7 @@ Contributors
* `Tecnativa <https://www.tecnativa.com>`_:

* David Vidal
* Pilar Vargas

* `Domatix <https://www.domatix.com>`_:

Expand All @@ -100,6 +101,6 @@ Current `maintainer <https://odoo-community.org/page/maintainer-role>`__:

|maintainer-chienandalu|

This module is part of the `OCA/sale-promotion <https://github.com/OCA/sale-promotion/tree/15.0/sale_coupon_multi_gift>`_ project on GitHub.
This module is part of the `OCA/sale-promotion <https://github.com/OCA/sale-promotion/tree/16.0/sale_loyalty_multi_gift>`_ project on GitHub.

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
6 changes: 3 additions & 3 deletions sale_loyalty_multi_gift/__manifest__.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
# Copyright 2021 Tecnativa - David Vidal
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
{
"name": "Coupons multi gift in sales",
"name": "Sale Loyalty Multi Gift",
"summary": "Allows to configure multiple gift rewards per promotion in sales",
"version": "15.0.1.0.0",
"version": "16.0.1.0.0",
"development_status": "Beta",
"category": "Sale",
"website": "https://github.com/OCA/sale-promotion",
"author": "Tecnativa, Odoo Community Association (OCA)",
"maintainers": ["chienandalu"],
"license": "AGPL-3",
"depends": ["sale_coupon_order_line_link", "coupon_multi_gift"],
"depends": ["sale_loyalty_order_line_link", "loyalty_multi_gift"],
"data": ["security/ir.model.access.csv"],
}
2 changes: 1 addition & 1 deletion sale_loyalty_multi_gift/models/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
from . import coupon_program
# from . import coupon_program
from . import sale_order
39 changes: 0 additions & 39 deletions sale_loyalty_multi_gift/models/coupon_program.py

This file was deleted.

165 changes: 54 additions & 111 deletions sale_loyalty_multi_gift/models/sale_order.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,16 @@
# Copyright 2021 Tecnativa - David Vidal
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
import random

from odoo import _, fields, models
from odoo.fields import first
from odoo.fields import Command, first
from odoo.tools.float_utils import float_round


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

def _get_paid_order_lines(self):
"""Add reward lines produced by multi gift promotions"""
lines = super()._get_paid_order_lines()
free_reward_products = (
self.env["coupon.program"]
.search([("reward_type", "=", "multi_gift")])
.mapped("coupon_multi_gift_ids.reward_product_ids")
)
free_reward_product_lines = self.order_line.filtered(
lambda x: x.is_reward_line and x.product_id in free_reward_products
)
return lines | free_reward_product_lines

def _get_reward_values_multi_gift_line(self, reward_line, program):
def _get_reward_values_multi_gift_line(self, reward_line, reward, coupon):
"""Multi Gift reward rules. For every gift reward rule, we'll create a new
sale order line flagged as reward line with a 100% discount"""

Expand All @@ -40,6 +30,24 @@ def _execute_onchanges(records, field_name):
& reward_line.reward_product_ids
)
reward_product_id = optional_product or first(reward_line.reward_product_ids)
taxes = self.fiscal_position_id.map_tax(
reward_product_id.taxes_id.filtered(
lambda t: t.company_id == self.company_id
)
)
points = self._get_real_points_for_coupon(coupon)
claimable_count = (
float_round(
points / reward.required_points,
precision_rounding=1,
rounding_method="DOWN",
)
if not reward.clear_wallet
else 1
)
cost = (
points if reward.clear_wallet else claimable_count * reward.required_points
)
# We prepare a new line and trigger the proper onchanges to ensure we get the
# right line values (price unit according to the customer pricelist, taxes, ect)
order_line = self.order_line.new(
Expand All @@ -52,30 +60,50 @@ def _execute_onchanges(records, field_name):
vals.update(
{
"is_reward_line": True,
"name": _("Free Product") + " - " + reward_product_id.name,
"name": _(
"Free Product - %(product)s",
product=reward_product_id.with_context(
display_default_code=False
).display_name,
),
"price_unit": reward_product_id.list_price,
"discount": 100,
"coupon_program_id": program.id,
"reward_id": reward.id,
"coupon_id": coupon.id,
"points_cost": cost,
"reward_identifier_code": str(random.getrandbits(32)),
"product_uom": reward_product_id.uom_id.id,
"sequence": max(
self.order_line.filtered(lambda x: not x.is_reward_line).mapped(
"sequence"
),
default=10,
)
+ 1,
"tax_id": [(Command.CLEAR, 0, 0)]
+ [(Command.LINK, tax.id, False) for tax in taxes],
"loyalty_program_id": reward.program_id.id,
"multi_gift_reward_line_id": reward_line.id,
"multi_gift_reward_line_id_option_product_id": reward_product_id.id,
}
)
return vals

def _get_reward_values_multi_gift(self, program):
def _get_reward_values_multi_gift(self, reward, coupon, **kwargs):
"""Wrapper to create the reward lines for a multi gift promotion"""
return [
self._get_reward_values_multi_gift_line(reward_line, program)
for reward_line in program.coupon_multi_gift_ids
self._get_reward_values_multi_gift_line(reward_line, reward, coupon)
for reward_line in reward.loyalty_multi_gift_ids
]

def _get_reward_line_values(self, program):
def _get_reward_line_values(self, reward, coupon, **kwargs):
"""Hook into the core method considering multi gift rewards"""
self.ensure_one()
self = self.with_context(lang=self.partner_id.lang)
program = program.with_context(lang=self.partner_id.lang)
if program.reward_type == "multi_gift":
return self._get_reward_values_multi_gift(program)
return super()._get_reward_line_values(program)
reward = reward.with_context(lang=self.partner_id.lang)
if reward.reward_type == "multi_gift":
return self._get_reward_values_multi_gift(reward, coupon, **kwargs)
return super()._get_reward_line_values(reward, coupon, **kwargs)

def _get_applicable_programs_multi_gift(self):
"""Wrapper to avoid long method name limitations"""
Expand All @@ -87,100 +115,15 @@ def _get_applicable_programs_multi_gift(self):
)
return programs

def _remove_invalid_reward_lines(self):
"""We have to put some logic redundancy here as the main method doesn't have
enough granularity to avoid deleting the lines belonging to the multi gift
programs when the promotions are updated. So the main module expects that the
promotion lines products match with the promotion discount product
(https://git.io/JWpoU) , which is not the approach in this module, where we add
extra lines with the reward products themselves and the proper price tag and
discount. So in this method override, we'll save those correct lines from the
pyre via context that the unlink method will properly catch. We also have to
remove the proper invalid lines that wouldn't be detected"""
self.ensure_one()
# This part is a repetition of the logic so we can get the right programs
applied_programs = self._get_applied_programs()
applicable_programs = self.env["coupon.program"]
if applied_programs:
applicable_programs = self._get_applicable_programs_multi_gift()
programs_to_remove = applied_programs - applicable_programs
# We're only interested in the Multi Gift programs
multi_gift_applied_programs = applied_programs.filtered(
lambda x: x.reward_type == "multi_gift"
)
# These will be the ones to keep
valid_lines = self.order_line.filtered(
lambda x: x.is_reward_line
and x.coupon_program_id in multi_gift_applied_programs
)
multi_gift_programs_to_remove = programs_to_remove.filtered(
lambda x: x.reward_type == "multi_gift"
)
if multi_gift_programs_to_remove:
# Invalidate the generated coupons which we are not eligible anymore
self.generated_coupon_ids.filtered(
lambda x: x.program_id in multi_gift_programs_to_remove
).write({"state": "expired"})
# Detect and remove the proper unvalid program order lines
self.order_line.filtered(
lambda x: x.is_reward_line
and x.coupon_program_id in multi_gift_programs_to_remove
).unlink()
# We'll catch the context in the subsequent unlink() method
return super(
SaleOrder, self.with_context(valid_multi_gift_lines=valid_lines.ids)
)._remove_invalid_reward_lines()

def _update_existing_reward_lines(self):
"""We need to match `multi gift` programs with their discount product"""
self.ensure_one()
res = super(
SaleOrder, self.with_context(only_reward_lines=True)
)._update_existing_reward_lines()
applied_programs = self._get_applied_programs_with_rewards_on_current_order()
for program in applied_programs.filtered(
lambda x: x.reward_type == "multi_gift"
):
for reward_line in program.coupon_multi_gift_ids:
lines = self.order_line.filtered(
lambda line: line.multi_gift_reward_line_id == reward_line
and line.is_reward_line
and line.coupon_program_id == program
)
applied_product = lines.multi_gift_reward_line_id_option_product_id
for product in applied_product:
reward_line_options = {reward_line.id: product.id}
values = self.with_context(
reward_line_options=reward_line_options
)._get_reward_values_multi_gift_line(reward_line, program)
# Remove reward line if price or qty equal to 0
if values.get("product_uom_qty") and values.get("price_unit"):
lines.write(values)
else:
lines.unlink()
return res


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

multi_gift_reward_line_id = fields.Many2one(
comodel_name="coupon.reward.product_line",
comodel_name="loyalty.reward.product_line",
readonly=True,
)
multi_gift_reward_line_id_option_product_id = fields.Many2one(
comodel_name="product.product",
readonly=True,
)

def unlink(self):
"""Avoid unlinking valid multi gift lines since they aren't linked to the
discount product of the promotion program"""
if not self.env.context.get("valid_multi_gift_lines"):
return super().unlink()
return super(
SaleOrderLine,
self.filtered(
lambda x: x.id not in self.env.context.get("valid_multi_gift_lines")
),
).unlink()
1 change: 1 addition & 0 deletions sale_loyalty_multi_gift/readme/CONTRIBUTORS.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
* `Tecnativa <https://www.tecnativa.com>`_:

* David Vidal
* Pilar Vargas

* `Domatix <https://www.domatix.com>`_:

Expand Down
4 changes: 2 additions & 2 deletions sale_loyalty_multi_gift/security/ir.model.access.csv
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
id,name,model_id/id,group_id/id,perm_read,perm_write,perm_create,perm_unlink
access_multi_gift_salesman,salesman,coupon_multi_gift.model_coupon_reward_product_line,sales_team.group_sale_salesman,1,0,0,0
access_multi_gift_manager,multi_gift manager,coupon_multi_gift.model_coupon_reward_product_line,sales_team.group_sale_manager,1,1,1,1
access_multi_gift_salesman,salesman,loyalty_multi_gift.model_loyalty_reward_product_line,sales_team.group_sale_salesman,1,0,0,0
access_multi_gift_manager,multi_gift manager,loyalty_multi_gift.model_loyalty_reward_product_line,sales_team.group_sale_manager,1,1,1,1
Loading

0 comments on commit 088c1f7

Please sign in to comment.