You can implement, or intercept - IProfileMigrator - to change that behavior.
However it's a bit "strange" way to handle carts. Yes it's up to your business, but normally you convert to order first then complete it. The system is built around that flow. Not saying you are doing it wrong. But there might be "easy" way to do things
We use smartpay which has a separate callback URL for the payment which we need posting in to our system. We wanted to be able to complete the cart to a PO only once this notification has been recieved and it's a successful so it made sense (as the status was there) to complete the cart and then process the cart in to a PO once we had all the correct information. I don't remember ever seeing any documentation that showed any flow around this so that developers knew a specific way this should be handled, it's not https://world.episerver.com/documentation/developer-guides/commerce/orders/order-system-overview/ where I would think it would be.
This really leaves me having to either rewrite the whole process or changing IProfileMigrator just so that it doesn't merge completed carts....
I guess I would have thought any merge code would only merge across the same statuses, if you've got a basket in progress you only want it merged with another in progress, not with any other status. This is the only issues with the way things are working
Also looking at the classes the problem with overriding the IProfileMigrator is that it's using concrete class CartMigrator for the cart migration. Although this isn't sealed a lot of the methods are private and when copied are using internal helper methods which makes it's a mess of a task just to stop it doing merged with completed carts....
Not sure if that is a problem. You can just load the cart and don't do anything if it is completed. Otherwise fall back to the default implementation
updating as I got an email alert, In the end for this I rewrote the whole system to convert to a puchase order and set as InProgress after coming back from our payment provider and then update it to completed later.
My problem with this is if there's status codes for a basket of being completed I wouldn't expect to merge it when logging in as it's completed. I didn't see any documentation around any flow of how this should be handled so it would be nice to have some (I will likely write a blog post) and also it would be nice to have maybe some appSettings like with the cart cleanup that could allow certain types of carts or statuses to be ignored out of the box. At the moment it's just a bit rigid, yes I know I can override it but a bit of flexibility would be nice.
We have recently implemented a payment provider that sent back the success of a payment via an Async postback. At this point the cart and customer details are null as it's outside the current flow. However what we did to get around this is to send the CartID as the unique reference to the payment provider. When they returned this to us in the postback as a successful order we loaded the cart by this Id and proceeded from there.
That way no purchase order is raised until a successful payment has been made. Hope this helps someone in future.
We have a cart process where once a cart has completed the primary payment the cart is changed to the completed status. After that there's a scheduled job that has to do a load of API work and calculate information and then covers the carts to a Purchase order.
The problem we have is if you have a cart in "Completed" and then you add items to a cart anonymously and then login in as that user the cart merge seems to be adding the items to the completed cart which really just doesn't seem right. It should only be doing in for InProgress carts.