Help Converting Desktop Script To Linnworks.net Script
B
Brian Friedman
started a topic
about 4 years ago
I found the following Desktop version script which is exactly what I need, but having not a lot of C# experience, I've been racking my brain to try to convert it to the Linworks.net version. Can anybody help? Basically the script splits an order based on stock availability.
// declare a list of unique ids System.Collections.Generic.List<System.Guid> list = new System.Collections.Generic.List<System.Guid>();
// let's collect all order items into a list, so that we can bulk check the stock level for a specific location foreach(OrderItem i in order.OrderItems){ // iterate through all order items if (i.pkStockItemId != System.Guid.Empty){ // is order item linked? list.Add(i.pkStockItemId); // if yes add to the list } }
// we can get stock levels for a list of items in bulk using the ListCombinedStockAvailablityExcludeOrderFolder method in the inventory // we will also exclude all orders in the 'Check For Split' folder from available quantity - This enables us to tell which order items we can take out of the order // and move to Ready folder List<linnworks.finaware.CommonData.Inventory.StockItemAvailability> availability = linnworks.finaware.CommonData.Inventory.ListCombinedStockAvailablityExcludeOrderFolder(list, "Check For Split", order.GetConnectionString);
debug.AddEntry(availability.Count.ToString());
List<linnworks.finaware.CommonData.Inventory.StockItemAvailability> splitoutItems = new List<linnworks.finaware.CommonData.Inventory.StockItemAvailability>(); bool allAreAvailable = true; foreach(linnworks.finaware.CommonData.Inventory.StockItemAvailability aItem in availability){ debug.AddEntry(aItem.SKU + "=" + aItem.Available.ToString()); if (aItem.Available > 0){ // if we have sufficient stock for one of the items splitoutItems.Add(aItem); }else{ allAreAvailable=false; }
// we now need to check that we have enought to fulfill the whole order line, so count all items on order for this SKU and compare with available int requiredToFulfil = 0; foreach(OrderItem i in order.OrderItems){ // itterate through all order items if (i.pkStockItemId ==aItem.pkStockItemId){ // is order item linked? requiredToFulfil += i.Qty; } } if (aItem.Available< requiredToFulfil){ allAreAvailable=false; }
}
// if nothing is available, exit if (splitoutItems.Count ==0){return;}
// if all items are available we are just going to put the order in the 'Ready' folder, and log the script as run, so that it never gets re-run if (allAreAvailable){ order.SetUnassignFromFolder("Check For Split"); order.SetAssignToAFolder("Ready"); debug.Progress(1,"Reassigning order " + order.OrderId.ToString()+" to Ready"); order.Save(0); return; }
/*Fun bit - actual splitting out of order items. Here we need to create a list called OrderSplitOutItem to identify which items we want to split out In this particular example we will take out everything we can fulfil. Also this specific example completely ignores composite item children. i.e. it will only split out the parent itself that can be fulfilled */ List<OrderSplitOutItem> splitoutList = new List<OrderSplitOutItem>(); foreach(linnworks.finaware.CommonData.Inventory.StockItemAvailability availableSKU in splitoutItems){
// find order item for the stock item and add it to the split list foreach(OrderItem i in order.OrderItems) if (i.pkStockItemId == availableSKU.pkStockItemId) { // here we need to double check that we still have something in stock if (availableSKU.Available>0){ // add to splitout list, notice that we check how many we can actually move to split item, if availablity is less than ordered quantity we only move order items we have in stock splitoutList.Add(new OrderSplitOutItem(i.rowid,(i.Qty<=availableSKU.Available ? i.Qty : availableSKU.Available))); availableSKU.Available = availableSKU.Available-(i.Qty<=availableSKU.Available ? i.Qty : availableSKU.Available); // here is a little trick, we reduce local available quantity by number of moved items - //this is to ensure that even if another order item is linked to the same stock item, we will keep available uptodate } } }
// double check again that we have something to split if (splitoutList.Count==0){return;} // add something in the progress debug.Progress(1,"Splitting out order " + order.OrderId+". "+splitoutList.Count.ToString() +" items");
//split out the items collected in the splitoutList Guid NewOrderId = order.SplitOut(splitoutList,order.fkPostalServiceId,0,"Sufficient stock split");
//save the parent order - THIS IS IMPORTANT - if you split out without saving the parent - you will end up with double orders order.Save(0); // allocate the new order to a Ready folder linnworks.finaware.CommonData.OrderData.AllocateToSingleFolder(order.GetConnectionString,NewOrderId,"Ready");
// mark the order as Macro Running not logged - this will enable Linnworks to rerun the macro for this order on next sync, i.e. The SCRIPT_EXEC audit trail step will NOT be added debug.DoNotLogScriptRun = true;
} // leave untouched
// the filter is used to limit what order we will feed into the script. this ensures we only check // orders that are allocated to Check For Split folder and only the orders that have order items that are available public string Filter(){ string query=@"SELECT o.pkOrderId FROM [Order] o INNER JOIN [Order_Folder] oh on oh.fkOrderId = o.pkOrderID AND oh.FolderName='Check For Split' INNER JOIN [OrderItem] oi on oi.fkOrderID = o.pkOrderID INNER JOIN [StockItems] sis on sis.pkStockID = oi.fkStockID INNER JOIN View_CombinedStock s on s.pkstockitemid = sis.fkStockControlStockItemId WHERE o.bProcessed =0 and o.nStatus!=0 and o.HoldOrCancel=0 and (oi.fkCompositeParentRowId is null or oi.fkCompositeParentRowId=dbo.emptyguid()) AND s.[Level]>0 GROUP BY o.pkOrderId"; return query; }
Brian Friedman
I found the following Desktop version script which is exactly what I need, but having not a lot of C# experience, I've been racking my brain to try to convert it to the Linworks.net version. Can anybody help? Basically the script splits an order based on stock availability.