Broadleaf Microservices
  • v1.0.0-latest-prod

TMF687 - Stock Management

TMForum API Version Support Required Broadleaf Service(s)

v4

Inventory Services

Supported APIs for Stock Management

TMForum Resource Description Endpoints

ProductStock

ProductStock describes the stock level of a particular product or variant. In Broadleaf this conceptually maps to the SkuInventory domain provided by Inventory Services

POST /productStock

GET /productStock

GET /productStock/{id}

DELETE /productStock/{id}

PATCH /productStock/{id}

ReserveProductStock

ReserveProductStock is used to request a product stock reservation. In Broadleaf this conceptually maps to the SKU Inventory Reservations Requests provided by Inventory Services

POST /reserveProductStock

GET /reserveProductStock

GET /reserveProductStock/{id}

Architecture View

Broadleaf supports TMF687 Stock Management via an Extension Model on top of Broadleaf’s existing Inventory Microservice. This extension model works by defining an extension library alongside Broadleaf’s default inventory service dependency which will enable additional TMForum specific capabilities.

TMF 687 Architecture

High Level Mapping Strategies

Broadleaf’s InventoryLocation and SkuInventory

The core Broadleaf concepts that underpin TMF687 are the InventoryLocation and SkuInventory domains. In Broadleaf, every SkuInventory record is associated with an InventoryLocation (i.e. a location like a warehouse, shipping location, pickup location, etc…​)

In TMForum 687, the analogous relationship identifier is surfaced by the RelatedPlaceRefOrValue which is used to define a place where the product stock is located. Broadleaf currently does not map or implement the concept of Place (TMF673/TMF674) nor do we assume that a reference value passed into this RefOrValue entity refers back to a Broadleaf managed resource.

Instead, Broadleaf supports an extended JSON property: blcInventoryLocationContextId on the default ProductStock and ReserveProductStock payloads which can properly identify the Broadleaf Inventory Location a certain stock request is associated with. Note that this field is optional and the system will default to a particular value specified in the API Context attributes if not in the request payload.

Key Components

Broadleaf’s TMForum Extensions library provides several Spring utility components that are responsible for assisting in conversions between TMForum Concepts and Broadleaf Concepts. The following components can be extended to support a different mapping strategy if needed.

  • com.broadleafcommerce.tmforum.inventory.tmf687.service.mapping.ProductStockIdProcessingUtility

    • ProductStock.id is derived from Broadleaf’s SkuInventory.id, and this component is responsible for handling the conversion from both directions

  • com.broadleafcommerce.tmforum.inventory.tmf687.service.mapping.ProductStockMappingUtility

    • The conversion logic between ProductStock and Broadleaf’s SkuInventory is handled in multiple places. For 'read' operations, the mapping is handled by ModelMapperMappable logic in JpaSkuInventoryProductStockView to go from the Broadleaf representation to the TMF representation. For modification operations like creates and updates, ProductStockMappingUtility is where the conversion from TMF representation to Broadleaf representation is defined.

  • Filtration and Sort

    • ProductStock

      • com.broadleafcommerce.tmforum.inventory.tmf687.web.attributefiltration.ProductStockAttributeFiltersRequestResolver

        • Handles resolving the supported filtration parameters for requests against ProductStock

      • com.broadleafcommerce.tmforum.inventory.tmf687.provider.jpa.filtering.JpaSkuInventoryProductStockViewRsqlAndSortTransformer

        • Handles field transformations for filter and sort requests against ProductStock

      • The following fields are supported for filtration/sort on ProductStock

        • id

        • name

        • replenishmentDate

        • productStockStatusType

        • lastUpdate

        • blcInventoryLocationContextId

        • productStockLevel.amount

        • stockedProduct.productSerialNumber

    • ReserveProductStock

      • com.broadleafcommerce.tmforum.inventory.tmf687.web.attributefiltration.ReserveProductStockAttributeFiltersRequestResolver

        • Handles resolving the supported filtration parameters for requests against ReserveProductStock

      • The following fields are supported for filtration/sort on ReserveProductStock

        • id

        • creationDate

        • reserveProductStockState

        • blcInventoryLocationContextId

  • com.broadleafcommerce.tmforum.inventory.tmf687.service.validation.ProductStockValidator

    • This component implements first-class validations on ProductStock request payloads to ensure API consumers cannot create an invalid state.

  • com.broadleafcommerce.tmforum.inventory.tmf687.service.mapping.ReserveProductStockMappingUtility

    • This handles the conversion logic between ReserveProductStock and Broadleaf’s SkuInventoryReservationRequest.

  • com.broadleafcommerce.tmforum.inventory.tmf687.service.validation.ReserveProductStockValidator

    • This component implements first-class validations on ReserveProductStock request payloads to ensure API consumers cannot create an invalid state.

  • com.broadleafcommerce.tmforum.inventory.tmf687.service.DefaultProductStockService

    • This is the top-level service component responsible for handling management of ProductStock. It orchestrates the main flow for CRUD operations, delegating specific responsibilities like validation and mapping to the other components as appropriate.

  • com.broadleafcommerce.tmforum.inventory.tmf687.service.DefaultReserveProductStockService

    • This is the top-level service component responsible for handling management of ReserveProductStock. It orchestrates the main flow for CRUD operations, delegating specific responsibilities like validation and mapping to the other components as appropriate.

  • com.broadleafcommerce.tmforum.inventory.tmf687.service.apicontext.InventoryCommonTMFApiContextKeys shows which fields can be defaulted via API Context attributes out-of-box

  • com.broadleafcommerce.tmforum.inventory.tmf687.jackson.autoconfigure.TMForumInventoryJacksonAutoConfiguration

    • Defines JacksonAnnotationMixinMapping beans for ProductStock and ReserveProductStock to drive behaviors such as attribute selection

Strategy for ProductStock

The TMForum ProductStock resource conceptually maps to Broadleaf’s SkuInventory resource, the main difference being that Broadleaf aggregates specific ProductStock inventory counts into a single SkuInventory record whereas TMForum defines each individual quantity count as being a separate entry.

In order to conform to the TMForum’s pagination, filtration, and sorting intent, Broadleaf employs a read-only database view (BLC_SKU_INV_PROD_STOCK) to expand a single SkuInventory entry into multiple rows to achieve conformance with TMForum’s API.

The create/update/delete operations follow a tailored flow to preserve the external 'separate entity' abstraction. Internally, the flow will make determinations about whether the operation needs to result in a net-new SkuInventory record or if it should update an existing SkuInventory record with the requested state. For example, if a TMF request comes in to create a 'reserved' ProductStock for SKU ABC123, and there is already a SkuInventory for ABC123 that does not have a 'reserved' quantity, the system may update that existing SkuInventory record instead of creating a net new one.

Below is a high level diagram describing the concept mapping strategies Broadleaf has employed to support this translation:

TMF 687 ProductStock Mapping Strategy

Considerations for ProductStock

  • The productStockStatusType is the primary field on which a SkuInventory is split into ProductStock. The ProductStock.id is built from a combination of the SkuInventory.id and a productStockStatusType.

  • In Broadleaf, quantities in a SkuInventory must always result in a valid state - for example, you cannot have an inventory that has more items reserved than are available (if backorder is disabled). Because of this, in TMF, an API consumer cannot, for example, create 'reserved' ProductStock for a SKU if they have not already created enough 'available' ProductStock for that SKU. The order of creation matters to ensure the backing SkuInventory remains valid.

  • TMF requires that the productStockStatusType value be PATCH-able. In Broadleaf, this creates a special case, since productStockStatusType is used to identify a ProductStock in the first place. Semantically, mutation of the productStockStatusType is equivalent to 'deleting' the ProductStock of the existing type and then creating a new ProductStock for the requested type (potentially migrating the quantity for the existing type to the new type). In the response, the new ProductStock.id will be returned so consumers can see the difference.

  • While some fields on SkuInventory are only used by a particular productStockStatusType (ex: only the 'preorder' or 'backorder' ProductStock will deal with the SkuInventory.expectedFutureRestockDate field), others like SkuRef.skuName are shared by all ProductStock instances backed by the same SkuInventory. In the interest of remaining flexible instead of rejecting mutation attempts altogether, any update to such a 'shared' field will implicitly result in updating all ProductStock instances backed by the same SkuInventory.

    • Note that blcInventoryLocationContextId is intentionally not honored as part of ProductStock update requests, as modification of this value would implicitly make a significant change to all ProductStock instances backed by the same SkuInventory.

Strategy for ReserveProductStock

Broadleaf supports the concept of reserving inventory through reservation requests that are already facilitated through core "task-based" inventory service methods. TMForum ReserveProductStock APIs assume the management of a persisted reservation request resource which is asynchronously executed.

Broadleaf TMForum Extensions introduces a BLC_RESERVE_PRODUCT_STOCK table to conform with the "resource-based" TMF687 ReserveProductStock intent.

Broadleaf provides a ReserveProductStockService which synchronously executes a stock reservation request and creates a corresponding new ReserveProductStock in the datastore. From the perspective of the API consumer, this is no different from an asynchronous execution, as the results are surfaced and retrieved in the same way.

Below is a high level diagram describing the concept mapping strategies Broadleaf has employed to support this API:

TMF 687 ReserveProductStock Mapping Strategy

Ultimately, creation of a ReserveProductStock involves building and submitting Broadleaf’s SkuInventoryReservationRequest to the internal reservation logic, at which point InventoryTransaction instances representing the reserved stock are created and tracked.

Considerations for ReserveProductStock

  • Broadleaf has the concept of 'soft' and 'hard' reservations. TMF consumers have no knowledge of BLC reservation types, and have no way to upgrade a soft reservation to a hard one. Thus, any reservations created from the TMF API will be 'hard' reservations.