diff --git a/admin-dev/ajax.php b/admin-dev/ajax.php
index 80ccb5169..c7efeba15 100644
--- a/admin-dev/ajax.php
+++ b/admin-dev/ajax.php
@@ -358,7 +358,7 @@ if (isset($_GET['ajaxStates']) AND isset($_GET['id_country']))
LEFT JOIN '._DB_PREFIX_.'country c ON (s.`id_country` = c.`id_country`)
WHERE s.id_country = '.(int)(Tools::getValue('id_country')).' AND s.active = 1 AND c.`contains_states` = 1
ORDER BY s.`name` ASC');
-
+
if (is_array($states) AND !empty($states))
{
$list = '';
@@ -504,30 +504,6 @@ if (Tools::isSubmit('toggleScreencast'))
$context->employee->save();
}
-if (Tools::isSubmit('ajaxAddZipCode') OR Tools::isSubmit('ajaxRemoveZipCode'))
-{
- require_once(PS_ADMIN_DIR.'/tabs/AdminCounty.php');
-
- $zipcodes = Tools::getValue('zipcodes');
- $id_county = (int)Tools::getValue('id_county');
-
- $county = new County($id_county);
- if (!Validate::isLoadedObject($county))
- die('error');
-
- if (Tools::isSubmit('ajaxAddZipCode'))
- {
- if ($county->isZipCodeRangePresent($zipcodes))
- die('error:'.Tools::displayError('This Zip Code is already in use.'));
- if ($county->addZipCodes($zipcodes))
- die(AdminCounty::renderZipCodeList($county->getZipCodes()));
- }
- else if (Tools::isSubmit('ajaxRemoveZipCode') AND $county->removeZipCodes($zipcodes))
- die(AdminCounty::renderZipCodeList($county->getZipCodes()));
-
- die('error');
-}
-
if (Tools::isSubmit('helpAccess'))
{
$item = Tools::getValue('item');
@@ -562,14 +538,14 @@ if (Tools::isSubmit('getHookableList'))
if ($moduleInstance->isHookableOn($hook_name))
array_push($hookableList[$hook_name], $module);
}
-
+
}
die(Tools::jsonEncode($hookableList));
}
if (Tools::isSubmit('getHookableModuleList'))
{
-
+
include('../init.php');
$hook_name = Tools::getValue('hook');
$hookableModulesList = array();
@@ -582,9 +558,9 @@ if (Tools::isSubmit('getHookableModuleList'))
$mod = new $module['name']();
if ($mod->isHookableOn($hook_name))
$hookableModulesList[] = array('id' => (int)$mod->id, 'name' => $mod->displayName, 'display' => Module::hookExec($hook_name, array(), (int)$mod->id));
- }
+ }
}
- die(Tools::jsonEncode($hookableModulesList));
+ die(Tools::jsonEncode($hookableModulesList));
}
if (Tools::isSubmit('saveHook'))
@@ -599,7 +575,7 @@ if (Tools::isSubmit('saveHook'))
$hook = trim($hook);
if (!$hook)
continue;
-
+
$sql = 'DELETE FROM '._DB_PREFIX_.'hook_module
WHERE id_hook = (SELECT id_hook FROM '._DB_PREFIX_.'hook WHERE `name` = \''.pSQL($hook).'\' LIMIT 1)
AND id_shop = '.$id_shop;
@@ -615,7 +591,7 @@ if (Tools::isSubmit('saveHook'))
}
$value = rtrim($value, ',');
Db::getInstance()->Execute('INSERT INTO '._DB_PREFIX_.'hook_module (id_module, id_shop, id_hook, position) VALUES '.$value);
-
+
}
}
die('{"hasError" : false, "errors" : ""}');
@@ -624,18 +600,18 @@ if (Tools::isSubmit('saveHook'))
if (Tools::isSubmit('getAdminHomeElement'))
{
$result = array();
-
+
$protocol = Tools::usingSecureMode() ? 'https' : 'http';
$isoUser = Context::getContext()->language->iso_code;
$isoCountry = Context::getContext()->country->iso_code;
$stream_context = stream_context_create(array('http' => array('method'=>"GET", 'timeout' => 5)));
-
+
// SCREENCAST
if (@fsockopen('www.prestashop.com', 80, $errno, $errst, 3))
$result['screencast'] = 'OK';
else
$result['screencast'] = 'NOK';
-
+
// PREACTIVATION
$content = @file_get_contents($protocol.'://www.prestashop.com/partner/preactivation/preactivation-block.php?version=1.0&shop='.urlencode(Configuration::get('PS_SHOP_NAME')).'&protocol='.$protocol.'&url='.urlencode($_SERVER['HTTP_HOST']).'&iso_country='.$isoCountry.'&iso_lang='.Tools::strtolower($isoUser).'&id_lang='.(int)Context::getContext()->language->id.'&email='.urlencode(Configuration::get('PS_SHOP_EMAIL')).'&date_creation='._PS_CREATION_DATE_.'&v='._PS_VERSION_.'&security='.md5(Configuration::get('PS_SHOP_EMAIL')._COOKIE_IV_), false, $stream_context);
if (!$content)
@@ -661,7 +637,7 @@ if (Tools::isSubmit('getAdminHomeElement'))
else
$result['partner_preactivation'] = 'NOK';
}
-
+
// PREACTIVATION PAYPAL WARNING
$content = @file_get_contents('https://www.prestashop.com/partner/preactivation/preactivation-warnings.php?version=1.0&partner=paypal&iso_country='.Tools::strtolower(Context::getContext()->country->iso_code).'&iso_lang='.Tools::strtolower(Context::getContext()->language->iso_code).'&id_lang='.(int)Context::getContext().'&email='.urlencode(Configuration::get('PS_SHOP_EMAIL')).'&security='.md5(Configuration::get('PS_SHOP_EMAIL')._COOKIE_IV_), false, $stream_context);
$content = explode('|', $content);
@@ -681,20 +657,20 @@ if (Tools::isSubmit('getAdminHomeElement'))
$result['discover_prestashop'] = $content[1];
else
$result['discover_prestashop'] = 'NOK';
-
+
if (@fsockopen('www.prestashop.com', 80, $errno, $errst, 3))
$result['discover_prestashop'] .= '';
-
+
$content = @file_get_contents($protocol.'://www.prestashop.com/partner/paypal/paypal-tips.php?protocol='.$protocol.'&iso_country='.$isoCountry.'&iso_lang='.Tools::strtolower($isoUser).'&id_lang='.(int)Context::getContext()->language->id, false, $stream_context);
$content = explode('|', $content);
if ($content[0] == 'OK')
$result['discover_prestashop'] .= $content[1];
- }
-
+ }
+
die(Tools::jsonEncode($result));
}
-if (Tools::isSubmit('getChildrenCategories') && Tools::getValue('id_category_parent'))
+if (Tools::isSubmit('getChildrenCategories') && Tools::getValue('id_category_parent'))
{
$children_categories = Category::getChildrenWithNbSelectedSubCat(Tools::getValue('id_category_parent'), Tools::getValue('selectedCat', array()), Context::getContext()->language->id);
die(Tools::jsonEncode($children_categories));
diff --git a/admin-dev/tabs/AdminAttributeGenerator.php b/admin-dev/tabs/AdminAttributeGenerator.php
index ea3b9cffd..d52164457 100644
--- a/admin-dev/tabs/AdminAttributeGenerator.php
+++ b/admin-dev/tabs/AdminAttributeGenerator.php
@@ -228,7 +228,7 @@ class AdminAttributeGenerator extends AdminTab
i18n_tax_exc = "'.$this->l('Tax Excl.:').'";
i18n_tax_inc = "'.$this->l('Tax Incl.:').'";
- var product_tax = "'.Tax::getProductTaxRate($this->product->id, NULL).'";
+ var product_tax = "'.$this->product->getTaxesRate().'";
function calcPrice(element, element_has_tax)
{
diff --git a/admin-dev/tabs/AdminProducts.php b/admin-dev/tabs/AdminProducts.php
index af4395a95..590e8e23c 100644
--- a/admin-dev/tabs/AdminProducts.php
+++ b/admin-dev/tabs/AdminProducts.php
@@ -131,7 +131,7 @@ class AdminProducts extends AdminTab
$nb = count($this->_list);
if ($this->_list)
{
-
+
/* update product final price */
for ($i = 0; $i < $nb; $i++)
@@ -1059,7 +1059,7 @@ class AdminProducts extends AdminTab
else
{
$image = new Image($id_image);
-
+
if (!$new_path = $image->getPathForCreation())
$this->_errors[] = Tools::displayError('An error occurred during new folder creation');
if (!$tmpName = tempnam(_PS_TMP_IMG_DIR_, 'PS') OR !move_uploaded_file($_FILES['image_product']['tmp_name'], $tmpName))
@@ -1179,7 +1179,7 @@ class AdminProducts extends AdminTab
$this->updateAccessories($object);
$this->updateDownloadProduct($object);
$this->updateAssoShop((int)$object->id);
-
+
if (!$this->updatePackItems($object))
$this->_errors[] = Tools::displayError('An error occurred while adding products to the pack.');
elseif (!$object->updateCategories($_POST['categoryBox'], true))
@@ -1662,7 +1662,7 @@ class AdminProducts extends AdminTab
$specificPrices = SpecificPrice::getByProductId((int)($obj->id));
$specificPricePriorities = SpecificPrice::getPriority((int)($obj->id));
- $taxRate = TaxRulesGroup::getTaxesRate($obj->id_tax_rules_group, $this->context->country->id, 0, 0);
+ $taxRate = $obj->getTaxesRate(Tax::initializeAddress());
$tmp = array();
foreach ($shops as $shop)
@@ -2613,11 +2613,11 @@ class AdminProducts extends AdminTab
';
-
-
+
+
if ((int)Configuration::get('PS_STOCK_MANAGEMENT'))
{
-
+
if (!$has_attribute)
{
if ($obj->id)
@@ -2675,7 +2675,7 @@ class AdminProducts extends AdminTab
echo '
'.$this->l('The stock management is disabled').'
';
-
+
echo '
@@ -2751,23 +2751,23 @@ class AdminProducts extends AdminTab
else
$selectedCat = Product::getProductCategoriesFull($obj->id, $this->_defaultFormLanguage);
}
-
+
echo '';
foreach($selectedCat AS $cat)
echo 'id_category_default == $cat['id_category'] ? 'selected' : '').'>'.$cat['name'].' ';
echo '
-
+
';
// Translations are not automatic for the moment ;)
$trads = array(
- 'Home' => $this->l('Home'),
- 'selected' => $this->l('selected'),
- 'Collapse All' => $this->l('Collapse All'),
- 'Expand All' => $this->l('Expand All'),
- 'Check All' => $this->l('Check All'),
+ 'Home' => $this->l('Home'),
+ 'selected' => $this->l('selected'),
+ 'Collapse All' => $this->l('Collapse All'),
+ 'Expand All' => $this->l('Expand All'),
+ 'Check All' => $this->l('Check All'),
'Uncheck All' => $this->l('Uncheck All')
);
echo Helper::renderAdminCategorieTree($trads, $selectedCat).'
@@ -2840,7 +2840,7 @@ class AdminProducts extends AdminTab
echo '
';
- echo ''.($obj->id ? $this->youEditFieldFor() : '').'
+ echo ''.($obj->id ? $this->youEditFieldFor() : '').'
@@ -2959,7 +2959,7 @@ class AdminProducts extends AdminTab
unitPriceWithTax(\'unit\');
';
$categoryBox = Tools::getValue('categoryBox', array());
-
+
}
function displayFormImages($obj, $token = NULL)
@@ -3070,7 +3070,7 @@ class AdminProducts extends AdminTab
';
foreach ($shops as $shop)
echo ''.$shop['name'].' ';
- }
+ }
echo '
'.$this->l('Cover').'
'.$this->l('Action').'
@@ -3111,7 +3111,7 @@ class AdminProducts extends AdminTab
if (Shop::isMultiShopActivated())
foreach ($shops AS $shop)
echo ' isAssociatedToShop($shop['id_shop']) ? 'checked="1"' : '').' /> ';
- echo '
+ echo '
@@ -3172,7 +3172,7 @@ class AdminProducts extends AdminTab
function displayFormAttributes($obj, $languages, $defaultLanguage)
{
-
+
$attributeJs = array();
$attributes = Attribute::getAttributes($this->context->language->id, true);
foreach ($attributes AS $k => $attribute)
@@ -3181,7 +3181,7 @@ class AdminProducts extends AdminTab
$attributes_groups = AttributeGroup::getAttributesGroups($this->context->language->id);
$default_country = new Country((int)Configuration::get('PS_COUNTRY_DEFAULT'));
-
+
$images = Image::getImages($this->context->language->id, $obj->id);
if ($obj->id)
{
@@ -3726,7 +3726,7 @@ class AdminProducts extends AdminTab
}
else if ($(\'#curPackItemId\').val() == \'\' || $(\'#curPackItemQty\').val() == \'\')
{
- alert(\''.$this->l('Thanks to set a quantity to add a product.').'\');
+ alert(\''.$this->l('Thanks to set a quantity to add a product.').'\');
return false;
}
diff --git a/admin-dev/tabs/AdminTaxRulesGroup.php b/admin-dev/tabs/AdminTaxRulesGroup.php
index 6342d81d5..33c874a47 100755
--- a/admin-dev/tabs/AdminTaxRulesGroup.php
+++ b/admin-dev/tabs/AdminTaxRulesGroup.php
@@ -25,543 +25,462 @@
* International Registered Trademark & Property of PrestaShop SA
*/
-
-class AdminTaxRulesGroup extends AdminTab
+class
+ AdminTaxRulesGroup extends AdminTab
{
+ public $tax_rule;
+ public $_errors_tax_rule;
+
public function __construct()
{
+ global $cookie;
$this->table = 'tax_rules_group';
$this->className = 'TaxRulesGroup';
$this->edit = true;
$this->delete = true;
+ $this->ajax = false;
$this->fieldsDisplay = array(
'id_tax_rules_group' => array('title' => $this->l('ID'), 'align' => 'center', 'width' => 25),
'name' => array('title' => $this->l('Name'), 'width' => 140),
'active' => array('title' => $this->l('Enabled'), 'width' => 25, 'align' => 'center', 'active' => 'status', 'type' => 'bool', 'orderby' => false));
- parent::__construct();
+ parent::__construct();
}
- public function displayTop()
+ /**
+ * retrieve a tax rule via ajax
+ * @return tax rule in json format
+ */
+ public function ajaxProcessGetTaxRule()
{
- echo '
- '.$this->l('The tax rules allow you to define a product or a carrier with different taxes depending on their location (country, state, etc.).').'
+ $id_rule = (int)Tools::getValue('id_tax_rule');
-
'.$this->l('In the majority of cases, the rules created by default by PrestaShop should be enough.').' '.
- $this->l('If, however, you need to change them, here is an example that will help you understand how it works:').
- '
'
- .$this->l('You want to apply a tax of 19.6% to a product in France and Europe, but not apply this tax to other countries. Follow these steps:').'
-
- '.$this->l('Click "Add New".').'
- '.$this->l('Give a name to your tax rule (ex: "19.6% tax rule).').'
- '.$this->l('Set the \'active\' field to true.').'
- '.$this->l('Edit its configuration by country by associating a 19.6% tax with France and with European countries, and a tax of 0% to other countries.').'
- '.$this->l('Click on Save.').'
- '.$this->l('Go to your product page (Catalog tab) and associate the "19.6% tax rule" to your product.').'
-
-
- '.$this->l('Later, if you need to apply a different tax to Spain, you can simply edit the rule "19.6% tax rule" and change the tax associated with Spain.').'
- '.$this->l('Note: The default rate applied to your product will be based on your store\'s default country.').'
-
';
+ if ($tax_rule = TaxRule::retrieveById($id_rule))
+ die(Tools::jsonEncode($tax_rule));
+ else
+ die('error');
}
- public function displayForm($isMainTab = true)
+
+ public function ajaxPreProcess() {}
+
+ public function postProcess()
+ {
+ $action = Tools::getValue('action');
+ if ($action == 'delete_rule')
+ {
+ $id_rule = (int)Tools::getValue('id_tax_rule');
+ $tax_rule = new TaxRule($id_rule);
+
+ if (Validate::isLoadedObject($tax_rule))
+ {
+ $tax_rule->delete();
+ Tools::redirectAdmin(self::$currentIndex.'&'.$this->identifier.'='.$tax_rule->id_tax_rules_group.'&conf=4&update'.$this->table.'&token='.$this->token);
+ }
+ }
+ else if ($action == 'create_rule')
+ {
+ $zipcode = Tools::getValue('zipcode');
+ $id_rule = (int)Tools::getValue('id_tax_rule');
+
+ $tr = new TaxRule();
+
+ // update or creation?
+ if (isset($id_rule))
+ $tr->id = $id_rule;
+
+ $tr->id_tax = (int)Tools::getValue('tax');
+ $tr->id_tax_rules_group = (int)Tools::getValue('id_tax_rules_group');
+ $tr->id_country = (int)Tools::getValue('country');
+ $tr->id_state = (int)Tools::getValue('states');
+ list($tr->zipcode_from, $tr->zipcode_to) = $tr->breakDownZipCode($zipcode);
+ $tr->behavior = (int)Tools::getValue('behavior');
+ $tr->description = Tools::getValue('description');
+
+ $this->_errors_tax_rule = $this->validateTaxRule($tr);
+
+ if (sizeof($this->_errors_tax_rule) == 0)
+ {
+ if (!$tr->save())
+ die('error');
+ }
+
+ $this->tax_rule = $tr;
+ Tools::redirectAdmin(self::$currentIndex.'&'.$this->identifier.'='.$tr->id_tax_rules_group.'&conf=4&update'.$this->table.'&token='.$this->token);
+ } else
+ parent::postProcess();
+ }
+
+ /**
+ * check if the tax rule could be added in the database
+ * @param TaxRule $tr
+ */
+ protected function validateTaxRule(TaxRule $tr)
{
- parent::displayForm();
+ // TODO: check if the rule already exists
+ return $tr->validateController();
+ }
+
+ protected function displayJS()
+ {
+ global $cookie;
+
+ $javascript = <<
+ function populateStates(id_country, id_state)
+ {
+ $.ajax({
+ url: "ajax.php",
+ cache: false,
+ data: "ajaxStates=1&id_country="+id_country+"&id_state="+id_state,
+ success: function(html){
+ if (html == "false")
+ {
+ $("#state-label").hide();
+ $("#state-select").hide();
+ }
+ else
+ {
+ $("#state-label").show();
+ $("#state-select").show();
+ $("#states").html(html);
+ }
+ }
+ });
+ }
+
+ function loadTaxRule(id_tax_rule)
+ {
+ $.ajax({
+ url: "ajax-tab.php",
+ cache: false,
+ dataType: "json",
+ data: "action=get_tax_rule&id_tax_rule="+id_tax_rule+"&tab=AdminTaxRulesGroup&token=$this->token",
+ success: function(data){
+ $('#rule_form').show();
+ $('#id_tax_rule').val(data.id_tax_rule);
+ $('#country').val(data.id_country);
+ $('#state').val(data.id_state);
+
+ zipcode = 0;
+ if (data.zipcode_from != 0)
+ {
+ zipcode = data.zipcode_from;
+
+ if (data.zipcode_to != 0)
+ zipcode = zipcode +"-"+data.zipcode_to
+ }
+
+ $('#zipcode').val(zipcode);
+ $('#behavior').val(data.behavior);
+ $('#tax').val(data.id_tax);
+ $('#description').val(data.description);
+
+ populateStates(data.id_country, data.id_state);
+ },
+ error: function(data)
+ {
+
+ }
+ });
+ }
+
+ function initForm()
+ {
+ $('#id_tax_rule').val('');
+ $('#country').val(0);
+ $('#state').val(0);
+ $('#zipcode').val(0);
+ $('#behavior').val(0);
+ $('#tax').val(0);
+ $('#description').val('');
+
+ populateStates(0,0);
+ }
+
+EOT;
+
+ echo $javascript;
+ }
+
+
+ public function displayTaxRulesErrors()
+ {
+ if ($nbErrors = count($this->_errors_tax_rule) AND $this->_includeContainer)
+ {
+
+ echo '
+ ';
+ if (count($this->_errors_tax_rule) == 1)
+ echo $this->_errors_tax_rule[0];
+ else
+ {
+ echo $nbErrors.' '.$this->l('errors').'
';
+ foreach ($this->_errors_tax_rule AS $error)
+ echo ''.$error.' ';
+ echo ' ';
+ }
+ echo '
';
+ }
+ }
+
+
+ public function display()
+ {
+ if ((Tools::getValue('submitAdd'.$this->table) AND sizeof($this->_errors_tax_rule)) OR isset($_GET['add'.$this->table]))
+ {
+ if ($this->tabAccess['add'] === '1')
+ $this->displayForm();
+ else
+ echo $this->l('You do not have permission to add here');
+ }
+ else parent::display();
+ }
+
+ /**
+ * displays the tax rules group form
+ */
+ protected function displayRuleGroupForm()
+ {
+ global $cookie, $currentIndex;
+ parent::displayForm();
if (!($obj = $this->loadObject(true)))
return;
- $tax_rules = isset($obj->id) ? $tax_rules = TaxRule::getTaxRulesByGroupId($obj->id) : array();
- $param_product = Tools::getValue('id_product') ? '&id_product='.Tools::getValue('id_product') : '';
+ // if the user come from the product page
+ $param_product = Tools::getValue('id_product') ? '&id_product='.Tools::getValue('id_product') : '';
- echo ' ';
foreach ($this->_list['obj'] AS $k => $prod)
{
- $product = new Product((int)($prod['id_product']));
+ $product = new Product((int)$prod['id_product'], false);
$product->name = $product->name[(int)$this->context->language->id];
- $taxrate = Tax::getProductTaxRate($product->id);
+ $taxrate = $product->getTaxesRate();
echo '
@@ -222,13 +222,15 @@ class AdminTracking extends AdminTab
else
$prod['combination_name'] = $prod['group_name'].' : '.$prod['attribute_name'];
+
$attributes[$prod['id_product_attribute']] = $prod;
$prevAttributeId = $prod['id_product_attribute'];
}
foreach ($attributes AS $prod)
{
- $taxrate = Tax::getProductTaxRate($prod['id_product']);
+ $product = new Product((int)$prod['id_product'], false);
+ $tax_rate = $product->getTaxesRate();
echo '
diff --git a/classes/Autoload.php b/classes/Autoload.php
index 46175918e..a788e2e5e 100644
--- a/classes/Autoload.php
+++ b/classes/Autoload.php
@@ -77,6 +77,8 @@ class Autoload
*/
public function load($classname)
{
+ // echo("Please load $classname. ");
+
// regenerate the class index if the requested class is not found in the index or if the requested file doesn't exists
if (!isset($this->index[$classname]) || ($this->index[$classname] && !file_exists($this->root_dir.$this->index[$classname])))
$this->generateIndex();
@@ -87,6 +89,7 @@ class Autoload
// If requested class does not exist, load associated core class
if (isset($this->index[$classname]) && !$this->index[$classname])
{
+
require_once($this->root_dir.$this->index[$classname.'Core']);
if (file_exists($this->root_dir.'override/'.$this->index[$classname.'Core']))
{
@@ -104,10 +107,14 @@ class Autoload
{
// request a non Core Class load the associated Core class if exists
if (isset($this->index[$classname.'Core']))
+ {
require_once($this->root_dir.$this->index[$classname.'Core']);
+ }
if (isset($this->index[$classname]))
+ {
require_once($this->root_dir.$this->index[$classname]);
+ }
}
}
// Call directly ProductCore, ShopCore class
diff --git a/classes/Carrier.php b/classes/Carrier.php
index 27625a4da..62364880e 100644
--- a/classes/Carrier.php
+++ b/classes/Carrier.php
@@ -70,7 +70,7 @@ class CarrierCore extends ObjectModel
/** @var boolean Free carrier */
public $is_free = false;
-
+
/** @var int shipping behavior: by weight or by price */
public $shipping_method = 0;
@@ -82,7 +82,7 @@ class CarrierCore extends ObjectModel
/** @var boolean Need Range */
public $need_range = 0;
-
+
protected $langMultiShop = true;
protected $fieldsRequired = array('name', 'active');
@@ -488,7 +488,7 @@ class CarrierCore extends ObjectModel
}
}
}
-
+
$row['name'] = (strval($row['name']) != '0' ? $row['name'] : Configuration::get('PS_SHOP_NAME'));
$row['price'] = ($shippingMethod == Carrier::SHIPPING_METHOD_FREE ? 0 : $cart->getOrderShippingCost((int)$row['id_carrier']));
$row['price_tax_exc'] = ($shippingMethod == Carrier::SHIPPING_METHOD_FREE ? 0 : $cart->getOrderShippingCost((int)$row['id_carrier'], false));
@@ -590,7 +590,7 @@ class CarrierCore extends ObjectModel
$where .= 'AND id_shop IS NULL AND id_group_shop = '.$shopGroupID;
else
$where .= 'AND id_shop = '.$shopID;
-
+
return Db::getInstance()->delete(_DB_PREFIX_.'delivery', $where);
}
@@ -610,7 +610,7 @@ class CarrierCore extends ObjectModel
$keys[] = 'id_shop';
if (!in_array('id_group_shop', $keys))
$keys[] = 'id_group_shop';
-
+
if (!$shop)
$shop = Context::getContext()->shop;
$shopID = $shop->getID();
@@ -623,7 +623,7 @@ class CarrierCore extends ObjectModel
$values['id_shop'] = ($shopID) ? $shopID : null;
if (!isset($values['id_group_shop']))
$values['id_group_shop'] = ($shopGroupID) ? $shopGroupID : null;
-
+
$sql .= '(';
foreach ($values as $v)
{
@@ -650,7 +650,7 @@ class CarrierCore extends ObjectModel
{
if (!Validate::isUnsignedId($oldId))
die(Tools::displayError());
-
+
if (!$this->id)
return false;
@@ -670,7 +670,7 @@ class CarrierCore extends ObjectModel
VALUES ('.$this->id.','.(float)$val['delimiter1'].','.(float)$val['delimiter2'].')';
Db::getInstance()->Execute($sql);
$rangeID = (int)Db::getInstance()->Insert_ID();
-
+
$rangePriceID = ($range == 'range_price') ? $rangeID : 'NULL';
$rangeWeightID = ($range == 'range_weight') ? $rangeID : 'NULL';
$sql = 'INSERT INTO '._DB_PREFIX_.$range.' (id_carrier, id_shop, id_group_shop, id_range_price, id_range_weight, id_zone, price)
@@ -769,10 +769,24 @@ class CarrierCore extends ObjectModel
return self::$_cache_tax_rule[$id_carrier];
}
-
+
+
+ /**
+ * Return the taxes rate associated to the carrier
+ *
+ * @since 1.5
+ * @param Address $address
+ */
+ public function getTaxesRate(Address $address)
+ {
+ $tax_manager = TaxManagerFactory::getManager($address, $this->id_tax_rules_group);
+ $tax_calculator = $tax_manager->getTaxCalculator();
+ return $tax_calculator->getTaxesRate();
+ }
+
/**
* This tricky method generate a sql clause to check if ranged data are overloaded by multishop
- *
+ *
* @since 1.5.0
* @param string $rangeTable
* @param Shop $shop
@@ -791,7 +805,7 @@ class CarrierCore extends ObjectModel
$where = 'AND ((d2.id_group_shop IS NULL OR d2.id_group_shop = '.$shopGroupID.') AND d2.id_shop IS NULL)';
else
$where = 'AND (d2.id_shop = '.$shopID.' OR (d2.id_group_shop = '.$shopGroupID.' AND d2.id_shop IS NULL) OR (d2.id_group_shop IS NULL AND d2.id_shop IS NULL))';
-
+
$sql = 'AND '.$alias.'.id_delivery = (
SELECT d2.id_delivery
FROM '._DB_PREFIX_.'delivery d2
diff --git a/classes/Cart.php b/classes/Cart.php
index 145f821d8..5e5ce22c1 100644
--- a/classes/Cart.php
+++ b/classes/Cart.php
@@ -28,11 +28,11 @@
class CartCore extends ObjectModel
{
public $id;
-
+
public $id_group_shop;
-
+
public $id_shop;
-
+
/** @var integer Customer delivery address ID */
public $id_address_delivery;
@@ -75,7 +75,7 @@ class CartCore extends ObjectModel
public $checkedTos = false;
public $pictures;
public $textFields;
-
+
protected static $_nbProducts = array();
protected static $_isVirtualCart = array();
@@ -129,7 +129,7 @@ class CartCore extends ObjectModel
$fields['id_group_shop'] = (int)$this->id_group_shop;
$fields['id_shop'] = (int)$this->id_shop;
-
+
$fields['id_address_delivery'] = (int)($this->id_address_delivery);
$fields['id_address_invoice'] = (int)($this->id_address_invoice);
$fields['id_currency'] = (int)($this->id_currency);
@@ -187,35 +187,35 @@ class CartCore extends ObjectModel
{
if ($this->OrderExists()) //NOT delete a cart which is associated with an order
return false;
-
+
$uploadedFiles = Db::getInstance()->ExecuteS('
- SELECT cd.`value`
+ SELECT cd.`value`
FROM `'._DB_PREFIX_.'customized_data` cd
INNER JOIN `'._DB_PREFIX_.'customization` c ON (cd.`id_customization`= c.`id_customization`)
WHERE cd.`type`= 0 AND c.`id_cart`='.(int)$this->id);
-
+
foreach ($uploadedFiles as $mustUnlink)
{
unlink(_PS_UPLOAD_DIR_.$mustUnlink['value'].'_small');
unlink(_PS_UPLOAD_DIR_.$mustUnlink['value']);
}
-
+
Db::getInstance()->Execute('
- DELETE FROM `'._DB_PREFIX_.'customized_data`
+ DELETE FROM `'._DB_PREFIX_.'customized_data`
WHERE `id_customization` IN (
- SELECT `id_customization`
- FROM `'._DB_PREFIX_.'customization`
+ SELECT `id_customization`
+ FROM `'._DB_PREFIX_.'customization`
WHERE `id_cart`='.(int)$this->id.'
)');
-
+
Db::getInstance()->Execute('
- DELETE FROM `'._DB_PREFIX_.'customization`
+ DELETE FROM `'._DB_PREFIX_.'customization`
WHERE `id_cart` = '.(int)$this->id);
- if (!Db::getInstance()->Execute('DELETE FROM `'._DB_PREFIX_.'cart_discount` WHERE `id_cart` = '.(int)($this->id))
+ if (!Db::getInstance()->Execute('DELETE FROM `'._DB_PREFIX_.'cart_discount` WHERE `id_cart` = '.(int)($this->id))
OR !Db::getInstance()->Execute('DELETE FROM `'._DB_PREFIX_.'cart_product` WHERE `id_cart` = '.(int)($this->id)))
return false;
-
+
return parent::delete();
}
@@ -344,7 +344,7 @@ class CartCore extends ObjectModel
if (is_int($id_product))
{
foreach ($this->_products as $product)
- if ($product['id_product'] == $id_product)
+ if ($product['id_product'] == $id_product)
return array($product);
return array();
}
@@ -352,7 +352,7 @@ class CartCore extends ObjectModel
}
if (!$id_country)
$id_country = Context::getContext()->country->id;
-
+
$sql = 'SELECT cp.`id_product_attribute`, cp.`id_product`, cu.`id_customization`, cp.`quantity` AS cart_quantity, cp.id_shop, cu.`quantity` AS customization_quantity, pl.`name`,
pl.`description_short`, pl.`available_now`, pl.`available_later`, p.`id_product`, p.`id_category_default`, p.`id_supplier`, p.`id_manufacturer`, p.`on_sale`, p.`ecotax`, p.`additional_shipping_cost`, p.`available_for_order`,
p.`price`, p.`weight`, p.`width`, p.`height`, p.`depth`, p.`out_of_stock`, p.`active`, p.`date_add`, p.`date_upd`, IFNULL(pa.`minimal_quantity`, p.`minimal_quantity`) as minimal_quantity,
@@ -369,7 +369,8 @@ class CartCore extends ObjectModel
LEFT JOIN `'._DB_PREFIX_.'product_attribute` pa ON (pa.`id_product_attribute` = cp.`id_product_attribute`)
LEFT JOIN `'._DB_PREFIX_.'tax_rule` tr ON (p.`id_tax_rules_group` = tr.`id_tax_rules_group`
AND tr.`id_country` = '.(int)$id_country.'
- AND tr.`id_state` = 0)
+ AND tr.`id_state` = 0
+ AND tr.`zipcode_from` = 0)
LEFT JOIN `'._DB_PREFIX_.'tax` t ON (t.`id_tax` = tr.`id_tax`)
LEFT JOIN `'._DB_PREFIX_.'tax_lang` tl ON (t.`id_tax` = tl.`id_tax` AND tl.`id_lang` = '.(int)$this->id_lang.')
LEFT JOIN `'._DB_PREFIX_.'customization` cu ON (p.`id_product` = cu.`id_product`)
@@ -381,6 +382,7 @@ class CartCore extends ObjectModel
AND p.`id_product` IS NOT NULL
GROUP BY unique_id
ORDER BY cp.date_add ASC';
+
$result = Db::getInstance()->ExecuteS($sql);
// Reset the cache before the following return, or else an empty cart will add dozens of queries
@@ -414,7 +416,7 @@ class CartCore extends ObjectModel
$row['price'] = Product::getPriceStatic((int)$row['id_product'], false, 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)($this->{Configuration::get('PS_TAX_ADDRESS_TYPE')}) ? (int)($this->{Configuration::get('PS_TAX_ADDRESS_TYPE')}) : NULL), $specificPriceOutput); // Here taxes are computed only once the quantity has been applied to the product price
$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)($this->{Configuration::get('PS_TAX_ADDRESS_TYPE')}) ? (int)($this->{Configuration::get('PS_TAX_ADDRESS_TYPE')}) : NULL));
$tax_rate = Tax::getProductTaxRate((int)$row['id_product'], (int)($this->{Configuration::get('PS_TAX_ADDRESS_TYPE')}));
-
+
$row['total_wt'] = Tools::ps_round($row['price'] * (float)$row['cart_quantity'] * (1 + (float)($tax_rate) / 100), 2);
$row['total'] = $row['price'] * (int)($row['cart_quantity']);
}
@@ -428,7 +430,7 @@ class CartCore extends ObjectModel
$row['total_wt'] = $row['price_wt'] * (int)($row['cart_quantity']);
$row['total'] = Tools::ps_round($row['price'] * (int)($row['cart_quantity']), 2);
}
-
+
$row2 = Db::getInstance()->getRow('
SELECT i.`id_image`, il.`legend`
FROM `'._DB_PREFIX_.'image` i
@@ -447,7 +449,7 @@ class CartCore extends ObjectModel
if (!$row2)
$row2 = array('id_image' => false, 'legend' => false);
$row = array_merge($row, $row2);
-
+
$row['reduction_applies'] = ($specificPriceOutput AND (float)$specificPriceOutput['reduction']);
$row['id_image'] = Product::defineProductImage($row,$this->id_lang);
$row['allow_oosp'] = Product::isAvailableWhenOutOfStock($row['out_of_stock']);
@@ -513,8 +515,8 @@ class CartCore extends ObjectModel
if (isset(self::$_nbProducts[$id]) && self::$_nbProducts[$id] !== NULL)
return self::$_nbProducts[$id];
self::$_nbProducts[$id] = (int)(Db::getInstance()->getValue('
- SELECT SUM(`quantity`)
- FROM `'._DB_PREFIX_.'cart_product`
+ SELECT SUM(`quantity`)
+ FROM `'._DB_PREFIX_.'cart_product`
WHERE `id_cart` = '.(int)($id)));
return self::$_nbProducts[$id];
}
@@ -579,7 +581,7 @@ class CartCore extends ObjectModel
$result = $this->containsProduct($id_product, $id_product_attribute, (int)$id_customization);
/* Update quantity if product already exist */
-
+
if ($result)
{
if ($operator == 'up')
@@ -652,7 +654,7 @@ class CartCore extends ObjectModel
// refresh cache of self::_products
$this->_products = $this->getProducts(true);
$this->update(true);
-
+
if ($product->customizable)
return $this->_updateCustomizationQuantity((int)$quantity, (int)$id_customization, (int)$id_product, (int)$id_product_attribute, $operator);
else
@@ -673,15 +675,15 @@ class CartCore extends ObjectModel
if ($field['quantity'] == 0)
{
Db::getInstance()->Execute('
- UPDATE `'._DB_PREFIX_.'customization`
- SET `quantity` = '.(int)($quantity).',
+ UPDATE `'._DB_PREFIX_.'customization`
+ SET `quantity` = '.(int)($quantity).',
`id_product_attribute` = '.(int)$id_product_attribute.',
`in_cart` = 1
WHERE `id_customization` = '.(int)$field['id_customization']);
}
}
}
-
+
/* Deletion */
if (!empty($id_customization) AND (int)($quantity) < 1)
return $this->_deleteCustomization((int)$id_customization, (int)$id_product, (int)$id_product_attribute);
@@ -694,7 +696,7 @@ class CartCore extends ObjectModel
if ($operator == 'down' AND (int)($result['quantity']) - (int)($quantity) < 1)
return Db::getInstance()->Execute('DELETE FROM `'._DB_PREFIX_.'customization` WHERE `id_customization` = '.(int)$id_customization);
return Db::getInstance()->Execute('
- UPDATE `'._DB_PREFIX_.'customization`
+ UPDATE `'._DB_PREFIX_.'customization`
SET `quantity` = `quantity` '.($operator == 'up' ? '+ ' : '- ').(int)($quantity).'
WHERE `id_customization` = '.(int)($id_customization));
}
@@ -726,15 +728,15 @@ class CartCore extends ObjectModel
AND cu.id_product = '.(int)$id_product.'
AND in_cart = 0');
- if ($exising_customization)
+ if ($exising_customization)
{
- // If the customization field is alreay filled, delete it
+ // If the customization field is alreay filled, delete it
foreach($exising_customization as $customization)
{
if ($customization['type'] == $type && $customization['index'] == $index)
{
Db::getInstance()->Execute('
- DELETE FROM `'._DB_PREFIX_.'customized_data`
+ DELETE FROM `'._DB_PREFIX_.'customized_data`
WHERE id_customization = '.(int)$customization['id_customization'].'
AND type = '.(int)$customization['type'].'
AND `index` = '.(int)$customization['index']);
@@ -750,7 +752,7 @@ class CartCore extends ObjectModel
}else
{
Db::getInstance()->Execute('INSERT INTO `'._DB_PREFIX_.'customization` (`id_cart`, `id_product`, `id_product_attribute`, `quantity`) VALUES ('.(int)($this->id).', '.(int)($id_product).', '.(int)($id_product_attribute).', '.(int)($quantity).')');
- $id_customization = Db::getInstance()->Insert_ID();
+ $id_customization = Db::getInstance()->Insert_ID();
}
$query = 'INSERT INTO `'._DB_PREFIX_.'customized_data` (`id_customization`, `type`, `index`, `value`) VALUES ('.(int)$id_customization.', '.(int)$type.', '.(int)$index.', \''.pSql($field).'\')';
@@ -922,7 +924,7 @@ class CartCore extends ObjectModel
// no shipping cost if is a cart with only virtuals products
$virtual = $this->isVirtualCart();
- if ($virtual AND $type == Cart::ONLY_SHIPPING)
+ if ($virtual AND $type == Cart::ONLY_SHIPPING)
return 0;
if ($virtual AND $type == Cart::BOTH)
$type = Cart::BOTH_WITHOUT_SHIPPING;
@@ -1042,7 +1044,7 @@ class CartCore extends ObjectModel
if (!$default_country)
$default_country = Context::getContext()->country;
-
+
// Checking discounts in cart
$products = $this->getProducts();
$discounts = $this->getDiscounts(true);
@@ -1087,7 +1089,7 @@ class CartCore extends ObjectModel
if (!Validate::isLoadedObject($default_country))
$default_country = new Country(Configuration::get('PS_COUNTRY_DEFAULT'), Configuration::get('PS_LANG_DEFAULT'));
$id_zone = (int)$default_country->id_zone;
- }
+ }
// If no carrier, select default one
if (!$id_carrier)
@@ -1173,14 +1175,14 @@ class CartCore extends ObjectModel
die(Tools::displayError('Fatal error: "no default carrier"'));
if (!$carrier->active)
return $shipping_cost;
-
+
// Free fees if free carrier
if ($carrier->is_free == 1)
- return 0;
-
+ return 0;
+
// Select carrier tax
if ($useTax AND !Tax::excludeTaxeOption())
- $carrierTax = Tax::getCarrierTaxRate((int)$carrier->id, (int)$this->{Configuration::get('PS_TAX_ADDRESS_TYPE')});
+ $carrierTax = $carrier->getTaxesRate(new Address((int)$this->{Configuration::get('PS_TAX_ADDRESS_TYPE')}));
$configuration = Configuration::getMultiple(array('PS_SHIPPING_FREE_PRICE', 'PS_SHIPPING_HANDLING', 'PS_SHIPPING_METHOD', 'PS_SHIPPING_FREE_WEIGHT'));
// Free fees
@@ -1238,7 +1240,7 @@ class CartCore extends ObjectModel
{
$moduleName = $carrier->external_module_name;
$module = Module::getInstanceByName($moduleName);
-
+
if (Validate::isLoadedObject($module))
{
if (array_key_exists('id_carrier', $module))
@@ -1295,13 +1297,13 @@ class CartCore extends ObjectModel
*
* @return mixed Return a string if an error occurred and false otherwise
*/
- function checkDiscountValidity($discountObj, $discounts, $order_total, $products, $checkCartDiscount = false,
+ function checkDiscountValidity($discountObj, $discounts, $order_total, $products, $checkCartDiscount = false,
Customer $customer = null, Shop $shop = null)
{
if (!$shop)
$shop = Context::getContext()->shop;
if (!$customer)
- $customer = Context::getContext()->customer;
+ $customer = Context::getContext()->customer;
if (!$order_total)
return Tools::displayError('Cannot add voucher if order is free.');
if (!$discountObj->active)
@@ -1331,12 +1333,12 @@ class CartCore extends ObjectModel
foreach ($discounts as $discount)
if (!$discount['cumulable'])
return Tools::displayError('Voucher is not valid with other discounts.');
-
+
foreach($discounts as $discount)
if($discount['id_discount'] == $discountObj->id)
return Tools::displayError('This voucher is already in your cart');
}
-
+
$groups = Customer::getGroupsStatic($this->id_customer);
if (($discountObj->id_customer OR $discountObj->id_group) AND ((($this->id_customer != $discountObj->id_customer) OR ($this->id_customer == 0)) AND !in_array($discountObj->id_group, $groups)))
@@ -1391,7 +1393,7 @@ class CartCore extends ObjectModel
// New layout system with personalization fields
$formattedAddresses['invoice'] = AddressFormat::getFormattedLayoutData($invoice);
$formattedAddresses['delivery'] = AddressFormat::getFormattedLayoutData($delivery);
-
+
$total_tax = $this->getOrderTotal() - $this->getOrderTotal(false);
if ($total_tax < 0)
@@ -1513,7 +1515,7 @@ class CartCore extends ObjectModel
$textValue = str_replace(array("\n", "\r"), '', nl2br($textValue));
$textValue = str_replace('\\', '\\\\', $textValue);
$textValue = str_replace('\'', '\\\'', $textValue);
- return $this->_addCustomization($id_product, 0, $index, $type, $textValue, 0);
+ return $this->_addCustomization($id_product, 0, $index, $type, $textValue, 0);
}
/*
@@ -1523,9 +1525,9 @@ class CartCore extends ObjectModel
*/
public function addPictureToProduct($id_product, $index, $type, $file)
{
- return $this->_addCustomization($id_product, 0, $index, $type, $file, 0);
+ return $this->_addCustomization($id_product, 0, $index, $type, $file, 0);
}
-
+
/*
* Remove a customer's customization
*
@@ -1534,7 +1536,7 @@ class CartCore extends ObjectModel
public function deleteCustomizationToProduct($id_product, $index)
{
$result = true;
-
+
$custData = Db::getInstance()->getRow('
SELECT cu.`id_customization`, cd.`index`, cd.`value`, cd.`type` FROM `'._DB_PREFIX_.'customization` cu
LEFT JOIN `'._DB_PREFIX_.'customized_data` cd
@@ -1544,7 +1546,7 @@ class CartCore extends ObjectModel
AND `index` = '.(int)$index.'
AND `in_cart` = 0'
);
-
+
// Delete customization picture if necessary
if ($custData['type'] == 0)
$result &= (@unlink(_PS_UPLOAD_DIR_.$custData['value']) && @unlink(_PS_UPLOAD_DIR_.$custData['value'].'_small'));
@@ -1556,7 +1558,7 @@ class CartCore extends ObjectModel
);
return $result;
}
-
+
/**
* Return custom pictures in this cart for a specified product
*
@@ -1603,7 +1605,7 @@ class CartCore extends ObjectModel
$cart->id = NULL;
$cart->id_shop = $this->id_shop;
$cart->id_group_shop = $this->id_group_shop;
-
+
$cart->add();
if (!Validate::isLoadedObject($cart))
@@ -1620,7 +1622,7 @@ class CartCore extends ObjectModel
FROM '._DB_PREFIX_.'customization c
LEFT JOIN '._DB_PREFIX_.'customized_data cd ON cd.id_customization = c.id_customization
WHERE c.id_cart = '.(int)$this->id);
-
+
// Group line by id_customization
$customsById = array();
foreach ($customs AS $custom)
@@ -1629,7 +1631,7 @@ class CartCore extends ObjectModel
$customsById[$custom['id_customization']] = array();
$customsById[$custom['id_customization']][] = $custom;
}
-
+
// Insert new customizations
$custom_ids = array();
foreach($customsById as $customizationId => $val)
@@ -1639,7 +1641,7 @@ class CartCore extends ObjectModel
VALUES(\'\', '.(int)$cart->id.', '.(int)$custom['id_product_attribute'].', '.(int)$custom['id_product'].', '.(int)$custom['quantity'].')');
$custom_ids[$custom['id_customization']] = Db::getInstance(_PS_USE_SQL_SLAVE_)->Insert_ID();
}
-
+
// Insert customized_data
if (sizeof($customs))
{
@@ -1655,7 +1657,7 @@ class CartCore extends ObjectModel
}
Db::getInstance(_PS_USE_SQL_SLAVE_)->Execute($sql_custom_data);
}
-
+
return array('cart' => $cart, 'success' => $success);
}
diff --git a/classes/Category.php b/classes/Category.php
index db50e67ae..91de31564 100644
--- a/classes/Category.php
+++ b/classes/Category.php
@@ -548,7 +548,8 @@ class CategoryCore extends ObjectModel
LEFT JOIN `'._DB_PREFIX_.'image_lang` il ON (i.`id_image` = il.`id_image` AND il.`id_lang` = '.(int)$id_lang.')
LEFT JOIN `'._DB_PREFIX_.'tax_rule` tr ON (p.`id_tax_rules_group` = tr.`id_tax_rules_group`
AND tr.`id_country` = '.(int)$context->country->id.'
- AND tr.`id_state` = 0)
+ AND tr.`id_state` = 0
+ AND tr.`zipcode_from` = 0)
LEFT JOIN `'._DB_PREFIX_.'tax` t ON (t.`id_tax` = tr.`id_tax`)
LEFT JOIN `'._DB_PREFIX_.'tax_lang` tl ON (t.`id_tax` = tl.`id_tax` AND tl.`id_lang` = '.(int)$id_lang.')
LEFT JOIN `'._DB_PREFIX_.'manufacturer` m ON m.`id_manufacturer` = p.`id_manufacturer`
diff --git a/classes/County.php b/classes/County.php
index 1f0045b66..d4449ba8a 100644
--- a/classes/County.php
+++ b/classes/County.php
@@ -25,6 +25,10 @@
* International Registered Trademark & Property of PrestaShop SA
*/
+
+/**
+* @deprecated since 1.5
+*/
class CountyCore extends ObjectModel
{
public $id;
@@ -63,181 +67,97 @@ class CountyCore extends ObjectModel
public function delete()
{
- $id = $this->id;
- parent::delete();
-
- // remove associated zip codes & tax rule
- return (County::deleteZipCodeByIdCounty($id) AND TaxRule::deleteTaxRuleByIdCounty($id));
+ return true;
}
+ /**
+ * @deprecated since 1.5
+ */
public static function getCounties($id_state)
{
- if (!isset(self::$_cache_get_counties[$id_state]))
- {
- self::$_cache_get_counties[$id_state] = Db::getInstance()->ExecuteS('
- SELECT * FROM `'._DB_PREFIX_.'county`
- WHERE `id_state` = '.(int)$id_state
- );
- }
-
- return self::$_cache_get_counties[$id_state];
+ Tools::displayAsDeprecated();
+ return false;
}
- // return the list of associated zipcode
+ /**
+ * @deprecated since 1.5
+ */
public function getZipCodes()
{
- return Db::getInstance()->ExecuteS('
- SELECT * FROM `'._DB_PREFIX_.'county_zip_code`
- WHERE `id_county` = '.(int)$this->id.'
- ORDER BY `from_zip_code` ASC'
- );
+ Tools::displayAsDeprecated();
+ return false;
}
+ /**
+ * @deprecated since 1.5
+ */
public function addZipCodes($zip_codes)
{
- list($from, $to) = $this->breakDownZipCode($zip_codes);
-
- if ($from == 0)
- return false;
-
- return Db::getInstance()->Execute(
- 'INSERT INTO `'._DB_PREFIX_.'county_zip_code` (`id_county`, `from_zip_code`, `to_zip_code`)
- VALUES ('.(int)$this->id.','.(int)$from.','.(int)$to.')'
- );
+ Tools::displayAsDeprecated();
+ return true;
}
-
+ /**
+ * @deprecated since 1.5
+ */
public function removeZipCodes($zip_codes)
{
- list($from, $to) = $this->breakDownZipCode($zip_codes);
-
- if ($from == 0)
- return false;
-
- return Db::getInstance()->Execute('
- DELETE FROM `'._DB_PREFIX_.'county_zip_code`
- WHERE `id_county` = '.(int)$this->id.'
- AND `from_zip_code` = '.(int)$from.'
- AND `to_zip_code` = '.(int)$to
- );
+ Tools::displayAsDeprecated();
+ return true;
}
-
+ /**
+ * @deprecated since 1.5
+ */
public function breakDownZipCode($zip_codes)
{
- $zip_codes = preg_split('/-/', $zip_codes);
-
- if (sizeof($zip_codes) == 2)
- {
- $from = $zip_codes[0];
- $to = $zip_codes[1];
- if ($zip_codes[0] > $zip_codes[1])
- {
- $from = $zip_codes[1];
- $to = $zip_codes[0];
- }
- else if ($zip_codes[0] == $zip_codes[1])
- {
- $from = $zip_codes[0];
- $to = 0;
- }
- }
- else if (sizeof($zip_codes) == 1)
- {
- $from = $zip_codes[0];
- $to = 0;
- }
-
- if (!Validate::isInt($from) OR !Validate::isInt($to))
- {
- $from = 0;
- $to = 0;
- }
-
- return array($from, $to);
+ Tools::displayAsDeprecated();
+ return array(0,0);
}
+ /**
+ * @deprecated since 1.5
+ */
public static function getIdCountyByZipCode($id_state, $zip_code)
{
- if (!isset(self::$_cache_county_zipcode[$id_state.'-'.$zip_code]))
- {
- self::$_cache_county_zipcode[$id_state.'-'.$zip_code] = Db::getInstance()->getValue('
- SELECT DISTINCT c.`id_county` FROM `'._DB_PREFIX_.'county` c
- LEFT JOIN `'._DB_PREFIX_.'county_zip_code` cz ON (c.`id_county` = cz.`id_county`)
- WHERE `id_state` = '.(int)$id_state.'
- AND cz.`from_zip_code` >= '.(int)$zip_code.'
- AND cz.`to_zip_code` <= '.(int)$zip_code
- );
- }
-
- return self::$_cache_county_zipcode[$id_state.'-'.$zip_code];
+ Tools::displayAsDeprecated();
+ return false;
}
+ /**
+ * @deprecated since 1.5
+ */
public function isZipCodeRangePresent($zip_codes)
{
- $res = false;
- list($from, $to) = $this->breakDownZipCode($zip_codes);
-
- if ($from == 0)
- return false;
-
- if ($to != 0)
- {
- $res = Db::getInstance()->getValue('
- SELECT COUNT(*) FROM `'._DB_PREFIX_.'county_zip_code` cz
- LEFT JOIN `'._DB_PREFIX_.'county` c ON (c.`id_county` = cz.`id_county`)
- LEFT JOIN `'._DB_PREFIX_.'state` s ON (s.`id_state` = c.`id_state`)
- WHERE `from_zip_code` >= '.(int)$from.'
- AND `to_zip_code` <= '.(int)$to.'
- AND s.`id_country` = (SELECT `id_country`
- FROM `'._DB_PREFIX_.'state` s
- LEFT JOIN `'._DB_PREFIX_.'county` c ON (c.`id_state` = s.`id_state`)
- WHERE `id_county` = '.(int)$this->id.'
- )'
- );
- }
-
- return ($res OR County::isZipCodePresent($from) OR County::isZipCodePresent($to));
+ Tools::displayAsDeprecated();
+ return false;
}
+ /**
+ * @deprecated since 1.5
+ */
public function isZipCodePresent($zip_code)
{
-
- if ($zip_code == 0)
- return false;
-
- return (bool) Db::getInstance()->getValue('
- SELECT COUNT(*) FROM `'._DB_PREFIX_.'county_zip_code` cz
- LEFT JOIN `'._DB_PREFIX_.'county` c ON (c.`id_county` = cz.`id_county`)
- LEFT JOIN `'._DB_PREFIX_.'state` s ON (s.`id_state` = c.`id_state`)
- WHERE
- (`from_zip_code` <= '.(int)$zip_code.' AND `to_zip_code` >= '.(int)$zip_code.')
- OR
- (`from_zip_code` = '.(int)$zip_code.')
- AND s.`id_country` = (SELECT `id_country`
- FROM `'._DB_PREFIX_.'state` s
- LEFT JOIN `'._DB_PREFIX_.'county` c ON (c.`id_state` = s.`id_state`)
- WHERE `id_county` = '.(int)$this->id.'
- )'
- );
+ Tools::displayAsDeprecated();
+ return false;
}
+ /**
+ * @deprecated since 1.5
+ */
public static function deleteZipCodeByIdCounty($id_county)
{
- return Db::getInstance()->Execute(
- 'DELETE FROM `'._DB_PREFIX_.'county_zip_code`
- WHERE `id_county` = '.(int)$id_county
- );
+ Tools::displayAsDeprecated();
+ return true;
}
-
+ /**
+ * @deprecated since 1.5
+ */
public static function getIdCountyByNameAndIdState($name, $id_state)
{
- return Db::getInstance()->getValue('
- SELECT `id_county` FROM `'._DB_PREFIX_.'county`
- WHERE `name` = \''.pSQL($name).'\'
- AND `id_state` = '.(int)$id_state
- );
+ Tools::displayAsDeprecated();
+ return false;
}
}
diff --git a/classes/Helper.php b/classes/Helper.php
index 3c52ab550..bc9ad0bdd 100755
--- a/classes/Helper.php
+++ b/classes/Helper.php
@@ -34,7 +34,7 @@ class HelperCore
public static $translationsKeysForAdminCategorieTree = array(
'Home', 'selected', 'selecteds', 'Collapse All', 'Expand All', 'Check All', 'Uncheck All'
);
-
+
/**
*
* @param type $trads values of translations keys
@@ -42,22 +42,22 @@ class HelperCore
* @param type $selected_cat array of selected categories
* Format
* Array
- (
- [0] => 1
- [1] => 2
- )
- * OR
- Array
- (
- [1] => Array
- (
- [id_category] => 1
- [name] => Home page
- [link_rewrite] => home
- )
- )
+ * (
+ * [0] => 1
+ * [1] => 2
+ * )
+ * OR
+ * Array
+ * (
+ * [1] => Array
+ * (
+ * [id_category] => 1
+ * [name] => Home page
+ * [link_rewrite] => home
+ * )
+ * )
* @param type $input_name name of input
- * @return string
+ * @return string
*/
public static function renderAdminCategorieTree($trads, $selected_cat = array(), $input_name = 'categoryBox', $use_radio = false)
{
@@ -86,7 +86,7 @@ class HelperCore
';
-
+
$html .= '
';
-
+
$home_is_selected = false;
foreach($selected_cat AS $cat)
{
@@ -121,10 +121,77 @@ class HelperCore
'.$trads['Home'].'
';
return $html;
}
+
+ /**
+ * Create a select input field
+ *
+ * @param array $values
+ * @param array $html_options any key => value options
+ * @param array $select_options
+ * - key: the array value that will be used as a key in my select (optional)
+ * - value: the array value that will be used as a label in my select (optional)
+ * - empty: the label displayed as an empty value (optional)
+ * - selected: the key corresponding to the selected value (optional)
+ *
+ * @return string html content
+ */
+ public static function selectInput(array $values, array $html_options = array(), array $select_options = array())
+ {
+ // options management
+ $options = self::buildHtmlOptions($html_options);
+ $select_html = '';
+
+ if (isset($select_options['key']))
+ $use_key = $select_options['key'];
+
+ if (isset($select_options['value']))
+ $use_value = $select_options['value'];
+
+ if (isset($select_options['empty']))
+ $select_html .= ''.$select_options['empty'].' ';
+
+ // render options fields
+ foreach ($values as $key => $value)
+ {
+ $current_key = isset($use_key) ? $value[$use_key] : $key;
+ $current_value = isset($use_value) ? $value[$use_value] : $value;
+
+ if (isset($select_options['selected']) && $select_options['selected'] == $current_key)
+ $selected = 'selected="selected"';
+ else
+ $selected = '';
+
+ $select_html .= ''.Tools::htmlentitiesUTF8($current_value).' ';
+ }
+
+ $select_html .= ' ';
+
+ return $select_html;
+ }
+
+ /**
+ * Create html a string containing html options
+ * eg: buildHtmlOptions(array('name' => 'myInputName', 'id' => 'myInputId'));
+ * return => 'name="myInputName" id="myInputId"'
+ *
+ * @param array $html_options
+ *
+ * @return string
+ */
+ protected static function buildHtmlOptions(array $html_options)
+ {
+ $html = '';
+
+ foreach ($html_options as $html_option => $value)
+ $html .= Tools::htmlentitiesUTF8($html_option).'="'.Tools::htmlentitiesUTF8($value).'" ';
+
+ return rtrim($html, ' ');
+ }
}
+
diff --git a/classes/LocalizationPack.php b/classes/LocalizationPack.php
index a7c78d92f..899a4d44b 100644
--- a/classes/LocalizationPack.php
+++ b/classes/LocalizationPack.php
@@ -117,60 +117,8 @@ class LocalizationPackCore
return false;
}
}
-
- // Add counties
- foreach ($data->county AS $xml_county)
- {
- $county_attributes = $xml_county->attributes();
- if (!$id_county = County::getIdCountyByNameAndIdState($county_attributes['name'], $state->id))
- {
- $county = new County();
- $county->name = $county_attributes['name'];
- $county->id_state = (int)$state->id;
- $county->active = 1;
-
- if (!$county->validateFields())
- {
- $this->_errors[] = Tools::displayError('Invalid County properties');
- return false;
- }
-
- if (!$county->save())
- {
- $this->_errors[] = Tools::displayError('An error has occurred while adding the county');
- return false;
- }
- } else {
- $county = new County((int)$id_county);
- if (!Validate::isLoadedObject($county))
- {
- $this->_errors[] = Tools::displayError('An error occurred while fetching the county.');
- return false;
- }
- }
-
- // add zip codes
- foreach ($xml_county->zipcode AS $xml_zipcode)
- {
- $zipcode_attributes = $xml_zipcode->attributes();
-
- $zipcodes = $zipcode_attributes['from'];
- if (isset($zipcode_attributes['to']))
- $zipcodes .= '-'.$zipcode_attributes['to'];
-
- if ($county->isZipCodeRangePresent($zipcodes))
- continue;
-
- if (!$county->addZipCodes($zipcodes))
- {
- $this->_errors[] = Tools::displayError('An error has occurred while adding zipcodes');
- return false;
- }
- }
- }
}
-
return true;
}
diff --git a/classes/Manufacturer.php b/classes/Manufacturer.php
index f0c4b1677..871314390 100644
--- a/classes/Manufacturer.php
+++ b/classes/Manufacturer.php
@@ -286,8 +286,9 @@ class ManufacturerCore extends ObjectModel
LEFT JOIN `'._DB_PREFIX_.'image` i ON (i.`id_product` = p.`id_product` AND i.`cover` = 1)
LEFT JOIN `'._DB_PREFIX_.'image_lang` il ON (i.`id_image` = il.`id_image` AND il.`id_lang` = '.(int)$id_lang.')
LEFT JOIN `'._DB_PREFIX_.'tax_rule` tr ON (p.`id_tax_rules_group` = tr.`id_tax_rules_group`
- AND tr.`id_country` = '.(int)$context->country->id.'
- AND tr.`id_state` = 0)
+ AND tr.`id_country` = '.(int)$context->country->id.'
+ AND tr.`id_state` = 0
+ AND tr.`zipcode_from` = 0)
LEFT JOIN `'._DB_PREFIX_.'tax` t ON (t.`id_tax` = tr.`id_tax`)
LEFT JOIN `'._DB_PREFIX_.'tax_lang` tl ON (t.`id_tax` = tl.`id_tax` AND tl.`id_lang` = '.(int)$id_lang.')
LEFT JOIN `'._DB_PREFIX_.'manufacturer` m ON m.`id_manufacturer` = p.`id_manufacturer`
diff --git a/classes/PaymentModule.php b/classes/PaymentModule.php
index 7f0d58a73..6168aaa0d 100644
--- a/classes/PaymentModule.php
+++ b/classes/PaymentModule.php
@@ -99,9 +99,12 @@ abstract class PaymentModuleCore extends Module
if ($secure_key !== false AND $secure_key != $cart->secure_key)
die(Tools::displayError());
+
+ $carrier = new Carrier((int)$cart->id_carrier, (int)$cart->id_lang);
+
// Copying data from cart
$order = new Order();
- $order->id_carrier = (int)($cart->id_carrier);
+ $order->id_carrier = $carrier->id;
$order->id_customer = (int)($cart->id_customer);
$order->id_address_invoice = (int)($cart->id_address_invoice);
$order->id_address_delivery = (int)($cart->id_address_delivery);
@@ -109,10 +112,10 @@ abstract class PaymentModuleCore extends Module
$order->id_currency = ($currency_special ? (int)($currency_special) : (int)($cart->id_currency));
$order->id_lang = (int)($cart->id_lang);
$order->id_cart = (int)($cart->id);
-
+
$order->id_shop = (int)($shop->getID() ? $shop->getID() : $cart->id_shop);
$order->id_group_shop = (int)($shop->getID() ? $shop->getGroupID() : $cart->id_group_shop);
-
+
$customer = new Customer((int)($order->id_customer));
$order->secure_key = ($secure_key ? pSQL($secure_key) : pSQL($customer->secure_key));
$order->payment = $paymentMethod;
@@ -128,8 +131,8 @@ abstract class PaymentModuleCore extends Module
$order->total_products = (float)($cart->getOrderTotal(false, Cart::ONLY_PRODUCTS));
$order->total_products_wt = (float)($cart->getOrderTotal(true, Cart::ONLY_PRODUCTS));
$order->total_discounts = (float)(abs($cart->getOrderTotal(true, Cart::ONLY_DISCOUNTS)));
- $order->total_shipping = (float)($cart->getOrderShippingCost());
- $order->carrier_tax_rate = (float)Tax::getCarrierTaxRate($cart->id_carrier, (int)$cart->{Configuration::get('PS_TAX_ADDRESS_TYPE')});
+ $order->total_shipping = (float)$cart->getOrderShippingCost();
+ $order->carrier_tax_rate = (float)$carrier->getTaxesRate(new Address((int)$cart->{Configuration::get('PS_TAX_ADDRESS_TYPE')}));
$order->total_wrapping = (float)(abs($cart->getOrderTotal(true, Cart::ONLY_WRAPPING)));
$order->total_paid = (float)(Tools::ps_round((float)($cart->getOrderTotal(true, Cart::BOTH)), 2));
$order->invoice_date = '0000-00-00 00:00:00';
@@ -256,15 +259,15 @@ abstract class PaymentModuleCore extends Module
if (isset($customization['datas'][_CUSTOMIZE_TEXTFIELD_]))
foreach ($customization['datas'][_CUSTOMIZE_TEXTFIELD_] AS $text)
$customizationText .= $text['name'].':'.' '.$text['value'].' ';
-
+
if (isset($customization['datas'][_CUSTOMIZE_FILE_]))
$customizationText .= sizeof($customization['datas'][_CUSTOMIZE_FILE_]) .' '. Tools::displayError('image(s)').' ';
-
- $customizationText .= '--- ';
+
+ $customizationText .= '--- ';
}
-
+
$customizationText = rtrim($customizationText, '--- ');
-
+
$customizationQuantity = (int)($product['customizationQuantityTotal']);
$productsList .=
'
@@ -377,7 +380,6 @@ abstract class PaymentModuleCore extends Module
{
$invoice = new Address((int)($order->id_address_invoice));
$delivery = new Address((int)($order->id_address_delivery));
- $carrier = new Carrier((int)($order->id_carrier), $order->id_lang);
$delivery_state = $delivery->id_state ? new State((int)($delivery->id_state)) : false;
$invoice_state = $invoice->id_state ? new State((int)($invoice->id_state)) : false;
@@ -387,11 +389,11 @@ abstract class PaymentModuleCore extends Module
'{email}' => $customer->email,
'{delivery_block_txt}' => $this->_getFormatedAddress($delivery, "\n"),
'{invoice_block_txt}' => $this->_getFormatedAddress($invoice, "\n"),
- '{delivery_block_html}' => $this->_getFormatedAddress($delivery, " ",
+ '{delivery_block_html}' => $this->_getFormatedAddress($delivery, " ",
array(
- 'firstname' => '%s ',
+ 'firstname' => '%s ',
'lastname' => '%s ')),
- '{invoice_block_html}' => $this->_getFormatedAddress($invoice, " ",
+ '{invoice_block_html}' => $this->_getFormatedAddress($invoice, " ",
array(
'firstname' => '%s ',
'lastname' => '%s ')),
diff --git a/classes/Product.php b/classes/Product.php
index 70b9b8f49..d08705035 100644
--- a/classes/Product.php
+++ b/classes/Product.php
@@ -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
*/
diff --git a/classes/Supplier.php b/classes/Supplier.php
index 04cc60991..7fbc535ef 100644
--- a/classes/Supplier.php
+++ b/classes/Supplier.php
@@ -223,7 +223,8 @@ class SupplierCore extends ObjectModel
LEFT JOIN `'._DB_PREFIX_.'image_lang` il ON (i.`id_image` = il.`id_image` AND il.`id_lang` = '.(int)($id_lang).')
LEFT JOIN `'._DB_PREFIX_.'tax_rule` tr ON (p.`id_tax_rules_group` = tr.`id_tax_rules_group`
AND tr.`id_country` = '.(int)Context::getContext()->country->id.'
- AND tr.`id_state` = 0)
+ AND tr.`id_state` = 0
+ AND tr.`zipcode_from` = 0)
LEFT JOIN `'._DB_PREFIX_.'tax` t ON (t.`id_tax` = tr.`id_tax`)
LEFT JOIN `'._DB_PREFIX_.'tax_lang` tl ON (t.`id_tax` = tl.`id_tax` AND tl.`id_lang` = '.(int)($id_lang).')
LEFT JOIN `'._DB_PREFIX_.'supplier` s ON s.`id_supplier` = p.`id_supplier`
diff --git a/classes/Tax.php b/classes/tax/Tax.php
similarity index 60%
rename from classes/Tax.php
rename to classes/tax/Tax.php
index 3ef78b811..d10c32638 100644
--- a/classes/Tax.php
+++ b/classes/tax/Tax.php
@@ -74,138 +74,6 @@ class TaxCore extends ObjectModel
return parent::delete();
}
- /**
- * Get all available taxes
- *
- * @return array Taxes
- */
- public static function getTaxes($id_lang = false, $active = 1)
- {
- return Db::getInstance(_PS_USE_SQL_SLAVE_)->ExecuteS('
- SELECT t.id_tax, t.rate'.((int)($id_lang) ? ', tl.name, tl.id_lang ' : '').'
- FROM `'._DB_PREFIX_.'tax` t
- '.((int)($id_lang) ? 'LEFT JOIN `'._DB_PREFIX_.'tax_lang` tl ON (t.`id_tax` = tl.`id_tax` AND tl.`id_lang` = '.(int)($id_lang).')'
- .($active == 1 ? 'WHERE t.`active` = 1' : '').'
- ORDER BY `name` ASC' : ''));
- }
-
- public static function excludeTaxeOption()
- {
- return !Configuration::get('PS_TAX');
- }
-
- 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;
- }
-
- /**
- * Return the product tax
- *
- * @param integer $id_product
- * @param integer $id_country
- * @return Tax
- */
- public static function getProductTaxRate($id_product, $id_address = NULL)
- {
- $id_country = (int)Context::getContext()->country->id;
- $id_state = 0;
- $id_county = 0;
- $rate = 0;
- if (!empty($id_address))
- {
- $address_infos = Address::getCountryAndState($id_address);
- if ($address_infos['id_country'])
- {
- $id_country = (int)($address_infos['id_country']);
- $id_state = (int)$address_infos['id_state'];
- $id_county = (int)County::getIdCountyByZipCode($address_infos['id_state'], $address_infos['postcode']);
- }
-
- if (!empty($address_infos['vat_number']) AND $address_infos['id_country'] != Configuration::get('VATNUMBER_COUNTRY') AND Configuration::get('VATNUMBER_MANAGEMENT'))
- return 0;
- }
-
- if ($rate = Tax::getProductTaxRateViaRules((int)$id_product, (int)$id_country, (int)$id_state, (int)$id_county))
- return $rate;
-
- return $rate;
- }
-
- public static function getProductEcotaxRate($id_address = NULL)
- {
- $id_country = (int)Context::getContext()->country->id;
- $id_state = 0;
- $id_county = 0;
- $rate = 0;
- if (!empty($id_address))
- {
- $address_infos = Address::getCountryAndState($id_address);
- if ($address_infos['id_country'])
- {
- $id_country = (int)($address_infos['id_country']);
- $id_state = (int)$address_infos['id_state'];
- $id_county = (int)County::getIdCountyByZipCode($address_infos['id_state'], $address_infos['postcode']);
- }
-
- if (!empty($address_infos['vat_number']) AND $address_infos['id_country'] != Configuration::get('VATNUMBER_COUNTRY') AND Configuration::get('VATNUMBER_MANAGEMENT'))
- return 0;
- }
-
- if ($rate = TaxRulesGroup::getTaxesRate((int)Configuration::get('PS_ECOTAX_TAX_RULES_GROUP_ID'), (int)$id_country, (int)$id_state, (int)$id_county))
- return $rate;
-
- return $rate;
- }
-
- /**
- * Return the product tax rate using the tax rules system
- *
- * @param integer $id_product
- * @param integer $id_country
- * @return Tax
- */
- public static function getProductTaxRateViaRules($id_product, $id_country, $id_state, $id_county)
- {
- if (!isset(self::$_product_tax_via_rules[$id_product.'-'.$id_country.'-'.$id_state.'-'.$id_county]))
- {
- $tax_rate = TaxRulesGroup::getTaxesRate((int)Product::getIdTaxRulesGroupByIdProduct((int)$id_product), (int)$id_country, (int)$id_state, (int)$id_county);
- self::$_product_tax_via_rules[$id_product.'-'.$id_country.'-'.$id_county] = $tax_rate;
- }
-
- return self::$_product_tax_via_rules[$id_product.'-'.$id_country.'-'.$id_county];
- }
-
-
- public static function getCarrierTaxRate($id_carrier, $id_address = NULL)
- {
- $id_country = (int)Context::getContext()->country->id;
- $id_state = 0;
- $id_county = 0;
- if (!empty($id_address))
- {
- $address_infos = Address::getCountryAndState($id_address);
- if ($address_infos['id_country'])
- {
- $id_country = (int)($address_infos['id_country']);
- $id_state = (int)$address_infos['id_state'];
- $id_county = (int)County::getIdCountyByZipCode($address_infos['id_state'], $address_infos['postcode']);
- }
-
- if (!empty($address_infos['vat_number']) AND $address_infos['id_country'] != Configuration::get('VATNUMBER_COUNTRY') AND Configuration::get('VATNUMBER_MANAGEMENT'))
- return 0;
- }
-
- return TaxRulesGroup::getTaxesRate((int)Carrier::getIdTaxRulesGroupByIdCarrier((int)$id_carrier), (int)$id_country, (int)$id_state, (int)$id_county);
- }
-
public function toggleStatus()
{
if (parent::toggleStatus())
@@ -229,5 +97,145 @@ class TaxCore extends ObjectModel
return true;
}
+
+ /**
+ * Get all available taxes
+ *
+ * @return array Taxes
+ */
+ public static function getTaxes($id_lang = false, $active = 1)
+ {
+ return Db::getInstance(_PS_USE_SQL_SLAVE_)->ExecuteS('
+ SELECT t.id_tax, t.rate'.((int)($id_lang) ? ', tl.name, tl.id_lang ' : '').'
+ FROM `'._DB_PREFIX_.'tax` t
+ '.((int)($id_lang) ? 'LEFT JOIN `'._DB_PREFIX_.'tax_lang` tl ON (t.`id_tax` = tl.`id_tax` AND tl.`id_lang` = '.(int)($id_lang).')'
+ .($active == 1 ? 'WHERE t.`active` = 1' : '').'
+ ORDER BY `name` ASC' : ''));
+ }
+
+ public static function excludeTaxeOption()
+ {
+ return !Configuration::get('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 product tax
+ *
+ * @param integer $id_product
+ * @param integer $id_country
+ * @return Tax
+ *
+ * @deprecated use $product->getTaxesRate() instead
+ */
+ public static function getProductTaxRate($id_product, $id_address = NULL)
+ {
+ $address = Tax::initializeAddress($id_address);
+ $id_tax_rules = (int)Product::getIdTaxRulesGroupByIdProduct($id_product);
+
+ $tax_manager = TaxManagerFactory::getManager($address, $id_tax_rules);
+ $tax_calculator = $tax_manager->getTaxCalculator();
+
+ return $tax_calculator->getTaxesRate();
+ }
+
+ /**
+ * Returns the ecotax tax rate
+ *
+ * @param id_address
+ * @return float $tax_rate
+ */
+ public static function getProductEcotaxRate($id_address = NULL)
+ {
+ $address = Tax::initializeAddress($id_address);
+
+ $tax_manager = TaxManagerFactory::getManager($address, (int)Configuration::get('PS_ECOTAX_TAX_RULES_GROUP_ID'));
+ $tax_calculator = $tax_manager->getTaxCalculator();
+
+ return $tax_calculator->getTaxesRate();
+ }
+
+ /**
+ * Returns the carrier tax rate
+ *
+ * @param id_address
+ * @return float $tax_rate
+ */
+ public static function getCarrierTaxRate($id_carrier, $id_address = NULL)
+ {
+ $address = Tax::initializeAddress($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->getTaxesRate();
+ }
+
+ /**
+ * Initiliaze an address corresponding to the id address if any or to the
+ * default shop configuration
+ *
+ * @param int $id_address
+ * @return Address address
+ */
+ public static function initializeAddress($id_address = NULL)
+ {
+ // set the default address
+ $address = new Address();
+ $address->id_country = (int)Context::getContext()->country->id;
+ $address->id_state = 0;
+ $address->postcode = 0;
+
+ // if an id_address has been specified retrieve the address
+ if ($id_address)
+ {
+ $address = new Address((int)$id_address);
+
+ if (!Validate::isLoadedObject())
+ throw new Exception('Invalid address');
+ }
+
+ return $address;
+ }
+
+ /**
+ * 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];
+ }
}
diff --git a/classes/tax/TaxCalculator.php b/classes/tax/TaxCalculator.php
new file mode 100644
index 000000000..547c3446e
--- /dev/null
+++ b/classes/tax/TaxCalculator.php
@@ -0,0 +1,144 @@
+
+* @copyright 2007-2011 PrestaShop SA
+* @version Release: $Revision$
+* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
+* International Registered Trademark & Property of PrestaShop SA
+*/
+
+/**
+ * @since 1.5.0
+ *
+ * TaxCaculator is responsible of the tax computation
+ */
+class TaxCalculatorCore
+{
+ /**
+ * COMBINE_METHOD sum taxes
+ * eg: 100€ * (10% + 15%)
+ */
+ const COMBINE_METHOD = 1;
+
+ /**
+ * ONE_AFTER_ANOTHER_METHOD apply taxes one after another
+ * eg: (100€ * 10%) * 15%
+ */
+ const ONE_AFTER_ANOTHER_METHOD = 2;
+
+ /**
+ * @var array $taxes_rate
+ */
+ public $taxes_rate;
+
+ /**
+ * @var int $computation_method (COMBINE_METHOD | ONE_AFTER_ANOTHER_METHOD)
+ */
+ public $computation_method;
+
+
+ /**
+ * @param array $taxes_rate
+ * @param int $computation_method (COMBINE_METHOD | ONE_AFTER_ANOTHER_METHOD)
+ */
+ public function __construct(array $taxes_rate, $computation_method = TaxCalculator::COMBINE_METHOD)
+ {
+ $this->taxes_rate = $taxes_rate;
+ $this->computation_method = (int)$computation_method;
+ }
+
+ /**
+ * Compute and add the taxes to the specified price
+ *
+ * @param price
+ * @return price with taxes
+ */
+ public function addTaxes($price)
+ {
+ $total_price = $price;
+ if ($this->computation_method == TaxCalculator::ONE_AFTER_ANOTHER_METHOD)
+ {
+ foreach ($this->taxes_rate as $tax_rate)
+ $total_price = $total_price * (1 + abs($tax_rate) / 100);
+ }
+ else
+ {
+ foreach ($this->taxes_rate as $tax_rate)
+ {
+ if ($tax_rate != 0)
+ $total_price = $total_price + ($price * (abs($tax_rate) / 100));
+ }
+ }
+ return $total_price;
+ }
+
+
+ /**
+ * Compute and remove the taxes to the specified price
+ *
+ * @param price
+ * @return price without taxes
+ */
+ public function removeTaxes($price)
+ {
+ $total_price = $price;
+ if ($this->computation_method == TaxCalculator::ONE_AFTER_ANOTHER_METHOD)
+ {
+ foreach ($this->taxes_rate as $tax_rate)
+ $total_price = $total_price / (1 + abs($tax_rate) / 100);
+ }
+ else
+ {
+ $taxes_rate = 0;
+ foreach ($this->taxes_rate as $tax_rate)
+ $taxes_rate += abs($tax_rate);
+
+ $total_price = $total_price / (1 + (abs($taxes_rate) / 100));
+ }
+
+ return $total_price;
+ }
+
+ /**
+ * @return total taxes rate
+ */
+ public function getTaxesRate()
+ {
+ $taxes_rate = 0;
+ if ($this->computation_method == TaxCalculator::ONE_AFTER_ANOTHER_METHOD)
+ {
+ $taxes_rate = 1;
+ foreach ($this->taxes_rate as $rate)
+ $taxes_rate *= (1 + (abs($rate) / 100));
+
+ $taxes_rate = $taxes_rate - 1;
+ $taxes_rate = $taxes_rate * 100;
+ }
+ else
+ {
+ foreach ($this->taxes_rate as $rate)
+ $taxes_rate += abs($rate);
+ }
+
+ return $taxes_rate;
+ }
+}
+
diff --git a/classes/tax/TaxManagerFactory.php b/classes/tax/TaxManagerFactory.php
new file mode 100644
index 000000000..4ced3f9b7
--- /dev/null
+++ b/classes/tax/TaxManagerFactory.php
@@ -0,0 +1,103 @@
+
+* @copyright 2007-2011 PrestaShop SA
+* @version Release: $Revision$
+* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
+* International Registered Trademark & Property of PrestaShop SA
+*/
+
+/**
+* @since 1.5
+*/
+class TaxManagerFactoryCore
+{
+ protected static $cache_tax_manager;
+
+ /**
+ * Returns a tax manager able to handle this address
+ *
+ * @param Address $address
+ * @param string $type
+ *
+ * @return TaxManager
+ */
+ public static function getManager(Address $address, $type)
+ {
+ $cache_id = TaxManagerFactory::getCacheKey($address).'-'.$type;
+ if (!isset(TaxManagerFactory::$cache_tax_manager[$cache_id]))
+ {
+ $tax_manager = TaxManagerFactory::execHookTaxManagerFactory($address, $type);
+ if (!($tax_manager instanceof TaxManagerInterface))
+ $tax_manager = new TaxRulesTaxManager($address, $type);
+
+ TaxManagerFactory::$cache_tax_manager[$cache_id] = $tax_manager;
+ }
+
+ return TaxManagerFactory::$cache_tax_manager[$cache_id];
+ }
+
+ /**
+ * Check for a tax manager able to handle this type of address in the module list
+ *
+ * @param Address $address
+ * @param string $type
+ *
+ * @return TaxManager
+ */
+ public static function execHookTaxManagerFactory(Address $address, $type)
+ {
+ $modules_infos = Hook::getModulesFromHook(Hook::getIdByName('taxManager'));
+ $tax_manager = false;
+
+ foreach ($modules_infos as $module_infos)
+ {
+ $module_instance = Module::getInstanceByName($module_infos['name']);
+ if (is_callable(array($module_instance, 'hookTaxManager')))
+ {
+ $tax_manager = $module_instance->hookTaxManager(array(
+ 'address' => $address,
+ 'params' => $type
+ ));
+ }
+
+ if ($tax_manager)
+ break;
+ }
+
+ return $tax_manager;
+ }
+
+
+ /**
+ * Create a unique identifier for the address
+ * @param Address
+ */
+ protected static function getCacheKey(Address $address)
+ {
+ return $address->id_country.'-'
+ .(int)$address->id_state.'-'
+ .$address->postcode.'-'
+ .$address->vat_number.'-'
+ .$address->dni;
+ }
+}
+
diff --git a/classes/tax/TaxManagerInterface.php b/classes/tax/TaxManagerInterface.php
new file mode 100644
index 000000000..c8b388e34
--- /dev/null
+++ b/classes/tax/TaxManagerInterface.php
@@ -0,0 +1,51 @@
+
+* @copyright 2007-2011 PrestaShop SA
+* @version Release: $Revision$
+* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
+* International Registered Trademark & Property of PrestaShop SA
+*/
+
+
+/**
+* A TaxManager define a way to retrieve tax.
+*/
+interface TaxManagerInterface
+{
+ /**
+ * This method determine if the tax manager is available for the specified address.
+ *
+ * @param Address $address
+ * @param string $type
+ *
+ * @return TaxManager
+ */
+ public static function isAvailableForThisAddress(Address $address);
+
+ /**
+ * Return the tax calculator associated to this address
+ *
+ * @return TaxCalculator
+ */
+ public function getTaxCalculator();
+}
+
diff --git a/classes/tax/TaxManagerModule.php b/classes/tax/TaxManagerModule.php
new file mode 100644
index 000000000..ecab6c6b9
--- /dev/null
+++ b/classes/tax/TaxManagerModule.php
@@ -0,0 +1,57 @@
+
+* @copyright 2007-2011 PrestaShop SA
+* @version Release: $Revision$
+* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
+* International Registered Trademark & Property of PrestaShop SA
+*/
+
+abstract class TaxManagerModuleCore extends Module
+{
+ public $tax_manager_class;
+
+ public function install()
+ {
+ return (parent::install() && $this->registerHook('taxManager') );
+ }
+
+ public function hookTaxManager($args)
+ {
+ $class_file =_PS_MODULE_DIR_.'/'.$this->name.'/'.$this->tax_manager_class.'.php';
+
+ if (!isset($this->tax_manager_class) || !file_exists($class_file))
+ die(Tools::displayError('Incorrect Tax Manager class ['.$this->tax_manager_class.']'));
+
+ require_once($class_file);
+
+ if (!class_exists($this->tax_manager_class))
+ die(Tools::displayError('Tax Manager class not found ['.$this->tax_manager_class.']'));
+
+ $class = $this->tax_manager_class;
+
+ if ($class::isAvailableForThisAddress($args['address']))
+ return new $class();
+
+ return false;
+ }
+}
+
diff --git a/classes/TaxRule.php b/classes/tax/TaxRule.php
similarity index 52%
rename from classes/TaxRule.php
rename to classes/tax/TaxRule.php
index c527f0db6..3b697f880 100644
--- a/classes/TaxRule.php
+++ b/classes/tax/TaxRule.php
@@ -30,13 +30,21 @@ class TaxRuleCore extends ObjectModel
public $id_tax_rules_group;
public $id_country;
public $id_state;
- public $id_county;
+ public $zipcode_from;
+ public $zipcode_to;
public $id_tax;
- public $state_behavior;
- public $county_behavior;
+ public $behavior;
+ public $description;
protected $fieldsRequired = array('id_tax_rules_group', 'id_country', 'id_tax');
- protected $fieldsValidate = array('id_tax_rules_group' => 'isUnsignedId', 'id_country' => 'isUnsignedId', 'id_state' => 'isUnsignedId', 'id_county' => 'isUnsignedId', 'id_tax' => 'isUnsignedId', 'state_behavior' => 'isUnsignedInt', 'county_behavior' => 'isUnsignedInt');
+ protected $fieldsValidate = array('id_tax_rules_group' => 'isUnsignedId',
+ 'id_country' => 'isUnsignedId',
+ 'id_state' => 'isUnsignedId',
+ 'zipcode_from' => 'isUnsignedId', // TODO: char
+ 'zipcode_to' => 'isUnsignedId', // TODO: char
+ 'id_tax' => 'isUnsignedId',
+ 'behavior' => 'isUnsignedInt',
+ 'description' => 'isUnsignedInt'); // TODO:char
protected $table = 'tax_rule';
protected $identifier = 'id_tax_rule';
@@ -47,10 +55,11 @@ class TaxRuleCore extends ObjectModel
$fields['id_tax_rules_group'] = (int)($this->id_tax_rules_group);
$fields['id_country'] = (int)$this->id_country;
$fields['id_state'] = (int)$this->id_state;
- $fields['id_county'] = (int)$this->id_county;
- $fields['state_behavior'] = (int)$this->state_behavior;
- $fields['county_behavior'] = (int)$this->county_behavior;
- $fields['id_tax'] = (int)($this->id_tax);
+ $fields['zipcode_from'] = (int)$this->zipcode_from;
+ $fields['zipcode_to'] = (int)$this->zipcode_to;
+ $fields['behavior'] = (int)$this->behavior;
+ $fields['id_tax'] = (int)($this->id_tax);
+ $fields['description'] = $this->description;
return $fields;
}
@@ -66,23 +75,44 @@ class TaxRuleCore extends ObjectModel
);
}
+ public static function retrieveById($id_tax_rule)
+ {
+ return Db::getInstance()->getRow('
+ SELECT * FROM `'._DB_PREFIX_.'tax_rule`
+ WHERE `id_tax_rule` = '.(int)$id_tax_rule);
+ }
+/*
public static function getTaxRulesByGroupId($id_group)
{
if (empty($id_group))
die(Tools::displayError());
- $results = Db::getInstance()->ExecuteS('
+ return Db::getInstance()->ExecuteS('
SELECT *
FROM `'._DB_PREFIX_.'tax_rule`
WHERE `id_tax_rules_group` = '.(int)$id_group
);
+ }*/
- $res = array();
- foreach ($results AS $row)
- $res[$row['id_country']][$row['id_state']][$row['id_county']] = array('id_tax' => $row['id_tax'], 'state_behavior' => $row['state_behavior'], 'county_behavior' => $row['county_behavior']);
+ public static function getTaxRulesByGroupId($id_lang, $id_group)
+ {
- return $res;
- }
+
+ return Db::getInstance()->ExecuteS('
+ SELECT g.`id_tax_rule`,
+ c.`name` AS country_name,
+ s.`name` AS state_name,
+ t.rate,
+ g.`zipcode_from`, g.`zipcode_to`,
+ g.`description`,
+ g.`behavior`
+ FROM `'._DB_PREFIX_.'tax_rule` g
+ LEFT JOIN `'._DB_PREFIX_.'country_lang` c ON (g.`id_country` = c.`id_country` AND id_lang = '.(int)$id_lang.')
+ LEFT JOIN `'._DB_PREFIX_.'state` s ON (g.`id_state` = s.`id_state`)
+ LEFT JOIN `'._DB_PREFIX_.'tax` t ON (g.`id_tax` = t.`id_tax`)
+ WHERE `id_tax_rules_group` = '.(int)$id_group
+ );
+ }
public static function deleteTaxRuleByIdTax($id_tax)
{
@@ -93,19 +123,57 @@ class TaxRuleCore extends ObjectModel
}
+ /**
+ * @deprecated since 1.5
+ */
public static function deleteTaxRuleByIdCounty($id_county)
{
- return Db::getInstance()->Execute('
- DELETE FROM `'._DB_PREFIX_.'tax_rule`
- WHERE `id_county` = '.(int)$id_county
- );
+ Tools::displayAsDeprecated();
+ return true;
}
+ /**
+ * @param int $id_tax
+ * @return boolean
+ */
public static function isTaxInUse($id_tax)
{
return Db::getInstance()->getValue('
SELECT COUNT(*) FROM `'._DB_PREFIX_.'tax_rule` WHERE `id_tax` = '.(int)$id_tax
);
}
+
+
+ /**
+ * @param string $zipcode a range of zipcode (eg: 75000 / 75000-75015)
+ * @return array an array containing two zipcode ordered by zipcode
+ */
+ public function breakDownZipCode($zip_codes)
+ {
+ $zip_codes = preg_split('/-/', $zip_codes);
+
+ if (sizeof($zip_codes) == 2)
+ {
+ $from = $zip_codes[0];
+ $to = $zip_codes[1];
+ if ($zip_codes[0] > $zip_codes[1])
+ {
+ $from = $zip_codes[1];
+ $to = $zip_codes[0];
+ }
+ elseif ($zip_codes[0] == $zip_codes[1])
+ {
+ $from = $zip_codes[0];
+ $to = 0;
+ }
+ }
+ elseif (sizeof($zip_codes) == 1)
+ {
+ $from = $zip_codes[0];
+ $to = 0;
+ }
+
+ return array($from, $to);
+ }
}
diff --git a/classes/TaxRulesGroup.php b/classes/tax/TaxRulesGroup.php
similarity index 61%
rename from classes/TaxRulesGroup.php
rename to classes/tax/TaxRulesGroup.php
index b8c4e1d6a..793f831a5 100644
--- a/classes/TaxRulesGroup.php
+++ b/classes/tax/TaxRulesGroup.php
@@ -59,74 +59,19 @@ class TaxRulesGroupCore extends ObjectModel
);
}
+ /**
+ * @return array an array of tax rules group formatted as $id => $name
+ */
public static function getTaxRulesGroupsForOptions()
{
$tax_rules[] = array('id_tax_rules_group' => 0, 'name' => Tools::displayError('No tax'));
return array_merge($tax_rules, TaxRulesGroup::getTaxRulesGroups());
}
- public static function getTaxes($id_tax_rules_group, $id_country, $id_state, $id_county)
- {
- if (empty($id_tax_rules_group) OR empty($id_country))
- return array(new Tax()); // No Tax
-
- if (isset(self::$_taxes[$id_tax_rules_group.'-'.$id_country.'-'.$id_state.'-'.$id_county]))
- return self::$_taxes[$id_tax_rules_group.'-'.$id_country.'-'.$id_state.'-'.$id_county];
-
- $rows = Db::getInstance()->ExecuteS('
- SELECT *
- FROM `'._DB_PREFIX_.'tax_rule`
- WHERE `id_country` = '.(int)$id_country.'
- AND `id_tax_rules_group` = '.(int)$id_tax_rules_group.'
- AND `id_state` IN (0, '.(int)$id_state.')
- AND `id_county` IN (0, '.(int)$id_county.')
- ORDER BY `id_county` DESC, `id_state` DESC'
- );
-
-
- $taxes = array();
- foreach ($rows AS $row)
- {
- if ($row['id_county'] != 0)
- {
- switch($row['county_behavior'])
- {
- case County::USE_BOTH_TAX:
- $taxes[] = new Tax($row['id_tax']);
- break;
-
- case County::USE_COUNTY_TAX:
- $taxes = array(new Tax($row['id_tax']));
- break 2;
-
- case County::USE_STATE_TAX: // do nothing
- break;
- }
- }
- else if ($row['id_state'] != 0)
- {
- switch($row['state_behavior'])
- {
- case PS_STATE_TAX: // use only product tax
- $taxes[] = new Tax($row['id_tax']);
- break 2; // switch + foreach
-
- case PS_BOTH_TAX:
- $taxes[] = new Tax($row['id_tax']);
- break;
-
- case PS_PRODUCT_TAX: // do nothing use country tax
- break;
- }
- }
- else
- $taxes[] = new Tax((int)$row['id_tax']);
- }
-
- self::$_taxes[$id_tax_rules_group.'-'.$id_country.'-'.$id_state.'-'.$id_county] = $taxes;
- return $taxes;
- }
+ /**
+ * @return array
+ */
public static function getAssociatedTaxRatesByIdCountry($id_country)
{
$rows = Db::getInstance()->ExecuteS('
@@ -136,7 +81,7 @@ class TaxRulesGroupCore extends ObjectModel
LEFT JOIN `'._DB_PREFIX_.'tax` t ON (t.`id_tax` = tr.`id_tax`)
WHERE tr.`id_country` = '.(int)$id_country.'
AND tr.`id_state` = 0
- AND tr.`id_county` = 0'
+ AND 0 between `zipcode_from` AND `zipcode_to`'
);
$res = array();
@@ -146,15 +91,12 @@ class TaxRulesGroupCore extends ObjectModel
return $res;
}
- public static function getTaxesRate($id_tax_rules_group, $id_country, $id_state, $id_county)
- {
- $rate = 0;
- foreach (TaxRulesGroup::getTaxes($id_tax_rules_group, $id_country, $id_state, $id_county) AS $tax)
- $rate += (float)$tax->rate;
-
- return $rate;
- }
-
+ /**
+ * Returns the tax rules group id corresponding to the name
+ *
+ * @param string name
+ * @return int id of the tax rules
+ */
public static function getIdByName($name)
{
return Db::getInstance()->getValue(
@@ -163,4 +105,29 @@ class TaxRulesGroupCore extends ObjectModel
WHERE `name` = \''.pSQL($name).'\''
);
}
-}
\ No newline at end of file
+
+ /**
+ * @deprecated since 1.5
+ */
+ public static function getTaxesRate($id_tax_rules_group, $id_country, $id_state, $zipcode)
+ {
+ Tools::displayAsDeprecated();
+ $rate = 0;
+ foreach (TaxRulesGroup::getTaxes($id_tax_rules_group, $id_country, $id_state, $zipcode) AS $tax)
+ $rate += (float)$tax->rate;
+
+ return $rate;
+ }
+
+ /**
+ * Return taxes associated to this para
+ * @deprecated since 1.5
+ */
+ public static function getTaxes($id_tax_rules_group, $id_country, $id_state, $id_county)
+ {
+ Tools::displayAsDeprecated();
+ return array();
+ }
+
+}
+
diff --git a/classes/tax/TaxRulesTaxManager.php b/classes/tax/TaxRulesTaxManager.php
new file mode 100644
index 000000000..9840a64d3
--- /dev/null
+++ b/classes/tax/TaxRulesTaxManager.php
@@ -0,0 +1,101 @@
+
+* @copyright 2007-2011 PrestaShop SA
+* @version Release: $Revision$
+* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
+* International Registered Trademark & Property of PrestaShop SA
+*/
+
+class TaxRulesTaxManagerCore implements TaxManagerInterface
+{
+ public $address;
+ public $type;
+ public $tax_calculator;
+
+
+ public function __construct(Address $address, $type)
+ {
+ $this->address = $address;
+ $this->type = $type;
+ }
+
+ /**
+ * Returns true if this tax manager is available for this address
+ *
+ * @return boolean
+ */
+ public static function isAvailableForThisAddress(Address $address)
+ {
+ return true; // default manager, available for all addresses
+ }
+
+ /**
+ * Return the tax calculator associated to this address
+ *
+ * @return TaxCalculator
+ */
+ public function getTaxCalculator()
+ {
+ if (isset($this->tax_calculator))
+ return $this->tax_calculator;
+
+ $postcode = 0;
+ if (!empty($this->address->postcode))
+ $postcode = $this->address->postcode;
+
+ $rows = Db::getInstance()->ExecuteS('
+ SELECT *
+ FROM `'._DB_PREFIX_.'tax_rule`
+ WHERE `id_country` = '.(int)$this->address->id_country.'
+ AND `id_tax_rules_group` = '.(int)$this->type.'
+ AND `id_state` IN (0, '.(int)$this->address->id_state.')
+ AND ('.pSQL($postcode).' BETWEEN `zipcode_from` AND `zipcode_to` OR `zipcode_from` = 0 OR `zipcode_from` = '.pSQL($postcode).')
+ ORDER BY `zipcode_from` DESC, `zipcode_to` DESC, `id_state` DESC, `id_country` DESC');
+
+ $behavior = 0;
+ $first_row = true;
+ $taxes_rates = array();
+
+ foreach ($rows as $row)
+ {
+ $tax = new Tax((int)$row['id_tax']);
+
+ $taxes_rates[] = $tax->rate;
+
+ // the applied behavior correspond to the most specific rules
+ if ($first_row)
+ {
+ $behavior = $row['behavior'];
+ $first_row = false;
+ }
+
+ if ($row['behavior'] == 0)
+ break;
+ }
+
+ $this->tax_calculator = new TaxCalculator($taxes_rates, $behavior);
+
+ return $this->tax_calculator;
+ }
+}
+
diff --git a/controllers/ProductController.php b/controllers/ProductController.php
index 8423629a7..754329c37 100644
--- a/controllers/ProductController.php
+++ b/controllers/ProductController.php
@@ -49,7 +49,7 @@ class ProductControllerCore extends FrontController
$this->addJS(_PS_JS_DIR_.'jquery/jquery.jqzoom.js');
}
}
-
+
public function canonicalRedirection()
{
// Automatically redirect to the canonical URL if the current in is the right one
@@ -189,9 +189,9 @@ class ProductControllerCore extends FrontController
$id_country = (int)($id_customer ? Customer::getCurrentCountry($id_customer) : Configuration::get('PS_COUNTRY_DEFAULT'));
// Tax
- $tax = (float)(Tax::getProductTaxRate((int)$this->product->id, $this->context->cart->{Configuration::get('PS_TAX_ADDRESS_TYPE')}));
+ $tax = (float)$this->product->getTaxesRate(new Address((int)$this->context->cart->{Configuration::get('PS_TAX_ADDRESS_TYPE')}));
$this->context->smarty->assign('tax_rate', $tax);
-
+
$productPriceWithTax = Product::getPriceStatic($this->product->id, true, NULL, 6);
if (Product::$_taxCalculationMethod == PS_TAX_INC)
$productPriceWithTax = Tools::ps_round($productPriceWithTax, 2);
diff --git a/install-dev/php/remove_tab.php b/install-dev/php/remove_tab.php
new file mode 100644
index 000000000..69666e70e
--- /dev/null
+++ b/install-dev/php/remove_tab.php
@@ -0,0 +1,11 @@
+Execute('
+ DELETE t, l
+ FROM `ps_tab` t LEFT JOIN `PREFIX_tab_lang` l ON (t.id_tab = l.id_tab)
+ WHERE t.`class_name` = '.pSQL($tabname));
+}
+
diff --git a/install-dev/php/update_tax_rules.php b/install-dev/php/update_tax_rules.php
new file mode 100644
index 000000000..252c4dd60
--- /dev/null
+++ b/install-dev/php/update_tax_rules.php
@@ -0,0 +1,48 @@
+Execute('
+ ALTER TABLE `'._DB_PREFIX_.'tax_rule`
+ ADD `zipcode_from` INT NOT NULL AFTER `id_state` ,
+ ADD `zipcode_to` INT NOT NULL AFTER `zipcode_from` ,
+ ADD `behavior` INT NOT NULL AFTER `zipcode_to`,
+ ADD `description` VARCHAR( 100 ) NOT NULL AFTER `id_tax`;
+ ');
+
+ // Drop integrity constraint
+ Db::getInstance()->Execute('
+ ALTER TABLE `'._DB_PREFIX_.'tax_rule` DROP INDEX tax_rule
+ ');
+
+ // Create new format rules
+ Db::getInstance()->Execute('
+ INSERT INTO `'._DB_PREFIX_.'tax_rule` (`id_tax_rules_group`, `id_country`, `id_state`, `id_tax`, `behavior`, `zipcode_from`, `zipcode_to`)
+ SELECT r.`id_tax_rules_group`, r.`id_country`, r.`id_state`, r.`id_tax`, 0, z.`from_zip_code`, z.`to_zip_code`
+ FROM `'._DB_PREFIX_.'tax_rule` r INNER JOIN `'._DB_PREFIX_.'county_zip_code` z ON (z.`id_county` = r.`id_county`)
+ ');
+
+ // update behavior
+ Db::getInstance()->Execute('
+ UPDATE `'._DB_PREFIX_.'tax_rule` SET `behavior` = GREATEST(`state_behavior`, `county_behavior`);
+ ');
+
+
+ // Clean old entries
+ Db::getInstance()->Execute('
+ DELETE FROM `'._DB_PREFIX_.'tax_rule`
+ WHERE `id_county` != 0
+ AND `zipcode_from` = 0
+ ');
+
+ // Remove old columns
+ Db::getInstance()->Execute('
+ ALTER TABLE `'._DB_PREFIX_.'tax_rule`
+ DROP `id_county`,
+ DROP `state_behavior`,
+ DROP `county_behavior`
+ ');
+}
+
diff --git a/install-dev/sql/db.sql b/install-dev/sql/db.sql
index 9d5bba38c..fa8171800 100644
--- a/install-dev/sql/db.sql
+++ b/install-dev/sql/db.sql
@@ -178,7 +178,7 @@ CREATE TABLE `PREFIX_cart` (
KEY `id_lang` (`id_lang`),
KEY `id_currency` (`id_currency`),
KEY `id_guest` (`id_guest`),
- KEY `id_group_shop` (`id_group_shop`),
+ KEY `id_group_shop` (`id_group_shop`),
KEY `id_shop` (`id_shop`)
) ENGINE=ENGINE_TYPE DEFAULT CHARSET=utf8;
@@ -324,7 +324,7 @@ CREATE TABLE `PREFIX_configuration_lang` (
CREATE TABLE `PREFIX_connections` (
`id_connections` int(10) unsigned NOT NULL auto_increment,
- `id_group_shop` INT(11) UNSIGNED NOT NULL DEFAULT '1',
+ `id_group_shop` INT(11) UNSIGNED NOT NULL DEFAULT '1',
`id_shop` INT(11) UNSIGNED NOT NULL DEFAULT '1',
`id_guest` int(10) unsigned NOT NULL,
`id_page` int(10) unsigned NOT NULL,
@@ -442,7 +442,7 @@ CREATE TABLE `PREFIX_customer` (
KEY `customer_login` (`email`,`passwd`),
KEY `id_customer_passwd` (`id_customer`,`passwd`),
KEY `id_gender` (`id_gender`),
- KEY `id_group_shop` (`id_group_shop`),
+ KEY `id_group_shop` (`id_group_shop`),
KEY `id_shop` (`id_shop`)
) ENGINE=ENGINE_TYPE DEFAULT CHARSET=utf8;
@@ -487,7 +487,7 @@ CREATE TABLE `PREFIX_customer_thread` (
KEY `id_contact` (`id_contact`),
KEY `id_customer` (`id_customer`),
KEY `id_order` (`id_order`),
- KEY `id_product` (`id_product`)
+ KEY `id_product` (`id_product`)
) ENGINE=ENGINE_TYPE DEFAULT CHARSET=utf8;
@@ -942,7 +942,7 @@ CREATE TABLE `PREFIX_orders` (
KEY `id_currency` (`id_currency`),
KEY `id_address_delivery` (`id_address_delivery`),
KEY `id_address_invoice` (`id_address_invoice`),
- KEY `id_group_shop` (`id_group_shop`),
+ KEY `id_group_shop` (`id_group_shop`),
KEY `id_shop` (`id_shop`),
INDEX `date_add`(`date_add`)
) ENGINE=ENGINE_TYPE DEFAULT CHARSET=utf8;
@@ -1119,7 +1119,7 @@ CREATE TABLE `PREFIX_page_type` (
CREATE TABLE `PREFIX_page_viewed` (
`id_page` int(10) unsigned NOT NULL,
- `id_group_shop` INT UNSIGNED NOT NULL DEFAULT '1',
+ `id_group_shop` INT UNSIGNED NOT NULL DEFAULT '1',
`id_shop` INT UNSIGNED NOT NULL DEFAULT '1',
`id_date_range` int(10) unsigned NOT NULL,
`counter` int(10) unsigned NOT NULL,
@@ -1637,14 +1637,14 @@ CREATE TABLE `PREFIX_tax_rule` (
`id_tax_rules_group` int(11) NOT NULL,
`id_country` int(11) NOT NULL,
`id_state` int(11) NOT NULL,
- `id_county` int(11) NOT NULL,
+ `zipcode_from` INT NOT NULL,
+ `zipcode_to` INT NOT NULL,
`id_tax` int(11) NOT NULL,
- `state_behavior` int(11) NOT NULL,
- `county_behavior` int(11) NOT NULL,
+ `behavior` int(11) NOT NULL,
+ `description` VARCHAR( 100 ) NOT NULL,
PRIMARY KEY (`id_tax_rule`),
KEY `id_tax_rules_group` (`id_tax_rules_group`),
- KEY `id_tax` (`id_tax`),
- UNIQUE KEY `tax_rule` (`id_tax_rules_group`, `id_country`, `id_state`, `id_county`)
+ KEY `id_tax` (`id_tax`)
) ENGINE=ENGINE_TYPE DEFAULT CHARSET=utf8;
CREATE TABLE `PREFIX_tax_rules_group` (
@@ -1688,23 +1688,6 @@ CREATE TABLE `PREFIX_import_match` (
PRIMARY KEY (`id_import_match`)
) ENGINE=ENGINE_TYPE DEFAULT CHARSET=utf8;
-
-CREATE TABLE `PREFIX_county` (
- `id_county` int(11) NOT NULL AUTO_INCREMENT,
- `name` varchar(64) NOT NULL,
- `id_state` int(11) NOT NULL,
- `active` tinyint(1) NOT NULL,
- PRIMARY KEY (`id_county`)
-) ENGINE=ENGINE_TYPE DEFAULT CHARSET=utf8 ;
-
-
-CREATE TABLE `PREFIX_county_zip_code` (
- `id_county` INT NOT NULL ,
- `from_zip_code` INT NOT NULL ,
- `to_zip_code` INT NOT NULL ,
- PRIMARY KEY ( `id_county` , `from_zip_code` , `to_zip_code` )
-) ENGINE=ENGINE_TYPE DEFAULT CHARSET=utf8;
-
CREATE TABLE `PREFIX_address_format` (
`id_country` int(10) unsigned NOT NULL,
`format` varchar(255) NOT NULL DEFAULT '',
diff --git a/install-dev/sql/db_settings_lite.sql b/install-dev/sql/db_settings_lite.sql
index 00ca26aca..82cef4119 100644
--- a/install-dev/sql/db_settings_lite.sql
+++ b/install-dev/sql/db_settings_lite.sql
@@ -66,7 +66,8 @@ INSERT INTO `PREFIX_hook` (`id_hook`, `name`, `title`, `description`, `position`
(63, 'beforeAuthentication', 'Before Authentication', 'Before authentication', 0, 0),
(64, 'paymentTop', 'Top of payment page', 'Top of payment page', 0, 0),
(65, 'afterCreateHtaccess', 'After htaccess creation', 'After htaccess creation', 0, 0),
-(66, 'afterSaveAdminMeta', 'After save configuration in AdminMeta', 'After save configuration in AdminMeta', 0, 0);
+(66, 'afterSaveAdminMeta', 'After save configuration in AdminMeta', 'After save configuration in AdminMeta', 0, 0),
+(67, 'taxManager', 'Tax Manager Factory', '' , 0, 0);
INSERT INTO `PREFIX_configuration` (`id_configuration`, `name`, `value`, `date_add`, `date_upd`) VALUES
(1, 'PS_LANG_DEFAULT', '1', NOW(), NOW()),
@@ -1180,7 +1181,7 @@ INSERT INTO `PREFIX_address_format` (`id_country`, `format`)
UPDATE `PREFIX_address_format` set `format`='firstname lastname
company
address1 address2
-city, State:name postcode
+city, State:name postcode
Country:name
phone' where `id_country`=21;
@@ -1199,3 +1200,4 @@ postcode city
State:name
Country:name
phone' where `id_country`=10;
+
diff --git a/install-dev/sql/upgrade/1.5.0.1.sql b/install-dev/sql/upgrade/1.5.0.1.sql
index 24603b766..65a786574 100644
--- a/install-dev/sql/upgrade/1.5.0.1.sql
+++ b/install-dev/sql/upgrade/1.5.0.1.sql
@@ -22,4 +22,20 @@ INSERT INTO `PREFIX_module_access` (`id_profile`, `id_module`, `configure`, `vie
AND a.`view` = 1
);
-UPDATE `PREFIX_tab` SET `class_name` = 'AdminThemes' WHERE `class_name` = 'AdminAppearance';
\ No newline at end of file
+UPDATE `PREFIX_tab` SET `class_name` = 'AdminThemes' WHERE `class_name` = 'AdminAppearance';
+
+INSERT INTO `PREFIX_hook` (
+`name` ,
+`title` ,
+`description` ,
+`position` ,
+`live_edit`
+)
+VALUES ('taxmanager', 'taxmanager', NULL , '1', '0');
+
+/* PHP:update_tax_rules(); */;
+
+/* PHP:remove_tab(AdminCounty); */;
+DROP TABLE `PREFIX_county_zip_code`;
+DROP TABLE `PREFIX_county`;
+
diff --git a/install-dev/xml/doUpgrade.php b/install-dev/xml/doUpgrade.php
index dbf90cf7d..812501710 100644
--- a/install-dev/xml/doUpgrade.php
+++ b/install-dev/xml/doUpgrade.php
@@ -30,7 +30,7 @@ $engineType = 'ENGINE_TYPE';
if (function_exists('date_default_timezone_set'))
date_default_timezone_set('Europe/Paris');
-
+
// if _PS_ROOT_DIR_ is defined, use it instead of "guessing" the module dir.
if (defined('_PS_ROOT_DIR_') AND !defined('_PS_MODULE_DIR_'))
define('_PS_MODULE_DIR_', _PS_ROOT_DIR_.'/modules/');
@@ -133,6 +133,10 @@ require_once(_PS_INSTALLER_PHP_UPGRADE_DIR_.'create_multistore.php');
require_once(_PS_INSTALLER_PHP_UPGRADE_DIR_.'add_order_state.php');
+require_once(_PS_INSTALLER_PHP_UPGRADE_DIR_.'update_tax_rules.php');
+
+require_once(_PS_INSTALLER_PHP_UPGRADE_DIR_.'remove_tab.php');
+
//old version detection
global $oldversion, $logger;
$oldversion = false;
@@ -313,9 +317,9 @@ if ($confFile->error != false)
// Settings updated, compile and cache directories must be emptied
$arrayToClean = array(
- INSTALL_PATH.'/../tools/smarty/cache/',
- INSTALL_PATH.'/../tools/smarty/compile/',
- INSTALL_PATH.'/../tools/smarty_v2/cache/',
+ INSTALL_PATH.'/../tools/smarty/cache/',
+ INSTALL_PATH.'/../tools/smarty/compile/',
+ INSTALL_PATH.'/../tools/smarty_v2/cache/',
INSTALL_PATH.'/../tools/smarty_v2/compile/');
foreach ($arrayToClean as $dir)
if (!file_exists($dir))
diff --git a/modules/vatnumber/VATNumberTaxManager.php b/modules/vatnumber/VATNumberTaxManager.php
new file mode 100755
index 000000000..b558b1e16
--- /dev/null
+++ b/modules/vatnumber/VATNumberTaxManager.php
@@ -0,0 +1,43 @@
+
+* @copyright 2007-2011 PrestaShop SA
+* @version Release: $Revision$
+* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
+* International Registered Trademark & Property of PrestaShop SA
+*/
+
+class VATNumberTaxManager implements TaxManagerInterface
+{
+ public static function isAvailableForThisAddress(Address $address)
+ {
+ return (!empty($address->vat_number)
+ AND $address->id_country != Configuration::get('VATNUMBER_COUNTRY')
+ AND Configuration::get('VATNUMBER_MANAGEMENT'));
+ }
+
+ public function getTaxCalculator()
+ {
+ // No tax
+ return new TaxCalculator(array(0));
+ }
+}
+
diff --git a/modules/vatnumber/vatnumber.php b/modules/vatnumber/vatnumber.php
index 260aa586b..f36ab48fb 100755
--- a/modules/vatnumber/vatnumber.php
+++ b/modules/vatnumber/vatnumber.php
@@ -1,6 +1,6 @@
version = 1.0;
$this->author = 'PrestaShop';
$this->need_instance = 0;
-
+
+ $this->tax_manager_class = 'VATNumberTaxManager';
+
parent::__construct();
-
+
$this->displayName = $this->l('European VAT number');
$this->description = $this->l('Enable entering of the VAT intra-community number when creating the address (You must fill in the company field to allow keyboarding VAT number)');
}
-
+
public function install()
{
return (parent::install() AND Configuration::updateValue('VATNUMBER_MANAGEMENT', 1));
}
-
+
public function uninstall()
{
return (parent::uninstall() AND Configuration::updateValue('VATNUMBER_MANAGEMENT', 0));
}
-
+
public function enable($forceAll = false)
{
parent::enable();
Configuration::updateValue('VATNUMBER_MANAGEMENT', 1);
}
-
+
public function disable($forceAll = false)
{
parent::disable();
Configuration::updateValue('VATNUMBER_MANAGEMENT', 0);
}
-
+
public static function getPrefixIntracomVAT()
{
$intracom_array = array(
@@ -95,13 +97,13 @@ class VatNumber extends Module
'SK'=>'SK', //Slovakia
'CZ'=>'CZ', //Czech Republic
'SI'=>'SI', //Slovenia
- 'RO'=>'RO', //Romania
- 'BG'=>'BG' //Bulgaria
+ 'RO'=>'RO', //Romania
+ 'BG'=>'BG' //Bulgaria
);
return $intracom_array;
}
- public static function isApplicable($id_country)
+ public static function isApplicable($id_country)
{
return (((int)$id_country AND in_array(Country::getIsoById($id_country), self::getPrefixIntracomVAT())) ? 1 : 0);
}
@@ -144,7 +146,7 @@ class VatNumber extends Module
public function getContent()
{
$echo = '';
-
+
if (Tools::isSubmit('submitVatNumber'))
{
if (Configuration::updateValue('VATNUMBER_COUNTRY', (int)(Tools::getValue('vatnumber_country'))))
@@ -178,6 +180,4 @@ class VatNumber extends Module
';
return $echo;
}
-}
-
-
+}
\ No newline at end of file