[IMP] stock_available_unreserved: black, isort

This commit is contained in:
Lois Rilo
2019-12-20 12:36:36 +01:00
committed by sbejaoui
parent f9e1d04e1c
commit 6a843ff7ae
4 changed files with 297 additions and 269 deletions

View File

@@ -9,12 +9,7 @@
"author": "ForgeFlow, Odoo Community Association (OCA)",
"website": "https://github.com/OCA/stock-logistics-warehouse",
"category": "Warehouse Management",
"depends": [
"stock",
],
"data": [
"views/stock_quant_view.xml",
"views/product_view.xml",
],
"depends": ["stock"],
"data": ["views/stock_quant_view.xml", "views/product_view.xml"],
"license": "LGPL-3",
}

View File

@@ -3,73 +3,70 @@
# Copyright 2016 ForgeFlow S.L. (https://www.forgeflow.com)
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
from odoo import api, fields, models, _
from odoo import _, api, fields, models
from odoo.exceptions import UserError
from odoo.tools.float_utils import float_round
from odoo.addons import decimal_precision as dp
from odoo.addons.stock.models.product import OPERATORS
from odoo.tools.float_utils import float_round
from odoo.exceptions import UserError
UNIT = dp.get_precision('Product Unit of Measure')
UNIT = dp.get_precision("Product Unit of Measure")
class ProductTemplate(models.Model):
_inherit = "product.template"
qty_available_not_res = fields.Float(
string='Quantity On Hand Unreserved',
string="Quantity On Hand Unreserved",
digits=UNIT,
compute='_compute_product_available_not_res',
search='_search_quantity_unreserved',
compute="_compute_product_available_not_res",
search="_search_quantity_unreserved",
)
@api.multi
@api.depends('product_variant_ids.qty_available_not_res')
@api.depends("product_variant_ids.qty_available_not_res")
def _compute_product_available_not_res(self):
for tmpl in self:
if isinstance(tmpl.id, models.NewId):
continue
tmpl.qty_available_not_res = sum(
tmpl.mapped('product_variant_ids.qty_available_not_res')
tmpl.mapped("product_variant_ids.qty_available_not_res")
)
@api.multi
def action_open_quants_unreserved(self):
products_ids = self.mapped('product_variant_ids').ids
quants = self.env['stock.quant'].search([
('product_id', 'in', products_ids),
])
products_ids = self.mapped("product_variant_ids").ids
quants = self.env["stock.quant"].search([("product_id", "in", products_ids)])
quant_ids = quants.filtered(
lambda x: x.product_id.qty_available_not_res > 0
).ids
result = self.env.ref('stock.product_open_quants').read()[0]
result['domain'] = [('id', 'in', quant_ids)]
result['context'] = {
'search_default_locationgroup': 1,
'search_default_internal_loc': 1,
result = self.env.ref("stock.product_open_quants").read()[0]
result["domain"] = [("id", "in", quant_ids)]
result["context"] = {
"search_default_locationgroup": 1,
"search_default_internal_loc": 1,
}
return result
def _search_quantity_unreserved(self, operator, value):
domain = [('qty_available_not_res', operator, value)]
product_variant_ids = self.env['product.product'].search(domain)
return [('product_variant_ids', 'in', product_variant_ids.ids)]
domain = [("qty_available_not_res", operator, value)]
product_variant_ids = self.env["product.product"].search(domain)
return [("product_variant_ids", "in", product_variant_ids.ids)]
class ProductProduct(models.Model):
_inherit = 'product.product'
_inherit = "product.product"
qty_available_not_res = fields.Float(
string='Qty Available Not Reserved',
string="Qty Available Not Reserved",
digits=UNIT,
compute='_compute_qty_available_not_reserved',
compute="_compute_qty_available_not_reserved",
search="_search_quantity_unreserved",
)
@api.multi
def _prepare_domain_available_not_reserved(self):
domain_quant = [
('product_id', 'in', self.ids),
]
domain_quant = [("product_id", "in", self.ids)]
domain_quant_locations = self._get_domain_locations()[0]
domain_quant.extend(domain_quant_locations)
return domain_quant
@@ -80,45 +77,48 @@ class ProductProduct(models.Model):
res = {}
domain_quant = self._prepare_domain_available_not_reserved()
quants = self.env['stock.quant'].with_context(lang=False).read_group(
domain_quant,
['product_id', 'location_id', 'quantity', 'reserved_quantity'],
['product_id', 'location_id'],
lazy=False)
quants = (
self.env["stock.quant"]
.with_context(lang=False)
.read_group(
domain_quant,
["product_id", "location_id", "quantity", "reserved_quantity"],
["product_id", "location_id"],
lazy=False,
)
)
product_sums = {}
for quant in quants:
# create a dictionary with the total value per products
product_sums.setdefault(quant['product_id'][0], 0.)
product_sums[quant['product_id'][0]] += (
quant['quantity'] - quant['reserved_quantity']
product_sums.setdefault(quant["product_id"][0], 0.0)
product_sums[quant["product_id"][0]] += (
quant["quantity"] - quant["reserved_quantity"]
)
for product in self.with_context(prefetch_fields=False, lang=''):
for product in self.with_context(prefetch_fields=False, lang=""):
available_not_res = float_round(
product_sums.get(product.id, 0.0),
precision_rounding=product.uom_id.rounding
precision_rounding=product.uom_id.rounding,
)
res[product.id] = {
'qty_available_not_res': available_not_res,
}
res[product.id] = {"qty_available_not_res": available_not_res}
return res
@api.multi
@api.depends('stock_move_ids.product_qty', 'stock_move_ids.state')
@api.depends("stock_move_ids.product_qty", "stock_move_ids.state")
def _compute_qty_available_not_reserved(self):
res = self._compute_product_available_not_res_dict()
for prod in self:
qty = res[prod.id]['qty_available_not_res']
qty = res[prod.id]["qty_available_not_res"]
prod.qty_available_not_res = qty
return res
def _search_quantity_unreserved(self, operator, value):
if operator not in OPERATORS:
raise UserError(_('Invalid domain operator %s') % operator)
raise UserError(_("Invalid domain operator %s") % operator)
if not isinstance(value, (float, int)):
raise UserError(_('Invalid domain right operand %s') % value)
raise UserError(_("Invalid domain right operand %s") % value)
ids = []
for product in self.search([]):
if OPERATORS[operator](product.qty_available_not_res, value):
ids.append(product.id)
return [('id', 'in', ids)]
return [("id", "in", ids)]

View File

@@ -14,11 +14,10 @@ class StockQuant(models.Model):
store=True,
)
@api.depends('product_id', 'location_id', 'quantity', 'reserved_quantity')
@api.depends("product_id", "location_id", "quantity", "reserved_quantity")
def _compute_contains_unreserved(self):
for record in self:
available = record._get_available_quantity(
record.product_id,
record.location_id,
record.product_id, record.location_id
)
record.contains_unreserved = True if available > 0 else False

View File

@@ -12,107 +12,132 @@ class TestStockLogisticsWarehouse(SavepointCase):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.pickingObj = cls.env['stock.picking']
cls.productObj = cls.env['product.product']
cls.templateObj = cls.env['product.template']
cls.supplier_location = cls.env.ref('stock.stock_location_suppliers')
cls.stock_location = cls.env.ref('stock.stock_location_stock')
cls.customer_location = cls.env.ref('stock.stock_location_customers')
cls.uom_unit = cls.env.ref('uom.product_uom_unit')
cls.main_company = cls.env.ref('base.main_company')
cls.pickingObj = cls.env["stock.picking"]
cls.productObj = cls.env["product.product"]
cls.templateObj = cls.env["product.template"]
cls.supplier_location = cls.env.ref("stock.stock_location_suppliers")
cls.stock_location = cls.env.ref("stock.stock_location_stock")
cls.customer_location = cls.env.ref("stock.stock_location_customers")
cls.uom_unit = cls.env.ref("uom.product_uom_unit")
cls.main_company = cls.env.ref("base.main_company")
cls.bin_a = cls.env['stock.location'].create({
'usage': 'internal',
'name': 'Bin A',
'location_id': cls.stock_location.id,
'company_id': cls.main_company.id
})
cls.bin_a = cls.env["stock.location"].create(
{
"usage": "internal",
"name": "Bin A",
"location_id": cls.stock_location.id,
"company_id": cls.main_company.id,
}
)
cls.bin_b = cls.env['stock.location'].create({
'usage': 'internal',
'name': 'Bin B',
'location_id': cls.stock_location.id,
'company_id': cls.main_company.id
})
cls.bin_b = cls.env["stock.location"].create(
{
"usage": "internal",
"name": "Bin B",
"location_id": cls.stock_location.id,
"company_id": cls.main_company.id,
}
)
cls.env['stock.location']._parent_store_compute()
cls.env["stock.location"]._parent_store_compute()
# Create product template
cls.templateAB = cls.templateObj.create({
'name': 'templAB',
'uom_id': cls.uom_unit.id,
})
cls.templateAB = cls.templateObj.create(
{"name": "templAB", "uom_id": cls.uom_unit.id}
)
cls.productC = cls.templateAB.product_variant_ids
# Create product A and B
cls.productA = cls.productObj.create({
'name': 'product A',
'standard_price': 1,
'type': 'product',
'uom_id': cls.uom_unit.id,
'default_code': 'A',
'product_tmpl_id': cls.templateAB.id,
})
cls.productA = cls.productObj.create(
{
"name": "product A",
"standard_price": 1,
"type": "product",
"uom_id": cls.uom_unit.id,
"default_code": "A",
"product_tmpl_id": cls.templateAB.id,
}
)
cls.productB = cls.productObj.create({
'name': 'product B',
'standard_price': 1,
'type': 'product',
'uom_id': cls.uom_unit.id,
'default_code': 'B',
'product_tmpl_id': cls.templateAB.id,
})
cls.productB = cls.productObj.create(
{
"name": "product B",
"standard_price": 1,
"type": "product",
"uom_id": cls.uom_unit.id,
"default_code": "B",
"product_tmpl_id": cls.templateAB.id,
}
)
# Create a picking move from INCOMING to STOCK
cls.pickingInA = cls.pickingObj.create({
'picking_type_id': cls.env.ref('stock.picking_type_in').id,
'location_id': cls.supplier_location.id,
'location_dest_id': cls.stock_location.id,
'move_lines': [
(0, 0, {
'name': 'Test move',
'product_id': cls.productA.id,
'product_uom': cls.productA.uom_id.id,
'product_uom_qty': 2,
'quantity_done': 2,
'location_id': cls.supplier_location.id,
'location_dest_id': cls.stock_location.id,
})
]
})
cls.pickingInA = cls.pickingObj.create(
{
"picking_type_id": cls.env.ref("stock.picking_type_in").id,
"location_id": cls.supplier_location.id,
"location_dest_id": cls.stock_location.id,
"move_lines": [
(
0,
0,
{
"name": "Test move",
"product_id": cls.productA.id,
"product_uom": cls.productA.uom_id.id,
"product_uom_qty": 2,
"quantity_done": 2,
"location_id": cls.supplier_location.id,
"location_dest_id": cls.stock_location.id,
},
)
],
}
)
cls.pickingInB = cls.pickingObj.create({
'picking_type_id': cls.env.ref('stock.picking_type_in').id,
'location_id': cls.supplier_location.id,
'location_dest_id': cls.stock_location.id,
'move_lines': [
(0, 0, {
'name': 'Test move',
'product_id': cls.productB.id,
'product_uom': cls.productB.uom_id.id,
'product_uom_qty': 3,
'quantity_done': 3,
'location_id': cls.supplier_location.id,
'location_dest_id': cls.stock_location.id,
})
]
})
cls.pickingOutA = cls.pickingObj.create({
'picking_type_id': cls.env.ref('stock.picking_type_out').id,
'location_id': cls.stock_location.id,
'location_dest_id': cls.customer_location.id,
'move_lines': [
(0, 0, {
'name': 'Test move',
'product_id': cls.productB.id,
'product_uom': cls.productB.uom_id.id,
'product_uom_qty': 2,
'location_id': cls.stock_location.id,
'location_dest_id': cls.customer_location.id,
})
]
})
cls.pickingInB = cls.pickingObj.create(
{
"picking_type_id": cls.env.ref("stock.picking_type_in").id,
"location_id": cls.supplier_location.id,
"location_dest_id": cls.stock_location.id,
"move_lines": [
(
0,
0,
{
"name": "Test move",
"product_id": cls.productB.id,
"product_uom": cls.productB.uom_id.id,
"product_uom_qty": 3,
"quantity_done": 3,
"location_id": cls.supplier_location.id,
"location_dest_id": cls.stock_location.id,
},
)
],
}
)
cls.pickingOutA = cls.pickingObj.create(
{
"picking_type_id": cls.env.ref("stock.picking_type_out").id,
"location_id": cls.stock_location.id,
"location_dest_id": cls.customer_location.id,
"move_lines": [
(
0,
0,
{
"name": "Test move",
"product_id": cls.productB.id,
"product_uom": cls.productB.uom_id.id,
"product_uom_qty": 2,
"location_id": cls.stock_location.id,
"location_dest_id": cls.customer_location.id,
},
)
],
}
)
def compare_qty_available_not_res(self, product, value):
product.invalidate_cache()
@@ -161,38 +186,47 @@ class TestStockLogisticsWarehouse(SavepointCase):
self.templateAB.action_open_quants_unreserved()
def test_more_than_one_quant(self):
self.env['stock.quant'].create(
{'location_id': self.stock_location.id,
'company_id': self.main_company.id,
'product_id': self.productA.id,
'quantity': 10.0})
self.env['stock.quant'].create(
{'location_id': self.bin_a.id,
'company_id': self.main_company.id,
'product_id': self.productA.id,
'quantity': 10.0})
self.env['stock.quant'].create(
{'location_id': self.bin_b.id,
'company_id': self.main_company.id,
'product_id': self.productA.id,
'quantity': 60.0})
self.env["stock.quant"].create(
{
"location_id": self.stock_location.id,
"company_id": self.main_company.id,
"product_id": self.productA.id,
"quantity": 10.0,
}
)
self.env["stock.quant"].create(
{
"location_id": self.bin_a.id,
"company_id": self.main_company.id,
"product_id": self.productA.id,
"quantity": 10.0,
}
)
self.env["stock.quant"].create(
{
"location_id": self.bin_b.id,
"company_id": self.main_company.id,
"product_id": self.productA.id,
"quantity": 60.0,
}
)
self.compare_qty_available_not_res(self.productA, 80)
def check_variants_found_correctly(self, operator, value, expected):
domain = [('id', 'in', self.templateAB.product_variant_ids.ids)]
return self.check_found_correctly(self.env['product.product'],
domain, operator, value, expected)
domain = [("id", "in", self.templateAB.product_variant_ids.ids)]
return self.check_found_correctly(
self.env["product.product"], domain, operator, value, expected
)
def check_template_found_correctly(self, operator, value, expected):
# There may be other products already in the system: ignore those
domain = [('id', 'in', self.templateAB.ids)]
return self.check_found_correctly(self.env['product.template'],
domain, operator, value, expected)
domain = [("id", "in", self.templateAB.ids)]
return self.check_found_correctly(
self.env["product.template"], domain, operator, value, expected
)
def check_found_correctly(self, model, domain, operator, value, expected):
found = model.search(domain + [
('qty_available_not_res', operator, value)]
)
found = model.search(domain + [("qty_available_not_res", operator, value)])
if found != expected:
self.fail(
"Searching for products failed: search for unreserved "
@@ -210,132 +244,132 @@ class TestStockLogisticsWarehouse(SavepointCase):
a_and_b = self.productA + self.productB
b_and_c = self.productB + self.productC
a_and_c = self.productA + self.productC
no_variants = self.env['product.product']
no_template = self.env['product.template']
no_variants = self.env["product.product"]
no_template = self.env["product.template"]
# Start: one template with three variants.
# All variants have zero unreserved stock
self.check_variants_found_correctly('=', 0, all_variants)
self.check_variants_found_correctly('>=', 0, all_variants)
self.check_variants_found_correctly('<=', 0, all_variants)
self.check_variants_found_correctly('>', 0, no_variants)
self.check_variants_found_correctly('<', 0, no_variants)
self.check_variants_found_correctly('!=', 0, no_variants)
self.check_variants_found_correctly("=", 0, all_variants)
self.check_variants_found_correctly(">=", 0, all_variants)
self.check_variants_found_correctly("<=", 0, all_variants)
self.check_variants_found_correctly(">", 0, no_variants)
self.check_variants_found_correctly("<", 0, no_variants)
self.check_variants_found_correctly("!=", 0, no_variants)
self.check_template_found_correctly('=', 0, self.templateAB)
self.check_template_found_correctly('>=', 0, self.templateAB)
self.check_template_found_correctly('<=', 0, self.templateAB)
self.check_template_found_correctly('>', 0, no_template)
self.check_template_found_correctly('<', 0, no_template)
self.check_template_found_correctly('!=', 0, no_template)
self.check_template_found_correctly("=", 0, self.templateAB)
self.check_template_found_correctly(">=", 0, self.templateAB)
self.check_template_found_correctly("<=", 0, self.templateAB)
self.check_template_found_correctly(">", 0, no_template)
self.check_template_found_correctly("<", 0, no_template)
self.check_template_found_correctly("!=", 0, no_template)
self.pickingInA.action_confirm()
# All variants still have zero unreserved stock
self.check_variants_found_correctly('=', 0, all_variants)
self.check_variants_found_correctly('>=', 0, all_variants)
self.check_variants_found_correctly('<=', 0, all_variants)
self.check_variants_found_correctly('>', 0, no_variants)
self.check_variants_found_correctly('<', 0, no_variants)
self.check_variants_found_correctly('!=', 0, no_variants)
self.check_variants_found_correctly("=", 0, all_variants)
self.check_variants_found_correctly(">=", 0, all_variants)
self.check_variants_found_correctly("<=", 0, all_variants)
self.check_variants_found_correctly(">", 0, no_variants)
self.check_variants_found_correctly("<", 0, no_variants)
self.check_variants_found_correctly("!=", 0, no_variants)
self.check_template_found_correctly('=', 0, self.templateAB)
self.check_template_found_correctly('>=', 0, self.templateAB)
self.check_template_found_correctly('<=', 0, self.templateAB)
self.check_template_found_correctly('>', 0, no_template)
self.check_template_found_correctly('<', 0, no_template)
self.check_template_found_correctly('!=', 0, no_template)
self.check_template_found_correctly("=", 0, self.templateAB)
self.check_template_found_correctly(">=", 0, self.templateAB)
self.check_template_found_correctly("<=", 0, self.templateAB)
self.check_template_found_correctly(">", 0, no_template)
self.check_template_found_correctly("<", 0, no_template)
self.check_template_found_correctly("!=", 0, no_template)
self.pickingInA.action_assign()
# All variants still have zero unreserved stock
self.check_variants_found_correctly('=', 0, all_variants)
self.check_variants_found_correctly('>=', 0, all_variants)
self.check_variants_found_correctly('<=', 0, all_variants)
self.check_variants_found_correctly('>', 0, no_variants)
self.check_variants_found_correctly('<', 0, no_variants)
self.check_variants_found_correctly('!=', 0, no_variants)
self.check_variants_found_correctly("=", 0, all_variants)
self.check_variants_found_correctly(">=", 0, all_variants)
self.check_variants_found_correctly("<=", 0, all_variants)
self.check_variants_found_correctly(">", 0, no_variants)
self.check_variants_found_correctly("<", 0, no_variants)
self.check_variants_found_correctly("!=", 0, no_variants)
self.check_template_found_correctly('=', 0, self.templateAB)
self.check_template_found_correctly('>=', 0, self.templateAB)
self.check_template_found_correctly('<=', 0, self.templateAB)
self.check_template_found_correctly('>', 0, no_template)
self.check_template_found_correctly('<', 0, no_template)
self.check_template_found_correctly('!=', 0, no_template)
self.check_template_found_correctly("=", 0, self.templateAB)
self.check_template_found_correctly(">=", 0, self.templateAB)
self.check_template_found_correctly("<=", 0, self.templateAB)
self.check_template_found_correctly(">", 0, no_template)
self.check_template_found_correctly("<", 0, no_template)
self.check_template_found_correctly("!=", 0, no_template)
self.pickingInA.button_validate()
# product A has 2 unreserved stock, other variants have 0
self.check_variants_found_correctly('=', 2, self.productA)
self.check_variants_found_correctly('=', 0, b_and_c)
self.check_variants_found_correctly('>', 0, self.productA)
self.check_variants_found_correctly('<', 0, no_variants)
self.check_variants_found_correctly('!=', 0, self.productA)
self.check_variants_found_correctly('!=', 1, all_variants)
self.check_variants_found_correctly('!=', 2, b_and_c)
self.check_variants_found_correctly('<=', 0, b_and_c)
self.check_variants_found_correctly('<=', 1, b_and_c)
self.check_variants_found_correctly('>=', 0, all_variants)
self.check_variants_found_correctly('>=', 1, self.productA)
self.check_variants_found_correctly("=", 2, self.productA)
self.check_variants_found_correctly("=", 0, b_and_c)
self.check_variants_found_correctly(">", 0, self.productA)
self.check_variants_found_correctly("<", 0, no_variants)
self.check_variants_found_correctly("!=", 0, self.productA)
self.check_variants_found_correctly("!=", 1, all_variants)
self.check_variants_found_correctly("!=", 2, b_and_c)
self.check_variants_found_correctly("<=", 0, b_and_c)
self.check_variants_found_correctly("<=", 1, b_and_c)
self.check_variants_found_correctly(">=", 0, all_variants)
self.check_variants_found_correctly(">=", 1, self.productA)
self.check_template_found_correctly('=', 0, self.templateAB)
self.check_template_found_correctly('=', 1, no_template)
self.check_template_found_correctly('=', 2, self.templateAB)
self.check_template_found_correctly('!=', 0, self.templateAB)
self.check_template_found_correctly('!=', 1, self.templateAB)
self.check_template_found_correctly('!=', 2, self.templateAB)
self.check_template_found_correctly('>', -1, self.templateAB)
self.check_template_found_correctly('>', 0, self.templateAB)
self.check_template_found_correctly('>', 1, self.templateAB)
self.check_template_found_correctly('>', 2, no_template)
self.check_template_found_correctly('<', 3, self.templateAB)
self.check_template_found_correctly('<', 2, self.templateAB)
self.check_template_found_correctly('<', 1, self.templateAB)
self.check_template_found_correctly('<', 0, no_template)
self.check_template_found_correctly('>=', 0, self.templateAB)
self.check_template_found_correctly('>=', 1, self.templateAB)
self.check_template_found_correctly('>=', 2, self.templateAB)
self.check_template_found_correctly('>=', 3, no_template)
self.check_template_found_correctly('<=', 3, self.templateAB)
self.check_template_found_correctly('<=', 2, self.templateAB)
self.check_template_found_correctly('<=', 1, self.templateAB)
self.check_template_found_correctly('<=', 0, self.templateAB)
self.check_template_found_correctly('<=', -1, no_template)
self.check_template_found_correctly("=", 0, self.templateAB)
self.check_template_found_correctly("=", 1, no_template)
self.check_template_found_correctly("=", 2, self.templateAB)
self.check_template_found_correctly("!=", 0, self.templateAB)
self.check_template_found_correctly("!=", 1, self.templateAB)
self.check_template_found_correctly("!=", 2, self.templateAB)
self.check_template_found_correctly(">", -1, self.templateAB)
self.check_template_found_correctly(">", 0, self.templateAB)
self.check_template_found_correctly(">", 1, self.templateAB)
self.check_template_found_correctly(">", 2, no_template)
self.check_template_found_correctly("<", 3, self.templateAB)
self.check_template_found_correctly("<", 2, self.templateAB)
self.check_template_found_correctly("<", 1, self.templateAB)
self.check_template_found_correctly("<", 0, no_template)
self.check_template_found_correctly(">=", 0, self.templateAB)
self.check_template_found_correctly(">=", 1, self.templateAB)
self.check_template_found_correctly(">=", 2, self.templateAB)
self.check_template_found_correctly(">=", 3, no_template)
self.check_template_found_correctly("<=", 3, self.templateAB)
self.check_template_found_correctly("<=", 2, self.templateAB)
self.check_template_found_correctly("<=", 1, self.templateAB)
self.check_template_found_correctly("<=", 0, self.templateAB)
self.check_template_found_correctly("<=", -1, no_template)
self.pickingInB.action_done()
# product A has 2 unreserved, product B has 3 unreserved and
# the remaining variant has 0
self.check_variants_found_correctly('=', 2, self.productA)
self.check_variants_found_correctly('=', 3, self.productB)
self.check_variants_found_correctly('=', 0, self.productC)
self.check_variants_found_correctly('>', 0, a_and_b)
self.check_variants_found_correctly('<', 0, no_variants)
self.check_variants_found_correctly('!=', 0, a_and_b)
self.check_variants_found_correctly('!=', 1, all_variants)
self.check_variants_found_correctly('!=', 2, b_and_c)
self.check_variants_found_correctly('!=', 3, a_and_c)
self.check_variants_found_correctly('<=', 0, self.productC)
self.check_variants_found_correctly('<=', 1, self.productC)
self.check_variants_found_correctly('>=', 0, all_variants)
self.check_variants_found_correctly('>=', 1, a_and_b)
self.check_variants_found_correctly('>=', 2, a_and_b)
self.check_variants_found_correctly('>=', 3, self.productB)
self.check_variants_found_correctly('>=', 4, no_variants)
self.check_variants_found_correctly("=", 2, self.productA)
self.check_variants_found_correctly("=", 3, self.productB)
self.check_variants_found_correctly("=", 0, self.productC)
self.check_variants_found_correctly(">", 0, a_and_b)
self.check_variants_found_correctly("<", 0, no_variants)
self.check_variants_found_correctly("!=", 0, a_and_b)
self.check_variants_found_correctly("!=", 1, all_variants)
self.check_variants_found_correctly("!=", 2, b_and_c)
self.check_variants_found_correctly("!=", 3, a_and_c)
self.check_variants_found_correctly("<=", 0, self.productC)
self.check_variants_found_correctly("<=", 1, self.productC)
self.check_variants_found_correctly(">=", 0, all_variants)
self.check_variants_found_correctly(">=", 1, a_and_b)
self.check_variants_found_correctly(">=", 2, a_and_b)
self.check_variants_found_correctly(">=", 3, self.productB)
self.check_variants_found_correctly(">=", 4, no_variants)
self.check_template_found_correctly('=', 0, self.templateAB)
self.check_template_found_correctly('=', 1, no_template)
self.check_template_found_correctly('=', 2, self.templateAB)
self.check_template_found_correctly('=', 3, self.templateAB)
self.check_template_found_correctly('!=', 0, self.templateAB)
self.check_template_found_correctly('!=', 2, self.templateAB)
self.check_template_found_correctly('!=', 3, self.templateAB)
self.check_template_found_correctly('>', 1, self.templateAB)
self.check_template_found_correctly('>', 2, self.templateAB)
self.check_template_found_correctly("=", 0, self.templateAB)
self.check_template_found_correctly("=", 1, no_template)
self.check_template_found_correctly("=", 2, self.templateAB)
self.check_template_found_correctly("=", 3, self.templateAB)
self.check_template_found_correctly("!=", 0, self.templateAB)
self.check_template_found_correctly("!=", 2, self.templateAB)
self.check_template_found_correctly("!=", 3, self.templateAB)
self.check_template_found_correctly(">", 1, self.templateAB)
self.check_template_found_correctly(">", 2, self.templateAB)
# This part may seem a bit unintuitive, but this is the
# way it works in the Odoo core
# Searches are "deferred" to the variants, so while the template says
# it has a stock of 5, searching for a stock greater than 3 will not
# find anything because no singular variant has a higher stock
self.check_template_found_correctly('>', 3, no_template)
self.check_template_found_correctly('<', 3, self.templateAB)
self.check_template_found_correctly('<', 2, self.templateAB)
self.check_template_found_correctly('<', 1, self.templateAB)
self.check_template_found_correctly('<', 0, no_template)
self.check_template_found_correctly(">", 3, no_template)
self.check_template_found_correctly("<", 3, self.templateAB)
self.check_template_found_correctly("<", 2, self.templateAB)
self.check_template_found_correctly("<", 1, self.templateAB)
self.check_template_found_correctly("<", 0, no_template)