How to override Stock Level calculation for Package?

Vote:
 

EPiServer.Commerce: v10.2.3

Hello all,

I have a task to have Package StockLevel calculated based on StockLevels of Variations included into the Package.

Important thing is that I cannot use Bundle because I need it to be presented as one LineItem in the Cart and I need to be able to setup a specific price to Package itself.

That means, that I should recalculate package stock level on

  1. variation stock level changed
  2. package stock level changed manually. It should be or recalculated or ability to change it manually should be disabled.

Steps that were taken:

  1. Subscription to events: CatalogKeyEventBroadcaster.InventoryUpdated, CatalogEventBroadcaster.CommerceProductUpdated. Possible solution looks heavy due to taking care of unsubscription of InventoryUpdated when Iam updating Package inventoryRecord.
  2. Another approach is to override InventoryServiceProvider. Here I need an IReferenceRepository as a dependency to be able to navigate to packageEntries (variation that are included into the package to get their stock level). This dependency follows a circular dependency to IInventoryService (LinksRepository has dependency to ICatalogSystem that depends on IInventory Service). From this point I do not see this approach as a solution.

Question:

Could you please share your thoungts, experience in implementing this kind of things?

#176579
Mar 22, 2017 11:57
Vote:
 

Am not quite sure what you want to do, when you want to use the calculated value, but maybe something like this? This basically takes the lowest stock level for all variations in the package.

public decimal LowestStockForPackage(PackageContent packageContent)
        {
            IContentRepository repo = ServiceLocator.Current.GetInstance<IContentRepository>();
            InventoryLoader inventoryLoader = ServiceLocator.Current.GetInstance<InventoryLoader>();
            IEnumerable<ContentReference> packageEntryLinks = packageContent.GetEntries();

            List<decimal> stockList = new List<decimal>();

            foreach (ContentReference contentReference in packageEntryLinks)
            {
                VariationContent variant;

                if (repo.TryGet(contentReference, out variant))
                {
                    stockList.AddRange(variant.GetStockPlacement(inventoryLoader).Select(i => i.InStockQuantity));
                }
            }

            return stockList.Min();
        }

Probably you'd want to add the inventory to the packaga within Find?

#176584
Edited, Mar 22, 2017 13:50
Vote:
 

Hello Jeroen,

Thank you for your input.

My task is to have Package Stock Level automatically recalculated in EpiServer Edit Mode.

Scenario: In case I am an editor and I am changing Stock Level of variations, I would like to see that Package Stock Level is also updated based on Variation Stock Level value.

So, I am looking for an approach to make this integration correctly from EpiServer perspective, like subscription on events, or overriding some classes.

Thank you,

Maria 

#176597
Mar 22, 2017 15:33
Vote:
 

I think InventoryUpdated is your best choice. You can always get the content (which should be cached always) and check if it is a package before continue processing. 

#176598
Mar 22, 2017 16:18
Vote:
 

You could use something like this to update the stock for all packages a variation belongs to, using the code mentioned earlier, in the event Quan mentioned.

public void AdjustStockForPackage(VariationContent variationContent)
        {
            IInventoryService inventoryService = ServiceLocator.Current.GetInstance<IInventoryService>();
            IContentLoader contentLoader = ServiceLocator.Current.GetInstance<IContentLoader>();
            IWarehouseRepository warehouseRepository = ServiceLocator.Current.GetInstance<IWarehouseRepository>();

            IEnumerable<ContentReference> references = variationContent.GetParentPackages();

            IEnumerable<PackageContent> items = contentLoader.GetItems(references, (CultureInfo)null).OfType<PackageContent>();

            IWarehouse firstWarehouse = warehouseRepository.GetDefaultWarehouse();

            foreach (PackageContent packageContent in items)
            {
                InventoryRecord inventoryRecord = inventoryService.Get(packageContent.Code, firstWarehouse.Code);

                if (inventoryRecord == null)
                {
                    continue;
                }

                decimal lowestStock = LowestStockForPackage(packageContent);

                inventoryRecord.PurchaseAvailableQuantity = lowestStock;

                inventoryService.Update(new[] { inventoryRecord });
            }
        }
#176602
Mar 22, 2017 17:23
Vote:
 

Thank you all, I found kind of similar discussion in http://world.episerver.com/forum/developer-forum/Episerver-Commerce/Thread-Container/2016/4/set-inventory-and-variationrow-on-entryupdating/

I will try out this approach.

Thank you

#177998
Apr 26, 2017 13:22
* You are NOT allowed to include any hyperlinks in the post because your account hasn't associated to your company. User profile should be updated.