From eb5213e2e82ef35880c02f86be03fc0020133b0d Mon Sep 17 00:00:00 2001 From: "Pedro M. Baeza" Date: Tue, 23 May 2023 17:23:29 +0200 Subject: [PATCH 01/16] [FIX] delivery_auto_refresh: Don't fail on fixed rate carriers Steps to reproduce: - Create a delivery method (delivery.carrier) with a fixed rate. - Enable the system parameter "delivery_auto_refresh.refresh_after_picking". - Create a sales order with such delivery method and storable products. - Confirm the sales order. - Validate the picking. Result: It can't be validated with the message "There is no matching delivery rule.". Explanation: Previous code computes the shipping values and call directly to `_get_price_from_picking`, which uses rules and doesn't take into account the rest of possibilities (integration or fixed price). We keep such computation for carriers based on rules, as they are not properly updated, but added the possibility of writing back the price for other carriers with fixed price or integrations, using the `carrier_price` field that contains it. TT43533 --- delivery_auto_refresh/models/stock_picking.py | 56 ++++++++++--------- .../tests/test_delivery_auto_refresh.py | 33 ++++++++++- 2 files changed, 63 insertions(+), 26 deletions(-) diff --git a/delivery_auto_refresh/models/stock_picking.py b/delivery_auto_refresh/models/stock_picking.py index 6cbe9cc059..9c806717c7 100644 --- a/delivery_auto_refresh/models/stock_picking.py +++ b/delivery_auto_refresh/models/stock_picking.py @@ -1,4 +1,4 @@ -# Copyright 2018 Tecnativa - Pedro M. Baeza +# Copyright 2018-2023 Tecnativa - Pedro M. Baeza # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). from odoo import models @@ -21,31 +21,37 @@ def _add_delivery_cost_to_so(self): so_line = sale_order.order_line.filtered(lambda x: x.is_delivery)[:1] if not so_line: # pragma: no cover return res - total = weight = volume = quantity = 0 - for move_line in self.move_line_ids.filtered("qty_done"): - if not move_line.product_id: - continue - move = move_line.move_id - qty = move.product_uom._compute_quantity( - move_line.qty_done, - move_line.product_id.uom_id, + so_line = so_line.with_context(delivery_auto_refresh_override_locked=True) + if self.carrier_id.delivery_type == "base_on_rule": + total = weight = volume = quantity = 0 + for move_line in self.move_line_ids.filtered("qty_done"): + if not move_line.product_id: + continue + move = move_line.move_id + qty = move.product_uom._compute_quantity( + move_line.qty_done, + move_line.product_id.uom_id, + ) + weight += (move_line.product_id.weight or 0.0) * qty + volume += (move_line.product_id.volume or 0.0) * qty + quantity += qty + total += move.sale_line_id.price_unit * qty + total = sale_order.currency_id._convert( + total, + sale_order.company_id.currency_id, + sale_order.company_id, + sale_order.date_order, ) - weight += (move_line.product_id.weight or 0.0) * qty - volume += (move_line.product_id.volume or 0.0) * qty - quantity += qty - total += move.sale_line_id.price_unit * qty - total = sale_order.currency_id._convert( - total, - sale_order.company_id.currency_id, - sale_order.company_id, - sale_order.date_order, - ) - so_line.price_unit = self.carrier_id._get_price_from_picking( - total, - weight, - volume, - quantity, - ) + self.carrier_price = self.carrier_id._get_price_from_picking( + total, + weight, + volume, + quantity, + ) + if self.carrier_price and so_line.price_unit != self.carrier_price: + so_line.with_context( + delivery_auto_refresh_override_locked=True + ).price_unit = self.carrier_price return res def _action_done(self): diff --git a/delivery_auto_refresh/tests/test_delivery_auto_refresh.py b/delivery_auto_refresh/tests/test_delivery_auto_refresh.py index 900a7c0aca..698cf31a48 100644 --- a/delivery_auto_refresh/tests/test_delivery_auto_refresh.py +++ b/delivery_auto_refresh/tests/test_delivery_auto_refresh.py @@ -1,4 +1,4 @@ -# Copyright 2018 Tecnativa - Pedro M. Baeza +# Copyright 2018-2023 Tecnativa - Pedro M. Baeza # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). from odoo.tests import Form, common, tagged @@ -141,6 +141,37 @@ def test_auto_refresh_picking(self): line_delivery = self.order.order_line.filtered("is_delivery") self.assertEqual(line_delivery.price_unit, 50) + def test_auto_refresh_picking_fixed_price(self): + self.settings.refresh_after_picking = True + self.settings.execute() + product_fixed_price = self.env["product.product"].create( + { + "name": "Test carrier fixed price auto refresh", + "type": "service", + } + ) + carrier_form = Form(self.env["delivery.carrier"]) + carrier_form.name = product_fixed_price.name + carrier_form.product_id = product_fixed_price + carrier_form.delivery_type = "fixed" + carrier_form.fixed_price = 2 + carrier_fixed_price = carrier_form.save() + wiz = Form( + self.env["choose.delivery.carrier"].with_context( + default_order_id=self.order.id, + default_carrier_id=carrier_fixed_price.id, + ) + ).save() + wiz.button_confirm() + self.order.action_confirm() + self.order.action_done() # Lock order to check writing protection disabling + picking = self.order.picking_ids + picking.action_assign() + picking.move_line_ids[0].qty_done = 2 + picking._action_done() + line_delivery = self.order.order_line.filtered("is_delivery") + self.assertEqual(line_delivery.price_unit, 2) + def test_no_auto_refresh_picking(self): self.env["ir.config_parameter"].sudo().set_param(self.param_name2, "0") self.order.order_line.product_uom_qty = 3 From 94bcaaafcf99b98d4598872213d93f5400247d14 Mon Sep 17 00:00:00 2001 From: Jacques-Etienne Baudoux Date: Tue, 16 Apr 2024 20:07:30 +0200 Subject: [PATCH 02/16] delivery_auto_refresh: docstring Don't modify standard method docstring --- delivery_auto_refresh/models/sale_order.py | 18 ++++-------------- delivery_auto_refresh/models/stock_picking.py | 5 ++++- 2 files changed, 8 insertions(+), 15 deletions(-) diff --git a/delivery_auto_refresh/models/sale_order.py b/delivery_auto_refresh/models/sale_order.py index 8ee72b9323..3d6653c4a0 100644 --- a/delivery_auto_refresh/models/sale_order.py +++ b/delivery_auto_refresh/models/sale_order.py @@ -71,21 +71,13 @@ def _auto_refresh_delivery(self): @api.model def create(self, vals): - """Create or refresh delivery line on create.""" + # Create or refresh delivery line on create order = super().create(vals) order._auto_refresh_delivery() return order def write(self, vals): - """Create or refresh the delivery line after saving.""" - # Check if it's already deleting a delivery line to not - # delete it again inside `_auto_refresh_delivery()` - deleting_delivery_line = vals.get("order_line") and any( - i[0] == 2 and self.env["sale.order.line"].browse(i[1]).is_delivery - for i in vals["order_line"] - ) - if deleting_delivery_line: - self = self.with_context(deleting_delivery_line=deleting_delivery_line) + # Create or refresh delivery line after saving res = super().write(vals) if self._get_param_auto_add_delivery_line() and not self.env.context.get( "auto_refresh_delivery" @@ -98,8 +90,7 @@ def write(self, vals): return res def _create_delivery_line(self, carrier, price_unit): - """Allow users to keep discounts to delivery lines. Unit price will - be recomputed anyway""" + # Allow users to keep discounts to delivery lines. Unit price will be recomputed anyway sol = super()._create_delivery_line(carrier, price_unit) discount = self.env.context.get("delivery_discount") if discount and sol: @@ -149,8 +140,7 @@ class SaleOrderLine(models.Model): _inherit = "sale.order.line" def _get_protected_fields(self): - """Avoid locked orders validation error when voiding the - delivery line""" + # Avoid locked orders validation error when voiding the delivery line fields = super()._get_protected_fields() if self.env.context.get("delivery_auto_refresh_override_locked"): return [x for x in fields if x not in ["product_uom_qty", "price_unit"]] diff --git a/delivery_auto_refresh/models/stock_picking.py b/delivery_auto_refresh/models/stock_picking.py index 9c806717c7..3fe60d4c59 100644 --- a/delivery_auto_refresh/models/stock_picking.py +++ b/delivery_auto_refresh/models/stock_picking.py @@ -10,7 +10,10 @@ class StockPicking(models.Model): _inherit = "stock.picking" def _add_delivery_cost_to_so(self): - """Update delivery price in SO from picking data.""" + # Update delivery price in SO (no matter the type of carrier invoicing + # policy) and in picking from picking data if indicated so. Carriers + # based on rules doesn't refresh with real picking data, only with SO + # ones. res = super()._add_delivery_cost_to_so() if not get_bool_param(self.env, "refresh_after_picking"): return res From 597bd8de104a17311230a97a09299e7702ea8f81 Mon Sep 17 00:00:00 2001 From: Jacques-Etienne Baudoux Date: Tue, 16 Apr 2024 20:10:41 +0200 Subject: [PATCH 03/16] delivery_auto_refresh: fix create in batch --- delivery_auto_refresh/models/sale_order.py | 12 +++++++----- delivery_auto_refresh/readme/CONTRIBUTORS.rst | 2 ++ 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/delivery_auto_refresh/models/sale_order.py b/delivery_auto_refresh/models/sale_order.py index 3d6653c4a0..a992eb0152 100644 --- a/delivery_auto_refresh/models/sale_order.py +++ b/delivery_auto_refresh/models/sale_order.py @@ -1,5 +1,6 @@ # Copyright 2018 Tecnativa - Pedro M. Baeza # Copyright 2021 Tecnativa - Carlos Roca +# Copyright 2024 Jacques-Etienne Baudoux (BCIM) # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). from odoo import api, fields, models @@ -69,12 +70,13 @@ def _auto_refresh_delivery(self): auto_refresh_delivery=True, skip_validation_check=True ).write({"recompute_delivery_price": False}) - @api.model - def create(self, vals): + @api.model_create_multi + def create(self, vals_list): # Create or refresh delivery line on create - order = super().create(vals) - order._auto_refresh_delivery() - return order + orders = super().create(vals_list) + for order in orders: + order._auto_refresh_delivery() + return orders def write(self, vals): # Create or refresh delivery line after saving diff --git a/delivery_auto_refresh/readme/CONTRIBUTORS.rst b/delivery_auto_refresh/readme/CONTRIBUTORS.rst index a38909d38a..051245e722 100644 --- a/delivery_auto_refresh/readme/CONTRIBUTORS.rst +++ b/delivery_auto_refresh/readme/CONTRIBUTORS.rst @@ -6,3 +6,5 @@ * Camptocamp : * Maksym Yankin * Simone Orsi + +* Jacques-Etienne Baudoux (BCIM) From ad4c6142033a44762e8b0e12c30588dd9dd58be2 Mon Sep 17 00:00:00 2001 From: Jacques-Etienne Baudoux Date: Tue, 16 Apr 2024 20:31:37 +0200 Subject: [PATCH 04/16] delivery_auto_refresh: fix write & discount Limit change of write to calling the auto refresh feature Prevent to call auto refresh multiple times Don't pass discount variable in context --- delivery_auto_refresh/README.rst | 2 + delivery_auto_refresh/models/sale_order.py | 60 ++++++++++--------- .../static/description/index.html | 12 ++-- 3 files changed, 41 insertions(+), 33 deletions(-) diff --git a/delivery_auto_refresh/README.rst b/delivery_auto_refresh/README.rst index 5f7a37bab2..80812ae0c2 100644 --- a/delivery_auto_refresh/README.rst +++ b/delivery_auto_refresh/README.rst @@ -109,6 +109,8 @@ Contributors * Maksym Yankin * Simone Orsi +* Jacques-Etienne Baudoux (BCIM) + Maintainers ~~~~~~~~~~~ diff --git a/delivery_auto_refresh/models/sale_order.py b/delivery_auto_refresh/models/sale_order.py index a992eb0152..b0eb3c2a89 100644 --- a/delivery_auto_refresh/models/sale_order.py +++ b/delivery_auto_refresh/models/sale_order.py @@ -46,29 +46,43 @@ def _get_param_auto_add_delivery_line(self): # e-commerce. So we don't want to add the delivery line automatically. if self.env.context.get("website_id"): return False - return get_bool_param(self.env, "auto_add_delivery_line") + return ( + self.env["ir.config_parameter"] + .sudo() + .get_param("delivery_auto_refresh.auto_add_delivery_line") + ) + + def _get_delivery_discount(self): + self.ensure_one() + delivery_lines = self.order_line.filtered("is_delivery") + return delivery_lines[-1:].discount def _auto_refresh_delivery(self): self.ensure_one() + if self.env.context.get("auto_refresh_delivery"): + return + if not self._get_param_auto_add_delivery_line(): + return + + delivery_discount = self._get_delivery_discount() + # Make sure that if you have removed the carrier, the line is gone if self.state in {"draft", "sent"} and not self.env.context.get( "deleting_delivery_line" ): # Context added to avoid the recursive calls and save the new # value of carrier_id - self.with_context( - auto_refresh_delivery=True, skip_validation_check=True - )._remove_delivery_line() - if self._get_param_auto_add_delivery_line() and self.carrier_id: + self.with_context(auto_refresh_delivery=True)._remove_delivery_line() + if self.carrier_id: if self.state in {"draft", "sent"}: price_unit = self.carrier_id.rate_shipment(self)["price"] if not self.is_all_service: - self.with_context(skip_validation_check=True)._create_delivery_line( - self.carrier_id, price_unit - ) - self.with_context( - auto_refresh_delivery=True, skip_validation_check=True - ).write({"recompute_delivery_price": False}) + sol = self._create_delivery_line(self.carrier_id, price_unit) + if delivery_discount and sol: + sol.discount = delivery_discount + self.with_context(auto_refresh_delivery=True).write( + {"recompute_delivery_price": False} + ) @api.model_create_multi def create(self, vals_list): @@ -79,26 +93,14 @@ def create(self, vals_list): return orders def write(self, vals): - # Create or refresh delivery line after saving - res = super().write(vals) - if self._get_param_auto_add_delivery_line() and not self.env.context.get( - "auto_refresh_delivery" - ): - for order in self: - delivery_line = order.order_line.filtered("is_delivery") - order.with_context( - delivery_discount=delivery_line[-1:].discount, - )._auto_refresh_delivery() + # Prevent to refresh delivery in the call to super + res = super(SaleOrder, self.with_context(auto_refresh_delivery=True)).write( + vals + ) + for order in self: + order._auto_refresh_delivery() return res - def _create_delivery_line(self, carrier, price_unit): - # Allow users to keep discounts to delivery lines. Unit price will be recomputed anyway - sol = super()._create_delivery_line(carrier, price_unit) - discount = self.env.context.get("delivery_discount") - if discount and sol: - sol.discount = discount - return sol - def set_delivery_line(self, carrier, amount): if self._get_param_auto_add_delivery_line() and self.state in {"draft", "sent"}: self.carrier_id = carrier.id diff --git a/delivery_auto_refresh/static/description/index.html b/delivery_auto_refresh/static/description/index.html index a3e5e538f7..8d2eb4cdbe 100644 --- a/delivery_auto_refresh/static/description/index.html +++ b/delivery_auto_refresh/static/description/index.html @@ -8,10 +8,11 @@ /* :Author: David Goodger (goodger@python.org) -:Id: $Id: html4css1.css 8954 2022-01-20 10:10:25Z milde $ +:Id: $Id: html4css1.css 9511 2024-01-13 09:50:07Z milde $ :Copyright: This stylesheet has been placed in the public domain. Default cascading style sheet for the HTML output of Docutils. +Despite the name, some widely supported CSS2 features are used. See https://docutils.sourceforge.io/docs/howto/html-stylesheets.html for how to customize this style sheet. @@ -274,7 +275,7 @@ margin-left: 2em ; margin-right: 2em } -pre.code .ln { color: grey; } /* line numbers */ +pre.code .ln { color: gray; } /* line numbers */ pre.code, code { background-color: #eeeeee } pre.code .comment, code .comment { color: #5C6576 } pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold } @@ -300,7 +301,7 @@ span.pre { white-space: pre } -span.problematic { +span.problematic, pre.problematic { color: red } span.section-subtitle { @@ -457,12 +458,15 @@

Contributors

  • Camptocamp <https://www.camptocamp.com>: * Maksym Yankin * Simone Orsi
  • +
  • Jacques-Etienne Baudoux (BCIM) <je@bcim.be>
  • Maintainers

    This module is maintained by the OCA.

    -Odoo Community Association + +Odoo Community Association +

    OCA, or the Odoo Community Association, is a nonprofit organization whose mission is to support the collaborative development of Odoo features and promote its widespread use.

    From d968a37b78237a4e8e4c881173918aa519020267 Mon Sep 17 00:00:00 2001 From: Jacques-Etienne Baudoux Date: Tue, 16 Apr 2024 20:35:53 +0200 Subject: [PATCH 05/16] delivery_auto_refresh: iterate over list, not set --- delivery_auto_refresh/models/sale_order.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/delivery_auto_refresh/models/sale_order.py b/delivery_auto_refresh/models/sale_order.py index b0eb3c2a89..c04a5e2254 100644 --- a/delivery_auto_refresh/models/sale_order.py +++ b/delivery_auto_refresh/models/sale_order.py @@ -67,14 +67,12 @@ def _auto_refresh_delivery(self): delivery_discount = self._get_delivery_discount() # Make sure that if you have removed the carrier, the line is gone - if self.state in {"draft", "sent"} and not self.env.context.get( - "deleting_delivery_line" - ): + if self.state in ("draft", "sent"): # Context added to avoid the recursive calls and save the new # value of carrier_id self.with_context(auto_refresh_delivery=True)._remove_delivery_line() if self.carrier_id: - if self.state in {"draft", "sent"}: + if self.state in ("draft", "sent"): price_unit = self.carrier_id.rate_shipment(self)["price"] if not self.is_all_service: sol = self._create_delivery_line(self.carrier_id, price_unit) @@ -102,7 +100,7 @@ def write(self, vals): return res def set_delivery_line(self, carrier, amount): - if self._get_param_auto_add_delivery_line() and self.state in {"draft", "sent"}: + if self._get_param_auto_add_delivery_line() and self.state in ("draft", "sent"): self.carrier_id = carrier.id else: return super().set_delivery_line(carrier, amount) @@ -129,7 +127,7 @@ def _is_delivery_line_voidable(self): # nothing to be done either. If there are more than one delivery lines # we won't be doing anything as well. if ( - self.state not in {"done", "sale"} + self.state not in ("done", "sale") or self.invoice_ids or not self.order_line.filtered("is_delivery") or len(self.order_line.filtered("is_delivery")) > 1 From 095265dfdc29dc25ffc41131fcd82096ded6da48 Mon Sep 17 00:00:00 2001 From: Jacques-Etienne Baudoux Date: Tue, 16 Apr 2024 22:06:02 +0200 Subject: [PATCH 06/16] delivery_auto_refresh: refresh the minimum Create or delete line only if necessary Update existing line if necessary --- delivery_auto_refresh/README.rst | 2 - delivery_auto_refresh/models/sale_order.py | 89 +++++++++++++------ delivery_auto_refresh/readme/ROADMAP.rst | 2 - .../static/description/index.html | 2 - 4 files changed, 61 insertions(+), 34 deletions(-) diff --git a/delivery_auto_refresh/README.rst b/delivery_auto_refresh/README.rst index 80812ae0c2..95a6bd5bb4 100644 --- a/delivery_auto_refresh/README.rst +++ b/delivery_auto_refresh/README.rst @@ -71,8 +71,6 @@ Known issues / Roadmap * After confirming the sales order, the price of the delivery line (if exists) will be only updated after the picking is transferred, but not when you might modify the order lines. -* There can be some duplicate delivery unset/set for assuring that the refresh - is done on all cases. * On multiple deliveries, second and successive pickings update the delivery price, but you can't invoice the new delivery price. * This is only working from user interface, as there's no way of making diff --git a/delivery_auto_refresh/models/sale_order.py b/delivery_auto_refresh/models/sale_order.py index c04a5e2254..58f985fd4e 100644 --- a/delivery_auto_refresh/models/sale_order.py +++ b/delivery_auto_refresh/models/sale_order.py @@ -52,10 +52,37 @@ def _get_param_auto_add_delivery_line(self): .get_param("delivery_auto_refresh.auto_add_delivery_line") ) - def _get_delivery_discount(self): - self.ensure_one() - delivery_lines = self.order_line.filtered("is_delivery") - return delivery_lines[-1:].discount + def _update_delivery_line(self, delivery_line, price_unit): + """Update the existing delivery line""" + values = self._prepare_delivery_line_vals(self.carrier_id, price_unit) + new_vals = {} + for f, val in values.items(): + field_def = delivery_line._fields.get(f) + if isinstance(field_def, (fields.One2many, fields.Many2many)): + # Tax is set with a SET command + clear = update = False + for cmd in val: + if cmd[0] == fields.Command.SET: + if delivery_line[f].ids != cmd[2]: + update = True + else: + clear = True + if clear: + new_vals[f] = [fields.Command.CLEAR] + val + elif update: + new_vals[f] = val + elif isinstance(field_def, fields.Many2one): + if delivery_line[f].id != val: + new_vals[f] = val + elif f == "sequence": + # sequence is last sequence + 1. As the delivery line already + # exists, substract 1 + if delivery_line[f] != val - 1: + new_vals[f] = val + elif delivery_line[f] != val: + new_vals[f] = val + if new_vals: + delivery_line.write(new_vals) def _auto_refresh_delivery(self): self.ensure_one() @@ -63,29 +90,40 @@ def _auto_refresh_delivery(self): return if not self._get_param_auto_add_delivery_line(): return + if self.state not in ("draft", "sent"): + return - delivery_discount = self._get_delivery_discount() - - # Make sure that if you have removed the carrier, the line is gone - if self.state in ("draft", "sent"): - # Context added to avoid the recursive calls and save the new - # value of carrier_id - self.with_context(auto_refresh_delivery=True)._remove_delivery_line() - if self.carrier_id: - if self.state in ("draft", "sent"): - price_unit = self.carrier_id.rate_shipment(self)["price"] - if not self.is_all_service: - sol = self._create_delivery_line(self.carrier_id, price_unit) - if delivery_discount and sol: - sol.discount = delivery_discount - self.with_context(auto_refresh_delivery=True).write( - {"recompute_delivery_price": False} - ) + self = self.with_context(auto_refresh_delivery=True) + + if not self.carrier_id: + self._set_delivery_carrier() + + if not self.carrier_id or self.is_all_service: + self._remove_delivery_line() + else: + price_unit = self.carrier_id.rate_shipment(self)["price"] + delivery_lines = self.order_line.filtered("is_delivery") + if not delivery_lines: + self._create_delivery_line(self.carrier_id, price_unit) + elif len(delivery_lines) > 1: + delivery_discount = delivery_lines[-1:].discount + self._remove_delivery_line() + sol = self._create_delivery_line(self.carrier_id, price_unit) + if delivery_discount and sol: + sol.discount = delivery_discount + else: + self._update_delivery_line(delivery_lines[0], price_unit) + if self.recompute_delivery_price: + self.recompute_delivery_price = False @api.model_create_multi def create(self, vals_list): - # Create or refresh delivery line on create - orders = super().create(vals_list) + # Prevent to refresh delivery in the call to super + orders = ( + super(SaleOrder, self.with_context(auto_refresh_delivery=True)) + .create(vals_list) + .with_context(auto_refresh_delivery=False) + ) for order in orders: order._auto_refresh_delivery() return orders @@ -105,11 +143,6 @@ def set_delivery_line(self, carrier, amount): else: return super().set_delivery_line(carrier, amount) - def _remove_delivery_line(self): - current_carrier = self.carrier_id - super()._remove_delivery_line() - self.carrier_id = current_carrier - def _is_delivery_line_voidable(self): """If the picking is returned before being invoiced, like when the picking is delivered but immediately return because the customer refused the order, diff --git a/delivery_auto_refresh/readme/ROADMAP.rst b/delivery_auto_refresh/readme/ROADMAP.rst index 7a7d2a7098..5d14317254 100644 --- a/delivery_auto_refresh/readme/ROADMAP.rst +++ b/delivery_auto_refresh/readme/ROADMAP.rst @@ -1,8 +1,6 @@ * After confirming the sales order, the price of the delivery line (if exists) will be only updated after the picking is transferred, but not when you might modify the order lines. -* There can be some duplicate delivery unset/set for assuring that the refresh - is done on all cases. * On multiple deliveries, second and successive pickings update the delivery price, but you can't invoice the new delivery price. * This is only working from user interface, as there's no way of making diff --git a/delivery_auto_refresh/static/description/index.html b/delivery_auto_refresh/static/description/index.html index 8d2eb4cdbe..198c5cbc38 100644 --- a/delivery_auto_refresh/static/description/index.html +++ b/delivery_auto_refresh/static/description/index.html @@ -423,8 +423,6 @@

    Known issues / Roadmap

  • After confirming the sales order, the price of the delivery line (if exists) will be only updated after the picking is transferred, but not when you might modify the order lines.
  • -
  • There can be some duplicate delivery unset/set for assuring that the refresh -is done on all cases.
  • On multiple deliveries, second and successive pickings update the delivery price, but you can’t invoice the new delivery price.
  • This is only working from user interface, as there’s no way of making From e1f60bb4ff9173c905bc69db80f4dbb592386a66 Mon Sep 17 00:00:00 2001 From: Jacques-Etienne Baudoux Date: Tue, 16 Apr 2024 23:01:23 +0200 Subject: [PATCH 07/16] delivery_auto_refresh: set carrier --- delivery_auto_refresh/README.rst | 24 +++-------- delivery_auto_refresh/__manifest__.py | 8 +++- .../migrations/16.0.2.0.0/post-migration.py | 16 +++++++ .../models/res_config_settings.py | 21 +++++++++ delivery_auto_refresh/models/sale_order.py | 24 ++--------- delivery_auto_refresh/readme/CONFIGURE.rst | 24 +++-------- .../static/description/index.html | 25 ++--------- .../tests/test_delivery_auto_refresh.py | 25 +++-------- .../views/res_config_settings_views.xml | 43 +++++++++++++++++++ 9 files changed, 109 insertions(+), 101 deletions(-) create mode 100644 delivery_auto_refresh/migrations/16.0.2.0.0/post-migration.py create mode 100644 delivery_auto_refresh/models/res_config_settings.py create mode 100644 delivery_auto_refresh/views/res_config_settings_views.xml diff --git a/delivery_auto_refresh/README.rst b/delivery_auto_refresh/README.rst index 95a6bd5bb4..66d338897b 100644 --- a/delivery_auto_refresh/README.rst +++ b/delivery_auto_refresh/README.rst @@ -45,25 +45,11 @@ This module automates the delivery price handling for the following cases: Configuration ============= -* Activate developer mode. -* Go to *Settings > Technical > Parameters > System Parameters*. -* Locate the setting with key "delivery_auto_refresh.set_default_carrier" - or create a new one if not exists. - Put a non Falsy value (1, True...) if you want to have default carrier computed - automatically. -* Locate the setting with key "delivery_auto_refresh.auto_add_delivery_line" - or create a new one if not exists. - Put a non Falsy value (1, True...) if you want to add automatically the - delivery line on save. -* Locate the setting with key "delivery_auto_refresh.refresh_after_picking" - or create a new one if not exists. - Put a non Falsy value (1, True...) if you want to refresh delivery price - after transferring. -* Locate the setting with key "delivery_auto_refresh.auto_void_delivery_line" - or create a new one if it doesn't exists. - Put a non Falsy value (1, True...) if you want to void the delivery line - values (price, units ordered, units delivered) in the sale order when the - delivered picking is returned to refund prior to be invoiced. +Go to *Settings > Sales > Shipping*: +* Enable "Refresh shipping cost line automatically" if you want to add automatically the delivery line on save and refresh the cost. This will also set the shipping method. +* Enable "Refresh After Picking Automatically" if you want to refresh delivery price after delivering based on what has been delivered. +* Enable "Void delivery lines automatically" if you want to void the delivery line values (price, units ordered, units delivered) in the sale order when the delivery is returned to refund prior to be invoiced. + Known issues / Roadmap ====================== diff --git a/delivery_auto_refresh/__manifest__.py b/delivery_auto_refresh/__manifest__.py index 1685fda095..8105ab1852 100644 --- a/delivery_auto_refresh/__manifest__.py +++ b/delivery_auto_refresh/__manifest__.py @@ -12,6 +12,10 @@ "license": "AGPL-3", "application": False, "installable": True, - "depends": ["delivery"], - "data": ["data/ir_config_parameter.xml", "views/sale_order_views.xml"], + "depends": ["delivery", "sale_order_carrier_auto_assign"], + "data": [ + "data/ir_config_parameter.xml", + "views/sale_order_views.xml", + "views/res_config_settings_views.xml", + ], } diff --git a/delivery_auto_refresh/migrations/16.0.2.0.0/post-migration.py b/delivery_auto_refresh/migrations/16.0.2.0.0/post-migration.py new file mode 100644 index 0000000000..e06e317083 --- /dev/null +++ b/delivery_auto_refresh/migrations/16.0.2.0.0/post-migration.py @@ -0,0 +1,16 @@ +# Copyright 2024 Jacques-Etienne Baudoux (BCIM) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import SUPERUSER_ID, api + + +def _migrate_setting_to_company(env): + if env["ir.config_parameter"].get_param( + "delivery_auto_refresh.set_default_carrier" + ): + env["res.company"].search([]).carrier_auto_assign_on_create = True + + +def migrate(cr, version): + env = api.Environment(cr, SUPERUSER_ID, {}) + _migrate_setting_to_company(env) diff --git a/delivery_auto_refresh/models/res_config_settings.py b/delivery_auto_refresh/models/res_config_settings.py new file mode 100644 index 0000000000..fd73d5e5de --- /dev/null +++ b/delivery_auto_refresh/models/res_config_settings.py @@ -0,0 +1,21 @@ +# Copyright 2023 Tecnativa - Pilar Vargas Moreno +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo import fields, models + + +class ResConfigSettings(models.TransientModel): + _inherit = "res.config.settings" + + auto_add_delivery_line = fields.Boolean( + "Refresh shipping cost line automatically", + config_parameter="delivery_auto_refresh.auto_add_delivery_line", + ) + refresh_after_picking = fields.Boolean( + "Refresh after picking automatically", + config_parameter="delivery_auto_refresh.refresh_after_picking", + ) + auto_void_delivery_line = fields.Boolean( + "Void delivery lines automatically", + config_parameter="delivery_auto_refresh.auto_void_delivery_line", + ) diff --git a/delivery_auto_refresh/models/sale_order.py b/delivery_auto_refresh/models/sale_order.py index 58f985fd4e..10b789d8b5 100644 --- a/delivery_auto_refresh/models/sale_order.py +++ b/delivery_auto_refresh/models/sale_order.py @@ -5,35 +5,16 @@ from odoo import api, fields, models -from ..utils import get_bool_param - class SaleOrder(models.Model): _inherit = "sale.order" + # Migration note: This field is not used anymore and can be dropped in later versions available_carrier_ids = fields.Many2many( comodel_name="delivery.carrier", compute="_compute_available_carrier_ids", ) - @api.onchange("partner_id", "partner_shipping_id") - def _onchange_partner_id(self): - if hasattr(super(), "_onchange_partner_id"): - super()._onchange_partner_id() - if get_bool_param(self.env, "set_default_carrier"): - for order in self: - action = order.action_open_delivery_wizard() - carrier_id = self.env["delivery.carrier"].browse( - action["context"]["default_carrier_id"] - ) - # If the carrier isn't allowed for the current shipping address, we wont - # default to it. In that case we'd try to fallback to the former carrier. - order.carrier_id = fields.first( - (carrier_id | order.carrier_id).filtered( - lambda x: x in order.available_carrier_ids._origin - ) - ) - @api.depends("partner_shipping_id") def _compute_available_carrier_ids(self): """We want to apply the same carriers filter in the header as in the wizard""" @@ -41,6 +22,8 @@ def _compute_available_carrier_ids(self): wizard = self.env["choose.delivery.carrier"].new({"order_id": sale.id}) sale.available_carrier_ids = wizard.available_carrier_ids._origin + # End migration note + def _get_param_auto_add_delivery_line(self): # When we have the context 'website_id' it means that we are doing the order from # e-commerce. So we don't want to add the delivery line automatically. @@ -139,6 +122,7 @@ def write(self, vals): def set_delivery_line(self, carrier, amount): if self._get_param_auto_add_delivery_line() and self.state in ("draft", "sent"): + # This will trigger an _auto_refresh_delivery in write self.carrier_id = carrier.id else: return super().set_delivery_line(carrier, amount) diff --git a/delivery_auto_refresh/readme/CONFIGURE.rst b/delivery_auto_refresh/readme/CONFIGURE.rst index dab0baaba0..82767725fd 100644 --- a/delivery_auto_refresh/readme/CONFIGURE.rst +++ b/delivery_auto_refresh/readme/CONFIGURE.rst @@ -1,19 +1,5 @@ -* Activate developer mode. -* Go to *Settings > Technical > Parameters > System Parameters*. -* Locate the setting with key "delivery_auto_refresh.set_default_carrier" - or create a new one if not exists. - Put a non Falsy value (1, True...) if you want to have default carrier computed - automatically. -* Locate the setting with key "delivery_auto_refresh.auto_add_delivery_line" - or create a new one if not exists. - Put a non Falsy value (1, True...) if you want to add automatically the - delivery line on save. -* Locate the setting with key "delivery_auto_refresh.refresh_after_picking" - or create a new one if not exists. - Put a non Falsy value (1, True...) if you want to refresh delivery price - after transferring. -* Locate the setting with key "delivery_auto_refresh.auto_void_delivery_line" - or create a new one if it doesn't exists. - Put a non Falsy value (1, True...) if you want to void the delivery line - values (price, units ordered, units delivered) in the sale order when the - delivered picking is returned to refund prior to be invoiced. +Go to *Settings > Sales > Shipping*: +* Enable "Refresh shipping cost line automatically" if you want to add automatically the delivery line on save and refresh the cost. This will also set the shipping method. +* Enable "Refresh After Picking Automatically" if you want to refresh delivery price after delivering based on what has been delivered. +* Enable "Void delivery lines automatically" if you want to void the delivery line values (price, units ordered, units delivered) in the sale order when the delivery is returned to refund prior to be invoiced. + diff --git a/delivery_auto_refresh/static/description/index.html b/delivery_auto_refresh/static/description/index.html index 198c5cbc38..682b00af0a 100644 --- a/delivery_auto_refresh/static/description/index.html +++ b/delivery_auto_refresh/static/description/index.html @@ -395,27 +395,10 @@

    Auto-refresh delivery

  • Configuration

    -
      -
    • Activate developer mode.
    • -
    • Go to Settings > Technical > Parameters > System Parameters.
    • -
    • Locate the setting with key “delivery_auto_refresh.set_default_carrier” -or create a new one if not exists. -Put a non Falsy value (1, True…) if you want to have default carrier computed -automatically.
    • -
    • Locate the setting with key “delivery_auto_refresh.auto_add_delivery_line” -or create a new one if not exists. -Put a non Falsy value (1, True…) if you want to add automatically the -delivery line on save.
    • -
    • Locate the setting with key “delivery_auto_refresh.refresh_after_picking” -or create a new one if not exists. -Put a non Falsy value (1, True…) if you want to refresh delivery price -after transferring.
    • -
    • Locate the setting with key “delivery_auto_refresh.auto_void_delivery_line” -or create a new one if it doesn’t exists. -Put a non Falsy value (1, True…) if you want to void the delivery line -values (price, units ordered, units delivered) in the sale order when the -delivered picking is returned to refund prior to be invoiced.
    • -
    +

    Go to Settings > Sales > Shipping: +* Enable “Refresh shipping cost line automatically” if you want to add automatically the delivery line on save and refresh the cost. This will also set the shipping method. +* Enable “Refresh After Picking Automatically” if you want to refresh delivery price after delivering based on what has been delivered. +* Enable “Void delivery lines automatically” if you want to void the delivery line values (price, units ordered, units delivered) in the sale order when the delivery is returned to refund prior to be invoiced.

    Known issues / Roadmap

    diff --git a/delivery_auto_refresh/tests/test_delivery_auto_refresh.py b/delivery_auto_refresh/tests/test_delivery_auto_refresh.py index 698cf31a48..3c8909e05f 100644 --- a/delivery_auto_refresh/tests/test_delivery_auto_refresh.py +++ b/delivery_auto_refresh/tests/test_delivery_auto_refresh.py @@ -67,11 +67,11 @@ def setUpClass(cls): "property_product_pricelist": pricelist.id, } ) - cls.param_name1 = "delivery_auto_refresh.auto_add_delivery_line" - cls.param_name2 = "delivery_auto_refresh.refresh_after_picking" - cls.param_name3 = "delivery_auto_refresh.auto_void_delivery_line" - cls.param_name4 = "delivery_auto_refresh.set_default_carrier" - cls.env["ir.config_parameter"].sudo().set_param(cls.param_name4, 1) + cls.auto_add_delivery_line = "delivery_auto_refresh.auto_add_delivery_line" + cls.refresh_after_picking = "delivery_auto_refresh.refresh_after_picking" + cls.auto_void_delivery_line = "delivery_auto_refresh.auto_void_delivery_line" + cls.settings = cls.env["res.config.settings"].create({}) + cls.settings.execute() order_form = Form(cls.env["sale.order"]) order_form.partner_id = cls.partner order_form.partner_invoice_id = cls.partner @@ -192,21 +192,6 @@ def test_no_auto_refresh_picking(self): line_delivery = self.order.order_line.filtered("is_delivery") self.assertEqual(line_delivery.price_unit, 60) - def test_compute_carrier_id(self): - order_form_1 = Form(self.env["sale.order"]) - order_form_1.partner_id = self.partner - self.assertEqual(order_form_1.carrier_id, self.carrier_1) - partner_without_carrier = self.env["res.partner"].create( - { - "name": "Test partner without carrier", - "property_delivery_carrier_id": False, - } - ) - no_carrier = self.env["delivery.carrier"] - order_form_2 = Form(self.env["sale.order"]) - order_form_2.partner_id = partner_without_carrier - self.assertEqual(order_form_2.carrier_id, no_carrier) - def _confirm_sale_order(self, order): sale_form = Form(order) # Force the delivery line creation diff --git a/delivery_auto_refresh/views/res_config_settings_views.xml b/delivery_auto_refresh/views/res_config_settings_views.xml new file mode 100644 index 0000000000..2cc2fa5695 --- /dev/null +++ b/delivery_auto_refresh/views/res_config_settings_views.xml @@ -0,0 +1,43 @@ + + + + res.config.settings.view.form.inherit.sale + res.config.settings + + + + +
    + +
    +
    +
    +
    + +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    From ea43bd10f385c67dd3064bb4f640a85e15814cf2 Mon Sep 17 00:00:00 2001 From: Jacques-Etienne Baudoux Date: Tue, 16 Apr 2024 23:32:40 +0200 Subject: [PATCH 08/16] delivery_auto_refresh: refresh on SO line create/write --- delivery_auto_refresh/models/sale_order.py | 17 +++++++++++++++++ delivery_auto_refresh/readme/ROADMAP.rst | 3 --- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/delivery_auto_refresh/models/sale_order.py b/delivery_auto_refresh/models/sale_order.py index 10b789d8b5..31146265a5 100644 --- a/delivery_auto_refresh/models/sale_order.py +++ b/delivery_auto_refresh/models/sale_order.py @@ -164,3 +164,20 @@ def _get_protected_fields(self): if self.env.context.get("delivery_auto_refresh_override_locked"): return [x for x in fields if x not in ["product_uom_qty", "price_unit"]] return fields + + @api.model_create_multi + def create(self, vals_list): + lines = super( + SaleOrderLine, self.with_context(auto_refresh_delivery=True) + ).create(vals_list) + for order in lines.order_id: + order._auto_refresh_delivery() + return lines + + def write(self, vals): + res = super(SaleOrderLine, self.with_context(auto_refresh_delivery=True)).write( + vals + ) + for order in self.order_id: + order._auto_refresh_delivery() + return res diff --git a/delivery_auto_refresh/readme/ROADMAP.rst b/delivery_auto_refresh/readme/ROADMAP.rst index 5d14317254..abfc8b2e83 100644 --- a/delivery_auto_refresh/readme/ROADMAP.rst +++ b/delivery_auto_refresh/readme/ROADMAP.rst @@ -3,6 +3,3 @@ might modify the order lines. * On multiple deliveries, second and successive pickings update the delivery price, but you can't invoice the new delivery price. -* This is only working from user interface, as there's no way of making - compatible the auto-refresh intercepting create/write methods from sale order - lines. From 6ac4ea3b5658934a7c9df8c9565ee21a02f58076 Mon Sep 17 00:00:00 2001 From: Jacques-Etienne Baudoux Date: Tue, 16 Apr 2024 23:31:35 +0200 Subject: [PATCH 09/16] delivery_auto_refresh: improve help & readme --- delivery_auto_refresh/README.rst | 13 +++++++------ delivery_auto_refresh/readme/CONFIGURE.rst | 10 +++++++--- .../static/description/index.html | 17 ++++++++++------- .../views/res_config_settings_views.xml | 2 ++ 4 files changed, 26 insertions(+), 16 deletions(-) diff --git a/delivery_auto_refresh/README.rst b/delivery_auto_refresh/README.rst index 66d338897b..eb2748ea51 100644 --- a/delivery_auto_refresh/README.rst +++ b/delivery_auto_refresh/README.rst @@ -46,10 +46,14 @@ Configuration ============= Go to *Settings > Sales > Shipping*: -* Enable "Refresh shipping cost line automatically" if you want to add automatically the delivery line on save and refresh the cost. This will also set the shipping method. -* Enable "Refresh After Picking Automatically" if you want to refresh delivery price after delivering based on what has been delivered. -* Enable "Void delivery lines automatically" if you want to void the delivery line values (price, units ordered, units delivered) in the sale order when the delivery is returned to refund prior to be invoiced. +* Enable "Refresh shipping cost line automatically" if you want to add automatically the + delivery line on save and refresh the cost. This will also set the shipping method. +* Enable "Refresh After Picking Automatically" if you want to refresh delivery + price after delivering based on what has been delivered. +* Enable "Void delivery lines automatically" if you want to void the delivery + line values (price, units ordered, units delivered) in the sale order when + the delivery is returned to refund prior to be invoiced. Known issues / Roadmap ====================== @@ -59,9 +63,6 @@ Known issues / Roadmap might modify the order lines. * On multiple deliveries, second and successive pickings update the delivery price, but you can't invoice the new delivery price. -* This is only working from user interface, as there's no way of making - compatible the auto-refresh intercepting create/write methods from sale order - lines. Bug Tracker =========== diff --git a/delivery_auto_refresh/readme/CONFIGURE.rst b/delivery_auto_refresh/readme/CONFIGURE.rst index 82767725fd..bb9cdf540c 100644 --- a/delivery_auto_refresh/readme/CONFIGURE.rst +++ b/delivery_auto_refresh/readme/CONFIGURE.rst @@ -1,5 +1,9 @@ Go to *Settings > Sales > Shipping*: -* Enable "Refresh shipping cost line automatically" if you want to add automatically the delivery line on save and refresh the cost. This will also set the shipping method. -* Enable "Refresh After Picking Automatically" if you want to refresh delivery price after delivering based on what has been delivered. -* Enable "Void delivery lines automatically" if you want to void the delivery line values (price, units ordered, units delivered) in the sale order when the delivery is returned to refund prior to be invoiced. +* Enable "Refresh shipping cost line automatically" if you want to add automatically the + delivery line on save and refresh the cost. This will also set the shipping method. +* Enable "Refresh After Picking Automatically" if you want to refresh delivery + price after delivering based on what has been delivered. +* Enable "Void delivery lines automatically" if you want to void the delivery + line values (price, units ordered, units delivered) in the sale order when + the delivery is returned to refund prior to be invoiced. diff --git a/delivery_auto_refresh/static/description/index.html b/delivery_auto_refresh/static/description/index.html index 682b00af0a..c82ea46318 100644 --- a/delivery_auto_refresh/static/description/index.html +++ b/delivery_auto_refresh/static/description/index.html @@ -395,10 +395,16 @@

    Auto-refresh delivery

    Configuration

    -

    Go to Settings > Sales > Shipping: -* Enable “Refresh shipping cost line automatically” if you want to add automatically the delivery line on save and refresh the cost. This will also set the shipping method. -* Enable “Refresh After Picking Automatically” if you want to refresh delivery price after delivering based on what has been delivered. -* Enable “Void delivery lines automatically” if you want to void the delivery line values (price, units ordered, units delivered) in the sale order when the delivery is returned to refund prior to be invoiced.

    +

    Go to Settings > Sales > Shipping:

    +
      +
    • Enable “Refresh shipping cost line automatically” if you want to add automatically the +delivery line on save and refresh the cost. This will also set the shipping method.
    • +
    • Enable “Refresh After Picking Automatically” if you want to refresh delivery +price after delivering based on what has been delivered.
    • +
    • Enable “Void delivery lines automatically” if you want to void the delivery +line values (price, units ordered, units delivered) in the sale order when +the delivery is returned to refund prior to be invoiced.
    • +

    Known issues / Roadmap

    @@ -408,9 +414,6 @@

    Known issues / Roadmap

    might modify the order lines.
  • On multiple deliveries, second and successive pickings update the delivery price, but you can’t invoice the new delivery price.
  • -
  • This is only working from user interface, as there’s no way of making -compatible the auto-refresh intercepting create/write methods from sale order -lines.
  • diff --git a/delivery_auto_refresh/views/res_config_settings_views.xml b/delivery_auto_refresh/views/res_config_settings_views.xml index 2cc2fa5695..4c1d860ac2 100644 --- a/delivery_auto_refresh/views/res_config_settings_views.xml +++ b/delivery_auto_refresh/views/res_config_settings_views.xml @@ -19,6 +19,7 @@ On the sales quotation, refresh the shipping cost line when saving
    +
    @@ -28,6 +29,7 @@ After delivering a sales order, update the shipping cost line based on what has been delivered +
    From 2414160e17e44fb0b5fef6168f8ac095586b80af Mon Sep 17 00:00:00 2001 From: Jacques-Etienne Baudoux Date: Tue, 16 Apr 2024 23:50:32 +0200 Subject: [PATCH 10/16] delivery_auto_refresh: add tests --- delivery_auto_refresh/tests/test_delivery_auto_refresh.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/delivery_auto_refresh/tests/test_delivery_auto_refresh.py b/delivery_auto_refresh/tests/test_delivery_auto_refresh.py index 3c8909e05f..cfde548b3d 100644 --- a/delivery_auto_refresh/tests/test_delivery_auto_refresh.py +++ b/delivery_auto_refresh/tests/test_delivery_auto_refresh.py @@ -289,7 +289,8 @@ def test_auto_refresh_so_and_unlink_line(self): self.assertFalse(delivery_line.exists()) def test_auto_add_delivery_line_add_service(self): - self.env["ir.config_parameter"].sudo().set_param(self.param_name1, 1) + """No delivery line when service only""" + self.env["ir.config_parameter"].sudo().set_param(self.auto_add_delivery_line, 1) service = self.env["product.product"].create( {"name": "Service Test", "type": "service"} ) @@ -305,7 +306,7 @@ def test_auto_add_delivery_line_add_service(self): self.assertFalse(delivery_line.exists()) def test_auto_refresh_so_and_manually_unlink_delivery_line(self): - """Test that we are able to manually remove the delivery line""" + """Manually remove the delivery line""" self._test_autorefresh_unlink_line() sale_form = Form(self.order) # Deleting the delivery line From bf2f48f42e91235951e10ac9f73607925ebfd9f6 Mon Sep 17 00:00:00 2001 From: Jacques-Etienne Baudoux Date: Thu, 18 Apr 2024 12:25:12 +0200 Subject: [PATCH 11/16] delivery-carrier: postpone new dependency to 17.0 This commit can be reverted in the migration to 17.0 --- delivery_auto_refresh/README.rst | 2 + delivery_auto_refresh/__manifest__.py | 4 +- .../migrations/16.0.2.0.0/post-migration.py | 2 +- delivery_auto_refresh/models/__init__.py | 2 + delivery_auto_refresh/models/res_company.py | 14 ++++ .../models/res_config_settings.py | 7 ++ delivery_auto_refresh/models/sale_order.py | 52 ++++++++++++ delivery_auto_refresh/readme/CONFIGURE.rst | 2 + .../static/description/index.html | 2 + delivery_auto_refresh/tests/__init__.py | 1 + .../test_sale_order_carrier_auto_assign.py | 81 +++++++++++++++++++ .../views/res_config_settings_views.xml | 18 +++++ 12 files changed, 185 insertions(+), 2 deletions(-) create mode 100644 delivery_auto_refresh/models/res_company.py create mode 100644 delivery_auto_refresh/tests/test_sale_order_carrier_auto_assign.py diff --git a/delivery_auto_refresh/README.rst b/delivery_auto_refresh/README.rst index eb2748ea51..379f880eab 100644 --- a/delivery_auto_refresh/README.rst +++ b/delivery_auto_refresh/README.rst @@ -47,6 +47,8 @@ Configuration Go to *Settings > Sales > Shipping*: +* Enable "Set default shipping method automalically" if you want to add + automatically the carrier on the sales quotation creation. * Enable "Refresh shipping cost line automatically" if you want to add automatically the delivery line on save and refresh the cost. This will also set the shipping method. * Enable "Refresh After Picking Automatically" if you want to refresh delivery diff --git a/delivery_auto_refresh/__manifest__.py b/delivery_auto_refresh/__manifest__.py index 8105ab1852..e70dfffdc0 100644 --- a/delivery_auto_refresh/__manifest__.py +++ b/delivery_auto_refresh/__manifest__.py @@ -12,7 +12,9 @@ "license": "AGPL-3", "application": False, "installable": True, - "depends": ["delivery", "sale_order_carrier_auto_assign"], + "depends": ["delivery"], + # Migration Note 17.0: Add dependency to sale_order_carrier_auto_assign + # "depends": ["delivery", "sale_order_carrier_auto_assign"], "data": [ "data/ir_config_parameter.xml", "views/sale_order_views.xml", diff --git a/delivery_auto_refresh/migrations/16.0.2.0.0/post-migration.py b/delivery_auto_refresh/migrations/16.0.2.0.0/post-migration.py index e06e317083..db854d8433 100644 --- a/delivery_auto_refresh/migrations/16.0.2.0.0/post-migration.py +++ b/delivery_auto_refresh/migrations/16.0.2.0.0/post-migration.py @@ -8,7 +8,7 @@ def _migrate_setting_to_company(env): if env["ir.config_parameter"].get_param( "delivery_auto_refresh.set_default_carrier" ): - env["res.company"].search([]).carrier_auto_assign_on_create = True + env["res.company"].search([]).sale_auto_assign_carrier_on_create = True def migrate(cr, version): diff --git a/delivery_auto_refresh/models/__init__.py b/delivery_auto_refresh/models/__init__.py index c0b4257cf6..c50cfc74d2 100644 --- a/delivery_auto_refresh/models/__init__.py +++ b/delivery_auto_refresh/models/__init__.py @@ -1,2 +1,4 @@ from . import sale_order from . import stock_picking +from . import res_company +from . import res_config_settings diff --git a/delivery_auto_refresh/models/res_company.py b/delivery_auto_refresh/models/res_company.py new file mode 100644 index 0000000000..9ec9f4c022 --- /dev/null +++ b/delivery_auto_refresh/models/res_company.py @@ -0,0 +1,14 @@ +# Copyright 2024 Jacques-Etienne Baudoux (BCIM) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import fields, models + + +class ResCompany(models.Model): + _inherit = "res.company" + + # Migration Note 17.0: move this to module sale_order_carrier_auto_assign + sale_auto_assign_carrier_on_create = fields.Boolean( + "Set default shipping method automatically" + ) + # End migration note diff --git a/delivery_auto_refresh/models/res_config_settings.py b/delivery_auto_refresh/models/res_config_settings.py index fd73d5e5de..33f46d2e00 100644 --- a/delivery_auto_refresh/models/res_config_settings.py +++ b/delivery_auto_refresh/models/res_config_settings.py @@ -7,6 +7,13 @@ class ResConfigSettings(models.TransientModel): _inherit = "res.config.settings" + # Migration Note 17.0: move this to module sale_order_carrier_auto_assign + sale_auto_assign_carrier_on_create = fields.Boolean( + related="company_id.sale_auto_assign_carrier_on_create", + readonly=False, + ) + # End migration note + auto_add_delivery_line = fields.Boolean( "Refresh shipping cost line automatically", config_parameter="delivery_auto_refresh.auto_add_delivery_line", diff --git a/delivery_auto_refresh/models/sale_order.py b/delivery_auto_refresh/models/sale_order.py index 31146265a5..5c7a60acbc 100644 --- a/delivery_auto_refresh/models/sale_order.py +++ b/delivery_auto_refresh/models/sale_order.py @@ -24,6 +24,54 @@ def _compute_available_carrier_ids(self): # End migration note + # Migration Note 17.0: move this section to module sale_order_carrier_auto_assign + def _set_delivery_carrier(self, set_delivery_line=True): + for order in self: + delivery_wiz_action = order.action_open_delivery_wizard() + delivery_wiz_context = delivery_wiz_action.get("context", {}) + if not delivery_wiz_context.get("default_carrier_id"): + continue + delivery_wiz = ( + self.env[delivery_wiz_action.get("res_model")] + .with_context(**delivery_wiz_context) + .new({}) + ) + + # Do not override carrier + if order.carrier_id: + delivery_wiz.carrier_id = order.carrier_id + + # If the carrier isn't allowed, we won't default to it + if ( + delivery_wiz.carrier_id + not in delivery_wiz.available_carrier_ids._origin + ): + continue + + if not set_delivery_line or order.is_all_service: + # Only set the carrier + if order.carrier_id != delivery_wiz.carrier_id: + order.carrier_id = delivery_wiz.carrier_id + else: + delivery_wiz._get_shipment_rate() + delivery_wiz.button_confirm() + + @api.onchange("partner_id", "partner_shipping_id") + def _add_delivery_carrier_on_partner_change(self): + partner = self.partner_shipping_id or self.partner_id + if not partner: + return + if self.company_id.sale_auto_assign_carrier_on_create: + self._set_delivery_carrier(set_delivery_line=False) + + def _is_auto_set_carrier_on_create(self): + self.ensure_one() + if self.state not in ("draft", "sent"): + return False + return self.company_id.sale_auto_assign_carrier_on_create + + # End migration note + def _get_param_auto_add_delivery_line(self): # When we have the context 'website_id' it means that we are doing the order from # e-commerce. So we don't want to add the delivery line automatically. @@ -108,6 +156,10 @@ def create(self, vals_list): .with_context(auto_refresh_delivery=False) ) for order in orders: + # Migration Note 17.0: move this to module sale_order_carrier_auto_assign + if not order.carrier_id and order._is_auto_set_carrier_on_create(): + order._set_delivery_carrier() + # End migration note order._auto_refresh_delivery() return orders diff --git a/delivery_auto_refresh/readme/CONFIGURE.rst b/delivery_auto_refresh/readme/CONFIGURE.rst index bb9cdf540c..d8915d3492 100644 --- a/delivery_auto_refresh/readme/CONFIGURE.rst +++ b/delivery_auto_refresh/readme/CONFIGURE.rst @@ -1,5 +1,7 @@ Go to *Settings > Sales > Shipping*: +* Enable "Set default shipping method automalically" if you want to add + automatically the carrier on the sales quotation creation. * Enable "Refresh shipping cost line automatically" if you want to add automatically the delivery line on save and refresh the cost. This will also set the shipping method. * Enable "Refresh After Picking Automatically" if you want to refresh delivery diff --git a/delivery_auto_refresh/static/description/index.html b/delivery_auto_refresh/static/description/index.html index c82ea46318..39481de3e3 100644 --- a/delivery_auto_refresh/static/description/index.html +++ b/delivery_auto_refresh/static/description/index.html @@ -397,6 +397,8 @@

    Auto-refresh delivery

    Configuration

    Go to Settings > Sales > Shipping:

      +
    • Enable “Set default shipping method automalically” if you want to add +automatically the carrier on the sales quotation creation.
    • Enable “Refresh shipping cost line automatically” if you want to add automatically the delivery line on save and refresh the cost. This will also set the shipping method.
    • Enable “Refresh After Picking Automatically” if you want to refresh delivery diff --git a/delivery_auto_refresh/tests/__init__.py b/delivery_auto_refresh/tests/__init__.py index 455b4c5814..8a952c0c8c 100644 --- a/delivery_auto_refresh/tests/__init__.py +++ b/delivery_auto_refresh/tests/__init__.py @@ -1 +1,2 @@ from . import test_delivery_auto_refresh +from . import test_sale_order_carrier_auto_assign diff --git a/delivery_auto_refresh/tests/test_sale_order_carrier_auto_assign.py b/delivery_auto_refresh/tests/test_sale_order_carrier_auto_assign.py new file mode 100644 index 0000000000..e97761c145 --- /dev/null +++ b/delivery_auto_refresh/tests/test_sale_order_carrier_auto_assign.py @@ -0,0 +1,81 @@ +# Copyright 2024 Jacques-Etienne Baudoux (BCIM) +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl) + +# MIGRATION NOTE for 17.0: Move this to module sale_order_carrier_auto_assign + +from odoo.tests import Form, TransactionCase + +from odoo.addons.base.tests.common import DISABLED_MAIL_CONTEXT + + +class TestSaleOrderCarrierAutoAssignCommon(TransactionCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.env = cls.env["base"].with_context(**DISABLED_MAIL_CONTEXT).env + + cls.partner = cls.env.ref("base.res_partner_2") + cls.product_storable = cls.env.ref("product.product_product_9") + cls.delivery_local_delivery = cls.env.ref("delivery.delivery_local_delivery") + cls.delivery_local_delivery.fixed_price = 10 + + +class TestSaleOrderCarrierAutoAssignOnCreate(TestSaleOrderCarrierAutoAssignCommon): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.settings = cls.env["res.config.settings"].create({}) + + def test_sale_order_carrier_auto_assign_onchange(self): + self.assertEqual( + self.partner.property_delivery_carrier_id, self.delivery_local_delivery + ) + self.settings.sale_auto_assign_carrier_on_create = True + self.settings.set_values() + sale_order_form = Form(self.env["sale.order"]) + sale_order_form.partner_id = self.partner + sale_order = sale_order_form.save() + self.assertEqual(sale_order.carrier_id, self.delivery_local_delivery) + + def test_sale_order_carrier_auto_assign_create(self): + self.assertEqual( + self.partner.property_delivery_carrier_id, self.delivery_local_delivery + ) + self.settings.sale_auto_assign_carrier_on_create = True + self.settings.set_values() + sale_order = self.env["sale.order"].create({"partner_id": self.partner.id}) + self.assertEqual(sale_order.carrier_id, self.delivery_local_delivery) + + def test_sale_order_carrier_auto_assign_disabled(self): + self.assertEqual( + self.partner.property_delivery_carrier_id, self.delivery_local_delivery + ) + self.settings.sale_auto_assign_carrier_on_create = False + self.settings.set_values() + sale_order_form = Form(self.env["sale.order"]) + sale_order_form.partner_id = self.partner + sale_order = sale_order_form.save() + self.assertFalse(sale_order.carrier_id) + + def test_sale_order_carrier_auto_assign_no_carrier(self): + self.partner.property_delivery_carrier_id = False + self.settings.sale_auto_assign_carrier_on_create = True + self.settings.set_values() + sale_order_form = Form(self.env["sale.order"]) + sale_order_form.partner_id = self.partner + sale_order = sale_order_form.save() + self.assertFalse(sale_order.carrier_id) + + def test_sale_order_carrier_auto_assign_carrier_already_set(self): + self.assertEqual( + self.partner.property_delivery_carrier_id, self.delivery_local_delivery + ) + self.settings.sale_auto_assign_carrier_on_create = True + carrier = self.env.ref("delivery.delivery_carrier") + sale_order = self.env["sale.order"].create( + { + "partner_id": self.partner.id, + "carrier_id": carrier.id, + } + ) + self.assertEqual(sale_order.carrier_id, carrier) diff --git a/delivery_auto_refresh/views/res_config_settings_views.xml b/delivery_auto_refresh/views/res_config_settings_views.xml index 4c1d860ac2..0e6c6a3c14 100644 --- a/delivery_auto_refresh/views/res_config_settings_views.xml +++ b/delivery_auto_refresh/views/res_config_settings_views.xml @@ -4,12 +4,30 @@ res.config.settings.view.form.inherit.sale res.config.settings + + + + + +
      + +
      +
      +
      + +
      From 16787fc75fcdf376617b2b459d2bc23f42364d2f Mon Sep 17 00:00:00 2001 From: Jacques-Etienne Baudoux Date: Thu, 18 Apr 2024 14:48:00 +0200 Subject: [PATCH 12/16] delivery_auto_refresh: multi-company Move config to company level Prefix config settings by sale --- .../migrations/16.0.2.0.0/post-migration.py | 15 +++++++++++ delivery_auto_refresh/models/res_company.py | 10 ++++++++ .../models/res_config_settings.py | 18 ++++++------- delivery_auto_refresh/models/sale_order.py | 24 +++++++++--------- delivery_auto_refresh/models/stock_picking.py | 9 ++----- .../tests/test_delivery_auto_refresh.py | 25 +++++++++++-------- .../views/res_config_settings_views.xml | 12 ++++----- 7 files changed, 68 insertions(+), 45 deletions(-) diff --git a/delivery_auto_refresh/migrations/16.0.2.0.0/post-migration.py b/delivery_auto_refresh/migrations/16.0.2.0.0/post-migration.py index db854d8433..ad113d97b4 100644 --- a/delivery_auto_refresh/migrations/16.0.2.0.0/post-migration.py +++ b/delivery_auto_refresh/migrations/16.0.2.0.0/post-migration.py @@ -10,6 +10,21 @@ def _migrate_setting_to_company(env): ): env["res.company"].search([]).sale_auto_assign_carrier_on_create = True + if env["ir.config_parameter"].get_param( + "delivery_auto_refresh.auto_add_delivery_line" + ): + env["res.company"].search([]).sale_auto_add_delivery_line = True + + if env["ir.config_parameter"].get_param( + "delivery_auto_refresh.refresh_after_picking" + ): + env["res.company"].search([]).sale_refresh_delivery_after_picking = True + + if env["ir.config_parameter"].get_param( + "delivery_auto_refresh.auto_void_delivery_line" + ): + env["res.company"].search([]).sale_auto_void_delivery_line = True + def migrate(cr, version): env = api.Environment(cr, SUPERUSER_ID, {}) diff --git a/delivery_auto_refresh/models/res_company.py b/delivery_auto_refresh/models/res_company.py index 9ec9f4c022..48bcf9895b 100644 --- a/delivery_auto_refresh/models/res_company.py +++ b/delivery_auto_refresh/models/res_company.py @@ -12,3 +12,13 @@ class ResCompany(models.Model): "Set default shipping method automatically" ) # End migration note + + sale_auto_add_delivery_line = fields.Boolean( + "Refresh shipping cost line automatically", + ) + sale_refresh_delivery_after_picking = fields.Boolean( + "Refresh delivery after picking automatically", + ) + sale_auto_void_delivery_line = fields.Boolean( + "Void delivery lines automatically", + ) diff --git a/delivery_auto_refresh/models/res_config_settings.py b/delivery_auto_refresh/models/res_config_settings.py index 33f46d2e00..d45b2112fd 100644 --- a/delivery_auto_refresh/models/res_config_settings.py +++ b/delivery_auto_refresh/models/res_config_settings.py @@ -14,15 +14,15 @@ class ResConfigSettings(models.TransientModel): ) # End migration note - auto_add_delivery_line = fields.Boolean( - "Refresh shipping cost line automatically", - config_parameter="delivery_auto_refresh.auto_add_delivery_line", + sale_auto_add_delivery_line = fields.Boolean( + related="company_id.sale_auto_add_delivery_line", + readonly=False, ) - refresh_after_picking = fields.Boolean( - "Refresh after picking automatically", - config_parameter="delivery_auto_refresh.refresh_after_picking", + sale_refresh_delivery_after_picking = fields.Boolean( + related="company_id.sale_refresh_delivery_after_picking", + readonly=False, ) - auto_void_delivery_line = fields.Boolean( - "Void delivery lines automatically", - config_parameter="delivery_auto_refresh.auto_void_delivery_line", + sale_auto_void_delivery_line = fields.Boolean( + related="company_id.sale_auto_void_delivery_line", + readonly=False, ) diff --git a/delivery_auto_refresh/models/sale_order.py b/delivery_auto_refresh/models/sale_order.py index 5c7a60acbc..145cd74ac1 100644 --- a/delivery_auto_refresh/models/sale_order.py +++ b/delivery_auto_refresh/models/sale_order.py @@ -72,16 +72,12 @@ def _is_auto_set_carrier_on_create(self): # End migration note - def _get_param_auto_add_delivery_line(self): + def _is_auto_add_delivery_line(self): # When we have the context 'website_id' it means that we are doing the order from # e-commerce. So we don't want to add the delivery line automatically. if self.env.context.get("website_id"): return False - return ( - self.env["ir.config_parameter"] - .sudo() - .get_param("delivery_auto_refresh.auto_add_delivery_line") - ) + return self.company_id.sale_auto_add_delivery_line def _update_delivery_line(self, delivery_line, price_unit): """Update the existing delivery line""" @@ -117,11 +113,11 @@ def _update_delivery_line(self, delivery_line, price_unit): def _auto_refresh_delivery(self): self.ensure_one() - if self.env.context.get("auto_refresh_delivery"): - return - if not self._get_param_auto_add_delivery_line(): - return - if self.state not in ("draft", "sent"): + if ( + self.env.context.get("auto_refresh_delivery") + or not self._is_auto_add_delivery_line() + or self.state not in ("draft", "sent") + ): return self = self.with_context(auto_refresh_delivery=True) @@ -173,7 +169,7 @@ def write(self, vals): return res def set_delivery_line(self, carrier, amount): - if self._get_param_auto_add_delivery_line() and self.state in ("draft", "sent"): + if self._is_auto_add_delivery_line() and self.state in ("draft", "sent"): # This will trigger an _auto_refresh_delivery in write self.carrier_id = carrier.id else: @@ -183,6 +179,10 @@ def _is_delivery_line_voidable(self): """If the picking is returned before being invoiced, like when the picking is delivered but immediately return because the customer refused the order, so no delivery charges should be applied.""" + self.ensure_one() + if not self.company_id.sale_auto_void_delivery_line: + return False + # There are invoiceable lines so there's no full return or the lines # were not set to refund. qty_delivered = sum( diff --git a/delivery_auto_refresh/models/stock_picking.py b/delivery_auto_refresh/models/stock_picking.py index 3fe60d4c59..b7897b1534 100644 --- a/delivery_auto_refresh/models/stock_picking.py +++ b/delivery_auto_refresh/models/stock_picking.py @@ -3,8 +3,6 @@ from odoo import models -from ..utils import get_bool_param - class StockPicking(models.Model): _inherit = "stock.picking" @@ -15,10 +13,9 @@ def _add_delivery_cost_to_so(self): # based on rules doesn't refresh with real picking data, only with SO # ones. res = super()._add_delivery_cost_to_so() - if not get_bool_param(self.env, "refresh_after_picking"): - return res - self.ensure_one() sale_order = self.sale_id + if not sale_order.company_id.sale_refresh_delivery_after_picking: + return res if not sale_order or not self.carrier_id: # pragma: no cover return res so_line = sale_order.order_line.filtered(lambda x: x.is_delivery)[:1] @@ -62,8 +59,6 @@ def _action_done(self): # If configured, we want to set to 0 automatically the delivery line # when we have a returned picking that isn't invoiced so we don't have # it as invoiceable line. Otherwise, the salesman has to do it by hand. - if not get_bool_param(self.env, "auto_void_delivery_line"): - return res sales_to_void_delivery = self.filtered( lambda x: x.sale_id and x.picking_type_code == "incoming" diff --git a/delivery_auto_refresh/tests/test_delivery_auto_refresh.py b/delivery_auto_refresh/tests/test_delivery_auto_refresh.py index cfde548b3d..86a7abace6 100644 --- a/delivery_auto_refresh/tests/test_delivery_auto_refresh.py +++ b/delivery_auto_refresh/tests/test_delivery_auto_refresh.py @@ -67,9 +67,6 @@ def setUpClass(cls): "property_product_pricelist": pricelist.id, } ) - cls.auto_add_delivery_line = "delivery_auto_refresh.auto_add_delivery_line" - cls.refresh_after_picking = "delivery_auto_refresh.refresh_after_picking" - cls.auto_void_delivery_line = "delivery_auto_refresh.auto_void_delivery_line" cls.settings = cls.env["res.config.settings"].create({}) cls.settings.execute() order_form = Form(cls.env["sale.order"]) @@ -83,7 +80,8 @@ def setUpClass(cls): def test_auto_refresh_so(self): self.assertFalse(self.order.order_line.filtered("is_delivery")) - self.env["ir.config_parameter"].sudo().set_param(self.param_name1, 1) + self.settings.sale_auto_add_delivery_line = True + self.settings.execute() self.order.write( {"order_line": [(1, self.order.order_line.id, {"product_uom_qty": 3})]} ) @@ -122,7 +120,8 @@ def test_auto_refresh_so(self): self.assertEqual(line_delivery.name, "Test carrier 1") def test_auto_refresh_picking(self): - self.env["ir.config_parameter"].sudo().set_param(self.param_name2, 1) + self.settings.sale_refresh_delivery_after_picking = True + self.settings.execute() self.order.order_line.product_uom_qty = 3 wiz = Form( self.env["choose.delivery.carrier"].with_context( @@ -142,7 +141,7 @@ def test_auto_refresh_picking(self): self.assertEqual(line_delivery.price_unit, 50) def test_auto_refresh_picking_fixed_price(self): - self.settings.refresh_after_picking = True + self.settings.sale_refresh_delivery_after_picking = True self.settings.execute() product_fixed_price = self.env["product.product"].create( { @@ -173,7 +172,8 @@ def test_auto_refresh_picking_fixed_price(self): self.assertEqual(line_delivery.price_unit, 2) def test_no_auto_refresh_picking(self): - self.env["ir.config_parameter"].sudo().set_param(self.param_name2, "0") + self.settings.sale_refresh_delivery_after_picking = False + self.settings.execute() self.order.order_line.product_uom_qty = 3 wiz = Form( self.env["choose.delivery.carrier"].with_context( @@ -229,8 +229,9 @@ def _return_whole_picking(self, picking, to_refund=True): def _test_autorefresh_void_line(self, lock=False, to_refund=True, invoice=False): """Helper method to test the possible cases for voiding the line""" self.assertFalse(self.order.order_line.filtered("is_delivery")) - self.env["ir.config_parameter"].sudo().set_param(self.param_name1, 1) - self.env["ir.config_parameter"].sudo().set_param(self.param_name3, 1) + self.settings.sale_auto_add_delivery_line = True + self.settings.sale_auto_void_delivery_line = True + self.settings.execute() line_delivery = self._confirm_sale_order(self.order) self._validate_picking(self.order.picking_ids) if invoice: @@ -270,7 +271,8 @@ def test_auto_refresh_so_and_return_no_refund(self): def _test_autorefresh_unlink_line(self): """Helper method to test the possible cases for voiding the line""" self.assertFalse(self.order.order_line.filtered("is_delivery")) - self.env["ir.config_parameter"].sudo().set_param(self.param_name1, 1) + self.settings.sale_auto_add_delivery_line = True + self.settings.execute() sale_form = Form(self.order) # Force the delivery line creation with sale_form.order_line.edit(0) as line_form: @@ -290,7 +292,8 @@ def test_auto_refresh_so_and_unlink_line(self): def test_auto_add_delivery_line_add_service(self): """No delivery line when service only""" - self.env["ir.config_parameter"].sudo().set_param(self.auto_add_delivery_line, 1) + self.settings.sale_auto_add_delivery_line = True + self.settings.set_values() service = self.env["product.product"].create( {"name": "Service Test", "type": "service"} ) diff --git a/delivery_auto_refresh/views/res_config_settings_views.xml b/delivery_auto_refresh/views/res_config_settings_views.xml index 0e6c6a3c14..a89cfc8ddd 100644 --- a/delivery_auto_refresh/views/res_config_settings_views.xml +++ b/delivery_auto_refresh/views/res_config_settings_views.xml @@ -29,30 +29,30 @@
      - +
      -
      - +
      -
      - +
      -
    • If you deliver a different quantity than the ordered one, the delivery price is adjusted on the linked SO when the picking is transferred.
    +

    Part of this module is a backport from Odoo SA and as such, it is not included in the OCA CLA. +That means we do not have a copy of the copyright on it like all other OCA modules.

    Table of contents

    From ba54be309a3ffd7f8c4535b6436155455d4868d0 Mon Sep 17 00:00:00 2001 From: Eduard Brahas Date: Mon, 8 Jul 2024 16:50:46 +0200 Subject: [PATCH 16/16] [FIX]delivery_auto_refresh: Adapt to 14.0 --- delivery_auto_refresh/__manifest__.py | 2 - .../migrations/16.0.2.0.0/post-migration.py | 31 -------- delivery_auto_refresh/models/res_company.py | 2 - .../models/res_config_settings.py | 2 - delivery_auto_refresh/models/sale_order.py | 56 +++++++------- .../test_sale_order_carrier_auto_assign.py | 2 - .../views/res_config_settings_views.xml | 75 ++++++++----------- 7 files changed, 61 insertions(+), 109 deletions(-) delete mode 100644 delivery_auto_refresh/migrations/16.0.2.0.0/post-migration.py diff --git a/delivery_auto_refresh/__manifest__.py b/delivery_auto_refresh/__manifest__.py index e70dfffdc0..c09bf00415 100644 --- a/delivery_auto_refresh/__manifest__.py +++ b/delivery_auto_refresh/__manifest__.py @@ -13,8 +13,6 @@ "application": False, "installable": True, "depends": ["delivery"], - # Migration Note 17.0: Add dependency to sale_order_carrier_auto_assign - # "depends": ["delivery", "sale_order_carrier_auto_assign"], "data": [ "data/ir_config_parameter.xml", "views/sale_order_views.xml", diff --git a/delivery_auto_refresh/migrations/16.0.2.0.0/post-migration.py b/delivery_auto_refresh/migrations/16.0.2.0.0/post-migration.py deleted file mode 100644 index ad113d97b4..0000000000 --- a/delivery_auto_refresh/migrations/16.0.2.0.0/post-migration.py +++ /dev/null @@ -1,31 +0,0 @@ -# Copyright 2024 Jacques-Etienne Baudoux (BCIM) -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). - -from odoo import SUPERUSER_ID, api - - -def _migrate_setting_to_company(env): - if env["ir.config_parameter"].get_param( - "delivery_auto_refresh.set_default_carrier" - ): - env["res.company"].search([]).sale_auto_assign_carrier_on_create = True - - if env["ir.config_parameter"].get_param( - "delivery_auto_refresh.auto_add_delivery_line" - ): - env["res.company"].search([]).sale_auto_add_delivery_line = True - - if env["ir.config_parameter"].get_param( - "delivery_auto_refresh.refresh_after_picking" - ): - env["res.company"].search([]).sale_refresh_delivery_after_picking = True - - if env["ir.config_parameter"].get_param( - "delivery_auto_refresh.auto_void_delivery_line" - ): - env["res.company"].search([]).sale_auto_void_delivery_line = True - - -def migrate(cr, version): - env = api.Environment(cr, SUPERUSER_ID, {}) - _migrate_setting_to_company(env) diff --git a/delivery_auto_refresh/models/res_company.py b/delivery_auto_refresh/models/res_company.py index 48bcf9895b..02f4f68ff5 100644 --- a/delivery_auto_refresh/models/res_company.py +++ b/delivery_auto_refresh/models/res_company.py @@ -7,11 +7,9 @@ class ResCompany(models.Model): _inherit = "res.company" - # Migration Note 17.0: move this to module sale_order_carrier_auto_assign sale_auto_assign_carrier_on_create = fields.Boolean( "Set default shipping method automatically" ) - # End migration note sale_auto_add_delivery_line = fields.Boolean( "Refresh shipping cost line automatically", diff --git a/delivery_auto_refresh/models/res_config_settings.py b/delivery_auto_refresh/models/res_config_settings.py index d45b2112fd..e6da6500ee 100644 --- a/delivery_auto_refresh/models/res_config_settings.py +++ b/delivery_auto_refresh/models/res_config_settings.py @@ -7,12 +7,10 @@ class ResConfigSettings(models.TransientModel): _inherit = "res.config.settings" - # Migration Note 17.0: move this to module sale_order_carrier_auto_assign sale_auto_assign_carrier_on_create = fields.Boolean( related="company_id.sale_auto_assign_carrier_on_create", readonly=False, ) - # End migration note sale_auto_add_delivery_line = fields.Boolean( related="company_id.sale_auto_add_delivery_line", diff --git a/delivery_auto_refresh/models/sale_order.py b/delivery_auto_refresh/models/sale_order.py index 0c7a73e047..773f471ba3 100644 --- a/delivery_auto_refresh/models/sale_order.py +++ b/delivery_auto_refresh/models/sale_order.py @@ -3,13 +3,12 @@ # Copyright 2024 Jacques-Etienne Baudoux (BCIM) # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -from odoo import api, fields, models, _ +from odoo import _, api, fields, models class SaleOrder(models.Model): _inherit = "sale.order" - # Migration note: This field is not used anymore and can be dropped in later versions available_carrier_ids = fields.Many2many( comodel_name="delivery.carrier", compute="_compute_available_carrier_ids", @@ -22,9 +21,6 @@ def _compute_available_carrier_ids(self): wizard = self.env["choose.delivery.carrier"].new({"order_id": sale.id}) sale.available_carrier_ids = wizard.available_carrier_ids._origin - # End migration note - - # Migration Note 17.0: move this section to module sale_order_carrier_auto_assign def _set_delivery_carrier(self, set_delivery_line=True): for order in self: delivery_wiz_action = order.action_open_delivery_wizard() @@ -70,8 +66,6 @@ def _is_auto_set_carrier_on_create(self): return False return self.company_id.sale_auto_assign_carrier_on_create - # End migration note - def _is_auto_add_delivery_line(self): # When we have the context 'website_id' it means that we are doing the order from # e-commerce. So we don't want to add the delivery line automatically. @@ -84,11 +78,13 @@ def _prepare_delivery_line_vals(self, carrier, price_unit): context = {} if self.partner_id: # set delivery detail in the customer language - context['lang'] = self.partner_id.lang + context["lang"] = self.partner_id.lang carrier = carrier.with_context(lang=self.partner_id.lang) # Apply fiscal position - taxes = carrier.product_id.taxes_id.filtered(lambda t: t.company_id.id == self.company_id.id) + taxes = carrier.product_id.taxes_id.filtered( + lambda t: t.company_id.id == self.company_id.id + ) taxes_ids = taxes.ids if self.partner_id and self.fiscal_position_id: taxes_ids = self.fiscal_position_id.map_tax(taxes).ids @@ -96,29 +92,35 @@ def _prepare_delivery_line_vals(self, carrier, price_unit): # Create the sales order line if carrier.product_id.description_sale: - so_description = '%s: %s' % (carrier.name, carrier.product_id.description_sale) + so_description = "%s: %s" % ( + carrier.name, + carrier.product_id.description_sale, + ) else: so_description = carrier.name values = { - 'order_id': self.id, - 'name': so_description, - 'product_uom_qty': 1, - 'product_uom': carrier.product_id.uom_id.id, - 'product_id': carrier.product_id.id, - 'tax_id': [(6, 0, taxes_ids)], - 'is_delivery': True, + "order_id": self.id, + "name": so_description, + "product_uom_qty": 1, + "product_uom": carrier.product_id.uom_id.id, + "product_id": carrier.product_id.id, + "tax_id": [(6, 0, taxes_ids)], + "is_delivery": True, } - if carrier.invoice_policy == 'real': - values['price_unit'] = 0 - values['name'] += _(' (Estimated Cost: %s )', self._format_currency_amount(price_unit)) + if carrier.invoice_policy == "real": + values["price_unit"] = 0 + values["name"] += _( + " (Estimated Cost: %s )", self._format_currency_amount(price_unit) + ) else: - values['price_unit'] = price_unit - if carrier.free_over and self.currency_id.is_zero(price_unit) : - values['name'] += '\n' + _('Free Shipping') + values["price_unit"] = price_unit + if carrier.free_over and self.currency_id.is_zero(price_unit): + values["name"] += "\n" + _("Free Shipping") if self.order_line: - values['sequence'] = self.order_line[-1].sequence + 1 + values["sequence"] = self.order_line[-1].sequence + 1 del context return values + # end of the odoo part def _update_delivery_line(self, delivery_line, price_unit): @@ -131,13 +133,13 @@ def _update_delivery_line(self, delivery_line, price_unit): # Tax is set with a SET command clear = update = False for cmd in val: - if cmd[0] == fields.Command.SET: + if cmd[0] == 6: if delivery_line[f].ids != cmd[2]: update = True else: clear = True if clear: - new_vals[f] = [fields.Command.CLEAR] + val + new_vals[f] = [(5, 0, 0)] + val elif update: new_vals[f] = val elif isinstance(field_def, fields.Many2one): @@ -194,10 +196,8 @@ def create(self, vals_list): .with_context(auto_refresh_delivery=False) ) for order in orders: - # Migration Note 17.0: move this to module sale_order_carrier_auto_assign if not order.carrier_id and order._is_auto_set_carrier_on_create(): order._set_delivery_carrier() - # End migration note order._auto_refresh_delivery() return orders diff --git a/delivery_auto_refresh/tests/test_sale_order_carrier_auto_assign.py b/delivery_auto_refresh/tests/test_sale_order_carrier_auto_assign.py index 28ba60283e..717626215e 100644 --- a/delivery_auto_refresh/tests/test_sale_order_carrier_auto_assign.py +++ b/delivery_auto_refresh/tests/test_sale_order_carrier_auto_assign.py @@ -1,8 +1,6 @@ # Copyright 2024 Jacques-Etienne Baudoux (BCIM) # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl) -# MIGRATION NOTE for 17.0: Move this to module sale_order_carrier_auto_assign - from odoo.tests import Form, common diff --git a/delivery_auto_refresh/views/res_config_settings_views.xml b/delivery_auto_refresh/views/res_config_settings_views.xml index a89cfc8ddd..64d179b89c 100644 --- a/delivery_auto_refresh/views/res_config_settings_views.xml +++ b/delivery_auto_refresh/views/res_config_settings_views.xml @@ -5,56 +5,47 @@ res.config.settings - - - -
    - -
    -
    -