mirror of
https://github.com/OCA/stock-logistics-warehouse.git
synced 2025-01-21 14:27:28 +02:00
[MIG] stock_inventory_discrepancy: Migration to 13.0
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
|
||||
|
||||
from . import models
|
||||
from .hooks import post_load_hook
|
||||
|
||||
@@ -5,18 +5,20 @@
|
||||
"summary": "Adds the capability to show the discrepancy of every line in "
|
||||
"an inventory and to block the inventory validation when the "
|
||||
"discrepancy is over a user defined threshold.",
|
||||
"version": "12.0.1.0.0",
|
||||
"version": "13.0.1.0.0",
|
||||
"author": "ForgeFlow, Odoo Community Association (OCA)",
|
||||
"website": "https://github.com/OCA/stock-logistics-warehouse",
|
||||
"category": "Warehouse Management",
|
||||
"category": "Warehouse",
|
||||
"depends": ["stock"],
|
||||
"data": [
|
||||
"security/stock_inventory_discrepancy_security.xml",
|
||||
"views/assets_backend.xml",
|
||||
"views/stock_inventory_view.xml",
|
||||
"views/stock_warehouse_view.xml",
|
||||
"views/stock_location_view.xml",
|
||||
],
|
||||
"license": "AGPL-3",
|
||||
"post_load": "post_load_hook",
|
||||
"installable": True,
|
||||
"application": False,
|
||||
}
|
||||
|
||||
79
stock_inventory_discrepancy/hooks.py
Normal file
79
stock_inventory_discrepancy/hooks.py
Normal file
@@ -0,0 +1,79 @@
|
||||
# Copyright 2019 Eficent Business and IT Consulting Services S.L.
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
|
||||
|
||||
|
||||
from odoo import _
|
||||
from odoo.exceptions import UserError
|
||||
from odoo.tools.float_utils import float_compare
|
||||
|
||||
from odoo.addons.stock.models.stock_inventory import Inventory
|
||||
|
||||
|
||||
def post_load_hook():
|
||||
def action_validate_discrepancy(self):
|
||||
"""Override method to avoid inline group validation"""
|
||||
if not self.exists():
|
||||
return
|
||||
self.ensure_one()
|
||||
# START HOOK: - Allow specific group to validate inventory
|
||||
# - Allow validate on pending status
|
||||
if (
|
||||
not self.user_has_groups("stock.group_stock_manager")
|
||||
and not self.user_has_groups(
|
||||
"stock_inventory_discrepancy.group_stock_inventory_validation"
|
||||
)
|
||||
and not self.user_has_groups(
|
||||
"stock_inventory_discrepancy.group_stock_inventory_validation_always"
|
||||
)
|
||||
):
|
||||
raise UserError(
|
||||
_("Only a stock manager can validate an inventory adjustment.")
|
||||
)
|
||||
if self.state not in ["confirm", "pending"]:
|
||||
raise UserError(
|
||||
_(
|
||||
"You can't validate the inventory '%s', maybe this inventory "
|
||||
+ "has been already validated or isn't ready."
|
||||
)
|
||||
% (self.name)
|
||||
)
|
||||
# END HOOK
|
||||
inventory_lines = self.line_ids.filtered(
|
||||
lambda l: l.product_id.tracking in ["lot", "serial"]
|
||||
and not l.prod_lot_id
|
||||
and l.theoretical_qty != l.product_qty
|
||||
)
|
||||
lines = self.line_ids.filtered(
|
||||
lambda l: float_compare(
|
||||
l.product_qty, 1, precision_rounding=l.product_uom_id.rounding
|
||||
)
|
||||
> 0
|
||||
and l.product_id.tracking == "serial"
|
||||
and l.prod_lot_id
|
||||
)
|
||||
if inventory_lines and not lines:
|
||||
wiz_lines = [
|
||||
(0, 0, {"product_id": product.id, "tracking": product.tracking})
|
||||
for product in inventory_lines.mapped("product_id")
|
||||
]
|
||||
wiz = self.env["stock.track.confirmation"].create(
|
||||
{"inventory_id": self.id, "tracking_line_ids": wiz_lines}
|
||||
)
|
||||
return {
|
||||
"name": _("Tracked Products in Inventory Adjustment"),
|
||||
"type": "ir.actions.act_window",
|
||||
"view_mode": "form",
|
||||
"views": [(False, "form")],
|
||||
"res_model": "stock.track.confirmation",
|
||||
"target": "new",
|
||||
"res_id": wiz.id,
|
||||
}
|
||||
self._action_done()
|
||||
self.line_ids._check_company()
|
||||
self._check_company()
|
||||
return True
|
||||
|
||||
if not hasattr(Inventory, "action_validate_original"):
|
||||
Inventory.action_validate_original = Inventory.action_validate
|
||||
|
||||
Inventory._patch_method("action_validate", action_validate_discrepancy)
|
||||
@@ -1,5 +1,5 @@
|
||||
# Copyright 2017-2020 ForgeFlow S.L.
|
||||
# (http://www.eficent.com)
|
||||
# (http://www.forgeflow.com)
|
||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
|
||||
|
||||
from odoo import _, api, fields, models
|
||||
@@ -9,16 +9,8 @@ from odoo.exceptions import UserError
|
||||
class StockInventory(models.Model):
|
||||
_inherit = "stock.inventory"
|
||||
|
||||
INVENTORY_STATE_SELECTION = [
|
||||
("draft", "Draft"),
|
||||
("cancel", "Cancelled"),
|
||||
("confirm", "In Progress"),
|
||||
("pending", "Pending to Approve"),
|
||||
("done", "Validated"),
|
||||
]
|
||||
|
||||
state = fields.Selection(
|
||||
selection=INVENTORY_STATE_SELECTION,
|
||||
selection_add=[("pending", "Pending to Approve"), ("done",)],
|
||||
string="Status",
|
||||
readonly=True,
|
||||
index=True,
|
||||
@@ -37,7 +29,6 @@ class StockInventory(models.Model):
|
||||
store=True,
|
||||
)
|
||||
|
||||
@api.multi
|
||||
@api.depends("line_ids.product_qty", "line_ids.theoretical_qty")
|
||||
def _compute_over_discrepancy_line_count(self):
|
||||
for inventory in self:
|
||||
@@ -46,13 +37,12 @@ class StockInventory(models.Model):
|
||||
)
|
||||
inventory.over_discrepancy_line_count = len(lines)
|
||||
|
||||
@api.multi
|
||||
def action_over_discrepancies(self):
|
||||
self.write({"state": "pending"})
|
||||
|
||||
def _check_group_inventory_validation_always(self):
|
||||
grp_inv_val = self.env.ref(
|
||||
"stock_inventory_discrepancy.group_" "stock_inventory_validation_always"
|
||||
"stock_inventory_discrepancy.group_stock_inventory_validation_always"
|
||||
)
|
||||
if grp_inv_val in self.env.user.groups_id:
|
||||
return True
|
||||
@@ -70,13 +60,17 @@ class StockInventory(models.Model):
|
||||
if inventory.over_discrepancy_line_count and inventory.line_ids.filtered(
|
||||
lambda t: t.discrepancy_threshold > 0.0
|
||||
):
|
||||
if inventory.env.context.get("normal_view", False):
|
||||
if self.user_has_groups(
|
||||
"stock_inventory_discrepancy.group_stock_inventory_validation"
|
||||
) and not self.user_has_groups(
|
||||
"stock_inventory_discrepancy."
|
||||
"group_stock_inventory_validation_always"
|
||||
):
|
||||
inventory.action_over_discrepancies()
|
||||
return True
|
||||
else:
|
||||
inventory._check_group_inventory_validation_always()
|
||||
return super(StockInventory, self)._action_done()
|
||||
|
||||
@api.multi
|
||||
def action_force_done(self):
|
||||
return super(StockInventory, self)._action_done()
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
# Copyright 2017-2020 ForgeFlow S.L.
|
||||
# (http://www.eficent.com)
|
||||
# (http://www.forgeflow.com)
|
||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
|
||||
|
||||
from odoo import api, fields, models
|
||||
|
||||
from odoo.addons import decimal_precision as dp
|
||||
|
||||
|
||||
class StockInventoryLine(models.Model):
|
||||
_inherit = "stock.inventory.line"
|
||||
@@ -15,7 +13,7 @@ class StockInventoryLine(models.Model):
|
||||
compute="_compute_discrepancy",
|
||||
help="The difference between the actual qty counted and the "
|
||||
"theoretical quantity on hand.",
|
||||
digits=dp.get_precision("Product Unit of Measure"),
|
||||
digits="Product Unit of Measure",
|
||||
default=0,
|
||||
)
|
||||
discrepancy_percent = fields.Float(
|
||||
@@ -32,7 +30,6 @@ class StockInventoryLine(models.Model):
|
||||
compute="_compute_discrepancy_threshold",
|
||||
)
|
||||
|
||||
@api.multi
|
||||
@api.depends("theoretical_qty", "product_qty")
|
||||
def _compute_discrepancy(self):
|
||||
for line in self:
|
||||
@@ -43,8 +40,9 @@ class StockInventoryLine(models.Model):
|
||||
)
|
||||
elif not line.theoretical_qty and line.product_qty:
|
||||
line.discrepancy_percent = 100.0
|
||||
else:
|
||||
line.discrepancy_percent = 0.0
|
||||
|
||||
@api.multi
|
||||
def _compute_discrepancy_threshold(self):
|
||||
for line in self:
|
||||
whs = line.location_id.get_warehouse()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Copyright 2017-2020 ForgeFlow S.L.
|
||||
# (http://www.eficent.com)
|
||||
# (http://www.forgeflow.com)
|
||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
|
||||
|
||||
from odoo import fields, models
|
||||
@@ -15,3 +15,22 @@ class StockLocation(models.Model):
|
||||
"an Inventory Adjustment. Thresholds defined in Locations have "
|
||||
"preference over Warehouse's ones.",
|
||||
)
|
||||
propagate_discrepancy_threshold = fields.Boolean(
|
||||
string="Propagate discrepancy threshold",
|
||||
help="Propagate Maximum Discrepancy Rate Threshold to child locations",
|
||||
)
|
||||
|
||||
def write(self, values):
|
||||
res = super().write(values)
|
||||
# Set the discrepancy threshold for all child locations
|
||||
if values.get("discrepancy_threshold", False):
|
||||
for location in self.filtered(
|
||||
lambda loc: loc.propagate_discrepancy_threshold and loc.child_ids
|
||||
):
|
||||
location.child_ids.write(
|
||||
{
|
||||
"discrepancy_threshold": values["discrepancy_threshold"],
|
||||
"propagate_discrepancy_threshold": True,
|
||||
}
|
||||
)
|
||||
return res
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Copyright 2017-2020 ForgeFlow S.L.
|
||||
# (http://www.eficent.com)
|
||||
# (http://www.forgeflow.com)
|
||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
|
||||
|
||||
from odoo import fields, models
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
* Lois Rilo <lois.rilo@forgeflow.com>
|
||||
* Andreas Dian Sukarno Putro <andreasdian777@gmail.com>
|
||||
* Bhavesh Odedra <bodedra@opensourceintegrators.com>
|
||||
* Héctor Villarreal <hector.villarreal@forgeflow.com>
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
odoo.define('stock_inventory_discrepancy.InventoryValidationController', function (require) {
|
||||
"use strict";
|
||||
|
||||
var core = require('web.core');
|
||||
var InventoryValidationController = require('stock.InventoryValidationController');
|
||||
|
||||
var _t = core._t;
|
||||
|
||||
InventoryValidationController.include({
|
||||
|
||||
/**
|
||||
* @override
|
||||
* @see displayNotification
|
||||
*/
|
||||
do_notify: function (title, message, sticky, className) {
|
||||
var self = this;
|
||||
if (this.modelName === "stock.inventory.line") {
|
||||
this._rpc({
|
||||
model: 'stock.inventory',
|
||||
method: 'read',
|
||||
args: [this.inventory_id, ['state']],
|
||||
}).then(function (res) {
|
||||
if (res[0].state === "pending") {
|
||||
title = _t("Pending to Approve");
|
||||
message = _t("The inventory needs to be approved");
|
||||
}
|
||||
}).finally(function () {
|
||||
return self.displayNotification({
|
||||
type: 'warning',
|
||||
title: title,
|
||||
message: message,
|
||||
sticky: sticky,
|
||||
className: className,
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
});
|
||||
@@ -1,5 +1,5 @@
|
||||
# Copyright 2017-2020 ForgeFlow S.L.
|
||||
# (http://www.eficent.com)
|
||||
# (http://www.forgeflow.com)
|
||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
|
||||
|
||||
from odoo.exceptions import UserError
|
||||
@@ -14,7 +14,6 @@ class TestInventoryDiscrepancy(TransactionCase):
|
||||
self.obj_inventory = self.env["stock.inventory"]
|
||||
self.obj_product = self.env["product.product"]
|
||||
self.obj_warehouse = self.env["stock.warehouse"]
|
||||
self.obj_upd_qty_wizard = self.env["stock.change.product.qty"]
|
||||
|
||||
self.product1 = self.obj_product.create(
|
||||
{"name": "Test Product 1", "type": "product", "default_code": "PROD1"}
|
||||
@@ -33,8 +32,10 @@ class TestInventoryDiscrepancy(TransactionCase):
|
||||
# Create Stock manager able to force validation on inventories.
|
||||
group_stock_man = self.env.ref("stock.group_stock_manager")
|
||||
group_inventory_all = self.env.ref(
|
||||
"stock_inventory_discrepancy." "group_stock_inventory_validation_always"
|
||||
"stock_inventory_discrepancy.group_stock_inventory_validation_always"
|
||||
)
|
||||
group_employee = self.env.ref("base.group_user")
|
||||
|
||||
self.manager = self.env["res.users"].create(
|
||||
{
|
||||
"name": "Test Manager",
|
||||
@@ -53,10 +54,27 @@ class TestInventoryDiscrepancy(TransactionCase):
|
||||
}
|
||||
)
|
||||
|
||||
self.user_2 = self.env["res.users"].create(
|
||||
{
|
||||
"name": "Test User 2",
|
||||
"login": "user_2",
|
||||
"email": "test2.user@example.com",
|
||||
"groups_id": [(6, 0, [group_stock_user.id, group_inventory_all.id])],
|
||||
}
|
||||
)
|
||||
|
||||
self.no_user = self.env["res.users"].create(
|
||||
{
|
||||
"name": "No User",
|
||||
"login": "no_user",
|
||||
"email": "test.no_user@example.com",
|
||||
"groups_id": [(6, 0, [group_employee.id])],
|
||||
}
|
||||
)
|
||||
|
||||
starting_inv = self.obj_inventory.create(
|
||||
{
|
||||
"name": "Starting inventory",
|
||||
"filter": "product",
|
||||
"line_ids": [
|
||||
(
|
||||
0,
|
||||
@@ -89,8 +107,7 @@ class TestInventoryDiscrepancy(TransactionCase):
|
||||
inventory = self.obj_inventory.create(
|
||||
{
|
||||
"name": "Test Discrepancy Computation",
|
||||
"location_id": self.test_loc.id,
|
||||
"filter": "none",
|
||||
"location_ids": [(4, self.test_loc.id)],
|
||||
"line_ids": [
|
||||
(
|
||||
0,
|
||||
@@ -131,8 +148,7 @@ class TestInventoryDiscrepancy(TransactionCase):
|
||||
inventory = self.obj_inventory.create(
|
||||
{
|
||||
"name": "Test Forcing Validation Method",
|
||||
"location_id": self.test_loc.id,
|
||||
"filter": "none",
|
||||
"location_ids": [(4, self.test_loc.id)],
|
||||
"line_ids": [
|
||||
(
|
||||
0,
|
||||
@@ -155,7 +171,8 @@ class TestInventoryDiscrepancy(TransactionCase):
|
||||
0.1,
|
||||
"Threshold wrongly computed in Inventory Line.",
|
||||
)
|
||||
inventory.with_context({"normal_view": True}).action_validate()
|
||||
inventory.with_user(self.user).action_start()
|
||||
inventory.with_user(self.user).action_validate()
|
||||
self.assertEqual(
|
||||
inventory.over_discrepancy_line_count,
|
||||
1,
|
||||
@@ -166,7 +183,7 @@ class TestInventoryDiscrepancy(TransactionCase):
|
||||
"pending",
|
||||
"Inventory Adjustment not changing to Pending to " "Approve.",
|
||||
)
|
||||
inventory.sudo(self.manager).action_force_done()
|
||||
inventory.with_user(self.manager).action_force_done()
|
||||
self.assertEqual(
|
||||
inventory.state,
|
||||
"done",
|
||||
@@ -174,13 +191,56 @@ class TestInventoryDiscrepancy(TransactionCase):
|
||||
"not working properly.",
|
||||
)
|
||||
|
||||
def test_discrepancy_validation_always(self):
|
||||
"""Tests the new workflow"""
|
||||
inventory = self.obj_inventory.create(
|
||||
{
|
||||
"name": "Test Forcing Validation Method",
|
||||
"location_ids": [(4, self.test_loc.id)],
|
||||
"line_ids": [
|
||||
(
|
||||
0,
|
||||
0,
|
||||
{
|
||||
"product_id": self.product1.id,
|
||||
"product_uom_id": self.env.ref("uom.product_uom_unit").id,
|
||||
"product_qty": 3.0,
|
||||
"location_id": self.test_loc.id,
|
||||
},
|
||||
)
|
||||
],
|
||||
}
|
||||
)
|
||||
self.assertEqual(
|
||||
inventory.state, "draft", "Testing Inventory wrongly configurated"
|
||||
)
|
||||
self.assertEqual(
|
||||
inventory.line_ids.discrepancy_threshold,
|
||||
0.1,
|
||||
"Threshold wrongly computed in Inventory Line.",
|
||||
)
|
||||
inventory.with_user(self.user_2).action_start()
|
||||
# User with no privileges can't validate a Inventory Adjustment.
|
||||
with self.assertRaises(UserError):
|
||||
inventory.with_user(self.no_user).action_validate()
|
||||
inventory.with_user(self.user_2).action_validate()
|
||||
self.assertEqual(
|
||||
inventory.over_discrepancy_line_count,
|
||||
1,
|
||||
"Computation of over-discrepancies failed.",
|
||||
)
|
||||
self.assertEqual(
|
||||
inventory.state,
|
||||
"done",
|
||||
"Stock Managers belongs to group Validate All inventory Adjustments",
|
||||
)
|
||||
|
||||
def test_warehouse_threshold(self):
|
||||
"""Tests the behaviour if the threshold is set on the WH."""
|
||||
inventory = self.obj_inventory.create(
|
||||
{
|
||||
"name": "Test Threshold Defined in WH",
|
||||
"location_id": self.test_wh.view_location_id.id,
|
||||
"filter": "none",
|
||||
"location_ids": [(4, self.test_wh.view_location_id.id)],
|
||||
"line_ids": [
|
||||
(
|
||||
0,
|
||||
@@ -201,17 +261,23 @@ class TestInventoryDiscrepancy(TransactionCase):
|
||||
"Threshold wrongly computed in Inventory Line.",
|
||||
)
|
||||
|
||||
def test_update_qty_user_error(self):
|
||||
"""Test if a user error raises when a stock user tries to update the
|
||||
qty for a product and the correction is a discrepancy over the
|
||||
threshold."""
|
||||
upd_qty = self.obj_upd_qty_wizard.sudo(self.user).create(
|
||||
def test_propagate_discrepancy_threshold(self):
|
||||
view_test_loc = self.obj_location.create(
|
||||
{"name": "Test Location", "usage": "view", "discrepancy_threshold": 0.1}
|
||||
)
|
||||
child_test_loc = self.obj_location.create(
|
||||
{
|
||||
"product_id": self.product1.id,
|
||||
"product_tmpl_id": self.product1.product_tmpl_id.id,
|
||||
"new_quantity": 10.0,
|
||||
"location_id": self.test_loc.id,
|
||||
"name": "Child Test Location",
|
||||
"usage": "internal",
|
||||
"discrepancy_threshold": 0.2,
|
||||
"location_id": view_test_loc.id,
|
||||
}
|
||||
)
|
||||
with self.assertRaises(UserError):
|
||||
upd_qty.change_product_qty()
|
||||
view_test_loc.write(
|
||||
{"discrepancy_threshold": 0.3, "propagate_discrepancy_threshold": True}
|
||||
)
|
||||
self.assertEqual(
|
||||
child_test_loc.discrepancy_threshold,
|
||||
0.3,
|
||||
"Threshold Discrepancy wrongly propagated",
|
||||
)
|
||||
|
||||
10
stock_inventory_discrepancy/views/assets_backend.xml
Normal file
10
stock_inventory_discrepancy/views/assets_backend.xml
Normal file
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<template id="stock_assets_backend" name="stock_inventory assets" inherit_id="web.assets_backend">
|
||||
<xpath expr="." position="inside">
|
||||
<script type="text/javascript" src="/stock_inventory_discrepancy/static/src/js/inventory_validate_button_controller.js"></script>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
</odoo>
|
||||
@@ -20,7 +20,6 @@
|
||||
<xpath expr="//button[@name='action_validate']"
|
||||
position="attributes">
|
||||
<attribute name="groups">stock_inventory_discrepancy.group_stock_inventory_validation</attribute>
|
||||
<attribute name="context">{'normal_view': True}</attribute>
|
||||
</xpath>
|
||||
<xpath expr="//button[@name='action_validate']"
|
||||
position="after">
|
||||
@@ -30,19 +29,31 @@
|
||||
groups="stock_inventory_discrepancy.group_stock_inventory_validation_always"
|
||||
attrs="{'invisible': ['|',('state', '!=', 'pending'),('over_discrepancy_line_count', '=', 0)]}"/>
|
||||
</xpath>
|
||||
<field name="date" position="after">
|
||||
<xpath expr="//button[@name='action_open_inventory_lines']" position="attributes">
|
||||
<attribute name="states">pending,confirm</attribute>
|
||||
</xpath>
|
||||
<xpath expr="//button[@name='action_cancel_draft'][2]" position="attributes">
|
||||
<attribute name="states">pending,confirm</attribute>
|
||||
</xpath>
|
||||
<field name="company_id" position="before">
|
||||
<field name="over_discrepancy_line_count" attrs="{'invisible': [('state', '!=', 'pending')]}"/>
|
||||
</field>
|
||||
<xpath expr="//field[@name='line_ids']/tree/field[@name='product_qty']"
|
||||
position="after">
|
||||
<field name="discrepancy_qty"/>
|
||||
<field name="discrepancy_percent"/>
|
||||
<field name="discrepancy_threshold"/>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='line_ids']/tree" position="attributes">
|
||||
<attribute name="decoration-danger">theoretical_qty < 0 or discrepancy_percent > discrepancy_threshold</attribute>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="stock_inventory_line_tree2" model="ir.ui.view">
|
||||
<field name="name">stock.inventory.line.tree2</field>
|
||||
<field name="model">stock.inventory.line</field>
|
||||
<field name="inherit_id" ref="stock.stock_inventory_line_tree2"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="product_qty" position="after">
|
||||
<field name="discrepancy_qty"/>
|
||||
<field name="discrepancy_percent"/>
|
||||
<field name="discrepancy_threshold"/>
|
||||
</field>
|
||||
<xpath expr="//tree" position="attributes">
|
||||
<attribute name="decoration-danger">theoretical_qty < 0 or discrepancy_percent > discrepancy_threshold or "product_qty != theoretical_qty"</attribute>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
</odoo>
|
||||
|
||||
@@ -9,11 +9,12 @@
|
||||
<field name="model">stock.location</field>
|
||||
<field name="inherit_id" ref="stock.view_location_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="partner_id" position="after">
|
||||
<field name="return_location" position="after">
|
||||
<label for="discrepancy_threshold"/>
|
||||
<div>
|
||||
<field name="discrepancy_threshold" class="oe_inline"/> %
|
||||
</div>
|
||||
<field name="propagate_discrepancy_threshold"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
<odoo>
|
||||
|
||||
<record id="view_warehouse_form" model="ir.ui.view">
|
||||
<record id="view_warehouse" model="ir.ui.view">
|
||||
<field name="name">Warehouse form - Inventory Discrepancy
|
||||
extension</field>
|
||||
<field name="model">stock.warehouse</field>
|
||||
|
||||
Reference in New Issue
Block a user