thelia loop with currency - TODO : best price whin in AND max args

This commit is contained in:
Etienne Roudeix
2013-09-10 18:58:21 +02:00
parent affc6805c5
commit 6187dbae22
5 changed files with 167 additions and 73 deletions

View File

@@ -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 <eroudeix@openstudio.fr>
*
* @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);

View File

@@ -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', '');

View File

@@ -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);
}

View File

@@ -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;
}
}

View File

@@ -1,3 +1,8 @@
<html>
<head>
</head>
<body>
Here you are : {navigate to="current"}<br />
From : {navigate to="return_to"}<br />
Index : {navigate to="index"}<br />
@@ -13,7 +18,7 @@ Index : {navigate to="index"}<br />
<h3>#TITLE</h3>
<p>#DESCRIPTION</p>
<p>Starting by #BEST_PRICE  HT (TAX : #BEST_PRICE_TAX ; #BEST_TAXED_PRICE  TTC)</p>
<p>Starting by #BEST_PRICE {currency attr="symbol"} HT (TAX : #BEST_PRICE_TAX ; #BEST_TAXED_PRICE {currency attr="symbol"} TTC)</p>
{ifloop rel="acc"}
<h4>Accessories</h4>
@@ -66,7 +71,7 @@ Index : {navigate to="index"}<br />
#ATTRIBUTE_TITLE = #ATTRIBUTE_AVAILABILITY_TITLE<br />
{/loop}
<br />#WEIGHT g
<br /><strong>{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}</strong>
<br /><strong>{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}</strong>
<br /><br />
Add
<select>
@@ -87,4 +92,8 @@ Index : {navigate to="index"}<br />
{elseloop rel="product"}
<h2>Produit introuvable !</h2>
{/elseloop}
{/elseloop}
</body>
</html>