Good question. I don't have an answer out of my head but I will make sure to look into it
How did you create the wishlists? I suppose you used the old, concrete APIs. So to options for you is to:
So there is no perfect way to do it. The first option can be written as a migration step to migrate all of your wishlists to make sure they have a proper shipment attached.
Hi Quan,
Yes, we used the old CartHelper and had an ExtCartHelper that used the CartHelper's AddEntry and also would set the OrderForm.Parent[metaFieldName] to the name the user wanted to save the list as.
Creating a shipment for every wishlist would seem to be an unnecessary step for something like a wishlist, but I understand under the new API that it is needed. It's a few extra steps for the current wishlists, but I'm sure the calls wouldn't need to be made for wishlists created under the new process and I can account for that by checking to make sure if a shipment exists for it and if it doesn't then create one.
Thank you,
Kevin Larsen
Hi,
I made changes to the way that the page loads so that it checks the cart for a shipment and if it does not then it will create a shipment and then get the line items for the order with the code below.
if (cart.GetFirstShipment() != null)
{
lineItems = cart.GetFirstShipment().LineItems.ToList();
}
else
{
// If shipment does not exist it is old wishlist, create shipment and add wishlist lineItems to it for future loads
lineItems = cart.GetAllLineItems().ToList();
var shipment = orderGroupFactory.CreateShipment(cart);
cart.AddShipment(shipment, orderGroupFactory);
shipment.ShippingAddress = orderGroupFactory.CreateOrderAddress(cart);
foreach (var item in lineItems)
{
var lItem = orderGroupFactory.CreateLineItem(item.Code, cart);
cart.AddLineItem(lItem, orderGroupFactory);
}
orderRepository.Save(cart);
// Get lineItems from created shipment
lineItems = cart.GetFirstShipment().LineItems.ToList();
}
I did notice that when this ran, the LineItem table would have two lines per item, one looking to be the old one and the other being the new one. When I ran the below code, which deletes a line item from the wishlist, it looks to remove the duplicate line for the deleted item and also any other old duplicate line item leaving any of the remaining line items that would be attached to the shipment. Below is the code that I'm using to delete a line item.
// Get the wishlist that the product should be removed from
var orderRepository = ServiceLocator.Current.GetInstance<IOrderRepository>();
var cart = orderRepository.Load<ICart>(wishlistId);
// Remove product from wishlist
var shipment = cart.GetFirstShipment();
if (shipment != null)
{
var lineItem = shipment.LineItems.FirstOrDefault(x => x.Code == productCode);
shipment.LineItems.Remove(lineItem);
}
orderRepository.Save(cart);
Would there be something in there that would "validate" the line items and remove any duplicates? I know there is the ValidateOrRemoveLineItems validation, but I don't know if that would be used to remove the old line items from the LineItem table, or if it would remove the new line items because I'm not adding any additional information like quantity or placed price.
Thank you,
Kevin Larsen
Hello Kevin.
The reason for that behaviour is that the old lineitems still exist on the OrderForm since they haven't been removed by any part of the API or explicitly by you.
The APIs for removing work on the LineItem.Code level. If you remove a lineitem from a shipment it triggers code that checks if it should also remove it from the OrderForm level. It removes any LineItems with the same Code that aren't a part of a shipment. (So that includes the duplicate)
It's probably best to remove duplicates when running your legacy handling code. Something like this will probably (untested by me :D) do the trick:
private void MyWishListLogic(ICart cart)
{
if (IsLegacyWishList(cart))
UpdateLegacyWishList(cart);
var lineItems = cart.GetAllLineItems().ToList();
// Show wishlist
}
private void UpdateLegacyWishList(ICart cart)
{
var codes = cart.GetAllLineItems().Select(x => x.Code); // Keep a reference of all current codes
(cart.GetFirstForm() as OrderForm)?.LineItems?.Clear(); // Clear all lineitems from the orderform.
var shipment = orderGroupFactory.CreateShipment(cart);
cart.AddShipment(shipment, orderGroupFactory);
shipment.ShippingAddress = orderGroupFactory.CreateOrderAddress(cart);
foreach (var code in codes)
{
var lineItem = orderGroupFactory.CreateLineItem(code, cart);
cart.AddLineItem(lineItem, orderGroupFactory);
}
orderRepository.Save(cart);
}
private bool IsLegacyWishList(ICart cart)
{
return cart.Name == Mediachase.Commerce.Orders.Cart.WishListName // or whatever the wishlist names are.
&& cart.GetFirstShipment() == null;
}
The main takeaway being the clearing of the old orderform as a new step in the process of porting the legacy wishlist.
You can ignore my refactor if you want. :P
@Jafet: it's even better if " The first option can be written as a migration step to migrate all of your wishlists to make sure they have a proper shipment attached."
So you don't have to care about IsLegacyWishList ever again
@Kevin
Do you have an estimate on how many wishlists would need to be updated this way?
The number of wishlists is probably not that big. I don't see it being any more than 250, and even being over 100 would be a bit of a surprise.
I was able to take the code that you wrote, Jafet, and incorporate it in what I had. Had to add a call .ToList() when gathering the codes, but other than that it did solve the issue.
There are few additional things that I still want to make sure are moved over in this check, such as setting the quantity and placed price which are easy, but also columns like MaxQty that are in the LineItem table. I've struggled trying to figure out how to use the lineItem.Properties[] hashtable to get the metafields to set from the LineItem, but I also may not fully grasp what is all needed to be done to use it.
Would making it a migration step be part of the migration that is ran after the first time the site loads after the upgrade, or would I just have to create a job that could be ran after the upgarde?
Thank you,
Kevin Larsen
Hello,
We are moving away from the CartHelper and are starting to use the new cart APIs (CMS 11.9.1 and Commerce 11.8.5) and I've run into an issue with our Wishlists. In the documentation for removing an item from the cart it shows to delete it from the shipment.
The wishlists that we currently have only have the LineItem, OrderForm, and OrderGroup tables populated, but no shipment is ever created. I tried to find another way to remove the line item from the LineItem table, but haven't found any method that would do so. Would we have to create a shipment for the Wishlists so we can delete the item using the new cart API or am I just missing a different way of doing this?
Thank you,
Kevin Larsen