add stock_inventory_product_exhausted: prevent for removing zero quantity stock quants. Add exhausted products to inventory adjustments

This commit is contained in:
Luis 2025-10-01 13:27:34 +02:00
parent e4050a6e31
commit 17cc64c522
15 changed files with 565 additions and 0 deletions

View file

@ -0,0 +1 @@
from . import test_stock_inventory_exhausted

View file

@ -0,0 +1,227 @@
from odoo.tests.common import TransactionCase
class TestStockInventoryExhausted(TransactionCase):
def setUp(self):
super().setUp()
# Create test products
self.product_with_stock = self.env["product.product"].create(
{
"name": "Product With Stock",
"type": "product",
"categ_id": self.env.ref("product.product_category_all").id,
}
)
self.product_without_stock = self.env["product.product"].create(
{
"name": "Product Without Stock",
"type": "product",
"categ_id": self.env.ref("product.product_category_all").id,
}
)
# Create test location
self.location = self.env["stock.location"].create(
{
"name": "Test Location",
"usage": "internal",
}
)
# Create initial stock for one product
self.env["stock.quant"].create(
{
"product_id": self.product_with_stock.id,
"location_id": self.location.id,
"quantity": 10.0,
}
)
def test_inventory_without_exhausted_products_flag(self):
"""Test that without the flag, zero stock products are not included"""
inventory = self.env["stock.inventory"].create(
{
"name": "Test Inventory without flag",
"location_ids": [(6, 0, [self.location.id])],
"product_selection": "all",
"include_exhausted_products": False,
}
)
inventory.action_start()
# Should only have quants for products with existing stock
self.assertTrue(
any(
q.product_id == self.product_with_stock
for q in inventory.stock_quant_ids
)
)
self.assertFalse(
any(
q.product_id == self.product_without_stock
for q in inventory.stock_quant_ids
)
)
def test_inventory_with_exhausted_products_flag(self):
"""Test that with the flag, zero stock products are included"""
inventory = self.env["stock.inventory"].create(
{
"name": "Test Inventory with flag",
"location_ids": [(6, 0, [self.location.id])],
"product_selection": "all",
"include_exhausted_products": True,
}
)
inventory.action_start()
# Should have quants for both products (including zero stock product)
self.assertTrue(
any(
q.product_id == self.product_with_stock
for q in inventory.stock_quant_ids
)
)
self.assertTrue(
any(
q.product_id == self.product_without_stock
for q in inventory.stock_quant_ids
)
)
# Check that zero stock product has quantity 0
zero_quant = inventory.stock_quant_ids.filtered(
lambda q: q.product_id == self.product_without_stock
)
self.assertEqual(zero_quant.quantity, 0.0)
def test_inventory_manual_selection_with_exhausted_flag(self):
"""Test manual product selection with exhausted products flag"""
inventory = self.env["stock.inventory"].create(
{
"name": "Test Manual Selection",
"location_ids": [(6, 0, [self.location.id])],
"product_selection": "manual",
"product_ids": [(6, 0, [self.product_without_stock.id])],
"include_exhausted_products": True,
}
)
inventory.action_start()
# Should have quant for the selected product even if it has zero stock
self.assertTrue(
any(
q.product_id == self.product_without_stock
for q in inventory.stock_quant_ids
)
)
zero_quant = inventory.stock_quant_ids.filtered(
lambda q: q.product_id == self.product_without_stock
)
self.assertEqual(zero_quant.quantity, 0.0)
def test_inventory_category_selection_with_exhausted_flag(self):
"""Test category selection with exhausted products flag"""
# Create a specific category
test_category = self.env["product.category"].create({"name": "Test Category"})
# Create product in this category
product_in_category = self.env["product.product"].create(
{
"name": "Product In Category",
"type": "product",
"categ_id": test_category.id,
}
)
inventory = self.env["stock.inventory"].create(
{
"name": "Test Category Selection",
"location_ids": [(6, 0, [self.location.id])],
"product_selection": "category",
"category_id": test_category.id,
"include_exhausted_products": True,
}
)
inventory.action_start()
# Should have quant for the product in category even if it has zero stock
self.assertTrue(
any(q.product_id == product_in_category for q in inventory.stock_quant_ids)
)
def test_create_zero_quants_only_for_product_type(self):
"""Test that zero quants are only created for products with type 'product'"""
# Create a service product
service_product = self.env["product.product"].create(
{
"name": "Service Product",
"type": "service",
}
)
inventory = self.env["stock.inventory"].create(
{
"name": "Test Service Product",
"location_ids": [(6, 0, [self.location.id])],
"product_selection": "manual",
"product_ids": [(6, 0, [service_product.id])],
"include_exhausted_products": True,
}
)
inventory.action_start()
# Should not create quants for service products
self.assertFalse(
any(q.product_id == service_product for q in inventory.stock_quant_ids)
)
def test_no_duplicate_quants_created(self):
"""Test that no duplicate quants are created if they already exist"""
# Create a quant with zero quantity manually
existing_quant = self.env["stock.quant"].create(
{
"product_id": self.product_without_stock.id,
"location_id": self.location.id,
"quantity": 0.0,
}
)
inventory = self.env["stock.inventory"].create(
{
"name": "Test No Duplicates",
"location_ids": [(6, 0, [self.location.id])],
"product_selection": "manual",
"product_ids": [(6, 0, [self.product_without_stock.id])],
"include_exhausted_products": True,
}
)
inventory.action_start()
# Should use existing quant, not create a new one
quants_for_product = self.env["stock.quant"].search(
[
("product_id", "=", self.product_without_stock.id),
("location_id", "=", self.location.id),
]
)
self.assertEqual(len(quants_for_product), 1)
self.assertEqual(quants_for_product.id, existing_quant.id)
def test_field_default_value(self):
"""Test that include_exhausted_products field defaults to False"""
inventory = self.env["stock.inventory"].create(
{
"name": "Test Default Value",
"location_ids": [(6, 0, [self.location.id])],
}
)
self.assertFalse(inventory.include_exhausted_products)