diff --git a/stock_change_qty_reason/__manifest__.py b/stock_change_qty_reason/__manifest__.py index 34a6173460c4..5d65da3180f7 100644 --- a/stock_change_qty_reason/__manifest__.py +++ b/stock_change_qty_reason/__manifest__.py @@ -1,5 +1,5 @@ # Copyright 2016-2017 ACSONE SA/NV () -# Copyright 2019 ForgeFlow S.L. +# Copyright 2019-2023 ForgeFlow S.L. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). { "name": "Stock Change Quantity Reason", @@ -8,16 +8,16 @@ "author": "ACSONE SA/NV, Odoo Community Association (OCA)", "website": "https://github.com/OCA/stock-logistics-warehouse", "category": "Warehouse Management", - "version": "14.0.1.0.2", + "version": "15.0.1.0.0", "license": "AGPL-3", "depends": ["stock"], "data": [ "security/ir.model.access.csv", "security/stock_security.xml", "views/base_config_view.xml", - "views/stock_inventory_line_reason_view.xml", - "views/stock_inventory_line_view.xml", - "views/stock_inventory_view.xml", + "views/stock_move_line_view.xml", + "views/stock_quant_reason_view.xml", + "views/stock_quant_view.xml", ], "installable": True, } diff --git a/stock_change_qty_reason/migrations/15.0.1.0.0/post-migration.py b/stock_change_qty_reason/migrations/15.0.1.0.0/post-migration.py new file mode 100644 index 000000000000..e71e8c926e45 --- /dev/null +++ b/stock_change_qty_reason/migrations/15.0.1.0.0/post-migration.py @@ -0,0 +1,54 @@ +# Copyright 2023 ForgeFlow +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from openupgradelib import openupgrade + + +def fill_stock_quant_reason(env): + openupgrade.logged_query( + env.cr, + """ + UPDATE stock_move_line sml + SET reason = sil.reason + FROM stock_inventory_line sil + JOIN stock_inventory si ON sil.inventory_id = si.id + JOIN stock_location sl ON sil.location_id = sl.id + JOIN stock_move sm ON sm.inventory_id = si.id + WHERE sil.reason IS NOT NULL AND sml.move_id = sm.id + AND sml.location_id = sl.id + AND sl.usage in ('internal', 'transit') + AND si.state = 'done' AND sml.product_id = sil.product_id + AND ((sil.prod_lot_id IS NULL AND sml.lot_id IS NULL) OR ( + sil.prod_lot_id = sml.lot_id)) + AND COALESCE(sml.date, sm.date) = COALESCE( + sil.inventory_date, si.date)""", + ) + + +def fill_stock_move_line_preset_reason_id(env): + openupgrade.logged_query( + env.cr, + """ + UPDATE stock_move_line sml + SET preset_reason_id = sm.preset_reason_id + FROM stock_move sm + WHERE sml.move_id = sm.id AND sm.preset_reason_id IS NOT NULL""", + ) + + +def fill_stock_move_line_reason(env): + openupgrade.logged_query( + env.cr, + """ + UPDATE stock_move_line sml + SET reason = COALESCE(sml.reason, sqr.name) + FROM stock_quant_reason sqr + WHERE sml.preset_reason_id = sqr.id""", + ) + + +@openupgrade.migrate() +def migrate(env, version): + fill_stock_quant_reason(env) + fill_stock_move_line_preset_reason_id(env) + fill_stock_move_line_reason(env) diff --git a/stock_change_qty_reason/migrations/15.0.1.0.0/pre-migration.py b/stock_change_qty_reason/migrations/15.0.1.0.0/pre-migration.py new file mode 100644 index 000000000000..91171fcbe483 --- /dev/null +++ b/stock_change_qty_reason/migrations/15.0.1.0.0/pre-migration.py @@ -0,0 +1,25 @@ +# Copyright 2023 ForgeFlow +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from openupgradelib import openupgrade + + +def fill_required_reason(env): + openupgrade.logged_query( + env.cr, + """ + UPDATE stock_quant_reason sqr + SET name = '???' + WHERE name IS NULL""", + ) + + +@openupgrade.migrate() +def migrate(env, version): + openupgrade.rename_tables( + env.cr, [("stock_inventory_line_reason", "stock_quant_reason")] + ) + openupgrade.rename_models( + env.cr, [("stock.inventory.line.reason", "stock.quant.reason")] + ) + fill_required_reason(env) diff --git a/stock_change_qty_reason/models/__init__.py b/stock_change_qty_reason/models/__init__.py index 0b357cdeccaa..3d3654457164 100644 --- a/stock_change_qty_reason/models/__init__.py +++ b/stock_change_qty_reason/models/__init__.py @@ -1,7 +1,6 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). from . import res_config_settings -from . import stock_inventory -from . import stock_inventory_line -from . import stock_inventory_line_reason -from . import stock_move +from . import stock_move_line +from . import stock_quant +from . import stock_quant_reason diff --git a/stock_change_qty_reason/models/res_config_settings.py b/stock_change_qty_reason/models/res_config_settings.py index ea82d0e30472..37986368e19b 100644 --- a/stock_change_qty_reason/models/res_config_settings.py +++ b/stock_change_qty_reason/models/res_config_settings.py @@ -1,4 +1,4 @@ -# Copyright 2019 ForgeFlow S.L. +# Copyright 2019-2023 ForgeFlow S.L. # License AGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). from odoo import fields, models diff --git a/stock_change_qty_reason/models/stock_inventory.py b/stock_change_qty_reason/models/stock_inventory.py deleted file mode 100644 index f755e28ab1f3..000000000000 --- a/stock_change_qty_reason/models/stock_inventory.py +++ /dev/null @@ -1,40 +0,0 @@ -# Copyright 2019 ForgeFlow S.L. -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -from odoo import api, fields, models - - -class StockInventory(models.Model): - _inherit = "stock.inventory" - - reason = fields.Char( - help="Type in a reason for the " "product quantity change", - states={"done": [("readonly", True)]}, - ) - preset_reason_id = fields.Many2one( - "stock.inventory.line.reason", states={"done": [("readonly", True)]} - ) - - def _get_inventory_lines_values(self): - vals = super(StockInventory, self)._get_inventory_lines_values() - for val in vals: - if self.preset_reason_id: - val["preset_reason_id"] = self.preset_reason_id.id - elif self.reason: - val["reason"] = self.reason - return vals - - @api.onchange("reason") - def onchange_reason(self): - line_ids = self.line_ids - if not isinstance(self.id, int): - line_ids = self.browse(self.id.origin).line_ids - for line in line_ids: - line.reason = self.reason - - @api.onchange("preset_reason_id") - def onchange_preset_reason(self): - line_ids = self.line_ids - if not isinstance(self.id, int): - line_ids = self.browse(self.id.origin).line_ids - for line in line_ids: - line.preset_reason_id = self.preset_reason_id diff --git a/stock_change_qty_reason/models/stock_inventory_line.py b/stock_change_qty_reason/models/stock_inventory_line.py deleted file mode 100644 index 5e5d9d63f7cf..000000000000 --- a/stock_change_qty_reason/models/stock_inventory_line.py +++ /dev/null @@ -1,29 +0,0 @@ -# Copyright 2016-2017 ACSONE SA/NV () -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). - -from odoo import fields, models - - -class StockInventoryLine(models.Model): - """Class to inherit model stock.inventory.line""" - - _inherit = "stock.inventory.line" - - reason = fields.Char(help="Type in a reason for the " "product quantity change") - preset_reason_id = fields.Many2one("stock.inventory.line.reason") - - def _get_move_values(self, qty, location_id, location_dest_id, out): - """Function to super _get_move_value""" - res = super(StockInventoryLine, self)._get_move_values( - qty, location_id, location_dest_id, out - ) - context = ( - self.reason if not self.preset_reason_id else self.preset_reason_id.name - ) - if res.get("origin"): - res["origin"] = " ,".join([res.get("origin"), context]) - else: - res["origin"] = context - if self.preset_reason_id: - res["preset_reason_id"] = self.preset_reason_id.id - return res diff --git a/stock_change_qty_reason/models/stock_move.py b/stock_change_qty_reason/models/stock_move.py deleted file mode 100644 index cb8bfcb1c10b..000000000000 --- a/stock_change_qty_reason/models/stock_move.py +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright 2019 ForgeFlow S.L. -# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). -from odoo import fields, models - - -class StockMove(models.Model): - _inherit = "stock.move" - - preset_reason_id = fields.Many2one("stock.inventory.line.reason", required=False) diff --git a/stock_change_qty_reason/models/stock_move_line.py b/stock_change_qty_reason/models/stock_move_line.py new file mode 100644 index 000000000000..46512121ac3b --- /dev/null +++ b/stock_change_qty_reason/models/stock_move_line.py @@ -0,0 +1,10 @@ +# Copyright 2019-2023 ForgeFlow S.L. +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). +from odoo import fields, models + + +class StockMoveLine(models.Model): + _inherit = "stock.move.line" + + preset_reason_id = fields.Many2one("stock.quant.reason") + reason = fields.Char(help="Type in a reason for the product quantity change") diff --git a/stock_change_qty_reason/models/stock_quant.py b/stock_change_qty_reason/models/stock_quant.py new file mode 100644 index 000000000000..7e5f0d78de3c --- /dev/null +++ b/stock_change_qty_reason/models/stock_quant.py @@ -0,0 +1,40 @@ +# Copyright 2016-2017 ACSONE SA/NV () +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import api, fields, models + + +class StockQuant(models.Model): + """Class to inherit model stock.quant""" + + _inherit = "stock.quant" + + reason = fields.Char(help="Type in a reason for the product quantity change") + preset_reason_id = fields.Many2one("stock.quant.reason") + + @api.model + def _get_inventory_fields_write(self): + res = super()._get_inventory_fields_write() + res.extend(["reason", "preset_reason_id"]) + return res + + def _get_inventory_move_values(self, qty, location_id, location_dest_id, out=False): + """Function to super _get_inventory_move_values""" + res = super()._get_inventory_move_values( + qty, location_id, location_dest_id, out + ) + context = ( + self.reason if not self.preset_reason_id else self.preset_reason_id.name + ) + line = res["move_line_ids"][0][2] + line["reason"] = context + if res.get("origin"): + res["origin"] = " ,".join([res.get("origin"), context]) + else: + res["origin"] = context + if self.preset_reason_id: + line["preset_reason_id"] = self.preset_reason_id.id + self.preset_reason_id = False + if self.reason: + self.reason = False + return res diff --git a/stock_change_qty_reason/models/stock_inventory_line_reason.py b/stock_change_qty_reason/models/stock_quant_reason.py similarity index 63% rename from stock_change_qty_reason/models/stock_inventory_line_reason.py rename to stock_change_qty_reason/models/stock_quant_reason.py index a41edc0cf311..0e94ba396039 100644 --- a/stock_change_qty_reason/models/stock_inventory_line_reason.py +++ b/stock_change_qty_reason/models/stock_quant_reason.py @@ -1,14 +1,13 @@ -# Copyright 2019 ForgeFlow S.L. +# Copyright 2019-2023 ForgeFlow S.L. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). from odoo import fields, models -class StockInventoryLineReason(models.Model): +class StockQuantReason(models.Model): + _name = "stock.quant.reason" + _description = "Stock Quant Reason" - _name = "stock.inventory.line.reason" - _description = "Stock Inventory Line Reason" - - name = fields.Char("Reason Name") + name = fields.Char("Reason Name", required=True) description = fields.Text("Reason Description") active = fields.Boolean(default=True) diff --git a/stock_change_qty_reason/security/ir.model.access.csv b/stock_change_qty_reason/security/ir.model.access.csv index 747b1302bdfc..7237d8a3eb21 100644 --- a/stock_change_qty_reason/security/ir.model.access.csv +++ b/stock_change_qty_reason/security/ir.model.access.csv @@ -1,3 +1,3 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink -access_stock_inventory_line_reason_user,stock.inventory.line.reason,model_stock_inventory_line_reason,stock.group_stock_user,1,0,0,0 -access_stock_inventory_line_reason_manager,stock.inventory.line.reason,model_stock_inventory_line_reason,stock.group_stock_manager,1,1,1,1 +access_stock_quant_reason_user,stock.quant.reason,model_stock_quant_reason,stock.group_stock_user,1,0,0,0 +access_stock_quant_reason_manager,stock.quant.reason,model_stock_quant_reason,stock.group_stock_manager,1,1,1,1 diff --git a/stock_change_qty_reason/tests/test_stock_change_qty_reason.py b/stock_change_qty_reason/tests/test_stock_change_qty_reason.py index e7e12d63d9e5..36b8919adf54 100644 --- a/stock_change_qty_reason/tests/test_stock_change_qty_reason.py +++ b/stock_change_qty_reason/tests/test_stock_change_qty_reason.py @@ -1,22 +1,22 @@ # pylint: disable=import-error,protected-access,too-few-public-methods # Copyright 2016-2017 ACSONE SA/NV () -# Copyright 2019 ForgeFlow S.L. +# Copyright 2019-2023 ForgeFlow S.L. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -from odoo.tests.common import SavepointCase +from odoo.tests.common import TransactionCase -class TestStockQuantityChangeReason(SavepointCase): +class TestStockQuantityChangeReason(TransactionCase): @classmethod def setUpClass(cls): super(TestStockQuantityChangeReason, cls).setUpClass() # MODELS - cls.stock_move = cls.env["stock.move"] + cls.stock_move_line = cls.env["stock.move.line"] cls.product_product_model = cls.env["product.product"] cls.product_category_model = cls.env["product.category"] - cls.wizard_model = cls.env["stock.change.product.qty"] - cls.preset_reason_id = cls.env["stock.inventory.line.reason"] + cls.stock_quant = cls.env["stock.quant"] + cls.preset_reason_id = cls.env["stock.quant.reason"] cls.stock_location = cls.env.ref("stock.stock_location_stock") # INSTANCES @@ -27,14 +27,13 @@ def _create_product(self, name): {"name": name, "categ_id": self.category.id, "type": "product"} ) - def _product_change_qty(self, product, new_qty): + def _product_change_qty(self, product, location, new_qty): values = { - "product_tmpl_id": product.product_tmpl_id.id, "product_id": product.id, - "new_quantity": new_qty, + "location_id": location.id, + "inventory_quantity": new_qty, } - wizard = self.wizard_model.create(values) - wizard.change_product_qty() + self.stock_quant.with_context(inventory_mode=True).create(values) def _create_reason(self, name, description=None): return self.preset_reason_id.create({"name": name, "description": description}) @@ -42,30 +41,23 @@ def _create_reason(self, name, description=None): def test_inventory_adjustment_onchange_reason_preset_reason(self): """Check that adding a reason or a preset reason explode to lines""" product2 = self._create_product("product_product_2") - self._product_change_qty(product2, 50) - inventory = self.env["stock.inventory"].create( + self._product_change_qty(product2, self.stock_location, 50) + inventory_quant = self.env["stock.quant"].create( { - "name": "remove product2", - "product_ids": [(4, product2.id)], - "location_ids": [(4, self.stock_location.id)], + "product_id": product2.id, + "location_id": self.stock_location.id, + "inventory_quantity": 10, } ) - inventory.preset_reason_id = self._create_reason("Test 1", "Description Test 1") - inventory.action_start() - self.assertEqual(len(inventory.line_ids), 1) - inventory.reason = "Reason 2" - inventory.onchange_reason() - self.assertEqual(inventory.line_ids.reason, inventory.reason) - inventory.preset_reason_id = self._create_reason("Test 2", "Description Test 2") - inventory.onchange_preset_reason() - self.assertEqual( - inventory.line_ids.preset_reason_id, inventory.preset_reason_id - ) - inventory.line_ids[0].write({"product_qty": 10}) - inventory.action_validate() - move = self.stock_move.search( + inventory_quant.user_id = self.env.user.id + inventory_quant.inventory_quantity_set = True + preset_reason_id = self._create_reason("Test 1", "Description Test 1") + inventory_quant.preset_reason_id = preset_reason_id + inventory_quant.action_apply_inventory() + move_line = self.stock_move_line.search( [("product_id", "=", product2.id), ("preset_reason_id", "!=", False)] ) - self.assertEqual(len(move), 1) - self.assertEqual(move.origin, inventory.preset_reason_id.name) - self.assertEqual(move.preset_reason_id, inventory.preset_reason_id) + self.assertEqual(len(move_line), 1) + self.assertEqual(inventory_quant.preset_reason_id.name, False) + self.assertEqual(move_line.move_id.origin, preset_reason_id.name) + self.assertEqual(move_line.preset_reason_id, preset_reason_id) diff --git a/stock_change_qty_reason/views/base_config_view.xml b/stock_change_qty_reason/views/base_config_view.xml index 8b388e3ba201..68b7a1778d72 100644 --- a/stock_change_qty_reason/views/base_config_view.xml +++ b/stock_change_qty_reason/views/base_config_view.xml @@ -1,5 +1,5 @@ - diff --git a/stock_change_qty_reason/views/stock_inventory_line_view.xml b/stock_change_qty_reason/views/stock_inventory_line_view.xml deleted file mode 100644 index a189eea7fef4..000000000000 --- a/stock_change_qty_reason/views/stock_inventory_line_view.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - stock.inventory.line.tree - stock.inventory.line - - - - - - - - - stock.inventory.line.tree.reason.code - stock.inventory.line - - 99 - - - - - - - - diff --git a/stock_change_qty_reason/views/stock_inventory_view.xml b/stock_change_qty_reason/views/stock_move_line_view.xml similarity index 50% rename from stock_change_qty_reason/views/stock_inventory_view.xml rename to stock_change_qty_reason/views/stock_move_line_view.xml index 41c4581f1b24..668d3c365395 100644 --- a/stock_change_qty_reason/views/stock_inventory_view.xml +++ b/stock_change_qty_reason/views/stock_move_line_view.xml @@ -1,21 +1,21 @@ - - - stock.inventory.reason.form.inherit - stock.inventory - + + stock.move.line.tree + stock.move.line + - - stock.inventory.reason.form.inherit.code - stock.inventory - + + stock.move.line.tree + stock.move.line + 99 - + diff --git a/stock_change_qty_reason/views/stock_inventory_line_reason_view.xml b/stock_change_qty_reason/views/stock_quant_reason_view.xml similarity index 92% rename from stock_change_qty_reason/views/stock_inventory_line_reason_view.xml rename to stock_change_qty_reason/views/stock_quant_reason_view.xml index 5922eadb188d..85f8a37258ad 100644 --- a/stock_change_qty_reason/views/stock_inventory_line_reason_view.xml +++ b/stock_change_qty_reason/views/stock_quant_reason_view.xml @@ -1,10 +1,10 @@ - Preset Reason - stock.inventory.line.reason + stock.quant.reason
@@ -34,7 +34,7 @@ Change Qty Reasons - stock.inventory.line.reason + stock.quant.reason ir.actions.act_window list,form diff --git a/stock_change_qty_reason/views/stock_quant_view.xml b/stock_change_qty_reason/views/stock_quant_view.xml new file mode 100644 index 000000000000..629635f20a70 --- /dev/null +++ b/stock_change_qty_reason/views/stock_quant_view.xml @@ -0,0 +1,36 @@ + + + + + stock.quant.tree + stock.quant + + + + + + + stock.quant.tree.reason.code + stock.quant + + 99 + + + + + + + +