Skip to content

Commit

Permalink
[FIX] stock_reserve_rule: Module flow is updated.
Browse files Browse the repository at this point in the history
  • Loading branch information
geomer198 committed Oct 11, 2023
1 parent e591d33 commit 5474662
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 263 deletions.
130 changes: 69 additions & 61 deletions stock_reserve_rule/models/stock_reserve_rule.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,30 +154,60 @@ class StockReserveRuleRemoval(models.Model):
"When empty, any packaging can be removed.",
)

reserve_lot = fields.Selection(
selection=[
("lot_qty_eq_requested_qty", "Lot qty = requested qty"),
("lot_qty_gt_requested_qty", "Lot qty > requested qty"),
("lot_qty_lt_requested_qty", "Lot qty < requested qty"),
],
string="Requested lot if",
TOLERANCE_LIMIT = [
("upper_limit", "Upper Limit"),
("lower_limit", "Lower Limit"),
]

tolerance_requested_limit = fields.Selection(
selection=TOLERANCE_LIMIT,
string="Tolerance on",
)

tolerance_margin = fields.Selection(
tolerance_requested_computation = fields.Selection(
selection=[
("percentage", "Percentage (%)"),
("absolute", "Absolute Value"),
],
string="Tolerance computation",
)

tolerance_upper_limit = fields.Float(string="Tolerance (upper limit)")
tolerance_lower_limit = fields.Float(string="Tolerance (lower limit)")
tolerance_requested_value = fields.Float(string="Tolerance value", default=0.0)

tolerance_display = fields.Char(
compute="_compute_tolerance_display", store=True, stirng="Tolerance"
)

@api.onchange("tolerance_upper_limit", "tolerance_lower_limit")
@api.depends(
"tolerance_requested_limit",
"tolerance_requested_computation",
"tolerance_requested_value",
)
def _compute_tolerance_display(self):
for rec in self:
tolerance_on = rec.tolerance_requested_limit
tolerance_computation = rec.tolerance_requested_computation
if not tolerance_computation or not tolerance_on:
rec.tolerance_display = ""
continue
value = rec.tolerance_requested_value
if value == 0.0:
rec.tolerance_display = "Requested Qty = Lot Qty"
continue
limit = "-" if tolerance_on == "lower_limit" else ""
computation = "%" if tolerance_computation == "percentage" else ""
tolerance_on_dict = dict(self.TOLERANCE_LIMIT)
rec.tolerance_display = "{} ({}{}{})".format(
tolerance_on_dict.get(tolerance_on), limit, value, computation
)

@api.onchange("tolerance_requested_value")
def _onchange_tolerance_limit(self):
if self.tolerance_lower_limit < 0.0 or self.tolerance_upper_limit < 0.0:
if self.tolerance_requested_value < 0.0:
raise models.UserError(
_("Tolerance Limit must be more than or equal to 0.0")
_(
"Tolerance from requested qty value must be more than or equal to 0.0"
)
)

@api.constrains("location_id")
Expand Down Expand Up @@ -327,61 +357,39 @@ def is_greater_eq(value, other):

@api.model
def _get_requested_comparisons(self, rounding):
lower_limit = self.tolerance_lower_limit
upper_limit = self.tolerance_upper_limit
requested_eq = {
"lot_qty_eq_requested_qty": lambda lot_qty, need_qty: lot_qty == need_qty
}
if self.tolerance_margin == "percentage":
upper_limit_percent = (100 + upper_limit) / 100
lower_limit_percent = (100 - lower_limit) / 100
return {
# need_qty + rounding < lot_qty <=
# need_qty * ((100 + tolerance_upper_limit) / 100)
"lot_qty_gt_requested_qty": lambda lot, n: n + rounding
< lot
<= n * upper_limit_percent
if upper_limit > 0.0
else lot > n,
# need_qty * ((100 - tolerance_lower_limit) / 100) <=
# lot_qty < need_qty - rounding
"lot_qty_lt_requested_qty": lambda lot, n: n * lower_limit_percent
<= lot
< n - rounding
if lower_limit > 0.0
else lot < n,
**requested_eq,
}
elif self.tolerance_margin == "absolute":
return {
# need_qty + rounding < lot_qty =< need_qty + tolerance_upper_limit
"lot_qty_gt_requested_qty": lambda lot, n: n + rounding
< lot
<= n + upper_limit
if upper_limit > 0.0
else lot > n,
# need_qty - tolerance_lower_limit <= lot_qty < need_qty - rounding
"lot_qty_lt_requested_qty": lambda lot, n: n - lower_limit
<= lot
< n - rounding
if lower_limit > 0.0
else lot < n,
**requested_eq,
}
# Default Behavior
return {
"lot_qty_gt_requested_qty": lambda lot_qty, need_qty: lot_qty > need_qty,
"lot_qty_lt_requested_qty": lambda lot_qty, need_qty: lot_qty < need_qty,
**requested_eq,
}
value = self.tolerance_requested_value
if value == 0.0:
return lambda product_qty, need: product_qty == need
computation = self.tolerance_requested_computation
if self.tolerance_requested_limit == "upper_limit":

def wrap(product_qty, need):
if computation == "percentage":
return need + rounding < product_qty <= need * (100 + value) / 100
# computation == "absolute"
else:
return need + rounding < product_qty <= need + value

return wrap

if self.tolerance_requested_limit == "lower_limit":

def wrap(product_qty, need):

Check warning on line 377 in stock_reserve_rule/models/stock_reserve_rule.py

View check run for this annotation

Codecov / codecov/patch

stock_reserve_rule/models/stock_reserve_rule.py#L377

Added line #L377 was not covered by tests
if computation == "percentage":
return need * (100 - value) / 100 <= product_qty < need - rounding

Check warning on line 379 in stock_reserve_rule/models/stock_reserve_rule.py

View check run for this annotation

Codecov / codecov/patch

stock_reserve_rule/models/stock_reserve_rule.py#L379

Added line #L379 was not covered by tests
# computation == "absolute"
else:
return need - value <= product_qty < need - rounding

Check warning on line 382 in stock_reserve_rule/models/stock_reserve_rule.py

View check run for this annotation

Codecov / codecov/patch

stock_reserve_rule/models/stock_reserve_rule.py#L382

Added line #L382 was not covered by tests

return wrap

Check warning on line 384 in stock_reserve_rule/models/stock_reserve_rule.py

View check run for this annotation

Codecov / codecov/patch

stock_reserve_rule/models/stock_reserve_rule.py#L384

Added line #L384 was not covered by tests

def _apply_strategy_single_lot(self, quants):
need = yield
# We take goods only if we empty the bin.
# The original ordering (fefo, fifo, ...) must be kept.
product = fields.first(quants).product_id
rounding = product.uom_id.rounding
comparison = self._get_requested_comparisons(rounding).get(self.reserve_lot)
comparison = self._get_requested_comparisons(rounding)
if product.tracking == "lot" or comparison is not None:
for location, location_quants in quants._group_by_location():
grouped_quants = self.env["stock.quant"].read_group(
Expand Down
Loading

0 comments on commit 5474662

Please sign in to comment.