Skip to content

Commit 77dd71e

Browse files
committed
Merge PR #782 into 14.0
Signed-off-by jbaudoux
2 parents f94168c + bc8193b commit 77dd71e

File tree

3 files changed

+106
-21
lines changed

3 files changed

+106
-21
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

+63-5
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"}]
@@ -15,7 +16,11 @@ class TestDeliverySendToShipper(SavepointCase):
1516
@classmethod
1617
def setUpClass(cls):
1718
super().setUpClass()
18-
cls.env = cls.env(context=dict(cls.env.context, tracking_disable=True))
19+
cls.env = cls.env(
20+
context=dict(
21+
cls.env.context, tracking_disable=True, set_default_package=False
22+
)
23+
)
1924
cls.wh = cls.env.ref("stock.warehouse0")
2025
cls.wh.delivery_steps = "pick_pack_ship"
2126
cls.stock_location = cls.env.ref("stock.stock_location_stock")
@@ -82,10 +87,19 @@ def setUpClass(cls):
8287
)
8388
(cls.picking | cls.packing | cls.shipping).sale_id = cls.order
8489

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

90104
def test_send_to_shipper_on_ship(self):
91105
"""Check sending of delivery notification on ship.
@@ -195,3 +209,47 @@ def test_picking_fields_view_get(self):
195209
attrs_str = button_send_to_shipper.attrib["attrs"]
196210
attrs = safe_eval(attrs_str)
197211
self.assertIn(("delivery_notification_sent", "=", True), attrs["invisible"])
212+
213+
def test_send_to_shipper_on_partial_pack(self):
214+
"""Check that the field delivery_notification_sent
215+
is not set on a pack backorder
216+
but on the ship transfer
217+
"""
218+
with mock.patch.object(
219+
type(self.carrier_on_pack),
220+
"send_shipping",
221+
return_value=SEND_SHIPPING_RETURN_VALUE,
222+
):
223+
self.shipping.carrier_id = self.carrier_on_pack
224+
self._validate_picking(self.picking)
225+
pack_backorder = self._validate_picking(self.packing, 5)
226+
self.assertTrue(self.shipping.delivery_notification_sent)
227+
self.assertFalse(pack_backorder.delivery_notification_sent)
228+
self._validate_picking(pack_backorder, 5)
229+
self.assertTrue(self.shipping.delivery_notification_sent)
230+
backorder = self._validate_picking(self.shipping, 5)
231+
self.assertEqual(self.shipping.state, "done")
232+
self.assertTrue(self.shipping.delivery_notification_sent)
233+
self.assertTrue(backorder.delivery_notification_sent)
234+
backorder2 = self._validate_picking(backorder, 5)
235+
self.assertFalse(backorder2)
236+
self.assertTrue(backorder.delivery_notification_sent)
237+
238+
def test_send_to_shipper_on_pack_partial_shipping(self):
239+
"""Check that delivery_notification_sent is set on a ship backorder"""
240+
with mock.patch.object(
241+
type(self.carrier_on_pack),
242+
"send_shipping",
243+
return_value=SEND_SHIPPING_RETURN_VALUE,
244+
):
245+
self.shipping.carrier_id = self.carrier_on_pack
246+
self._validate_picking(self.picking)
247+
self._validate_picking(self.packing)
248+
self.assertTrue(self.shipping.delivery_notification_sent)
249+
backorder = self._validate_picking(self.shipping, 5)
250+
self.assertEqual(self.shipping.state, "done")
251+
self.assertTrue(self.shipping.delivery_notification_sent)
252+
self.assertTrue(backorder.delivery_notification_sent)
253+
backorder2 = self._validate_picking(backorder, 5)
254+
self.assertFalse(backorder2)
255+
self.assertTrue(backorder.delivery_notification_sent)

0 commit comments

Comments
 (0)