diff --git a/core/lib/Thelia/Core/Template/Loop/Product.php b/core/lib/Thelia/Core/Template/Loop/Product.php index 22860adbb..2b8aa95fc 100755 --- a/core/lib/Thelia/Core/Template/Loop/Product.php +++ b/core/lib/Thelia/Core/Template/Loop/Product.php @@ -25,6 +25,7 @@ namespace Thelia\Core\Template\Loop; use Propel\Runtime\ActiveQuery\Criteria; use Propel\Runtime\ActiveQuery\Join; +use Propel\Runtime\Exception\PropelException; use Thelia\Core\Template\Element\BaseI18nLoop; use Thelia\Core\Template\Element\LoopResult; use Thelia\Core\Template\Element\LoopResultRow; @@ -35,6 +36,7 @@ use Thelia\Log\Tlog; use Thelia\Model\CategoryQuery; use Thelia\Model\CountryQuery; +use Thelia\Model\CurrencyQuery; use Thelia\Model\Map\FeatureProductTableMap; use Thelia\Model\Map\ProductPriceTableMap; use Thelia\Model\Map\ProductSaleElementsTableMap; @@ -54,8 +56,6 @@ use Thelia\Type\BooleanOrBothType; * Class Product * @package Thelia\Core\Template\Loop * @author Etienne Roudeix - * - * @todo : manage currency in price filter */ class Product extends BaseI18nLoop { @@ -137,6 +137,10 @@ class Product extends BaseI18nLoop */ public function exec(&$pagination) { + $currency = $this->request->getSession()->getCurrency(); + $defaultCurrency = CurrencyQuery::create()->findOneByByDefault(1); + $defaultCurrencySuffix = '_default_currency'; + $search = ProductQuery::create(); /* manage translations */ @@ -144,7 +148,7 @@ class Product extends BaseI18nLoop $attributeNonStrictMatch = $this->getAttribute_non_strict_match(); $isPSELeftJoinList = array(); - $isProductPriceLeftJoinList = array(); + $isProductPriceFirstLeftJoin = array(); $id = $this->getId(); @@ -232,46 +236,6 @@ class Product extends BaseI18nLoop ->where('NOT ISNULL(`is_max_weight`.ID)'); } - $min_price = $this->getMin_price(); - - if(null !== $min_price) { - $isPSELeftJoinList[] = 'is_min_price'; - $isProductPriceLeftJoinList['is_min_price'] = 'min_price_data'; - $minPriceJoin = new Join(); - $minPriceJoin->addExplicitCondition(ProductSaleElementsTableMap::TABLE_NAME, 'ID', 'is_min_price', ProductPriceTableMap::TABLE_NAME, 'PRODUCT_SALE_ELEMENTS_ID', 'min_price_data'); - $minPriceJoin->setJoinType(Criteria::LEFT_JOIN); - - $search->joinProductSaleElements('is_min_price', Criteria::LEFT_JOIN) - ->addJoinObject($minPriceJoin) - ->condition('in_promo', '`is_min_price`.promo'. Criteria::EQUAL .'1') - ->condition('not_in_promo', '`is_min_price`.promo'. Criteria::NOT_EQUAL .'1') - ->condition('min_promo_price', '`min_price_data`.promo_price' . Criteria::GREATER_EQUAL . '?', $min_price, \PDO::PARAM_STR) - ->condition('min_price', '`min_price_data`.price' . Criteria::GREATER_EQUAL . '?', $min_price, \PDO::PARAM_STR) - ->combine(array('in_promo', 'min_promo_price'), Criteria::LOGICAL_AND, 'in_promo_min_price') - ->combine(array('not_in_promo', 'min_price'), Criteria::LOGICAL_AND, 'not_in_promo_min_price') - ->where(array('not_in_promo_min_price', 'in_promo_min_price'), Criteria::LOGICAL_OR); - } - - $max_price = $this->getMax_price(); - - if(null !== $max_price) { - $isPSELeftJoinList[] = 'is_max_price'; - $isProductPriceLeftJoinList['is_max_price'] = 'max_price_data'; - $minPriceJoin = new Join(); - $minPriceJoin->addExplicitCondition(ProductSaleElementsTableMap::TABLE_NAME, 'ID', 'is_max_price', ProductPriceTableMap::TABLE_NAME, 'PRODUCT_SALE_ELEMENTS_ID', 'max_price_data'); - $minPriceJoin->setJoinType(Criteria::LEFT_JOIN); - - $search->joinProductSaleElements('is_max_price', Criteria::LEFT_JOIN) - ->addJoinObject($minPriceJoin) - ->condition('in_promo', '`is_max_price`.promo'. Criteria::EQUAL .'1') - ->condition('not_in_promo', '`is_max_price`.promo'. Criteria::NOT_EQUAL .'1') - ->condition('min_promo_price', '`max_price_data`.promo_price' . Criteria::LESS_EQUAL . '?', $max_price, \PDO::PARAM_STR) - ->condition('max_price', '`max_price_data`.price' . Criteria::LESS_EQUAL . '?', $max_price, \PDO::PARAM_STR) - ->combine(array('in_promo', 'min_promo_price'), Criteria::LOGICAL_AND, 'in_promo_max_price') - ->combine(array('not_in_promo', 'max_price'), Criteria::LOGICAL_AND, 'not_in_promo_max_price') - ->where(array('not_in_promo_max_price', 'in_promo_max_price'), Criteria::LOGICAL_OR); - } - if( $attributeNonStrictMatch != '*' ) { if($attributeNonStrictMatch == 'none') { $actuallyUsedAttributeNonStrictMatchList = $isPSELeftJoinList; @@ -286,13 +250,92 @@ class Product extends BaseI18nLoop } } + $min_price = $this->getMin_price(); + + if(null !== $min_price) { + $isPSELeftJoinList[] = 'is_min_price'; + $isProductPriceFirstLeftJoin = array('is_min_price', 'min_price_data'); + + $minPriceJoin = new Join(); + $minPriceJoin->addExplicitCondition(ProductSaleElementsTableMap::TABLE_NAME, 'ID', 'is_min_price', ProductPriceTableMap::TABLE_NAME, 'PRODUCT_SALE_ELEMENTS_ID', 'min_price_data'); + $minPriceJoin->setJoinType(Criteria::LEFT_JOIN); + + $search->joinProductSaleElements('is_min_price', Criteria::LEFT_JOIN) + ->addJoinObject($minPriceJoin, 'is_min_price_join') + ->addJoinCondition('is_min_price_join', '`min_price_data`.`currency_id` = ?', $currency->getId(), null, \PDO::PARAM_INT); + + if($defaultCurrency->getId() != $currency->getId()) { + $minPriceJoinDefaultCurrency = new Join(); + $minPriceJoinDefaultCurrency->addExplicitCondition(ProductSaleElementsTableMap::TABLE_NAME, 'ID', 'is_min_price', ProductPriceTableMap::TABLE_NAME, 'PRODUCT_SALE_ELEMENTS_ID', 'min_price_data' . $defaultCurrencySuffix); + $minPriceJoinDefaultCurrency->setJoinType(Criteria::LEFT_JOIN); + + $search->addJoinObject($minPriceJoinDefaultCurrency, 'is_min_price_join' . $defaultCurrencySuffix) + ->addJoinCondition('is_min_price_join' . $defaultCurrencySuffix, '`min_price_data' . $defaultCurrencySuffix . '`.`currency_id` = ?', $defaultCurrency->getId(), null, \PDO::PARAM_INT); + + $MinPriceToCompareAsSQL = 'CASE WHEN `is_min_price`.PROMO=1 THEN `min_price_data' . $defaultCurrencySuffix . '`.PROMO_PRICE ELSE `min_price_data' . $defaultCurrencySuffix . '`.PRICE END'; + /** + * In propel we trust : $currency->getRate() always returns a float. + * Or maybe not : rate value is checked as a float in overloaded getRate method. + */ + $MinPriceToCompareAsSQL = 'CASE WHEN ISNULL(CASE WHEN `is_min_price`.PROMO=1 THEN `min_price_data`.PROMO_PRICE ELSE `min_price_data`.PRICE END) THEN + CASE WHEN `is_min_price`.PROMO=1 THEN `min_price_data' . $defaultCurrencySuffix . '`.PROMO_PRICE ELSE `min_price_data' . $defaultCurrencySuffix . '`.PRICE END * ' . $currency->getRate() . ' + ELSE + CASE WHEN `is_min_price`.PROMO=1 THEN `min_price_data`.PROMO_PRICE ELSE `min_price_data`.PRICE END + END'; + } else { + $MinPriceToCompareAsSQL = 'CASE WHEN `is_min_price`.PROMO=1 THEN `min_price_data`.PROMO_PRICE ELSE `min_price_data`.PRICE END'; + } + + $search->where('ROUND(' . $MinPriceToCompareAsSQL . ', 2)>=?', $min_price, \PDO::PARAM_STR); + } + + $max_price = $this->getMax_price(); + + if(null !== $max_price) { + $isPSELeftJoinList[] = 'is_max_price'; + $isProductPriceFirstLeftJoin = array('is_max_price', 'max_price_data'); + + $maxPriceJoin = new Join(); + $maxPriceJoin->addExplicitCondition(ProductSaleElementsTableMap::TABLE_NAME, 'ID', 'is_max_price', ProductPriceTableMap::TABLE_NAME, 'PRODUCT_SALE_ELEMENTS_ID', 'max_price_data'); + $maxPriceJoin->setJoinType(Criteria::LEFT_JOIN); + + $search->joinProductSaleElements('is_max_price', Criteria::LEFT_JOIN) + ->addJoinObject($maxPriceJoin, 'is_max_price_join') + ->addJoinCondition('is_max_price_join', '`max_price_data`.`currency_id` = ?', $currency->getId(), null, \PDO::PARAM_INT); + + if($defaultCurrency->getId() != $currency->getId()) { + $maxPriceJoinDefaultCurrency = new Join(); + $maxPriceJoinDefaultCurrency->addExplicitCondition(ProductSaleElementsTableMap::TABLE_NAME, 'ID', 'is_max_price', ProductPriceTableMap::TABLE_NAME, 'PRODUCT_SALE_ELEMENTS_ID', 'max_price_data' . $defaultCurrencySuffix); + $maxPriceJoinDefaultCurrency->setJoinType(Criteria::LEFT_JOIN); + + $search->addJoinObject($maxPriceJoinDefaultCurrency, 'is_max_price_join' . $defaultCurrencySuffix) + ->addJoinCondition('is_max_price_join' . $defaultCurrencySuffix, '`max_price_data' . $defaultCurrencySuffix . '`.`currency_id` = ?', $defaultCurrency->getId(), null, \PDO::PARAM_INT); + + /** + * In propel we trust : $currency->getRate() always returns a float. + * Or maybe not : rate value is checked as a float in overloaded getRate method. + */ + $MaxPriceToCompareAsSQL = 'CASE WHEN ISNULL(CASE WHEN `is_max_price`.PROMO=1 THEN `max_price_data`.PROMO_PRICE ELSE `max_price_data`.PRICE END) THEN + CASE WHEN `is_max_price`.PROMO=1 THEN `max_price_data' . $defaultCurrencySuffix . '`.PROMO_PRICE ELSE `max_price_data' . $defaultCurrencySuffix . '`.PRICE END * ' . $currency->getRate() . ' + ELSE + CASE WHEN `is_max_price`.PROMO=1 THEN `max_price_data`.PROMO_PRICE ELSE `max_price_data`.PRICE END + END'; + + } else { + $MaxPriceToCompareAsSQL = 'CASE WHEN `is_max_price`.PROMO=1 THEN `max_price_data`.PROMO_PRICE ELSE `max_price_data`.PRICE END'; + } + + $search->where('ROUND(' . $MaxPriceToCompareAsSQL . ', 2)<=?', $max_price, \PDO::PARAM_STR); + } + /* * for ordering and outputs, the product will be : * - new if at least one the criteria matching PSE is new * - in promo if at least one the criteria matching PSE is in promo */ - if(count($isProductPriceLeftJoinList) == 0) { + /* if we don't have any join yet, let's make a global one */ + if(empty($isProductPriceFirstLeftJoin)) { if(count($isPSELeftJoinList) == 0) { $joiningTable = "global"; $isPSELeftJoinList[] = $joiningTable; @@ -301,15 +344,22 @@ class Product extends BaseI18nLoop $joiningTable = $isPSELeftJoinList[0]; } - $isProductPriceLeftJoinList[$joiningTable] = 'global_price_data'; + $isProductPriceFirstLeftJoin = array($joiningTable, 'global_price_data'); - $minPriceJoin = new Join(); - $minPriceJoin->addExplicitCondition(ProductSaleElementsTableMap::TABLE_NAME, 'ID', $joiningTable, ProductPriceTableMap::TABLE_NAME, 'PRODUCT_SALE_ELEMENTS_ID', 'global_price_data'); - $minPriceJoin->setJoinType(Criteria::LEFT_JOIN); + $globalPriceJoin = new Join(); + $globalPriceJoin->addExplicitCondition(ProductSaleElementsTableMap::TABLE_NAME, 'ID', $joiningTable, ProductPriceTableMap::TABLE_NAME, 'PRODUCT_SALE_ELEMENTS_ID', 'global_price_data'); + $globalPriceJoin->setJoinType(Criteria::LEFT_JOIN); - $currency = $this->request->getSession()->getCurrency(); - $search->addJoinObject($minPriceJoin, 'min_price_join') - ->addJoinCondition('min_price_join', '`global_price_data`.`currency_id` = ?', $currency, null, \PDO::PARAM_INT); + $search->addJoinObject($globalPriceJoin, 'global_price_join') + ->addJoinCondition('global_price_join', '`global_price_data`.`currency_id` = ?', $currency->getId(), null, \PDO::PARAM_INT); + + if($defaultCurrency->getId() != $currency->getId()) { + $globalPriceJoinDefaultCurrency = new Join(); + $globalPriceJoinDefaultCurrency->addExplicitCondition(ProductSaleElementsTableMap::TABLE_NAME, 'ID', $joiningTable, ProductPriceTableMap::TABLE_NAME, 'PRODUCT_SALE_ELEMENTS_ID', 'global_price_data' . $defaultCurrencySuffix); + $globalPriceJoinDefaultCurrency->setJoinType(Criteria::LEFT_JOIN); + $search->addJoinObject($globalPriceJoinDefaultCurrency, 'global_price_join' . $defaultCurrencySuffix) + ->addJoinCondition('global_price_join' . $defaultCurrencySuffix, '`global_price_data' . $defaultCurrencySuffix . '`.`currency_id` = ?', $defaultCurrency->getId(), null, \PDO::PARAM_INT); + } } /* @@ -332,18 +382,24 @@ class Product extends BaseI18nLoop $booleanMatchedPromoList[] = '`' . $isPSELeftJoin . '`.PROMO'; $booleanMatchedNewnessList[] = '`' . $isPSELeftJoin . '`.NEWNESS'; } - $booleanMatchedPriceList = array(); - foreach($isProductPriceLeftJoinList as $pSE => $isProductPriceLeftJoin) { - $booleanMatchedPriceList[] = 'CASE WHEN `' . $pSE . '`.PROMO=1 THEN `' . $isProductPriceLeftJoin . '`.PROMO_PRICE ELSE `' . $isProductPriceLeftJoin . '`.PRICE END'; - } $search->withColumn('ROUND(MAX(' . implode(' OR ', $booleanMatchedPromoList) . '), 2)', 'main_product_is_promo'); $search->withColumn('ROUND(MAX(' . implode(' OR ', $booleanMatchedNewnessList) . '), 2)', 'main_product_is_new'); - $search->withColumn('ROUND(MAX(' . implode(' OR ', $booleanMatchedPriceList) . '), 2)', 'real_highest_price'); - $search->withColumn('ROUND(MIN(' . implode(' OR ', $booleanMatchedPriceList) . '), 2)', 'real_lowest_price'); - $search->withColumn('ROUND(MAX(' . implode(' OR ', $booleanMatchedPriceList) . '), 2)', 'real_highest_price_default_currency'); - $search->withColumn('ROUND(MIN(' . implode(' OR ', $booleanMatchedPriceList) . '), 2)', 'real_lowest_price_default_currency'); + $booleanMatchedPrice = 'CASE WHEN `' . $isProductPriceFirstLeftJoin[0] . '`.PROMO=1 THEN `' . $isProductPriceFirstLeftJoin[1] . '`.PROMO_PRICE ELSE `' . $isProductPriceFirstLeftJoin[1] . '`.PRICE END'; + $booleanMatchedPriceDefaultCurrency = 'CASE WHEN `' . $isProductPriceFirstLeftJoin[0] . '`.PROMO=1 THEN `' . $isProductPriceFirstLeftJoin[1] . $defaultCurrencySuffix . '`.PROMO_PRICE ELSE `' . $isProductPriceFirstLeftJoin[1] . $defaultCurrencySuffix . '`.PRICE END'; + if($defaultCurrency->getId() != $currency->getId()) { + /** + * In propel we trust : $currency->getRate() always returns a float. + * Or maybe not : rate value is checked as a float in overloaded getRate method. + */ + $priceToCompareAsSQL = 'CASE WHEN ISNULL(' . $booleanMatchedPrice .') THEN ' . $booleanMatchedPriceDefaultCurrency . ' * ' . $currency->getRate() . ' ELSE ' . $booleanMatchedPrice . ' END'; + } else { + $priceToCompareAsSQL = $booleanMatchedPrice; + } + + $search->withColumn('ROUND(MAX(' . $priceToCompareAsSQL . '), 2)', 'real_highest_price'); + $search->withColumn('ROUND(MIN(' . $priceToCompareAsSQL . '), 2)', 'real_lowest_price'); $current = $this->getCurrent(); @@ -507,8 +563,6 @@ class Product extends BaseI18nLoop } } - var_dump($search->toString()); - /* perform search */ $products = $this->search($search, $pagination); diff --git a/core/lib/Thelia/Core/Template/Loop/ProductSaleElements.php b/core/lib/Thelia/Core/Template/Loop/ProductSaleElements.php index ec4c73230..38d4d2e94 100755 --- a/core/lib/Thelia/Core/Template/Loop/ProductSaleElements.php +++ b/core/lib/Thelia/Core/Template/Loop/ProductSaleElements.php @@ -36,6 +36,7 @@ use Thelia\Log\Tlog; use Thelia\Model\Base\ProductSaleElementsQuery; use Thelia\Model\ConfigQuery; use Thelia\Model\CountryQuery; +use Thelia\Model\CurrencyQuery; use Thelia\Type\TypeCollection; use Thelia\Type; @@ -94,22 +95,37 @@ class ProductSaleElements extends BaseLoop foreach($orders as $order) { switch ($order) { - case "alpha": - //$search->addAscendingOrderByColumn(\Thelia\Model\Map\AttributeI18nTableMap::TITLE); + case "min_price": + $search->addAscendingOrderByColumn('real_lowest_price', Criteria::ASC); break; - case "alpha_reverse": - //$search->addDescendingOrderByColumn(\Thelia\Model\Map\AttributeI18nTableMap::TITLE); + case "max_price": + $search->addDescendingOrderByColumn('real_lowest_price'); break; - case "attribute": - //$search->orderByPosition(Criteria::ASC); + case "promo": + $search->addDescendingOrderByColumn('main_product_is_promo'); break; - case "attribute_reverse": - //$search->orderByPosition(Criteria::DESC); + case "new": + $search->addDescendingOrderByColumn('main_product_is_new'); break; + case "random": + $search->clearOrderByColumns(); + $search->addAscendingOrderByColumn('RAND()'); + break(2); } } - $currency = $this->getCurrency(); + $currencyId = $this->getCurrency(); + if(null !== $currency) { + $currency = CurrencyQuery::create()->findOneById($currencyId); + if(null === $currency) { + throw new \InvalidArgumentException('Cannot found currency id: `' . $currency . '` in product_sale_elements loop'); + } + } else { + $currency = $this->request->getSession()->getCurrency(); + } + + $defaultCurrency = CurrencyQuery::create()->findOneByByDefault(1); + $defaultCurrencySuffix = '_default_currency'; $search->joinProductPrice('price', Criteria::INNER_JOIN); //->addJoinCondition('price', ''); diff --git a/core/lib/Thelia/Core/Thelia.php b/core/lib/Thelia/Core/Thelia.php index e5148e408..8920126b0 100755 --- a/core/lib/Thelia/Core/Thelia.php +++ b/core/lib/Thelia/Core/Thelia.php @@ -83,6 +83,7 @@ class Thelia extends Kernel $serviceContainer->setConnectionManager('thelia', $manager); if ($this->isDebug()) { + $serviceContainer->setLogger('defaultLogger', Tlog::getInstance()); $con = Propel::getConnection(\Thelia\Model\Map\ProductTableMap::DATABASE_NAME); $con->useDebug(true); } diff --git a/core/lib/Thelia/Model/Currency.php b/core/lib/Thelia/Model/Currency.php index 843211d5a..fb59022b8 100755 --- a/core/lib/Thelia/Model/Currency.php +++ b/core/lib/Thelia/Model/Currency.php @@ -80,4 +80,18 @@ class Currency extends BaseCurrency { { $this->dispatchEvent(TheliaEvents::AFTER_DELETECURRENCY, new CurrencyEvent($this)); } + + /** + * Get the [rate] column value. + * + * @return double + */ + public function getRate() + { + if(false === filter_var($this->rate, FILTER_VALIDATE_FLOAT)) { + throw new PropelException('Currency::rate is not float value'); + } + + return $this->rate; + } } \ No newline at end of file diff --git a/templates/default_save/product.html b/templates/default_save/product.html index 4280fc88c..c3e68fd71 100755 --- a/templates/default_save/product.html +++ b/templates/default_save/product.html @@ -1,3 +1,8 @@ + + + + + Here you are : {navigate to="current"}
From : {navigate to="return_to"}
Index : {navigate to="index"}
@@ -13,7 +18,7 @@ Index : {navigate to="index"}

#TITLE

#DESCRIPTION

-

Starting by #BEST_PRICE € HT (TAX : #BEST_PRICE_TAX ; #BEST_TAXED_PRICE € TTC)

+

Starting by #BEST_PRICE {currency attr="symbol"} HT (TAX : #BEST_PRICE_TAX ; #BEST_TAXED_PRICE {currency attr="symbol"} TTC)

{ifloop rel="acc"}

Accessories

@@ -66,7 +71,7 @@ Index : {navigate to="index"}
#ATTRIBUTE_TITLE = #ATTRIBUTE_AVAILABILITY_TITLE
{/loop}
#WEIGHT g -
{if #IS_PROMO == 1} #PROMO_PRICE € HT // TAX : #PROMO_PRICE_TAX ; #TAXED_PROMO_PRICE € TTC (instead of #PRICE HT // TAX : #PRICE_TAX ; #TAXED_PRICE € TTC){else} #PRICE € HT // TAX : #PRICE_TAX ; #TAXED_PRICE € TTC{/if} +
{if #IS_PROMO == 1} #PROMO_PRICE {currency attr="symbol"} HT // TAX : #PROMO_PRICE_TAX ; #TAXED_PROMO_PRICE {currency attr="symbol"} TTC (instead of #PRICE HT // TAX : #PRICE_TAX ; #TAXED_PRICE {currency attr="symbol"} TTC){else} #PRICE {currency attr="symbol"} HT // TAX : #PRICE_TAX ; #TAXED_PRICE {currency attr="symbol"} TTC{/if}

Add