mirror of
https://github.com/OCA/stock-logistics-warehouse.git
synced 2025-01-21 14:27:28 +02:00
[IMP] stock_available_unreserved: black, isort
This commit is contained in:
@@ -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",
|
||||
}
|
||||
|
||||
@@ -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)]
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user