Our monthly Virtual Happy Hour is happening today (Fri Feb 23)!
Hi All,Commerce version 12.5.0What is the correct way to split shipments in code? For example, I have a shipment that has 1 lineitem qty 5. Via integration we receive a request to split the shipment (for whatever reason) into 2 shipments. Shipment 1 has qty 2, Shipment 2 has qty 3.Currently we create the shipment via OrderGroupExtensions, set the shipping method (this is a $0 shipping method since we don't want to charge for shipping again), add lineitems (again via CreateLineItem in OrderGroupExtensions), set appropriate properties, etc. Then call ReleaseShipment on the ShipmentProcessor and Save on the OrderRepository - this all seems to work fine on a straight forward shipment. What I've noticed on a lineitem that has a discount is that the LineItemDiscountAmount doesn't get updated for the original or split item, so I think I either need to do that manually or call a Processor/Calculator..? Any advise on process or sample code would be great.ThanksMark
Normally splitting shipment should mean recalculating discounts because changed shipping total etc. Means different discounts and taxes. Do you have a reason not to?
No reason, someone else wrote this code, so just trying to determine best approach.
At this point we are dealing with a PO.So would you recommend something like ValidateAndCalculateOrder in the IOrderGroupExtensions?orderGroup.ValidateOrRemoveLineItemsorderGroup.AdjustInventoryOrRemoveLineItemsorderGroup.ApplyDiscounts
That looks about right. I know we have checks that make sure splitting shipment will work properly - i.e. you already reserved 5 for the shipment, you don't have to worry about cancelling that and reserve 2 and 3.
I'm still having issues with this. Once a lineitem has been split into multiple shipments as per my original question, what is the correct way to split the lineitem discount? or should that happen automatically?
var newShipment = po.CreateShipment(orderGroupFactory);
// Set shipment properties, i.e. shipping method, shipping address
var splitLineitem = po.CreateLineItem(lineitem.Code, orderGroupFactory);
// Set lineitem properties, i.e. quantity, price, etc...
po.UpdateShipmentLineItemQuantity(lineitem.LineItemId, (Shipment)shipment, lineitem.Quantity - splitItem.Quantity);
I believe Save calls "CalculateTotals" on the order group, but do I need to do anything else?
Are there any updated examples of manipulating purchase orders using the new api? i.e specifically splitting a lineitem.
If you run the promotion engine (i.e. ApplyDiscounts ) again, the discount should be properly distributed
I'm reluctant to do that since I'm not sure when the split will occur, i.e. straight away or days later. If days later the promotion may not be valid anymore or a new promotion may be applied when it shouldn't. I want the discount that is currently applied to just be distributed correctly after the split occurs.
If you are going to split shipments after the day it is created, it is much trickier and you can't get it to be perfectly accurate. For example you might have shipping promotion that give free shipping (or a discount) if the shipping cost is > $100. But if you accepts some quirks and inaccuracies, you can look into ILineItemDiscountAmount. Here you can set EntryAmount and OrderAmount that are lineitem-level discount amount and order-level discount amount to distribute the discounts
Thanks Quan, Yeah I was already setting the entry amount in ILineItemDiscountAmount, but the value wouldn't persist. I worked out my issue in the end and created a method similar to PurchaseOrderManager.UpdateShipmentLineItemQuantity
var originalLineItem = ((Shipment)shipment).Parent.LineItems.FirstOrDefault(x => x.LineItemId == lineItem.LineItemId);
This is the implementation of SetEntryDiscountValue
var lineItemDiscountAmounts = lineItem as ILineItemDiscountAmount;
if (lineItemDiscountAmounts == null)
lineItemDiscountAmounts.EntryAmount = value;
unless I'm missing something by a very early morning, how is that different?
Just to make sure - the values won't be persisted until you save it.
I'm iterating through the lineitems in a specific shipment to determine which ones need to be split. So my issue was updating the value on the original lineitem, setting the value on the newly created lineitem wasn't an issue. Where I was trying to set the value my lineitem was actually a SerializableLineItem rather than a LineItem, so when I call _orderRepository.Save(po) the value didn't persist.
For the new lineitem I use
newItem.TrySetDiscountValue(l => l.EntryAmount, newEntryAmount);