November Happy Hour will be moved to Thursday December 5th.

Purchase order is null after orderRepository.SaveAsPurchaeOrder

Vote:
 

I was wondering if anyone has encountered an issue where the purchase order from OrderRepository is NULL after calling SaveAsPurchaseOrder saving a cart about once or twice a day(we have about 200 orders per day).

It seems that every part of the process before the exception is working fine. We're not getting any exceptions or indication anything went wrong before the exception. For some bizzare reason the purchase order we get back is null after the cart is successfully saved.

Here is the code that does the order processing from the cart. The problem line is below the comment "Null reference exception is thrown here because purchase order is null"

public OrderReference SaveCurrentShoppingCartAsPurchaseOrder()
{
	ICart cart = this._shoppingCartManager.GetCart();

	//Assign order number before processing for payment
	string orderNumber = this._orderNumberManager.TryIssueNewOrderNumberOrFallback(cart.MarketId, false);
	cart.Properties[PurchaseOrderConstants.OrderNumberFieldName] = orderNumber;

	using (var scope = new TransactionScope())
	{
		this._inventoryProcessor.AdjustInventoryOrRemoveLineItem(cart.GetFirstShipment(), OrderStatus.InProgress, (item, issue) => { });

		try
		{
			//Process the payment
			cart.ProcessPayments();
		}
		catch (PaymentException e)
		{
			this._inventoryProcessor.AdjustInventoryOrRemoveLineItem(cart.GetFirstShipment(), OrderStatus.Cancelled, (item, issue) => { });
			this._logManager.WriteError("Payment processing failed", e);
			throw new PaymentCouldNotBeProccessedOrIncorrectAmountWereAuthorizedException("Payment processing failed");
		}

		//Find the amount authorized / processed
		decimal totalProcessedPayment = cart.GetFirstForm().Payments.Where(p => p.Status.Equals(PaymentStatus.Processed.ToString())).Sum(p => p.Amount);
		Money cartTotal = cart.GetTotal();

		//If the processed amount were different than the total
		if (cartTotal.Amount != totalProcessedPayment)
		{
			this._inventoryProcessor.AdjustInventoryOrRemoveLineItem(cart.GetFirstShipment(), OrderStatus.Cancelled, (item, issue) => { });
			throw new PaymentCouldNotBeProccessedOrIncorrectAmountWereAuthorizedException("Wrong amount");
		}

		cart.GetFirstShipment().OrderShipmentStatus = OrderShipmentStatus.InventoryAssigned;

		try
		{
			this._inventoryProcessor.AdjustInventoryOrRemoveLineItem(cart.GetFirstShipment(), OrderStatus.Completed, (item, issue) => {
				var message = string.Format("Issue adjusting inventory for Item: {0} with issue {1} ", item.Code, issue);
				_logManager.WriteInfo(message);
			});
		}
		catch (Exception e)
		{
			_logManager.WriteError("Error adjusting inventory", e);
		}

		//Save as purchase order
		OrderReference reference = this._orderRepository.SaveAsPurchaseOrder(cart);

		//Mark order as OnHold to indicate it hasn't been queued for processing yet
		IPurchaseOrder purchaseOrder = this._orderRepository.Load<IPurchaseOrder>(orderReference.OrderGroupId);
		
		// Null reference exception is thrown here becuase purchaseOrder is NULL
		purchaseOrder.OrderStatus = OrderStatus.OnHold;

		purchaseOrder.AcceptChanges();
			
		this._orderRepository.Delete(cart.OrderLink);

		scope.Complete();

		return reference;
	}
}

So far I can only get this to happen in our preproduction or production environment so I wonder if there is some synchronization issues between the Episerver API and database in DXC.

Or maybe we're doing something not very efficient here? Also we're on Commerce 12.17.2 but it appears that we had the same issue before when we were on Commerce 11.

Thanks!

#208533
Oct 25, 2019 18:47
Vote:
 

Hi Peter

First, I would try to get rid of the TransactionScope wrapper. Or keep everything, from the Load method call and down, out of it.

I have had issues before when I tried something similar. Instead, I wrapped the logic in a try-catch block. In the catch block I log the exception, cancel the order, void the payment authorization, and so on.

Question: using the orderReference.OrderGroupId, can you actually find the purchase order in the preproduction database after the saving action, when the purchase order is NULL?

#208551
Oct 27, 2019 8:11
Vote:
 

Hi Stefan.

Thanks so much for taking a look at my question. I'm not sure if I'm looking at the correct table but I don't see a record for the purchase order in the [OrderGroup] table. I do see that the orderGroupId value for the purchase order was reserved because the ids of the records before and after the exception skip a number, but I don't see the record.

I'll talk to our implementation consultants about replacing the TransactionScope with a try-catch. I'm not sure why they used it since there isn't anything that can be cancelled by the user at this point.

Thanks,

Peter

#208667
Oct 29, 2019 19:40
Vote:
 

The OrderGroup table is where you should look in this case.

Good that you are getting the TransactionScope refactored away. It doesn't make sense to wrap your logic in a transaction, as Episerver Commerce is robust enough without it.

#208671
Oct 30, 2019 7:20
This topic was created over six months ago and has been resolved. If you have a similar question, please create a new topic and refer to this one.
* You are NOT allowed to include any hyperlinks in the post because your account hasn't associated to your company. User profile should be updated.