Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 8fa0b92

Browse files
committedApr 17, 2024·
[IMP] sale_order_carrier_auto_assign
Allow to assign carrier on create
1 parent 622322f commit 8fa0b92

10 files changed

+215
-37
lines changed
 

‎sale_order_carrier_auto_assign/__manifest__.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@
22
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl)
33
{
44
"name": "Sale Order Carrier Auto Assign",
5-
"summary": "Auto assign delivery carrier on sale order confirmation",
6-
"version": "16.0.1.1.0",
5+
"summary": "Auto assign delivery carrier on sales order",
6+
"version": "16.0.2.0.0",
77
"development_status": "Alpha",
88
"category": "Operations/Inventory/Delivery",
99
"website": "https://github.com/OCA/sale-workflow",
10-
"author": "Camptocamp, Odoo Community Association (OCA)",
10+
"author": "Camptocamp, BCIM, Odoo Community Association (OCA)",
1111
"license": "AGPL-3",
1212
"data": ["views/res_config_settings_views.xml"],
1313
"application": False,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Copyright 2024 Jacques-Etienne Baudoux (BCIM) <je@bcim.be>
2+
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
3+
4+
from odoo.tools import sql
5+
6+
7+
def migrate(cr, version):
8+
if sql.column_exists(cr, "res_company", "carrier_auto_assign"):
9+
sql.rename_column(
10+
cr, "res_company", "carrier_auto_assign", "carrier_auto_assign_on_confirm"
11+
)
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# Copyright 2023 Camptocamp SA
2+
# Copyright 2024 Jacques-Etienne Baudoux (BCIM) <je@bcim.be>
23
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
34

45
from odoo import fields, models
@@ -7,4 +8,5 @@
78
class ResCompany(models.Model):
89
_inherit = "res.company"
910

10-
carrier_auto_assign = fields.Boolean()
11+
carrier_auto_assign_on_create = fields.Boolean()
12+
carrier_auto_assign_on_confirm = fields.Boolean()
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# Copyright 2023 Camptocamp SA
2+
# Copyright 2024 Jacques-Etienne Baudoux (BCIM) <je@bcim.be>
23
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
34

45
from odoo import fields, models
@@ -7,8 +8,14 @@
78
class ResConfigSettings(models.TransientModel):
89
_inherit = "res.config.settings"
910

10-
carrier_auto_assign = fields.Boolean(
11-
related="company_id.carrier_auto_assign",
11+
carrier_auto_assign_on_create = fields.Boolean(
12+
related="company_id.carrier_auto_assign_on_create",
1213
readonly=False,
13-
help="Enable carrier auto assign on sale order confirmation.",
14+
help="Enable carrier auto assign on sales order creation.",
15+
)
16+
17+
carrier_auto_assign_on_confirm = fields.Boolean(
18+
related="company_id.carrier_auto_assign_on_confirm",
19+
readonly=False,
20+
help="Enable carrier auto assign on sales order confirmation.",
1421
)
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,80 @@
11
# Copyright 2020 Camptocamp SA
2+
# Copyright 2024 Jacques-Etienne Baudoux (BCIM) <je@bcim.be>
23
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl)
3-
from odoo import models
44

5+
from odoo import api, models
56

6-
class SaleOrder(models.Model):
77

8+
class SaleOrder(models.Model):
89
_inherit = "sale.order"
910

10-
def action_confirm(self):
11-
for rec in self:
12-
if not rec.company_id.carrier_auto_assign:
13-
continue
14-
rec._add_delivery_carrier_on_confirmation()
15-
return super().action_confirm()
16-
17-
def _add_delivery_carrier_on_confirmation(self):
18-
"""Automatically add delivery.carrier on sale order confirmation"""
11+
def _set_delivery_carrier(self, set_delivery_line=True):
1912
for order in self:
20-
if order.delivery_set:
21-
continue
2213
delivery_wiz_action = order.action_open_delivery_wizard()
2314
delivery_wiz_context = delivery_wiz_action.get("context", {})
2415
if not delivery_wiz_context.get("default_carrier_id"):
2516
continue
2617
delivery_wiz = (
2718
self.env[delivery_wiz_action.get("res_model")]
2819
.with_context(**delivery_wiz_context)
29-
.create({})
20+
.new({})
3021
)
31-
delivery_wiz._get_shipment_rate()
32-
delivery_wiz.button_confirm()
22+
23+
# Do not override carrier
24+
if order.carrier_id:
25+
delivery_wiz.carrier_id = order.carrier_id
26+
27+
# If the carrier isn't allowed, we won't default to it
28+
if (
29+
delivery_wiz.carrier_id
30+
not in delivery_wiz.available_carrier_ids._origin
31+
):
32+
return
33+
34+
if not set_delivery_line or order.is_all_service:
35+
# Only set the carrier
36+
if order.carrier_id != delivery_wiz.carrier_id:
37+
order.carrier_id = delivery_wiz.carrier_id
38+
else:
39+
delivery_wiz._get_shipment_rate()
40+
delivery_wiz.button_confirm()
41+
42+
@api.onchange("partner_id", "partner_shipping_id")
43+
def _add_delivery_carrier_on_partner_change(self):
44+
partner = self.partner_shipping_id or self.partner_id
45+
if not partner:
46+
return
47+
if self.company_id.carrier_auto_assign_on_create:
48+
self._set_delivery_carrier(set_delivery_line=False)
49+
50+
def _is_auto_set_carrier_on_create(self):
51+
self.ensure_one()
52+
if self.state not in ("draft", "sent"):
53+
return False
54+
if self.company_id.carrier_auto_assign_on_create:
55+
return True
56+
return False
57+
58+
@api.model_create_multi
59+
def create(self, vals_list):
60+
orders = super().create(vals_list)
61+
for order in orders:
62+
if not order.carrier_id and order._is_auto_set_carrier_on_create():
63+
order._set_delivery_carrier()
64+
return orders
65+
66+
def _add_delivery_carrier_on_confirmation(self):
67+
"""Automatically add delivery.carrier on sale order confirmation"""
68+
for order in self:
69+
if order.delivery_set:
70+
continue
71+
if order.is_all_service:
72+
continue
73+
order._set_delivery_carrier()
74+
75+
def action_confirm(self):
76+
for order in self:
77+
if not order.company_id.carrier_auto_assign_on_confirm:
78+
continue
79+
order._add_delivery_carrier_on_confirmation()
80+
return super().action_confirm()
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
11
To enable sale order carrier auto assign:
22

33
#. Go to *Settings > Sales > Carrier Auto Assign*.
4+
5+
* Enable on creation: only the carrier will be set.
6+
* Enable on confirmation: the carrier and delivery line will be set.

‎sale_order_carrier_auto_assign/readme/CONTRIBUTORS.rst

+1
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@
33
* Phuc (Tran Thanh) <phuc@trobz.com>
44
* Telmo Santos <telmo.santos@camptocamp.com>
55
* Tris Doan <tridm@trobz.com>
6+
* Jacques-Etienne Baudoux (BCIM) <je@bcim.be>
67

Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
1-
This module assigns automatically delivery carrier on sale order confirmation.
1+
This module assigns automatically delivery carrier on sale order creation or confirmation.
2+
3+
You may also have a look at the module delivery_auto_refresh in delivery-carrier repository.
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,96 @@
11
# Copyright 2020 Camptocamp SA
2+
# Copyright 2024 Jacques-Etienne Baudoux (BCIM) <je@bcim.be>
23
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl)
34
from odoo.tests import Form, TransactionCase
45

56
from odoo.addons.base.tests.common import DISABLED_MAIL_CONTEXT
67

78

8-
class TestSaleOrderCarrierAutoAssign(TransactionCase):
9+
class TestSaleOrderCarrierAutoAssignCommon(TransactionCase):
910
@classmethod
1011
def setUpClass(cls):
1112
super().setUpClass()
1213
cls.env = cls.env["base"].with_context(**DISABLED_MAIL_CONTEXT).env
13-
cls.settings = cls.env["res.config.settings"].create({})
14-
cls.settings.carrier_auto_assign = True
15-
cls.settings.set_values()
1614

1715
cls.partner = cls.env.ref("base.res_partner_2")
18-
product = cls.env.ref("product.product_product_9")
16+
cls.product_storable = cls.env.ref("product.product_product_9")
1917
cls.delivery_local_delivery = cls.env.ref("delivery.delivery_local_delivery")
2018
cls.delivery_local_delivery.fixed_price = 10
21-
sale_order_form = Form(cls.env["sale.order"])
22-
sale_order_form.partner_id = cls.partner
23-
with sale_order_form.order_line.new() as line_form:
24-
line_form.product_id = product
25-
cls.sale_order = sale_order_form.save()
19+
20+
21+
class TestSaleOrderCarrierAutoAssignOnCreate(TestSaleOrderCarrierAutoAssignCommon):
22+
@classmethod
23+
def setUpClass(cls):
24+
super().setUpClass()
25+
cls.settings = cls.env["res.config.settings"].create({})
26+
27+
def test_sale_order_carrier_auto_assign_onchange(self):
28+
self.assertEqual(
29+
self.partner.property_delivery_carrier_id, self.delivery_local_delivery
30+
)
31+
self.settings.carrier_auto_assign_on_create = True
32+
self.settings.set_values()
33+
sale_order_form = Form(self.env["sale.order"])
34+
sale_order_form.partner_id = self.partner
35+
sale_order = sale_order_form.save()
36+
self.assertEqual(sale_order.carrier_id, self.delivery_local_delivery)
37+
38+
def test_sale_order_carrier_auto_assign_create(self):
39+
self.assertEqual(
40+
self.partner.property_delivery_carrier_id, self.delivery_local_delivery
41+
)
42+
self.settings.carrier_auto_assign_on_create = True
43+
self.settings.set_values()
44+
sale_order = self.env["sale.order"].create({"partner_id": self.partner.id})
45+
self.assertEqual(sale_order.carrier_id, self.delivery_local_delivery)
46+
47+
def test_sale_order_carrier_auto_assign_disabled(self):
48+
self.assertEqual(
49+
self.partner.property_delivery_carrier_id, self.delivery_local_delivery
50+
)
51+
self.settings.carrier_auto_assign_on_create = False
52+
self.settings.set_values()
53+
sale_order_form = Form(self.env["sale.order"])
54+
sale_order_form.partner_id = self.partner
55+
sale_order = sale_order_form.save()
56+
self.assertFalse(sale_order.carrier_id)
57+
58+
def test_sale_order_carrier_auto_assign_no_carrier(self):
59+
self.partner.property_delivery_carrier_id = False
60+
self.settings.carrier_auto_assign_on_create = True
61+
self.settings.set_values()
62+
sale_order_form = Form(self.env["sale.order"])
63+
sale_order_form.partner_id = self.partner
64+
sale_order = sale_order_form.save()
65+
self.assertFalse(sale_order.carrier_id)
66+
67+
def test_sale_order_carrier_auto_assign_carrier_already_set(self):
68+
self.assertEqual(
69+
self.partner.property_delivery_carrier_id, self.delivery_local_delivery
70+
)
71+
self.settings.carrier_auto_assign_on_create = True
72+
carrier = self.env.ref("delivery.delivery_carrier")
73+
sale_order = self.env["sale.order"].create(
74+
{
75+
"partner_id": self.partner.id,
76+
"carrier_id": carrier.id,
77+
}
78+
)
79+
self.assertEqual(sale_order.carrier_id, carrier)
80+
81+
82+
class TestSaleOrderCarrierAutoAssignOnConfirm(TestSaleOrderCarrierAutoAssignCommon):
83+
@classmethod
84+
def setUpClass(cls):
85+
super().setUpClass()
86+
cls.settings = cls.env["res.config.settings"].create({})
87+
cls.settings.carrier_auto_assign_on_confirm = True
88+
cls.settings.set_values()
89+
cls.sale_order_form = Form(cls.env["sale.order"])
90+
cls.sale_order_form.partner_id = cls.partner
91+
with cls.sale_order_form.order_line.new() as line_form:
92+
line_form.product_id = cls.product_storable
93+
cls.sale_order = cls.sale_order_form.save()
2694

2795
def test_sale_order_carrier_auto_assign(self):
2896
self.assertEqual(
@@ -36,9 +104,30 @@ def test_sale_order_carrier_auto_assign(self):
36104
delivery_rate = self.delivery_local_delivery.rate_shipment(self.sale_order)
37105
self.assertEqual(delivery_line.price_unit, delivery_rate["carrier_price"])
38106

107+
def test_sale_order_carrier_auto_assign_disabled(self):
108+
self.assertEqual(
109+
self.partner.property_delivery_carrier_id, self.delivery_local_delivery
110+
)
111+
self.assertFalse(self.sale_order.carrier_id)
112+
self.settings.carrier_auto_assign_on_confirm = False
113+
self.settings.set_values()
114+
self.sale_order.action_confirm()
115+
self.assertEqual(self.sale_order.state, "sale")
116+
self.assertFalse(self.sale_order.carrier_id)
117+
39118
def test_sale_order_carrier_auto_assign_no_carrier(self):
40119
self.partner.property_delivery_carrier_id = False
41120
self.assertFalse(self.sale_order.carrier_id)
42121
self.sale_order.action_confirm()
43122
self.assertEqual(self.sale_order.state, "sale")
44123
self.assertFalse(self.sale_order.carrier_id)
124+
125+
def test_sale_order_carrier_auto_assign_carrier_already_set(self):
126+
self.assertEqual(
127+
self.partner.property_delivery_carrier_id, self.delivery_local_delivery
128+
)
129+
carrier = self.env.ref("delivery.delivery_carrier")
130+
self.sale_order.carrier_id = carrier
131+
self.sale_order.action_confirm()
132+
self.assertEqual(self.sale_order.state, "sale")
133+
self.assertEqual(self.sale_order.carrier_id, carrier)

‎sale_order_carrier_auto_assign/views/res_config_settings_views.xml

+18-3
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,27 @@
88
<xpath expr="//div[@name='shipping_setting_container']" position="inside">
99
<div class="col-12 col-lg-6 o_setting_box" id="carrier_auto_assign">
1010
<div class="o_setting_left_pane">
11-
<field name="carrier_auto_assign" />
11+
<field name="carrier_auto_assign_on_create" />
1212
</div>
1313
<div class="o_setting_right_pane">
14-
<label for="carrier_auto_assign" string="Carrier auto assign" />
14+
<label
15+
for="carrier_auto_assign_on_create"
16+
string="Carrier auto assign on create"
17+
/>
1518
<div class="text-muted">
16-
Assigns automatically delivery carrier on sale order confirmation.
19+
Assigns automatically the delivery carrier on sales order creation.
20+
</div>
21+
</div>
22+
<div class="o_setting_left_pane">
23+
<field name="carrier_auto_assign_on_confirm" />
24+
</div>
25+
<div class="o_setting_right_pane">
26+
<label
27+
for="carrier_auto_assign_on_confirm"
28+
string="Carrier auto assign on confirmation"
29+
/>
30+
<div class="text-muted">
31+
Assigns automatically delivery carrier on sales order confirmation.
1732
</div>
1833
</div>
1934
</div>

0 commit comments

Comments
 (0)
Please sign in to comment.