diff --git a/setup/stock_packaging_usability/odoo/addons/stock_packaging_usability b/setup/stock_packaging_usability/odoo/addons/stock_packaging_usability new file mode 120000 index 00000000000..63777295a1f --- /dev/null +++ b/setup/stock_packaging_usability/odoo/addons/stock_packaging_usability @@ -0,0 +1 @@ +../../../../stock_packaging_usability \ No newline at end of file diff --git a/setup/stock_packaging_usability/setup.py b/setup/stock_packaging_usability/setup.py new file mode 100644 index 00000000000..28c57bb6403 --- /dev/null +++ b/setup/stock_packaging_usability/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +) diff --git a/setup/stock_packaging_usability_pp/odoo/addons/stock_packaging_usability_pp b/setup/stock_packaging_usability_pp/odoo/addons/stock_packaging_usability_pp new file mode 120000 index 00000000000..9a457ebfc03 --- /dev/null +++ b/setup/stock_packaging_usability_pp/odoo/addons/stock_packaging_usability_pp @@ -0,0 +1 @@ +../../../../stock_packaging_usability_pp \ No newline at end of file diff --git a/setup/stock_packaging_usability_pp/setup.py b/setup/stock_packaging_usability_pp/setup.py new file mode 100644 index 00000000000..28c57bb6403 --- /dev/null +++ b/setup/stock_packaging_usability_pp/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +) diff --git a/stock_packaging_usability/README.rst b/stock_packaging_usability/README.rst new file mode 100644 index 00000000000..1f597ed796f --- /dev/null +++ b/stock_packaging_usability/README.rst @@ -0,0 +1,60 @@ +.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 + +========================= +Stock Packaging Usability +========================= + +Configuration +============= + +Go to the Settings page of the Inventory menu and enable the option +*Record packages used on packing: pallets, boxes, ...*: it will add all +users to the group *Manage Packages*. + +Usage +===== + +This module adds 2 buttons in the *Operations* lines of a picking: + +* *Put in current pack* + +* *Put in new pack* + +It is a complement of the button *Put in Pack* which is available on the picking. With these 2 new buttons, you are not obliged to set the *Done quantity* package by package. + +.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas + :alt: Try me on Runbot + :target: https://runbot.odoo-community.org/runbot/152/10.0 + +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 smashing it by providing a detailed and welcomed feedback. + +Credits +======= + +Contributors +------------ + +* Alexis de Lattre + +Maintainer +---------- + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +This module is maintained by the OCA. + +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. + +To contribute to this module, please visit https://odoo-community.org. diff --git a/stock_packaging_usability/__init__.py b/stock_packaging_usability/__init__.py new file mode 100644 index 00000000000..0650744f6bc --- /dev/null +++ b/stock_packaging_usability/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/stock_packaging_usability/__manifest__.py b/stock_packaging_usability/__manifest__.py new file mode 100644 index 00000000000..eb6d5eedcfd --- /dev/null +++ b/stock_packaging_usability/__manifest__.py @@ -0,0 +1,20 @@ +# Copyright 2014-2021 Akretion France (http://www.akretion.com). +# @author Alexis de Lattre +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + + +{ + "name": "Stock Packaging Usability", + "version": "14.0.1.0.0", + "category": "Inventory/Inventory", + "license": "AGPL-3", + "summary": "Faster packaging process in Odoo", + "author": "Akretion,Odoo Community Association (OCA)", + "maintainers": ["alexis-via"], + "website": "https://github.com/OCA/stock-logistics-tracking", + "depends": ["stock"], + "data": [ + "views/stock_move_line.xml", + ], + "installable": True, +} diff --git a/stock_packaging_usability/i18n/fr.po b/stock_packaging_usability/i18n/fr.po new file mode 100644 index 00000000000..6fe0de969b8 --- /dev/null +++ b/stock_packaging_usability/i18n/fr.po @@ -0,0 +1,78 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * stock_packaging_usability +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 14.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-12-23 16:50+0000\n" +"PO-Revision-Date: 2021-12-23 16:50+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_packaging_usability +#: code:addons/stock_packaging_usability/models/stock_move_line.py:0 +#, python-format +msgid "Could not find any package level linked to package '%s'." +msgstr "" + +#. module: stock_packaging_usability +#: model:ir.model.fields,field_description:stock_packaging_usability.field_stock_move_line__display_name +msgid "Display Name" +msgstr "Nom affiché" + +#. module: stock_packaging_usability +#: model:ir.model.fields,field_description:stock_packaging_usability.field_stock_move_line__id +msgid "ID" +msgstr "" + +#. module: stock_packaging_usability +#: model:ir.model.fields,field_description:stock_packaging_usability.field_stock_move_line____last_update +msgid "Last Modified on" +msgstr "Dernière modification le" + +#. module: stock_packaging_usability +#: model:ir.model,name:stock_packaging_usability.model_stock_move_line +msgid "Product Moves (Stock Move Line)" +msgstr "Mouvements d'article (Ligne de mouvement de stock)" + +#. module: stock_packaging_usability +#: model_terms:ir.ui.view,arch_db:stock_packaging_usability.view_stock_move_line_detailed_operation_tree +#: model_terms:ir.ui.view,arch_db:stock_packaging_usability.view_stock_move_line_operation_tree +msgid "Put in Current Pack" +msgstr "" + +#. module: stock_packaging_usability +#: model_terms:ir.ui.view,arch_db:stock_packaging_usability.view_stock_move_line_detailed_operation_tree +#: model_terms:ir.ui.view,arch_db:stock_packaging_usability.view_stock_move_line_operation_tree +msgid "Put in New Pack" +msgstr "" + +#. module: stock_packaging_usability +#: code:addons/stock_packaging_usability/models/stock_move_line.py:0 +#, python-format +msgid "Qty done is 0" +msgstr "" + +#. module: stock_packaging_usability +#: code:addons/stock_packaging_usability/models/stock_move_line.py:0 +#, python-format +msgid "There are several package levels linked to package '%s'." +msgstr "" + +#. module: stock_packaging_usability +#: code:addons/stock_packaging_usability/models/stock_move_line.py:0 +#, python-format +msgid "There is no current package." +msgstr "" + +#. module: stock_packaging_usability +#: code:addons/stock_packaging_usability/models/stock_move_line.py:0 +#, python-format +msgid "This operation is already packaged." +msgstr "" diff --git a/stock_packaging_usability/i18n/stock_packaging_usability.pot b/stock_packaging_usability/i18n/stock_packaging_usability.pot new file mode 100644 index 00000000000..e69de29bb2d diff --git a/stock_packaging_usability/models/__init__.py b/stock_packaging_usability/models/__init__.py new file mode 100644 index 00000000000..431f51c2747 --- /dev/null +++ b/stock_packaging_usability/models/__init__.py @@ -0,0 +1 @@ +from . import stock_move_line diff --git a/stock_packaging_usability/models/stock_move_line.py b/stock_packaging_usability/models/stock_move_line.py new file mode 100644 index 00000000000..401e7ee4aa3 --- /dev/null +++ b/stock_packaging_usability/models/stock_move_line.py @@ -0,0 +1,91 @@ +# Copyright 2014-2021 Akretion France (http://www.akretion.com) +# @author Alexis de Lattre +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + + +from odoo import _, models +from odoo.exceptions import UserError +from odoo.tools import float_compare, float_is_zero, float_round + + +class StockMoveLine(models.Model): + _inherit = "stock.move.line" + + def put_in_new_pack(self): + self.ensure_one() + pack = self.env["stock.quant.package"].create({}) + picking = self.picking_id + pack_level = self.env["stock.package_level"].create( + { + "package_id": pack.id, + "picking_id": picking.id, + "location_id": False, + "location_dest_id": self.location_dest_id.id, + "move_line_ids": [(6, 0, [self.id])], + "company_id": picking.company_id.id, + } + ) + self._put_in_target_pack(pack, pack_level) + + def put_in_last_pack(self): + all_cur_packs_ids = [ + moveline2.result_package_id.id + for moveline2 in self.picking_id.move_line_ids + if moveline2.result_package_id + ] + if not all_cur_packs_ids: + raise UserError(_("There is no current package.")) + pack_id = max(all_cur_packs_ids) + pack = self.env["stock.quant.package"].browse(pack_id) + pack_levels = self.env["stock.package_level"].search( + [("package_id", "=", pack_id)] + ) + if not pack_levels: + raise UserError( + _("Could not find any package level linked to package '%s'.") + % pack.display_name + ) + if len(pack_levels) > 1: + raise UserError( + _("There are several package levels linked to package '%s'.") + % pack.display_name + ) + self._put_in_target_pack(pack, pack_levels) + + def _put_in_target_pack(self, pack, pack_level): + self.ensure_one() + assert pack, "pack is a required argument" + prec = self.env["decimal.precision"].precision_get("Product Unit of Measure") + if float_is_zero(self.qty_done, precision_digits=prec): + raise UserError(_("Qty done is 0")) + if self.result_package_id: + raise UserError(_("This operation is already packaged.")) + moveline_to_pack = self + if ( + float_compare(self.qty_done, self.product_uom_qty, precision_digits=prec) + < 0 + ): + quantity_left_todo = float_round( + self.product_uom_qty - self.qty_done, + precision_rounding=self.product_uom_id.rounding, + ) + done_to_keep = self.qty_done + # IMPORTANT: we first create the new move line with product_uom_qty=0 + # and THEN we write product_uom_qty = qty_done on it. + # We MUSTN'T create the new move line directly with + # product_uom_qty=self.qty_done because it doesn't update + # the reserved_qty on the quant, because on stock.move.line + # the inherit of write() calls + # self.env['stock.quant']._update_reserved_quantity() + # but the inherit of create() doesn't ! + new_moveline = self.copy({"product_uom_qty": 0, "qty_done": done_to_keep}) + self.write( + { + "product_uom_qty": quantity_left_todo, + "qty_done": 0, + } + ) + new_moveline.write({"product_uom_qty": done_to_keep}) + moveline_to_pack = new_moveline + pack_level.write({"move_line_ids": [(4, moveline_to_pack.id)]}) + moveline_to_pack.write({"result_package_id": pack.id}) diff --git a/stock_packaging_usability/readme/CONFIGURE.rst b/stock_packaging_usability/readme/CONFIGURE.rst new file mode 100644 index 00000000000..8396e6d808f --- /dev/null +++ b/stock_packaging_usability/readme/CONFIGURE.rst @@ -0,0 +1,3 @@ +Go to the Configuration page of the Inventory menu and enable the option +*Delivery Packages* (Put your products in packs and track them): it will add all +users to the group *Manage Packages*. diff --git a/stock_packaging_usability/readme/CONTRIBUTORS.rst b/stock_packaging_usability/readme/CONTRIBUTORS.rst new file mode 100644 index 00000000000..ff65d68ce6d --- /dev/null +++ b/stock_packaging_usability/readme/CONTRIBUTORS.rst @@ -0,0 +1 @@ +* Alexis de Lattre diff --git a/stock_packaging_usability/readme/DESCRIPTION.rst b/stock_packaging_usability/readme/DESCRIPTION.rst new file mode 100644 index 00000000000..bd94ee5df35 --- /dev/null +++ b/stock_packaging_usability/readme/DESCRIPTION.rst @@ -0,0 +1,7 @@ +This module makes it faster to define which product goes in which pack on an outgoing picking. It adds 2 buttons in the *Operations* lines of a picking: + +* **Put in current pack** + +* **Put in new pack** + +It is a complement of the button **Put in Pack** which is available on the picking. With these 2 new buttons, you are not obliged to set the *Done quantity* package by package. diff --git a/stock_packaging_usability/views/stock_move_line.xml b/stock_packaging_usability/views/stock_move_line.xml new file mode 100644 index 00000000000..8a837dccf8d --- /dev/null +++ b/stock_packaging_usability/views/stock_move_line.xml @@ -0,0 +1,63 @@ + + + + + + + stock_packaging_usability.stock.move.line.form + stock.move.line + + + + + + + + + stock.move.line + + + + + + + + diff --git a/stock_packaging_usability_pp/views/stock_picking.xml b/stock_packaging_usability_pp/views/stock_picking.xml new file mode 100644 index 00000000000..ad42692d559 --- /dev/null +++ b/stock_packaging_usability_pp/views/stock_picking.xml @@ -0,0 +1,49 @@ + + + + + + + stock_packaging_usability_pp.stock.picking.form + stock.picking + + + + action + %(stock_select_product_packaging_action)d + {'pack_function': 'put_selection_in_new_pack'} + + + action + %(stock_select_product_packaging_action)d + {'pack_function': 'put_selection_in_new_pack'} + + + action + %(stock_select_product_packaging_action)d + {'pack_function': 'put_selection_in_new_pack'} + + + + + + diff --git a/stock_packaging_usability_pp/views/stock_quant_package.xml b/stock_packaging_usability_pp/views/stock_quant_package.xml new file mode 100644 index 00000000000..7c348cbc7e1 --- /dev/null +++ b/stock_packaging_usability_pp/views/stock_quant_package.xml @@ -0,0 +1,27 @@ + + + + + + + stock_packaging_usability_pp.stock.quant.package.kanban + stock.quant.package + + + + + +
+
+ +
+
+
+
+ + +
diff --git a/stock_packaging_usability_pp/wizard/__init__.py b/stock_packaging_usability_pp/wizard/__init__.py new file mode 100644 index 00000000000..212240ca1a1 --- /dev/null +++ b/stock_packaging_usability_pp/wizard/__init__.py @@ -0,0 +1 @@ +from . import stock_select_product_packaging diff --git a/stock_packaging_usability_pp/wizard/stock_select_product_packaging.py b/stock_packaging_usability_pp/wizard/stock_select_product_packaging.py new file mode 100644 index 00000000000..b6ad5b684bf --- /dev/null +++ b/stock_packaging_usability_pp/wizard/stock_select_product_packaging.py @@ -0,0 +1,39 @@ +# Copyright 2014-2021 Akretion France (http://www.akretion.com) +# @author Alexis de Lattre +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + + +from odoo import fields, models + + +class StockSelectProductPackaging(models.TransientModel): + _name = "stock.select.product.packaging" + _description = "Select Packaging" + + packaging_id = fields.Many2one("product.packaging", string="Packaging") + # required=False, because we accept that it can be left empty + + def validate(self): + self.ensure_one() + default_packaging_id = self.packaging_id.id or False + assert ( + self.env.context.get("pack_function") is not None + ), "missing context key pack_function" + action = {} + if self._context.get("pack_function") == "put_selection_in_new_pack": + assert ( + self.env.context.get("active_model") == "stock.picking" + ), "Wrong underlying model" + pick = self.env["stock.picking"].browse(self.env.context["active_id"]) + pick.with_context( + default_packaging_id=default_packaging_id + ).action_put_in_pack() + elif self._context.get("pack_function") == "put_in_new_pack": + assert ( + self.env.context.get("active_model") == "stock.move.line" + ), "Wrong underlying model" + ml = self.env["stock.move.line"].browse(self.env.context["active_id"]) + action = ml.with_context( + default_packaging_id=default_packaging_id + ).put_in_new_pack() + return action diff --git a/stock_packaging_usability_pp/wizard/stock_select_product_packaging_view.xml b/stock_packaging_usability_pp/wizard/stock_select_product_packaging_view.xml new file mode 100644 index 00000000000..1e3b6444ac9 --- /dev/null +++ b/stock_packaging_usability_pp/wizard/stock_select_product_packaging_view.xml @@ -0,0 +1,42 @@ + + + + + + + stock.select.product.packaging + +
+ + + +
+
+
+
+
+ + + Select Packaging + stock.select.product.packaging + form + new + + + +