I have a shop where the client enters the product price with the tax in his country. When i save it i need to remove the tax and keep only the base.
When i calculate the tax back for the clients from the same country in some cases the total price will be different with 0.01 , 0.03 then the original price.
I tried to calculate with 2 to 4 digits but it never works on all cases.
Ex: price with tax = 157, tax is 7.7% => base = 145.78 and tax amount 11.22
When i calculate the tax to the previous price base i get this:
Base: 145.78 , tax is 7.7% => 11.23 = price is 157.01
Php code i use:
$baseprice = round($fullprice / (1+($taxperc/100)),2);
On the frontend:
$tax = round($baseprice * ( $taxperc / 100 ),2);
$total = $tax + $baseprice;
Anyone have a suggestion about how to fix this ?
Thanks!
Update: after some research I found a solution is to use round with PHP_ROUND_HALF_EVEN
Update2: first solution doesnt work. 1-9 works fine, 10 -tax + tax =10.01
Today's solution would be to work on the back with full number of digits ( for base price, tax and total ) and only when display for user to round it. :)
Seems ( not 100% sure yet, i need to test more ) a solution is to use the banker's rounding PHP_ROUND_HALF_EVEN
$baseprice = round($fullprice / (1+($taxperc/100)),2 , PHP_ROUND_HALF_EVEN);
$tax = round($baseprice * ( $taxperc / 100 ),2 , PHP_ROUND_HALF_EVEN);
$total = $tax + $baseprice;
Related
I am looking to add a very specific tax calculation to the cart and "invoice plugin" as well. Flat -+ percentage doesn't work since this is a very specific case. I just have no idea how to go about it and all the resources online seem to be about woocommerce inbuilt tax classes, which are flat rates.
Lets define the variables:
Final price = X (in this case it is 100$)
Final price is always known, since its added while creating the product in woocommerce
Subtotal Tax = Y (it's 25% of X)
Subtotal Tax - Actual Tax = Z (it's 21% tax calculation of Y)
Actual Tax amount = M (y-z)
So if final price is X = 100.00
Y = 0.25 * 100 = 25.00
Z = 25/1.21 = 20.66
M = 25.00 - 20.66 = 4.34 (rounded up to 2 decimal places)
In the cart i need to output this:
Subtotal: (X)
Price without tax: (X - Y)
Price applicable with special tax: (Z)
Special tax amount: (M)
Total Sum: (X)
I found this code to add extra fees (taxes) to the cart, but nothing that would help me achieve desired result.
// Add CUSTOM TAX
add_action( 'woocommerce_cart_calculate_fees','custom_tax_surcharge_for_swiss', 10, 1 );
function custom_tax_surcharge_for_swiss( $cart ) {
$percent = 25;
// Calculation
$surcharge = ( $cart->cart_contents_total + $cart->shipping_total ) * $percent / 100;
// Add the fee (tax third argument disabled: false)
$cart->add_fee( __( 'Custom Tax', 'woocommerce')." ($percent%)", $surcharge, false );
}
I can do the calculation myself, i just need to know how to add multiple new lines to the output so its displayed in the cart totals and later in the invoice plugin.
I am trying to do some maths to work out free items in php on my shop checkout.
Here is my code:
$bugofq = $cart_item['quantity'] * get_free_quantity($cart_item['product_id']);
$deal['freequantity'] = 10;
$deal['itemquantity'] = 5;
if($deal['freequantity'] >= 1 && $deal['itemquantity'] >= 1 && $cart_item['quantity'] > $deal['itemquantity']){
$bugofq = $cart_item['quantity'] + $deal['freequantity'];
}
So basically i am querying my database to see if a certain product exists. If it does i am then checking to see if it has any offers applied.
The above example has an offer of "buy 5 products, get 10 free".
My if statement above calculates this correctly so the total products is then 15.
However, if i add 10 products to my cart i should end up with a total of 30 products ( 5+10 + 5+10 = 30), but i end up with 20. This also happens if i add any amount of the 5. So if i add 20 products to my cart i would expect to see 60, the origial 20 and 40 free, Bu ti end up with 30.
Is there anything obviously wrong with my above cal
In your all described cases your if statement condition evaluates to true, so following code $bugofq = $cart_item['quantity'] + $deal['freequantity']; is running and as a result it is adding value of $deal['freequantity'] to $cart_item['quantity'] only once i.e. in your case it will always add 10 to the value that is why for 5 you are getting 15, for 10 you are getting 20 instead of 30, for 20 you are getting 30 instead of 60.
For correct calculation you should calculate the multiplier $c= floor($cart_item['quantity'] / $deal['itemquantity']). $c shows how many times you should apply free items package, hence the result would be $bugofq = $cart_item['quantity'] + ( $c * $deal['freequantity']);.
The formula you have only accounts for one time addition of the free count. To do it correctly you need to see how many times that addition should be applied. This you can do with the following code:
$bugofq = $cart_item['quantity']; // default case
if($deal['itemquantity'] >= 1){ // deal present
$bugofq += $deal['freequantity'] *
intdiv($cart_item['quantity'], $deal['itemquantity']);
}
I've got a significant problem in working out the percentage tax applied to a product, due to the rounding.
For example:
If you have a product which is £1.00 including 20% tax the break down would be:
0.83 ex tax
0.17 tax
1.00 total
However, if you work out the percentage increase:
round( (( ( 1 - 0.83 ) / 0.83 ) * 100), 2);
The answer is 20.48, because the actual price ex VAT is 0.8333333333
Therefore if you calculate:
round( (( ( 1 - 0.8333333333 ) /0.8333333333 ) * 100), 2);
You get the correct answer of 20.
In this case it would obviously work to round the 20.48 down to 20, but thats not a solution because some tax rates are to 2 decimal places so the assumption can't be made that you can just round the tax rate.
Am I missing something or is this impossible without knowing the original tax percentage?
0.17 is not 20% of 0.83, so your basic assumption is inaccurate( is rounded :P ).
Don't round money, calculate it without all that rounding and display rounded if need be. That avoids having to loose the precision in calculations.
A simple test will demonstrate
$price=0.8333333333;
$taxRate=21.25;
$tax=$price*$taxRate/100;
$total=$price+$tax;
$calculatedTaxRate=(($total-$price)/$price)*100; // 21.25
Since we didn't round anywhere, we can reverse engineer the tax rate always down to the dot.
Try with 20%
$price=0.8333333333;
$taxRate=20;
$tax=$price*$taxRate/100;
$total=$price+$tax;
$calculatedTaxRate=(($total-$price)/$price)*100; // 20
Wouldn't it something like:
17% VAT
85.47 taxless
85.47x0.17 = 14.53
Total: 100
So 100/1.17 = 85.47
My little-and-dirty version:
$taxrate=22; // 22%
$price=100;
$priceMinusTax=($price/(($taxrate/100)+1));
As long as you are dealing with low precision numbers, you will get a low precision answer. If you must show low precision numbers, you can round them when you show them to the user in the view, but save them as high precision numbers in the database.
Assuming your total price is £1 and tax rate is 20%:
$vatDecimal = (float) 1 + (20 / 100);
$priceExclVAT = round((1.00 / $vatDecimal), 2);
$priceDisplay = number_format($priceExclVAT, 2, ',', '.');
echo $priceDisplay;
The user enters the total amount and tax. Sometime its come form database, we can also use this code.
$actualPrice = "";
$total = 1000;//User Entry Total Amount
$gst = 18;//User Entry GST Tax %
$calculateTax = 100+$gst;
$calculateAmount = $total*100;
$actualPrice = $calculateAmount/$calculateTax;
echo $actualPrice = round($actualPrice,2);
echo $gstAmount = round($total-$actualPrice,2);
Im trying to make a calculation with the following values:
Product cost (without VAT) = 12,40 ($product)
The VAT percentage = 21%, what I will store in the database as 0,21 ($vat_perc)
The VAT is 2,604 ($vat)
edit: The VAT is per product
When I try to get the total then I get 15,00 ($total)
What I did is the following:
$total = $product + $vat
This will echo 15.004
Then I use the number_format:
echo(number_format($total,2,',','.'));
This will print 15.00
But then I want to multiply the product with 2
So that will give the following calculation:
$total = $product * 2 + $vat
Then again I use the format:
echo(number_format($total,2,',','.'));
Then the total = 30,01
I tried serveral things like ROUND en INT, but with no succes.
What am I doing wrong in this? In know that the VAT is the evil one here but I have no idea how to fix this.
$tax = round( ($price / 100) * 3.8, 2);
tax is rounded price divided by the 100 to make a clear percentage. Multiplied by the wanted stack
then you do the addition to or from your price table.
Well good to have you on the phone - maybe we can solve this faster by phone. Thank god for phones!
Cheers mate!
Here are some examples of how the numbers are rounded with PHP functions.
$product = 12.40;
$vat = 2.644;
$total = ( $product + $vat ) * 2;
var_dump( $total ); // float(30.088)
var_dump( number_format($total,2,',','.') ); // string(5) "30,09", rounded
var_dump( round( $total, 2 ) ); // float(30.09), rounded
var_dump( sprintf('%0.2f', $total ) ); // string(5) "30.09", rounded
var_dump( floor( $total * 100 ) / 100 ); // float(30.08), not rounded
All three founctions ( number_format, round, sprintf ) will round the result, to avoid the rounding and discard the decimal part after two decimal points you can use the last example.
Your initial total is 15.004 so when you call number_format that gets rounded down to 15.00. Now when you multiply by 2 your total is 15.008 which number_format will round up to 15.01. The issue isn't with the addition it is with the multiplication by 2. number_format rounds to the nearest place which for your case would be 30.01.
If you want the number to be rounded down all the time use floor, like so:
$total = floor(($product * 200)) / 100 + $vat;
echo(number_format($total,2,',','.'));
I'm trying to calculate a tax or discount value using BCMATH in PHP. I need 2 DECIMAL PLACES. Here's how i'm doing it:
bcscale(2);
$price = '60.67';
$discount = bcmul(bcdiv($price, 100), '3.8'); // calculate 3.8 percent from 60.67
// result is: 2.28
// result should be: 2.31
I could simply increase the scale to 4 or something like that and that would now give me a correct result.
So the question is: how should i do this correctly? Should i set the scale to 4 and then sprintf('%0.2f', $discount) in the end? Or is there a better way of doing this?
Bypass bcmath?
$discount = round( ($price / 100) * 3.8, 2);
// 2.31