Skip to content

Ordering constraints

Rules that turn requested orders into feasible ones. Guide: Ordering constraints.

OrderingConstraints

OrderingConstraints(
    constraints: Sequence[OrderingConstraint],
)

Bases: OrderingConstraint

An ordered sequence of constraints, passed to the engine as order_constraints.

Each constraint is applied to the result of the previous one. The final order is then checked against every constraint; if one rule's adjustment breaks another, the run stops with a message naming the SKU and the rule.

Parameters:

Name Type Description Default
constraints Sequence[OrderingConstraint]

One or more OrderingConstraint objects with unique names.

required
Example
OrderingConstraints([
    MinimumOrderQuantity(12, mode="adjust"),
    OrderMultiple(6, mode="adjust"),
])

to_manifest

to_manifest() -> dict

Describe the sequence for the run manifest.

OrderingConstraint

Bases: ABC

Base class for one operational ordering rule.

Subclass it, set a unique name, and implement apply. Override validate to check the final order after the whole sequence has run, and to_manifest to record the rule's settings. Constraints run after order callbacks and before the order is placed, in the order they are listed in OrderingConstraints.

reset

reset(context: ConstraintContext) -> None

Reset run-local state before a run. Stateless rules need nothing.

apply abstractmethod

apply(
    order: OrderDecision, context: ConstraintContext
) -> ConstraintResult

Apply the rule to an order.

Parameters:

Name Type Description Default
order OrderDecision

The order after callbacks and earlier constraints.

required
context ConstraintContext

The state before demand, the policy, and the decision period.

required

Returns:

Type Description
ConstraintResult

A ConstraintResult with the new order and one audit row per SKU.

validate

validate(
    order: OrderDecision, context: ConstraintContext
) -> None

Check the final order after every constraint has run.

The base implementation checks the order's shape (known SKUs, finite, non-negative quantities). Raise ValueError if the final order breaks this rule.

to_manifest

to_manifest() -> dict

Describe the rule for the run manifest.

Returns:

Type Description
dict

A JSON-serialisable dict.

MinimumOrderQuantity

MinimumOrderQuantity(values, *, mode: str = 'raise')

Bases: _PerSkuConstraint

Positive orders must be at least a minimum quantity.

With mode="adjust", a positive order below the minimum is raised to it. Zero orders are always allowed.

Parameters:

Name Type Description Default
values

One number for all SKUs, or a dict with exactly one value per SKU.

required
mode str

"raise" (default) stops the run when an order breaks the rule; "adjust" changes the order to satisfy it.

'raise'

OrderMultiple

OrderMultiple(values, *, mode: str = 'raise')

Bases: _PerSkuConstraint

Positive orders must be whole multiples, for example of a case size.

With mode="adjust", orders are rounded up to the next multiple.

Parameters:

Name Type Description Default
values

One number for all SKUs, or a dict with exactly one value per SKU. Values must be > 0.

required
mode str

"raise" (default) stops the run when an order breaks the rule; "adjust" changes the order to satisfy it.

'raise'

MaximumOrderQuantity

MaximumOrderQuantity(values, *, mode: str = 'raise')

Bases: _PerSkuConstraint

Orders may not exceed a maximum quantity.

With mode="adjust", larger orders are cut to the maximum and the event table's capacity_violation_flag is set.

Parameters:

Name Type Description Default
values

One number for all SKUs, or a dict with exactly one value per SKU.

required
mode str

"raise" (default) stops the run when an order breaks the rule; "adjust" changes the order to satisfy it.

'raise'

ShelfSpaceLimit

ShelfSpaceLimit(values, *, mode: str = 'raise')

Bases: _PerSkuConstraint

On-hand stock plus pipeline plus the new order may not exceed a capacity.

The free space is max(0, capacity - (on_hand + on_order)). With mode="adjust", larger orders are cut to it and the event table's capacity_violation_flag is set.

Parameters:

Name Type Description Default
values

One number for all SKUs, or a dict with exactly one value per SKU.

required
mode str

"raise" (default) stops the run when an order breaks the rule; "adjust" changes the order to satisfy it.

'raise'

ConstraintContext dataclass

ConstraintContext(
    inventory: InventoryStateDataFrame,
    policy: object | None,
    decision_period: int,
)

Information given to a constraint at one decision.

Attributes:

Name Type Description
inventory InventoryStateDataFrame

The InventoryStateDataFrame before demand. In an engine run it is a copy: a constraint changes the order, never the stock.

policy object | None

The policy that proposed the order (a copy in an engine run).

decision_period int

The state period of the decision.

ConstraintResult dataclass

ConstraintResult(order: OrderDecision, audit: DataFrame)

What a constraint returns: the new order and its audit rows.

Attributes:

Name Type Description
order OrderDecision

The constrained OrderDecision.

audit DataFrame

One row per SKU with unique_id, requested_order_quantity, constrained_order_quantity, constraint_adjustment_units, constraint_binding_flag, capacity_violation_flag and binding_constraints.