Page 1 of 1
Order Total and Payment Total Rounding problem
Posted: Wed Jul 28, 2010 12:51 am
by Alan Rich
Using 7.04, build 13424
I need 4 decimal places on product prices, so currency is set to 4 decimals. This causes some order totals to include fractions of a penny. I am not using OnePageCheckout because I need a custom address selection scheme. Checkout\Default.aspx uses my custom address selection page (which never references the order or basket objects) and then redirects to the ShipMethod page. Then on to the PaymentPage.aspx which shows the order total rounded to 2 decimals. When I pay by purchase order, the receipt page shows the rounded payment amount, but the order total now shows the true (unrounded) amount. So there's like a few pennies of a credit mismatch and the order status shows Payment Pending. Is this a bug? Is the basket.Items.TotalPrice() function not rounding the same way as the GetBasketSubtotal function?
I can add a miscellaneous charge of 0.0014 (or some such) and let the order complete, but this not elegant. And I do not want users to see orders and email confirmations with fractions of cents in any line or order totals. Suggestions?
-=Alan=-
Re: Order Total and Payment Total Rounding problem
Posted: Wed Jul 28, 2010 1:07 am
by Alan Rich
Same thing happens with Credit Card payment (using the Ablecommerce Test Gateway)
-=A=-
Re: Order Total and Payemnt Total Rounding problem
Posted: Wed Jul 28, 2010 6:35 am
by jmestep
I had run into the problem with custom code and once I made sure my figures were rounded the way Able's were, the problem went away. I used something like this:
Code: Select all
Double halfPrice = Math.Round(AlwaysConvert.ToDouble(_Product.Price/2),2,MidpointRounding.AwayFromZero);
LSDecimal dhalfPrice = AlwaysConvert.ToDecimal(halfPrice);
SecondPrice.Text = dhalfPrice.ToString("ulc");
Re: Order Total and Payment Total Rounding problem
Posted: Wed Jul 28, 2010 10:04 am
by Alan Rich
Thanks for the response jmestep!
However, I'm not quite sure where that code should go. Do I need to make a custom BasketTotalSummary.ascx control?
Re: Order Total and Payment Total Rounding problem
Posted: Wed Jul 28, 2010 10:23 am
by Alan Rich
Nope, not BasketTotalSummary.ascx. That's simply a display widget. It's like the Basket.Recalculate function is inconsistent. (Or perhaps the Basket.Items.TotalPrice() function)
Those two are in the .dll, thus I cannot examine or update those. Hence, my suspicion of a bug. But if others are not having this problem, then my custom stuff must be the culprit.
Re: Order Total and Payment Total Rounding problem
Posted: Wed Jul 28, 2010 12:02 pm
by jmestep
That code would go wherever your custom code is located. No one else is reporting the problem with standard Able code.
Re: Order Total and Payment Total Rounding problem
Posted: Wed Jul 28, 2010 4:16 pm
by Alan Rich
Well I removed my mods, went back to OnePagecheckout and still have the same results. So, it "seems" the checkout process is recalculating the basket's total price without using GetShopExtendedPrice values, but instead is calculating a running total from (basketitem.price * basketitem.quantity). I am at a total loss as to what to do next.
Re: Order Total and Payment Total Rounding problem
Posted: Wed Jul 28, 2010 8:36 pm
by Alan Rich
OK. So I decided to live with an extra CHARGE or DISCOUNT order line being added to account for the rounding discrepancy. I added the following code right before the checkout occurs in the PurchaseOrderPaymentForm.ascx file:
(I'm still learning C# so it may not be the most efficient or best way, but it works.)
Right after:
Code: Select all
protected void PurchaseOrderButton_Click(object sender, EventArgs e)
{
if (Page.IsValid)
{
//CREATE THE PAYMENT OBJECT
Payment payment = GetPayment();
//PROCESS CHECKING OUT EVENT
bool checkOut = true;
if (CheckingOut != null)
{
CheckingOutEventArgs c = new CheckingOutEventArgs(payment);
CheckingOut(this, c);
checkOut = !c.Cancel;
}
if (checkOut)
{
I inserted:
Code: Select all
// Calculate the subtotal two ways and compare.
// 1. subtotal = basketitem.ExtendedPrice (which rounds correctly with basket.recalculate())
// 2. itemsubtotal = basketitem.Quantity * basketitem.Price (does not round, apparantly the way Checkout is doing it)
//
//If the itemsubtotal does not equal the subtotal, it indicates that the order will be created with a total including fractions of a penny (bad)
//so add a basket item (CHARGE or DISCOUNT) for the rounding amt so the resulting order will be rounded to 2 decimals
LSDecimal subtotal = 0;
LSDecimal itemsubtotal = 0;
Basket basket = Token.Instance.User.Basket;
foreach (BasketItem item in basket.Items)
{
LSDecimal extendedProductPrice = item.Quantity * item.Price;
LSDecimal extendedPrice = item.ExtendedPrice;
switch (item.OrderItemType)
{
case OrderItemType.Shipping:
case OrderItemType.Handling:
break;
case OrderItemType.Tax:
break;
case OrderItemType.Coupon:
break;
case OrderItemType.GiftWrap:
break;
default:
subtotal += extendedPrice;
itemsubtotal += extendedProductPrice;
break;
}
}
if (itemsubtotal != subtotal)
{
LSDecimal roundingdiff = (subtotal - itemsubtotal);
BasketItem _BasketItem = new BasketItem();
_BasketItem.BasketId = Token.Instance.User.Basket.BasketId;
//Determine OrderItemType to add
if (roundingdiff > 0)
{
//cart rounded up, Need a CHARGE +roundingdiff
_BasketItem.OrderItemType = OrderItemType.Charge;
}
else
{
//cart rounded down, Need a DISCOUNT (roundingdiff * -1)
_BasketItem.OrderItemType = OrderItemType.Discount;
}
_BasketItem.Price = roundingdiff;
_BasketItem.Name = "Rounding";
_BasketItem.Quantity = 1;
_BasketItem.Shippable = CommerceBuilder.Shipping.Shippable.No;
_BasketItem.Save();
Token.Instance.User.Basket.Items.Add(_BasketItem);
Token.Instance.User.Basket.Items.Save();
}
Which is followed by:
Code: Select all
//PROCESS THE CHECKOUT
CheckoutRequest checkoutRequest = new CheckoutRequest(payment);
CheckoutResponse checkoutResponse = Token.Instance.User.Basket.Checkout(checkoutRequest);
.........