Jump to content

[PS1.5] Tax Exempt customers/group


Recommended Posts

Hello,

 

I have a little problem, I need to create option for my customers with TAX 0.

If they are EU members and they have registered VAT number they can buy stuff without TAX in my web store. But in Presatshop BO I can't figure it out.

 

I figure out with shipping/carrier tax (incl/excl) - everything is now tax excl. - simple change in database.

 

My question is how to do it, does anybody experience with that?

I found this solution LINK but it doesn't work.

 

Any help will be much appreciated.

BR, Marcos.

 

ver. PS1.5.2

Edited by m.andrzejak (see edit history)
Link to comment
Share on other sites

Problem solved:

 

If you need customer without TAX follow those steps:

 

Edit: classes/tax/Tax.php

 

Searh this part of code - is should be in the end of file:

/**
* Returns the product tax
*
* @param integer $id_product
* @param integer $id_country
* @return Tax
*/
public static function getProductTaxRate($id_product, $id_address = null, Context $context = null)
{
if ($context == null)
 $context = Context::getContext();
 $address = Address::initialize($id_address);
 $id_tax_rules = (int)Product::getIdTaxRulesGroupByIdProduct($id_product, $context);
 $tax_manager = TaxManagerFactory::getManager($address, $id_tax_rules);
 $tax_calculator = $tax_manager->getTaxCalculator();
 return $tax_calculator->getTotalRate();
}

 

 

Replace it with this code (It's the same as solution post above):

/**
* Returns the product tax
*
* @param integer $id_product
* @param integer $id_country
* @return Tax
*/
public static function getProductTaxRate($id_product, $id_address = null, Context $context = null)
{
/*if ($context == null)
 $context = Context::getContext();
$address = Address::initialize($id_address);
$id_tax_rules = (int)Product::getIdTaxRulesGroupByIdProduct($id_product, $context);
$tax_manager = TaxManagerFactory::getManager($address, $id_tax_rules);
$tax_calculator = $tax_manager->getTaxCalculator();
return $tax_calculator->getTotalRate();
*/

if (is_numeric($id_address)) {
$address = new Address((int)($id_address));

 // get customer groups to check for tax exempt group
 $groups = Customer::getGroupsStatic((int)($address->id_customer));
 foreach ($groups as $g) {
  $query = "SELECT name FROM group_lang WHERE id_group=$g AND id_lang=1";
  $groupname = Db::getInstance()->getValue($query);
  if (strtolower(substr($groupname, 0, 10))=="tax exempt") return 0;
 }
}
}

 

To get this work you have to follow rest steps form fbas post

4) add a group in Back Office named (or at least first 10 characters equal to) "Tax Exempt" in Language 1 (English)*

5) add qualifying customers to Tax Exempt group

Link to comment
Share on other sites

  • 2 months later...

Well I tried the mod. Exact copy of what was posted didn't work so I did get the advertised result by deleting out rather then commenting out the commented out section.

 

I also tried to delete

	if (is_numeric($id_address)) {
	$address = new Address((int)($id_address));

as I did think it would matter the address. (I don't really know what that code above does)

But that seemed to give HTTP500 error.

 

 

The code that work for me is this, BUT seems to give everyone free shipping!

Still needs further testing. If anybody has input please let me know.

 

/**
 * Returns the product tax
 *
 * @param integer $id_product
 * @param integer $id_country
 * @return Tax
 */
public static function getProductTaxRate($id_product, $id_address = null, Context $context = null)
{
 // get customer groups to check for tax exempt group
 $groups = Customer::getGroupsStatic((int)($address->id_customer));
 foreach ($groups as $g) {
  $query = "SELECT name FROM group_lang WHERE id_group=$g AND id_lang=1";
  $groupname = Db::getInstance()->getValue($query);
  if (strtolower(substr($groupname, 0, 9))=="wholesale") return 0;
 }
	}
}

 

AND THANK YOU m.andrzejak for getting this started on the right foot.

Edited by dsgnmind (see edit history)
Link to comment
Share on other sites

Hi guys, I don't like this solution at all.. What if you upgrade your Prestashop? You probably loose this script. You have to override the function.

By the way, the problem is in your query "SELECT name FROM group_lang WHERE id_group=$g AND id_lang=1"

The table is ps_group_lang instead group_lang.

Then you have to calculate taxes for customers that are in another groups, so the right script is:

 

/**
* Returns the product tax
*
* @param integer $id_product
* @param integer $id_country
* @return Tax
*/
public static function getProductTaxRate($id_product, $id_address = null, Context $context = null)
{

    if (is_numeric($id_address)) {
		    $address = new Address((int)($id_address));
	    // get customer groups to check for tax exempt group
	    $groups = Customer::getGroupsStatic((int)($address->id_customer));
	    //var_dump($groups);
	    foreach ($groups as $g) {
			    $query = "SELECT name FROM ps_group_lang WHERE id_group=$g AND id_lang=1";
			    $groupname = Db::getInstance()->getValue($query);

			    if (strtolower(substr($groupname, 0, 10))=="tax exempt"){
				 return 0;
				 }
			   }
		   }
    $context = Context::getContext();
 $address = Address::initialize($id_address);
 $id_tax_rules = (int)Product::getIdTaxRulesGroupByIdProduct($id_product, $context);
 $tax_manager = TaxManagerFactory::getManager($address, $id_tax_rules);
 $tax_calculator = $tax_manager->getTaxCalculator();
 return $tax_calculator->getTotalRate();	  





}

 

Sorry for my bad bad english, hope this is useful. When I find out an override for the function I'll post here the code ;)

Link to comment
Share on other sites

Put the code in override/classes/tax/Tax.php , code look like this

class Tax extends TaxCore
{
/**
* Returns the product tax
*
* @param integer $id_product
* @param integer $id_country
* @return Tax
*/
public static function getProductTaxRate($id_product, $id_address = null, Context $context = null)
{
/*if ($context == null)
 $context = Context::getContext();
$address = Address::initialize($id_address);
$id_tax_rules = (int)Product::getIdTaxRulesGroupByIdProduct($id_product, $context);
$tax_manager = TaxManagerFactory::getManager($address, $id_tax_rules);
$tax_calculator = $tax_manager->getTaxCalculator();
return $tax_calculator->getTotalRate();
*/
    if (is_numeric($id_address)) {
		    $address = new Address((int)($id_address));
	    // get customer groups to check for tax exempt group
	    $groups = Customer::getGroupsStatic((int)($address->id_customer));
	    //var_dump($groups);
	    foreach ($groups as $g) {
			    $query = "SELECT name FROM ps_group_lang WHERE id_group=$g AND id_lang=1";
			    $groupname = Db::getInstance()->getValue($query);

			    if (strtolower(substr($groupname, 0, 10))=="tax exempt"){
				 return 0;
				 }
			   }
		   }
    $context = Context::getContext();
 $address = Address::initialize($id_address);
 $id_tax_rules = (int)Product::getIdTaxRulesGroupByIdProduct($id_product, $context);
 $tax_manager = TaxManagerFactory::getManager($address, $id_tax_rules);
 $tax_calculator = $tax_manager->getTaxCalculator();
 return $tax_calculator->getTotalRate();	  





}

 

With this solution (it's orrible, I know that :D ) you can upgrade your prestashop without loose the script

Link to comment
Share on other sites

Well I tried your code Aleolly And I feel that I'm not getting something right.

 

I tried pasting your code into the Tax.php under root/overide/classes/tax and no go.

One uncertainty is if removing the <?php that is there or leaving it OR replacing the file completely starting with the tax.php file under root/classes/tax and going from there.

 

I tried each and the site fails each time.

Tried clearing the cache folder and browser cache - still nothing.

I also tried the code mod and replaced the file under the root/classes/tax folder - ignoring the override folder and also a no go.

Just crashes the site.

If i put the original back - the site is back up with no problems.

 

I do need to have the group name be 'wholesale' because the group, customer and discounts are already applied using that name - so am i right in changing the code to:

if (strtolower(substr($groupname, 0, 9))=="wholesale"){

 

i feel like i'm getting something extraordinary simple wrong like i'm missing a { or } somewhere.

Any help or advise would be great. And if anybody else has applied this successfully please post.

Link to comment
Share on other sites

Hi, the correct path is root/override/classes/tax/Tax.php

If you have the file yet, just copy the part you needinside the function. At the end the code have to looks like the posted code, but wrapped in <?php ....... ?> tags.

You have to create a group with name wholesale (in english field translation).

On monday i'll check the code again but i've copied that with ctrl-c then ctrl-v , so i think is correct. It works on my site. If your site crashed is probably a sintax error.

Let me know if it works

Link to comment
Share on other sites

Well I can get prestashop to accept the file if I add a } to the end - but no wholesale = 0 tax.

 

Here is the whole code for my tax.php file under the root/classes/tax folder.

We will probably not upgrade so I'm not worried about using the override folder at this time.

 

<?php
/*
* 2007-2012 PrestaShop
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://opensource.org/licenses/osl-3.0.php
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to http://www.prestashop.com for more information.
*
*  @author PrestaShop SA <[email protected]>
*  @copyright  2007-2012 PrestaShop SA
*  @license	http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
*  International Registered Trademark & Property of PrestaShop SA
*/

class TaxCore extends ObjectModel
{
 /** @var string Name */
public $name;
/** @var float Rate (%) */
public $rate;
/** @var bool active state */
public $active;
/** @var boolean true if the tax has been historized */
public $deleted = 0;
/**
 * @see ObjectModel::$definition
 */
public static $definition = array(
 'table' => 'tax',
 'primary' => 'id_tax',
 'multilang' => true,
 'fields' => array(
  'rate' =>	array('type' => self::TYPE_FLOAT, 'validate' => 'isFloat', 'required' => true),
  'active' =>   array('type' => self::TYPE_BOOL),
  'deleted' =>   array('type' => self::TYPE_BOOL),
  // Lang fields
  'name' =>	array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'required' => true, 'size' => 32),
 ),
);

protected static $_product_country_tax = array();
protected static $_product_tax_via_rules = array();
protected $webserviceParameters = array(
 'objectsNodeName' => 'taxes',
);
public function delete()
{
 /* Clean associations */
 TaxRule::deleteTaxRuleByIdTax((int)$this->id);
 if ($this->isUsed())
  return $this->historize();
 else
  return parent::delete();
}
/**
 * Save the object with the field deleted to true
 *
 *  @return bool
 */
public function historize()
{
 $this->deleted = true;
 return parent::update();
}
public function toggleStatus()
{
 if (parent::toggleStatus())
		return $this->_onStatusChange();
	return false;
}
public function update($nullValues = false)
{
 if (!$this->deleted && $this->isUsed())
 {
  $historized_tax = new Tax($this->id);
  $historized_tax->historize();
  // remove the id in order to create a new object
  $this->id = 0;
  $this->add();
  // change tax id in the tax rule table
  TaxRule::swapTaxId($historized_tax->id, $this->id);
 } else if (parent::update($nullValues))
		 return $this->_onStatusChange();
	return false;
}
protected function _onStatusChange()
{
	if (!$this->active)
		return TaxRule::deleteTaxRuleByIdTax($this->id);
	return true;
}
/**
 * Returns true if the tax is used in an order details
 *
 * @return bool
 */
public function isUsed()
{
 return Db::getInstance()->getValue('
 SELECT `id_tax`
 FROM `'._DB_PREFIX_.'order_detail_tax`
 WHERE `id_tax` = '.(int)$this->id
 );
}
/**
* Get all available taxes
*
* @return array Taxes
*/
public static function getTaxes($id_lang = false, $active_only = true)
{
 $sql = new DbQuery();
 $sql->select('t.id_tax, t.rate');
 $sql->from('tax', 't');
 $sql->where('t.`deleted` != 1');
 if ($id_lang)
 {
  $sql->select('tl.name, tl.id_lang');
  $sql->leftJoin('tax_lang', 'tl', 't.`id_tax` = tl.`id_tax` AND tl.`id_lang` = '.(int)$id_lang);
  $sql->orderBy('`name` ASC');
 }
 if ($active_only)
  $sql->where('t.`active` = 1');
 return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql);
}
public static function excludeTaxeOption()
{
 static $ps_tax = null;
 if ($ps_tax === null)
  $ps_tax = Configuration::get('PS_TAX');
 return !$ps_tax;
}
/**
* Return the tax id associated to the specified name
*
* @param string $tax_name
* @param boolean $active (true by default)
*/
public static function getTaxIdByName($tax_name, $active = 1)
{
 $tax = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow('
  SELECT t.`id_tax`
  FROM `'._DB_PREFIX_.'tax` t
  LEFT JOIN `'._DB_PREFIX_.'tax_lang` tl ON (tl.id_tax = t.id_tax)
  WHERE tl.`name` = \''.pSQL($tax_name).'\' '.
  ($active == 1 ? ' AND t.`active` = 1' : ''));
 return $tax ? (int)($tax['id_tax']) : false;
}
/**
* Returns the ecotax tax rate
*
* @param id_address
* @return float $tax_rate
*/
public static function getProductEcotaxRate($id_address = null)
{
 $address = Address::initialize($id_address);
 $tax_manager = TaxManagerFactory::getManager($address, (int)Configuration::get('PS_ECOTAX_TAX_RULES_GROUP_ID'));
 $tax_calculator = $tax_manager->getTaxCalculator();
 return $tax_calculator->getTotalRate();
}
/**
* Returns the carrier tax rate
*
* @param id_address
* @return float $tax_rate
*/
public static function getCarrierTaxRate($id_carrier, $id_address = null)
{
 $address = Address::initialize($id_address);
 $id_tax_rules = (int)Carrier::getIdTaxRulesGroupByIdCarrier((int)$id_carrier);
 $tax_manager = TaxManagerFactory::getManager($address, $id_tax_rules);
 $tax_calculator = $tax_manager->getTaxCalculator();
 return $tax_calculator->getTotalRate();
}
/**
 * Return the product tax rate using the tax rules system
 *
 * @param integer $id_product
 * @param integer $id_country
 * @return Tax
 *
 * @deprecated since 1.5
 */
public static function getProductTaxRateViaRules($id_product, $id_country, $id_state, $zipcode)
{
 Tools::displayAsDeprecated();
 if (!isset(self::$_product_tax_via_rules[$id_product.'-'.$id_country.'-'.$id_state.'-'.$zipcode]))
 {
  $tax_rate = TaxRulesGroup::getTaxesRate((int)Product::getIdTaxRulesGroupByIdProduct((int)$id_product), (int)$id_country, (int)$id_state, $zipcode);
  self::$_product_tax_via_rules[$id_product.'-'.$id_country.'-'.$zipcode] = $tax_rate;
 }
 return self::$_product_tax_via_rules[$id_product.'-'.$id_country.'-'.$zipcode];
}
/**
* Returns the product tax
*
* @param integer $id_product
* @param integer $id_country
* @return Tax
*/
public static function getProductTaxRate($id_product, $id_address = null, Context $context = null)
{
/*if ($context == null)
 $context = Context::getContext();
$address = Address::initialize($id_address);
$id_tax_rules = (int)Product::getIdTaxRulesGroupByIdProduct($id_product, $context);
$tax_manager = TaxManagerFactory::getManager($address, $id_tax_rules);
$tax_calculator = $tax_manager->getTaxCalculator();
return $tax_calculator->getTotalRate();
*/
		if (is_numeric($id_address)) {
						$address = new Address((int)($id_address));
				// get customer groups to check for tax exempt group
				$groups = Customer::getGroupsStatic((int)($address->id_customer));
				//var_dump($groups);
				foreach ($groups as $g) {
								$query = "SELECT name FROM ps_group_lang WHERE id_group=$g AND id_lang=1";
								$groupname = Db::getInstance()->getValue($query);

								if (strtolower(substr($groupname, 0, 9))=="Wholesale"){
									 return 0;
									 }
							   }
					   }
		$context = Context::getContext();
 $address = Address::initialize($id_address);
 $id_tax_rules = (int)Product::getIdTaxRulesGroupByIdProduct($id_product, $context);
 $tax_manager = TaxManagerFactory::getManager($address, $id_tax_rules);
 $tax_calculator = $tax_manager->getTaxCalculator();
 return $tax_calculator->getTotalRate();
}
}

 

If you take the last } away you get this (see image)

post-442115-0-89579200-1365399889_thumb.jpg

Edited by dsgnmind (see edit history)
Link to comment
Share on other sites

  • 2 months later...

Can somebody please give some input. Thanks!!!

 

Hi it work for me iam using prestashop 1.5.4.1.

 

I didnt touch anything from Tax.php from classes/tax/Tax.php, i created a Tax.php in override/classes/tax/Tax.php with the following;

 

<?php
class Tax extends TaxCore
{
/**
* Returns the product tax
*
* @param integer $id_product
* @param integer $id_country
* @return Tax
*/
public static function getProductTaxRate($id_product, $id_address = null, Context $context = null)
{
/*if ($context == null)
 $context = Context::getContext();
$address = Address::initialize($id_address);
$id_tax_rules = (int)Product::getIdTaxRulesGroupByIdProduct($id_product, $context);
$tax_manager = TaxManagerFactory::getManager($address, $id_tax_rules);
$tax_calculator = $tax_manager->getTaxCalculator();
return $tax_calculator->getTotalRate();
*/
		if (is_numeric($id_address)) {
						$address = new Address((int)($id_address));
				// get customer groups to check for tax exempt group
				$groups = Customer::getGroupsStatic((int)($address->id_customer));
				//var_dump($groups);
				foreach ($groups as $g) {
								$query = "SELECT name FROM ps_group_lang WHERE id_group=$g AND id_lang=1";
								$groupname = Db::getInstance()->getValue($query);

								if (strtolower(substr($groupname, 0, 7))=="empresa"){
									 return 0;
									 }
							   }
					   }
		$context = Context::getContext();
 $address = Address::initialize($id_address);
 $id_tax_rules = (int)Product::getIdTaxRulesGroupByIdProduct($id_product, $context);
 $tax_manager = TaxManagerFactory::getManager($address, $id_tax_rules);
 $tax_calculator = $tax_manager->getTaxCalculator();
 return $tax_calculator->getTotalRate();		





}
}

 

At first didnt work but then I erased class_index.php from /cache/class_index.php and it works!

 

Looking at you code i think you need to replace "class TaxCore extends ObjectModel" to "class Tax extends TaxCore".

Edited by nguerra (see edit history)
Link to comment
Share on other sites

@nguerra

 

I'd like to have costumers with valid European VAT, exempted from tax so I tried your code on a local 1.5.4.1 installation with European VAT module enabled, but i didn't see any result.

 

Can you give some more details on how you made it work?

Link to comment
Share on other sites

@nguerra

 

I'd like to have costumers with valid European VAT, exempted from tax so I tried your code on a local 1.5.4.1 installation with European VAT module enabled, but i didn't see any result.

 

Can you give some more details on how you made it work?

 

Did you change the name and lenght on line

   if (strtolower(substr($groupname, 0, 7))=="empresa"){

? In my case 'empresa' is the name of the group with costumers with exempted tax, and 7 the "length" of the word.

Link to comment
Share on other sites

Thanks for answering nguerra but it was a really really stupid mistake of me, nothing to do with your code, i had the wrong country setting in module...

 

Is it possible to add a "hardcoded" country prefix in VAT field before digits, for example DE for Denmark?

I need that because most costumers don't know they have to enter the prefix before the number so the check fails...

Link to comment
Share on other sites

@yanc

I think I understand you now, you are talking about de registration form? If yes try this...

 

In \themes\yourtheme\authentication.tpl at line 476 change:

 

<input type="text" class="text" name="vat_number" value="{if isset($smarty.post.vat_number)}{$smarty.post.vat_number}{/if}" />

 

With:

 

<input type="text" class="text" name="vat_number" value="{if isset($smarty.post.vat_number)}{$smarty.post.vat_number}{else}{l s='DE'}{/if}" />

Link to comment
Share on other sites

@yanc

I think I understand you now, you are talking about de registration form? If yes try this...

 

In \themes\yourtheme\authentication.tpl at line 476 change:

 

<input type="text" class="text" name="vat_number" value="{if isset($smarty.post.vat_number)}{$smarty.post.vat_number}{/if}" />

 

With:

 

<input type="text" class="text" name="vat_number" value="{if isset($smarty.post.vat_number)}{$smarty.post.vat_number}{else}{l s='DE'}{/if}" />

 

Hi nguerra.

 

Yes, that's exactly what i meant!

Just tried your code, but didn't work, i edited both theme & default authentication.tpl

Link to comment
Share on other sites

Try this... in Backoffice>Advanced Parameters.

 

adv002-perfSmarty.png?version=1&modificationDate=1344444607000

 

Change template cache to force compile, and cache off, then in your browser erase all your navigation information. Dont forget to change this options to default when you upload your site to a real hosting (this is only for develop). Tell me if it work.

Link to comment
Share on other sites

  • 3 months later...

Hi it work for me iam using prestashop 1.5.4.1.

 

I didnt touch anything from Tax.php from classes/tax/Tax.php, i created a Tax.php in override/classes/tax/Tax.php with the following;

 

<?php
class Tax extends TaxCore
{
/**
* Returns the product tax
*
* @param integer $id_product
* @param integer $id_country
* @return Tax
*/
public static function getProductTaxRate($id_product, $id_address = null, Context $context = null)
{
/*if ($context == null)
  $context = Context::getContext();
$address = Address::initialize($id_address);
$id_tax_rules = (int)Product::getIdTaxRulesGroupByIdProduct($id_product, $context);
$tax_manager = TaxManagerFactory::getManager($address, $id_tax_rules);
$tax_calculator = $tax_manager->getTaxCalculator();
return $tax_calculator->getTotalRate();
*/
			if (is_numeric($id_address)) {
							$address = new Address((int)($id_address));
					// get customer groups to check for tax exempt group
					$groups = Customer::getGroupsStatic((int)($address->id_customer));
					//var_dump($groups);
					foreach ($groups as $g) {
									$query = "SELECT name FROM ps_group_lang WHERE id_group=$g AND id_lang=1";
									$groupname = Db::getInstance()->getValue($query);
								
									if (strtolower(substr($groupname, 0, 7))=="empresa"){
										 return 0;
										 }
								   }
						   }
			$context = Context::getContext();
  $address = Address::initialize($id_address);
  $id_tax_rules = (int)Product::getIdTaxRulesGroupByIdProduct($id_product, $context);
  $tax_manager = TaxManagerFactory::getManager($address, $id_tax_rules);
  $tax_calculator = $tax_manager->getTaxCalculator();
  return $tax_calculator->getTotalRate();		
						
						
						
						
						
}
}
At first didnt work but then I erased class_index.php from /cache/class_index.php and it works!

 

Looking at you code i think you need to replace "class TaxCore extends ObjectModel" to "class Tax extends TaxCore".

 

 

I tried this on PS 1.5.6.0 But it doesn't work for me.

I'm forcing recompile, deleted all cache files as well as browser cache.  I don't see any /cache/class_index.php in my files.

Any idea what else I can try please?

Link to comment
Share on other sites

  • 5 months later...

I tried this on PS 1.5.6.0 But it doesn't work for me.

I'm forcing recompile, deleted all cache files as well as browser cache.  I don't see any /cache/class_index.php in my files.

Any idea what else I can try please?

 

EDIT: see 1.6.0.14 proposal below.

 

Another solution is to be independant of the Group name and use the price_display_method value which will work for all VAT exempted groups. Works for me on 1.5.6.0 and it was not necessary to clear any cache. You do need to copy the full Tax.php file to the override/tax folder and edit the last function. Extract from end of file:

    public static function getProductTaxRate($id_product, $id_address = null, Context $context = null)
    {
/*        if ($context == null)
            $context = Context::getContext();

        $address = Address::initialize($id_address);
        $id_tax_rules = (int)Product::getIdTaxRulesGroupByIdProduct($id_product, $context);

        $tax_manager = TaxManagerFactory::getManager($address, $id_tax_rules);
        $tax_calculator = $tax_manager->getTaxCalculator();

        return $tax_calculator->getTotalRate();
*/
        
        if (is_numeric($id_address))
        {
            $address = new Address((int)($id_address));
            // get customer groups to check for tax exempt group
            $groups = Customer::getGroupsStatic((int)($address->id_customer));
            //var_dump($groups);

            foreach ($groups as $g)
            {
                $query = "SELECT price_display_method FROM ps_group WHERE id_group=$g";
                $price_display_method = Db::getInstance()->getValue($query);

                if ( $price_display_method == 1 )        // BO / Clients / Groups: 0 = including tax, 1 = excluding tax
                {
                    return 0;
                }
            }
            
        }// if is_numeric

        $context = Context::getContext();
        $address = Address::initialize($id_address);
        $id_tax_rules = (int)Product::getIdTaxRulesGroupByIdProduct($id_product, $context);
        $tax_manager = TaxManagerFactory::getManager($address, $id_tax_rules);
        $tax_calculator = $tax_manager->getTaxCalculator();
        return $tax_calculator->getTotalRate();

    }// fn getProductTaxRate
    
}// class taxcore
Edited by Spazbot (see edit history)
Link to comment
Share on other sites

  • 1 year later...
  • 2 weeks later...

Has anyone gotten this working on PS 1.6? I am using 1.6.0.14 and this code does NOT work. Tax is always calculated, even if I say return (float)0; right in the first line of my getProductTaxRate override.

@panamahatpub it so happens I have to work on this again for precisely 1.6.0.14. I'd appreciate your feedback in case I missed some of my code below.

 

My requirements: When a customer has his primary group set to a group with no VAT I want 0% VAT everywhere for products, carriers, product totals, FO and BO.

 

I threw all my overrides out and started from scratch 1.6.0.14. I gave up listing all the caller methods that would need to be overridden and decided to trick the system into thinking it is a PS_TAX=0 (don't show VAT) site. That sorts most things except carrier VAT and order total. As a bonus, the customer can browse the catalog excl. VAT when logged in.

 

DISCLAIMER: These are some of the important checks I made which anyone should do before going to prod - never know how your setup may differ from mine.

 

Tax excl. group checks:

 

FO visitor all prices incl. - OK

FO logged in prices excl. - OK

FO discounts apply excl. - OK

BO new order all prices excl. - OK

BO new order send email all prices excl. in FO - OK

BO gen invoice, VAT detail - KO, still shows up and is not zero, I just kill the VAT detail section on invoice tpl

 

Remove customer from Tax excl. group checks:

 

FO cart refreshes to all incl. - OK

FO logged in prices incl. - OK

FO discounts apply incl. - OK

BO new order all prices incl. - OK

 

Overrides:

 

override/classes/tax/tax.php::excludeTaxeOption

override/classes/cart.php::getPackageShippingCost

override/classes.cart.php::getOrderTotal

 

The files:

 

EDIT: Updated to use buit in constant PS_TAX_EXC

EDIT: Added Cart->getProducts override due to total being recalculated with VAT by PayPal module

 

override/classes/tax/tax.php

<?php

class Tax extends TaxCore
{
    public static function excludeTaxeOption()
    {
        static $ps_tax = null;
        if ($ps_tax === null)
            $ps_tax = Configuration::get('PS_TAX');
    
        // @tucoinfo custom start excl. vat group
        if (isset($context) && $context == null)
        {
            $context = Context::getContext();
        }
        
        if (isset($context->customer))
        {
            $id_default_group = Customer::getDefaultGroupId((int)($context->customer->id));
            $price_display_method = Group::getPriceDisplayMethod($id_default_group);
            if ( $price_display_method == PS_TAX_EXC )        // BO / Clients / Groups: 0 = including tax, 1 = excluding tax
            {
                return(true);
            }
        }
        // custom end
        
        return !$ps_tax;
    }
}

override/classes/cart.php (extracts only, you should copy the full methods first)

<?php

class Cart extends CartCore
{
    public function getPackageShippingCost($id_carrier = null, $use_tax = true, Country $default_country = null, $product_list = null, $id_zone = null)
    {
...
                    // Free fees if free carrier
                    if ($carrier->is_free == 1)
                    {
                        Cache::store($cache_id, 0);
                        return 0;
                    }
    
                    // @tucoinfo custom start BO & FO: no carrier tax if vat excl. group customer
                    $is_vat_excl_group = false;
                    $id_default_group = Customer::getDefaultGroupId((int)($this->id_customer));
                    $price_display_method = Group::getPriceDisplayMethod($id_default_group);
                    if ( $price_display_method == PS_TAX_EXC )        // BO / Clients / Groups: 0 = including tax, 1 = excluding tax
                    {
                        $is_vat_excl_group = true;
                    }
                    if ($use_tax && !Tax::excludeTaxeOption() && !$is_vat_excl_group)
                    // custom end
                        
                    // Select carrier tax
                    //if ($use_tax && !Tax::excludeTaxeOption())
                    {
                        $address = Address::initialize((int)$address_id);
                        $carrier_tax = $carrier->getTaxesRate($address);
                    }
...
                        return $shipping_cost;
    }
    
    public function getOrderTotal($with_taxes = true, $type = Cart::BOTH, $products = null, $id_carrier = null, $use_cache = true)
    {
        static $address = null;
...
        $order_total = 0;
        if (Tax::excludeTaxeOption())
            $with_taxes = false;
        
        // @tucoinfo custom start BO & FO: no product tax if vat excl. group customer
        $is_vat_excl_group = false;
        $id_default_group = Customer::getDefaultGroupId((int)($this->id_customer));
        $price_display_method = Group::getPriceDisplayMethod($id_default_group);
        if ( $price_display_method == PS_TAX_EXC )        // BO / Clients / Groups: 0 = including tax, 1 = excluding tax
        {
            $is_vat_excl_group = true;
        }
        $with_taxes = ($is_vat_excl_group)? false : $with_taxes;
        // custom end
...
    }

    public function getProducts($refresh = false, $id_product = false, $id_country = null)
    {
...
        $address = Address::initialize($address_id, true);
        $id_tax_rules_group = Product::getIdTaxRulesGroupByIdProduct((int)$row['id_product'], $cart_shop_context);
            
        // @tucoinfo PayPal, no product tax if vat excl. group customer
        // using non existant vat id zero will cancel tax
        $id_default_group = Customer::getDefaultGroupId((int)($this->id_customer));
        $price_display_method = Group::getPriceDisplayMethod($id_default_group);
        if ( $price_display_method == PS_TAX_EXC )        // BO / Clients / Groups: 0 = including tax, 1 = excluding tax
        {
            $id_tax_rules_group = 0;
        }
        // custom end
                
        $tax_calculator = TaxManagerFactory::getManager($address, $id_tax_rules_group)->getTaxCalculator();
...
    }

}
Edited by Spazbot (see edit history)
Link to comment
Share on other sites

  • 4 months later...
 public static function getProductTaxRate( $id_product, $id_address = null, Context $context = null)
    {
    /* if ($context == null)
            $context = Context::getContext();
 
        $address = Address::initialize($id_address);
        $id_tax_rules = (int)Product::getIdTaxRulesGroupByIdProduct($id_product, $context);
 
        $tax_manager = TaxManagerFactory::getManager($address, $id_tax_rules);
        $tax_calculator = $tax_manager->getTaxCalculator();
 
        return $tax_calculator->getTotalRate();
     */
     if ($context == null)
            $context = Context::getContext();
 
        $address = Address::initialize($id_address);
        $groupid = null;
        $cid = $context->cookie->id_customer;
 
            if ($cid <>0){
               $query = "SELECT id_default_group FROM qme_customer WHERE id_customer=$cid ";
$groupid = Db::getInstance()->getValue($query);
                         }
 
 
                if ($groupid >3)
                {
                    return 0;
                }
 
            else
                {
                     $id_tax_rules = (int)Product::getIdTaxRulesGroupByIdProduct($id_product, $context);
 
                      $tax_manager = TaxManagerFactory::getManager($address, $id_tax_rules);
                        $tax_calculator = $tax_manager->getTaxCalculator();
 
 
                      return $tax_calculator->getTotalRate();
 
                  }
 
 
 
    }// fn getProductTaxRate

 

 

I wrote a code and tested on PS 1.6.0.9, it works fine at my end.

Link to comment
Share on other sites

@thijsvk yes this is working if I have not forgotten a piece. For me it is especially working for BO manual order creation. The problem was using $this->_taxCalculationMethod because it relies on Context->customer which is not initialised during a BO order.

Link to comment
Share on other sites

Hi,

I have a problem when I checked out by paypal. The cart's value there was not tax, but the amount of paypal check out page still included tax. 

Any idea?

I have tried to add something at  paypal/process.php like if (Customer::getDefaultGroupId=5)  in  $fields['L_PAYMENTREQUEST_0_AMT'.$index] = Tools::ps_round($product['price_wt'], $this->decimals) , but it doesn't work. 

Do you have similar issue? I need help, please.

 

 

post-149521-0-23859000-1446965242_thumb.png

post-149521-0-90865800-1446965249_thumb.png

Link to comment
Share on other sites

Hi,

I have a problem when I checked out by paypal. The cart's value there was not tax, but the amount of paypal check out page still included tax. 

Any idea?

I have tried to add something at  paypal/process.php like if (Customer::getDefaultGroupId=5)  in  $fields['L_PAYMENTREQUEST_0_AMT'.$index] = Tools::ps_round($product['price_wt'], $this->decimals) , but it doesn't work. 

Do you have similar issue? I need help, please.

@Jameh well spotted, yes I have the same issue in 1.6.014. It seems that the PayPal module doesn't use the cart totals, it calls getProducts which gets VAT for each product as it is defined in BO/Catalogue/Products i.e. no relation to the customer setup!

 

I have updated #26 with a Cart->getProducts override. Seems OK but please provide your own feedback.

Link to comment
Share on other sites

@Spazbot

I have used your code and also tired my revision, neither work at Paypal, my shop is 1.6.0.9, that cart->product in cart.php might different with your version, there wasn't words as follow what did you show #26. 

 

$address = Address::initialize($address_id, true);

$id_tax_rules_group = Product::getIdTaxRulesGroupByIdProduct((int)$row['id_product'], $cart_shop_context)

 

I found there was formula  about cart product calculation, "if ($this->_taxCalculationMethod == PS_TAX_EXC)" in line 553, I tried give a condition for it, tired change the calculation method, but the value didn't submit to paypal. I thought there might be value of tax hiding in the form, but I couldn't found it in script.

Link to comment
Share on other sites

@Spazbot

I have used your code and also tired my revision, neither work at Paypal, my shop is 1.6.0.9, that cart->product in cart.php might different with your version, there wasn't words as follow what did you show #26. 

 

I found there was formula  about cart product calculation, "if ($this->_taxCalculationMethod == PS_TAX_EXC)" in line 553, I tried give a condition for it, tired change the calculation method, but the value didn't submit to paypal. I thought there might be value of tax hiding in the form, but I couldn't found it in script.

Yes quite different but the same problem/solution I think (getProductTaxRate and PP using total_wt). Try forcing $tax_rate = 0 at line 592 and if that works then you can do something conditional like:

$tax_rate = Tax::getProductTaxRate((int)$row['id_product'], (int)$address_id);

// custom start
$id_default_group = Customer::getDefaultGroupId((int)($this->id_customer));
$price_display_method = Group::getPriceDisplayMethod($id_default_group);
if ( $price_display_method == PS_TAX_EXC )		// BO / Clients / Groups: 0 = including tax, 1 = excluding tax
{
	$tax_rate = 0;
}
// custom end

$row['total_wt'] = Tools::ps_round($row['price'] * (float)$row['cart_quantity'] * (1 + (float)$tax_rate / 100), 2);
...
Link to comment
Share on other sites

@Spazbot

It doesn't work, I found paypal takes the value from row['product_wt'] and calculate by itself, so I have revised the value of row['product_wt'] as row['product'] under a certain condition, then, the paypal amount was excluded the tax, but when I change back customer's profile as visitor, even if the page of cart shows the amount was including the tax, but paypal waved it.

It looks the code of condition don't  work. I will show you my codes after cleaning up, I didn't realized what was wrong with it. 

Link to comment
Share on other sites

I found I fixed the issue on ver 1.6.0.9.

Because the paypal calculated the amount according with row['price_wt'], so I make a formula for $row['price_wt'] = Tools::ps_round($row['price'] *  (1 + (float)$tax_rate / 100), 2);

The old code from line 573 to 592 is,


				$row['price_wt'] = Product::getPriceStatic(
					(int)$row['id_product'],
					true,
					isset($row['id_product_attribute']) ? (int)$row['id_product_attribute'] : null,
					2,
					null,
					false,
					true,
					(int)$row['cart_quantity'],
					false,
					((int)$this->id_customer ? (int)$this->id_customer : null),
					(int)$this->id,
					((int)$address_id ? (int)$address_id : null),
					$null,
					true,
					true,
					$cart_shop_context
				);

				$tax_rate = Tax::getProductTaxRate((int)$row['id_product'], (int)$address_id);

replace to following code:

                $tax_rate = Tax::getProductTaxRate((int)$row['id_product'], (int)$address_id);
				$row['price_wt'] =  Tools::ps_round($row['price']* (1 + (float)$tax_rate / 100), 2);

Because we already identify the tax rate to be calculated in different conditions at page Tax.php, we don't need to set up condition for the it here.

But I don't know is there any effect to another function in the store, at least it works for paypal now. 

:)  :)

Link to comment
Share on other sites

×
×
  • Create New...