[IMP] stock_cycle_count: preformance improvements

This commit is contained in:
ArnauCForgeFlow
2024-06-12 11:12:48 +02:00
parent afeda527d8
commit c027a0cb56
7 changed files with 252 additions and 245 deletions

View File

@@ -84,20 +84,23 @@ class StockCycleCount(models.Model):
"responsible_id": self.responsible_id.id,
}
@api.model
def create(self, vals):
vals["name"] = self.env["ir.sequence"].next_by_code("stock.cycle.count") or ""
return super(StockCycleCount, self).create(vals)
@api.model_create_multi
def create(self, vals_list):
for vals in vals_list:
vals["name"] = (
self.env["ir.sequence"].next_by_code("stock.cycle.count") or ""
)
return super().create(vals_list)
def action_create_inventory_adjustment(self):
if any([s != "draft" for s in self.mapped("state")]):
if any([state != "draft" for state in self.mapped("state")]):
raise UserError(_("You can only confirm cycle counts in state 'Planned'."))
for rec in self:
data = rec._prepare_inventory_adjustment()
inv = self.env["stock.inventory"].create(data)
if self.company_id.auto_start_inventory_from_cycle_count:
if rec.company_id.auto_start_inventory_from_cycle_count:
inv.prefill_counted_quantity = (
self.company_id.inventory_adjustment_counted_quantities
rec.company_id.inventory_adjustment_counted_quantities
)
inv.action_state_to_in_progress()
if inv.prefill_counted_quantity == "zero":
@@ -109,9 +112,9 @@ class StockCycleCount(models.Model):
return True
def action_view_inventory(self):
action = self.env.ref(
action = self.env["ir.actions.act_window"]._for_xml_id(
"stock_inventory.action_view_inventory_group_form"
).read()[0]
)
action["context"] = {}
adjustment_ids = self.mapped("stock_adjustment_ids").ids
if len(adjustment_ids) > 1:

View File

@@ -12,6 +12,47 @@ class StockCycleCountRule(models.Model):
_name = "stock.cycle.count.rule"
_description = "Stock Cycle Counts Rules"
name = fields.Char(required=True)
rule_type = fields.Selection(
selection="_selection_rule_types", string="Type of rule", required=True
)
rule_description = fields.Char(compute="_compute_rule_description")
active = fields.Boolean(default=True)
periodic_qty_per_period = fields.Integer(string="Counts per period", default=1)
periodic_count_period = fields.Integer(string="Period in days")
turnover_inventory_value_threshold = fields.Float()
currency_id = fields.Many2one(
comodel_name="res.currency", string="Currency", compute="_compute_currency_id"
)
accuracy_threshold = fields.Float(
string="Minimum Accuracy Threshold", digits=(3, 2)
)
apply_in = fields.Selection(
string="Apply this rule in:",
selection=[
("warehouse", "Selected warehouses"),
("location", "Selected Location Zones."),
],
default="warehouse",
)
warehouse_ids = fields.Many2many(
comodel_name="stock.warehouse",
relation="warehouse_cycle_count_rule_rel",
column1="rule_id",
column2="warehouse_id",
string="Warehouses where applied",
compute="_compute_warehouse_ids",
store=True,
readonly=False,
)
location_ids = fields.Many2many(
comodel_name="stock.location",
relation="location_cycle_count_rule_rel",
column1="rule_id",
column2="location_id",
string="Zones where applied",
)
def _compute_currency_id(self):
for rec in self:
rec.currency_id = self.env.user.company_id.currency_id
@@ -94,53 +135,15 @@ class StockCycleCountRule(models.Model):
if rec.periodic_count_period < 0:
raise ValidationError(_("You cannot define a negative period."))
@api.onchange("location_ids")
def _onchange_locaton_ids(self):
"""Get the warehouses for the selected locations."""
wh_ids = []
for loc in self.location_ids:
wh_ids.append(loc.warehouse_id.id)
wh_ids = list(set(wh_ids))
wh_ids = [wh for wh in wh_ids if wh]
self.warehouse_ids = self.env["stock.warehouse"].browse(wh_ids)
name = fields.Char(required=True)
rule_type = fields.Selection(
selection="_selection_rule_types", string="Type of rule", required=True
)
rule_description = fields.Char(compute="_compute_rule_description")
active = fields.Boolean(default=True)
periodic_qty_per_period = fields.Integer(string="Counts per period", default=1)
periodic_count_period = fields.Integer(string="Period in days")
turnover_inventory_value_threshold = fields.Float()
currency_id = fields.Many2one(
comodel_name="res.currency", string="Currency", compute="_compute_currency_id"
)
accuracy_threshold = fields.Float(
string="Minimum Accuracy Threshold", digits=(3, 2)
)
apply_in = fields.Selection(
string="Apply this rule in:",
selection=[
("warehouse", "Selected warehouses"),
("location", "Selected Location Zones."),
],
default="warehouse",
)
warehouse_ids = fields.Many2many(
comodel_name="stock.warehouse",
relation="warehouse_cycle_count_rule_rel",
column1="rule_id",
column2="warehouse_id",
string="Warehouses where applied",
)
location_ids = fields.Many2many(
comodel_name="stock.location",
relation="location_cycle_count_rule_rel",
column1="rule_id",
column2="location_id",
string="Zones where applied",
)
@api.depends("location_ids")
def _compute_warehouse_ids(self):
for record in self:
wh_ids = []
for loc in record.location_ids:
if loc.warehouse_id: # Make sure warehouse_id is set
wh_ids.append(loc.warehouse_id.id)
wh_ids = list(set(wh_ids)) # Remove duplicates
record.warehouse_ids = [(6, 0, wh_ids)]
def compute_rule(self, locs):
if self.rule_type == "periodic":
@@ -184,7 +187,7 @@ class StockCycleCountRule(models.Model):
) + timedelta(days=period)
if next_date < datetime.today():
next_date = datetime.today()
except Exception as e:
except AttributeError as e:
raise UserError(
_(
"Error found determining the frequency of periodic "
@@ -220,35 +223,36 @@ class StockCycleCountRule(models.Model):
@api.model
def _compute_rule_turnover(self, locs):
cycle_counts = []
location_ids = locs.mapped("id")
inventories = self.env["stock.inventory"].search(
[
("location_ids", "in", location_ids),
("state", "in", ["confirm", "done", "draft"]),
]
)
inventory_dates_by_location = {loc.id: [] for loc in locs}
for inventory in inventories:
for location in inventory.location_ids:
if location.id in inventory_dates_by_location:
inventory_dates_by_location[location.id].append(inventory.date)
for loc in locs:
last_inventories = (
self.env["stock.inventory"]
.search(
[
("location_ids", "in", [loc.id]),
("state", "in", ["confirm", "done", "draft"]),
]
)
.mapped("date")
)
last_inventories = inventory_dates_by_location.get(loc.id, [])
if last_inventories:
latest_inventory = sorted(last_inventories, reverse=True)[0]
moves = self._get_turnover_moves(loc, latest_inventory)
if moves:
total_turnover = 0.0
for m in moves:
turnover = self._compute_turnover(m)
total_turnover += turnover
total_turnover = sum(self._compute_turnover(m) for m in moves)
try:
if total_turnover > self.turnover_inventory_value_threshold:
next_date = datetime.today()
cycle_count = self._propose_cycle_count(next_date, loc)
cycle_counts.append(cycle_count)
except Exception as e:
except AttributeError as e:
raise UserError(
_(
"Error found when comparing turnover with the "
"rule threshold. %s"
"Error found when comparing turnover "
"with the rule threshold. %s"
)
% str(e)
) from e

View File

@@ -11,20 +11,6 @@ PERCENT = 100.0
class StockInventory(models.Model):
_inherit = "stock.inventory"
@api.depends("state", "stock_quant_ids")
def _compute_inventory_accuracy(self):
for inv in self:
theoretical = sum(inv.stock_quant_ids.mapped(lambda x: abs(x.quantity)))
abs_discrepancy = sum(
inv.stock_quant_ids.mapped(lambda x: abs(x.inventory_diff_quantity))
)
if theoretical:
inv.inventory_accuracy = max(
PERCENT * (theoretical - abs_discrepancy) / theoretical, 0.0
)
if not inv.stock_quant_ids and inv.state == "done":
inv.inventory_accuracy = PERCENT
prefill_counted_quantity = fields.Selection(
string="Counted Quantities",
help="Allows to start with a pre-filled counted quantity for each lines or "
@@ -49,20 +35,19 @@ class StockInventory(models.Model):
group_operator="avg",
)
def _get_default_counted_quantitites(self):
company_id = self.env.context.get("default_company_id", self.env.company)
return company_id.inventory_adjustment_counted_quantities or "counted"
prefill_counted_quantity = fields.Selection(
string="Counted Quantities",
help="Allows to start with a pre-filled counted quantity for each lines or "
"with all counted quantities set to zero.",
default=_get_default_counted_quantitites,
selection=[
("counted", "Default to stock on hand"),
("zero", "Default to zero"),
],
)
@api.depends("state", "stock_quant_ids")
def _compute_inventory_accuracy(self):
for inv in self:
theoretical = sum(inv.stock_quant_ids.mapped(lambda x: abs(x.quantity)))
abs_discrepancy = sum(
inv.stock_quant_ids.mapped(lambda x: abs(x.inventory_diff_quantity))
)
if theoretical:
inv.inventory_accuracy = max(
PERCENT * (theoretical - abs_discrepancy) / theoretical, 0.0
)
if not inv.stock_quant_ids and inv.state == "done":
inv.inventory_accuracy = PERCENT
def _update_cycle_state(self):
for inv in self:
@@ -99,21 +84,22 @@ class StockInventory(models.Model):
return True
def action_state_to_done(self):
res = super(StockInventory, self).action_state_to_done()
res = super().action_state_to_done()
self._update_cycle_state()
return res
def action_force_done(self):
res = super(StockInventory, self).action_force_done()
res = super().action_force_done()
self._update_cycle_state()
return res
@api.model
def create(self, vals):
res = super().create(vals)
if not res.cycle_count_id:
res._link_to_planned_cycle_count()
return res
@api.model_create_multi
def create(self, vals_list):
inventories = super().create(vals_list)
for inv in inventories:
if not inv.cycle_count_id:
inv._link_to_planned_cycle_count()
return inventories
def _is_consistent_with_cycle_count(self):
self.ensure_one()
@@ -153,7 +139,9 @@ class StockInventory(models.Model):
if not is_consistent:
raise ValidationError(
_(
"The Inventory Adjustment is inconsistent with the Cycle Count:\n%s"
"The Inventory Adjustment is inconsistent "
"with the Cycle Count:\n%(message)s",
message=msg,
)
% msg
)

View File

@@ -21,28 +21,6 @@ except (ImportError, IOError) as err:
class StockLocation(models.Model):
_inherit = "stock.location"
def _compute_loc_accuracy(self):
for rec in self:
history = self.env["stock.inventory"].search(
[("location_ids", "in", rec.id), ("state", "=", "done")],
order="write_date desc",
)
if history:
wh = rec.warehouse_id
if (
wh.counts_for_accuracy_qty
and len(history) > wh.counts_for_accuracy_qty
):
rec.loc_accuracy = mean(
history[: wh.counts_for_accuracy_qty].mapped(
"inventory_accuracy"
)
)
else:
rec.loc_accuracy = mean(history.mapped("inventory_accuracy"))
else:
rec.loc_accuracy = 0
zero_confirmation_disabled = fields.Boolean(
string="Disable Zero Confirmations",
help="Define whether this location will trigger a zero-confirmation "
@@ -60,19 +38,46 @@ class StockLocation(models.Model):
string="Inventory Accuracy", compute="_compute_loc_accuracy", digits=(3, 2)
)
def _compute_loc_accuracy(self):
history = self.env["stock.inventory"].search(
[("location_ids", "in", self.ids), ("state", "=", "done")],
order="write_date desc",
)
for rec in self:
loc_history = history.filtered_domain([("location_ids", "in", rec.id)])
if loc_history:
wh = rec.warehouse_id
if (
wh.counts_for_accuracy_qty
and len(loc_history) > wh.counts_for_accuracy_qty
):
rec.loc_accuracy = mean(
loc_history[: wh.counts_for_accuracy_qty].mapped(
"inventory_accuracy"
)
)
else:
rec.loc_accuracy = mean(loc_history.mapped("inventory_accuracy"))
else:
rec.loc_accuracy = 0
def _get_zero_confirmation_domain(self):
self.ensure_one()
domain = [("location_id", "=", self.id), ("quantity", ">", 0.0)]
return domain
def check_zero_confirmation(self):
rule_model = self.env["stock.cycle.count.rule"]
warehouse_ids = self.mapped("warehouse_id.id")
zero_rules = rule_model.search(
[("rule_type", "=", "zero"), ("warehouse_ids", "in", warehouse_ids)]
)
warehouse_to_rules = {rule.warehouse_ids.id: rule for rule in zero_rules}
for rec in self:
if not rec.zero_confirmation_disabled:
wh = rec.warehouse_id
rule_model = self.env["stock.cycle.count.rule"]
zero_rule = rule_model.search(
[("rule_type", "=", "zero"), ("warehouse_ids", "=", wh.id)]
)
zero_rule = warehouse_to_rules.get(wh.id)
if zero_rule:
quants = self.env["stock.quant"].search(
rec._get_zero_confirmation_domain()

View File

@@ -41,7 +41,7 @@ class StockWarehouse(models.Model):
@api.model
def _get_cycle_count_locations_search_domain(self, parent):
domain = [
("parent_path", "=like", parent.parent_path + "%"),
("id", "child_of", parent.id),
("cycle_count_disabled", "=", False),
]
return domain
@@ -81,56 +81,62 @@ class StockWarehouse(models.Model):
returns a list with required dates for the cycle count of each
location"""
for rec in self:
proposed_cycle_counts = []
rules = rec._cycle_count_rules_to_compute()
for rule in rules:
locations = rec._search_cycle_count_locations(rule)
if locations:
proposed_cycle_counts.extend(rule.compute_rule(locations))
proposed_cycle_counts = rec._get_proposed_cycle_counts()
if proposed_cycle_counts:
locations = list({d["location"] for d in proposed_cycle_counts})
for loc in locations:
proposed_for_loc = list(
filter(lambda x: x["location"] == loc, proposed_cycle_counts)
)
earliest_date = min(d["date"] for d in proposed_for_loc)
cycle_count_proposed = list(
filter(lambda x: x["date"] == earliest_date, proposed_for_loc)
)[0]
domain = [("location_id", "=", loc.id), ("state", "in", ["draft"])]
existing_cycle_counts = self.env["stock.cycle.count"].search(domain)
if existing_cycle_counts:
existing_earliest_date = sorted(
existing_cycle_counts.mapped("date_deadline")
)[0]
existing_earliest_date = fields.Date.from_string(
existing_earliest_date
)
cycle_count_proposed_date = fields.Date.from_string(
cycle_count_proposed["date"]
)
if cycle_count_proposed_date < existing_earliest_date:
cc_to_update = existing_cycle_counts.search(
[("date_deadline", "=", existing_earliest_date)]
)
cc_to_update.write(
{
"date_deadline": cycle_count_proposed_date,
"cycle_count_rule_id": cycle_count_proposed[
"rule_type"
].id,
}
)
delta = (
fields.Datetime.from_string(cycle_count_proposed["date"])
- datetime.today()
)
if (
not existing_cycle_counts
and delta.days < rec.cycle_count_planning_horizon
):
cc_vals = self._prepare_cycle_count(cycle_count_proposed)
self.env["stock.cycle.count"].create(cc_vals)
cc_vals_list = rec._process_cycle_counts(proposed_cycle_counts)
self.env["stock.cycle.count"].create(cc_vals_list)
def _get_proposed_cycle_counts(self):
proposed_cycle_counts = []
rules = self._cycle_count_rules_to_compute()
for rule in rules:
locations = self._search_cycle_count_locations(rule)
if locations:
proposed_cycle_counts.extend(rule.compute_rule(locations))
return proposed_cycle_counts
def _process_cycle_counts(self, proposed_cycle_counts):
cc_vals_list = []
locations = list({d["location"] for d in proposed_cycle_counts})
for loc in locations:
proposed_for_loc = list(
filter(lambda x: x["location"] == loc, proposed_cycle_counts)
)
earliest_date = min(d["date"] for d in proposed_for_loc)
cycle_count_proposed = next(
filter(lambda x: x["date"] == earliest_date, proposed_for_loc)
)
self._handle_existing_cycle_counts(loc, cycle_count_proposed)
delta = (
fields.Datetime.from_string(cycle_count_proposed["date"])
- datetime.today()
)
if delta.days < self.cycle_count_planning_horizon:
cc_vals = self._prepare_cycle_count(cycle_count_proposed)
cc_vals_list.append(cc_vals)
return cc_vals_list
def _handle_existing_cycle_counts(self, location, cycle_count_proposed):
domain = [("location_id", "=", location.id), ("state", "in", ["draft"])]
existing_cycle_counts = self.env["stock.cycle.count"].search(domain)
if existing_cycle_counts:
existing_earliest_date = sorted(
existing_cycle_counts.mapped("date_deadline")
)[0]
existing_earliest_date = fields.Date.from_string(existing_earliest_date)
cycle_count_proposed_date = fields.Date.from_string(
cycle_count_proposed["date"]
)
if cycle_count_proposed_date < existing_earliest_date:
cc_to_update = existing_cycle_counts.filtered(
lambda x: x.date_deadline == existing_earliest_date
)
cc_to_update.write(
{
"date_deadline": cycle_count_proposed_date,
"cycle_count_rule_id": cycle_count_proposed["rule_type"].id,
}
)
@api.model
def cron_cycle_count(self):

View File

@@ -22,9 +22,11 @@ class LocationAccuracyReport(models.AbstractModel):
def _get_location_data(self, locations):
data = dict()
inventory_obj = self.env["stock.inventory"]
location_ids = locations.mapped("id")
counts = inventory_obj.search([("location_id", "in", location_ids)])
for loc in locations:
counts = inventory_obj.search(self._get_inventory_domain(loc.id))
data[loc] = counts
loc_counts = counts.filtered(lambda c: c.location_id == loc)
data[loc] = loc_counts
return data
def render_html(self, data=None):

View File

@@ -8,84 +8,80 @@ from odoo.tests import common
class TestStockCycleCount(common.TransactionCase):
def setUp(self):
super(TestStockCycleCount, self).setUp()
self.res_users_model = self.env["res.users"]
self.cycle_count_model = self.env["stock.cycle.count"]
self.stock_cycle_count_rule_model = self.env["stock.cycle.count.rule"]
self.inventory_model = self.env["stock.inventory"]
self.stock_location_model = self.env["stock.location"]
self.stock_move_model = self.env["stock.move"]
self.stock_warehouse_model = self.env["stock.warehouse"]
self.product_model = self.env["product.product"]
self.quant_model = self.env["stock.quant"]
self.move_model = self.env["stock.move"]
@classmethod
def setUpClass(cls):
super(TestStockCycleCount, cls).setUpClass()
cls.res_users_model = cls.env["res.users"]
cls.cycle_count_model = cls.env["stock.cycle.count"]
cls.stock_cycle_count_rule_model = cls.env["stock.cycle.count.rule"]
cls.inventory_model = cls.env["stock.inventory"]
cls.stock_location_model = cls.env["stock.location"]
cls.stock_move_model = cls.env["stock.move"]
cls.stock_warehouse_model = cls.env["stock.warehouse"]
cls.product_model = cls.env["product.product"]
cls.quant_model = cls.env["stock.quant"]
cls.move_model = cls.env["stock.move"]
self.company = self.env.ref("base.main_company")
self.partner = self.env.ref("base.res_partner_1")
self.g_stock_manager = self.env.ref("stock.group_stock_manager")
self.g_stock_user = self.env.ref("stock.group_stock_user")
cls.company = cls.env.ref("base.main_company")
cls.partner = cls.env.ref("base.res_partner_1")
cls.g_stock_manager = cls.env.ref("stock.group_stock_manager")
cls.g_stock_user = cls.env.ref("stock.group_stock_user")
# Create users:
self.manager = self._create_user(
"user_1", [self.g_stock_manager], self.company
).id
self.user = self._create_user("user_2", [self.g_stock_user], self.company).id
cls.manager = cls._create_user("user_1", [cls.g_stock_manager], cls.company).id
cls.user = cls._create_user("user_2", [cls.g_stock_user], cls.company).id
# Create warehouses:
self.big_wh = self.stock_warehouse_model.create(
cls.big_wh = cls.stock_warehouse_model.create(
{"name": "BIG", "code": "B", "cycle_count_planning_horizon": 30}
)
self.small_wh = self.stock_warehouse_model.create(
{"name": "SMALL", "code": "S"}
)
cls.small_wh = cls.stock_warehouse_model.create({"name": "SMALL", "code": "S"})
# Create rules:
self.rule_periodic = self._create_stock_cycle_count_rule_periodic(
self.manager, "rule_1", [2, 7]
cls.rule_periodic = cls._create_stock_cycle_count_rule_periodic(
cls.manager, "rule_1", [2, 7]
)
self.rule_turnover = self._create_stock_cycle_count_rule_turnover(
self.manager, "rule_2", [100]
cls.rule_turnover = cls._create_stock_cycle_count_rule_turnover(
cls.manager, "rule_2", [100]
)
self.rule_accuracy = self._create_stock_cycle_count_rule_accuracy(
self.manager, "rule_3", [5], self.big_wh.view_location_id.ids
)
self.zero_rule = self._create_stock_cycle_count_rule_zero(
self.manager, "rule_4"
cls.rule_accuracy = cls._create_stock_cycle_count_rule_accuracy(
cls.manager, "rule_3", [5], cls.big_wh.view_location_id.ids
)
cls.zero_rule = cls._create_stock_cycle_count_rule_zero(cls.manager, "rule_4")
# Configure warehouses:
self.rule_ids = [
self.rule_periodic.id,
self.rule_turnover.id,
self.rule_accuracy.id,
self.zero_rule.id,
cls.rule_ids = [
cls.rule_periodic.id,
cls.rule_turnover.id,
cls.rule_accuracy.id,
cls.zero_rule.id,
]
self.big_wh.write({"cycle_count_rule_ids": [(6, 0, self.rule_ids)]})
cls.big_wh.write({"cycle_count_rule_ids": [(6, 0, cls.rule_ids)]})
# Create a location:
self.count_loc = self.stock_location_model.create(
cls.count_loc = cls.stock_location_model.create(
{"name": "Place", "usage": "production"}
)
self.stock_location_model._parent_store_compute()
cls.stock_location_model._parent_store_compute()
# Create a cycle count:
self.cycle_count_1 = self.cycle_count_model.with_user(self.manager).create(
cls.cycle_count_1 = cls.cycle_count_model.with_user(cls.manager).create(
{
"name": "Test cycle count",
"cycle_count_rule_id": self.rule_periodic.id,
"location_id": self.count_loc.id,
"cycle_count_rule_id": cls.rule_periodic.id,
"location_id": cls.count_loc.id,
}
)
# Create a product:
self.product1 = self.product_model.create(
cls.product1 = cls.product_model.create(
{"name": "Test Product 1", "type": "product", "default_code": "PROD1"}
)
def _create_user(self, login, groups, company):
@classmethod
def _create_user(cls, login, groups, company):
group_ids = [group.id for group in groups]
user = self.res_users_model.create(
user = cls.res_users_model.create(
{
"name": login,
"login": login,
@@ -97,8 +93,9 @@ class TestStockCycleCount(common.TransactionCase):
)
return user
def _create_stock_cycle_count_rule_periodic(self, uid, name, values):
rule = self.stock_cycle_count_rule_model.with_user(uid).create(
@classmethod
def _create_stock_cycle_count_rule_periodic(cls, uid, name, values):
rule = cls.stock_cycle_count_rule_model.with_user(uid).create(
{
"name": name,
"rule_type": "periodic",
@@ -108,8 +105,9 @@ class TestStockCycleCount(common.TransactionCase):
)
return rule
def _create_stock_cycle_count_rule_turnover(self, uid, name, values):
rule = self.stock_cycle_count_rule_model.with_user(uid).create(
@classmethod
def _create_stock_cycle_count_rule_turnover(cls, uid, name, values):
rule = cls.stock_cycle_count_rule_model.with_user(uid).create(
{
"name": name,
"rule_type": "turnover",
@@ -118,8 +116,9 @@ class TestStockCycleCount(common.TransactionCase):
)
return rule
def _create_stock_cycle_count_rule_accuracy(self, uid, name, values, zone_ids):
rule = self.stock_cycle_count_rule_model.with_user(uid).create(
@classmethod
def _create_stock_cycle_count_rule_accuracy(cls, uid, name, values, zone_ids):
rule = cls.stock_cycle_count_rule_model.with_user(uid).create(
{
"name": name,
"rule_type": "accuracy",
@@ -130,8 +129,9 @@ class TestStockCycleCount(common.TransactionCase):
)
return rule
def _create_stock_cycle_count_rule_zero(self, uid, name):
rule = self.stock_cycle_count_rule_model.with_user(uid).create(
@classmethod
def _create_stock_cycle_count_rule_zero(cls, uid, name):
rule = cls.stock_cycle_count_rule_model.with_user(uid).create(
{"name": name, "rule_type": "zero"}
)
return rule
@@ -263,7 +263,6 @@ class TestStockCycleCount(common.TransactionCase):
for r in rules:
r._compute_rule_description()
self.assertTrue(r.rule_description, "No description provided")
self.rule_accuracy._onchange_locaton_ids()
self.assertEqual(
self.rule_accuracy.warehouse_ids.ids,
self.big_wh.ids,