From 0661339103e8a6be5ca61b5fbe60d28e941fcfcd Mon Sep 17 00:00:00 2001 From: Denis Roussel Date: Thu, 6 Jul 2023 14:13:40 +0200 Subject: [PATCH 1/9] [ADD] stock_available_location_orderpoint --- .../stock_available_location_orderpoint | 1 + .../setup.py | 6 + .../README.rst | 96 ++++ .../__init__.py | 1 + .../__manifest__.py | 19 + .../i18n/fr.po | 81 ++++ .../stock_available_location_orderpoint.pot | 81 ++++ .../models/__init__.py | 2 + .../models/product_product.py | 132 ++++++ .../models/product_template.py | 83 ++++ .../readme/CONFIGURE.rst | 1 + .../readme/CONTRIBUTORS.rst | 1 + .../readme/DESCRIPTION.rst | 2 + .../readme/USAGE.rst | 10 + .../static/description/icon.png | Bin 0 -> 9455 bytes .../static/description/index.html | 443 ++++++++++++++++++ .../static/description/product_form.bmp | Bin 0 -> 2625134 bytes .../tests/__init__.py | 4 + .../test_available_location_orderpoint.py | 225 +++++++++ ..._available_location_orderpoint_template.py | 342 ++++++++++++++ .../views/product_product.xml | 91 ++++ .../views/product_template.xml | 115 +++++ 22 files changed, 1736 insertions(+) create mode 120000 setup/stock_available_location_orderpoint/odoo/addons/stock_available_location_orderpoint create mode 100644 setup/stock_available_location_orderpoint/setup.py create mode 100644 stock_available_location_orderpoint/README.rst create mode 100644 stock_available_location_orderpoint/__init__.py create mode 100644 stock_available_location_orderpoint/__manifest__.py create mode 100644 stock_available_location_orderpoint/i18n/fr.po create mode 100644 stock_available_location_orderpoint/i18n/stock_available_location_orderpoint.pot create mode 100644 stock_available_location_orderpoint/models/__init__.py create mode 100644 stock_available_location_orderpoint/models/product_product.py create mode 100644 stock_available_location_orderpoint/models/product_template.py create mode 100644 stock_available_location_orderpoint/readme/CONFIGURE.rst create mode 100644 stock_available_location_orderpoint/readme/CONTRIBUTORS.rst create mode 100644 stock_available_location_orderpoint/readme/DESCRIPTION.rst create mode 100644 stock_available_location_orderpoint/readme/USAGE.rst create mode 100644 stock_available_location_orderpoint/static/description/icon.png create mode 100644 stock_available_location_orderpoint/static/description/index.html create mode 100644 stock_available_location_orderpoint/static/description/product_form.bmp create mode 100644 stock_available_location_orderpoint/tests/__init__.py create mode 100644 stock_available_location_orderpoint/tests/test_available_location_orderpoint.py create mode 100644 stock_available_location_orderpoint/tests/test_available_location_orderpoint_template.py create mode 100644 stock_available_location_orderpoint/views/product_product.xml create mode 100644 stock_available_location_orderpoint/views/product_template.xml diff --git a/setup/stock_available_location_orderpoint/odoo/addons/stock_available_location_orderpoint b/setup/stock_available_location_orderpoint/odoo/addons/stock_available_location_orderpoint new file mode 120000 index 00000000..d2ae9cd3 --- /dev/null +++ b/setup/stock_available_location_orderpoint/odoo/addons/stock_available_location_orderpoint @@ -0,0 +1 @@ +../../../../stock_available_location_orderpoint \ No newline at end of file diff --git a/setup/stock_available_location_orderpoint/setup.py b/setup/stock_available_location_orderpoint/setup.py new file mode 100644 index 00000000..28c57bb6 --- /dev/null +++ b/setup/stock_available_location_orderpoint/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +) diff --git a/stock_available_location_orderpoint/README.rst b/stock_available_location_orderpoint/README.rst new file mode 100644 index 00000000..a4893c17 --- /dev/null +++ b/stock_available_location_orderpoint/README.rst @@ -0,0 +1,96 @@ +=================================== +Stock Available Location Orderpoint +=================================== + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:71151022a8e19bfec7156a9615a8feff096de2f692f655c24c32f60aa51cab07 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fstock--logistics--availability-lightgray.png?logo=github + :target: https://github.com/OCA/stock-logistics-availability/tree/16.0/stock_available_location_orderpoint + :alt: OCA/stock-logistics-availability +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/stock-logistics-availability-16-0/stock-logistics-availability-16-0-stock_available_location_orderpoint + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png + :target: https://runboat.odoo-community.org/builds?repo=OCA/stock-logistics-availability&target_branch=16.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module allows to display on product level the quantity to be replenished +through location orderpoints and the quantity that is currently in replenishments. + +**Table of contents** + +.. contents:: + :local: + +Configuration +============= + +See stock_location_orderpoint module README. + +Usage +===== + +#. Go to Inventory > Products +#. On product form, the quantity to replenish is on top 'N.N (N.N) To Replenish' +#. The number between brackets is the quantity in replenishments +#. If you click on the button, you will see the movements that are to be done + to fullfill the replenishment(s). + +.. image:: https://raw.githubusercontent.com/OCA/stock-logistics-availability/16.0/stock_available_location_orderpoint/static/description/product_form.bmp + +* These quantities are also displayed optionally on product list level and in + product kanban. + +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 +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +~~~~~~~ + +* ACSONE SA/NV + +Contributors +~~~~~~~~~~~~ + +* Denis Roussel + +Maintainers +~~~~~~~~~~~ + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +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. + +This module is part of the `OCA/stock-logistics-availability `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/stock_available_location_orderpoint/__init__.py b/stock_available_location_orderpoint/__init__.py new file mode 100644 index 00000000..0650744f --- /dev/null +++ b/stock_available_location_orderpoint/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/stock_available_location_orderpoint/__manifest__.py b/stock_available_location_orderpoint/__manifest__.py new file mode 100644 index 00000000..9573a3b8 --- /dev/null +++ b/stock_available_location_orderpoint/__manifest__.py @@ -0,0 +1,19 @@ +# Copyright 2023 ACSONE SA/NV +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +{ + "name": "Stock Available Location Orderpoint", + "summary": """ + Allows to retrieve the quantity to replenish on a product from a + location orderpoint (stock_location_orderpoint)""", + "version": "16.0.1.0.0", + "license": "AGPL-3", + "author": "ACSONE SA/NV,Odoo Community Association (OCA)", + "website": "https://github.com/OCA/stock-logistics-availability", + "depends": [ + "stock_location_orderpoint", + "stock_available", + "stock_available_location_get_domain", + ], + "data": ["views/product_product.xml", "views/product_template.xml"], +} diff --git a/stock_available_location_orderpoint/i18n/fr.po b/stock_available_location_orderpoint/i18n/fr.po new file mode 100644 index 00000000..36dd6e3a --- /dev/null +++ b/stock_available_location_orderpoint/i18n/fr.po @@ -0,0 +1,81 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * stock_available_location_orderpoint +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0+e\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-07-06 12:00+0000\n" +"PO-Revision-Date: 2023-07-06 12:00+0000\n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: stock_available_location_orderpoint +#: model_terms:ir.ui.view,arch_db:stock_available_location_orderpoint.product_normal_form_view +#: model_terms:ir.ui.view,arch_db:stock_available_location_orderpoint.view_stock_available_form +msgid "To Replenish" +msgstr "A réassortir" + +#. module: stock_available_location_orderpoint +#: model_terms:ir.ui.view,arch_db:stock_available_location_orderpoint.product_template_search_form_view_stock +#: model_terms:ir.ui.view,arch_db:stock_available_location_orderpoint.stock_product_search_form_view +msgid "In Replenishments" +msgstr "En réassort" + +#. module: stock_available_location_orderpoint +#: model:ir.model,name:stock_available_location_orderpoint.model_product_template +msgid "Product" +msgstr "Produit" + +#. module: stock_available_location_orderpoint +#: model:ir.model,name:stock_available_location_orderpoint.model_product_product +msgid "Product Variant" +msgstr "Variante de produit" + +#. module: stock_available_location_orderpoint +#: model:ir.model.fields,field_description:stock_available_location_orderpoint.field_product_product__quantity_in_replenishments +#: model:ir.model.fields,field_description:stock_available_location_orderpoint.field_product_template__quantity_in_replenishments +msgid "Quantity In Replenishments" +msgstr "Quantité en Réassort" + +#. module: stock_available_location_orderpoint +#: model:ir.model.fields,field_description:stock_available_location_orderpoint.field_product_product__quantity_to_replenish +#: model:ir.model.fields,field_description:stock_available_location_orderpoint.field_product_template__quantity_to_replenish +msgid "Quantity To Replenish" +msgstr "Quantité à réassortir" + +#. module: stock_available_location_orderpoint +#: model_terms:ir.ui.view,arch_db:stock_available_location_orderpoint.product_normal_form_view +#: model_terms:ir.ui.view,arch_db:stock_available_location_orderpoint.view_stock_available_form +msgid "Quantity to replenish (Quantity in replenishments)" +msgstr "Quantité à réassortir (Quantité en réassort)" + +#. module: stock_available_location_orderpoint +#: model:ir.model.fields,help:stock_available_location_orderpoint.field_product_product__quantity_in_replenishments +#: model:ir.model.fields,help:stock_available_location_orderpoint.field_product_template__quantity_in_replenishments +msgid "" +"This is the quantity currently in replenishments following the location " +"orderpoints." +msgstr "C'est la quantité actuellement en réassorts suivant les réassorts d'emplacements." + +#. module: stock_available_location_orderpoint +#: model:ir.model.fields,help:stock_available_location_orderpoint.field_product_product__quantity_to_replenish +#: model:ir.model.fields,help:stock_available_location_orderpoint.field_product_template__quantity_to_replenish +msgid "This is the quantity to replenish following the location orderpoints." +msgstr "C'est la quantité à réassortir suivant les réassorts d'emplacement." + +#. module: stock_available_location_orderpoint +#: model_terms:ir.ui.view,arch_db:stock_available_location_orderpoint.product_template_search_form_view_stock +#: model_terms:ir.ui.view,arch_db:stock_available_location_orderpoint.stock_product_search_form_view +msgid "To Replenish" +msgstr "A réassortir" + +#. module: stock_available_location_orderpoint +#: model_terms:ir.ui.view,arch_db:stock_available_location_orderpoint.view_stock_available_kanban +msgid "To Replenish:" +msgstr "A réassortir:" diff --git a/stock_available_location_orderpoint/i18n/stock_available_location_orderpoint.pot b/stock_available_location_orderpoint/i18n/stock_available_location_orderpoint.pot new file mode 100644 index 00000000..7d9777bb --- /dev/null +++ b/stock_available_location_orderpoint/i18n/stock_available_location_orderpoint.pot @@ -0,0 +1,81 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * stock_available_location_orderpoint +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0+e\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-07-06 12:01+0000\n" +"PO-Revision-Date: 2023-07-06 12:01+0000\n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: stock_available_location_orderpoint +#: model_terms:ir.ui.view,arch_db:stock_available_location_orderpoint.product_normal_form_view +#: model_terms:ir.ui.view,arch_db:stock_available_location_orderpoint.view_stock_available_form +msgid "To Replenish" +msgstr "" + +#. module: stock_available_location_orderpoint +#: model_terms:ir.ui.view,arch_db:stock_available_location_orderpoint.product_template_search_form_view_stock +#: model_terms:ir.ui.view,arch_db:stock_available_location_orderpoint.stock_product_search_form_view +msgid "In Replenishments" +msgstr "" + +#. module: stock_available_location_orderpoint +#: model:ir.model,name:stock_available_location_orderpoint.model_product_template +msgid "Product" +msgstr "" + +#. module: stock_available_location_orderpoint +#: model:ir.model,name:stock_available_location_orderpoint.model_product_product +msgid "Product Variant" +msgstr "" + +#. module: stock_available_location_orderpoint +#: model:ir.model.fields,field_description:stock_available_location_orderpoint.field_product_product__quantity_in_replenishments +#: model:ir.model.fields,field_description:stock_available_location_orderpoint.field_product_template__quantity_in_replenishments +msgid "Quantity In Replenishments" +msgstr "" + +#. module: stock_available_location_orderpoint +#: model:ir.model.fields,field_description:stock_available_location_orderpoint.field_product_product__quantity_to_replenish +#: model:ir.model.fields,field_description:stock_available_location_orderpoint.field_product_template__quantity_to_replenish +msgid "Quantity To Replenish" +msgstr "" + +#. module: stock_available_location_orderpoint +#: model_terms:ir.ui.view,arch_db:stock_available_location_orderpoint.product_normal_form_view +#: model_terms:ir.ui.view,arch_db:stock_available_location_orderpoint.view_stock_available_form +msgid "Quantity to replenish (Quantity in replenishments)" +msgstr "" + +#. module: stock_available_location_orderpoint +#: model:ir.model.fields,help:stock_available_location_orderpoint.field_product_product__quantity_in_replenishments +#: model:ir.model.fields,help:stock_available_location_orderpoint.field_product_template__quantity_in_replenishments +msgid "" +"This is the quantity currently in replenishments following the location " +"orderpoints." +msgstr "" + +#. module: stock_available_location_orderpoint +#: model:ir.model.fields,help:stock_available_location_orderpoint.field_product_product__quantity_to_replenish +#: model:ir.model.fields,help:stock_available_location_orderpoint.field_product_template__quantity_to_replenish +msgid "This is the quantity to replenish following the location orderpoints." +msgstr "" + +#. module: stock_available_location_orderpoint +#: model_terms:ir.ui.view,arch_db:stock_available_location_orderpoint.product_template_search_form_view_stock +#: model_terms:ir.ui.view,arch_db:stock_available_location_orderpoint.stock_product_search_form_view +msgid "To Replenish" +msgstr "" + +#. module: stock_available_location_orderpoint +#: model_terms:ir.ui.view,arch_db:stock_available_location_orderpoint.view_stock_available_kanban +msgid "To Replenish:" +msgstr "" diff --git a/stock_available_location_orderpoint/models/__init__.py b/stock_available_location_orderpoint/models/__init__.py new file mode 100644 index 00000000..049669dd --- /dev/null +++ b/stock_available_location_orderpoint/models/__init__.py @@ -0,0 +1,2 @@ +from . import product_template +from . import product_product diff --git a/stock_available_location_orderpoint/models/product_product.py b/stock_available_location_orderpoint/models/product_product.py new file mode 100644 index 00000000..458d2dab --- /dev/null +++ b/stock_available_location_orderpoint/models/product_product.py @@ -0,0 +1,132 @@ +# Copyright 2023 ACSONE SA/NV +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +from collections import defaultdict + +from odoo import fields, models +from odoo.tools import float_compare +from odoo.tools.safe_eval import safe_eval + +from odoo.addons.stock.models.product import OPERATORS + + +class ProductProduct(models.Model): + + _inherit = "product.product" + + quantity_to_replenish = fields.Float( + compute="_compute_available_quantities", + search="_search_quantity_to_replenish", + help="This is the quantity to replenish following the location orderpoints.", + ) + quantity_in_replenishments = fields.Float( + compute="_compute_available_quantities", + search="_search_quantity_in_replenishments", + help="This is the quantity currently in replenishments following the " + "location orderpoints.", + ) + + def _compute_available_quantities_dict(self): + """ + Retrieve all replenishment quantities for the selected products + and locations. + """ + res, stock_dict = super()._compute_available_quantities_dict() + location_domain = self._get_domain_location_for_locations() + locations = self.env["stock.location"].search(location_domain) + orderpoint_obj = self.env["stock.location.orderpoint"] + if orderpoint_obj.check_access_rights("read", raise_exception=False): + orderpoint_domain = orderpoint_obj._prepare_orderpoint_domain_location( + locations.ids + ) + orderpoints = orderpoint_obj.search(orderpoint_domain) + else: + for product in self: + res[product.id]["quantity_to_replenish"] = 0 + res[product.id]["quantity_in_replenishments"] = 0 + return res, stock_dict + + # Merge both source locations and destination locations + location_ids = set( + orderpoints.location_id.ids + orderpoints.location_src_id.ids + ) + qties_on_locations = orderpoints._compute_quantities_dict( + self.env["stock.location"].browse(location_ids), + self, + ) + # Get current replenishments + current_moves = self.env["stock.move"].read_group( + [ + ("location_id", "in", orderpoints.location_src_id.ids), + ("state", "not in", ("done", "cancel")), + ("product_id", "in", self.ids), + ], + ["product_id"], + ["product_id"], + ) + quantities_in_replenishments = defaultdict(lambda: defaultdict(lambda: 0)) + for current_move in current_moves: + quantities_in_replenishments[current_move["product_id"][0]] = current_move[ + "product_id_count" + ] + for product in self: + qties_replenished_for_location = {product: 0.0} + for orderpoint in orderpoints: + qty_to_replenish = orderpoint._get_qty_to_replenish( + product, + qties_on_locations, + 0, + ) + if ( + float_compare( + qty_to_replenish, 0, precision_rounding=product.uom_id.rounding + ) + > 0 + ): + qties_replenished_for_location[product] += qty_to_replenish + res[product.id][ + "quantity_in_replenishments" + ] = quantities_in_replenishments[product.id] + res[product.id]["quantity_to_replenish"] = qties_replenished_for_location[ + product + ] + return res, stock_dict + + def _get_search_quantity_to_replenish_domain(self): + return [("type", "=", "product")] + + def _search_quantity_to_replenish(self, operator, value): + product_domain = self._get_search_quantity_to_replenish_domain() + products = self.with_context(prefetch_fields=False).search( + product_domain, order="id" + ) + product_ids = [] + for product in products: + if OPERATORS[operator](product.quantity_to_replenish, value): + product_ids.append(product.id) + return [("id", "in", product_ids)] + + def _get_search_quantity_in_replenishments_domain(self): + return [("type", "=", "product")] + + def _search_quantity_in_replenishments(self, operator, value): + product_domain = self._get_search_quantity_in_replenishments_domain() + products = self.with_context(prefetch_fields=False).search( + product_domain, order="id" + ) + product_ids = [] + for product in products: + if OPERATORS[operator](product.quantity_in_replenishments, value): + product_ids.append(product.id) + return [("id", "in", product_ids)] + + def action_open_replenishments(self): + action = self.env["ir.actions.act_window"]._for_xml_id( + "stock.stock_move_action" + ) + + action["domain"] = [ + ("location_orderpoint_id", "!=", False), + ("product_id", "=", self.id), + ] + action["context"] = dict(safe_eval(action["context"]), search_default_future=1) + return action diff --git a/stock_available_location_orderpoint/models/product_template.py b/stock_available_location_orderpoint/models/product_template.py new file mode 100644 index 00000000..a0fcab4d --- /dev/null +++ b/stock_available_location_orderpoint/models/product_template.py @@ -0,0 +1,83 @@ +# Copyright 2023 ACSONE SA/NV +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +from odoo import api, fields, models +from odoo.tools.safe_eval import safe_eval + +from odoo.addons.stock.models.product import OPERATORS + + +class ProductTemplate(models.Model): + + _inherit = "product.template" + + quantity_to_replenish = fields.Float( + compute="_compute_available_quantities", + search="_search_quantity_to_replenish", + help="This is the quantity to replenish following the location orderpoints.", + ) + quantity_in_replenishments = fields.Float( + compute="_compute_available_quantities", + search="_search_quantity_in_replenishments", + help="This is the quantity currently in replenishments following the " + "location orderpoints.", + ) + + @api.depends( + "product_variant_ids.quantity_to_replenish", + "product_variant_ids.quantity_in_replenishments", + ) + def _compute_available_quantities(self): + return super()._compute_available_quantities() + + def _compute_available_quantities_dict(self): + """ + Sum all quantities to replenish from variants + """ + res = super()._compute_available_quantities_dict() + for template in self: + res[template.id]["quantity_to_replenish"] = sum( + p.quantity_to_replenish for p in template.product_variant_ids + ) + res[template.id]["quantity_in_replenishments"] = sum( + p.quantity_in_replenishments for p in template.product_variant_ids + ) + return res + + def _get_search_quantity_to_replenish_domain(self): + return [("type", "=", "product")] + + def _search_quantity_to_replenish(self, operator, value): + product_domain = self._get_search_quantity_to_replenish_domain() + products = self.with_context(prefetch_fields=False).search( + product_domain, order="id" + ) + product_ids = [] + for product in products: + if OPERATORS[operator](product.quantity_to_replenish, value): + product_ids.append(product.id) + return [("id", "in", product_ids)] + + def _get_search_quantity_in_replenishments_domain(self): + return [("type", "=", "product")] + + def _search_quantity_in_replenishments(self, operator, value): + product_domain = self._get_search_quantity_in_replenishments_domain() + products = self.with_context(prefetch_fields=False).search( + product_domain, order="id" + ) + product_ids = [] + for product in products: + if OPERATORS[operator](product.quantity_in_replenishments, value): + product_ids.append(product.id) + return [("id", "in", product_ids)] + + def action_open_replenishments(self): + action = self.env["ir.actions.act_window"]._for_xml_id( + "stock.stock_move_action" + ) + action["domain"] = [ + ("location_orderpoint_id", "!=", False), + ("product_id", "in", self.product_variant_ids.ids), + ] + action["context"] = dict(safe_eval(action["context"]), search_default_future=1) + return action diff --git a/stock_available_location_orderpoint/readme/CONFIGURE.rst b/stock_available_location_orderpoint/readme/CONFIGURE.rst new file mode 100644 index 00000000..a9863a63 --- /dev/null +++ b/stock_available_location_orderpoint/readme/CONFIGURE.rst @@ -0,0 +1 @@ +See stock_location_orderpoint module README. diff --git a/stock_available_location_orderpoint/readme/CONTRIBUTORS.rst b/stock_available_location_orderpoint/readme/CONTRIBUTORS.rst new file mode 100644 index 00000000..9179ee4b --- /dev/null +++ b/stock_available_location_orderpoint/readme/CONTRIBUTORS.rst @@ -0,0 +1 @@ +* Denis Roussel diff --git a/stock_available_location_orderpoint/readme/DESCRIPTION.rst b/stock_available_location_orderpoint/readme/DESCRIPTION.rst new file mode 100644 index 00000000..c02b5147 --- /dev/null +++ b/stock_available_location_orderpoint/readme/DESCRIPTION.rst @@ -0,0 +1,2 @@ +This module allows to display on product level the quantity to be replenished +through location orderpoints and the quantity that is currently in replenishments. diff --git a/stock_available_location_orderpoint/readme/USAGE.rst b/stock_available_location_orderpoint/readme/USAGE.rst new file mode 100644 index 00000000..ca91c22a --- /dev/null +++ b/stock_available_location_orderpoint/readme/USAGE.rst @@ -0,0 +1,10 @@ +#. Go to Inventory > Products +#. On product form, the quantity to replenish is on top 'N.N (N.N) To Replenish' +#. The number between brackets is the quantity in replenishments +#. If you click on the button, you will see the movements that are to be done + to fullfill the replenishment(s). + +.. image:: ../static/description/product_form.bmp + +* These quantities are also displayed optionally on product list level and in + product kanban. diff --git a/stock_available_location_orderpoint/static/description/icon.png b/stock_available_location_orderpoint/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..3a0328b516c4980e8e44cdb63fd945757ddd132d GIT binary patch literal 9455 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 z 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 Xviia!U7SGha1wx#SCgwmn*{w2TRX*I literal 0 HcmV?d00001 diff --git a/stock_available_location_orderpoint/static/description/index.html b/stock_available_location_orderpoint/static/description/index.html new file mode 100644 index 00000000..eff69ad2 --- /dev/null +++ b/stock_available_location_orderpoint/static/description/index.html @@ -0,0 +1,443 @@ + + + + + + +Stock Available Location Orderpoint + + + +
+

Stock Available Location Orderpoint

+ + +

Beta License: AGPL-3 OCA/stock-logistics-availability Translate me on Weblate Try me on Runboat

+

This module allows to display on product level the quantity to be replenished +through location orderpoints and the quantity that is currently in replenishments.

+

Table of contents

+ +
+

Configuration

+

See stock_location_orderpoint module README.

+
+
+

Usage

+
    +
  1. Go to Inventory > Products
  2. +
  3. On product form, the quantity to replenish is on top ‘N.N (N.N) To Replenish’
  4. +
  5. The number between brackets is the quantity in replenishments
  6. +
  7. If you click on the button, you will see the movements that are to be done +to fullfill the replenishment(s).
  8. +
+https://raw.githubusercontent.com/OCA/stock-logistics-availability/16.0/stock_available_location_orderpoint/static/description/product_form.bmp +
    +
  • These quantities are also displayed optionally on product list level and in +product kanban.
  • +
+
+
+

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 +feedback.

+

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

+
+
+

Credits

+
+

Authors

+
    +
  • ACSONE SA/NV
  • +
+
+
+

Contributors

+ +
+
+

Maintainers

+

This module is maintained by the OCA.

+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.

+

This module is part of the OCA/stock-logistics-availability project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+ + diff --git a/stock_available_location_orderpoint/static/description/product_form.bmp b/stock_available_location_orderpoint/static/description/product_form.bmp new file mode 100644 index 0000000000000000000000000000000000000000..93d32b5d3008e079084c1163301ca5bf1c6267a2 GIT binary patch literal 2625134 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%0D(*OR;rj?S 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 + + + + Quantity to Replenish (in stock_available_location_orderpoint) + product.product + + + + + + + + + + Quantity to Replenish (in stock_available_location_orderpoint) + product.product + + + + + + + + + + + Quantity to Replenish (in stock_available_location_orderpoint) + product.product + + + + + + + + + + diff --git a/stock_available_location_orderpoint/views/product_template.xml b/stock_available_location_orderpoint/views/product_template.xml new file mode 100644 index 00000000..45bfa250 --- /dev/null +++ b/stock_available_location_orderpoint/views/product_template.xml @@ -0,0 +1,115 @@ + + + + + + Quantity to Replenish (in stock_available_location_orderpoint) + product.template + + + + + + + + + + Quantity to Replenish (in stock_available_location_orderpoint) + product.template + + + + + + + + + + + Quantity to Replenish (in stock_available_location_orderpoint) + product.template + + + +
To Replenish: + ( + ) + +
+
+
+
+ + + Quantity to Replenish (in stock_available_location_orderpoint) + product.template + + + + + + + + + +
From 47d6b2fe6d87854d16c12a50773a53f3d24b39a8 Mon Sep 17 00:00:00 2001 From: Denis Roussel Date: Mon, 10 Jul 2023 09:02:21 +0200 Subject: [PATCH 2/9] [IMP] stock_available_location_orderpoint: Improve tests for sublocations --- .../models/product_product.py | 2 + .../readme/ROADMAP.rst | 0 .../test_available_location_orderpoint.py | 14 ++- ..._available_location_orderpoint_template.py | 105 +++++++++++++++++- 4 files changed, 115 insertions(+), 6 deletions(-) create mode 100644 stock_available_location_orderpoint/readme/ROADMAP.rst diff --git a/stock_available_location_orderpoint/models/product_product.py b/stock_available_location_orderpoint/models/product_product.py index 458d2dab..d5b49451 100644 --- a/stock_available_location_orderpoint/models/product_product.py +++ b/stock_available_location_orderpoint/models/product_product.py @@ -71,6 +71,8 @@ def _compute_available_quantities_dict(self): for product in self: qties_replenished_for_location = {product: 0.0} for orderpoint in orderpoints: + # As we compute global quantities for the product, pass + # always 0 to the already replenished quantity qty_to_replenish = orderpoint._get_qty_to_replenish( product, qties_on_locations, diff --git a/stock_available_location_orderpoint/readme/ROADMAP.rst b/stock_available_location_orderpoint/readme/ROADMAP.rst new file mode 100644 index 00000000..e69de29b diff --git a/stock_available_location_orderpoint/tests/test_available_location_orderpoint.py b/stock_available_location_orderpoint/tests/test_available_location_orderpoint.py index 0fc92bd0..96b037a1 100644 --- a/stock_available_location_orderpoint/tests/test_available_location_orderpoint.py +++ b/stock_available_location_orderpoint/tests/test_available_location_orderpoint.py @@ -139,8 +139,11 @@ def test_available_on_one_shelf_location(self): move = self._create_outgoing_move(1) self.assertEqual(move.state, "confirmed") self.product.invalidate_recordset() + # The quantity to replenish is equal to the total of replenishment locations + # quantity as they are in shelf parents path. self.assertEqual( - 7.0, self.product.with_context(location=self.shelf.id).quantity_to_replenish + 17.0, + self.product.with_context(location=self.shelf.id).quantity_to_replenish, ) def test_available_on_one_stock_location_with_shelf(self): @@ -204,16 +207,17 @@ def test_available_on_one_stock_location_with_shelf(self): # Check the replenishment value for shelf location only self.assertEqual( - 5.0, self.product.with_context(location=self.shelf.id).quantity_to_replenish + 15.0, + self.product.with_context(location=self.shelf.id).quantity_to_replenish, ) # We are not in shelf location context - product = self.product.search([("quantity_to_replenish", "=", 5.0)]) - self.assertFalse(self.product.id in product.ids) + product = self.product.search([("quantity_to_replenish", "=", 15.0)]) + self.assertTrue(self.product.id in product.ids) # We are in shelf location context product = self.product.with_context(location=self.shelf.id).search( - [("quantity_to_replenish", "=", 5.0)] + [("quantity_to_replenish", "=", 15.0)] ) self.assertTrue(self.product.id in product.ids) diff --git a/stock_available_location_orderpoint/tests/test_available_location_orderpoint_template.py b/stock_available_location_orderpoint/tests/test_available_location_orderpoint_template.py index 251af56b..ea9a1e62 100644 --- a/stock_available_location_orderpoint/tests/test_available_location_orderpoint_template.py +++ b/stock_available_location_orderpoint/tests/test_available_location_orderpoint_template.py @@ -329,11 +329,114 @@ def test_available_on_one_stock_location_with_shelf(self): # We are in shelf context self.template.invalidate_recordset() + self.template.product_variant_ids.invalidate_recordset() + self.template.with_context( + location=self.shelf.id + )._compute_available_quantities_dict() + self.assertEqual( + 15.0, + self.template.with_context(location=self.shelf.id).quantity_to_replenish, + ) templates = self.template.with_context(location=self.shelf.id).search( - [("quantity_to_replenish", "=", 5.0)] + [("quantity_to_replenish", "=", 15.0)] ) self.assertTrue(self.template.id in templates.ids) + def test_available_on_different_sublocation(self): + """ + Remove the existing orderpoints + + Create a location structure like: + - Stock + - Area 1 + - Shelf 1 + - Area 2 + - Shelf 2 + + Create orderpoints for both areas. + + Create ougoing moves for both shelves: + - Shelf 1: 12.0 + - Shelf 2: 2.0 + + Global quantity to replenish should be 8.0 + + Quantity for Shelf 1 should be 6.0 + + """ + # Archive orderpoints + self.env["stock.location.orderpoint"].search([]).write({"active": False}) + + self.area_1 = self.env["stock.location"].create( + { + "name": "Area 1", + "location_id": self.location_dest.id, + "usage": "view", + } + ) + + self.shelf_1 = self.env["stock.location"].create( + {"name": "Shelf 1", "location_id": self.area_1.id} + ) + + self.area_2 = self.env["stock.location"].create( + { + "name": "Area 2", + "location_id": self.location_dest.id, + "usage": "view", + } + ) + + self.shelf_2 = self.env["stock.location"].create( + {"name": "Shelf 1", "location_id": self.area_2.id} + ) + + # Create an orderpoint by shelf + self.location_dest = self.area_1 + ( + self.orderpoint_shelf_1, + self.location_src_shelf_1, + ) = self._create_orderpoint_complete("Area 1 Replenishment", trigger="manual") + + self.location_dest = self.area_2 + ( + self.orderpoint_shelf_2, + self.location_src_shelf_2, + ) = self._create_orderpoint_complete("Area 2 Replenishment", trigger="manual") + + # Set stock on replenishment locations + self.env["stock.quant"].with_context(inventory_mode=True).create( + { + "inventory_quantity": 6.0, + "location_id": self.location_src_shelf_1.id, + "product_id": self.product.id, + } + )._apply_inventory() + self.env["stock.quant"].with_context(inventory_mode=True).create( + { + "inventory_quantity": 4.0, + "location_id": self.location_src_shelf_2.id, + "product_id": self.product.id, + } + )._apply_inventory() + + self.location_dest = self.shelf_1 + move = self._create_outgoing_move(12) + self.assertEqual(move.state, "confirmed") + + self.location_dest = self.shelf_2 + move = self._create_outgoing_move(2) + self.assertEqual(move.state, "confirmed") + + self.template.invalidate_recordset() + self.assertEqual(8.0, self.template.quantity_to_replenish) + + self.template.invalidate_recordset() + self.assertEqual( + 6.0, + self.template.with_context(location=self.shelf_1.id).quantity_to_replenish, + ) + def test_action(self): action = self.template.action_open_replenishments() self.assertIn( From 84682c7f0c1e156ea6ec54652d44830ce9ac0b48 Mon Sep 17 00:00:00 2001 From: Denis Roussel Date: Tue, 11 Jul 2023 13:44:32 +0200 Subject: [PATCH 3/9] [FIX] stock_available_location_orderpoint: Use correct quantity for current replenishments --- .../models/product_product.py | 4 +- .../test_available_location_orderpoint.py | 117 ++++++++++++++++++ ..._available_location_orderpoint_template.py | 61 ++++++++- 3 files changed, 174 insertions(+), 8 deletions(-) diff --git a/stock_available_location_orderpoint/models/product_product.py b/stock_available_location_orderpoint/models/product_product.py index d5b49451..bd5c5804 100644 --- a/stock_available_location_orderpoint/models/product_product.py +++ b/stock_available_location_orderpoint/models/product_product.py @@ -60,13 +60,13 @@ def _compute_available_quantities_dict(self): ("state", "not in", ("done", "cancel")), ("product_id", "in", self.ids), ], - ["product_id"], + ["product_id", "product_uom_qty:sum"], ["product_id"], ) quantities_in_replenishments = defaultdict(lambda: defaultdict(lambda: 0)) for current_move in current_moves: quantities_in_replenishments[current_move["product_id"][0]] = current_move[ - "product_id_count" + "product_uom_qty" ] for product in self: qties_replenished_for_location = {product: 0.0} diff --git a/stock_available_location_orderpoint/tests/test_available_location_orderpoint.py b/stock_available_location_orderpoint/tests/test_available_location_orderpoint.py index 96b037a1..11e798b0 100644 --- a/stock_available_location_orderpoint/tests/test_available_location_orderpoint.py +++ b/stock_available_location_orderpoint/tests/test_available_location_orderpoint.py @@ -221,6 +221,123 @@ def test_available_on_one_stock_location_with_shelf(self): ) self.assertTrue(self.product.id in product.ids) + def test_available_on_different_sublocation(self): + """ + Remove the existing orderpoints + + Create a location structure like: + - Stock + - Area 1 + - Shelf 1 + - Area 2 + - Shelf 2 + + Create orderpoints for both areas. + + Create ougoing moves for both shelves: + - Shelf 1: 12.0 (product 1) + - Shelf 2: 2.0 + + Global quantity to replenish should be 8.0 + + Quantity for Shelf 1 should be 6.0 + + """ + # Archive orderpoints + self.env["stock.location.orderpoint"].search([]).write({"active": False}) + + self.area_1 = self.env["stock.location"].create( + { + "name": "Area 1", + "location_id": self.location_dest.id, + "usage": "view", + } + ) + + self.shelf_1 = self.env["stock.location"].create( + {"name": "Shelf 1", "location_id": self.area_1.id} + ) + + self.area_2 = self.env["stock.location"].create( + { + "name": "Area 2", + "location_id": self.location_dest.id, + "usage": "view", + } + ) + + self.shelf_2 = self.env["stock.location"].create( + {"name": "Shelf 1", "location_id": self.area_2.id} + ) + + # Create an orderpoint by shelf + self.location_dest = self.area_1 + ( + self.orderpoint_shelf_1, + self.location_src_shelf_1, + ) = self._create_orderpoint_complete("Area 1 Replenishment", trigger="manual") + + self.location_dest = self.area_2 + ( + self.orderpoint_shelf_2, + self.location_src_shelf_2, + ) = self._create_orderpoint_complete("Area 2 Replenishment", trigger="manual") + + # Set stock on replenishment locations + self.env["stock.quant"].with_context(inventory_mode=True).create( + { + "inventory_quantity": 6.0, + "location_id": self.location_src_shelf_1.id, + "product_id": self.product.id, + } + )._apply_inventory() + self.env["stock.quant"].with_context(inventory_mode=True).create( + { + "inventory_quantity": 4.0, + "location_id": self.location_src_shelf_2.id, + "product_id": self.product.id, + } + )._apply_inventory() + + self.location_dest = self.area_1 + move = self._create_outgoing_move(12) + self.assertEqual(move.state, "confirmed") + + self.location_dest = self.area_2 + move = self._create_outgoing_move(2) + self.assertEqual(move.state, "confirmed") + + self.product.invalidate_recordset() + self.assertEqual(8.0, self.product.quantity_to_replenish) + + self.product.invalidate_recordset() + self.assertEqual( + 6.0, + self.product.with_context(location=self.shelf_1.id).quantity_to_replenish, + ) + + # Run replenishment on area 1 + self.orderpoint_shelf_1.run_replenishment() + # Test all variables in different contexts + self.product.invalidate_recordset() + self.assertEqual(2.0, self.product.quantity_to_replenish) + self.assertEqual(6.0, self.product.quantity_in_replenishments) + self.product.invalidate_recordset() + self.assertEqual( + 0.0, + self.product.with_context(location=self.shelf_1.id).quantity_to_replenish, + ) + self.product.invalidate_recordset() + self.assertEqual( + 6.0, + self.product.with_context( + location=self.shelf_1.id + ).quantity_in_replenishments, + ) + + products = self.product.search([("quantity_in_replenishments", "=", 6.0)]) + self.assertTrue(self.product.id in products.ids) + def test_action(self): action = self.product.action_open_replenishments() self.assertIn( diff --git a/stock_available_location_orderpoint/tests/test_available_location_orderpoint_template.py b/stock_available_location_orderpoint/tests/test_available_location_orderpoint_template.py index ea9a1e62..49d9e8e5 100644 --- a/stock_available_location_orderpoint/tests/test_available_location_orderpoint_template.py +++ b/stock_available_location_orderpoint/tests/test_available_location_orderpoint_template.py @@ -356,8 +356,9 @@ def test_available_on_different_sublocation(self): Create orderpoints for both areas. Create ougoing moves for both shelves: - - Shelf 1: 12.0 - - Shelf 2: 2.0 + - Shelf 1: 12.0 (Product 1) + - Shelf 1: 4.0 (Product 2) + - Shelf 2: 2.0 (Product 1) Global quantity to replenish should be 8.0 @@ -412,6 +413,13 @@ def test_available_on_different_sublocation(self): "product_id": self.product.id, } )._apply_inventory() + self.env["stock.quant"].with_context(inventory_mode=True).create( + { + "inventory_quantity": 5.0, + "location_id": self.location_src_shelf_1.id, + "product_id": self.product_2.id, + } + )._apply_inventory() self.env["stock.quant"].with_context(inventory_mode=True).create( { "inventory_quantity": 4.0, @@ -420,22 +428,63 @@ def test_available_on_different_sublocation(self): } )._apply_inventory() - self.location_dest = self.shelf_1 + self.env["stock.quant"].with_context(inventory_mode=True).create( + { + "inventory_quantity": 3.0, + "location_id": self.location_src_shelf_2.id, + "product_id": self.product_2.id, + } + )._apply_inventory() + + # Product 1 + self.location_dest = self.area_1 move = self._create_outgoing_move(12) self.assertEqual(move.state, "confirmed") - self.location_dest = self.shelf_2 + self.location_dest = self.area_2 move = self._create_outgoing_move(2) self.assertEqual(move.state, "confirmed") + # Product 2 - with less quantity than in replenishment location + self.product = self.product_2 + self.location_dest = self.area_1 + move = self._create_outgoing_move(1) + self.assertEqual(move.state, "confirmed") + + self.location_dest = self.area_2 + move = self._create_outgoing_move(3) + self.assertEqual(move.state, "confirmed") + + self.template.invalidate_recordset() + self.assertEqual(12.0, self.template.quantity_to_replenish) + self.template.invalidate_recordset() - self.assertEqual(8.0, self.template.quantity_to_replenish) + self.assertEqual( + 7.0, + self.template.with_context(location=self.shelf_1.id).quantity_to_replenish, + ) + # Run replenishment on area 1 + self.orderpoint_shelf_1.run_replenishment() + # Test all variables in different contexts + self.template.invalidate_recordset() + self.assertEqual(5.0, self.template.quantity_to_replenish) + self.assertEqual(7.0, self.template.quantity_in_replenishments) self.template.invalidate_recordset() self.assertEqual( - 6.0, + 0.0, self.template.with_context(location=self.shelf_1.id).quantity_to_replenish, ) + self.template.invalidate_recordset() + self.assertEqual( + 7.0, + self.template.with_context( + location=self.shelf_1.id + ).quantity_in_replenishments, + ) + + templates = self.template.search([("quantity_in_replenishments", "=", 7.0)]) + self.assertTrue(self.template.id in templates.ids) def test_action(self): action = self.template.action_open_replenishments() From 34dd3254494ed5f4ee2a13d89db81a1654e364dc Mon Sep 17 00:00:00 2001 From: Denis Roussel Date: Wed, 22 Nov 2023 10:09:40 +0100 Subject: [PATCH 4/9] [IMP] stock_available_location_orderpoint: Don't compute to replenish with other fields As for performances improvements, we don't need always the replenishement quantities in the recordset with the other quantity fields --- .../models/product_product.py | 50 +++++++++++-------- ..._available_location_orderpoint_template.py | 2 + 2 files changed, 30 insertions(+), 22 deletions(-) diff --git a/stock_available_location_orderpoint/models/product_product.py b/stock_available_location_orderpoint/models/product_product.py index bd5c5804..bdef5a52 100644 --- a/stock_available_location_orderpoint/models/product_product.py +++ b/stock_available_location_orderpoint/models/product_product.py @@ -2,7 +2,7 @@ # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). from collections import defaultdict -from odoo import fields, models +from odoo import api, fields, models from odoo.tools import float_compare from odoo.tools.safe_eval import safe_eval @@ -14,36 +14,38 @@ class ProductProduct(models.Model): _inherit = "product.product" quantity_to_replenish = fields.Float( - compute="_compute_available_quantities", + compute="_compute_replenishment_quantities", search="_search_quantity_to_replenish", + prefetch=False, help="This is the quantity to replenish following the location orderpoints.", ) quantity_in_replenishments = fields.Float( - compute="_compute_available_quantities", + compute="_compute_replenishment_quantities", search="_search_quantity_in_replenishments", + prefetch=False, help="This is the quantity currently in replenishments following the " "location orderpoints.", ) - def _compute_available_quantities_dict(self): - """ - Retrieve all replenishment quantities for the selected products - and locations. - """ - res, stock_dict = super()._compute_available_quantities_dict() - location_domain = self._get_domain_location_for_locations() - locations = self.env["stock.location"].search(location_domain) + @api.depends_context("location") + def _compute_replenishment_quantities(self): orderpoint_obj = self.env["stock.location.orderpoint"] if orderpoint_obj.check_access_rights("read", raise_exception=False): + orderpoint_obj = self.env["stock.location.orderpoint"] + location_domain = self._get_domain_location_for_locations() + locations = self.env["stock.location"].search(location_domain) orderpoint_domain = orderpoint_obj._prepare_orderpoint_domain_location( locations.ids ) orderpoints = orderpoint_obj.search(orderpoint_domain) else: - for product in self: - res[product.id]["quantity_to_replenish"] = 0 - res[product.id]["quantity_in_replenishments"] = 0 - return res, stock_dict + self.update( + { + "quantity_to_replenish": 0.0, + "quantity_in_replenishments": 0.0, + } + ) + return # Merge both source locations and destination locations location_ids = set( @@ -84,14 +86,18 @@ def _compute_available_quantities_dict(self): ) > 0 ): + # We take the maximum value from all the concerned orderpoints + # for the product qties_replenished_for_location[product] += qty_to_replenish - res[product.id][ - "quantity_in_replenishments" - ] = quantities_in_replenishments[product.id] - res[product.id]["quantity_to_replenish"] = qties_replenished_for_location[ - product - ] - return res, stock_dict + product.update( + { + "quantity_in_replenishments": quantities_in_replenishments[ + product.id + ], + "quantity_to_replenish": qties_replenished_for_location[product], + } + ) + return def _get_search_quantity_to_replenish_domain(self): return [("type", "=", "product")] diff --git a/stock_available_location_orderpoint/tests/test_available_location_orderpoint_template.py b/stock_available_location_orderpoint/tests/test_available_location_orderpoint_template.py index 49d9e8e5..abc7f77e 100644 --- a/stock_available_location_orderpoint/tests/test_available_location_orderpoint_template.py +++ b/stock_available_location_orderpoint/tests/test_available_location_orderpoint_template.py @@ -456,6 +456,7 @@ def test_available_on_different_sublocation(self): self.assertEqual(move.state, "confirmed") self.template.invalidate_recordset() + self.template.product_variant_ids.invalidate_recordset() self.assertEqual(12.0, self.template.quantity_to_replenish) self.template.invalidate_recordset() @@ -468,6 +469,7 @@ def test_available_on_different_sublocation(self): self.orderpoint_shelf_1.run_replenishment() # Test all variables in different contexts self.template.invalidate_recordset() + self.template.product_variant_ids.invalidate_recordset() self.assertEqual(5.0, self.template.quantity_to_replenish) self.assertEqual(7.0, self.template.quantity_in_replenishments) self.template.invalidate_recordset() From 2ba313ac5f0a62a4b42a3550aeeef7460dcc098d Mon Sep 17 00:00:00 2001 From: Nicolas Delbovier Date: Tue, 2 Sep 2025 09:39:00 +0200 Subject: [PATCH 5/9] [FIX] stock_available_location_orderpoint: fix miscalculated replenishment quantities + fix unit tests. The code to compute the current replenishment moves was not returning the expected value inside `_compute_replenishment_quantities`. (there were missing moves). The code in unit tests was having unexpected behavior due to class variables being modified while they are used as defaults everywhere in the code's methods. The tests have been corrected to make sure they do not modify these variable anymore while ensuring the logic is the same as before. --- .../README.rst | 1 + .../models/product_product.py | 3 +- .../readme/CONTRIBUTORS.rst | 1 + .../static/description/index.html | 47 ++++++------ .../test_available_location_orderpoint.py | 29 ++++---- ..._available_location_orderpoint_template.py | 71 ++++++++++--------- 6 files changed, 78 insertions(+), 74 deletions(-) diff --git a/stock_available_location_orderpoint/README.rst b/stock_available_location_orderpoint/README.rst index a4893c17..1d007106 100644 --- a/stock_available_location_orderpoint/README.rst +++ b/stock_available_location_orderpoint/README.rst @@ -77,6 +77,7 @@ Contributors ~~~~~~~~~~~~ * Denis Roussel +* Nicolas Delbovier Maintainers ~~~~~~~~~~~ diff --git a/stock_available_location_orderpoint/models/product_product.py b/stock_available_location_orderpoint/models/product_product.py index bdef5a52..f651ccf1 100644 --- a/stock_available_location_orderpoint/models/product_product.py +++ b/stock_available_location_orderpoint/models/product_product.py @@ -10,7 +10,6 @@ class ProductProduct(models.Model): - _inherit = "product.product" quantity_to_replenish = fields.Float( @@ -58,7 +57,7 @@ def _compute_replenishment_quantities(self): # Get current replenishments current_moves = self.env["stock.move"].read_group( [ - ("location_id", "in", orderpoints.location_src_id.ids), + ("location_orderpoint_id", "in", orderpoints.ids), ("state", "not in", ("done", "cancel")), ("product_id", "in", self.ids), ], diff --git a/stock_available_location_orderpoint/readme/CONTRIBUTORS.rst b/stock_available_location_orderpoint/readme/CONTRIBUTORS.rst index 9179ee4b..934a8448 100644 --- a/stock_available_location_orderpoint/readme/CONTRIBUTORS.rst +++ b/stock_available_location_orderpoint/readme/CONTRIBUTORS.rst @@ -1 +1,2 @@ * Denis Roussel +* Nicolas Delbovier \ No newline at end of file diff --git a/stock_available_location_orderpoint/static/description/index.html b/stock_available_location_orderpoint/static/description/index.html index eff69ad2..e7e19409 100644 --- a/stock_available_location_orderpoint/static/description/index.html +++ b/stock_available_location_orderpoint/static/description/index.html @@ -1,20 +1,20 @@ - - + Stock Available Location Orderpoint -
-

Stock Available Location Orderpoint

+
+ + +Odoo Community Association + +
+

Stock Available Location Orderpoint

-

Beta License: AGPL-3 OCA/stock-logistics-availability Translate me on Weblate Try me on Runboat

+

Beta License: AGPL-3 OCA/stock-logistics-availability Translate me on Weblate Try me on Runboat

This module allows to display on product level the quantity to be replenished through location orderpoints and the quantity that is currently in replenishments.

Table of contents

@@ -387,11 +392,11 @@

Stock Available Location Orderpoint

-

Configuration

+

Configuration

See stock_location_orderpoint module README.

-

Usage

+

Usage

  1. Go to Inventory > Products
  2. On product form, the quantity to replenish is on top ‘N.N (N.N) To Replenish’
  3. @@ -406,7 +411,7 @@

    Usage

-

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 @@ -414,22 +419,22 @@

Bug Tracker

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

-

Credits

+

Credits

-

Authors

+

Authors

  • ACSONE SA/NV
-

Maintainers

+

Maintainers

This module is maintained by the OCA.

Odoo Community Association @@ -442,5 +447,6 @@

Maintainers

+