Skip to content

Commit

Permalink
Merge PR #782 into 14.0
Browse files Browse the repository at this point in the history
Signed-off-by jbaudoux
  • Loading branch information
OCA-git-bot committed Feb 5, 2025
2 parents f94168c + bc8193b commit 77dd71e
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 21 deletions.
58 changes: 42 additions & 16 deletions delivery_send_to_shipper_at_operation/models/stock_picking.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Copyright 2021 Camptocamp SA
# Copyright 2023 Jacques-Etienne Baudoux (BCIM) <[email protected]>
# Copyright 2024 Michael Tietz (MT Software) <[email protected]>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)

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

def _send_confirmation_email(self):
picking_ids_skip_costs = []
for picking in self:
skip_delivery_cost = picking._handle_send_to_shipper_at_operation()
picking = picking.with_context(skip_delivery_cost=skip_delivery_cost)
super(StockPicking, picking)._send_confirmation_email()
if not picking._is_send_to_shipper_at_operation():
continue
picking_ids_skip_costs.append(picking.id)
picking.carrier_id = picking.ship_picking_id.carrier_id
pickings_skip_costs = self.browse(picking_ids_skip_costs)
if pickings_skip_costs:
pickings_skip_costs._handle_send_to_shipper_at_operation()
super(StockPicking, self - pickings_skip_costs)._send_confirmation_email()

def _handle_send_to_shipper_at_operation(self):
"""Send the delivery notice to the carrier from a specific operation type.
We are only interested by sending the delivery notice, the delivery fee
still have to be added to the SO by the ship operation.
Return True if the operation has send the delivery notice.
"""
super().with_context(skip_delivery_cost=True)._send_confirmation_email()
for picking in self:
related_ship = picking.ship_picking_id
values = picking._prepare_values_send_to_ship_at_operation(related_ship)
related_ship.write(values)

def _is_send_to_shipper_at_operation(self):
"""Return True if the operation needs to send the delivery notice."""
self.ensure_one()
if not self.carrier_id:
# If the current operation has no carrier defined, but a carrier
Expand All @@ -47,20 +60,23 @@ def _handle_send_to_shipper_at_operation(self):
and self.picking_type_id
in carrier.send_delivery_notice_picking_type_ids
):
self.carrier_id = carrier
self.with_context(skip_delivery_cost=True).send_to_shipper()
# Flag the current operation and the ship one.
# Mandatory to not execute twice 'send_to_shipper' method
self.delivery_notification_sent = True
related_ship.delivery_notification_sent = True
related_ship.carrier_price = self.carrier_price
if not related_ship.carrier_tracking_ref:
related_ship.carrier_tracking_ref = self.carrier_tracking_ref
else:
related_ship.carrier_tracking_ref += "," + self.carrier_tracking_ref
return True
return False

def _prepare_values_send_to_ship_at_operation(self, related_ship):
self.ensure_one()
related_ship.ensure_one()
carrier_tracking_ref = related_ship.carrier_tracking_ref
if carrier_tracking_ref:
carrier_tracking_ref += "," + self.carrier_tracking_ref
else:
carrier_tracking_ref = self.carrier_tracking_ref
return {
"delivery_notification_sent": True,
"carrier_price": self.carrier_price,
"carrier_tracking_ref": carrier_tracking_ref,
}

def send_to_shipper(self):
# Do not send delivery notice to the carrier if it has already been sent
# through a previous operation (like a pack)
Expand Down Expand Up @@ -111,3 +127,13 @@ def _fields_view_get_adapt_send_to_shipper_attrs(self, view_arch):
)
transfer_modifiers_to_node(modifiers, field)
return etree.tostring(doc, encoding="unicode")

def _create_backorder(self):
backorders = super()._create_backorder()
for backorder in backorders:
delivery_notification_sent = (
backorder.backorder_id.delivery_notification_sent
)
if delivery_notification_sent:
backorder.delivery_notification_sent = delivery_notification_sent
return backorders
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
* `Trobz <https://trobz.com>`_:
* Nguyen Hoang Hiep <[email protected]>
* Jacques-Etienne Baudoux (BCIM) <[email protected]>
* Michael Tietz (MT Software) <[email protected]>
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
# Copyright 2021 Camptocamp SA
# Copyright 2024 Michael Tietz (MT Software) <[email protected]>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)

from unittest import mock

from lxml import etree

from odoo.tests.common import SavepointCase
from odoo.tests.common import Form, SavepointCase
from odoo.tools.safe_eval import safe_eval

SEND_SHIPPING_RETURN_VALUE = [{"exact_price": 10.0, "tracking_number": "TEST"}]
Expand All @@ -15,7 +16,11 @@ class TestDeliverySendToShipper(SavepointCase):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.env = cls.env(context=dict(cls.env.context, tracking_disable=True))
cls.env = cls.env(
context=dict(
cls.env.context, tracking_disable=True, set_default_package=False
)
)
cls.wh = cls.env.ref("stock.warehouse0")
cls.wh.delivery_steps = "pick_pack_ship"
cls.stock_location = cls.env.ref("stock.stock_location_stock")
Expand Down Expand Up @@ -82,10 +87,19 @@ def setUpClass(cls):
)
(cls.picking | cls.packing | cls.shipping).sale_id = cls.order

def _validate_picking(self, picking):
def _validate_picking(self, picking, qty_done=None):
for ml in picking.move_line_ids:
ml.qty_done = ml.product_uom_qty
picking._action_done()
ml.qty_done = qty_done or ml.product_uom_qty
action_data = picking.button_validate()
if not action_data or action_data is True:
return picking.browse()
backorder_wizard = Form(
self.env["stock.backorder.confirmation"].with_context(
action_data["context"]
)
).save()
backorder_wizard.process()
return self.env["stock.picking"].search([("backorder_id", "=", picking.id)])

def test_send_to_shipper_on_ship(self):
"""Check sending of delivery notification on ship.
Expand Down Expand Up @@ -195,3 +209,47 @@ def test_picking_fields_view_get(self):
attrs_str = button_send_to_shipper.attrib["attrs"]
attrs = safe_eval(attrs_str)
self.assertIn(("delivery_notification_sent", "=", True), attrs["invisible"])

def test_send_to_shipper_on_partial_pack(self):
"""Check that the field delivery_notification_sent
is not set on a pack backorder
but on the ship transfer
"""
with mock.patch.object(
type(self.carrier_on_pack),
"send_shipping",
return_value=SEND_SHIPPING_RETURN_VALUE,
):
self.shipping.carrier_id = self.carrier_on_pack
self._validate_picking(self.picking)
pack_backorder = self._validate_picking(self.packing, 5)
self.assertTrue(self.shipping.delivery_notification_sent)
self.assertFalse(pack_backorder.delivery_notification_sent)
self._validate_picking(pack_backorder, 5)
self.assertTrue(self.shipping.delivery_notification_sent)
backorder = self._validate_picking(self.shipping, 5)
self.assertEqual(self.shipping.state, "done")
self.assertTrue(self.shipping.delivery_notification_sent)
self.assertTrue(backorder.delivery_notification_sent)
backorder2 = self._validate_picking(backorder, 5)
self.assertFalse(backorder2)
self.assertTrue(backorder.delivery_notification_sent)

def test_send_to_shipper_on_pack_partial_shipping(self):
"""Check that delivery_notification_sent is set on a ship backorder"""
with mock.patch.object(
type(self.carrier_on_pack),
"send_shipping",
return_value=SEND_SHIPPING_RETURN_VALUE,
):
self.shipping.carrier_id = self.carrier_on_pack
self._validate_picking(self.picking)
self._validate_picking(self.packing)
self.assertTrue(self.shipping.delivery_notification_sent)
backorder = self._validate_picking(self.shipping, 5)
self.assertEqual(self.shipping.state, "done")
self.assertTrue(self.shipping.delivery_notification_sent)
self.assertTrue(backorder.delivery_notification_sent)
backorder2 = self._validate_picking(backorder, 5)
self.assertFalse(backorder2)
self.assertTrue(backorder.delivery_notification_sent)

0 comments on commit 77dd71e

Please sign in to comment.