diff --git a/sale_delivery_state/README.rst b/sale_delivery_state/README.rst index c17bdb585041..b5c1013d9e9f 100644 --- a/sale_delivery_state/README.rst +++ b/sale_delivery_state/README.rst @@ -7,7 +7,7 @@ Sale delivery State !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !! source digest: sha256:0ff06f9e489784baf8b25b5d53c355c7c8ade5638a55431b288c216b3520b689 + !! source digest: sha256:df53b074f16b808caf5d41acc70a817089ff3852a2504e53ad9ebb8cf7cbdcdd !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! .. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png @@ -38,8 +38,14 @@ state of the sale order can be forced to fully delivered in case some quantities were cancelled by the customer and you consider you have nothing more to deliver. -Sale order lines can have products or services, as long as the field -qty_delivered is set, it will trigger the computation of delivery state. +Sale order lines can have products or services, as long as the field `qty_delivered` +is set, it will trigger the computation of delivery state. + +Sale order lines with the Skip Delivery State field set to True will be ignored when +computing the delivery state. This field is automatically set depending on the field +Sales > Configuration > Quotations & Orders > Skip Service products for Sale Delivery +State. If set to True, the field Skip Delivery State in sale order lines containing +service products will be automatically set to True, but it can manually changed. This module also works with delivery.carrier fees that are added as a sale order line. Thoses line are special as they will never be @@ -56,6 +62,12 @@ from 'sale_stock'. .. contents:: :local: +Configuration +============= + +#. Go to *Sales > Configuration > Quotations & Orders*. +#. Check the Skip Service products for Sale Delivery State checkbox to automatically set the field Skip Delivery State in sale order lines to True when the line contains a service product. + Bug Tracker =========== @@ -77,12 +89,13 @@ Authors Contributors ------------ -- Pierrick BRUN -- Benoît Guillot -- Yannick Vaucher -- Daniel Reis , `Open Source - Integrators `__ -- Carlos Lopez +* Pierrick BRUN +* Benoît Guillot +* Yannick Vaucher +* Daniel Reis , + `Open Source Integrators ` +* Carlos Lopez +* Manuel Regidor Maintainers ----------- diff --git a/sale_delivery_state/__manifest__.py b/sale_delivery_state/__manifest__.py index a934d04020ad..7d8a7508d688 100644 --- a/sale_delivery_state/__manifest__.py +++ b/sale_delivery_state/__manifest__.py @@ -14,6 +14,7 @@ "depends": ["sale"], "data": [ "views/sale_order_views.xml", + "views/res_config_settings_views.xml", ], "demo": [ "demo/sale_demo.xml", diff --git a/sale_delivery_state/models/__init__.py b/sale_delivery_state/models/__init__.py index 6aacb753131f..ef49580d8444 100644 --- a/sale_delivery_state/models/__init__.py +++ b/sale_delivery_state/models/__init__.py @@ -1 +1,4 @@ from . import sale_order +from . import sale_order_line +from . import res_company +from . import res_config_settings diff --git a/sale_delivery_state/models/res_company.py b/sale_delivery_state/models/res_company.py new file mode 100644 index 000000000000..08163c4f49a9 --- /dev/null +++ b/sale_delivery_state/models/res_company.py @@ -0,0 +1,12 @@ +# Copyright 2023 Manuel Regidor +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo import fields, models + + +class ResCompany(models.Model): + _inherit = "res.company" + + skip_service_sale_delivery_state = fields.Boolean( + string="Skip Service products for Sale Delivery State" + ) diff --git a/sale_delivery_state/models/res_config_settings.py b/sale_delivery_state/models/res_config_settings.py new file mode 100644 index 000000000000..34d0adb37cc7 --- /dev/null +++ b/sale_delivery_state/models/res_config_settings.py @@ -0,0 +1,14 @@ +# Copyright 2023 Manuel Regidor +# 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" + + skip_service_sale_delivery_state = fields.Boolean( + string="Skip Service products for Sale Delivery State", + related="company_id.skip_service_sale_delivery_state", + readonly=False, + ) diff --git a/sale_delivery_state/models/sale_order.py b/sale_delivery_state/models/sale_order.py index c4149002338d..4a96fefc9449 100644 --- a/sale_delivery_state/models/sale_order.py +++ b/sale_delivery_state/models/sale_order.py @@ -2,6 +2,8 @@ # @author Pierrick BRUN # Copyright 2018 Camptocamp # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +# Copyright 2023 Manuel Regidor +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). from odoo import api, fields, models from odoo.tools import float_compare, float_is_zero @@ -39,7 +41,9 @@ def _all_qty_delivered(self): """ self.ensure_one() # Skip delivery costs lines - sale_lines = self.order_line.filtered(lambda rec: not rec._is_delivery()) + sale_lines = self.order_line.filtered( + lambda rec: not rec._is_delivery() and not rec.skip_sale_delivery_state + ) precision = self.env["decimal.precision"].precision_get( "Product Unit of Measure" ) @@ -59,7 +63,9 @@ def _partially_delivered(self): """ self.ensure_one() # Skip delivery costs lines - sale_lines = self.order_line.filtered(lambda rec: not rec._is_delivery()) + sale_lines = self.order_line.filtered( + lambda rec: not rec._is_delivery() and not rec.skip_sale_delivery_state + ) precision = self.env["decimal.precision"].precision_get( "Product Unit of Measure" ) @@ -68,8 +74,13 @@ def _partially_delivered(self): for line in sale_lines ) - @api.depends("order_line.qty_delivered", "state", "force_delivery_state") - def _compute_oca_delivery_status(self): + @api.depends( + "order_line.qty_delivered", + "order_line.skip_sale_delivery_state", + "state", + "force_delivery_state", + ) + def _compute_sale_delivery_state(self): for order in self: if order.state in ("draft", "cancel"): order.delivery_status = None diff --git a/sale_delivery_state/models/sale_order_line.py b/sale_delivery_state/models/sale_order_line.py new file mode 100644 index 000000000000..b3ff1fbcbdb4 --- /dev/null +++ b/sale_delivery_state/models/sale_order_line.py @@ -0,0 +1,27 @@ +# Copyright 2023 Manuel Regidor +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo import api, fields, models + + +class SaleOrderLine(models.Model): + _inherit = "sale.order.line" + + skip_sale_delivery_state = fields.Boolean( + string="Skip Delivery State", + compute="_compute_skip_sale_delivery_state", + store=True, + readonly=False, + ) + + @api.depends("company_id", "product_id") + def _compute_skip_sale_delivery_state(self): + for line in self: + skip_sale_delivery_state = False + if ( + line.product_id + and line.product_id.type == "service" + and line.company_id.skip_service_sale_delivery_state + ): + skip_sale_delivery_state = True + line.skip_sale_delivery_state = skip_sale_delivery_state diff --git a/sale_delivery_state/readme/CONFIGURE.rst b/sale_delivery_state/readme/CONFIGURE.rst new file mode 100644 index 000000000000..bff9dfc69d19 --- /dev/null +++ b/sale_delivery_state/readme/CONFIGURE.rst @@ -0,0 +1,2 @@ +#. Go to *Sales > Configuration > Quotations & Orders*. +#. Check the Skip Service products for Sale Delivery State checkbox to automatically set the field Skip Delivery State in sale order lines to True when the line contains a service product. diff --git a/sale_delivery_state/static/description/index.html b/sale_delivery_state/static/description/index.html index 49ab555ed2dd..b628371a3635 100644 --- a/sale_delivery_state/static/description/index.html +++ b/sale_delivery_state/static/description/index.html @@ -366,7 +366,7 @@

Sale delivery State

!! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -!! source digest: sha256:0ff06f9e489784baf8b25b5d53c355c7c8ade5638a55431b288c216b3520b689 +!! source digest: sha256:df53b074f16b808caf5d41acc70a817089ff3852a2504e53ad9ebb8cf7cbdcdd !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->

Beta License: AGPL-3 OCA/sale-workflow Translate me on Weblate Try me on Runboat

This odoo module add delivery state on the sale order.

@@ -376,8 +376,13 @@

Sale delivery State

state of the sale order can be forced to fully delivered in case some quantities were cancelled by the customer and you consider you have nothing more to deliver.

-

Sale order lines can have products or services, as long as the field -qty_delivered is set, it will trigger the computation of delivery state.

+

Sale order lines can have products or services, as long as the field qty_delivered +is set, it will trigger the computation of delivery state.

+

Sale order lines with the Skip Delivery State field set to True will be ignored when +computing the delivery state. This field is automatically set depending on the field +Sales > Configuration > Quotations & Orders > Skip Service products for Sale Delivery +State. If set to True, the field Skip Delivery State in sale order lines containing +service products will be automatically set to True, but it can manually changed.

This module also works with delivery.carrier fees that are added as a sale order line. Thoses line are special as they will never be considered delivered. Delivery fees lines are ignored in the computation @@ -389,17 +394,25 @@

Sale delivery State

Table of contents

+
+

Configuration

+
    +
  1. Go to Sales > Configuration > Quotations & Orders.
  2. +
  3. Check the Skip Service products for Sale Delivery State checkbox to automatically set the field Skip Delivery State in sale order lines to True when the line contains a service product.
  4. +
+
-

Bug Tracker

+

Bug Tracker

Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us to smash it by providing a detailed and welcomed @@ -407,26 +420,26 @@

Bug Tracker

Do not contact contributors directly about support or help with technical issues.

-

Credits

+

Credits

-

Authors

+

Authors

  • Akretion
-

Maintainers

+

Maintainers

This module is maintained by the OCA.

Odoo Community Association

OCA, or the Odoo Community Association, is a nonprofit organization whose diff --git a/sale_delivery_state/tests/test_delivery_state.py b/sale_delivery_state/tests/test_delivery_state.py index 25e813145bed..393060913b53 100644 --- a/sale_delivery_state/tests/test_delivery_state.py +++ b/sale_delivery_state/tests/test_delivery_state.py @@ -17,6 +17,9 @@ def setUpClass(cls): cls.delivery_cost = cls.env["product.product"].create( {"name": "delivery", "type": "service"} ) + cls.service_product = cls.env["product.product"].create( + {"name": "service", "type": "service"} + ) def _mock_delivery(self, delivery_prod=None): delivery_prod = delivery_prod or self.delivery_cost @@ -38,6 +41,19 @@ def _add_delivery_cost_line(self): } ) + def _add_service_line(self, skip_sale_delivery_state=False): + self.env["sale.order.line"].create( + { + "order_id": self.order.id, + "name": "Service", + "product_id": self.service_product.id, + "product_uom_qty": 1, + "product_uom": self.env.ref("uom.product_uom_unit").id, + "price_unit": 10.0, + "skip_sale_delivery_state": skip_sale_delivery_state, + } + ) + def test_no_delivery(self): self.assertFalse(self.order.delivery_status) @@ -90,4 +106,17 @@ def test_delivery_done_delivery_cost(self): if line._is_delivery(): continue line.qty_delivered = line.product_uom_qty - self.assertEqual(self.order.delivery_status, "full") + self.assertEqual(self.order.delivery_state, "done") + + def test_skip_service_line(self): + self._add_service_line() + self.order.action_confirm() + for line in self.order.order_line: + if line.product_id == self.service_product: + continue + line.qty_delivered = line.product_uom_qty + self.assertEqual(self.order.delivery_state, "partially") + self.order.order_line.filtered( + lambda a: a.product_id and a.product_id == self.service_product + ).write({"skip_sale_delivery_state": True}) + self.assertEqual(self.order.delivery_state, "done") diff --git a/sale_delivery_state/views/res_config_settings_views.xml b/sale_delivery_state/views/res_config_settings_views.xml new file mode 100644 index 000000000000..9b916aeb1018 --- /dev/null +++ b/sale_delivery_state/views/res_config_settings_views.xml @@ -0,0 +1,26 @@ + + + + sale.delivery.state.res.config.settings.view.form + res.config.settings + + + +

+
+ +
+
+
+
+ + + + diff --git a/sale_delivery_state/views/sale_order_views.xml b/sale_delivery_state/views/sale_order_views.xml index 8d1d0f7bb259..e46648245350 100644 --- a/sale_delivery_state/views/sale_order_views.xml +++ b/sale_delivery_state/views/sale_order_views.xml @@ -19,10 +19,13 @@ invisible="not force_delivery_state or state != 'sale' or not locked" /> - - - - + + + + + + +