[MIG] stock_inventory_preparation_filter: Migration to v13.0

This commit is contained in:
Sergio Teruel
2020-02-11 22:39:51 +01:00
committed by Ivàn Todorovich
parent 29a598a5db
commit 86ca74629e
10 changed files with 186 additions and 327 deletions

View File

@@ -14,39 +14,42 @@ Extended Inventory Preparation Filters
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fstock--logistics--warehouse-lightgray.png?logo=github
:target: https://github.com/OCA/stock-logistics-warehouse/tree/12.0/stock_inventory_preparation_filter
:target: https://github.com/OCA/stock-logistics-warehouse/tree/13.0/stock_inventory_preparation_filter
:alt: OCA/stock-logistics-warehouse
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/stock-logistics-warehouse-12-0/stock-logistics-warehouse-12-0-stock_inventory_preparation_filter
:target: https://translation.odoo-community.org/projects/stock-logistics-warehouse-13-0/stock-logistics-warehouse-13-0-stock_inventory_preparation_filter
:alt: Translate me on Weblate
.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png
:target: https://runbot.odoo-community.org/runbot/153/12.0
:target: https://runbot.odoo-community.org/runbot/153/13.0
:alt: Try me on Runbot
|badge1| |badge2| |badge3| |badge4| |badge5|
Includes more options for making an inventory out of:
* Multiple products.
* Products filtered by a domain.
* Products of a category.
* Multiple lots
It also allows to make an inventory based on scanned products, adding a line
with product code and quantity.
**Table of contents**
.. contents::
:local:
Known issues / Roadmap
======================
* The widget domain is not displayed correctly, but this issue is related to
Odoo. To avoid this malfunction, use the keyboard arrows to properly work
with the domain option.
Bug Tracker
===========
Bugs are tracked on `GitHub Issues <https://github.com/OCA/stock-logistics-warehouse/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 <https://github.com/OCA/stock-logistics-warehouse/issues/new?body=module:%20stock_inventory_preparation_filter%0Aversion:%2012.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
`feedback <https://github.com/OCA/stock-logistics-warehouse/issues/new?body=module:%20stock_inventory_preparation_filter%0Aversion:%2013.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
Do not contact contributors directly about support or help with technical issues.
@@ -67,6 +70,7 @@ Contributors
* Pedro M. Baeza
* David Vidal
* Sergio Teruel
* Xavier Jimenez <xavier.jimenez@qubiq.es>
@@ -83,6 +87,6 @@ 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.
This module is part of the `OCA/stock-logistics-warehouse <https://github.com/OCA/stock-logistics-warehouse/tree/12.0/stock_inventory_preparation_filter>`_ project on GitHub.
This module is part of the `OCA/stock-logistics-warehouse <https://github.com/OCA/stock-logistics-warehouse/tree/13.0/stock_inventory_preparation_filter>`_ project on GitHub.
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

View File

@@ -5,13 +5,13 @@
{
"name": "Extended Inventory Preparation Filters",
"version": "12.0.1.1.0",
"version": "13.0.1.0.0",
"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"],
"data": ["views/stock_inventory_view.xml"],
"installable": True,
"license": "AGPL-3",
}

View File

@@ -1,53 +1,40 @@
# Copyright 2015 AvanzOSC - Oihane Crucelaegi
# Copyright 2015 Tecnativa - Pedro M. Baeza
# Copyright 2020 Sergio Teruel <sergio.teruel@tecnativa.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import _, api, fields, models
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"
product_code = fields.Char(string="Product Code", required=True)
product_qty = fields.Float(
string="Quantity",
required=True,
default=1.0,
digits=dp.get_precision("Product Unit of Measure"),
)
inventory_id = fields.Many2one(
comodel_name="stock.inventory",
string="Inventory",
required=True,
ondelete="cascade",
)
class StockInventory(models.Model):
_inherit = "stock.inventory"
@api.model
def _selection_filter(self):
"""This function will return the list of filters allowed according to
the options checked in 'Settings/Warehouse'.
: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")))
for res_filter in res_filters:
if res_filter[0] == "lot":
res_filters.append(("lots", _("Selected Lots")))
break
res_filters.append(("empty", _("Empty list")))
return res_filters
""" Get the list of filter allowed according to the options checked
in 'Settings / Warehouse'. """
res_filter = [
("products", _("All products")),
("categories", _("Selected Categories")),
("domain", _("Filtered Products")),
]
if self.user_has_groups("stock.group_production_lot"):
res_filter.append(("lots", _("Selected Lots")))
return res_filter
filter = fields.Selection(
string="Inventory of",
selection="_selection_filter",
required=True,
default="products",
help="If you do an entire inventory, you can choose 'All Products' and "
"it will prefill the inventory with the current stock. If you "
"only do some products (e.g. Cycle Counting) you can choose "
"'Manual Selection of Products' and the system won't propose "
"anything. You can also let the system propose for a single "
"product / lot /... ",
)
categ_ids = fields.Many2many(
comodel_name="product.category",
relation="rel_inventories_categories",
@@ -55,13 +42,6 @@ class StockInventory(models.Model):
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",
)
lot_ids = fields.Many2many(
comodel_name="stock.production.lot",
relation="rel_inventories_lots",
@@ -69,75 +49,21 @@ class StockInventory(models.Model):
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", "")])
@api.model
def _get_inventory_lines_values(self):
self.ensure_one()
vals = []
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)]
)
else: # filter = 'products'
products = self.product_ids
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"
for lot in self.lot_ids:
inventory.lot_id = lot
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"
for product in products:
inventory.product_id = product
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"
# 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,
)
if not product:
continue
inventory.product_id = product
values = super(StockInventory, inventory)._get_inventory_lines_values()
if values:
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 += values
else:
vals = super()._get_inventory_lines_values()
return vals
def _action_start(self):
Product = self.env["product.product"]
for inventory in self:
products = Product.browse()
if inventory.state != "draft":
continue
if inventory.filter == "categories":
products = Product.search([("categ_id", "in", inventory.categ_ids.ids)])
if inventory.filter == "lots":
products = inventory.lot_ids.mapped("product_id")
if inventory.filter == "domain":
domain = safe_eval(inventory.product_domain)
products = Product.search(domain)
if products:
inventory.product_ids = [(6, 0, products.ids)]
return super()._action_start()

View File

@@ -3,5 +3,6 @@
* Pedro M. Baeza
* David Vidal
* Sergio Teruel
* Xavier Jimenez <xavier.jimenez@qubiq.es>

View File

@@ -1,9 +1,5 @@
Includes more options for making an inventory out of:
* Multiple products.
* Products filtered by a domain.
* Products of a category.
* Multiple lots
It also allows to make an inventory based on scanned products, adding a line
with product code and quantity.

View File

@@ -0,0 +1,3 @@
* The widget domain is not displayed correctly, but this issue is related to
Odoo. To avoid this malfunction, use the keyboard arrows to properly work
with the domain option.

View File

@@ -1,3 +0,0 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_stock_inventory_line_empty_user,access_stock_inventory_line_empty_user,model_stock_inventory_line_empty,stock.group_stock_user,1,0,0,0
access_stock_inventory_line_empty_manager,access_stock_inventory_line_empty_manager,model_stock_inventory_line_empty,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_empty_user access_stock_inventory_line_empty_user model_stock_inventory_line_empty stock.group_stock_user 1 0 0 0
3 access_stock_inventory_line_empty_manager access_stock_inventory_line_empty_manager model_stock_inventory_line_empty stock.group_stock_manager 1 1 1 1

View File

@@ -367,65 +367,72 @@ ul.auto-toc {
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<p><a class="reference external" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external" href="https://github.com/OCA/stock-logistics-warehouse/tree/12.0/stock_inventory_preparation_filter"><img alt="OCA/stock-logistics-warehouse" src="https://img.shields.io/badge/github-OCA%2Fstock--logistics--warehouse-lightgray.png?logo=github" /></a> <a class="reference external" href="https://translation.odoo-community.org/projects/stock-logistics-warehouse-12-0/stock-logistics-warehouse-12-0-stock_inventory_preparation_filter"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external" href="https://runbot.odoo-community.org/runbot/153/12.0"><img alt="Try me on Runbot" src="https://img.shields.io/badge/runbot-Try%20me-875A7B.png" /></a></p>
<p><a class="reference external" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external" href="https://github.com/OCA/stock-logistics-warehouse/tree/13.0/stock_inventory_preparation_filter"><img alt="OCA/stock-logistics-warehouse" src="https://img.shields.io/badge/github-OCA%2Fstock--logistics--warehouse-lightgray.png?logo=github" /></a> <a class="reference external" href="https://translation.odoo-community.org/projects/stock-logistics-warehouse-13-0/stock-logistics-warehouse-13-0-stock_inventory_preparation_filter"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external" href="https://runbot.odoo-community.org/runbot/153/13.0"><img alt="Try me on Runbot" src="https://img.shields.io/badge/runbot-Try%20me-875A7B.png" /></a></p>
<p>Includes more options for making an inventory out of:</p>
<ul class="simple">
<li>Multiple products.</li>
<li>Products filtered by a domain.</li>
<li>Products of a category.</li>
<li>Multiple lots</li>
</ul>
<p>It also allows to make an inventory based on scanned products, adding a line
with product code and quantity.</p>
<p><strong>Table of contents</strong></p>
<div class="contents local topic" id="contents">
<ul class="simple">
<li><a class="reference internal" href="#bug-tracker" id="id1">Bug Tracker</a></li>
<li><a class="reference internal" href="#credits" id="id2">Credits</a><ul>
<li><a class="reference internal" href="#authors" id="id3">Authors</a></li>
<li><a class="reference internal" href="#contributors" id="id4">Contributors</a></li>
<li><a class="reference internal" href="#maintainers" id="id5">Maintainers</a></li>
<li><a class="reference internal" href="#known-issues-roadmap" id="id1">Known issues / Roadmap</a></li>
<li><a class="reference internal" href="#bug-tracker" id="id2">Bug Tracker</a></li>
<li><a class="reference internal" href="#credits" id="id3">Credits</a><ul>
<li><a class="reference internal" href="#authors" id="id4">Authors</a></li>
<li><a class="reference internal" href="#contributors" id="id5">Contributors</a></li>
<li><a class="reference internal" href="#maintainers" id="id6">Maintainers</a></li>
</ul>
</li>
</ul>
</div>
<div class="section" id="known-issues-roadmap">
<h1><a class="toc-backref" href="#id1">Known issues / Roadmap</a></h1>
<ul class="simple">
<li>The widget domain is not displayed correctly, but this issue is related to
Odoo. To avoid this malfunction, use the keyboard arrows to properly work
with the domain option.</li>
</ul>
</div>
<div class="section" id="bug-tracker">
<h1><a class="toc-backref" href="#id1">Bug Tracker</a></h1>
<h1><a class="toc-backref" href="#id2">Bug Tracker</a></h1>
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/stock-logistics-warehouse/issues">GitHub Issues</a>.
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
<a class="reference external" href="https://github.com/OCA/stock-logistics-warehouse/issues/new?body=module:%20stock_inventory_preparation_filter%0Aversion:%2012.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
<a class="reference external" href="https://github.com/OCA/stock-logistics-warehouse/issues/new?body=module:%20stock_inventory_preparation_filter%0Aversion:%2013.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
<p>Do not contact contributors directly about support or help with technical issues.</p>
</div>
<div class="section" id="credits">
<h1><a class="toc-backref" href="#id2">Credits</a></h1>
<h1><a class="toc-backref" href="#id3">Credits</a></h1>
<div class="section" id="authors">
<h2><a class="toc-backref" href="#id3">Authors</a></h2>
<h2><a class="toc-backref" href="#id4">Authors</a></h2>
<ul class="simple">
<li>AvanzOSC</li>
<li>Tecnativa</li>
</ul>
</div>
<div class="section" id="contributors">
<h2><a class="toc-backref" href="#id4">Contributors</a></h2>
<h2><a class="toc-backref" href="#id5">Contributors</a></h2>
<ul class="simple">
<li>Oihane Crucelaegui &lt;<a class="reference external" href="mailto:oihanecrucelaegi&#64;avanzosc.es">oihanecrucelaegi&#64;avanzosc.es</a>&gt;</li>
<li><a class="reference external" href="https://www.tecnativa.com">Tecnativa</a>:<ul>
<li>Pedro M. Baeza</li>
<li>David Vidal</li>
<li>Sergio Teruel</li>
</ul>
</li>
<li>Xavier Jimenez &lt;<a class="reference external" href="mailto:xavier.jimenez&#64;qubiq.es">xavier.jimenez&#64;qubiq.es</a>&gt;</li>
</ul>
</div>
<div class="section" id="maintainers">
<h2><a class="toc-backref" href="#id5">Maintainers</a></h2>
<h2><a class="toc-backref" href="#id6">Maintainers</a></h2>
<p>This module is maintained by the OCA.</p>
<a class="reference external image-reference" href="https://odoo-community.org"><img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" /></a>
<p>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.</p>
<p>This module is part of the <a class="reference external" href="https://github.com/OCA/stock-logistics-warehouse/tree/12.0/stock_inventory_preparation_filter">OCA/stock-logistics-warehouse</a> project on GitHub.</p>
<p>This module is part of the <a class="reference external" href="https://github.com/OCA/stock-logistics-warehouse/tree/13.0/stock_inventory_preparation_filter">OCA/stock-logistics-warehouse</a> project on GitHub.</p>
<p>You are welcome to contribute. To learn how please visit <a class="reference external" href="https://odoo-community.org/page/Contribute">https://odoo-community.org/page/Contribute</a>.</p>
</div>
</div>

View File

@@ -11,15 +11,14 @@ class TestStockInventoryPreparationFilterCategories(common.TransactionCase):
def setUp(self):
super(TestStockInventoryPreparationFilterCategories, self).setUp()
self.inventory_model = self.env["stock.inventory"]
self.location = self.env.ref("stock.stock_location_stock")
self.Product = self.env["product.product"]
self.Category = self.env["product.category"]
# 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.Category.create({"name": "Category for inventory"})
self.category2 = self.Category.create({"name": "Category for inventory 2"})
# Create some products in the category
self.product1 = self.env["product.product"].create(
self.product1 = self.Product.create(
{
"name": "Product for inventory 1",
"type": "product",
@@ -27,7 +26,7 @@ class TestStockInventoryPreparationFilterCategories(common.TransactionCase):
"default_code": "PROD1-TEST",
}
)
self.product2 = self.env["product.product"].create(
self.product2 = self.Product.create(
{
"name": "Product for inventory 2",
"type": "product",
@@ -35,7 +34,7 @@ class TestStockInventoryPreparationFilterCategories(common.TransactionCase):
"default_code": "PROD2-TEST",
}
)
self.product3 = self.env["product.product"].create(
self.product3 = self.Product.create(
{
"name": "Product for inventory 3",
"type": "product",
@@ -43,7 +42,7 @@ class TestStockInventoryPreparationFilterCategories(common.TransactionCase):
"default_code": "PROD3-TEST",
}
)
self.product_lot = self.env["product.product"].create(
self.product_lot = self.Product.create(
{
"name": "Product for inventory with lots",
"type": "product",
@@ -51,7 +50,41 @@ class TestStockInventoryPreparationFilterCategories(common.TransactionCase):
}
)
self.lot = self.env["stock.production.lot"].create(
{"name": "Lot test", "product_id": self.product_lot.id}
{
"name": "Lot test",
"product_id": self.product_lot.id,
"company_id": self.env.user.company_id.id,
}
)
# Add quants for products to ensure that inventory lines are created
self.env["stock.quant"].create(
[
{
"product_id": self.product1.id,
"product_uom_id": self.product1.uom_id.id,
"location_id": self.location.id,
"quantity": 2.0,
},
{
"product_id": self.product2.id,
"product_uom_id": self.product2.uom_id.id,
"location_id": self.location.id,
"quantity": 2.0,
},
{
"product_id": self.product3.id,
"product_uom_id": self.product3.uom_id.id,
"location_id": self.location.id,
"quantity": 2.0,
},
{
"product_id": self.product_lot.id,
"product_uom_id": self.product_lot.uom_id.id,
"location_id": self.location.id,
"quantity": 2.0,
"lot_id": self.lot.id,
},
]
)
# Add user to lot tracking group
self.env.user.groups_id = [(4, self.env.ref("stock.group_production_lot").id)]
@@ -59,93 +92,35 @@ class TestStockInventoryPreparationFilterCategories(common.TransactionCase):
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.test_products = (
self.product1 + self.product2 + self.product3 + self.product_lot
)
inventory._action_done()
def test_inventory_category_filter(self):
def test_inventory_filter(self):
# Filter all products
inventory = self.inventory_model.create(
{
"name": "Category inventory",
"filter": "categories",
"location_id": self.location.id,
"categ_ids": [(6, 0, [self.category.id])],
}
{"name": "Inventory test", "filter": "products"}
)
inventory.action_start()
self.assertEqual(len(inventory.line_ids), 2)
line1 = inventory.line_ids[0]
self.assertEqual(line1.product_id, self.product1)
self.assertEqual(line1.theoretical_qty, 2.0)
self.assertEqual(line1.location_id, self.location)
line2 = inventory.line_ids[1]
self.assertEqual(line2.product_id, self.product2)
self.assertEqual(line2.theoretical_qty, 4.0)
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])],
}
self.assertTrue(self.test_products <= inventory.line_ids.mapped("product_id"))
# Filter by categories
inventory.action_cancel_draft()
inventory.update(
{"filter": "categories", "categ_ids": [(6, 0, [self.category.id])]}
)
inventory.action_start()
self.assertEqual(len(inventory.line_ids), 2)
line1 = inventory.line_ids[0]
self.assertEqual(line1.product_id, self.product1)
self.assertEqual(line1.theoretical_qty, 2.0)
self.assertEqual(line1.location_id, self.location)
line2 = inventory.line_ids[1]
self.assertEqual(line2.product_id, self.product2)
self.assertEqual(line2.theoretical_qty, 4.0)
self.assertEqual(line2.location_id, self.location)
self.assertEqual(len(inventory.line_ids), 3)
# Filter by lots
inventory.action_cancel_draft()
inventory.update({"filter": "lots", "lot_ids": [(6, 0, self.lot.ids)]})
inventory.action_start()
self.assertEqual(len(inventory.line_ids), 1)
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)],
}
)
@@ -154,53 +129,3 @@ class TestStockInventoryPreparationFilterCategories(common.TransactionCase):
line1 = inventory.line_ids[0]
self.assertEqual(line1.product_id, self.product1)
self.assertEqual(line1.theoretical_qty, 2.0)
self.assertEqual(line1.location_id, self.location)
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])],
}
)
inventory.action_start()
self.assertEqual(len(inventory.line_ids), 1)
line1 = inventory.line_ids[0]
self.assertEqual(line1.product_id, self.product_lot)
self.assertEqual(line1.prod_lot_id, self.lot)
self.assertEqual(line1.theoretical_qty, 6.0)
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.action_start()
self.assertEqual(len(inventory.line_ids), 3)
line1 = inventory.line_ids[0]
self.assertEqual(line1.product_id, self.product1)
self.assertEqual(line1.theoretical_qty, 2.0)
self.assertEqual(line1.product_qty, 3.0)
self.assertEqual(line1.location_id, self.location)
line2 = inventory.line_ids[1]
self.assertEqual(line2.product_id, self.product2)
self.assertEqual(line2.theoretical_qty, 4.0)
self.assertEqual(line2.product_qty, 7.0)
self.assertEqual(line2.location_id, self.location)
line3 = inventory.line_ids[2]
self.assertEqual(line3.product_id, self.product3)
self.assertEqual(line3.theoretical_qty, 0.0)
self.assertEqual(line3.product_qty, 5.0)
self.assertEqual(line3.location_id, self.location)

View File

@@ -1,48 +1,48 @@
<?xml version="1.0" encoding="UTF-8"?>
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<record model="ir.ui.view" id="stock_inventory_form">
<field name="name">stock.inventory.form</field>
<field name="model">stock.inventory</field>
<field name="inherit_id" ref="stock.view_inventory_form" />
<field name="arch" type="xml">
<data>
<notebook position="attributes">
<attribute name="attrs" />
</notebook>
<xpath expr="//button[@name='action_reset_product_qty']/ancestor::*[position()=1]" position="attributes">
<attribute name="attrs">{'invisible':[('state','=','draft')]}</attribute>
</xpath>
<field name="category_id" position="after">
<field name="categ_ids"
widget="many2many_tags"
attrs="{'invisible':[('filter','!=','categories')]}" />
</field>
<field name="product_id" position="after">
<field name="product_ids"
widget="many2many_tags"
attrs="{'invisible':[('filter','!=','products')]}" />
</field>
<field name="lot_id" position="after">
<field name="lot_ids"
attrs="{'invisible':[('filter','!=','lots')]}" />
</field>
<notebook position="before">
<field name="product_domain" widget="domain" attrs="{'invisible': [('filter', '!=', 'domain')]}" options="{'model': 'product.product'}"/>
</notebook>
<notebook position="inside">
<page string="Capture Lines"
attrs="{'invisible':[('filter','!=','empty')]}">
<field name="empty_line_ids" nolabel="1">
<tree editable="bottom">
<field name="product_code"/>
<field name="product_qty"/>
</tree>
</field>
</page>
</notebook>
</data>
<record model="ir.ui.view" id="view_inventory_form">
<field name="model">stock.inventory</field>
<field name="inherit_id" ref="stock.view_inventory_form" />
<field name="arch" type="xml">
<field name="product_ids" position="attributes">
<attribute
name="attrs"
>{'invisible': [('filter', '!=', 'products')]}</attribute>
</field>
</record>
<xpath expr="//field[@name='location_ids']/../.." position="before">
<group>
<group>
<field
name="filter"
string="Inventory of"
widget='radio'
attrs="{'readonly': [('state', '!=', 'draft')]}"
/>
</group>
</group>
</xpath>
<field name="location_ids" position="before">
<field
name="categ_ids"
widget="many2many_tags"
attrs="{'invisible':[('filter','!=','categories')]}"
/>
</field>
<field name="location_ids" position="before">
<field
name="lot_ids"
widget="many2many_tags"
attrs="{'invisible':[('filter','!=','lots')]}"
/>
</field>
<xpath expr="//field[@name='location_ids']/../.." position="after">
<field
name="product_domain"
widget="domain"
attrs="{'invisible': [('filter', '!=', 'domain')]}"
options="{'model': 'product.product'}"
/>
</xpath>
</field>
</record>
</odoo>