Jump to content

Pricing to decimal places


keat

Recommended Posts

I've modified the database table 'pricing_quantity' to accept a few more decimal places on product pricing.

However, from the customer side, the pricing quantity rounds up/down to two decimal places.

eg buy one item for £1.00 or buy 12 for £10.50.

12 for £10.50 would make the single unit price £0.875, but this is rounded to £0.88.

 

Is it possible to have this show to three decimal places.

 

Link to comment
Share on other sites

Let's look at this:

/classes/catalogue.class.php, near line 1368-1375:
// Limit by membership
if (($prices = $GLOBALS['db']->select('CubeCart_pricing_quantity', false, array('product_id' => $product['product_id'], 'group_id' => $group_id), array('quantity' => 'ASC'))) !== false) {
  foreach ($prices as $price) {
    $price['price'] = ($GLOBALS['config']->get('config', 'catalogue_sale_mode')==2) ? ($price['price'] - ($price['price'] / 100) * $GLOBALS['config']->get('config', 'catalogue_sale_percentage')) : $price['price'];
    $price['price'] = $GLOBALS['tax']->priceFormat($price['price'], true);
    $product['discounts'][] = $price;
  }
}

The quantity pricing schedule is retrieved for this product and this customer (typically a member of group zero).

If the store is in Global Sale mode, then apply the percent off. This results in a numeric value with an unknown number of decimal places. That is nothing to be concerned about.

Then, convert the (float)price amount to a string that conforms to the currency table.

Finally, load the result into the product's 'discounts' element.

For this function, we can try to:

1. Create a custom currency where the exchange rate is 1.0000, and the decimal places is 3 (maybe 4?). Call it USX, for example.
2. Change the arguments in the call to Tax->priceFormat().

Unfortunately, the Tax class is not versatile enough to affect the display of the price in the way you want.

Coincidentally, there is a hook immediately following this that we can exploit. In the hook, we can completely recompute the display of these prices.

Link to comment
Share on other sites

I think I'd be OK if those little price break prices just showed 3 decimal places.

I guess most customers would understand the rounding up/down of the subtotal.

It's when they come to spend hundreds and all those pennies start to round up, someone will no doubt make a fuss over 20p

Link to comment
Share on other sites

As mentioned above, typical example is this battery.

Puchase one item for £1.00 or buy 12 for £10.50.

12 for £10.50 would make the single unit price £0.875, but this is rounded to £0.88.

So the customer sees £0.88 per unit, he buys 12, and expects to pay £10.56, but he's actually paying £10.50.

Great, he's better off, but it also works the other way around , making it look worse off, in which case customers will complain that they expect to pay one price, but the web charged him another.

To make every 'price break' item fit the web site isn't going to happen. The web site needs to fit what we have.

We have a printed catalogue with over 4500 items and an internal invoicing system with every price and price break already committed.

If this pricing option showed to 3 decimal places, then i'm sure customers wouldn't compain about rounding.

Link to comment
Share on other sites

Mathematically, the number of decimal places needs to be unlimited.

A price break that gets seven items that sells for 130.00 means the unit price is 18.57142857.

Practically, that is close enough to 18.57 each (total 129.99).

Many retailers have faced fines, and nastiness by customers, when the rung-up charges do not match the sticker price on the shelf.

Link to comment
Share on other sites

Indeed, as bsmither points out, this kind of operation can quickly break with limited precision, unless you are either extremely lucky or very deliberate in choosing your quantity pricing. Furthermore, since the unit price is always shown in the basket, any rounding that you do will result in the total not matching the apparent sum.

Perhaps you could look into alternatives such as creating a separate product e.g. 'Batteries, pack of 12' with the discounted price set exactly?

Another option would be to round off to 2 points of precision, so the battery would cost $0.88 in quantity and the customer overpays a few cents, whereas on others it would round down and the customer would underpay a few cents. I would not go this route if you have advertised pricing somewhere, e.g. you specifically advertise that you can buy 12 batteries for $10.50.

If you really want to allow 3 decimal places in the price, though, you could try modifying the priceFormat method in tax.class.php by changing the `$decimal_places` variable, but there are some hard-coded formatting decisions elsewhere in the code, such as in cubecart.class.php's _receipt() function:

$item['price_total'] = $GLOBALS['tax']->priceFormat(sprintf('%.2F', $item['price'] * $item['quantity']), true);

You'd have to change the formatting to '%.3F' and also look through the rest of the code for similar practices. The easiest way to find all of those would be to search for '%.2F' using Linux grep or Windows findstr functions in your cubecart directory.

Link to comment
Share on other sites

2 minutes ago, bsmither said:

Interesting... the changes made to CC6010 (maybe CC609) include removing all of the sprintf('%.2F') that preempts what priceFormat() does.

Maybe that one got missed?

There are still lots of occurrences of this type of formatting especially in the Cart class, as well as that one in the CubeCart class, and possibly others (I haven't done a global search yet). If they were they all supposed to be replaced, then whoops :P

Link to comment
Share on other sites

27 minutes ago, bsmither said:

Ok, only in the Tax class and two somethings in the Cart class.

There are 9 occurrences in the Cart class I have from the master branch:

Line 783:  $this->basket['discount'] = sprintf('%.2F', $this->_discount);
Line 784:  $this->basket['subtotal'] = sprintf('%.2F', $this->_subtotal);
Line 787:  $this->basket['total_tax'] = sprintf('%.2F', $taxes['applied']);
Line 796:  $this->basket['total'] = sprintf('%.2F', $this->_total);
Line 905:  $package['value'] = sprintf('%.2F',$package['value']);
Line 1129: $this->basket['coupons'][$key]['value_display'] = sprintf('%.2F',$discount);
Line 1132: $this->basket['coupons'][$key]['value_display'] = sprintf('%.2F',$subtotal);
Line 1205: $this->basket['coupons'][$key]['value_display'] = sprintf('%.2F',$discount);
Line 1209: $this->basket['coupons'][$key]['value_display'] = sprintf('%.2F',$subtotal);

Are you looking at the 6.1 branch, perhaps?

Link to comment
Share on other sites

I'm looking at a File Compare result between CC608 and CC609. In the Cart class, near what was line 1278, this was removed:
$ave_tax_rate = sprintf('%.4F',$ave_tax_rate);

Also, near what was line 760, this was removed:
$product['price'] = sprintf("%0.2F",$product['price']);

 

Link to comment
Share on other sites

On our V3 site we used product options to get around these price breaks.

so a customer could use the drop down and choose a pack of 1 pack, or pack of 5, or pack of 12 etc, and then multiples there of.

This has sort of worked for a few years, but can get messy when a customer orders 12 packs of 1, rather than 1 pack of 12.

Or if he wants 15 packs, does he order 15 singles or a pack of 12 and 3 singles.

 

This is a tricky one as we either stick with the old drop down options or change everything we've ever done to suit the cart.

Link to comment
Share on other sites

20 hours ago, bsmither said:

Many retailers have faced fines, and nastiness by customers, when the rung-up charges do not match the sticker price on the shelf.

Interesting how they can get away with it when selling fuel though !!

99.9p per litre.

It's physically impossible to purchase 99.9p worth of Gas.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...