Skip to content

Commit 2b96600

Browse files
sebalixnguyen hoang hiep
authored and
nguyen hoang hiep
committed
[ADD] Send delivery notification from any operation
New module 'delivery_send_to_shipper_at_operation' allowing to send the delivery notification from any operation (among chained operations) before the delivery. With a pick/pack/ship setup this allows to send the delivery notification to the carrier when the pack operation is marked as done for instance (by default Odoo sends it on the ship/delivery). Once the notification has been sent from a non-delivery operation, it won't be sent again when the delivery operation is validated. Drawback: This way of sending delivery notifications is not compatible if we have several pack operations to process before the delivery (backorders?). In such a case, the notification will be generated from only part of the goods to deliver, which is not expected.
1 parent b48f23f commit 2b96600

17 files changed

+968
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
=====================================
2+
Delivery Send To Shipper at Operation
3+
=====================================
4+
5+
.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
6+
!! This file is generated by oca-gen-addon-readme !!
7+
!! changes will be overwritten. !!
8+
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
9+
10+
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
11+
:target: https://odoo-community.org/page/development-status
12+
:alt: Beta
13+
.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
14+
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
15+
:alt: License: AGPL-3
16+
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fdelivery--carrier-lightgray.png?logo=github
17+
:target: https://github.com/OCA/delivery-carrier/tree/13.0/delivery_send_to_shipper_at_operation
18+
:alt: OCA/delivery-carrier
19+
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
20+
:target: https://translation.odoo-community.org/projects/delivery-carrier-13-0/delivery-carrier-13-0-delivery_send_to_shipper_at_operation
21+
:alt: Translate me on Weblate
22+
.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png
23+
:target: https://runbot.odoo-community.org/runbot/99/13.0
24+
:alt: Try me on Runbot
25+
26+
|badge1| |badge2| |badge3| |badge4| |badge5|
27+
28+
This module allows to send the delivery notification to the carrier when
29+
any operation before the delivery one is marked as done.
30+
31+
This is used mainly to send the notification when the pack operation is marked
32+
as done, using the shipping method of the related delivery operation.
33+
By doing so, the delivery operation won't send again the delivery notification
34+
when it will be validated.
35+
However, the delivery cost will still be added to the sale order by the delivery
36+
operation, not the pack.
37+
38+
**Table of contents**
39+
40+
.. contents::
41+
:local:
42+
43+
Usage
44+
=====
45+
46+
On the shipping method, you can configure on which operation types the
47+
delivery notification is triggered by selecting *Defined operations* in the
48+
*Send delivery notice on* field:
49+
50+
.. image:: ../static/description/delivery_carrier1.png
51+
52+
Then select the operation type which will trigger the delivery notification:
53+
54+
.. image:: ../static/description/delivery_carrier2.png
55+
56+
Known issues / Roadmap
57+
======================
58+
59+
Known issues:
60+
61+
* this module is working fine only if the operation from which the delivery
62+
note is sent has no backorder. All quantities have to be processed to get
63+
full data in the delivery notification;
64+
65+
TODO:
66+
67+
* hide the "Send to shipper" button on the delivery form if the delivery
68+
notification has already been sent
69+
70+
Bug Tracker
71+
===========
72+
73+
Bugs are tracked on `GitHub Issues <https://github.com/OCA/delivery-carrier/issues>`_.
74+
In case of trouble, please check there if your issue has already been reported.
75+
If you spotted it first, help us smashing it by providing a detailed and welcomed
76+
`feedback <https://github.com/OCA/delivery-carrier/issues/new?body=module:%20delivery_send_to_shipper_at_operation%0Aversion:%2013.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
77+
78+
Do not contact contributors directly about support or help with technical issues.
79+
80+
Credits
81+
=======
82+
83+
Authors
84+
~~~~~~~
85+
86+
* Camptocamp
87+
88+
Contributors
89+
~~~~~~~~~~~~
90+
91+
* Sébastien Alix <sebastien.alix@camptocamp.com>
92+
93+
Maintainers
94+
~~~~~~~~~~~
95+
96+
This module is maintained by the OCA.
97+
98+
.. image:: https://odoo-community.org/logo.png
99+
:alt: Odoo Community Association
100+
:target: https://odoo-community.org
101+
102+
OCA, or the Odoo Community Association, is a nonprofit organization whose
103+
mission is to support the collaborative development of Odoo features and
104+
promote its widespread use.
105+
106+
This module is part of the `OCA/delivery-carrier <https://github.com/OCA/delivery-carrier/tree/13.0/delivery_send_to_shipper_at_operation>`_ project on GitHub.
107+
108+
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from . import models
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Copyright 2021 Camptocamp SA
2+
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl)
3+
{
4+
"name": "Delivery Send To Shipper at Operation",
5+
"summary": "Send delivery notice to the shipper from any operation.",
6+
"version": "13.0.1.0.0",
7+
"development_status": "Beta",
8+
"category": "Inventory",
9+
"website": "https://github.com/OCA/stock-logistics-workflow",
10+
"author": "Camptocamp, Odoo Community Association (OCA)",
11+
"license": "AGPL-3",
12+
"application": False,
13+
"installable": True,
14+
"depends": [
15+
# core
16+
"stock",
17+
"delivery",
18+
# OCA/delivery-carrier
19+
"stock_picking_delivery_link",
20+
],
21+
"data": ["views/delivery_carrier.xml", "views/stock_picking.xml"],
22+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
from . import delivery_carrier
2+
from . import stock_picking
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Copyright 2021 Camptocamp SA
2+
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
3+
4+
from odoo import fields, models
5+
6+
SEND_DELIVERY_NOTICE_ON_HELP = """
7+
'Ship operation' (default): send the carrier notification after the
8+
operation having a delivery method defined has been marked as done.
9+
10+
'Defined operations': send the carrier notification after the operation
11+
of the chosen types has been marked as done. In this case, the
12+
carrier will be taken looking at the next operations until a
13+
carrier is found. For instance, in a pick + pack + ship setup,
14+
if you set the notification to be sent on the pack operation type,
15+
it will look at the carrier defined in the next operation (the ship in this case).
16+
17+
If no notification have been sent when reaching the ship step
18+
(e.g. re-route goods from carrier A to B), then a fallback ensure the
19+
ship operation will trigger the call anyway.
20+
"""
21+
22+
23+
class DeliveryCarrier(models.Model):
24+
_inherit = "delivery.carrier"
25+
26+
send_delivery_notice_on = fields.Selection(
27+
selection=[("ship", "Ship operation"), ("custom", "Defined operations")],
28+
string="Send delivery notice on",
29+
default="ship",
30+
help=SEND_DELIVERY_NOTICE_ON_HELP,
31+
)
32+
send_delivery_notice_picking_type_ids = fields.Many2many(
33+
comodel_name="stock.picking.type",
34+
string="Send delivery notice operation types",
35+
help="""
36+
When an operation of the listed type will be mark as done, the
37+
notification will be sent to the carrier (instead of the default
38+
behavior, which is whenever a delivery method is set on an
39+
operation).
40+
""",
41+
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
# Copyright 2021 Camptocamp SA
2+
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
3+
4+
from lxml import etree
5+
6+
from odoo import fields, models
7+
from odoo.osv import expression
8+
from odoo.tools.safe_eval import safe_eval
9+
10+
from odoo.addons.base.models.ir_ui_view import (
11+
transfer_modifiers_to_node,
12+
transfer_node_to_modifiers,
13+
)
14+
15+
16+
class StockPicking(models.Model):
17+
_inherit = "stock.picking"
18+
19+
delivery_notification_sent = fields.Boolean(default=False)
20+
21+
def _send_confirmation_email(self):
22+
for picking in self:
23+
skip_delivery_cost = picking._handle_send_to_shipper_at_operation()
24+
picking = picking.with_context(skip_delivery_cost=skip_delivery_cost)
25+
super(StockPicking, picking)._send_confirmation_email()
26+
27+
def _handle_send_to_shipper_at_operation(self):
28+
"""Send the delivery notice to the carrier from a specific operation type.
29+
30+
We are only interested by sending the delivery notice, the delivery fee
31+
still have to be added to the SO by the ship operation.
32+
33+
Return True if the operation has send the delivery notice.
34+
"""
35+
self.ensure_one()
36+
if not self.carrier_id:
37+
# If the current operation has no carrier defined, but a carrier
38+
# has been found from the ship and is configured to match the
39+
# current operation type: force the sending of the delivery notice
40+
# to the carrier
41+
related_ship = self.ship_picking_id
42+
carrier = related_ship.carrier_id
43+
if (
44+
carrier.integration_level == "rate_and_ship"
45+
and carrier.send_delivery_notice_on == "custom"
46+
and self.picking_type_id
47+
in carrier.send_delivery_notice_picking_type_ids
48+
):
49+
self.carrier_id = carrier
50+
self.with_context(skip_delivery_cost=True).send_to_shipper()
51+
# Flag the current operation and the ship one.
52+
# Mandatory to not execute twice 'send_to_shipper' method
53+
self.delivery_notification_sent = True
54+
related_ship.delivery_notification_sent = True
55+
related_ship.carrier_price = self.carrier_price
56+
related_ship.carrier_tracking_ref = self.carrier_tracking_ref
57+
return True
58+
return False
59+
60+
def send_to_shipper(self):
61+
# Do not send delivery notice to the carrier if it has already been sent
62+
# through a previous operation (like a pack)
63+
self.ensure_one()
64+
if self.delivery_notification_sent:
65+
# But we still need to add the delivery cost to the SO
66+
self._add_delivery_cost_to_so()
67+
return False
68+
return super().send_to_shipper()
69+
70+
def _add_delivery_cost_to_so(self):
71+
if self.env.context.get("skip_delivery_cost"):
72+
return
73+
return super()._add_delivery_cost_to_so()
74+
75+
def fields_view_get(
76+
self, view_id=None, view_type="form", toolbar=False, submenu=False
77+
):
78+
# Override to hide the "Send to shipper" button if the delivery
79+
# notification has already been sent
80+
result = super().fields_view_get(
81+
view_id=view_id, view_type=view_type, toolbar=toolbar, submenu=submenu
82+
)
83+
if result.get("name") == "stock.picking.form":
84+
result["arch"] = self._fields_view_get_adapt_send_to_shipper_attrs(
85+
result["arch"]
86+
)
87+
return result
88+
89+
def _fields_view_get_adapt_send_to_shipper_attrs(self, view_arch):
90+
"""Hide 'Send to Shipper' button if 'delivery_notification_sent' is True."""
91+
doc = etree.XML(view_arch)
92+
xpath_expr = "//button[@name='send_to_shipper']"
93+
attrs_key = "invisible"
94+
nodes = doc.xpath(xpath_expr)
95+
for field in nodes:
96+
attrs = safe_eval(field.attrib.get("attrs", "{}"))
97+
if not attrs[attrs_key]:
98+
continue
99+
invisible_domain = expression.OR(
100+
[attrs[attrs_key], [("delivery_notification_sent", "=", True)]]
101+
)
102+
attrs[attrs_key] = invisible_domain
103+
field.set("attrs", str(attrs))
104+
modifiers = {}
105+
transfer_node_to_modifiers(
106+
field, modifiers, self.env.context, in_tree_view=True
107+
)
108+
transfer_modifiers_to_node(modifiers, field)
109+
return etree.tostring(doc, encoding="unicode")
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
* Sébastien Alix <sebastien.alix@camptocamp.com>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
This module allows to send the delivery notification to the carrier when
2+
any operation before the delivery one is marked as done.
3+
4+
This is used mainly to send the notification when the pack operation is marked
5+
as done, using the shipping method of the related delivery operation.
6+
By doing so, the delivery operation won't send again the delivery notification
7+
when it will be validated.
8+
However, the delivery cost will still be added to the sale order by the delivery
9+
operation, not the pack.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
Known issues:
2+
3+
* this module is working fine only if the operation from which the delivery
4+
note is sent has no backorder. All quantities have to be processed to get
5+
full data in the delivery notification;
6+
7+
TODO:
8+
9+
* hide the "Send to shipper" button on the delivery form if the delivery
10+
notification has already been sent
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
On the shipping method, you can configure on which operation types the
2+
delivery notification is triggered by selecting *Defined operations* in the
3+
*Send delivery notice on* field:
4+
5+
.. image:: ../static/description/delivery_carrier1.png
6+
7+
Then select the operation type which will trigger the delivery notification:
8+
9+
.. image:: ../static/description/delivery_carrier2.png
Loading
Loading

0 commit comments

Comments
 (0)