Skip to content

Commit

Permalink
Merge PR #1475 into 16.0
Browse files Browse the repository at this point in the history
Signed-off-by simahawk
  • Loading branch information
OCA-git-bot committed Dec 14, 2023
2 parents d09bb0f + 8b449ce commit d92c5fe
Show file tree
Hide file tree
Showing 6 changed files with 147 additions and 31 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
# Copyright 2023 Camptocamp (<https://www.camptocamp.com>).
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
import logging
from functools import partial

from odoo import Command, models
from odoo import Command, _, models

_logger = logging.getLogger(__name__)


class OrderMixin(models.AbstractModel):
Expand Down Expand Up @@ -30,6 +34,7 @@ def update_order_container_deposit_quantity(self):
if self.env.context.get("skip_update_container_deposit"):
return
self = self.with_context(skip_update_container_deposit=True)
line_ids_to_delete = []
for order in self:
# Lines to compute container deposit
lines_to_comp_deposit = order[self._get_order_line_field()].filtered(
Expand All @@ -41,36 +46,63 @@ def update_order_container_deposit_quantity(self):
deposit_container_qties = (
lines_to_comp_deposit._get_order_lines_container_deposit_quantities()
)
values_lst = []
for line in self[self._get_order_line_field()]:
if not line.is_container_deposit:
continue
qty, qty_dlvd_rcvd = deposit_container_qties.pop(
line["product_id"], [False, False]
)
if not qty:
new_vals = {
line._get_product_qty_field(): 0,
}
if order.state == "draft":
line.unlink()
else:
line.write(
{
line._get_product_qty_field(): 0,
}
# values_lst.append(Command.delete(line.id))
line_ids_to_delete.append(line.id)
# TODO: check if it is needed for UI only
new_vals["name"] = _("[DEL] %(name)s", name=line.name)
# else:
values_lst.append(
Command.update(
line.id,
new_vals,
)
)

else:
line.write(
{
line._get_product_qty_field(): qty,
line._get_product_qty_delivered_received_field(): qty_dlvd_rcvd,
}
values_lst.append(
Command.update(
line.id,
{
line._get_product_qty_field(): qty,
line._get_product_qty_delivered_received_field(): qty_dlvd_rcvd,
},
)
)
values_lst = []
for product in deposit_container_qties:
if deposit_container_qties[product][0] > 0:
values = order.prepare_deposit_container_line(
product, deposit_container_qties[product][0]
)
values_lst.append(Command.create(values))
order.write({self._get_order_line_field(): values_lst})
# Schedule line to delete after commit to avoid caching issue w/ UI
if line_ids_to_delete:
self.env.cr.postcommit.add(
partial(
self._order_container_deposit_delete_lines_after_commit,
sorted(line_ids_to_delete),
)
)

def _order_container_deposit_delete_lines_after_commit(self, line_ids):
line_model = self._fields[self._get_order_line_field()].comodel_name
recs = self.env[line_model].browse(line_ids).exists()
recs.unlink()
_logger.debug("%s deleted after commit", recs)
# Needs an explicit commit as it runs after the original commit is done
self.env.cr.commit() # pylint: disable=invalid-commit

def copy(self, default=None):
return super(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
* Telmo Santos <[email protected]>
* Jacques-Etienne Baudoux (BCIM) <[email protected]>
* Simone Orsi <[email protected]>
2 changes: 0 additions & 2 deletions product_packaging_container_deposit/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,2 @@
from . import common
from . import fake_models
from . import test_product_packaging_container_deposit
from . import test_container_deposit_order_mixin
30 changes: 30 additions & 0 deletions product_packaging_container_deposit/tests/common.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Copyright 2023 Camptocamp (<https://www.camptocamp.com>).
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from contextlib import contextmanager
from unittest import mock

from odoo.tests import common

from odoo.addons.base.tests.common import DISABLED_MAIL_CONTEXT
Expand Down Expand Up @@ -84,3 +87,30 @@ def setUpClass(cls):
)
cls.pallet = cls.package_type_pallet.container_deposit_product_id
cls.box = cls.package_type_box.container_deposit_product_id

@contextmanager
def _check_delete_after_commit(self, lines):
"""Ensure lines are scheduled for deletion in post commit hook.
The method ``update_order_container_deposit_quantity``
will not delete lines immediately to avoid caching issues.
Hence, you can use this ctx manager as following:
with self._check_delete_after_commit(lines_to_delete):
order_line.write({"product_qty": 10})
to test that ``lines_to_delete`` records are marked as to be deleted
in the after commit hook.
"""
with mock.patch.object(type(self.env.cr.postcommit), "add") as mocked:
yield
for line in lines:
self.assertTrue(line.name.startswith("[DEL]"))
self.assertEqual(line[line._get_product_qty_field()], 0)
partial_func = mocked.call_args[0][0]
self.assertEqual(partial_func.args, (sorted(lines.ids),))
self.assertEqual(
partial_func.func.__name__,
"_order_container_deposit_delete_lines_after_commit",
)
1 change: 1 addition & 0 deletions product_packaging_container_deposit/tests/fake_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ class ContainerDepositOrderTest(models.Model):
name = fields.Char()
partner_id = fields.Many2one("res.partner")
company_id = fields.Many2one("res.company")
state = fields.Char()
order_line = fields.One2many(
"container.deposit.order.line.test", inverse_name="order_id"
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
# Copyright 2023 Camptocamp (<https://www.camptocamp.com>).
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from unittest import mock

from odoo_test_helper import FakeModelLoader

from odoo.tests.common import Form

from .common import Common


Expand All @@ -22,25 +26,25 @@ def setUpClass(cls):
ContainerDepositOrderLineTest,
)
)

def setUp(self):
super().setUp()
self.order = self.env["container.deposit.order.test"].create(
cls.order_model = cls.env[ContainerDepositOrderTest._name]
cls.line_model = cls.env[ContainerDepositOrderLineTest._name]
cls.order = cls.order_model.create(
{
"company_id": self.env.company.id,
"partner_id": self.env.ref("base.res_partner_12").id,
"company_id": cls.env.company.id,
"partner_id": cls.env.ref("base.res_partner_12").id,
"state": "draft",
}
)

def test_implemented_get_order_line_field(self):
self.assertEqual(
self.env["container.deposit.order.test"]._get_order_line_field(),
self.order_model._get_order_line_field(),
"order_line",
)

def test_implemented_get_product_qty_field(self):
self.assertEqual(
self.env["container.deposit.order.line.test"]._get_product_qty_field(),
self.line_model._get_product_qty_field(),
"product_qty",
)

Expand All @@ -49,7 +53,7 @@ def test_get_order_lines_container_deposit_quantities(self):
self.order.order_line._get_order_lines_container_deposit_quantities()
)
self.assertEqual(deposit_product_qties, {})
self.env["container.deposit.order.line.test"].create(
self.line_model.create(
{
"order_id": self.order.id,
"name": self.product_a.name,
Expand All @@ -71,7 +75,7 @@ def test_implemented_get_product_qty_delivered_received_field(self):
)

def test_product_container_deposit_order(self):
self.env["container.deposit.order.line.test"].create(
self.line_model.create(
{
"order_id": self.order.id,
"name": self.product_a.name,
Expand All @@ -93,7 +97,7 @@ def test_order_product_packaging_container_deposit_quantities_case1(self):
280 // 240 = 1 => add order line for 1 Pallet
280 // 24 (biggest PACK) => add order line for 11 boxes of 24
"""
self.env["container.deposit.order.line.test"].create(
self.line_model.create(
[
{
"order_id": self.order.id,
Expand Down Expand Up @@ -123,7 +127,7 @@ def test_order_product_packaging_container_deposit_quantities_case2(self):
280 // 240 = 1 => add order line for 1 Pallet
280 // 12 (forced packaging for Boxes) => add order line for 23 boxes of 12
"""
self.env["container.deposit.order.line.test"].create(
self.line_model.create(
{
"order_id": self.order.id,
"name": self.product_a.name,
Expand All @@ -142,7 +146,7 @@ def test_order_product_packaging_container_deposit_quantities_case3(self):
Case 3: Product A & Product B. Both have a deposit of 1 box of 24. Result:
Only one line for 2 boxes of 24
"""
self.env["container.deposit.order.line.test"].create(
self.line_model.create(
[
{
"order_id": self.order.id,
Expand Down Expand Up @@ -171,7 +175,7 @@ def test_order_product_packaging_container_deposit_quantities_case4(self):
1 order line with 2 boxes of 24 (System added)
+ 1 order line with 1 box (manually added)
"""
order_line = self.env["container.deposit.order.line.test"].create(
order_line = self.line_model.create(
{
"order_id": self.order.id,
"name": self.product_a.name,
Expand All @@ -190,7 +194,7 @@ def test_order_product_packaging_container_deposit_quantities_case4(self):
self.assertEqual(deposit_line.product_qty, 2.0)

# Add manually 1 box
self.env["container.deposit.order.line.test"].create(
self.line_model.create(
{
"order_id": self.order.id,
"name": self.package_type_box.container_deposit_product_id.name,
Expand All @@ -214,7 +218,7 @@ def test_order_product_packaging_container_deposit_quantities_case5(self):
Received 200 // 280 = 0 Pallet
Received 200 // 24 = 5 Boxes
"""
self.env["container.deposit.order.line.test"].create(
self.line_model.create(
[
{
"order_id": self.order.id,
Expand All @@ -236,3 +240,53 @@ def test_order_product_packaging_container_deposit_quantities_case5(self):
self.order.order_line[0].qty_delivered = 200
self.assertEqual(pallet_line.qty_delivered, 0)
self.assertEqual(box_line.qty_delivered, 8)

def test_confirmed_sale_product_packaging_container_deposit_quantities6(self):
"""Test deposit line is added deleted after reduce product_a quantity"""
order_line = self.line_model.create(
{
"order_id": self.order.id,
"name": self.product_a.name,
"product_id": self.product_a.id,
"product_qty": 240,
},
)
lines_to_delete = self.order.order_line.filtered(
lambda ol: ol.product_id == self.pallet or ol.product_id == self.box
)
with self._check_delete_after_commit(lines_to_delete):
order_line.write({"product_qty": 10})

def test_form(self):
"""Test add and delete container deposit lines on the fly"""
order_form = Form(self.order_model)
with order_form.order_line.new() as line:
line.product_id = self.product_a
line.product_qty = 280
order = order_form.save()
order.state = "draft"
with order_form.order_line.edit(0) as line:
line.product_qty = 10
lines_to_delete = order.order_line.filtered(
lambda ol: ol.product_id == self.pallet or ol.product_id == self.box
)
with self._check_delete_after_commit(lines_to_delete):
order_form.save()

def test_order_container_deposit_delete_lines_after_commit(self):
line = self.line_model.create(
{
"order_id": self.order.id,
"name": self.product_a.name,
"product_id": self.product_a.id,
"product_qty": 280,
"product_packaging_id": self.packaging[0].id,
},
)
# ensure that the post commit hook deletes lines
# however to preserve test isolation
# we have to prevent the explicit commit to take place
with mock.patch.object(type(self.env.cr), "commit") as mocked:
self.order._order_container_deposit_delete_lines_after_commit(line.ids)
self.assertFalse(line.exists())
mocked.assert_called()

0 comments on commit d92c5fe

Please sign in to comment.