mirror of
https://github.com/OCA/stock-logistics-warehouse.git
synced 2025-01-21 14:27:28 +02:00
[IMP] stock_inventory_preparation_filter: black, isort
This commit is contained in:
committed by
Ivàn Todorovich
parent
c25ab2d58f
commit
29a598a5db
@@ -1,2 +1 @@
|
||||
|
||||
from . import models
|
||||
|
||||
@@ -6,19 +6,12 @@
|
||||
{
|
||||
"name": "Extended Inventory Preparation Filters",
|
||||
"version": "12.0.1.1.0",
|
||||
"depends": [
|
||||
"stock",
|
||||
],
|
||||
"author": "AvanzOSC,"
|
||||
"Tecnativa,"
|
||||
"Odoo Community Association (OCA)",
|
||||
"depends": ["stock"],
|
||||
"author": "AvanzOSC," "Tecnativa," "Odoo Community Association (OCA)",
|
||||
"category": "Inventory, Logistic, Storage",
|
||||
"website": "http://github.com/OCA/stock-logistics-warehouse",
|
||||
"summary": "More filters for inventory adjustments",
|
||||
"data": [
|
||||
"views/stock_inventory_view.xml",
|
||||
"security/ir.model.access.csv",
|
||||
],
|
||||
'installable': True,
|
||||
"license": 'AGPL-3',
|
||||
"data": ["views/stock_inventory_view.xml", "security/ir.model.access.csv"],
|
||||
"installable": True,
|
||||
"license": "AGPL-3",
|
||||
}
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
|
||||
from . import stock_inventory
|
||||
|
||||
@@ -3,34 +3,32 @@
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import _, api, fields, models
|
||||
from odoo.addons import decimal_precision as dp
|
||||
from odoo.tools.safe_eval import safe_eval
|
||||
|
||||
from odoo.addons import decimal_precision as dp
|
||||
|
||||
|
||||
class StockInventoryEmptyLines(models.Model):
|
||||
_name = 'stock.inventory.line.empty'
|
||||
_description = 'Inventory Line Empty'
|
||||
_name = "stock.inventory.line.empty"
|
||||
_description = "Inventory Line Empty"
|
||||
|
||||
product_code = fields.Char(
|
||||
string='Product Code',
|
||||
required=True,
|
||||
)
|
||||
product_code = fields.Char(string="Product Code", required=True)
|
||||
product_qty = fields.Float(
|
||||
string='Quantity',
|
||||
string="Quantity",
|
||||
required=True,
|
||||
default=1.0,
|
||||
digits=dp.get_precision('Product Unit of Measure'),
|
||||
digits=dp.get_precision("Product Unit of Measure"),
|
||||
)
|
||||
inventory_id = fields.Many2one(
|
||||
comodel_name='stock.inventory',
|
||||
string='Inventory',
|
||||
comodel_name="stock.inventory",
|
||||
string="Inventory",
|
||||
required=True,
|
||||
ondelete="cascade",
|
||||
)
|
||||
|
||||
|
||||
class StockInventory(models.Model):
|
||||
_inherit = 'stock.inventory'
|
||||
_inherit = "stock.inventory"
|
||||
|
||||
@api.model
|
||||
def _selection_filter(self):
|
||||
@@ -40,90 +38,105 @@ class StockInventory(models.Model):
|
||||
:return: list of tuple
|
||||
"""
|
||||
res_filters = super(StockInventory, self)._selection_filter()
|
||||
res_filters.append(('categories', _('Selected Categories')))
|
||||
res_filters.append(('products', _('Selected Products')))
|
||||
res_filters.append(('domain', _('Filtered Products')))
|
||||
res_filters.append(("categories", _("Selected Categories")))
|
||||
res_filters.append(("products", _("Selected Products")))
|
||||
res_filters.append(("domain", _("Filtered Products")))
|
||||
for res_filter in res_filters:
|
||||
if res_filter[0] == 'lot':
|
||||
res_filters.append(('lots', _('Selected Lots')))
|
||||
if res_filter[0] == "lot":
|
||||
res_filters.append(("lots", _("Selected Lots")))
|
||||
break
|
||||
res_filters.append(('empty', _('Empty list')))
|
||||
res_filters.append(("empty", _("Empty list")))
|
||||
return res_filters
|
||||
|
||||
categ_ids = fields.Many2many(
|
||||
comodel_name='product.category', relation='rel_inventories_categories',
|
||||
column1='inventory_id', column2='category_id', string='Categories')
|
||||
comodel_name="product.category",
|
||||
relation="rel_inventories_categories",
|
||||
column1="inventory_id",
|
||||
column2="category_id",
|
||||
string="Categories",
|
||||
)
|
||||
product_ids = fields.Many2many(
|
||||
comodel_name='product.product', relation='rel_inventories_products',
|
||||
column1='inventory_id', column2='product_id', string='Products')
|
||||
comodel_name="product.product",
|
||||
relation="rel_inventories_products",
|
||||
column1="inventory_id",
|
||||
column2="product_id",
|
||||
string="Products",
|
||||
)
|
||||
lot_ids = fields.Many2many(
|
||||
comodel_name='stock.production.lot', relation='rel_inventories_lots',
|
||||
column1='inventory_id', column2='lot_id', string='Lots')
|
||||
comodel_name="stock.production.lot",
|
||||
relation="rel_inventories_lots",
|
||||
column1="inventory_id",
|
||||
column2="lot_id",
|
||||
string="Lots",
|
||||
)
|
||||
empty_line_ids = fields.One2many(
|
||||
comodel_name='stock.inventory.line.empty', inverse_name='inventory_id',
|
||||
string='Capture Lines')
|
||||
product_domain = fields.Char('Domain', default=[('name', 'ilike', '')])
|
||||
comodel_name="stock.inventory.line.empty",
|
||||
inverse_name="inventory_id",
|
||||
string="Capture Lines",
|
||||
)
|
||||
product_domain = fields.Char("Domain", default=[("name", "ilike", "")])
|
||||
|
||||
@api.model
|
||||
def _get_inventory_lines_values(self):
|
||||
self.ensure_one()
|
||||
vals = []
|
||||
product_obj = self.env['product.product']
|
||||
product_obj = self.env["product.product"]
|
||||
inventory = self.new(self._convert_to_write(self.read()[0]))
|
||||
if self.filter in ('categories', 'products'):
|
||||
if self.filter == 'categories':
|
||||
products = product_obj.search([
|
||||
('product_tmpl_id.categ_id', 'in', self.categ_ids.ids)
|
||||
])
|
||||
if self.filter in ("categories", "products"):
|
||||
if self.filter == "categories":
|
||||
products = product_obj.search(
|
||||
[("product_tmpl_id.categ_id", "in", self.categ_ids.ids)]
|
||||
)
|
||||
else: # filter = 'products'
|
||||
products = self.product_ids
|
||||
inventory.filter = 'product'
|
||||
inventory.filter = "product"
|
||||
for product in products:
|
||||
inventory.product_id = product
|
||||
vals += super(StockInventory,
|
||||
inventory)._get_inventory_lines_values()
|
||||
elif self.filter == 'lots':
|
||||
inventory.filter = 'lot'
|
||||
vals += super(StockInventory, inventory)._get_inventory_lines_values()
|
||||
elif self.filter == "lots":
|
||||
inventory.filter = "lot"
|
||||
for lot in self.lot_ids:
|
||||
inventory.lot_id = lot
|
||||
vals += super(StockInventory,
|
||||
inventory)._get_inventory_lines_values()
|
||||
elif self.filter == 'domain':
|
||||
vals += super(StockInventory, inventory)._get_inventory_lines_values()
|
||||
elif self.filter == "domain":
|
||||
domain = safe_eval(self.product_domain)
|
||||
products = self.env['product.product'].search(domain)
|
||||
inventory.filter = 'product'
|
||||
products = self.env["product.product"].search(domain)
|
||||
inventory.filter = "product"
|
||||
for product in products:
|
||||
inventory.product_id = product
|
||||
vals += super(
|
||||
StockInventory, inventory)._get_inventory_lines_values()
|
||||
elif self.filter == 'empty':
|
||||
vals += super(StockInventory, inventory)._get_inventory_lines_values()
|
||||
elif self.filter == "empty":
|
||||
tmp_lines = {}
|
||||
for line in self.empty_line_ids:
|
||||
tmp_lines.setdefault(line.product_code, 0)
|
||||
tmp_lines[line.product_code] += line.product_qty
|
||||
self.empty_line_ids.unlink()
|
||||
inventory.filter = 'product'
|
||||
inventory.filter = "product"
|
||||
# HACK: Make sure location is preserved
|
||||
inventory.location_id = self.location_id
|
||||
for product_code in tmp_lines.keys():
|
||||
product = product_obj.search([
|
||||
'|',
|
||||
('default_code', '=', product_code),
|
||||
('barcode', '=', product_code),
|
||||
], limit=1)
|
||||
product = product_obj.search(
|
||||
[
|
||||
"|",
|
||||
("default_code", "=", product_code),
|
||||
("barcode", "=", product_code),
|
||||
],
|
||||
limit=1,
|
||||
)
|
||||
if not product:
|
||||
continue
|
||||
inventory.product_id = product
|
||||
values = super(StockInventory,
|
||||
inventory)._get_inventory_lines_values()
|
||||
values = super(StockInventory, inventory)._get_inventory_lines_values()
|
||||
if values:
|
||||
values[0]['product_qty'] = tmp_lines[product_code]
|
||||
values[0]["product_qty"] = tmp_lines[product_code]
|
||||
else:
|
||||
vals += [{
|
||||
'product_id': product.id,
|
||||
'product_qty': tmp_lines[product_code],
|
||||
'location_id': self.location_id.id,
|
||||
}]
|
||||
vals += [
|
||||
{
|
||||
"product_id": product.id,
|
||||
"product_qty": tmp_lines[product_code],
|
||||
"location_id": self.location_id.id,
|
||||
}
|
||||
]
|
||||
vals += values
|
||||
else:
|
||||
vals = super()._get_inventory_lines_values()
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
|
||||
from . import test_stock_inventory_preparation_filter
|
||||
|
||||
@@ -10,88 +10,105 @@ from odoo.tests import common
|
||||
class TestStockInventoryPreparationFilterCategories(common.TransactionCase):
|
||||
def setUp(self):
|
||||
super(TestStockInventoryPreparationFilterCategories, self).setUp()
|
||||
self.inventory_model = self.env['stock.inventory']
|
||||
self.inventory_model = self.env["stock.inventory"]
|
||||
# Create some categories
|
||||
self.category = self.env['product.category'].create({
|
||||
'name': 'Category for inventory',
|
||||
})
|
||||
self.category2 = self.env['product.category'].create({
|
||||
'name': 'Category for inventory 2',
|
||||
})
|
||||
self.category = self.env["product.category"].create(
|
||||
{"name": "Category for inventory"}
|
||||
)
|
||||
self.category2 = self.env["product.category"].create(
|
||||
{"name": "Category for inventory 2"}
|
||||
)
|
||||
# Create some products in the category
|
||||
self.product1 = self.env['product.product'].create({
|
||||
'name': 'Product for inventory 1',
|
||||
'type': 'product',
|
||||
'categ_id': self.category.id,
|
||||
'default_code': 'PROD1-TEST',
|
||||
})
|
||||
self.product2 = self.env['product.product'].create({
|
||||
'name': 'Product for inventory 2',
|
||||
'type': 'product',
|
||||
'categ_id': self.category.id,
|
||||
'default_code': 'PROD2-TEST',
|
||||
})
|
||||
self.product3 = self.env['product.product'].create({
|
||||
'name': 'Product for inventory 3',
|
||||
'type': 'product',
|
||||
'categ_id': self.category.id,
|
||||
'default_code': 'PROD3-TEST',
|
||||
})
|
||||
self.product_lot = self.env['product.product'].create({
|
||||
'name': 'Product for inventory with lots',
|
||||
'type': 'product',
|
||||
'categ_id': self.category2.id,
|
||||
})
|
||||
self.lot = self.env['stock.production.lot'].create({
|
||||
'name': 'Lot test',
|
||||
'product_id': self.product_lot.id,
|
||||
})
|
||||
self.product1 = self.env["product.product"].create(
|
||||
{
|
||||
"name": "Product for inventory 1",
|
||||
"type": "product",
|
||||
"categ_id": self.category.id,
|
||||
"default_code": "PROD1-TEST",
|
||||
}
|
||||
)
|
||||
self.product2 = self.env["product.product"].create(
|
||||
{
|
||||
"name": "Product for inventory 2",
|
||||
"type": "product",
|
||||
"categ_id": self.category.id,
|
||||
"default_code": "PROD2-TEST",
|
||||
}
|
||||
)
|
||||
self.product3 = self.env["product.product"].create(
|
||||
{
|
||||
"name": "Product for inventory 3",
|
||||
"type": "product",
|
||||
"categ_id": self.category.id,
|
||||
"default_code": "PROD3-TEST",
|
||||
}
|
||||
)
|
||||
self.product_lot = self.env["product.product"].create(
|
||||
{
|
||||
"name": "Product for inventory with lots",
|
||||
"type": "product",
|
||||
"categ_id": self.category2.id,
|
||||
}
|
||||
)
|
||||
self.lot = self.env["stock.production.lot"].create(
|
||||
{"name": "Lot test", "product_id": self.product_lot.id}
|
||||
)
|
||||
# Add user to lot tracking group
|
||||
self.env.user.groups_id = [
|
||||
(4, self.env.ref('stock.group_production_lot').id),
|
||||
]
|
||||
self.env.user.groups_id = [(4, self.env.ref("stock.group_production_lot").id)]
|
||||
# And have some stock in a location
|
||||
self.location = self.env['stock.location'].create({
|
||||
'name': 'Inventory tests',
|
||||
'usage': 'internal',
|
||||
})
|
||||
inventory = self.inventory_model.create({
|
||||
'name': 'Product1 inventory',
|
||||
'filter': 'product',
|
||||
'line_ids': [
|
||||
(0, 0, {
|
||||
'product_id': self.product1.id,
|
||||
'product_uom_id': self.env.ref(
|
||||
"uom.product_uom_unit").id,
|
||||
'product_qty': 2.0,
|
||||
'location_id': self.location.id,
|
||||
}),
|
||||
(0, 0, {
|
||||
'product_id': self.product2.id,
|
||||
'product_uom_id': self.env.ref(
|
||||
"uom.product_uom_unit").id,
|
||||
'product_qty': 4.0,
|
||||
'location_id': self.location.id,
|
||||
}),
|
||||
(0, 0, {
|
||||
'product_id': self.product_lot.id,
|
||||
'product_uom_id': self.env.ref(
|
||||
"uom.product_uom_unit").id,
|
||||
'product_qty': 6.0,
|
||||
'location_id': self.location.id,
|
||||
'prod_lot_id': self.lot.id,
|
||||
}),
|
||||
],
|
||||
})
|
||||
self.location = self.env["stock.location"].create(
|
||||
{"name": "Inventory tests", "usage": "internal"}
|
||||
)
|
||||
inventory = self.inventory_model.create(
|
||||
{
|
||||
"name": "Product1 inventory",
|
||||
"filter": "product",
|
||||
"line_ids": [
|
||||
(
|
||||
0,
|
||||
0,
|
||||
{
|
||||
"product_id": self.product1.id,
|
||||
"product_uom_id": self.env.ref("uom.product_uom_unit").id,
|
||||
"product_qty": 2.0,
|
||||
"location_id": self.location.id,
|
||||
},
|
||||
),
|
||||
(
|
||||
0,
|
||||
0,
|
||||
{
|
||||
"product_id": self.product2.id,
|
||||
"product_uom_id": self.env.ref("uom.product_uom_unit").id,
|
||||
"product_qty": 4.0,
|
||||
"location_id": self.location.id,
|
||||
},
|
||||
),
|
||||
(
|
||||
0,
|
||||
0,
|
||||
{
|
||||
"product_id": self.product_lot.id,
|
||||
"product_uom_id": self.env.ref("uom.product_uom_unit").id,
|
||||
"product_qty": 6.0,
|
||||
"location_id": self.location.id,
|
||||
"prod_lot_id": self.lot.id,
|
||||
},
|
||||
),
|
||||
],
|
||||
}
|
||||
)
|
||||
inventory._action_done()
|
||||
|
||||
def test_inventory_category_filter(self):
|
||||
inventory = self.inventory_model.create({
|
||||
'name': 'Category inventory',
|
||||
'filter': 'categories',
|
||||
'location_id': self.location.id,
|
||||
'categ_ids': [(6, 0, [self.category.id])],
|
||||
})
|
||||
inventory = self.inventory_model.create(
|
||||
{
|
||||
"name": "Category inventory",
|
||||
"filter": "categories",
|
||||
"location_id": self.location.id,
|
||||
"categ_ids": [(6, 0, [self.category.id])],
|
||||
}
|
||||
)
|
||||
inventory.action_start()
|
||||
self.assertEqual(len(inventory.line_ids), 2)
|
||||
line1 = inventory.line_ids[0]
|
||||
@@ -104,12 +121,14 @@ class TestStockInventoryPreparationFilterCategories(common.TransactionCase):
|
||||
self.assertEqual(line2.location_id, self.location)
|
||||
|
||||
def test_inventory_products_filter(self):
|
||||
inventory = self.inventory_model.create({
|
||||
'name': 'Products inventory',
|
||||
'filter': 'products',
|
||||
'location_id': self.location.id,
|
||||
'product_ids': [(6, 0, [self.product1.id, self.product2.id])],
|
||||
})
|
||||
inventory = self.inventory_model.create(
|
||||
{
|
||||
"name": "Products inventory",
|
||||
"filter": "products",
|
||||
"location_id": self.location.id,
|
||||
"product_ids": [(6, 0, [self.product1.id, self.product2.id])],
|
||||
}
|
||||
)
|
||||
inventory.action_start()
|
||||
self.assertEqual(len(inventory.line_ids), 2)
|
||||
line1 = inventory.line_ids[0]
|
||||
@@ -122,12 +141,14 @@ class TestStockInventoryPreparationFilterCategories(common.TransactionCase):
|
||||
self.assertEqual(line2.location_id, self.location)
|
||||
|
||||
def test_inventory_domain_filter(self):
|
||||
inventory = self.inventory_model.create({
|
||||
'name': 'Domain inventory',
|
||||
'filter': 'domain',
|
||||
'location_id': self.location.id,
|
||||
'product_domain': [('id', '=', self.product1.id)],
|
||||
})
|
||||
inventory = self.inventory_model.create(
|
||||
{
|
||||
"name": "Domain inventory",
|
||||
"filter": "domain",
|
||||
"location_id": self.location.id,
|
||||
"product_domain": [("id", "=", self.product1.id)],
|
||||
}
|
||||
)
|
||||
inventory.action_start()
|
||||
self.assertEqual(len(inventory.line_ids), 1)
|
||||
line1 = inventory.line_ids[0]
|
||||
@@ -138,10 +159,10 @@ class TestStockInventoryPreparationFilterCategories(common.TransactionCase):
|
||||
def test_inventory_lots_filter(self):
|
||||
inventory = self.inventory_model.create(
|
||||
{
|
||||
'name': 'Products inventory',
|
||||
'filter': 'lots',
|
||||
'location_id': self.location.id,
|
||||
'lot_ids': [(6, 0, [self.lot.id, ])],
|
||||
"name": "Products inventory",
|
||||
"filter": "lots",
|
||||
"location_id": self.location.id,
|
||||
"lot_ids": [(6, 0, [self.lot.id])],
|
||||
}
|
||||
)
|
||||
inventory.action_start()
|
||||
@@ -153,29 +174,19 @@ class TestStockInventoryPreparationFilterCategories(common.TransactionCase):
|
||||
self.assertEqual(line1.location_id, self.location)
|
||||
|
||||
def test_inventory_empty_filter(self):
|
||||
inventory = self.inventory_model.create({
|
||||
'name': 'Products inventory',
|
||||
'filter': 'empty',
|
||||
'location_id': self.location.id,
|
||||
'empty_line_ids': [
|
||||
(0, 0, {
|
||||
'product_code': 'PROD1-TEST',
|
||||
'product_qty': 3.0,
|
||||
}),
|
||||
(0, 0, {
|
||||
'product_code': 'PROD2-TEST',
|
||||
'product_qty': 7.0,
|
||||
}),
|
||||
(0, 0, {
|
||||
'product_code': 'PROD3-TEST',
|
||||
'product_qty': 5.0,
|
||||
}),
|
||||
(0, 0, {
|
||||
'product_code': 'UNEXISTING-CODE',
|
||||
'product_qty': 0.0,
|
||||
}),
|
||||
],
|
||||
})
|
||||
inventory = self.inventory_model.create(
|
||||
{
|
||||
"name": "Products inventory",
|
||||
"filter": "empty",
|
||||
"location_id": self.location.id,
|
||||
"empty_line_ids": [
|
||||
(0, 0, {"product_code": "PROD1-TEST", "product_qty": 3.0}),
|
||||
(0, 0, {"product_code": "PROD2-TEST", "product_qty": 7.0}),
|
||||
(0, 0, {"product_code": "PROD3-TEST", "product_qty": 5.0}),
|
||||
(0, 0, {"product_code": "UNEXISTING-CODE", "product_qty": 0.0}),
|
||||
],
|
||||
}
|
||||
)
|
||||
inventory.action_start()
|
||||
self.assertEqual(len(inventory.line_ids), 3)
|
||||
line1 = inventory.line_ids[0]
|
||||
|
||||
Reference in New Issue
Block a user