mirror of
https://github.com/OCA/stock-logistics-warehouse.git
synced 2025-01-21 14:27:28 +02:00
@@ -17,27 +17,38 @@ class StockInventory(models.Model):
|
||||
vals = super()._get_inventory_lines_values()
|
||||
|
||||
if self.include_exhausted:
|
||||
domain = [("qty_available", "=", 0), ("type", "=", "product")]
|
||||
product_ids = [data.get("product_id") for data in vals]
|
||||
domain.append(("id", "not in", product_ids))
|
||||
non_exhausted_set = {(l["product_id"], l["location_id"]) for l in vals}
|
||||
if self.product_ids:
|
||||
domain.append(("id", "in", self.product_ids.ids))
|
||||
exhausted_products = self.env["product.product"].search(domain)
|
||||
vals_dic = {
|
||||
"inventory_id": self.id,
|
||||
"company_id": self.company_id.id,
|
||||
"product_qty": 0,
|
||||
"theoretical_qty": 0,
|
||||
}
|
||||
vals_dic["location_id"] = (
|
||||
self.env["stock.warehouse"]
|
||||
.search([("company_id", "=", vals_dic["company_id"])], limit=1)
|
||||
.lot_stock_id.id
|
||||
)
|
||||
for product in exhausted_products:
|
||||
vals_dic["product_id"] = product.id
|
||||
vals_dic["product_uom_id"] = product.uom_id.id
|
||||
|
||||
vals.append(vals_dic.copy())
|
||||
|
||||
product_ids = self.product_ids.ids
|
||||
else:
|
||||
product_ids = self.env["product.product"].search_read(
|
||||
[
|
||||
"|",
|
||||
("company_id", "=", self.company_id.id),
|
||||
("company_id", "=", False),
|
||||
("type", "=", "product"),
|
||||
("active", "=", True),
|
||||
],
|
||||
["id"],
|
||||
)
|
||||
product_ids = [p["id"] for p in product_ids]
|
||||
if self.location_ids:
|
||||
location_ids = self.location_ids.ids
|
||||
else:
|
||||
location_ids = (
|
||||
self.env["stock.warehouse"]
|
||||
.search([("company_id", "=", self.company_id.id)])
|
||||
.lot_stock_id.ids
|
||||
)
|
||||
for product in product_ids:
|
||||
for location_id in location_ids:
|
||||
if (product, location_id) not in non_exhausted_set:
|
||||
vals.append(
|
||||
{
|
||||
"inventory_id": self.id,
|
||||
"product_id": product,
|
||||
"location_id": location_id,
|
||||
"theoretical_qty": 0,
|
||||
}
|
||||
)
|
||||
return vals
|
||||
|
||||
@@ -18,9 +18,7 @@ class StockInventoryIncludeExhaustedTest(TransactionCase):
|
||||
# We need this to know how many product with no stock we have on our
|
||||
# database
|
||||
self.quantity_out_of_stock = len(
|
||||
self.env["product.product"].search(
|
||||
[("qty_available", "=", 0), ("type", "=", "product")]
|
||||
)
|
||||
self.env["product.product"].search([("type", "=", "product")])
|
||||
)
|
||||
|
||||
self.user = self.res_users_model.create(
|
||||
@@ -48,6 +46,11 @@ class StockInventoryIncludeExhaustedTest(TransactionCase):
|
||||
}
|
||||
)
|
||||
|
||||
self.quantity_out_of_stock_by_product = len(
|
||||
self.env["product.product"].search(
|
||||
[("id", "=", self.product1.id), ("type", "=", "product")]
|
||||
)
|
||||
)
|
||||
self.location = self.location_model.create(
|
||||
{"name": "Inventory tests 1", "usage": "internal"}
|
||||
)
|
||||
@@ -55,21 +58,26 @@ class StockInventoryIncludeExhaustedTest(TransactionCase):
|
||||
{"name": "Inventory tests 2", "usage": "internal"}
|
||||
)
|
||||
|
||||
def _create_inventory_all_products(self, name, location, include_exhausted):
|
||||
inventory = self.inventory_model.create(
|
||||
{
|
||||
"name": name,
|
||||
"location_ids": [(4, location.id)],
|
||||
"include_exhausted": include_exhausted,
|
||||
}
|
||||
)
|
||||
def _create_inventory_all_products(
|
||||
self, name, include_exhausted, location=False, product=False
|
||||
):
|
||||
vals = {
|
||||
"name": name,
|
||||
"include_exhausted": include_exhausted,
|
||||
}
|
||||
if location:
|
||||
vals["location_ids"] = [(4, location.id)]
|
||||
if product:
|
||||
vals["product_ids"] = [(4, product.id)]
|
||||
|
||||
inventory = self.inventory_model.create(vals)
|
||||
return inventory
|
||||
|
||||
def test_not_including_exhausted(self):
|
||||
"""Check if products with no stock are not included into the inventory
|
||||
if the including exhausted option is disabled."""
|
||||
inventory_not_inc = self._create_inventory_all_products(
|
||||
"not_included", self.location, False
|
||||
"not_included", False, self.location
|
||||
)
|
||||
inventory_not_inc.action_start()
|
||||
inventory_not_inc.action_validate()
|
||||
@@ -83,8 +91,8 @@ class StockInventoryIncludeExhaustedTest(TransactionCase):
|
||||
# The products with no stock don't have a location,
|
||||
# that's why search the non-stocked in all locations
|
||||
"included",
|
||||
self.location,
|
||||
True,
|
||||
location=self.location,
|
||||
)
|
||||
|
||||
inventory_inc.action_start()
|
||||
@@ -95,3 +103,34 @@ class StockInventoryIncludeExhaustedTest(TransactionCase):
|
||||
self.quantity_out_of_stock + 2,
|
||||
"The products with no stock are not included",
|
||||
)
|
||||
|
||||
def test_not_including_exhausted_with_product(self):
|
||||
"""Check if products with no stock are not included into the inventory
|
||||
if the including exhausted option is disabled."""
|
||||
inventory_not_inc = self._create_inventory_all_products(
|
||||
"not_included", False, product=self.product1
|
||||
)
|
||||
inventory_not_inc.action_start()
|
||||
inventory_not_inc.action_validate()
|
||||
lines = inventory_not_inc.line_ids
|
||||
self.assertEqual(len(lines), 0, "Not all expected products are included")
|
||||
|
||||
def test_including_exhausted_with_product(self):
|
||||
"""Check if products with no stock are included into the inventory
|
||||
if the including exhausted option is enabled."""
|
||||
inventory_inc = self._create_inventory_all_products(
|
||||
# The products with no stock don't have a location,
|
||||
# that's why search the non-stocked in all locations
|
||||
"included",
|
||||
True,
|
||||
product=self.product1,
|
||||
)
|
||||
|
||||
inventory_inc.action_start()
|
||||
inventory_inc.action_validate()
|
||||
lines = inventory_inc.line_ids
|
||||
self.assertEqual(
|
||||
len(lines),
|
||||
self.quantity_out_of_stock_by_product,
|
||||
"The products with no stock are not included",
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user