Correct way handling inventory and shipments in the new way not using workflows version 10+

Hello, 

We have some questions what the correct/easiet way of handling inventory is in the new system.. 
Should we do the InventoryRequest manually and also updating the inventory manually or should this be done some other way... 

let say we have one item with 1 in stock and 10 in backorder 
we buy 2 of these items.. one should be shipped now and the other later when in stock.. 
so what would the easiest happy flow be for making this happend :)? 

when we do this now we can buy these 2 items and create the purchase order.. 

The inventory will be instock 1 and backorder 10 for this items (not changed)
The order will be "In Progress" state
And shipping status "awaiting inventory" 
If we manually in "commerce manager" change the status to "On Hold" and then back things happens:
-The inventory will be instock 0 and backorder 9 for this items
-shipping status "Inventory Assigned" (one is still in backorder) 

We want this to be set already when purchase order is created but i guess is some extra steps to do that.

When we add up inventory manually to be instock 2 and backorder 9, nothing happends.. and maybe it should not. .

so should all this be handled manually from code? (order status, shipping status, invetory quantitys.. ) 

im a bit confused abut the right way doing this and dont want to start doing things wrong way. .

Thanks in advance for any directions.. :)

#184714 Nov 02, 2017 13:28
  • Member since: 2011

    I might not fully understand the whole picture (busy day), but I think that would require some custom changes in your "workflow" - processing code. You would have to automatically split shipments if one or more items shared across InStock and BackOrder (things that can be shipped right away into a shipment, and other ones into another shipment). One place to do that is before calling UpdateInventoryOrRemoveLineItems

    #184716 Nov 02, 2017 13:43
  • #184718 Removed, Nov 02, 2017 13:49
  • Also other question, when doing a AdjustInventoryOrRemoveLineItems just before creating order everything will be adjusted in the inventory..

    but how can i find items that are "BackoOrdered" in my orders?

    Do i need to do something or is there a easy way to find them? 

    #184740 Nov 02, 2017 19:32
  • Member since: 2011

    Out of my head, at that point couldn't you query the inventory and decide if you should split? 

    #184743 Nov 02, 2017 21:06
  • ok, so what you saying is that we can´t see on order is some items are backordered.. 

    I would like the customer to be able to fulfill the order even with item that are backorderes but i want them ontl shipped when all items are in stock.. 

    So i guess when refilling stock we should look at the inventory to see if we have anything on "BackorderRequestedQuantity"

    and then add to our orders that are "On Hold" and fill them up before we fill the inventory.

    then step 2 in our case would be to split into severals shipments.. 

    would this be a good way to go?  

    #184763 Nov 03, 2017 8:48
  • ok, still not clear how this should be handled.. 

    i see 2 ways..

    one way manually make "RequestInventory"

    https://world.episerver.com/documentation/developer-guides/commerce/warehouses-and-inventories/Warehouses-and-inventories-examples/

    the other call "AdjustInventoryOrRemoveLineItems"

    https://world.episerver.com/documentation/developer-guides/commerce/orders/order-processing/

    im really confused how to use it correct the new "way" without workflows. 

    the first way requires us to store "OperationKeys" on shipment i guess?

     
    Is there any documentaiton on how it should be done somewhere?

    i have only found the 2 links above

    #185298 Nov 14, 2017 20:28
  • Member since: 2011

    i would use AdjustInventoryOrRemoveLineItems this will handle all cases depending the status of the order.  The reason the framework does not work as you would like is becasue not all customers would want to create a new shipment for the backorder as they might want to wait to ship all together.  When calling AdjustInventoryOrRemoveLineItems you only get back AdjustedQuantityByBackorderQuantity when there is not enough to fullfill the order.  If you want to check if an item was placed on back order but did not receive a valiadation issue you can use the method below.

    public Dictionary<ILineItem, Dictionary<InventoryRequestType, InventoryChange>> GetInventoryStatus(IOrderGroup order)
            {
                var status = new Dictionary<ILineItem, Dictionary<InventoryRequestType, InventoryChange>>();
                var serializer = ServiceLocator.Current.GetInstance<OperationKeySerializer>();
                foreach (var shipment in order.GetFirstForm().Shipments)
                {
                    if (!(shipment is IShipmentInventory shipmentInventory))
                    {
                        continue;
                    }
                    foreach (var lineItem in shipment.LineItems)
                    {
                        var keys = shipmentInventory.GetOperationKeys(lineItem).ToList();
                        if (!keys.Any())
                        {
                            continue;
                        }
                        
                        foreach (var key in keys)
                        {
                            if (!serializer.TryDeserialize(key, out var inventoryRequestType, out var inventoryChange))
                            {
                                continue;
                            }
                            if (!status.ContainsKey(lineItem))
                            {
                                status.Add(lineItem, new Dictionary<InventoryRequestType, InventoryChange>());
                            }
                            status[lineItem].Add(inventoryRequestType, inventoryChange);
                        }
                    }
                }
                return status;
            }

    #185304 Nov 15, 2017 3:37
  • Ok, so lets take a happy flow fo rexample.. Without backorder to make things really easy.. 

    Item A -> 10 in stock
    customer adds 1 to cart and complete the checkout.. 

    just before we convert the cart to purchase order we do a "AdjustInventoryOrRemoveLineItems"  with cart 

    now we have inventoryrecord that looks like this:

    PurchaseAvailableQuantity: 9
    PurchaseRequestedQuantity: 1
     

    We mark the order as completed and also mark the onyl shipment as shipped and save order. 

    now we call "AdjustInventoryOrRemoveLineItems" again but on order this time (cart is gone now)

    and...

    nothing happens.. we still have 

    PurchaseAvailableQuantity: 9
    PurchaseRequestedQuantity: 1

    Shouldnt this look like:
    PurchaseAvailableQuantity: 9
    PurchaseRequestedQuantity: 0 
     

    so to complete this i only found that we should make a "RequestInventory"https://world.episerver.com/documentation/developer-guides/commerce/warehouses-and-inventories/Warehouses-and-inventories-examples/ 

     and mark it as Completed.. ? mixing these 2 makes it a but confusing

    so "i would use AdjustInventoryOrRemoveLineItems this will handle all cases"  does not handle that much or i use it wrong way in the wrong time? 

    #185306 Nov 15, 2017 8:45
  • Member since: 2011

    I think this will work as expected if you want to use the api instead of commerce manager to prcoess shipments.

    public void CompleteOrder(IOrderGroup cart)
            {
                var inventoryProcessor = ServiceLocator.Current.GetInstance<IInventoryProcessor>();
                var paymentProcessor = ServiceLocator.Current.GetInstance<IPaymentProcessor>();
                var orderGroupCalculator = ServiceLocator.Current.GetInstance<IOrderGroupCalculator>();
                var orderRepository = ServiceLocator.Current.GetInstance<IOrderRepository>();
                var validationIssues = new Dictionary<ILineItem, List<ValidationIssue>>();
                cart.AdjustInventoryOrRemoveLineItems((item, issue) => AddValidationIssues(validationIssues, item, issue), inventoryProcessor);
                cart.ProcessPayments(paymentProcessor, orderGroupCalculator);
                var orderReference = orderRepository.SaveAsPurchaseOrder(cart);
                orderRepository.Delete(cart.OrderLink);
                var purchaseOrder = orderRepository.Load<IPurchaseOrder>(orderReference.OrderGroupId);
                purchaseOrder.GetFirstForm().Shipments.First().OrderShipmentStatus = OrderShipmentStatus.Shipped;
                purchaseOrder.OrderStatus = OrderStatus.Completed;
                validationIssues = new Dictionary<ILineItem, List<ValidationIssue>>();
                purchaseOrder.AdjustInventoryOrRemoveLineItems((item, issue) => AddValidationIssues(validationIssues, item, issue), inventoryProcessor);
                orderRepository.Save(purchaseOrder);
    
            }
    
            public static void AddValidationIssues(Dictionary<ILineItem, List<ValidationIssue>> issues, ILineItem lineItem, ValidationIssue issue)
            {
                if (!issues.ContainsKey(lineItem))
                {
                    issues.Add(lineItem, new List<ValidationIssue>());
                }
    
                if (!issues[lineItem].Contains(issue))
                {
                    issues[lineItem].Add(issue);
                }
            }

    #185347 Nov 15, 2017 21:07