Class DefaultJpaCustomizableSkuInventoryRepository<D extends JpaSkuInventory>

java.lang.Object
com.broadleafcommerce.inventory.provider.jpa.repository.DefaultJpaCustomizableSkuInventoryRepository<D>
Type Parameters:
D -
All Implemented Interfaces:
CustomizableSkuInventoryRepository<D>, org.springframework.beans.factory.InitializingBean

@Transactional(transactionManager="inventoryTransactionManager") public class DefaultJpaCustomizableSkuInventoryRepository<D extends JpaSkuInventory> extends Object implements CustomizableSkuInventoryRepository<D>, org.springframework.beans.factory.InitializingBean
Spring Data Repository Fragment for providing some custom query logic, especially related to explicit locking and custom queries. Note that most default queries defined by SkuInventoryRepository do not assign locks. These should generally not be used for updates as there is no guarantee about concurrency. Reads that do not assign explicit locks are not guaranteed to be accurate for read or update as another thread may be updating those records concurrently. Read locks are less important because, although you can get unreliable data which may be accurate enough for many applications, the persisted data will be accurate. But, in order to have accurate persisted data in a highly concurrent system, you will need to ensure that write locks are properly applied. However, no read locks are required when having an exact inventory count is not required (where there is some room for inaccuracies).
Author:
Kelly Tisdell (ktisdell)
See Also:
  • Constructor Details

    • DefaultJpaCustomizableSkuInventoryRepository

      public DefaultJpaCustomizableSkuInventoryRepository(@NonNull com.broadleafcommerce.data.tracking.core.TrackableBehaviorUtil behaviorUtil, @NonNull com.broadleafcommerce.data.tracking.jpa.filtering.fetch.rsql.JpaFiltersCriteriaBuilder criteriaBuilder, @NonNull List<com.broadleafcommerce.data.tracking.core.service.RsqlQueryTransformer> rsqlQueryTransformers, @NonNull com.broadleafcommerce.data.tracking.jpa.filtering.fetch.rsql.JpaCriteriaBuilderRsqlVisitor rsqlVisitor)
  • Method Details

    • findBySkuReferencesAndLocationId

      @NonNull @Policy(operationTypes=READ) public List<D> findBySkuReferencesAndLocationId(@NonNull Set<String> skuReferences, @Nullable Integer minQuantity, @NonNull String locationId, @NonNull SkuReferenceFieldType skuReferenceFieldType, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo context)
      Description copied from interface: CustomizableSkuInventoryRepository
      Retrieves SkuInventory records, filtering on SkuRef, based on the skuReferenceFieldType parameter, and InventoryLocation.getId().
      Specified by:
      findBySkuReferencesAndLocationId in interface CustomizableSkuInventoryRepository<D extends JpaSkuInventory>
      minQuantity - - (optional) the expected minimum quantity available
      locationId - - the inventory location in which to find inventory
      skuReferenceFieldType - - the type of SKU reference (identifies what SkuRef field should be filtered by the skuReferences argument
      Returns:
    • findByContextId

      @Policy(operationTypes=READ) public Optional<D> findByContextId(String contextId, com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Description copied from interface: CustomizableSkuInventoryRepository
      Retrieve a domain instance based on the context id (see Trackable.getContextId()). If a NarrowExecutor implementation was specified via Narrow, the result should be narrowed based on sandbox and catalog state. This overrides the method TrackableRepository.findByContextId(String, ContextInfo). The mixin implementation will provide an exclusive write lock, if applicable, to prevent concurrent modification of SkuInventory records.
      Specified by:
      findByContextId in interface CustomizableSkuInventoryRepository<D extends JpaSkuInventory>
      Parameters:
      contextId - An identifying id
      contextInfo - Request context information around sandbox and multitenant state
      Returns:
      If nothing found, an empty Optional. Otherwise, an Optional containing the narrowed entity.
    • findAllByContextId

      @Policy(operationTypes=READ) public Iterable<D> findAllByContextId(Iterable<String> contextIds, com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Overrides default TrackableRepository.findByContextId(String, ContextInfo) to add a LockModeType.PESSIMISTIC_WRITE lock. Methods like this are used in update functionality within CrudEntityHelper and BaseCrudEntityService.
      Specified by:
      findAllByContextId in interface CustomizableSkuInventoryRepository<D extends JpaSkuInventory>
      Parameters:
      contextIds - A list of identifying ids
      contextInfo - Request context information around sandbox and multitenant state
      Returns:
      The list of narrowed entities
    • findAvailableBySkuReferenceForQuantity

      @Policy(operationTypes=READ) public List<D> findAvailableBySkuReferenceForQuantity(@NonNull Map<String,Integer> skuReferenceQuantities, @NonNull SkuReferenceFieldType skuReferenceFieldType, @NonNull Optional<Boolean> shippingLocation, @NonNull Optional<Boolean> pickupLocation, @NonNull Optional<Boolean> storeLocation, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo context)
      Description copied from interface: CustomizableSkuInventoryRepository
      Finds SkuInventory records with the mapped available quantities for given fulfillment types.
      Specified by:
      findAvailableBySkuReferenceForQuantity in interface CustomizableSkuInventoryRepository<D extends JpaSkuInventory>
      Returns:
    • buildSkuRefAndQuantityAvailablePredicates

      protected List<jakarta.persistence.criteria.Predicate> buildSkuRefAndQuantityAvailablePredicates(@NonNull @NonNull Map<String,Integer> skuReferenceQuantities, @NonNull @NonNull String skuRefFieldName, @NonNull @NonNull jakarta.persistence.criteria.Root<?> root, @NonNull @NonNull jakarta.persistence.criteria.CriteriaQuery<?> criteria, @NonNull @NonNull jakarta.persistence.criteria.CriteriaBuilder builder)
      Builds a list of Predicates based on the given skuRefs and quantities in skuReferenceQuantities.

      If any skuRefs are serialized, e.g. FOOTBALL-GM1_GAME?serializationValue=100, the skuRef is parsed and a Predicate is built to filter as serialized inventory via buildSerializedInventoryQueryPredicate(String, Integer, Root, CriteriaQuery, CriteriaBuilder).

      Parameters:
      skuReferenceQuantities - map of sku reference to quantity requested
      skuRefFieldName - the name of sku reference
      root - the root entity of the query
      criteria - the current query being built up
      builder - the CriteriaBuilder for the select query
      Returns:
      a list of Predicates based on the given skuRefs and quantities in skuReferenceQuantities
    • buildPredicateForSkuRefs

      protected jakarta.persistence.criteria.Predicate buildPredicateForSkuRefs(@NonNull @NonNull SkuReferenceFieldType skuReferenceFieldType, @NonNull @NonNull Set<String> skuReferences, @Nullable Integer minQuantity, @NonNull @NonNull jakarta.persistence.criteria.Root<?> root, @NonNull @NonNull jakarta.persistence.criteria.CriteriaQuery<?> criteria, @NonNull @NonNull jakarta.persistence.criteria.CriteriaBuilder builder)
    • buildSkuRefPredicates

      protected List<jakarta.persistence.criteria.Predicate> buildSkuRefPredicates(String skuRef, String skuRefFieldName, @Nullable Integer quantity, @NonNull @NonNull jakarta.persistence.criteria.Root<?> root, @NonNull @NonNull jakarta.persistence.criteria.CriteriaQuery<?> criteria, @NonNull @NonNull jakarta.persistence.criteria.CriteriaBuilder builder)
    • isSerializedSkuRef

      protected boolean isSerializedSkuRef(@NonNull @NonNull String skuRef)
      Determines if the given skuRef is serialized.
      Parameters:
      skuRef - the sku ref to check
      Returns:
      true if the given skuRef is serialized, otherwise false
    • getSerializedInventoryParam

      protected String getSerializedInventoryParam()
    • buildSerializedInventoryQueryPredicate

      protected Optional<jakarta.persistence.criteria.Predicate> buildSerializedInventoryQueryPredicate(@NonNull @NonNull String serializationValue, @Nullable Integer quantity, @NonNull @NonNull jakarta.persistence.criteria.Root<?> root, @NonNull @NonNull jakarta.persistence.criteria.CriteriaQuery<?> criteria, @NonNull @NonNull jakarta.persistence.criteria.CriteriaBuilder builder)
      Builds an optional Predicate for a serialized inventory.

      A Subquery is also included to query the inventory availability for the parent, which is needed for the availability of a serialized inventory since the parent could be sold as well.

      Consider stadium suites at a football game, there may be 10 gold suites, represented with SKU FOOTBALL-GM1-GOLD-SUITE. The parent sku inventory would have 10 as quantity available, and each serialized sku inventory for each suite would have 1 as quantity available. Let's say all 10 suites are sold out as a generic sku, which means that the suites are all sold but no one bought a specific suite. In this case, a serialized sku FOOTBALL-GM1-GOLD-SUITE?serializationValue=100 may seem available but in reality it is already sold, it is simply not sold as a serialized sku.

      Parameters:
      serializationValue - the serialization value
      quantity - the quantity to check
      root - the root entity of the query
      criteria - the current query being built up
      builder - the CriteriaBuilder for the select query
      Returns:
      an optional Predicate for a serialized inventory if the pattern is found, otherwise an Optional.empty() is returned
    • findAvailableBySkuReferenceForQuantity

      @Policy(operationTypes=READ) public List<D> findAvailableBySkuReferenceForQuantity(@NonNull Map<String,Integer> skuReferenceQuantities, @NonNull SkuReferenceFieldType skuReferenceFieldType, @NonNull String inventoryLocationId, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo context)
      Description copied from interface: CustomizableSkuInventoryRepository
      Finds SkuInventory records with at least the mapped available quantities for a given inventory location.
      Specified by:
      findAvailableBySkuReferenceForQuantity in interface CustomizableSkuInventoryRepository<D extends JpaSkuInventory>
      Returns:
    • readAllByInventoryLocationId

      public Stream<D> readAllByInventoryLocationId(String inventoryLocationId, @Nullable cz.jirutka.rsql.parser.ast.Node filters, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Description copied from interface: CustomizableSkuInventoryRepository
      Read all Sku Inventories for the specified inventory location id matching the given filters.
      Specified by:
      readAllByInventoryLocationId in interface CustomizableSkuInventoryRepository<D extends JpaSkuInventory>
      Parameters:
      inventoryLocationId - the inventory location id
      filters - additional filters to apply in the query, can be null
      contextInfo - context information surrounding sandboxing and multitenant state
      Returns:
      the Sku Inventories for the specified inventory location id
    • deleteAllByInventoryLocationId

      public void deleteAllByInventoryLocationId(String inventoryLocationId, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Description copied from interface: CustomizableSkuInventoryRepository
      Softly deletes all the SkuInventory for the specified inventory location id
      Specified by:
      deleteAllByInventoryLocationId in interface CustomizableSkuInventoryRepository<D extends JpaSkuInventory>
      Parameters:
      inventoryLocationId - the inventory location id
      contextInfo - context information surrounding sandboxing and multitenant state
    • getUnarchivedAndInventoryLocationIdEqualsPredicate

      protected jakarta.persistence.criteria.Predicate getUnarchivedAndInventoryLocationIdEqualsPredicate(jakarta.persistence.criteria.CriteriaBuilder builder, jakarta.persistence.criteria.Root<D> entity, String inventoryLocationId)
      Builds the predicate for getting all unarchived skuInventory from a particular inventoryLocationId
      Parameters:
      builder - the criteria-builder
      entity - the entity whose attributes are to be queried upon
      inventoryLocationId - the id of the inventoryLocation whose inventory is to be deleted
      Returns:
      a predicate that performs the appropriate filtering
    • readSummaryAvailability

      public Object[][] readSummaryAvailability(SkuReferenceFieldType skuReferenceFieldType, Set<String> skuReferences, int minQuantity, Optional<Boolean> shippingLocation, Optional<Boolean> pickupLocation, Optional<Boolean> storeLocation, com.broadleafcommerce.data.tracking.core.context.ContextInfo context)
      Description copied from interface: CustomizableSkuInventoryRepository
      Queries for applications and tenant IDs associated with the requested availability. The response is a an Object array that contains: - skuReference (i.e. typically skuCode, but depends on what is requested by skuReferenceFieldType) - tenantId - applicationId (nullable) This method is pretty specific as it allows the Search Services, for example, to determine, for which SKUs have general availability across tenants and applications, not specific to inventory locations.
      Specified by:
      readSummaryAvailability in interface CustomizableSkuInventoryRepository<D extends JpaSkuInventory>
      Parameters:
      skuReferenceFieldType - The type of fields for which we are search (e.g. SKU_CODE)
      skuReferences - The SKU reference number or code e.g. SkuRef.skuCode
      shippingLocation - Indicates if we want to include availability at shipping locations
      pickupLocation - - Indicates if we want to include availability at pickup locations
      storeLocation - - Indicates if we want to include availability at store locations
      context - the ContextInfo for this request
      Returns:
      An object array, representing the rows and columns from the query
    • findAvailableBySkuReferenceForQuantity

      @Policy(operationTypes=READ) public List<D> findAvailableBySkuReferenceForQuantity(@NonNull Set<String> skuReferences, int minQuantityAvailable, @NonNull SkuReferenceFieldType skuReferenceFieldType, @NonNull Optional<Boolean> shippingLocation, @NonNull Optional<Boolean> pickupLocation, @NonNull Optional<Boolean> storeLocation, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo context)
      Description copied from interface: CustomizableSkuInventoryRepository
      Finds available SkuInventory records for the provided skuReferences where each have at least the minQuantityAvailable.
      Specified by:
      findAvailableBySkuReferenceForQuantity in interface CustomizableSkuInventoryRepository<D extends JpaSkuInventory>
      Returns:
    • findByInventoryLocationAndSkuRefFieldValues

      @Policy(operationTypes=READ) public Optional<D> findByInventoryLocationAndSkuRefFieldValues(String inventoryLocationId, @NonNull Optional<String> externalId, @NonNull Optional<String> skuCode, @NonNull Optional<String> upc, @NonNull Optional<String> ean, @NonNull Optional<String> gtin, com.broadleafcommerce.data.tracking.core.context.ContextInfo context)
      Description copied from interface: CustomizableSkuInventoryRepository
      Tries to find a unique SkuInventory record based on the InventoryLocation.getId() and any one of SkuRef field values. Note that for any SkuInventory record, there can be only one unique SKU identifier, which includes any number of unique fields, per InventoryLocation.
      Specified by:
      findByInventoryLocationAndSkuRefFieldValues in interface CustomizableSkuInventoryRepository<D extends JpaSkuInventory>
      Returns:
    • findByInventoryLocationAndSkuRefFieldValuesAndNotSerialized

      @Policy(operationTypes=READ) public Optional<D> findByInventoryLocationAndSkuRefFieldValuesAndNotSerialized(String inventoryLocationId, @NonNull Optional<String> externalId, @NonNull Optional<String> skuCode, @NonNull Optional<String> upc, @NonNull Optional<String> ean, @NonNull Optional<String> gtin, com.broadleafcommerce.data.tracking.core.context.ContextInfo context)
      Description copied from interface: CustomizableSkuInventoryRepository
      Tries to find a unique non-serialized SkuInventory record based on the InventoryLocation.getId() and any one of SkuRef field values. Note that for any SkuInventory record, there can be only one unique SKU identifier, which includes any number of unique fields, per InventoryLocation.
      Specified by:
      findByInventoryLocationAndSkuRefFieldValuesAndNotSerialized in interface CustomizableSkuInventoryRepository<D extends JpaSkuInventory>
    • readConsolidatedInventoryQuantities

      public Map<String,Long> readConsolidatedInventoryQuantities(@NonNull Set<String> skus, @NonNull Optional<Boolean> shippingLocation, @NonNull Optional<Boolean> pickupLocation, @NonNull Optional<Boolean> storeLocation, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo context)
      Description copied from interface: CustomizableSkuInventoryRepository
      This reads a sum of inventory quantities available for a particular SKU. This returns a Map of quantities available. The Map has a key that represents the SKU with a value that represents the quantity available for that SKU.
      Specified by:
      readConsolidatedInventoryQuantities in interface CustomizableSkuInventoryRepository<D extends JpaSkuInventory>
      Parameters:
      skus - the skus for which we are requesting inventory
      shippingLocation - whether the inventory can come from a shipping location
      pickupLocation - whether the inventory can come from a pickup location
      storeLocation - whether the inventory can come from a store or shopping location
      context - the context for which this query should be applied
      Returns:
    • isAvailableBySkuReferenceForQuantity

      @Policy(operationTypes=READ) public boolean isAvailableBySkuReferenceForQuantity(@NonNull String skuReference, int quantity, @NonNull SkuReferenceFieldType skuReferenceFieldType, @NonNull Optional<Boolean> shippingLocation, @NonNull Optional<Boolean> pickupLocation, @NonNull Optional<Boolean> storeLocation, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo context)
      Description copied from interface: CustomizableSkuInventoryRepository
      Determines if the SkuInventory, identified by skuReference, is available for the specified quantity across one or more InventoryLocations, identified by their allowed fulfillment types. SkuRef is determined by the skuReference argument and the
      Specified by:
      isAvailableBySkuReferenceForQuantity in interface CustomizableSkuInventoryRepository<D extends JpaSkuInventory>
      quantity - - requested quantity
      skuReferenceFieldType - - the type of skuReference being passed in
      shippingLocation - - Optional value represents whether we should query shipping locations. If not present, no filtering will be applied.
      pickupLocation - - Optional value represents whether we should query pickup locations. If not present, no filtering will be applied.
      storeLocation - - Optional value represents whether we should query store locations. If not present, no filtering will be applied.
      Returns:
    • findAll

      @Policy(operationTypes=READ) public Stream<D> findAll(@NonNull Optional<cz.jirutka.rsql.parser.ast.Node> filters, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Description copied from interface: CustomizableSkuInventoryRepository
      Generally used for batch export, this allows a caller to query, filter, and stream paged results.
      Specified by:
      findAll in interface CustomizableSkuInventoryRepository<D extends JpaSkuInventory>
      Returns:
    • buildSkuRefFieldPredicate

      protected jakarta.persistence.criteria.Predicate buildSkuRefFieldPredicate(@NonNull @NonNull jakarta.persistence.criteria.Root<?> root, @NonNull @NonNull jakarta.persistence.criteria.CriteriaBuilder builder, @NonNull Optional<String> externalId, @NonNull Optional<String> skuCode, @NonNull Optional<String> upc, @NonNull Optional<String> ean, @NonNull Optional<String> gtin)
    • buildInventoryLocationCorrelatedSubQueryPredicate

      protected Optional<jakarta.persistence.criteria.Predicate> buildInventoryLocationCorrelatedSubQueryPredicate(jakarta.persistence.criteria.Root<? extends JpaSkuInventory> root, jakarta.persistence.criteria.CriteriaQuery<? extends JpaSkuInventory> criteriaQuery, com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      This creates a subquery that ensures that the associated JpaInventoryLocation record is valid (i.e. that it exists, it is not archived, and it belongs to the same context / tenant as the JpaSkuInventory record). We do this instead of a join to avoid complications around pessimistic locking across tables, as well as to avoid pulling back additional (unnecessary) data in a ManyToOne join that would otherwise require a Hibernate proxy to lazy load the data.
      Parameters:
      root -
      criteriaQuery -
      contextInfo -
      Returns:
    • buildInventoryLocationCorrelatedSubQueryPredicate

      protected Optional<jakarta.persistence.criteria.Predicate> buildInventoryLocationCorrelatedSubQueryPredicate(jakarta.persistence.criteria.Root<?> root, jakarta.persistence.criteria.CriteriaQuery<?> criteriaQuery, Optional<Boolean> shippingLocation, Optional<Boolean> pickupLocation, Optional<Boolean> storeLocation, com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      This creates a subquery that ensures that the associated JpaInventoryLocation record is valid (i.e. that it exists, it is not archived, and it belongs to the same context / tenant as the JpaSkuInventory record). We do this instead of a join to avoid complications around pessimistic locking across tables, as well as to avoid pulling back additional (unnecessary) data in a ManyToOne join that would otherwise require a Hibernate proxy to lazy load the data. This also filters based on whether the InventoryLocation is a shippingLocation, pickupLocation, or storeLocation.
      Parameters:
      root -
      criteriaQuery -
      shippingLocation -
      pickupLocation -
      storeLocation -
      contextInfo -
      Returns:
    • buildContextFilterPredicate

      protected Optional<jakarta.persistence.criteria.Predicate> buildContextFilterPredicate(jakarta.persistence.criteria.Path<?> path, com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Optionally returns basic Predicate for TenantJpaTracking.getTenant() based on the ContextInfo argument. This predicate provides filtering for tenantId and archived flags. Only use this to query or filter Path elements that represent entities that implement Trackable. This is applied to queries for JpaSkuInventory as well as to correlated subqueries for JpaInventoryLocation. This method also supports the "INCLUDE_APPLICATION_ID_PREDICATE" flag on ContextInfo.additionalProperties. If that attribute is set to Boolean.FALSE, then the application id predicate will not be included.
      Parameters:
      path -
      contextInfo -
      Returns:
    • collectNonNullPredicates

      protected jakarta.persistence.criteria.Predicate[] collectNonNullPredicates(jakarta.persistence.criteria.Predicate archivedIsFalsePredicate, jakarta.persistence.criteria.Predicate tenantMatch, jakarta.persistence.criteria.Predicate applicationMatch)
    • resolveSkuRefFieldName

      protected String resolveSkuRefFieldName(SkuReferenceFieldType skuRefFieldType)
      Resolves the name of the field that should be used in a Predicate based on the provided SkuReferenceFieldType.
      Parameters:
      skuRefFieldType -
      Returns:
    • setSkuInventoryRepository

      @Autowired @Lazy public void setSkuInventoryRepository(SkuInventoryRepository<D> skuInventoryRepository)
    • afterPropertiesSet

      public void afterPropertiesSet() throws Exception
      Specified by:
      afterPropertiesSet in interface org.springframework.beans.factory.InitializingBean
      Throws:
      Exception
    • getEntityManager

      protected jakarta.persistence.EntityManager getEntityManager()
    • getSkuInventoryRepository

      protected SkuInventoryRepository<D> getSkuInventoryRepository()
    • getNarrowingHelper

      protected com.broadleafcommerce.data.tracking.jpa.filtering.narrow.JpaNarrowingHelper getNarrowingHelper()
    • getBehaviorUtil

      protected com.broadleafcommerce.data.tracking.core.TrackableBehaviorUtil getBehaviorUtil()
    • getCriteriaBuilder

      protected com.broadleafcommerce.data.tracking.jpa.filtering.fetch.rsql.JpaFiltersCriteriaBuilder getCriteriaBuilder()
    • getRsqlQueryTransformers

      protected List<com.broadleafcommerce.data.tracking.core.service.RsqlQueryTransformer> getRsqlQueryTransformers()
    • getRsqlVisitor

      protected com.broadleafcommerce.data.tracking.jpa.filtering.fetch.rsql.JpaCriteriaBuilderRsqlVisitor getRsqlVisitor()