Skip to content

Commit df59faa

Browse files
committed
[IMP] sale_order_carrier_auto_assign
Allow to assign carrier on create
1 parent 622322f commit df59faa

12 files changed

+230
-42
lines changed

sale_order_carrier_auto_assign/README.rst

+9-2
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,9 @@ Sale Order Carrier Auto Assign
2828

2929
|badge1| |badge2| |badge3| |badge4| |badge5|
3030

31-
This module assigns automatically delivery carrier on sale order confirmation.
31+
This module assigns automatically delivery carrier on sale order creation or confirmation.
32+
33+
You may also have a look at the module delivery_auto_refresh in delivery-carrier repository.
3234

3335
.. IMPORTANT::
3436
This is an alpha version, the data model and design can change at any time without warning.
@@ -45,7 +47,10 @@ Configuration
4547

4648
To enable sale order carrier auto assign:
4749

48-
#. Go to *Settings > Sales > Carrier Auto Assign*.
50+
#. Go to *Settings > Sales > Shipping*.
51+
52+
* Enable on creation: only the carrier will be set.
53+
* Enable on confirmation: the carrier and delivery line will be set.
4954

5055
Bug Tracker
5156
===========
@@ -64,6 +69,7 @@ Authors
6469
~~~~~~~
6570

6671
* Camptocamp
72+
* BCIM
6773

6874
Contributors
6975
~~~~~~~~~~~~
@@ -73,6 +79,7 @@ Contributors
7379
* Phuc (Tran Thanh) <phuc@trobz.com>
7480
* Telmo Santos <telmo.santos@camptocamp.com>
7581
* Tris Doan <tridm@trobz.com>
82+
* Jacques-Etienne Baudoux (BCIM) <je@bcim.be>
7683

7784

7885
Maintainers

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,9 @@
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+
"Set default shipping method automatically"
13+
)
14+
carrier_auto_assign_on_confirm = fields.Boolean(
15+
"Ensure shipping method and cost line on confirmation"
16+
)
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,12 @@
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",
13+
readonly=False,
14+
)
15+
16+
carrier_auto_assign_on_confirm = fields.Boolean(
17+
related="company_id.carrier_auto_assign_on_confirm",
1218
readonly=False,
13-
help="Enable carrier auto assign on sale order confirmation.",
1419
)
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

3-
#. Go to *Settings > Sales > Carrier Auto Assign*.
3+
#. Go to *Settings > Sales > Shipping*.
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.

sale_order_carrier_auto_assign/static/description/index.html

+9-2
Original file line numberDiff line numberDiff line change
@@ -369,7 +369,8 @@ <h1 class="title">Sale Order Carrier Auto Assign</h1>
369369
!! source digest: sha256:b5f0ff98a101634f6d21500615b789f2e2cbd6d305d896b93dd77cb31461dec0
370370
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
371371
<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Alpha" src="https://img.shields.io/badge/maturity-Alpha-red.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/sale-workflow/tree/16.0/sale_order_carrier_auto_assign"><img alt="OCA/sale-workflow" src="https://img.shields.io/badge/github-OCA%2Fsale--workflow-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/sale-workflow-16-0/sale-workflow-16-0-sale_order_carrier_auto_assign"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/sale-workflow&amp;target_branch=16.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
372-
<p>This module assigns automatically delivery carrier on sale order confirmation.</p>
372+
<p>This module assigns automatically delivery carrier on sale order creation or confirmation.</p>
373+
<p>You may also have a look at the module delivery_auto_refresh in delivery-carrier repository.</p>
373374
<div class="admonition important">
374375
<p class="first admonition-title">Important</p>
375376
<p class="last">This is an alpha version, the data model and design can change at any time without warning.
@@ -393,8 +394,12 @@ <h1 class="title">Sale Order Carrier Auto Assign</h1>
393394
<h1><a class="toc-backref" href="#toc-entry-1">Configuration</a></h1>
394395
<p>To enable sale order carrier auto assign:</p>
395396
<ol class="arabic simple">
396-
<li>Go to <em>Settings &gt; Sales &gt; Carrier Auto Assign</em>.</li>
397+
<li>Go to <em>Settings &gt; Sales &gt; Shipping</em>.</li>
397398
</ol>
399+
<ul class="simple">
400+
<li>Enable on creation: only the carrier will be set.</li>
401+
<li>Enable on confirmation: the carrier and delivery line will be set.</li>
402+
</ul>
398403
</div>
399404
<div class="section" id="bug-tracker">
400405
<h1><a class="toc-backref" href="#toc-entry-2">Bug Tracker</a></h1>
@@ -410,6 +415,7 @@ <h1><a class="toc-backref" href="#toc-entry-3">Credits</a></h1>
410415
<h2><a class="toc-backref" href="#toc-entry-4">Authors</a></h2>
411416
<ul class="simple">
412417
<li>Camptocamp</li>
418+
<li>BCIM</li>
413419
</ul>
414420
</div>
415421
<div class="section" id="contributors">
@@ -420,6 +426,7 @@ <h2><a class="toc-backref" href="#toc-entry-5">Contributors</a></h2>
420426
<li>Phuc (Tran Thanh) &lt;<a class="reference external" href="mailto:phuc&#64;trobz.com">phuc&#64;trobz.com</a>&gt;</li>
421427
<li>Telmo Santos &lt;<a class="reference external" href="mailto:telmo.santos&#64;camptocamp.com">telmo.santos&#64;camptocamp.com</a>&gt;</li>
422428
<li>Tris Doan &lt;<a class="reference external" href="mailto:tridm&#64;trobz.com">tridm&#64;trobz.com</a>&gt;</li>
429+
<li>Jacques-Etienne Baudoux (BCIM) &lt;<a class="reference external" href="mailto:je&#64;bcim.be">je&#64;bcim.be</a>&gt;</li>
423430
</ul>
424431
</div>
425432
<div class="section" id="maintainers">
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)

0 commit comments

Comments
 (0)