[MIG] stock_change_qty_reason: Migration to 15.0

This commit is contained in:
Miquel Raïch
2023-01-12 18:38:00 +01:00
committed by JasminSForgeFlow
parent fd7775741a
commit e65dee6bad
18 changed files with 220 additions and 171 deletions

View File

@@ -1,5 +1,5 @@
# Copyright 2016-2017 ACSONE SA/NV (<http://acsone.eu>)
# 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,
}

View File

@@ -0,0 +1,54 @@
# Copyright 2023 ForgeFlow <http://www.forgeflow.com>
# 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)

View File

@@ -0,0 +1,25 @@
# Copyright 2023 ForgeFlow <http://www.forgeflow.com>
# 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)

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -1,29 +0,0 @@
# Copyright 2016-2017 ACSONE SA/NV (<http://acsone.eu>)
# 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

View File

@@ -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)

View File

@@ -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")

View File

@@ -0,0 +1,40 @@
# Copyright 2016-2017 ACSONE SA/NV (<http://acsone.eu>)
# 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

View File

@@ -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)

View File

@@ -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
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_stock_inventory_line_reason_user access_stock_quant_reason_user stock.inventory.line.reason stock.quant.reason model_stock_inventory_line_reason model_stock_quant_reason stock.group_stock_user 1 0 0 0
3 access_stock_inventory_line_reason_manager access_stock_quant_reason_manager stock.inventory.line.reason stock.quant.reason model_stock_inventory_line_reason model_stock_quant_reason stock.group_stock_manager 1 1 1 1

View File

@@ -1,22 +1,22 @@
# pylint: disable=import-error,protected-access,too-few-public-methods
# Copyright 2016-2017 ACSONE SA/NV (<http://acsone.eu>)
# 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 @@ class TestStockQuantityChangeReason(SavepointCase):
{"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 @@ class TestStockQuantityChangeReason(SavepointCase):
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)

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- Copyright 2019 ForgeFlow S.L.
<!-- Copyright 2019-2023 ForgeFlow S.L.
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -->
<odoo>
<record id="qty_reason_preset_selection" model="ir.ui.view">

View File

@@ -1,28 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<record id="reason_stock_inventory_line_tree" model="ir.ui.view">
<field name="name">stock.inventory.line.tree</field>
<field name="model">stock.inventory.line</field>
<field name="inherit_id" ref="stock.stock_inventory_line_tree" />
<field name="arch" type="xml">
<field name="location_id" position="before">
<field name="reason" />
</field>
</field>
</record>
<record id="reason_stock_inventory_line_tree_reason_id" model="ir.ui.view">
<field name="name">stock.inventory.line.tree.reason.code</field>
<field name="model">stock.inventory.line</field>
<field name="inherit_id" ref="reason_stock_inventory_line_tree" />
<field name="priority">99</field>
<field
name="groups_id"
eval="[(4, ref('stock_change_qty_reason.group_qty_reason_preset'))]"
/>
<field name="arch" type="xml">
<field name="reason" position="replace">
<field name="preset_reason_id" />
</field>
</field>
</record>
</odoo>

View File

@@ -1,21 +1,21 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- Copyright 2019 ForgeFlow S.L.
<!-- Copyright 2019-2023 ForgeFlow S.L.
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -->
<odoo>
<record id="reason_stock_inventory_form_inherit" model="ir.ui.view">
<field name="name">stock.inventory.reason.form.inherit</field>
<field name="model">stock.inventory</field>
<field name="inherit_id" ref="stock.view_inventory_form" />
<record id="reason_view_move_line_tree" model="ir.ui.view">
<field name="name">stock.move.line.tree</field>
<field name="model">stock.move.line</field>
<field name="inherit_id" ref="stock.view_move_line_tree" />
<field name="arch" type="xml">
<field name="company_id" position="after">
<field name="reason" />
</field>
</field>
</record>
<record id="preset_reason_stock_inventory_form_inherit" model="ir.ui.view">
<field name="name">stock.inventory.reason.form.inherit.code</field>
<field name="model">stock.inventory</field>
<field name="inherit_id" ref="reason_stock_inventory_form_inherit" />
<record id="preset_reason_view_move_line_tree" model="ir.ui.view">
<field name="name">stock.move.line.tree</field>
<field name="model">stock.move.line</field>
<field name="inherit_id" ref="reason_view_move_line_tree" />
<field name="priority">99</field>
<field
name="groups_id"
@@ -23,7 +23,7 @@
/>
<field name="arch" type="xml">
<field name="reason" position="replace">
<field name="preset_reason_id" />
<field name="preset_reason_id" string="Reason" />
</field>
</field>
</record>

View File

@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- Copyright 2019 ForgeFlow S.L.
<!-- Copyright 2019-2023 ForgeFlow S.L.
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -->
<odoo>
<record id="view_preset_reason" model="ir.ui.view">
<field name="name">Preset Reason</field>
<field name="model">stock.inventory.line.reason</field>
<field name="model">stock.quant.reason</field>
<field name="arch" type="xml">
<form string="Preset Reason">
<header>
@@ -34,7 +34,7 @@
</record>
<record id="action_change_qty_reasons_list" model="ir.actions.act_window">
<field name="name">Change Qty Reasons</field>
<field name="res_model">stock.inventory.line.reason</field>
<field name="res_model">stock.quant.reason</field>
<field name="type">ir.actions.act_window</field>
<field name="view_mode">list,form</field>
</record>

View File

@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- Copyright 2019-2023 ForgeFlow S.L.
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -->
<odoo>
<record id="reason_view_stock_quant_tree_inventory_editable" model="ir.ui.view">
<field name="name">stock.quant.tree</field>
<field name="model">stock.quant</field>
<field name="inherit_id" ref="stock.view_stock_quant_tree_inventory_editable" />
<field name="arch" type="xml">
<button name="action_inventory_history" position="before">
<field
name="reason"
attrs="{'invisible': [('inventory_quantity_set', '=', False)]}"
/>
</button>
</field>
</record>
<record id="reason_stock_inventory_line_tree_reason_id" model="ir.ui.view">
<field name="name">stock.quant.tree.reason.code</field>
<field name="model">stock.quant</field>
<field
name="inherit_id"
ref="reason_view_stock_quant_tree_inventory_editable"
/>
<field name="priority">99</field>
<field
name="groups_id"
eval="[(4, ref('stock_change_qty_reason.group_qty_reason_preset'))]"
/>
<field name="arch" type="xml">
<field name="reason" position="replace">
<field name="preset_reason_id" string="Reason" />
</field>
</field>
</record>
</odoo>