Skip to content

[16.0][IMP] stock_location_orderpoint: decouple trigger from replenishment computation #84

Description

@lmignon

Context

The stock_location_orderpoint module allows defining replenishment rules at the stock location level.

A replenishment rule currently defines:

  • a location scope
  • a trigger mode (real-time, periodic, manual)
  • a replenishment computation method

The current implementation is heavily based on stock moves (stock.move) as the entry point to determine which products should be evaluated.

Problem

The current design introduces several functional and technical limitations.

1. Incorrect behavior when no stock moves occur

For periodic rules, only products involved in stock moves since the last execution are evaluated.

This leads to incorrect situations:

  • If planned replenishment pickings are deleted
  • And no new stock moves occur
  • Then the periodic rule does not generate any replenishment
  • Even if stock is below the required level

2. Incompatibility with advanced replenishment strategies

The current approach prevents implementing strategies where demand evolves independently of stock moves.

Example:

  • Seasonality-based replenishment
  • Forecast-driven replenishment

In such cases:

  • The replenishment need may change without any stock movement
  • But the rule is never triggered → missing replenishment

3. Tight coupling and maintainability issues

The current implementation couples:

  • trigger logic
  • product selection
  • replenishment computation

This results in:

  • complex and heterogeneous code paths
  • difficult extensibility
  • duplication of logic across trigger modes

Proposed solution

Key idea

Refactor the module to rely on a common abstraction based on the following triplet:

  • product
  • forecasted quantity at location
  • replenishment need

Separation of responsibilities

1. Trigger (when to compute)

The trigger becomes responsible for:

  • selecting the products to evaluate
  • computing their forecasted quantities at the given location

2. Replenishment strategy (how to compute)

The replenishment method becomes responsible for:

  • computing the replenishment need

  • based on:

    • product
    • forecasted quantity
    • location

=> This fully decouples when the rule is executed from how the replenishment is computed.

Product selection per trigger mode

Real-time trigger

  • Products come from stock moves
  • 👍 unchanged behavior

Periodic / Manual trigger

  • Products are selected based on recommended quantity.
  • 👎 no longer dependent on stock moves

This ensures:

  • all relevant products are evaluated
  • even when no stock movement occurred

Performance considerations

To avoid performance issues when evaluating all products at a location:

  • Forecasted quantities are computed using SQL queries
  • Avoid relying on ORM-based computations for large datasets

Benefits

Functional

  • Fixes missing replenishment scenarios
  • Enables advanced strategies (e.g. seasonality, forecasting)
  • Ensures consistent behavior across trigger modes

Technical

  • Clear separation of concerns
  • Improved modularity and extensibility
  • Simplified and more homogeneous codebase

Performance

  • Maintains performance through SQL-based computations
  • Avoids heavy ORM recomputations

Migration / Compatibility

  • This is a refactoring with behavioral changes for periodic/manual triggers:

    • rules are no longer dependent on stock moves
  • No data model changes expected (to be confirmed if implementation introduces new fields)

Future improvements enabled

This refactoring enables:

  • pluggable replenishment strategies
  • forecast-based or seasonality-based computations
  • easier integration with demand planning tools

Notes

  • Real-time behavior remains unchanged
  • Focus has been put on preserving performance while improving correctness and extensibility

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions