Example #1
0
 /**
  * Return the product tax rate
  *
  * @param integer $id_product
  * @param integer $id_address
  * @return Tax
  */
 public static function getProductTaxRate($id_product, $id_address = null)
 {
     $id_country = (int) Country::getDefaultCountryId();
     $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']) && $address_infos['id_country'] != Configuration::get('VATNUMBER_COUNTRY') && Configuration::get('VATNUMBER_MANAGEMENT')) {
             return 0;
         }
     }
     return Tax::getProductTaxRateViaRules((int) $id_product, (int) $id_country, (int) $id_state, (int) $id_county);
 }
Example #2
0
    /**
     * Price calculation / Get product price
     *
     * @param integer $id_shop Shop id
     * @param integer $id_product Product id
     * @param integer $id_product_attribute Product attribute id
     * @param integer $id_country Country id
     * @param integer $id_state State id
     * @param integer $id_currency Currency id
     * @param integer $id_group Group id
     * @param integer $quantity Quantity Required for Specific prices : quantity discount application
     * @param boolean $use_tax with (1) or without (0) tax
     * @param integer $decimals Number of decimals returned
     * @param boolean $only_reduc Returns only the reduction amount
     * @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)
    {
        // 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;
        // reference parameter is filled before any returns
        $specific_price = SpecificPrice::getSpecificPrice((int) $id_product, $id_shop, $id_currency, $id_country, $id_group, $quantity);
        if (isset(self::$_prices[$cacheId])) {
            return self::$_prices[$cacheId];
        }
        // fetch price & attribute price
        $cacheId2 = $id_product . '-' . $id_product_attribute;
        if (!isset(self::$_pricesLevel2[$cacheId2])) {
            self::$_pricesLevel2[$cacheId2] = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow('
			SELECT p.`price`,
			' . ($id_product_attribute ? 'pa.`price`' : 'IFNULL((SELECT pa.price FROM `' . _DB_PREFIX_ . 'product_attribute` pa WHERE id_product = ' . (int) $id_product . ' AND default_on = 1), 0)') . ' AS attribute_price,
			p.`ecotax`
			' . ($id_product_attribute ? ', pa.`ecotax` AS attribute_ecotax' : '') . '
			FROM `' . _DB_PREFIX_ . 'product` p
			' . ($id_product_attribute ? 'LEFT JOIN `' . _DB_PREFIX_ . 'product_attribute` pa ON pa.`id_product_attribute` = ' . (int) $id_product_attribute : '') . '
			WHERE p.`id_product` = ' . (int) $id_product);
        }
        $result = self::$_pricesLevel2[$cacheId2];
        $price = (double) (!$specific_price or $specific_price['price'] == 0) ? $result['price'] : $specific_price['price'];
        // convert only if the specific price is in the default currency (id_currency = 0)
        if (!$specific_price or !($specific_price['price'] > 0 and $specific_price['id_currency'])) {
            $price = Tools::convertPrice($price, $id_currency);
        }
        // Attribute price
        $attribute_price = Tools::convertPrice(array_key_exists('attribute_price', $result) ? (double) $result['attribute_price'] : 0, $id_currency);
        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;
        }
        // Add Tax
        if ($use_tax) {
            $price = $price * (1 + $tax_rate / 100);
        }
        $price = Tools::ps_round($price, $decimals);
        // Reduction
        $reduc = 0;
        if (($only_reduc or $use_reduc) and $specific_price) {
            if ($specific_price['reduction_type'] == 'amount') {
                $reduction_amount = $specific_price['reduction'];
                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);
            } else {
                $reduc = Tools::ps_round($price * $specific_price['reduction'], $decimals);
            }
        }
        if ($only_reduc) {
            return $reduc;
        }
        if ($use_reduc) {
            $price -= $reduc;
        }
        // Group reduction
        if ($use_groupReduction) {
            if ($reductionFromCategory = (double) GroupReduction::getValueForProduct($id_product, $id_group)) {
                $price -= $price * $reductionFromCategory;
            } else {
                // apply group reduction if there is no group reduction for this category
                $price *= (100 - Group::getReductionByIdGroup($id_group)) / 100;
            }
        }
        $price = Tools::ps_round($price, $decimals);
        // Eco Tax
        if (($result['ecotax'] or isset($result['attribute_ecotax'])) and $with_ecotax) {
            $ecotax = $result['ecotax'];
            if (isset($result['attribute_ecotax']) && $result['attribute_ecotax'] > 0) {
                $ecotax = $result['attribute_ecotax'];
            }
            if ($id_currency) {
                $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);
            } else {
                $price += $ecotax;
            }
        }
        $price = Tools::ps_round($price, $decimals);
        if ($price < 0) {
            $price = 0;
        }
        self::$_prices[$cacheId] = $price;
        return self::$_prices[$cacheId];
    }
Example #3
0
    public static function getPriceRangeForSearchBloc($search, $id_criterion_group, $id_currency, $id_country, $id_group, $count_product = false, $selected_criterion = array(), $selected_criteria_groups_type = array())
    {
        global $cookie;
        if (!$id_country) {
            $id_country = (int) (version_compare(_PS_VERSION_, '1.5.0.0', '>=') ? Context::getContext()->country->id : Country::getDefaultCountryId());
        }
        $search['display_empty_criteria'] = false;
        $leftJoinWhereCriterion = self::makeLeftJoinWhereCriterion('getPriceRangeForSearchBloc', $search, $cookie->id_lang, $selected_criterion, $selected_criteria_groups_type, $id_criterion_group, false, $id_currency, $id_country, $id_group, true, true);
        $now = date('Y-m-d H:i:s');
        $minIdProduct = self::getMinIdProductSlider($search, $id_criterion_group, $id_currency, $id_country, $id_group, $count_product, $selected_criterion, $selected_criteria_groups_type);
        list($taxConversion, $taxConversionForReduction, $specificPriceCondition, $specificPriceGroupCondition) = self::getPriceRangeConditions($id_group);
        if ($leftJoinWhereCriterion['nbSelectedCriterions'] > 0 && ($leftJoinWhereCriterion['priceIncluded'] || $leftJoinWhereCriterion['productTableIncluded'])) {
            $specificPriceCondition .= $specificPriceGroupCondition;
        }
        $return = array();
        $query_min = 'SELECT app.price_wt as min_price, app.`reduction_amount`, app.`reduction_type`, app.`reduction_tax`, app.id_currency, acp.id_product, app.id_country, ' . self::_getScoreQuery(version_compare(_PS_VERSION_, '1.5.0.0', '>=') ? Context::getContext()->shop->id : 0, $id_currency, $id_country, $id_group, true, true) . '
		FROM `' . _DB_PREFIX_ . 'pm_advancedsearch_product_price_' . (int) $search['id_search'] . '` app
		LEFT JOIN `' . _DB_PREFIX_ . 'pm_advancedsearch_cache_product_' . (int) $search['id_search'] . '` acp ON (app.`id_cache_product` = acp.`id_cache_product`)' . (AdvancedSearchCoreClass::_isFilledArray($leftJoinWhereCriterion['join']) ? implode(' ', $leftJoinWhereCriterion['join']) : '') . ' WHERE acp.`id_product` = ' . (int) $minIdProduct . ' AND ' . ' ((app.`from` = \'0000-00-00 00:00:00\' OR \'' . $now . '\' >= app.`from`) AND (app.`to` = \'0000-00-00 00:00:00\' OR \'' . $now . '\' <= app.`to`)) AND ' . ' ((app.`valid_id_specific_price`=1 AND app.`is_specific`=1 AND app.`id_currency` IN (0, ' . (int) $id_currency . ')) OR app.`has_no_specific`=1) AND ' . (AdvancedSearchCoreClass::_isFilledArray($leftJoinWhereCriterion['where']) ? implode(' AND ', $leftJoinWhereCriterion['where']) : ' 1 ') . ' AND app.`id_country` IN (0, ' . (int) $id_country . ') ' . ' AND app.`id_group` IN (0, ' . (int) $id_group . ') ' . (version_compare(_PS_VERSION_, '1.5.0.0', '>=') ? ' AND app.`id_shop` IN (0, ' . implode(', ', Shop::getContextListShopID()) . ') ' : '') . ' ORDER BY score DESC, ' . $specificPriceCondition . ' ASC';
        $row = Db::getInstance()->getRow($query_min);
        if (version_compare(_PS_VERSION_, '1.5.0.0', '>=')) {
            $tax_rate = Tax::getProductTaxRate((int) $row['id_product']);
        } else {
            $tax_rate = Tax::getProductTaxRateViaRules((int) $row['id_product'], (int) $id_country, 0, 0);
            if ($tax_rate === false) {
                $tax_rate = 0;
            }
        }
        $reduction_amount = $row['reduction_amount'];
        $reduction_type = $row['reduction_type'];
        $reduction_tax = $row['reduction_tax'];
        if (floor($row['min_price']) == 0) {
            $reduction_amount = 0;
        }
        if (Product::$_taxCalculationMethod != PS_TAX_EXC) {
            if ($reduction_type == 'amount') {
                if (!$reduction_tax) {
                    $reduction_amount = $reduction_amount * (1 + $tax_rate / 100);
                }
                $price_ttc = $row['min_price'] * (1 + $tax_rate / 100) - $reduction_amount;
            } else {
                $price_ttc = ($row['min_price'] - $reduction_amount) * (1 + $tax_rate / 100);
            }
            $return[0]['min_price'] = floor($price_ttc);
        } else {
            if ($reduction_type == 'amount') {
                if ($reduction_tax) {
                    $reduction_amount = $reduction_amount / (1 + $tax_rate / 100);
                }
            }
            $return[0]['min_price'] = floor($row['min_price'] - $reduction_amount);
        }
        $return[0]['min_price_id_currency'] = $row['id_currency'];
        $return[0]['min_price'] = self::getGroupReducedPrice((int) $row['id_product'], $id_group, $return[0]['min_price']);
        $maxIdProduct = self::getMaxIdProductSlider($search, $id_criterion_group, $id_currency, $id_country, $id_group, $count_product, $selected_criterion, $selected_criteria_groups_type);
        $query_max = 'SELECT app.price_wt as max_price, app.`reduction_amount`, app.`reduction_type`, app.`reduction_tax`, acp.id_product, app.id_currency, app.id_country, ' . self::_getScoreQuery(version_compare(_PS_VERSION_, '1.5.0.0', '>=') ? Context::getContext()->shop->id : 0, $id_currency, $id_country, $id_group, true, true) . '
		FROM `' . _DB_PREFIX_ . 'pm_advancedsearch_product_price_' . (int) $search['id_search'] . '` app
		LEFT JOIN `' . _DB_PREFIX_ . 'pm_advancedsearch_cache_product_' . (int) $search['id_search'] . '` acp ON (app.`id_cache_product` = acp.`id_cache_product`)' . (AdvancedSearchCoreClass::_isFilledArray($leftJoinWhereCriterion['join']) ? implode(' ', $leftJoinWhereCriterion['join']) : '') . ' WHERE acp.`id_product` = ' . (int) $maxIdProduct . ' AND ' . ' ((app.`from` = \'0000-00-00 00:00:00\' OR \'' . $now . '\' >= app.`from`) AND (app.`to` = \'0000-00-00 00:00:00\' OR \'' . $now . '\' <= app.`to`)) AND ' . ' ((app.`valid_id_specific_price`=1 AND app.`is_specific`=1 AND app.`id_currency` IN (0, ' . (int) $id_currency . ')) OR app.`has_no_specific`=1) AND ' . (AdvancedSearchCoreClass::_isFilledArray($leftJoinWhereCriterion['where']) ? implode(' AND ', $leftJoinWhereCriterion['where']) : ' 1 ') . ' AND app.`id_country` IN (0, ' . (int) $id_country . ') ' . ' AND app.`id_group` IN (0, ' . (int) $id_group . ') ' . (version_compare(_PS_VERSION_, '1.5.0.0', '>=') ? ' AND app.`id_shop` IN (0, ' . implode(', ', Shop::getContextListShopID()) . ') ' : '') . ' ORDER BY score DESC, ' . $specificPriceCondition . ' DESC';
        $row = Db::getInstance()->getRow($query_max);
        if (version_compare(_PS_VERSION_, '1.5.0.0', '>=')) {
            $tax_rate = Tax::getProductTaxRate((int) $row['id_product']);
        } else {
            $tax_rate = Tax::getProductTaxRateViaRules((int) $row['id_product'], (int) $id_country, 0, 0);
            if ($tax_rate === false) {
                $tax_rate = 0;
            }
        }
        $reduction_amount = $row['reduction_amount'];
        $reduction_type = $row['reduction_type'];
        $reduction_tax = $row['reduction_tax'];
        if (Product::$_taxCalculationMethod != PS_TAX_EXC) {
            if ($reduction_type == 'amount') {
                if (!$reduction_tax) {
                    $reduction_amount = $reduction_amount * (1 + $tax_rate / 100);
                }
                $price_ttc = $row['max_price'] * (1 + $tax_rate / 100) - $reduction_amount;
            } else {
                $price_ttc = ($row['max_price'] - $reduction_amount) * (1 + $tax_rate / 100);
            }
            $return[0]['max_price'] = ceil($price_ttc);
        } else {
            if ($reduction_type == 'amount') {
                if ($reduction_tax) {
                    $reduction_amount = $reduction_amount / (1 + $tax_rate / 100);
                }
            }
            $return[0]['max_price'] = ceil($row['max_price'] - $reduction_amount);
        }
        $return[0]['max_price_id_currency'] = $row['id_currency'];
        $return[0]['max_price'] = self::getGroupReducedPrice((int) $row['id_product'], $id_group, $return[0]['max_price']);
        return $return;
    }