Skip to content

Commit ef147b5

Browse files
[FIX] delivery_send_to_shipper_at_operation:
Keep delivery_notification_sent set on backorder
1 parent 2406552 commit ef147b5

File tree

3 files changed

+102
-20
lines changed

3 files changed

+102
-20
lines changed

delivery_send_to_shipper_at_operation/models/stock_picking.py

+42-16
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# Copyright 2021 Camptocamp SA
22
# Copyright 2023 Jacques-Etienne Baudoux (BCIM) <je@bcim.be>
3+
# Copyright 2024 Michael Tietz (MT Software) <mtietz@mt-software.de>
34
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
45

56
from lxml import etree
@@ -20,19 +21,31 @@ class StockPicking(models.Model):
2021
delivery_notification_sent = fields.Boolean(default=False, copy=False)
2122

2223
def _send_confirmation_email(self):
24+
picking_ids_skip_costs = []
2325
for picking in self:
24-
skip_delivery_cost = picking._handle_send_to_shipper_at_operation()
25-
picking = picking.with_context(skip_delivery_cost=skip_delivery_cost)
26-
super(StockPicking, picking)._send_confirmation_email()
26+
if not picking._is_send_to_shipper_at_operation():
27+
continue
28+
picking_ids_skip_costs.append(picking.id)
29+
picking.carrier_id = picking.ship_picking_id.carrier_id
30+
pickings_skip_costs = self.browse(picking_ids_skip_costs)
31+
if pickings_skip_costs:
32+
pickings_skip_costs._handle_send_to_shipper_at_operation()
33+
super(StockPicking, self - pickings_skip_costs)._send_confirmation_email()
2734

2835
def _handle_send_to_shipper_at_operation(self):
2936
"""Send the delivery notice to the carrier from a specific operation type.
3037
3138
We are only interested by sending the delivery notice, the delivery fee
3239
still have to be added to the SO by the ship operation.
33-
34-
Return True if the operation has send the delivery notice.
3540
"""
41+
super().with_context(skip_delivery_cost=True)._send_confirmation_email()
42+
for picking in self:
43+
related_ship = picking.ship_picking_id
44+
values = picking._prepare_values_send_to_ship_at_operation(related_ship)
45+
related_ship.write(values)
46+
47+
def _is_send_to_shipper_at_operation(self):
48+
"""Return True if the operation needs to send the delivery notice."""
3649
self.ensure_one()
3750
if not self.carrier_id:
3851
# If the current operation has no carrier defined, but a carrier
@@ -47,20 +60,23 @@ def _handle_send_to_shipper_at_operation(self):
4760
and self.picking_type_id
4861
in carrier.send_delivery_notice_picking_type_ids
4962
):
50-
self.carrier_id = carrier
51-
self.with_context(skip_delivery_cost=True).send_to_shipper()
52-
# Flag the current operation and the ship one.
53-
# Mandatory to not execute twice 'send_to_shipper' method
54-
self.delivery_notification_sent = True
55-
related_ship.delivery_notification_sent = True
56-
related_ship.carrier_price = self.carrier_price
57-
if not related_ship.carrier_tracking_ref:
58-
related_ship.carrier_tracking_ref = self.carrier_tracking_ref
59-
else:
60-
related_ship.carrier_tracking_ref += "," + self.carrier_tracking_ref
6163
return True
6264
return False
6365

66+
def _prepare_values_send_to_ship_at_operation(self, related_ship):
67+
self.ensure_one()
68+
related_ship.ensure_one()
69+
carrier_tracking_ref = related_ship.carrier_tracking_ref
70+
if carrier_tracking_ref:
71+
carrier_tracking_ref += "," + self.carrier_tracking_ref
72+
else:
73+
carrier_tracking_ref = self.carrier_tracking_ref
74+
return {
75+
"delivery_notification_sent": True,
76+
"carrier_price": self.carrier_price,
77+
"carrier_tracking_ref": carrier_tracking_ref,
78+
}
79+
6480
def send_to_shipper(self):
6581
# Do not send delivery notice to the carrier if it has already been sent
6682
# through a previous operation (like a pack)
@@ -111,3 +127,13 @@ def _fields_view_get_adapt_send_to_shipper_attrs(self, view_arch):
111127
)
112128
transfer_modifiers_to_node(modifiers, field)
113129
return etree.tostring(doc, encoding="unicode")
130+
131+
def _create_backorder(self):
132+
backorders = super()._create_backorder()
133+
for backorder in backorders:
134+
delivery_notification_sent = (
135+
backorder.backorder_id.delivery_notification_sent
136+
)
137+
if delivery_notification_sent:
138+
backorder.delivery_notification_sent = delivery_notification_sent
139+
return backorders

delivery_send_to_shipper_at_operation/readme/CONTRIBUTORS.rst

+1
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@
22
* `Trobz <https://trobz.com>`_:
33
* Nguyen Hoang Hiep <hiepnh@trobz.com>
44
* Jacques-Etienne Baudoux (BCIM) <je@bcim.be>
5+
* Michael Tietz (MT Software) <mtietz@mt-software.de>

delivery_send_to_shipper_at_operation/tests/test_send_to_shipper.py

+59-4
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
# Copyright 2021 Camptocamp SA
2+
# Copyright 2024 Michael Tietz (MT Software) <mtietz@mt-software.de>
23
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
34

45
from unittest import mock
56

67
from lxml import etree
78

8-
from odoo.tests.common import SavepointCase
9+
from odoo.tests.common import Form, SavepointCase
910
from odoo.tools.safe_eval import safe_eval
1011

1112
SEND_SHIPPING_RETURN_VALUE = [{"exact_price": 10.0, "tracking_number": "TEST"}]
@@ -82,10 +83,19 @@ def setUpClass(cls):
8283
)
8384
(cls.picking | cls.packing | cls.shipping).sale_id = cls.order
8485

85-
def _validate_picking(self, picking):
86+
def _validate_picking(self, picking, qty_done=None):
8687
for ml in picking.move_line_ids:
87-
ml.qty_done = ml.product_uom_qty
88-
picking._action_done()
88+
ml.qty_done = qty_done or ml.product_uom_qty
89+
action_data = picking.button_validate()
90+
if not action_data or action_data is True:
91+
return picking.browse()
92+
backorder_wizard = Form(
93+
self.env["stock.backorder.confirmation"].with_context(
94+
action_data["context"]
95+
)
96+
).save()
97+
backorder_wizard.process()
98+
return self.env["stock.picking"].search([("backorder_id", "=", picking.id)])
8999

90100
def test_send_to_shipper_on_ship(self):
91101
"""Check sending of delivery notification on ship.
@@ -195,3 +205,48 @@ def test_picking_fields_view_get(self):
195205
attrs_str = button_send_to_shipper.attrib["attrs"]
196206
attrs = safe_eval(attrs_str)
197207
self.assertIn(("delivery_notification_sent", "=", True), attrs["invisible"])
208+
209+
def test_send_to_shipper_on_partial_pack(self):
210+
"""Check if a backorder of a transfer, where the delivery notification is already sent
211+
keeps the delivery notification sent set.
212+
"""
213+
with mock.patch.object(
214+
type(self.carrier_on_pack),
215+
"send_shipping",
216+
return_value=SEND_SHIPPING_RETURN_VALUE,
217+
):
218+
self.shipping.carrier_id = self.carrier_on_pack
219+
self._validate_picking(self.picking)
220+
pack_backorder = self._validate_picking(self.packing, 5)
221+
self.assertTrue(self.shipping.delivery_notification_sent)
222+
self.assertFalse(pack_backorder.delivery_notification_sent)
223+
self._validate_picking(pack_backorder, 5)
224+
self.assertTrue(self.shipping.delivery_notification_sent)
225+
backorder = self._validate_picking(self.shipping, 5)
226+
self.assertEqual(self.shipping.state, "done")
227+
self.assertTrue(self.shipping.delivery_notification_sent)
228+
self.assertTrue(backorder.delivery_notification_sent)
229+
backorder2 = self._validate_picking(backorder, 5)
230+
self.assertFalse(backorder2)
231+
self.assertTrue(backorder.delivery_notification_sent)
232+
233+
def test_send_to_shipper_on_pack_partial_shipping(self):
234+
"""Check if a backorder of a transfer, where the delivery notification is already sent
235+
keeps the delivery notification sent set.
236+
"""
237+
with mock.patch.object(
238+
type(self.carrier_on_pack),
239+
"send_shipping",
240+
return_value=SEND_SHIPPING_RETURN_VALUE,
241+
):
242+
self.shipping.carrier_id = self.carrier_on_pack
243+
self._validate_picking(self.picking)
244+
self._validate_picking(self.packing)
245+
self.assertTrue(self.shipping.delivery_notification_sent)
246+
backorder = self._validate_picking(self.shipping, 5)
247+
self.assertEqual(self.shipping.state, "done")
248+
self.assertTrue(self.shipping.delivery_notification_sent)
249+
self.assertTrue(backorder.delivery_notification_sent)
250+
backorder2 = self._validate_picking(backorder, 5)
251+
self.assertFalse(backorder2)
252+
self.assertTrue(backorder.delivery_notification_sent)

0 commit comments

Comments
 (0)