Exchange rate wrong upon 2 currencies with different rounding rules EUR and CZK

Started by stAn99, March 09, 2016, 15:54:27 PM

Previous topic - Next topic

stAn99

Problem:
when using EUR as vendor currency and CZK as customer selected currency, the shipping value of 3.30 eur gets rounded to 3 eur and further calculated to CZK which is an obviously wrong calculation.

VM3.0.12 + Joomla 3.x

Configuration:
- EUR (2 decimal rounding)
- CZK (0 decimal rounding)
- price config is all to "-1" (follow currency config)
- checkout "use swiss rounding" (but doesn't play a role here)

Shipping price 3.30 euro (weight countries)

Quick fix:
- remove all roundinternal from vmpsplugin.php:


this is a "quick fix" and we are still working on a better "real world fix":

function setCartPrices (VirtueMartCart $cart, &$cart_prices, $method, $progressive = true) {

$c = array();
$idN = 'virtuemart_'.$this->_psType.'method_id';

$_psType = ucfirst ($this->_psType);

/*if(isset($c[$this->_psType][$method->$idN])){
$cart_prices = array_merge($cart_prices,$c[$this->_psType][$method->$idN]);
return $cart_prices['salesPrice' . $_psType];
}*/

if (!class_exists ('calculationHelper')) {
require(VMPATH_ADMIN . DS . 'helpers' . DS . 'calculationh.php');
}

$calculator = calculationHelper::getInstance ();

$cart_prices[$this->_psType . 'Value'] = $this->getCosts ($cart, $method, $cart_prices); //, 'salesPrice');
if(!isset($cart_prices[$this->_psType . 'Value'])) $cart_prices[$this->_psType . 'Value'] = 0.0;
if(!isset($cart_prices[$this->_psType . 'Tax'])) $cart_prices[$this->_psType . 'Tax'] = 0.0;

if($this->_psType=='payment'){
$cartTotalAmountOrig=$this->getCartAmount($cart_prices);

if(!$progressive){
//Simple
$cartTotalAmount=($cartTotalAmountOrig + $method->cost_per_transaction) * (1 +($method->cost_percent_total * 0.01));
//vmdebug('Simple $cartTotalAmount = ('.$cartTotalAmountOrig.' + '.$method->cost_per_transaction.') * (1 + ('.$method->cost_percent_total.' * 0.01)) = '.$cartTotalAmount );
//vmdebug('Simple $cartTotalAmount = '.($cartTotalAmountOrig + $method->cost_per_transaction).' * '. (1 + $method->cost_percent_total * 0.01) .' = '.$cartTotalAmount );
} else {
//progressive
$cartTotalAmount = ($cartTotalAmountOrig + $method->cost_per_transaction) / (1 -($method->cost_percent_total * 0.01));
//vmdebug('Progressive $cartTotalAmount = ('.$cartTotalAmountOrig.' + '.$method->cost_per_transaction.') / (1 - ('.$method->cost_percent_total.' * 0.01)) = '.$cartTotalAmount );
//vmdebug('Progressive $cartTotalAmount = '.($cartTotalAmountOrig + $method->cost_per_transaction) .' / '. (1 - $method->cost_percent_total * 0.01) .' = '.$cartTotalAmount );
}

$cart_prices[$this->_psType . 'Value'] = $cartTotalAmount - $cartTotalAmountOrig;
if(!empty($method->cost_min_transaction) and $method->cost_min_transaction!='' and $cart_prices[$this->_psType . 'Value'] < $method->cost_min_transaction){
$cart_prices[$this->_psType . 'Value'] = $method->cost_min_transaction;

}
}

if(!isset($cart_prices['salesPrice' . $_psType])) $cart_prices['salesPrice' . $_psType] = $cart_prices[$this->_psType . 'Value'];

$taxrules = array();
if(isset($method->tax_id) and (int)$method->tax_id === -1){

} else if (!empty($method->tax_id)) {
$cart_prices[$this->_psType . '_calc_id'] = $method->tax_id;

$db = JFactory::getDBO ();
$q = 'SELECT * FROM #__virtuemart_calcs WHERE `virtuemart_calc_id`="' . $method->tax_id . '" ';
$db->setQuery ($q);
$taxrules = $db->loadAssocList ();

if(!empty($taxrules) ){
foreach($taxrules as &$rule){
if(!isset($rule['subTotal'])) $rule['subTotal'] = 0;
if(!isset($rule['taxAmount'])) $rule['taxAmount'] = 0;
$rule['subTotalOld'] = $rule['subTotal'];
$rule['taxAmountOld'] = $rule['taxAmount'];
$rule['taxAmount'] = 0;
$rule['subTotal'] = $cart_prices[$this->_psType . 'Value'];
$cart_prices[$this->_psType . 'TaxPerID'][$rule['virtuemart_calc_id']] = $calculator->interpreteMathOp($rule, $rule['subTotal']) - $rule['subTotal']; //, 'salesPrice');
$cart_prices[$this->_psType . 'Tax'] += $cart_prices[$this->_psType . 'TaxPerID'][$rule['virtuemart_calc_id']];
}
}
} else {

$taxrules = array_merge($cart->cartData['VatTax'],$cart->cartData['taxRulesBill']);
$cartdiscountBeforeTax = $calculator->cartRuleCalculation($cart->cartData['DBTaxRulesBill']); //, $cart->cartPrices['salesPrice']));

if(!empty($taxrules) ){

foreach($taxrules as &$rule){
//Quickn dirty
if(!isset($rule['calc_kind'])) $rule = (array)VmModel::getModel('calc')->getCalc($rule['virtuemart_calc_id']);

if(!isset($rule['subTotal'])) $rule['subTotal'] = 0;
if(!isset($rule['taxAmount'])) $rule['taxAmount'] = 0;
if(!isset($rule['DBTax'])) $rule['DBTax'] = 0;
if(!isset($rule['percentage']) && $rule['subTotal'] < $cart->cartPrices['salesPrice']) {
$rule['percentage'] = ($rule['subTotal'] + $rule['DBTax']) / ($cart->cartPrices['salesPrice'] + $cartdiscountBeforeTax);
} else if(!isset($rule['percentage'])) {
$rule['percentage'] = 1;
}
$rule['subTotalOld'] = $rule['subTotal'];
$rule['subTotal'] = 0;
$rule['taxAmountOld'] = $rule['taxAmount'];
$rule['taxAmount'] = 0;
}

foreach($taxrules as &$rule){
$rule['subTotal'] = $cart_prices[$this->_psType . 'Value'] * $rule['percentage'];

if(!isset($cart_prices[$this->_psType . 'Tax'])) $cart_prices[$this->_psType . 'Tax'] = 0.0;
$cart_prices[$this->_psType . 'TaxPerID'][$rule['virtuemart_calc_id']] = $calculator->interpreteMathOp($rule, $rule['subTotal']) - $rule['subTotal']; //, 'salesPrice');
$cart_prices[$this->_psType . 'Tax'] += $cart_prices[$this->_psType . 'TaxPerID'][$rule['virtuemart_calc_id']];

}
}
}

if(empty($method->cost_per_transaction)) $method->cost_per_transaction = 0.0;
if(empty($method->cost_min_transaction)) $method->cost_min_transaction = 0.0;
if(empty($method->cost_percent_total)) $method->cost_percent_total = 0.0;

if (count ($taxrules) > 0 ) {

$cart_prices['salesPrice' . $_psType] = $calculator->executeCalculation ($taxrules, $cart_prices[$this->_psType . 'Value'],true,false); //, 'salesPrice');
// $cart_prices[$this->_psType . 'Tax'] = $calculator->roundInternal (($cart_prices['salesPrice' . $_psType] -  $cart_prices[$this->_psType . 'Value']), 'salesPrice');
reset($taxrules);

foreach($taxrules as &$rule){
if(!isset($cart_prices[$this->_psType . '_calc_id']) or !is_array($cart_prices[$this->_psType . '_calc_id'])) $cart_prices[$this->_psType . '_calc_id'] = array();
$cart_prices[$this->_psType . '_calc_id'][] = $rule['virtuemart_calc_id'];

if(isset($rule['subTotalOld'])) $rule['subTotal'] += $rule['subTotalOld'];
if(isset($rule['taxAmountOld'])) $rule['taxAmount'] += $rule['taxAmountOld'];
}

} else {

$cart_prices['salesPrice' . $_psType] = $cart_prices[$this->_psType . 'Value'];
$cart_prices[$this->_psType . 'Tax'] = 0;
$cart_prices[$this->_psType . '_calc_id'] = 0;
}
//$c[$this->_psType][$method->$idN] =& $cart_prices;
//if($_psType='Shipment')vmTrace('setCartPrices '.$cart_prices['salesPrice' . $_psType]);




return $cart_prices['salesPrice' . $_psType];

}




the above code is from vm3.0.12 and it suffers from more issues then just this one:
- if "default tax rules" are used, the foreach loop uses ALL calculation rules instead of just picking one and exiting... OR checking the rules agains the products in the cart OR other logic
- since this is quite core calculation, i believe it should be all located in calculationh.php

best regards, stan
----
RuposTel.com
www.rupostel.com
Your customized checkout solution for Virtuemart

Milbo

Please enter the value with a DOT, not comma, then it works correctly
Should I fix your bug, please support the VirtueMart project and become a member
______________________________________
Extensions approved by the core team: http://extensions.virtuemart.net/