[*] Project : US + CA TaxSystem

This commit is contained in:
fBrignoli
2011-08-18 10:10:50 +00:00
parent 50e9f03719
commit 8f8ac0670d
33 changed files with 1665 additions and 1168 deletions
+85 -54
View File
@@ -186,7 +186,7 @@ class ProductCore extends ObjectModel
public $tags;
public $isFullyLoaded = false;
protected $langMultiShop = true;
public $cache_is_pack;
@@ -202,10 +202,10 @@ class ProductCore extends ObjectModel
protected static $_cacheFeatures = array();
protected static $_frontFeaturesCache = array();
protected static $producPropertiesCache = array();
/** @var array cache stock data in getStock() method */
protected static $cacheStock = array();
/** @var array tables */
protected $tables = array ('product', 'product_lang');
@@ -303,7 +303,7 @@ class ProductCore extends ObjectModel
parent::__construct($id_product, $id_lang, $id_shop);
if (!$context)
$context = Context::getContext();
if ($full AND $this->id)
{
$this->isFullyLoaded = $full;
@@ -311,10 +311,13 @@ class ProductCore extends ObjectModel
$this->manufacturer_name = Manufacturer::getNameById((int)$this->id_manufacturer);
$this->supplier_name = Supplier::getNameById((int)$this->id_supplier);
self::$_tax_rules_group[$this->id] = $this->id_tax_rules_group;
$address = NULL;
if (is_object($context->cart) AND $context->cart->{Configuration::get('PS_TAX_ADDRESS_TYPE')} != NULL)
$this->tax_rate = Tax::getProductTaxRate($this->id, $context->cart->{Configuration::get('PS_TAX_ADDRESS_TYPE')});
else
$this->tax_rate = Tax::getProductTaxRate($this->id, NULL);
$address = $context->cart->{Configuration::get('PS_TAX_ADDRESS_TYPE')};
$this->tax_rate = $this->getTaxesRate(new Address($address));
$this->new = $this->isNew();
$this->price = Product::getPriceStatic((int)($this->id), false, NULL, 6, NULL, false, true, 1, false, NULL, NULL, NULL, $this->specificPrice);
$this->unit_price = ($this->unit_price_ratio != 0 ? $this->price / $this->unit_price_ratio : 0);
@@ -375,7 +378,7 @@ class ProductCore extends ObjectModel
return $fields;
}
public function add($autodate = true, $nullValues = false)
{
if (!parent::add($autodate, $nullValues))
@@ -405,18 +408,25 @@ class ProductCore extends ObjectModel
));
}
public static function initPricesComputation($customer = NULL)
public static function initPricesComputation($id_customer = NULL)
{
if ($customer)
if ($id_customer)
{
$customer = new Customer((int)($id_customer));
if (!Validate::isLoadedObject($customer))
die(Tools::displayError());
self::$_taxCalculationMethod = Group::getPriceDisplayMethod((int)($customer->id_default_group));
}
else if (Validate::isLoadedObject(Context::getContext()->customer))
self::$_taxCalculationMethod = Group::getPriceDisplayMethod(Context::getContext()->customer->id_default_group);
else
self::$_taxCalculationMethod = Group::getDefaultPriceDisplayMethod();
}
public static function getTaxCalculationMethod($customer = NULL)
public static function getTaxCalculationMethod($id_customer = NULL)
{
if ($customer)
self::initPricesComputation((int)($customer));
if ($id_customer)
self::initPricesComputation((int)($id_customer));
return (int)(self::$_taxCalculationMethod);
}
@@ -556,7 +566,7 @@ class ProductCore extends ObjectModel
{
if (!GroupReduction::deleteProductReduction($this->id))
return false;
Hook::deleteProduct($this);
if (!parent::delete() OR
!$this->deleteCategories(true) OR
@@ -669,7 +679,7 @@ class ProductCore extends ObjectModel
if (!$this->setGroupReduction())
return false;
return true;
}
@@ -740,7 +750,7 @@ class ProductCore extends ObjectModel
SELECT `id_image`
FROM `'._DB_PREFIX_.'image`
WHERE `id_product` = '.(int)($this->id));
$status = true;
if ($result)
foreach($result as $row)
@@ -1369,7 +1379,7 @@ class ProductCore extends ObjectModel
AND tr.`id_state` = 0)
LEFT JOIN `'._DB_PREFIX_.'tax` t ON (t.`id_tax` = tr.`id_tax`)
LEFT JOIN `'._DB_PREFIX_.'manufacturer` m ON (m.`id_manufacturer` = p.`id_manufacturer`)
WHERE p.`active` = 1
WHERE p.`active` = 1
AND DATEDIFF(p.`date_add`, DATE_SUB(NOW(), INTERVAL '.(Validate::isUnsignedInt(Configuration::get('PS_NB_DAYS_NEW_PRODUCT')) ? Configuration::get('PS_NB_DAYS_NEW_PRODUCT') : 20).' DAY)) > 0
AND p.`id_product` IN (
SELECT cp.`id_product`
@@ -1556,7 +1566,7 @@ class ProductCore extends ObjectModel
$ret[] = $val['id_category'];
return $ret;
}
public static function getProductCategoriesFull($id_product = '', $id_lang)
{
$ret = array();
@@ -1642,7 +1652,7 @@ class ProductCore extends ObjectModel
{
if (!$context)
$context = Context::getContext();
$cur_cart = $context->cart;
if (isset($divisor))
@@ -1680,7 +1690,7 @@ class ProductCore extends ObjectModel
// retrieve address informations
$id_country = (int)$context->country->id;
$id_state = 0;
$id_county = 0;
$zipcode = 0;
if (!$id_address)
$id_address = $cur_cart->{Configuration::get('PS_TAX_ADDRESS_TYPE')};
@@ -1692,18 +1702,14 @@ class ProductCore extends ObjectModel
{
$id_country = (int)($address_infos['id_country']);
$id_state = (int)($address_infos['id_state']);
$postcode = (int)$address_infos['postcode'];
$id_county = (int)County::getIdCountyByZipCode($id_state, $postcode);
$zipcode = $address_infos['postcode'];
}
}
elseif (isset($context->customer->geoloc_id_country))
{
$id_country = (int)$context->customer->geoloc_id_country;
$id_state = (int)$context->customer->id_state;
$postcode = (int)$context->customer->postcode;
$id_county = (int)County::getIdCountyByZipCode($id_state, $postcode);
$zipcode = (int)$context->customer->postcode;
}
if (Tax::excludeTaxeOption())
@@ -1712,7 +1718,7 @@ class ProductCore extends ObjectModel
if ($usetax != false AND !empty($address_infos['vat_number']) AND $address_infos['id_country'] != Configuration::get('VATNUMBER_COUNTRY') AND Configuration::get('VATNUMBER_MANAGEMENT'))
$usetax = false;
return Product::priceCalculation($context->shop->getID(), $id_product, $id_product_attribute, $id_country, $id_state, $id_county, $id_currency, $id_group, $quantity, $usetax, $decimals, $only_reduc,
return Product::priceCalculation($context->shop->getID(), $id_product, $id_product_attribute, $id_country, $id_state, $zipcode, $id_currency, $id_group, $quantity, $usetax, $decimals, $only_reduc,
$usereduc, $with_ecotax, $specificPriceOutput, $use_groupReduction);
}
@@ -1733,16 +1739,17 @@ class ProductCore extends ObjectModel
* @param boolean $use_reduc Set if the returned amount will include reduction
* @param boolean $with_ecotax insert ecotax in price output.
* @param variable_reference $specific_price_output If a specific price applies regarding the previous parameters, this variable is filled with the corresponding SpecificPrice object
*
* @return float Product price
**/
public static function priceCalculation($id_shop, $id_product, $id_product_attribute, $id_country, $id_state, $id_county, $id_currency, $id_group, $quantity, $use_tax, $decimals, $only_reduc, $use_reduc, $with_ecotax, &$specific_price, $use_groupReduction)
public static function priceCalculation($id_shop, $id_product, $id_product_attribute, $id_country, $id_state, $zipcode, $id_currency, $id_group, $quantity, $use_tax, $decimals, $only_reduc, $use_reduc, $with_ecotax, &$specific_price, $use_groupReduction)
{
// Caching
if ($id_product_attribute === NULL)
$product_attribute_label = 'NULL';
else
$product_attribute_label = ($id_product_attribute === false ? 'false' : $id_product_attribute);
$cacheId = $id_product.'-'.$id_shop.'-'.$id_currency.'-'.$id_country.'-'.$id_state.'-'.$id_county.'-'.$id_group.'-'.$quantity.'-'.$product_attribute_label.'-'.($use_tax?'1':'0').'-'.$decimals.'-'.($only_reduc?'1':'0').'-'.($use_reduc?'1':'0').'-'.$with_ecotax;
$cacheId = $id_product.'-'.$id_shop.'-'.$id_currency.'-'.$id_country.'-'.$id_state.'-'.$zipcode.'-'.$id_group.'-'.$quantity.'-'.$product_attribute_label.'-'.($use_tax?'1':'0').'-'.$decimals.'-'.($only_reduc?'1':'0').'-'.($use_reduc?'1':'0').'-'.$with_ecotax;
// reference parameter is filled before any returns
$specific_price = SpecificPrice::getSpecificPrice((int)($id_product), $id_shop, $id_currency, $id_country, $id_group, $quantity);
@@ -1773,14 +1780,18 @@ class ProductCore extends ObjectModel
if ($id_product_attribute !== false) // If you want the default combination, please use NULL value instead
$price += $attribute_price;
// TaxRate calculation
$tax_rate = Tax::getProductTaxRateViaRules((int)$id_product, (int)$id_country, (int)$id_state, (int)$id_county);
if ($tax_rate === false)
$tax_rate = 0;
// Tax
$address = new Address();
$address->id_country = $id_country;
$address->id_state = $id_state;
$address->postcode = $zipcode;
$tax_manager = TaxManagerFactory::getManager($address, Product::getIdTaxRulesGroupByIdProduct((int)$id_product));
$product_tax_calculator = $tax_manager->getTaxCalculator();
// Add Tax
if ($use_tax)
$price = $price * (1 + ($tax_rate / 100));
$price = $product_tax_calculator->addTaxes($price);
$price = Tools::ps_round($price, $decimals);
// Reduction
@@ -1793,7 +1804,7 @@ class ProductCore extends ObjectModel
if (!$specific_price['id_currency'])
$reduction_amount = Tools::convertPrice($reduction_amount, $id_currency);
$reduc = Tools::ps_round(!$use_tax ? $reduction_amount / (1 + $tax_rate / 100) : $reduction_amount, $decimals);
$reduc = Tools::ps_round(!$use_tax ? $product_tax_calculator->removeTax($reduction_amount) : $reduction_amount, $decimals);
}
else
$reduc = Tools::ps_round($price * $specific_price['reduction'], $decimals);
@@ -1825,8 +1836,13 @@ class ProductCore extends ObjectModel
$ecotax = Tools::convertPrice($ecotax, $id_currency);
if ($use_tax)
{
$taxRate = TaxRulesGroup::getTaxesRate((int)Configuration::get('PS_ECOTAX_TAX_RULES_GROUP_ID'), (int)$id_country, (int)$id_state, (int)$id_county);
$price += $ecotax * (1 + ($taxRate / 100));
// reinit the tax manager for ecotax handling
$tax_manager = TaxManagerFactory::getManager(
$address,
(int)Configuration::get('PS_ECOTAX_TAX_RULES_GROUP_ID')
);
$ecotax_tax_calculator = $tax_manager->getTaxCalculator();
$price += $ecotax_tax_calculator->addTaxes($ecotax);
}
else
$price += $ecotax;
@@ -1915,7 +1931,7 @@ class ProductCore extends ObjectModel
$ret .= Tools::displayPrice($params['p']['price'], $smarty->ps_currency);
return $ret;
}
/**
* Display price with right format and currency
*
@@ -1975,10 +1991,10 @@ class ProductCore extends ObjectModel
$product = new Product($id_product);
return $product->getStock($id_product_attribute);
}
/**
* Create JOIN query with 'stock' table
*
*
* @param string $productAlias Alias of product table
* @param string|int $productAttribute If string : alias of PA table ; if int : value of PA ; if null : nothing about PA
* @param bool $innerJoin LEFT JOIN or INNER JOIN
@@ -2002,10 +2018,10 @@ class ProductCore extends ObjectModel
return $sql;
}
/**
* Set the stock quantity of current product
*
*
* @since 1.5.0
* @param int $quantity
* @param int $id_product_attribute
@@ -2060,7 +2076,7 @@ class ProductCore extends ObjectModel
'quantity' => $quantity,
), 'INSERT');
}
// Change stock quantity on product
if ($id_stock = Stock::getStockId($this->id, $id_product_attribute, $shop->getID(true)))
{
@@ -2082,7 +2098,7 @@ class ProductCore extends ObjectModel
/**
* Get the stock quantity of current product
*
*
* @since 1.5.0
* @param int $id_product_attribute
* @param Context $context
@@ -2103,6 +2119,7 @@ class ProductCore extends ObjectModel
WHERE id_product = '.$this->id.'
AND id_product_attribute = '.(int)$id_product_attribute
.$context->shop->sqlRestriction(Shop::SHARE_STOCK);
self::$cacheStock[$this->id][$id_product_attribute] = (int)Db::getInstance()->getValue($sql);
}
return self::$cacheStock[$this->id][$id_product_attribute];
@@ -2692,7 +2709,7 @@ class ProductCore extends ObjectModel
{
if (!$this->isFullyLoaded && is_null($this->tags))
$this->tags = Tag::getProductTags($this->id);
if (!($this->tags AND key_exists($id_lang, $this->tags)))
return '';
@@ -2714,7 +2731,7 @@ class ProductCore extends ObjectModel
if (!$row['id_product'])
return false;
$context = Context::getContext();
// Product::getDefaultAttribute is only called if id_product_attribute is missing from the SQL query at the origin of it: consider adding it in order to avoid unnecessary queries
$row['allow_oosp'] = Product::isAvailableWhenOutOfStock($row['out_of_stock']);
if ((!isset($row['id_product_attribute']) OR !$row['id_product_attribute'])
@@ -3030,10 +3047,10 @@ class ProductCore extends ObjectModel
$fields_present[] = array('id_customization_field' => $field['index'], 'type' => $field['type']);
foreach ($requiredFields AS $required_field)
if (!in_array($required_field, $fields_present))
return false;
return false;
return true;
}
public static function idIsOnCategoryId($id_product, $categories)
{
$sql = 'SELECT id_product FROM `'._DB_PREFIX_.'category_product` WHERE `id_product`='.(int)($id_product).' AND `id_category` IN(';
@@ -3063,7 +3080,7 @@ class ProductCore extends ObjectModel
FROM `'._DB_PREFIX_.'category_product` cp
INNER JOIN `'._DB_PREFIX_.'category_group` ctg ON (ctg.`id_category` = cp.`id_category`)
WHERE cp.`id_product` = '.(int)$this->id.' AND ctg.`id_group` = 1');
else
else
return (bool)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue('
SELECT cg.`id_group`
FROM `'._DB_PREFIX_.'category_product` cp
@@ -3075,7 +3092,7 @@ class ProductCore extends ObjectModel
/**
* Add a stock movement for current product
*
*
* @param int $quantity
* @param int $id_reason
* @param int $id_product_attribute
@@ -3155,6 +3172,20 @@ class ProductCore extends ObjectModel
return self::$_tax_rules_group[$id_product];
}
/**
* @return the total taxes rate applied to the product
*/
public function getTaxesRate(Address $address = NULL)
{
if (!$address OR !$address->id_country)
$address = Tax::initializeAddress();
$tax_manager = TaxManagerFactory::getManager($address, $this->id_tax_rules_group);
$tax_calculator = $tax_manager->getTaxCalculator();
return $tax_calculator->getTaxesRate();
}
/**
* Webservice getter : get product features association
*
@@ -3368,7 +3399,7 @@ class ProductCore extends ObjectModel
SET `cover` = 1 WHERE `id_product` = '.(int)($this->id).' AND `id_image` = '.(int)$id_image);
return true;
}
/**
* Webservice getter : get image ids of current product for association
*
@@ -3390,8 +3421,8 @@ class ProductCore extends ObjectModel
FROM `'._DB_PREFIX_.'product_tag`
WHERE `id_product` = '.(int)($this->id));
}
public function getWsManufacturerName()
{
return Manufacturer::getNameById((int)$this->id_manufacturer);
@@ -3404,7 +3435,7 @@ class ProductCore extends ObjectModel
SET ecotax = 0
');
}
/**
* Set Group reduction if needed
*/