* @copyright PrestaShop * @license http://www.opensource.org/licenses/osl-3.0.php Open-source licence 3.0 * @version 1.3 * */ class Tax extends ObjectModel { /** @var string Name */ public $name; /** @var float Rate (%) */ public $rate; protected $fieldsRequired = array('rate'); protected $fieldsValidate = array('rate' => 'isFloat'); protected $fieldsRequiredLang = array('name'); protected $fieldsSizeLang = array('name' => 32); protected $fieldsValidateLang = array('name' => 'isGenericName'); protected $table = 'tax'; protected $identifier = 'id_tax'; public $noZeroObject = 'getTaxes'; public function getFields() { parent::validateFields(); $fields['rate'] = floatval($this->rate); return $fields; } /** @var array Tax zones cache */ private static $_TAX_ZONES; /** * Check then return multilingual fields for database interaction * * @return array Multilingual fields */ public function getTranslationsFieldsChild() { parent::validateFieldsLang(); return parent::getTranslationsFields(array('name')); } public function delete() { if (!Db::getInstance()->Execute('DELETE FROM `'._DB_PREFIX_.'tax_state` WHERE `id_tax` = '.intval($this->id))) return false; return parent::delete(); } public static function checkTaxZone($id_tax, $id_zone) { return isset(self::$_TAX_ZONES[intval($id_zone)][intval($id_tax)]); } public function getStates() { return Db::getInstance()->ExecuteS('SELECT `id_state`, `id_tax` FROM `'._DB_PREFIX_.'tax_state` WHERE `id_tax` = '.intval($this->id)); } public function getState($id_state) { return Db::getInstance()->getRow('SELECT `id_state` FROM `'._DB_PREFIX_.'tax_state` WHERE `id_tax` = '.intval($this->id).' AND `id_state` = '.intval($id_state)); } public function addState($id_state) { return Db::getInstance()->Execute('INSERT INTO `'._DB_PREFIX_.'tax_state` (`id_tax`, `id_state`) VALUES ('.intval($this->id).', '.intval($id_state).')'); } public function deleteState($id_state) { return Db::getInstance()->Execute('DELETE FROM `'._DB_PREFIX_.'tax_state` WHERE `id_tax` = '.intval($this->id).' AND `id_state` = '.intval($id_state)); } /** * Get all zones * * @return array Zones */ public function getZones() { return Db::getInstance()->ExecuteS(' SELECT * FROM `'._DB_PREFIX_.'tax_zone` WHERE `id_tax` = '.intval($this->id)); } /** * Get a specific zones * * @return array Zone */ public function getZone($id_zone) { return Db::getInstance()->ExecuteS(' SELECT * FROM `'._DB_PREFIX_.'tax_zone` WHERE `id_tax` = '.intval($this->id).' AND `id_zone` = '.intval($id_zone)); } /** * Add zone */ public function addZone($id_zone) { return Db::getInstance()->ExecuteS(' INSERT INTO `'._DB_PREFIX_.'tax_zone` (`id_tax` , `id_zone`) VALUES ('.intval($this->id).', '.intval($id_zone).')'); } /** * Delete zone */ public function deleteZone($id_zone) { return Db::getInstance()->ExecuteS(' DELETE FROM `'._DB_PREFIX_.'tax_zone` WHERE `id_tax` = '.intval($this->id).' AND `id_zone` = '.intval($id_zone).' LIMIT 1'); } /** * Get all available taxes * * @return array Taxes */ static public function getTaxes($id_lang = false) { return Db::getInstance()->ExecuteS(' SELECT t.id_tax, t.rate'.(intval($id_lang) ? ', tl.name, tl.id_lang ' : '').' FROM `'._DB_PREFIX_.'tax` t '.(intval($id_lang) ? 'LEFT JOIN `'._DB_PREFIX_.'tax_lang` tl ON (t.`id_tax` = tl.`id_tax` AND tl.`id_lang` = '.intval($id_lang).') ORDER BY `name` ASC' : '')); } static public function excludeTaxeOption() { return !Configuration::get('PS_TAX'); } static public function zoneHasTax($id_tax, $id_zone) { return Tax::checkTaxZone(intval($id_tax), intval($id_zone)); } static public function getRateByState($id_state) { $tax = Db::getInstance()->getRow(' SELECT ts.`id_tax`, t.`rate` FROM `'._DB_PREFIX_.'tax_state` ts LEFT JOIN `'._DB_PREFIX_.'tax` t ON (t.`id_tax` = ts.`id_tax`) WHERE `id_state` = '.intval($id_state)); return $tax ? floatval($tax['rate']) : false; } static public function getApplicableTax($id_tax, $productTax, $id_address_delivery = NULL) { global $cart, $cookie, $defaultCountry; if (!is_object($cart)) die(Tools::displayError()); if (!$id_address_delivery) $id_address_delivery = $cart->id_address_delivery; /* If customer has an address (implies that he is registered and logged) */ if ($id_address_delivery AND $address_ids = Address::getCountryAndState($id_address_delivery)) { $id_zone_country = Country::getIdZone(intval($address_ids['id_country'])); /* If customer's invoice address is inside a state */ if ($address_ids['id_state']) { $state = new State(intval($address_ids['id_state'])); if (!Validate::isLoadedObject($state)) die(Tools::displayError()); /* Return tax value depending to the tax behavior */ $tax_behavior = intval($state->tax_behavior); if ($tax_behavior == PS_PRODUCT_TAX) return $productTax * Tax::zoneHasTax(intval($id_tax), intval($id_zone_country)); if ($tax_behavior == PS_STATE_TAX) return Tax::getRateByState(intval($address_ids['id_state'])); if ($tax_behavior == PS_BOTH_TAX) return ($productTax * Tax::zoneHasTax(intval($id_tax), intval($id_zone_country))) + Tax::getRateByState(intval($address_ids['id_state'])); /* Unknown behavior */ die(Tools::displayError('Unknown tax behavior!')); } /* Else getting country zone tax */ if (!$id_zone = Address::getZoneById($id_address_delivery)) die(Tools::displayError()); return $productTax * Tax::zoneHasTax(intval($id_tax), intval($id_zone)); } /* Default tax application */ if (!Validate::isLoadedObject($defaultCountry)) die(Tools::displayError()); return $productTax * Tax::zoneHasTax(intval($id_tax), intval($defaultCountry->id_zone)); } /** * Load all tax/zones relations in memory for caching */ static public function loadTaxZones() { self::$_TAX_ZONES = array(); $result = Db::getInstance()->ExecuteS('SELECT `id_tax`, `id_zone` FROM `'._DB_PREFIX_.'tax_zone`'); if ($result === false) die(Tools::displayError('Invalid loadTaxZones() SQL query!')); foreach ($result AS $row) self::$_TAX_ZONES[intval($row['id_zone'])][intval($row['id_tax'])] = true; } static public function getTaxIdByRate($rate) { $tax = Db::getInstance()->getRow(' SELECT `id_tax` FROM `'._DB_PREFIX_.'tax` WHERE `rate` = '.floatval($rate)); return $tax ? intval($tax['id_tax']) : false; } }