Fluent Commerce Logo
Docs
Essential knowledge

Intended Audience:

Technical User

Authors:

Holger Lierse, Kirill Gaiduk

Changed on:

24 Aug 2026

Overview

`ControlUtils` is the entry point of the Controls Utilities bundle. This page is the API reference for applying controls to a position from a rule.For the underlying concepts (control, control group, bulk vs position-level control) see Controls Utilities Overview. For the order in which the `ControlUtils` resolves and applies controls, and the behavior of the caches, see the Detailed Technical Description on the Controls Utilities package page.

Key points

  • Specificity-aware: position/product/variant-level controls take precedence over group-level (bulk) controls
  • Auditable: `ControlUtils` records every applied control with a before/after snapshot
  • Extensible: the position source and the set of control functions are both parameters you can supply

Applying Controls to a Position

`applyControls(context, inventoryCatalogueRef, inventoryPositionRef)`
The convenience overload. Loads the position with the default position supplier and applies the default set of control functions. Use this when the position maps one-to-one to the triggering event.
`applyControls(context, positionSupplier, controlFunctions)`
Applies the given control functions to the position produced by `positionSupplier`. Use this to control where the position comes from (for example, an aggregate across locations) and which control functions run.
`applyControls(context, positionSupplier, controlFunctions, defaultControls)`
Like the previous overload, but the `ControlUtils` adds `defaultControls` to the loaded controls where a control of that type is not already present. Use this to guarantee a baseline of behavior when no matching control exists.
`applyControlsWithDefaultBehavior(context, positionSupplier, controlFunctions)`
A shorthand for the overload above that supplies `ControlTypes.DEFAULT_THRESHOLD_CONTROL_ACTIVE` as the default control, so a position with no matching threshold control defaults to `ACTIVE`.

Position Suppliers

A position supplier is a `Supplier<Position>` that tells `applyControls` which position to operate on. `ControlUtils` provides two.
`defaultPositionSupplier(context, inventoryCatalogueRef, inventoryPositionRef)`
Loads a single inventory position and enriches it with the standard related product and location information.
`aggregatePositionSupplier(...)`
Produces a single position whose `quantity` is the sum of on-hand across multiple locations, for a product. `ControlUtils` provides three variants:
  • `aggregatePositionSupplier(context, inventoryCatalogueRef, productRef, activeStatuses)`
    aggregates the positions passed to it, counting only those whose status is in `activeStatuses`.
  • `aggregatePositionSupplier(context, inventoryCatalogueRef, productRef, networkRef, activeStatuses)`
    aggregates across every location in the given network.
  • `aggregatePositionSupplier(context, inventoryCatalogueRef, productRef, locationSupplier, activeStatuses)`
    aggregates across the locations returned by a custom `locationSupplier`.
`locationsByNetworkSupplier(context, networkRef)`
Returns a `Supplier<List<LocationReference>>` of the locations in a network. Pass it to the `locationSupplier` variant of `aggregatePositionSupplier` when you want to aggregate over a network but supply the locations yourself.

Supplying Custom Control Functions

The control functions passed to `applyControls` determine which control types `ControlUtils` recognizes and how each applies. `ControlTypes.buildControlFunctions()` returns the standard set; pass your own list to add or override behavior. The example below assumes you have statically imported the relevant members of `ControlTypes` (`ControlFunction`, `CONTROL_FUNCTION_*`, `appliesToPosition`, `EXCLUSION_TYPE`):

The Result: `PositionUpdateResult`

Every overload returns a `PositionUpdateResult`:
  • `getPosition()` - the updated position (`status` and `quantity` after all controls were applied).
  • `getPositionBefore()` - the original position, before any control was applied.
  • `getAudit()` - an ordered list of `PositionUpdate` entries, one per applied control.
  • `getMessage()` - a human-readable summary, for example `"2 controls were applied"`.
Each `PositionUpdate` in the audit exposes `getBefore()`, `getAfter()` and `getControl()`, giving the position on either side of that single control and the control  that applied the change.