diff --git a/core/lib/Thelia/Action/Order.php b/core/lib/Thelia/Action/Order.php index 532284382..0893a0502 100755 --- a/core/lib/Thelia/Action/Order.php +++ b/core/lib/Thelia/Action/Order.php @@ -32,6 +32,8 @@ use Thelia\Core\Event\Order\OrderEvent; use Thelia\Core\Event\TheliaEvents; use Thelia\Exception\TheliaProcessException; use Thelia\Model\AddressQuery; +use Thelia\Model\ConfigQuery; +use Thelia\Model\MessageQuery; use Thelia\Model\OrderProductAttributeCombination; use Thelia\Model\ModuleQuery; use Thelia\Model\OrderProduct; @@ -291,7 +293,48 @@ class Order extends BaseAction implements EventSubscriberInterface */ public function sendOrderEmail(OrderEvent $event) { - /* @todo */ + $order = $event->getOrder(); + $customer = $order->getCustomer(); + + $parser = $this->container->get("thelia.parser"); + + $parser->assign('order_id', $order->getId()); + $parser->assign('order_ref', $order->getRef()); + + $message = MessageQuery::create() + ->filterByName('order_confirmation') + ->findOne(); + + $message + ->setLocale($order->getLang()->getLocale()); + + $subject = $parser->fetch(sprintf("string:%s", $message->getSubject())); + $htmlMessage = $parser->fetch(sprintf("string:%s", $message->getHtmlMessage())); + $textMessage = $parser->fetch(sprintf("string:%s", $message->getTextMessage())); + + $instance = \Swift_Message::newInstance($subject) + ->addTo($customer->getEmail(), $customer->getFirstname()." ".$customer->getLastname()) + ->addFrom(ConfigQuery::read('contact_email'), ConfigQuery::read('company_name')) + ; + $instance + ->setBody($htmlMessage, 'text/html') + ->addPart($textMessage, 'text/plain'); + + $mail = $this->getMailer()->send($instance); + + } + + /** + * + * return an instance of \Swift_Mailer with good Transporter configured. + * + * @return \Swift_Mailer + */ + public function getMailer() + { + $mailer = $this->container->get('mailer'); + + return $mailer->getSwiftMailer(); } /** diff --git a/core/lib/Thelia/Config/Resources/routing/admin.xml b/core/lib/Thelia/Config/Resources/routing/admin.xml index a23d99485..afaacb85a 100755 --- a/core/lib/Thelia/Config/Resources/routing/admin.xml +++ b/core/lib/Thelia/Config/Resources/routing/admin.xml @@ -174,7 +174,7 @@ \d+ - + Thelia\Controller\Admin\OrderController::generateDeliveryPdf \d+ diff --git a/core/lib/Thelia/Config/Resources/routing/front.xml b/core/lib/Thelia/Config/Resources/routing/front.xml index 981e8130f..cf7797cc9 100755 --- a/core/lib/Thelia/Config/Resources/routing/front.xml +++ b/core/lib/Thelia/Config/Resources/routing/front.xml @@ -95,6 +95,11 @@ + + Thelia\Controller\Front\DefaultController::noAction + cart + + Thelia\Controller\Front\CartController::addItem diff --git a/core/lib/Thelia/Controller/Admin/CustomerController.php b/core/lib/Thelia/Controller/Admin/CustomerController.php index fd203a066..7f8cd8615 100644 --- a/core/lib/Thelia/Controller/Admin/CustomerController.php +++ b/core/lib/Thelia/Controller/Admin/CustomerController.php @@ -30,7 +30,7 @@ use Thelia\Core\Event\Customer\CustomerCreateOrUpdateEvent; use Thelia\Core\Event\Customer\CustomerEvent; use Thelia\Core\Event\TheliaEvents; use Thelia\Core\Security\AccessManager; -use Thelia\Form\CustomerModification; +use Thelia\Form\CustomerUpdateForm; use Thelia\Form\Exception\FormValidationException; use Thelia\Model\CustomerQuery; use Thelia\Core\Translation\Translator; @@ -68,7 +68,7 @@ class CustomerController extends BaseAdminController $message = false; - $customerModification = new CustomerModification($this->getRequest()); + $customerUpdateForm = new CustomerUpdateForm($this->getRequest()); try { $customer = CustomerQuery::create()->findPk($customer_id); @@ -77,7 +77,7 @@ class CustomerController extends BaseAdminController throw new \InvalidArgumentException(sprintf("%d customer id does not exist", $customer_id)); } - $form = $this->validateForm($customerModification); + $form = $this->validateForm($customerUpdateForm); $event = $this->createEventInstance($form->getData()); $event->setCustomer($customer); @@ -91,7 +91,7 @@ class CustomerController extends BaseAdminController if ($this->getRequest()->get("save_mode") == "close") { $this->redirectToRoute("admin.customers"); } else { - $this->redirectSuccess($customerModification); + $this->redirectSuccess($customerUpdateForm); } } catch (FormValidationException $e) { @@ -105,10 +105,10 @@ class CustomerController extends BaseAdminController if ($message !== false) { \Thelia\Log\Tlog::getInstance()->error(sprintf("Error during customer login process : %s.", $message)); - $customerModification->setErrorMessage($message); + $customerUpdateForm->setErrorMessage($message); $this->getParserContext() - ->addForm($customerModification) + ->addForm($customerUpdateForm) ->setGeneralError($message) ; } diff --git a/core/lib/Thelia/Controller/Admin/MessageController.php b/core/lib/Thelia/Controller/Admin/MessageController.php index c0bce7918..e85e9267d 100644 --- a/core/lib/Thelia/Controller/Admin/MessageController.php +++ b/core/lib/Thelia/Controller/Admin/MessageController.php @@ -45,10 +45,8 @@ class MessageController extends AbstractCrudController null, // no sort order change null, // no sort order change - AdminResources::MESSAGE_VIEW, - AdminResources::MESSAGE_CREATE, - AdminResources::MESSAGE_UPDATE, - AdminResources::MESSAGE_DELETE, + AdminResources::MESSAGE, + TheliaEvents::MESSAGE_CREATE, TheliaEvents::MESSAGE_UPDATE, diff --git a/core/lib/Thelia/Controller/Front/AddressController.php b/core/lib/Thelia/Controller/Front/AddressController.php index 94d0f78d7..6ab6e72e8 100644 --- a/core/lib/Thelia/Controller/Front/AddressController.php +++ b/core/lib/Thelia/Controller/Front/AddressController.php @@ -101,7 +101,7 @@ class AddressController extends BaseFrontController $address = AddressQuery::create()->findPk($address_id); if (!$address || $customer->getId() != $address->getCustomerId()) { - $this->redirectToRoute("home"); + $this->redirectToRoute('default'); } $this->getParserContext()->set("address_id", $address_id); @@ -122,11 +122,11 @@ class AddressController extends BaseFrontController $address = AddressQuery::create()->findPk($address_id); if (null === $address) { - $this->redirectToRoute("home"); + $this->redirectToRoute('default'); } if ($address->getCustomer()->getId() != $customer->getId()) { - $this->redirectToRoute("home"); + $this->redirectToRoute('default'); } $event = $this->createAddressEvent($form); @@ -161,12 +161,12 @@ class AddressController extends BaseFrontController $address = AddressQuery::create()->findPk($address_id); if (!$address || $customer->getId() != $address->getCustomerId()) { - $this->redirectToRoute("home"); + $this->redirectToRoute('default'); } $this->dispatch(TheliaEvents::ADDRESS_DELETE, new AddressEvent($address)); - $this->redirectToRoute("customer.account.view"); + $this->redirectToRoute('default', array('view'=>'account')); } protected function createAddressEvent($form) diff --git a/core/lib/Thelia/Controller/Front/BaseFrontController.php b/core/lib/Thelia/Controller/Front/BaseFrontController.php index fadf65795..5892194a4 100755 --- a/core/lib/Thelia/Controller/Front/BaseFrontController.php +++ b/core/lib/Thelia/Controller/Front/BaseFrontController.php @@ -56,7 +56,7 @@ class BaseFrontController extends BaseController public function checkAuth() { if ($this->getSecurityContext()->hasCustomerUser() === false) { - $this->redirectToRoute("customer.login.view"); + $this->redirectToRoute('default', array('view'=>'login')); } } @@ -64,7 +64,7 @@ class BaseFrontController extends BaseController { $cart = $this->getSession()->getCart(); if ($cart===null || $cart->countCartItems() == 0) { - $this->redirectToRoute("cart.view"); + $this->redirectToRoute('cart.view'); } } diff --git a/core/lib/Thelia/Controller/Front/CustomerController.php b/core/lib/Thelia/Controller/Front/CustomerController.php index 5611675e8..23f2e0f30 100755 --- a/core/lib/Thelia/Controller/Front/CustomerController.php +++ b/core/lib/Thelia/Controller/Front/CustomerController.php @@ -109,7 +109,7 @@ class CustomerController extends BaseFrontController $cart = $this->getCart($this->getRequest()); if ($cart->getCartItems()->count() > 0) { - $this->redirectToRoute("cart.view"); + $this->redirectToRoute('cart.view'); } else { $this->redirectSuccess($customerCreation); } @@ -278,7 +278,7 @@ class CustomerController extends BaseFrontController // If User is a new customer if ($form->get('account')->getData() == 0 && !$form->get("email")->getErrors()) { - $this->redirectToRoute("customer.create.view", array("email" => $form->get("email")->getData())); + $this->redirectToRoute("default", array("view" => "register","email" => $form->get("email")->getData())); } else { try { diff --git a/core/lib/Thelia/Controller/Front/OrderController.php b/core/lib/Thelia/Controller/Front/OrderController.php index 968597b8a..bb0604bd1 100755 --- a/core/lib/Thelia/Controller/Front/OrderController.php +++ b/core/lib/Thelia/Controller/Front/OrderController.php @@ -197,7 +197,7 @@ class OrderController extends BaseFrontController $this->redirect(URL::getInstance()->absoluteUrl($this->getRoute('order.placed', array('order_id' => $orderEvent->getPlacedOrder()->getId())))); } else { /* order has not been placed */ - $this->redirectToRoute("cart.view"); + $this->redirectToRoute('cart.view'); } } diff --git a/core/lib/Thelia/Core/EventListener/ViewListener.php b/core/lib/Thelia/Core/EventListener/ViewListener.php index aefc0cf90..db036f111 100755 --- a/core/lib/Thelia/Core/EventListener/ViewListener.php +++ b/core/lib/Thelia/Core/EventListener/ViewListener.php @@ -84,13 +84,13 @@ class ViewListener implements EventSubscriberInterface $response = new Response($content, $parser->getStatus() ?: 200); } - $response->setCache(array( +/* $response->setCache(array( 'last_modified' => new \DateTime(), 'max_age' => 600, 's_maxage' => 600, 'private' => false, 'public' => true, - )); + ));*/ $event->setResponse($response); } catch (ResourceNotFoundException $e) { diff --git a/core/lib/Thelia/Core/Template/Element/BaseLoop.php b/core/lib/Thelia/Core/Template/Element/BaseLoop.php index 7e803c43a..1ed7292cf 100755 --- a/core/lib/Thelia/Core/Template/Element/BaseLoop.php +++ b/core/lib/Thelia/Core/Template/Element/BaseLoop.php @@ -23,12 +23,18 @@ namespace Thelia\Core\Template\Element; +use Propel\Runtime\ActiveQuery\Criteria; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use Thelia\Core\Template\Element\Exception\SearchLoopException; use Thelia\Core\Template\Loop\Argument\Argument; use Propel\Runtime\ActiveQuery\ModelCriteria; use Thelia\Core\Security\SecurityContext; +use Thelia\Type\AlphaNumStringListType; +use Thelia\Type\EnumListType; +use Thelia\Type\EnumType; +use Thelia\Type\TypeCollection; /** * @@ -84,13 +90,43 @@ abstract class BaseLoop */ protected function getDefaultArgs() { - return array( - Argument::createIntTypeArgument('offset', 0), - Argument::createIntTypeArgument('page'), - Argument::createIntTypeArgument('limit', PHP_INT_MAX), + $defaultArgs = array( Argument::createBooleanTypeArgument('backend_context', false), Argument::createBooleanTypeArgument('force_return', false), ); + + if(true === $this->countable) { + $defaultArgs = array_merge($defaultArgs, array( + Argument::createIntTypeArgument('offset', 0), + Argument::createIntTypeArgument('page'), + Argument::createIntTypeArgument('limit', PHP_INT_MAX), + )); + } + + if($this instanceof SearchLoopInterface) { + $defaultArgs = array_merge($defaultArgs, array( + Argument::createAnyTypeArgument('search_term'), + new Argument( + 'search_in', + new TypeCollection( + new EnumListType($this->getSearchIn()) + ) + ), + new Argument( + 'search_mode', + new TypeCollection( + new EnumType(array( + SearchLoopInterface::MODE_ANY_WORD, + SearchLoopInterface::MODE_SENTENCE, + SearchLoopInterface::MODE_STRICT_SENTENCE, + )) + ), + SearchLoopInterface::MODE_STRICT_SENTENCE + ) + )); + } + + return $defaultArgs; } /** @@ -205,6 +241,30 @@ abstract class BaseLoop */ protected function search(ModelCriteria $search, &$pagination = null) { + if($this instanceof SearchLoopInterface) { + $searchTerm = $this->getSearch_term(); + $searchIn = $this->getSearch_in(); + $searchMode = $this->getSearch_mode(); + if(null !== $searchTerm && null !== $searchIn) { + + switch($searchMode) { + case SearchLoopInterface::MODE_ANY_WORD: + $searchCriteria = Criteria::IN; + $searchTerm = explode(' ', $searchTerm); + break; + case SearchLoopInterface::MODE_SENTENCE: + $searchCriteria = Criteria::LIKE; + $searchTerm = '%' . $searchTerm . '%'; + break; + case SearchLoopInterface::MODE_STRICT_SENTENCE: + $searchCriteria = Criteria::EQUAL; + break; + } + + $this->doSearch($search, $searchTerm, $searchIn, $searchCriteria); + } + } + if ($this->getArgValue('page') !== null) { return $this->searchWithPagination($search, $pagination); } else { diff --git a/core/lib/Thelia/Core/Template/Element/Exception/SearchLoopException.php b/core/lib/Thelia/Core/Template/Element/Exception/SearchLoopException.php new file mode 100644 index 000000000..f1ce6657f --- /dev/null +++ b/core/lib/Thelia/Core/Template/Element/Exception/SearchLoopException.php @@ -0,0 +1,40 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Core\Template\Element\Exception; + +class SearchLoopException extends \RuntimeException +{ + const UNKNOWN_EXCEPTION = 0; + + public function __construct($message, $code = null, $arguments = array(), $previous = null) + { + if (is_array($arguments)) { + $this->arguments = $arguments; + } + if ($code === null) { + $code = self::UNKNOWN_EXCEPTION; + } + parent::__construct($message, $code, $previous); + } +} diff --git a/core/lib/Thelia/Core/Template/Element/SearchLoopInterface.php b/core/lib/Thelia/Core/Template/Element/SearchLoopInterface.php new file mode 100644 index 000000000..48876012f --- /dev/null +++ b/core/lib/Thelia/Core/Template/Element/SearchLoopInterface.php @@ -0,0 +1,44 @@ +. */ +/* */ +/*************************************************************************************/ +namespace Thelia\Core\Template\Element; + +use Symfony\Component\Validator\ExecutionContextInterface; + +/** + * + * @author Etienne Roudeix + * + */ +interface SearchLoopInterface +{ + const MODE_ANY_WORD = 'any_word'; + const MODE_SENTENCE = 'sentence'; + const MODE_STRICT_SENTENCE = 'strict_sentence'; + + /** + * @return array of available field to search in + */ + public function getSearchIn(); + + public function doSearch(&$search, $searchTerm, $searchIn, $searchCriteria); +} diff --git a/core/lib/Thelia/Core/Template/Loop/Customer.php b/core/lib/Thelia/Core/Template/Loop/Customer.php index e811606c0..e49d9ef76 100755 --- a/core/lib/Thelia/Core/Template/Loop/Customer.php +++ b/core/lib/Thelia/Core/Template/Loop/Customer.php @@ -28,6 +28,7 @@ use Thelia\Core\Template\Element\BaseLoop; use Thelia\Core\Template\Element\LoopResult; use Thelia\Core\Template\Element\LoopResultRow; +use Thelia\Core\Template\Element\SearchLoopInterface; use Thelia\Core\Template\Loop\Argument\ArgumentCollection; use Thelia\Core\Template\Loop\Argument\Argument; @@ -44,7 +45,7 @@ use Thelia\Type; * @package Thelia\Core\Template\Loop * @author Etienne Roudeix */ -class Customer extends BaseLoop +class Customer extends BaseLoop implements SearchLoopInterface { public $timestampable = true; @@ -67,6 +68,47 @@ class Customer extends BaseLoop ); } + public function getSearchIn() + { + return array( + "ref", + "firstname", + "lastname", + "email", + ); + } + + /** + * @param CustomerQuery $search + * @param $searchTerm + * @param $searchIn + * @param $searchCriteria + */ + public function doSearch(&$search, $searchTerm, $searchIn, $searchCriteria) + { + + $search->_and(); + foreach($searchIn as $index => $searchInElement) { + if($index > 0) { + $search->_or(); + } + switch($searchInElement) { + case "ref": + $search->filterByRef($searchTerm, $searchCriteria); + break; + case "firstname": + $search->filterByFirstname($searchTerm, $searchCriteria); + break; + case "lastname": + $search->filterByLastname($searchTerm, $searchCriteria); + break; + case "email": + $search->filterByEmail($searchTerm, $searchCriteria); + break; + } + } + } + /** * @param $pagination * diff --git a/core/lib/Thelia/Core/Template/Loop/Order.php b/core/lib/Thelia/Core/Template/Loop/Order.php index 5b1e97cc1..140a64fc3 100755 --- a/core/lib/Thelia/Core/Template/Loop/Order.php +++ b/core/lib/Thelia/Core/Template/Loop/Order.php @@ -28,8 +28,12 @@ use Thelia\Core\Template\Element\BaseLoop; use Thelia\Core\Template\Element\LoopResult; use Thelia\Core\Template\Element\LoopResultRow; +use Thelia\Core\Template\Element\SearchLoopInterface; use Thelia\Core\Template\Loop\Argument\ArgumentCollection; use Thelia\Core\Template\Loop\Argument\Argument; +use Thelia\Model\CustomerQuery; +use Thelia\Model\OrderAddress; +use Thelia\Model\OrderAddressQuery; use Thelia\Model\OrderQuery; use Thelia\Type\TypeCollection; use Thelia\Type; @@ -38,8 +42,9 @@ use Thelia\Type; * @package Thelia\Core\Template\Loop * * @author Franck Allimant + * @author Etienne Roudeix */ -class Order extends BaseLoop +class Order extends BaseLoop implements SearchLoopInterface { public $countable = true; public $timestampable = true; @@ -74,6 +79,59 @@ class Order extends BaseLoop ); } + public function getSearchIn() + { + return array( + "ref", + "customer_ref", + "customer_firstname", + "customer_lastname", + "customer_email", + ); + } + + /** + * @param OrderQuery $search + * @param $searchTerm + * @param $searchIn + * @param $searchCriteria + */ + public function doSearch(&$search, $searchTerm, $searchIn, $searchCriteria) + { + + $search->_and(); + foreach($searchIn as $index => $searchInElement) { + if($index > 0) { + $search->_or(); + } + switch($searchInElement) { + case "ref": + $search->filterByRef($searchTerm, $searchCriteria); + break; + case "customer_ref": + $search->filterByCustomer( + CustomerQuery::create()->filterByRef($searchTerm, $searchCriteria)->find() + ); + break; + case "customer_firstname": + $search->filterByOrderAddressRelatedByInvoiceOrderAddressId( + OrderAddressQuery::create()->filterByFirstname($searchTerm, $searchCriteria)->find() + ); + break; + case "customer_lastname": + $search->filterByOrderAddressRelatedByInvoiceOrderAddressId( + OrderAddressQuery::create()->filterByLastname($searchTerm, $searchCriteria)->find() + ); + break; + case "customer_email": + $search->filterByCustomer( + CustomerQuery::create()->filterByEmail($searchTerm, $searchCriteria)->find() + ); + break; + } + } + } + /** * @param $pagination * diff --git a/core/lib/Thelia/Core/Template/Loop/Product.php b/core/lib/Thelia/Core/Template/Loop/Product.php index a2ddd9433..4d32b7101 100755 --- a/core/lib/Thelia/Core/Template/Loop/Product.php +++ b/core/lib/Thelia/Core/Template/Loop/Product.php @@ -26,36 +26,35 @@ namespace Thelia\Core\Template\Loop; use Propel\Runtime\ActiveQuery\Criteria; use Propel\Runtime\ActiveQuery\Join; use Thelia\Core\Template\Element\BaseI18nLoop; +use Thelia\Core\Template\Element\BaseLoop; use Thelia\Core\Template\Element\LoopResult; use Thelia\Core\Template\Element\LoopResultRow; +use Thelia\Core\Template\Element\SearchLoopInterface; use Thelia\Core\Template\Loop\Argument\ArgumentCollection; use Thelia\Core\Template\Loop\Argument\Argument; use Thelia\Exception\TaxEngineException; +use Thelia\Model\Base\ProductSaleElementsQuery; use Thelia\Model\CategoryQuery; use Thelia\Model\CountryQuery; use Thelia\Model\CurrencyQuery; use Thelia\Model\Map\ProductPriceTableMap; use Thelia\Model\Map\ProductSaleElementsTableMap; use Thelia\Model\Map\ProductTableMap; -use Thelia\Model\ProductCategoryQuery; use Thelia\Model\ProductQuery; -use Thelia\Model\ConfigQuery; use Thelia\Type\TypeCollection; use Thelia\Type; -use Thelia\Type\BooleanOrBothType; /** * * Product loop * - * * Class Product * @package Thelia\Core\Template\Loop * @author Etienne Roudeix */ -class Product extends BaseI18nLoop +class Product extends BaseI18nLoop implements SearchLoopInterface { public $timestampable = true; public $versionable = true; @@ -66,6 +65,7 @@ class Product extends BaseI18nLoop protected function getArgDefinitions() { return new ArgumentCollection( + Argument::createBooleanTypeArgument('complex', false), Argument::createIntListTypeArgument('id'), new Argument( 'ref', @@ -130,6 +130,39 @@ class Product extends BaseI18nLoop ); } + public function getSearchIn() + { + return array( + "ref", + "title", + ); + } + + /** + * @param ProductQuery $search + * @param $searchTerm + * @param $searchIn + * @param $searchCriteria + */ + public function doSearch(&$search, $searchTerm, $searchIn, $searchCriteria) + { + + $search->_and(); + foreach($searchIn as $index => $searchInElement) { + if($index > 0) { + $search->_or(); + } + switch($searchInElement) { + case "ref": + $search->filterByRef($searchTerm, $searchCriteria); + break; + case "title": + $search->where("CASE WHEN NOT ISNULL(`requested_locale_i18n`.ID) THEN `requested_locale_i18n`.`TITLE` ELSE `default_locale_i18n`.`TITLE` END ".$searchCriteria." ?", $searchTerm, \PDO::PARAM_STR); + break; + } + } + } + /** * @param $pagination * @@ -137,6 +170,390 @@ class Product extends BaseI18nLoop * @throws \InvalidArgumentException */ public function exec(&$pagination) + { + $complex = $this->getComplex(); + if(true === $complex) { + return $this->execComplex($pagination); + } + + $currencyId = $this->getCurrency(); + if (null !== $currencyId) { + $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 = ProductQuery::create(); + $search->innerJoinProductSaleElements('pse'); + $search->addJoinCondition('pse', '`pse`.IS_DEFAULT=1'); + + $priceJoin = new Join(); + $priceJoin->addExplicitCondition(ProductSaleElementsTableMap::TABLE_NAME, 'ID', 'pse', ProductPriceTableMap::TABLE_NAME, 'PRODUCT_SALE_ELEMENTS_ID', 'price'); + $priceJoin->setJoinType(Criteria::LEFT_JOIN); + + $search->addJoinObject($priceJoin, 'price_join') + ->addJoinCondition('price_join', '`price`.`currency_id` = ?', $currency->getId(), null, \PDO::PARAM_INT); + + if ($defaultCurrency->getId() != $currency->getId()) { + $priceJoinDefaultCurrency = new Join(); + $priceJoinDefaultCurrency->addExplicitCondition(ProductSaleElementsTableMap::TABLE_NAME, 'ID', 'pse', ProductPriceTableMap::TABLE_NAME, 'PRODUCT_SALE_ELEMENTS_ID', 'price' . $defaultCurrencySuffix); + $priceJoinDefaultCurrency->setJoinType(Criteria::LEFT_JOIN); + + $search->addJoinObject($priceJoinDefaultCurrency, 'price_join' . $defaultCurrencySuffix) + ->addJoinCondition('price_join' . $defaultCurrencySuffix, '`price' . $defaultCurrencySuffix . '`.`currency_id` = ?', $defaultCurrency->getId(), null, \PDO::PARAM_INT); + + /** + * rate value is checked as a float in overloaded getRate method. + */ + $priceToCompareAsSQL = 'CASE WHEN ISNULL(`price`.PRICE) OR `price`.FROM_DEFAULT_CURRENCY = 1 THEN + CASE WHEN `price`.PROMO=1 THEN `price' . $defaultCurrencySuffix . '`.PROMO_PRICE ELSE `price' . $defaultCurrencySuffix . '`.PRICE END * ' . $currency->getRate() . ' + ELSE + CASE WHEN `price`.PROMO=1 THEN `price`.PROMO_PRICE ELSE `price`.PRICE END + END'; + } else { + $priceToCompareAsSQL = 'CASE WHEN `pse`.PROMO=1 THEN `price`.PROMO_PRICE ELSE `price`.PRICE END'; + } + + /* manage translations */ + $locale = $this->configureI18nProcessing($search); + + $id = $this->getId(); + + if (!is_null($id)) { + $search->filterById($id, Criteria::IN); + } + + $ref = $this->getRef(); + + if (!is_null($ref)) { + $search->filterByRef($ref, Criteria::IN); + } + + $title = $this->getTitle(); + + if(!is_null($title)) { + $search->where("CASE WHEN NOT ISNULL(`requested_locale_i18n`.ID) THEN `requested_locale_i18n`.`TITLE` ELSE `default_locale_i18n`.`TITLE` END ".Criteria::LIKE." ?", "%".$title."%", \PDO::PARAM_STR); + } + + $category = $this->getCategory(); + $categoryDefault = $this->getCategoryDefault(); + + if (!is_null($category) ||!is_null($categoryDefault)) { + + $categoryIds = array(); + if (!is_array($category)) { + $category = array(); + } + if (!is_array($categoryDefault)) { + $categoryDefault = array(); + } + + $categoryIds = array_merge($categoryIds, $category, $categoryDefault); + $categories =CategoryQuery::create()->filterById($categoryIds, Criteria::IN)->find(); + + $depth = $this->getDepth(); + + if (null !== $depth) { + foreach (CategoryQuery::findAllChild($category, $depth) as $subCategory) { + $categories->prepend($subCategory); + } + } + + $search->filterByCategory( + $categories, + Criteria::IN + ); + } + + $new = $this->getNew(); + + if ($new === true) { + $search->where('`pse`.NEWNESS' . Criteria::EQUAL . '1'); + } elseif ($new === false) { + $search->where('`pse`.NEWNESS' . Criteria::EQUAL . '0'); + } + + $promo = $this->getPromo(); + + if ($promo === true) { + $search->where('`pse`.PROMO' . Criteria::EQUAL . '1'); + } elseif ($promo === false) { + $search->where('`pse`.PROMO' . Criteria::EQUAL . '0'); + } + + $min_stock = $this->getMin_stock(); + + if (null != $min_stock) { + $search->where('`pse`.QUANTITY' . Criteria::GREATER_THAN . '?', $min_stock, \PDO::PARAM_INT); + } + + $min_weight = $this->getMin_weight(); + + if (null != $min_weight) { + $search->where('`pse`.WEIGHT' . Criteria::GREATER_THAN . '?', $min_weight, \PDO::PARAM_STR); + } + + $max_weight = $this->getMax_weight(); + + if (null != $max_weight) { + $search->where('`is_max_weight`.WEIGHT' . Criteria::LESS_THAN . '?', $max_weight, \PDO::PARAM_STR); + } + + $min_price = $this->getMin_price(); + + if (null !== $min_price) { + + if (false === ConfigQuery::useTaxFreeAmounts()) { + // @todo + } + + $search->where('ROUND(' . $priceToCompareAsSQL . ', 2)>=?', $min_price, \PDO::PARAM_STR); + } + + $max_price = $this->getMax_price(); + + if (null !== $max_price) { + if (false === ConfigQuery::useTaxFreeAmounts()) { + // @todo + } + + $search->where('ROUND(' . $priceToCompareAsSQL . ', 2)<=?', $max_price, \PDO::PARAM_STR); + } + + $current = $this->getCurrent(); + + if ($current === true) { + $search->filterById($this->request->get("product_id"), Criteria::EQUAL); + } elseif ($current === false) { + $search->filterById($this->request->get("product_id"), Criteria::NOT_IN); + } + + $current_category = $this->getCurrent_category(); + + if ($current_category === true) { + $search->filterByCategory( + CategoryQuery::create()->filterByProduct( + ProductCategoryQuery::create()->filterByProductId( + $this->request->get("product_id"), + Criteria::EQUAL + )->find(), + Criteria::IN + )->find(), + Criteria::IN + ); + } elseif ($current_category === false) { + $search->filterByCategory( + CategoryQuery::create()->filterByProduct( + ProductCategoryQuery::create()->filterByProductId( + $this->request->get("product_id"), + Criteria::EQUAL + )->find(), + Criteria::IN + )->find(), + Criteria::NOT_IN + ); + } + + $visible = $this->getVisible(); + + if ($visible !== Type\BooleanOrBothType::ANY) $search->filterByVisible($visible ? 1 : 0); + + $exclude = $this->getExclude(); + + if (!is_null($exclude)) { + $search->filterById($exclude, Criteria::NOT_IN); + } + + $exclude_category = $this->getExclude_category(); + + if (!is_null($exclude_category)) { + $search->filterByCategory( + CategoryQuery::create()->filterById($exclude_category, Criteria::IN)->find(), + Criteria::NOT_IN + ); + } + + $feature_availability = $this->getFeature_availability(); + + $this->manageFeatureAv($search, $feature_availability); + + $feature_values = $this->getFeature_values(); + + $this->manageFeatureValue($search, $feature_values); + + $search->groupBy(ProductTableMap::ID); + + $search->withColumn('`pse`.ID', 'pse_id'); + $search->withColumn('`pse`.NEWNESS', 'is_new'); + $search->withColumn('`pse`.PROMO', 'is_promo'); + $search->withColumn('`pse`.QUANTITY', 'quantity'); + $search->withColumn('`pse`.WEIGHT', 'weight'); + $search->withColumn('`pse`.EAN_CODE', 'ean_code'); + + $search->withColumn('ROUND(' . $priceToCompareAsSQL . ', 2)', 'real_price'); + $search->withColumn('`price`.PRICE', 'price'); + $search->withColumn('`price`.PROMO_PRICE', 'promo_price'); + + $orders = $this->getOrder(); + + foreach ($orders as $order) { + switch ($order) { + case "id": + $search->orderById(Criteria::ASC); + break; + case "id_reverse": + $search->orderById(Criteria::DESC); + break; + case "alpha": + $search->addAscendingOrderByColumn('i18n_TITLE'); + break; + case "alpha_reverse": + $search->addDescendingOrderByColumn('i18n_TITLE'); + break; + case "min_price": + $search->addAscendingOrderByColumn('real_price'); + break; + case "max_price": + $search->addDescendingOrderByColumn('real_price'); + break; + case "manual": + if(null === $categoryIds || count($categoryIds) != 1) + throw new \InvalidArgumentException('Manual order cannot be set without single category argument'); + $search->orderByPosition(Criteria::ASC); + break; + case "manual_reverse": + if(null === $categoryIds || count($categoryIds) != 1) + throw new \InvalidArgumentException('Manual order cannot be set without single category argument'); + $search->orderByPosition(Criteria::DESC); + break; + case "ref": + $search->orderByRef(Criteria::ASC); + break; + case "promo": + $search->addDescendingOrderByColumn('is_promo'); + break; + case "new": + $search->addDescendingOrderByColumn('is_new'); + break; + case "given_id": + if(null === $id) + throw new \InvalidArgumentException('Given_id order cannot be set without `id` argument'); + foreach ($id as $singleId) { + $givenIdMatched = 'given_id_matched_' . $singleId; + $search->withColumn(ProductTableMap::ID . "='$singleId'", $givenIdMatched); + $search->orderBy($givenIdMatched, Criteria::DESC); + } + break; + case "random": + $search->clearOrderByColumns(); + $search->addAscendingOrderByColumn('RAND()'); + break(2); + } + } + + /* perform search */ + $products = $this->search($search, $pagination); + + $loopResult = new LoopResult($products); + + $taxCountry = CountryQuery::create()->findPk(64); // @TODO : make it magic + + foreach ($products as $product) { + + $loopResultRow = new LoopResultRow($loopResult, $product, $this->versionable, $this->timestampable, $this->countable); + + $price = $product->getVirtualColumn('price'); + try { + $taxedPrice = $product->getTaxedPrice( + $taxCountry, + $price + ); + } catch (TaxEngineException $e) { + $taxedPrice = null; + } + $promoPrice = $product->getVirtualColumn('promo_price'); + try { + $taxedPromoPrice = $product->getTaxedPromoPrice( + $taxCountry, + $promoPrice + ); + } catch (TaxEngineException $e) { + $taxedPromoPrice = null; + } + + // Find previous and next product, in the default category. + $default_category_id = $product->getDefaultCategoryId(); + + $previous = ProductQuery::create() + ->joinProductCategory() + ->where('ProductCategory.category_id = ?', $default_category_id) + ->filterByPosition($product->getPosition(), Criteria::LESS_THAN) + ->orderByPosition(Criteria::DESC) + ->findOne() + ; + + $next = ProductQuery::create() + ->joinProductCategory() + ->where('ProductCategory.category_id = ?', $default_category_id) + ->filterByPosition($product->getPosition(), Criteria::GREATER_THAN) + ->orderByPosition(Criteria::ASC) + ->findOne() + ; + + $loopResultRow + ->set("ID" , $product->getId()) + ->set("REF" , $product->getRef()) + ->set("IS_TRANSLATED" , $product->getVirtualColumn('IS_TRANSLATED')) + ->set("LOCALE" , $locale) + ->set("TITLE" , $product->getVirtualColumn('i18n_TITLE')) + ->set("CHAPO" , $product->getVirtualColumn('i18n_CHAPO')) + ->set("DESCRIPTION" , $product->getVirtualColumn('i18n_DESCRIPTION')) + ->set("POSTSCRIPTUM" , $product->getVirtualColumn('i18n_POSTSCRIPTUM')) + ->set("URL" , $product->getUrl($locale)) + ->set("BEST_PRICE" , $product->getVirtualColumn('is_promo') ? $promoPrice : $price) + ->set("BEST_PRICE_TAX" , $taxedPrice - $product->getVirtualColumn('is_promo') ? $taxedPromoPrice - $promoPrice : $taxedPrice - $price) + ->set("BEST_TAXED_PRICE" , $product->getVirtualColumn('is_promo') ? $taxedPromoPrice : $taxedPrice) + ->set("PRICE" , $price) + ->set("PRICE_TAX" , $taxedPrice - $price) + ->set("TAXED_PRICE" , $taxedPrice) + ->set("PROMO_PRICE" , $promoPrice) + ->set("PROMO_PRICE_TAX" , $taxedPromoPrice - $promoPrice) + ->set("TAXED_PROMO_PRICE" , $taxedPromoPrice) + ->set("PRODUCT_SALE_ELEMENT" , $product->getVirtualColumn('pse_id')) + ->set("WEIGHT" , $product->getVirtualColumn('weight')) + ->set("QUANTITY" , $product->getVirtualColumn('quantity')) + ->set("EAN_CODE" , $product->getVirtualColumn('ean_code')) + ->set("IS_PROMO" , $product->getVirtualColumn('is_promo')) + ->set("IS_NEW" , $product->getVirtualColumn('is_new')) + ->set("POSITION" , $product->getPosition()) + ->set("VISIBLE" , $product->getVisible() ? "1" : "0") + ->set("TEMPLATE" , $product->getTemplateId()) + ->set("HAS_PREVIOUS" , $previous != null ? 1 : 0) + ->set("HAS_NEXT" , $next != null ? 1 : 0) + ->set("PREVIOUS" , $previous != null ? $previous->getId() : -1) + ->set("NEXT" , $next != null ? $next->getId() : -1) + ->set("DEFAULT_CATEGORY" , $default_category_id) + ; + + $loopResult->addRow($loopResultRow); + } + + return $loopResult; + } + + /** + * @param $pagination + * + * @return \Thelia\Core\Template\Element\LoopResult + * @throws \InvalidArgumentException + */ + public function execComplex(&$pagination) { $currencyId = $this->getCurrency(); if (null !== $currencyId) { @@ -313,7 +730,7 @@ class Product extends BaseI18nLoop * 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 + $MinPriceToCompareAsSQL = 'CASE WHEN ISNULL(CASE WHEN `is_min_price`.PROMO=1 THEN `min_price_data`.PROMO_PRICE ELSE `min_price_data`.PRICE END) OR `min_price_data`.FROM_DEFAULT_CURRENCY = 1 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 @@ -351,7 +768,7 @@ class Product extends BaseI18nLoop * 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 + $MaxPriceToCompareAsSQL = 'CASE WHEN ISNULL(CASE WHEN `is_max_price`.PROMO=1 THEN `max_price_data`.PROMO_PRICE ELSE `max_price_data`.PRICE END) OR `min_price_data`.FROM_DEFAULT_CURRENCY = 1 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 @@ -492,59 +909,11 @@ class Product extends BaseI18nLoop $feature_availability = $this->getFeature_availability(); - if (null !== $feature_availability) { - foreach ($feature_availability as $feature => $feature_choice) { - foreach ($feature_choice['values'] as $feature_av) { - $featureAlias = 'fa_' . $feature; - if($feature_av != '*') - $featureAlias .= '_' . $feature_av; - $search->joinFeatureProduct($featureAlias, Criteria::LEFT_JOIN) - ->addJoinCondition($featureAlias, "`$featureAlias`.FEATURE_ID = ?", $feature, null, \PDO::PARAM_INT); - if($feature_av != '*') - $search->addJoinCondition($featureAlias, "`$featureAlias`.FEATURE_AV_ID = ?", $feature_av, null, \PDO::PARAM_INT); - } - - /* format for mysql */ - $sqlWhereString = $feature_choice['expression']; - if ($sqlWhereString == '*') { - $sqlWhereString = 'NOT ISNULL(`fa_' . $feature . '`.ID)'; - } else { - $sqlWhereString = preg_replace('#([0-9]+)#', 'NOT ISNULL(`fa_' . $feature . '_' . '\1`.ID)', $sqlWhereString); - $sqlWhereString = str_replace('&', ' AND ', $sqlWhereString); - $sqlWhereString = str_replace('|', ' OR ', $sqlWhereString); - } - - $search->where("(" . $sqlWhereString . ")"); - } - } + $this->manageFeatureAv($search, $feature_availability); $feature_values = $this->getFeature_values(); - if (null !== $feature_values) { - foreach ($feature_values as $feature => $feature_choice) { - foreach ($feature_choice['values'] as $feature_value) { - $featureAlias = 'fv_' . $feature; - if($feature_value != '*') - $featureAlias .= '_' . $feature_value; - $search->joinFeatureProduct($featureAlias, Criteria::LEFT_JOIN) - ->addJoinCondition($featureAlias, "`$featureAlias`.FEATURE_ID = ?", $feature, null, \PDO::PARAM_INT); - if($feature_value != '*') - $search->addJoinCondition($featureAlias, "`$featureAlias`.BY_DEFAULT = ?", $feature_value, null, \PDO::PARAM_STR); - } - - /* format for mysql */ - $sqlWhereString = $feature_choice['expression']; - if ($sqlWhereString == '*') { - $sqlWhereString = 'NOT ISNULL(`fv_' . $feature . '`.ID)'; - } else { - $sqlWhereString = preg_replace('#([a-zA-Z0-9_\-]+)#', 'NOT ISNULL(`fv_' . $feature . '_' . '\1`.ID)', $sqlWhereString); - $sqlWhereString = str_replace('&', ' AND ', $sqlWhereString); - $sqlWhereString = str_replace('|', ' OR ', $sqlWhereString); - } - - $search->where("(" . $sqlWhereString . ")"); - } - } + $this->manageFeatureValue($search, $feature_values); $search->groupBy(ProductTableMap::ID); @@ -620,7 +989,8 @@ class Product extends BaseI18nLoop try { $taxedPrice = $product->getTaxedPrice( - $taxCountry + $taxCountry, + $product->getRealLowestPrice() ); } catch (TaxEngineException $e) { $taxedPrice = null; @@ -670,11 +1040,69 @@ class Product extends BaseI18nLoop ->set("DEFAULT_CATEGORY" , $default_category_id) ->set("TAX_RULE_ID" , $product->getTaxRuleId()) - ; + ; $loopResult->addRow($loopResultRow); } return $loopResult; } + + protected function manageFeatureAv(&$search, $feature_availability) + { + if (null !== $feature_availability) { + foreach ($feature_availability as $feature => $feature_choice) { + foreach ($feature_choice['values'] as $feature_av) { + $featureAlias = 'fa_' . $feature; + if($feature_av != '*') + $featureAlias .= '_' . $feature_av; + $search->joinFeatureProduct($featureAlias, Criteria::LEFT_JOIN) + ->addJoinCondition($featureAlias, "`$featureAlias`.FEATURE_ID = ?", $feature, null, \PDO::PARAM_INT); + if($feature_av != '*') + $search->addJoinCondition($featureAlias, "`$featureAlias`.FEATURE_AV_ID = ?", $feature_av, null, \PDO::PARAM_INT); + } + + /* format for mysql */ + $sqlWhereString = $feature_choice['expression']; + if ($sqlWhereString == '*') { + $sqlWhereString = 'NOT ISNULL(`fa_' . $feature . '`.ID)'; + } else { + $sqlWhereString = preg_replace('#([0-9]+)#', 'NOT ISNULL(`fa_' . $feature . '_' . '\1`.ID)', $sqlWhereString); + $sqlWhereString = str_replace('&', ' AND ', $sqlWhereString); + $sqlWhereString = str_replace('|', ' OR ', $sqlWhereString); + } + + $search->where("(" . $sqlWhereString . ")"); + } + } + } + + protected function manageFeatureValue(&$search, $feature_values) + { + if (null !== $feature_values) { + foreach ($feature_values as $feature => $feature_choice) { + foreach ($feature_choice['values'] as $feature_value) { + $featureAlias = 'fv_' . $feature; + if($feature_value != '*') + $featureAlias .= '_' . $feature_value; + $search->joinFeatureProduct($featureAlias, Criteria::LEFT_JOIN) + ->addJoinCondition($featureAlias, "`$featureAlias`.FEATURE_ID = ?", $feature, null, \PDO::PARAM_INT); + if($feature_value != '*') + $search->addJoinCondition($featureAlias, "`$featureAlias`.BY_DEFAULT = ?", $feature_value, null, \PDO::PARAM_STR); + } + + /* format for mysql */ + $sqlWhereString = $feature_choice['expression']; + if ($sqlWhereString == '*') { + $sqlWhereString = 'NOT ISNULL(`fv_' . $feature . '`.ID)'; + } else { + $sqlWhereString = preg_replace('#([a-zA-Z0-9_\-]+)#', 'NOT ISNULL(`fv_' . $feature . '_' . '\1`.ID)', $sqlWhereString); + $sqlWhereString = str_replace('&', ' AND ', $sqlWhereString); + $sqlWhereString = str_replace('|', ' OR ', $sqlWhereString); + } + + $search->where("(" . $sqlWhereString . ")"); + } + } + } } diff --git a/core/lib/Thelia/Core/Template/Loop/ProductSaleElements.php b/core/lib/Thelia/Core/Template/Loop/ProductSaleElements.php index 29d56b149..b48b0359e 100755 --- a/core/lib/Thelia/Core/Template/Loop/ProductSaleElements.php +++ b/core/lib/Thelia/Core/Template/Loop/ProductSaleElements.php @@ -136,8 +136,8 @@ class ProductSaleElements extends BaseLoop /** * rate value is checked as a float in overloaded getRate method. */ - $priceSelectorAsSQL = 'ROUND(CASE WHEN ISNULL(`price`.PRICE) THEN `price_default_currency`.PRICE * ' . $currency->getRate() . ' ELSE `price`.PRICE END, 2)'; - $promoPriceSelectorAsSQL = 'ROUND(CASE WHEN ISNULL(`price`.PRICE) THEN `price_default_currency`.PROMO_PRICE * ' . $currency->getRate() . ' ELSE `price`.PROMO_PRICE END, 2)'; + $priceSelectorAsSQL = 'ROUND(CASE WHEN ISNULL(`price`.PRICE) OR `price`.FROM_DEFAULT_CURRENCY = 1 THEN `price_default_currency`.PRICE * ' . $currency->getRate() . ' ELSE `price`.PRICE END, 2)'; + $promoPriceSelectorAsSQL = 'ROUND(CASE WHEN ISNULL(`price`.PRICE) OR `price`.FROM_DEFAULT_CURRENCY = 1 THEN `price_default_currency`.PROMO_PRICE * ' . $currency->getRate() . ' ELSE `price`.PROMO_PRICE END, 2)'; $search->withColumn($priceSelectorAsSQL, 'price_PRICE') ->withColumn($promoPriceSelectorAsSQL, 'price_PROMO_PRICE') ->withColumn('CASE WHEN ' . ProductSaleElementsTableMap::PROMO . ' = 1 THEN ' . $promoPriceSelectorAsSQL . ' ELSE ' . $priceSelectorAsSQL . ' END', 'price_FINAL_PRICE'); diff --git a/core/lib/Thelia/Model/OrderQuery.php b/core/lib/Thelia/Model/OrderQuery.php index 8d5e4c085..0fff5dba1 100755 --- a/core/lib/Thelia/Model/OrderQuery.php +++ b/core/lib/Thelia/Model/OrderQuery.php @@ -2,6 +2,7 @@ namespace Thelia\Model; +use Propel\Runtime\ActiveQuery\Criteria; use Propel\Runtime\Exception\PropelException; use Propel\Runtime\Propel; use Thelia\Model\Base\OrderQuery as BaseOrderQuery; @@ -52,4 +53,5 @@ class OrderQuery extends BaseOrderQuery return $obj; } + } // OrderQuery diff --git a/core/lib/Thelia/Model/Product.php b/core/lib/Thelia/Model/Product.php index 1441810b0..f16a8a776 100755 --- a/core/lib/Thelia/Model/Product.php +++ b/core/lib/Thelia/Model/Product.php @@ -41,11 +41,16 @@ class Product extends BaseProduct return $amount; } - public function getTaxedPrice(Country $country) + public function getTaxedPrice(Country $country, $price) { $taxCalculator = new Calculator(); + return round($taxCalculator->load($this, $country)->getTaxedPrice($price), 2); + } - return $taxCalculator->load($this, $country)->getTaxedPrice($this->getRealLowestPrice()); + public function getTaxedPromoPrice(Country $country, $price) + { + $taxCalculator = new Calculator(); + return round($taxCalculator->load($this, $country)->getTaxedPrice($price), 2); } /** diff --git a/install/insert.sql b/install/insert.sql index bf9022df4..0f1634d6f 100755 --- a/install/insert.sql +++ b/install/insert.sql @@ -30,6 +30,7 @@ INSERT INTO `config` (`name`, `value`, `secured`, `hidden`, `created_at`, `updat ('session_config.handlers', 'Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\NativeFileSessionHandler', 0, 0, NOW(), NOW()), ('company_name','', 0, 0, NOW(), NOW()), ('contact_email','', 0, 0, NOW(), NOW()), +('url_site','', 0, 0, NOW(), NOW()), ('one_domain_foreach_lang','0', 1, 1, NOW(), NOW()) ; @@ -1273,3 +1274,12 @@ INSERT INTO resource_i18n (`id`, `locale`, `title`) VALUES (22, 'fr_FR', 'Configuration / Tax'), (23, 'en_US', 'Configuration / Template'), (23, 'fr_FR', 'Configuration / Template'); + + +INSERT INTO `message` (`id`, `name`, `secured`, `created_at`, `updated_at`, `version`, `version_created_at`, `version_created_by`) VALUES +(1, 'order_confirmation', NULL, NOW(), NOW(), 2, NOW(), NULL); + +INSERT INTO `message_i18n` (`id`, `locale`, `title`, `subject`, `text_message`, `html_message`) VALUES +(1, 'en_US', 'order confirmation', 'Commande : Commande : {$order_ref}', '{assign var="order_id" value=1}\r\n\r\n{loop name="order.invoice" type="order" id=$order_id customer="*"}\r\n {loop name="currency.order" type="currency" id=$CURRENCY}\r\n {assign "orderCurrency" $CODE}\r\n {/loop}\r\n{loop type="order_address" name="delivery_address" id=$INVOICE_ADDRESS}\r\n{loop type="title" name="order-invoice-address-title" id=$TITLE}{$LONG}{/loop}{$FIRSTNAME} {$LASTNAME}\\r\\n\r\n{$ADDRESS1} {$ADDRESS2} {$ADDRESS3}\\r\\n\r\n{$ZIPCODE} {$CITY}\\r\\n\r\n{loop type="country" name="country_delivery" id=$COUNTRY}{$TITLE}{/loop}\\r\\n\r\n{/loop}\r\nConfirmation de commande {$REF} du {format_date date=$INVOICE_DATE}\\r\\n\\r\\n\r\nLes articles commandés:\\r\\n\r\n{loop type="order_product" name="order-products" order=$ID}\r\n{if $WAS_IN_PROMO == 1}\r\n {assign "realPrice" $PROMO_PRICE}\r\n {assign "realTax" $PROMO_PRICE_TAX}\r\n {assign "realTaxedPrice" $TAXED_PROMO_PRICE}\r\n{else}\r\n {assign "realPrice" $PRICE}\r\n {assign "realTax" $PRICE_TAX}\r\n {assign "realTaxedPrice" $TAXED_PRICE}\r\n{/if}\r\n \\r\\n\r\n Article : {$TITLE}\r\n{ifloop rel="combinations"}\r\n {loop type="order_product_attribute_combination" name="combinations" order_product=$ID}\r\n {$ATTRIBUTE_TITLE} - {$ATTRIBUTE_AVAILABILITY_TITLE}\\r\\n\r\n{/loop}\r\n{/ifloop}\\r\\n\r\n Quantité : {$QUANTITY}\\r\\n\r\n Prix unitaire TTC : {$realTaxedPrice} {$orderCurrency}\\r\\n\r\n{/loop}\r\n\\r\\n-----------------------------------------\\r\\n\r\nMontant total TTC : {$TOTAL_TAXED_AMOUNT - $POSTAGE} {$orderCurrency} \\r\\n\r\nFrais de port TTC : {$POSTAGE} {$orderCurrency} \\r\\n\r\nSomme totale: {$TOTAL_TAXED_AMOUNT} {$orderCurrency} \\r\\n\r\n==================================\\r\\n\\r\\n\r\nVotre facture est disponible dans la rubrique mon compte sur {config key="url_site"}\r\n{/loop}', '{loop name="order.invoice" type="order" id=$order_id customer="*"}\r\n {loop name="currency.order" type="currency" id=$CURRENCY}\r\n {assign "orderCurrency" $SYMBOL}\r\n {/loop}\r\n{loop type="customer" name="customer.invoice" id=$CUSTOMER current="0"}\r\n {assign var="customer_ref" value=$REF}\r\n{/loop}\r\n\r\n\r\n\r\n \r\n courriel de confirmation de commande de {config key="url_site"} \r\n {literal}\r\n \r\n {/literal}\r\n\r\n\r\n
\r\n

{config key="company_name"}

\r\n

Confirmation de commande

\r\n

N° {$REF} du {format_date date=$INVOICE_DATE output="date"}

\r\n
\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n {loop type="order_product" name="order-products" order=$ID}\r\n {if $WAS_IN_PROMO == 1}\r\n {assign "realPrice" $PROMO_PRICE}\r\n {assign "realTax" $PROMO_PRICE_TAX}\r\n {assign "realTaxedPrice" $TAXED_PROMO_PRICE}\r\n {else}\r\n {assign "realPrice" $PRICE}\r\n {assign "realTax" $PRICE_TAX}\r\n {assign "realTaxedPrice" $TAXED_PRICE}\r\n {/if}\r\n \r\n \r\n \r\n \r\n \r\n \r\n {/loop}\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n
RéférenceDésignationP.U. €Qté
{$REF}{$TITLE}\r\n {ifloop rel="combinations"}\r\n {loop type="order_product_attribute_combination" name="combinations" order_product=$ID}\r\n {$ATTRIBUTE_TITLE} - {$ATTRIBUTE_AVAILABILITY_TITLE}
\r\n {/loop}\r\n {/ifloop}\r\n
{$orderCurrency} {$realTaxedPrice}{$QUANTITY}
 
Montant total avant remise €{$orderCurrency} {$TOTAL_TAXED_AMOUNT - $POSTAGE}
Port €{$orderCurrency} {$POSTAGE}
Montant total de la commande €{$orderCurrency} {$TOTAL_TAXED_AMOUNT}
\r\n
\r\n

LIVRAISON : {loop name="delivery-module" type="module" id=$DELIVERY_MODULE}{$TITLE}{/loop}

\r\n {loop type="order_address" name="delivery_address" id=$INVOICE_ADDRESS}\r\n

N° de client : {$customer_ref}

\r\n

Nom :\r\n {loop type="title" name="order-invoice-address-title" id=$TITLE}{$LONG}{/loop} {$FIRSTNAME} {$LASTNAME}

\r\n

N° et rue :\r\n {$ADDRESS1}

\r\n

Complément : {$ADDRESS2}\r\n {$ADDRESS3}

\r\n

Code postal : {$ZIPCODE}

\r\n

Ville : {$CITY}

\r\n

Pays : {loop type="country" name="country_delivery" id=$COUNTRY}{$TITLE}{/loop}

\r\n
\r\n {/loop}\r\n
\r\n

FACTURATION : paiement par {loop name="payment-module" type="module" id=$PAYMENT_MODULE}{$TITLE}{/loop}

\r\n {loop type="order_address" name="delivery_address" id=$DELIVERY_ADDRESS}\r\n

N° de client : {$customer_ref}

\r\n

Nom :\r\n {loop type="title" name="order-invoice-address-title" id=$TITLE}{$LONG}{/loop} {$FIRSTNAME} {$LASTNAME}

\r\n

N° et rue :\r\n {$ADDRESS1}

\r\n

Complément : {$ADDRESS2}\r\n {$ADDRESS3}

\r\n

Code postal : {$ZIPCODE}

\r\n

Ville : {$CITY}

\r\n

Pays : {loop type="country" name="country_delivery" id=$COUNTRY}{$TITLE}{/loop}

\r\n
\r\n {/loop}\r\n

Le suivi de votre commande est disponible dans la rubrique mon compte sur {config key="url_site"}

\r\n
\r\n\r\n\r\n{/loop}'), +(1, 'fr_FR', 'order confirmation', 'Commande : {$order_ref}', '{assign var="order_id" value=1}\r\n\r\n{loop name="order.invoice" type="order" id=$order_id customer="*"}\r\n {loop name="currency.order" type="currency" id=$CURRENCY}\r\n {assign "orderCurrency" $CODE}\r\n {/loop}\r\n{loop type="order_address" name="delivery_address" id=$INVOICE_ADDRESS}\r\n{loop type="title" name="order-invoice-address-title" id=$TITLE}{$LONG}{/loop}{$FIRSTNAME} {$LASTNAME}\\r\\n\r\n{$ADDRESS1} {$ADDRESS2} {$ADDRESS3}\\r\\n\r\n{$ZIPCODE} {$CITY}\\r\\n\r\n{loop type="country" name="country_delivery" id=$COUNTRY}{$TITLE}{/loop}\\r\\n\r\n{/loop}\r\nConfirmation de commande {$REF} du {format_date date=$INVOICE_DATE}\\r\\n\\r\\n\r\nLes articles commandés:\\r\\n\r\n{loop type="order_product" name="order-products" order=$ID}\r\n{if $WAS_IN_PROMO == 1}\r\n {assign "realPrice" $PROMO_PRICE}\r\n {assign "realTax" $PROMO_PRICE_TAX}\r\n {assign "realTaxedPrice" $TAXED_PROMO_PRICE}\r\n{else}\r\n {assign "realPrice" $PRICE}\r\n {assign "realTax" $PRICE_TAX}\r\n {assign "realTaxedPrice" $TAXED_PRICE}\r\n{/if}\r\n \\r\\n\r\n Article : {$TITLE}\r\n{ifloop rel="combinations"}\r\n {loop type="order_product_attribute_combination" name="combinations" order_product=$ID}\r\n {$ATTRIBUTE_TITLE} - {$ATTRIBUTE_AVAILABILITY_TITLE}\\r\\n\r\n{/loop}\r\n{/ifloop}\\r\\n\r\n Quantité : {$QUANTITY}\\r\\n\r\n Prix unitaire TTC : {$realTaxedPrice} {$orderCurrency}\\r\\n\r\n{/loop}\r\n\\r\\n-----------------------------------------\\r\\n\r\nMontant total TTC : {$TOTAL_TAXED_AMOUNT - $POSTAGE} {$orderCurrency} \\r\\n\r\nFrais de port TTC : {$POSTAGE} {$orderCurrency} \\r\\n\r\nSomme totale: {$TOTAL_TAXED_AMOUNT} {$orderCurrency} \\r\\n\r\n==================================\\r\\n\\r\\n\r\nVotre facture est disponible dans la rubrique mon compte sur {config key="url_site"}\r\n{/loop}', '{loop name="order.invoice" type="order" id=$order_id customer="*"}\r\n {loop name="currency.order" type="currency" id=$CURRENCY}\r\n {assign "orderCurrency" $SYMBOL}\r\n {/loop}\r\n{loop type="customer" name="customer.invoice" id=$CUSTOMER current="0"}\r\n {assign var="customer_ref" value=$REF}\r\n{/loop}\r\n\r\n\r\n\r\n \r\n courriel de confirmation de commande de {config key="url_site"} \r\n {literal}\r\n \r\n {/literal}\r\n\r\n\r\n
\r\n

{config key="company_name"}

\r\n

Confirmation de commande

\r\n

N° {$REF} du {format_date date=$INVOICE_DATE output="date"}

\r\n
\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n {loop type="order_product" name="order-products" order=$ID}\r\n {if $WAS_IN_PROMO == 1}\r\n {assign "realPrice" $PROMO_PRICE}\r\n {assign "realTax" $PROMO_PRICE_TAX}\r\n {assign "realTaxedPrice" $TAXED_PROMO_PRICE}\r\n {else}\r\n {assign "realPrice" $PRICE}\r\n {assign "realTax" $PRICE_TAX}\r\n {assign "realTaxedPrice" $TAXED_PRICE}\r\n {/if}\r\n \r\n \r\n \r\n \r\n \r\n \r\n {/loop}\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n
RéférenceDésignationP.U. €Qté
{$REF}{$TITLE}\r\n {ifloop rel="combinations"}\r\n {loop type="order_product_attribute_combination" name="combinations" order_product=$ID}\r\n {$ATTRIBUTE_TITLE} - {$ATTRIBUTE_AVAILABILITY_TITLE}
\r\n {/loop}\r\n {/ifloop}\r\n
{$orderCurrency} {$realTaxedPrice}{$QUANTITY}
 
Montant total avant remise €{$orderCurrency} {$TOTAL_TAXED_AMOUNT - $POSTAGE}
Port €{$orderCurrency} {$POSTAGE}
Montant total de la commande €{$orderCurrency} {$TOTAL_TAXED_AMOUNT}
\r\n
\r\n

LIVRAISON : {loop name="delivery-module" type="module" id=$DELIVERY_MODULE}{$TITLE}{/loop}

\r\n {loop type="order_address" name="delivery_address" id=$INVOICE_ADDRESS}\r\n

N° de client : {$customer_ref}

\r\n

Nom :\r\n {loop type="title" name="order-invoice-address-title" id=$TITLE}{$LONG}{/loop} {$FIRSTNAME} {$LASTNAME}

\r\n

N° et rue :\r\n {$ADDRESS1}

\r\n

Complément : {$ADDRESS2}\r\n {$ADDRESS3}

\r\n

Code postal : {$ZIPCODE}

\r\n

Ville : {$CITY}

\r\n

Pays : {loop type="country" name="country_delivery" id=$COUNTRY}{$TITLE}{/loop}

\r\n
\r\n {/loop}\r\n
\r\n

FACTURATION : paiement par {loop name="payment-module" type="module" id=$PAYMENT_MODULE}{$TITLE}{/loop}

\r\n {loop type="order_address" name="delivery_address" id=$DELIVERY_ADDRESS}\r\n

N° de client : {$customer_ref}

\r\n

Nom :\r\n {loop type="title" name="order-invoice-address-title" id=$TITLE}{$LONG}{/loop} {$FIRSTNAME} {$LASTNAME}

\r\n

N° et rue :\r\n {$ADDRESS1}

\r\n

Complément : {$ADDRESS2}\r\n {$ADDRESS3}

\r\n

Code postal : {$ZIPCODE}

\r\n

Ville : {$CITY}

\r\n

Pays : {loop type="country" name="country_delivery" id=$COUNTRY}{$TITLE}{/loop}

\r\n
\r\n {/loop}\r\n

Le suivi de votre commande est disponible dans la rubrique mon compte sur {config key="url_site"}

\r\n
\r\n\r\n\r\n{/loop}'); + diff --git a/templates/admin/default/configuration.html b/templates/admin/default/configuration.html index 14f195270..4c6acd1db 100644 --- a/templates/admin/default/configuration.html +++ b/templates/admin/default/configuration.html @@ -151,7 +151,7 @@ {/loop} - {loop type="auth" name="pcc6" role="ADMIN" resource="admin.configuration.mailing-system" access="VIEW"} +{* {loop type="auth" name="pcc6" role="ADMIN" resource="admin.configuration.mailing-system" access="VIEW"} {intl l='Mailing system'} @@ -170,7 +170,7 @@ {intl l='System logs'} - {/loop} + {/loop}*} {module_include location='system_configuration_bottom'} diff --git a/templates/admin/default/customer-edit.html b/templates/admin/default/customer-edit.html index 6fea48aea..71c6b8695 100644 --- a/templates/admin/default/customer-edit.html +++ b/templates/admin/default/customer-edit.html @@ -29,7 +29,7 @@
- {form name="thelia.admin.customer.modification"} + {form name="thelia.admin.customer.update"}
diff --git a/templates/admin/default/search.html b/templates/admin/default/search.html new file mode 100644 index 000000000..a39eda982 --- /dev/null +++ b/templates/admin/default/search.html @@ -0,0 +1,238 @@ +{extends file="admin-layout.tpl"} + +{block name="page-title"}{intl l='Modules'}{/block} + +{block name="check-resource"}admin.configuration.search{/block} +{block name="check-access"}view{/block} + +{block name="main-content"} +
+ +
+ + + + {module_include location='modules_top'} + +
+
+ + {* customer search *} +
+
+ + + + + + + + + + + + + + + + + + + + {loop name="customer_list" type="customer" current="false" visible="*" backend_context="1" search_term=$smarty.get.search_term search_in="ref,firstname,lastname,email"} + {assign "lastOrderDate" ''} + {assign "lastOrderAmount" ''} + {assign "lastOrderCurrency" ''} + + {loop type="order" name="last-order" customer=$ID order="create-date-reverse" limit="1"} + {assign "lastOrderDate" "{format_date date=$CREATE_DATE}"} + {assign "lastOrderAmount" "{format_number number=$TOTAL_TAXED_AMOUNT}"} + {loop type="currency" name="order-currency" id=$CURRENCY} + {assign "lastOrderCurrency" $SYMBOL} + {/loop} + {/loop} + + + + + + + + + {module_include location='customer_list_row'} + + + + + + + + {/loop} + +
+ {intl l='Customer'} +
+ {intl l="customer ref"} + + {intl l="company"} + + {intl l="firstname & lastname"} + + {intl l="last order"} + {intl l='order amount'}{intl l="Actions"}
{$REF} + {$COMPANY} + + {$FIRSTNAME} {$LASTNAME} + + {$lastOrderDate} + + {$lastOrderCurrency} {$lastOrderAmount} + +
+ + {loop type="auth" name="can_change" role="ADMIN" resource="admin.customer" access="UPDATE"} + + {/loop} + {loop type="auth" name="can_send_mail" role="ADMIN" resource="admin.customer" access="VIEW"} + + {/loop} + {loop type="auth" name="can_delete" role="ADMIN" resource="admin.customer" access="DELETE"} + + {/loop} +
+
+
+
+ {* end customer search *} + + {* order search *} +
+
+ + + + + + + + + + + + + + + + + {loop type="order" name="order-search" backend_context=1 customer="*" search_term=$smarty.get.search_term search_in="ref,customer_ref,customer_firstname,customer_lastname,customer_email"} + {loop type="order_address" name="order-invoice-address" id=$INVOICE_ADDRESS} + {assign "orderInvoiceFirstName" $FIRSTNAME} + {assign "orderInvoiceLastName" $LASTNAME} + {assign "orderInvoiceCompany" $COMPANY} + {/loop} + + {loop type="order-status" name="order-status" id=$STATUS} + {assign "orderStatus" $TITLE} + {assign "orderStatusLabel" "order_$CODE"} + {/loop} + + + + + + + + + + + + + {/loop} + +
+ {intl l='Orders'} +
{intl l="Order n°"}{intl l="Date & Hour"}{intl l="Company"}{intl l="Name"}{intl l="Amount"}{intl l="Status"}{intl l="Actions"}
{$REF}{format_date date=$CREATE_DATE}{$orderInvoiceCompany}{$orderInvoiceFirstName|ucwords} {$orderInvoiceLastName|upper}{$TOTAL_TAXED_AMOUNT}{$orderStatus} +
+ + {loop type="auth" name="can_change" role="ADMIN" resource="admin.order" access="UPDATE"} + + {/loop} +
+
+
+
+ {* end order search *} + + {* product search *} +
+
+ + + + + + + + + + + + + + + {loop type="product" name="product-search" visible="*" search_mode="sentence" search_term=$smarty.get.search_term search_in="ref,title"} + + + + + + + + + + + + + {/loop} + +
+ {intl l='Product'} +
{intl l="ID"}{intl l="Reference"}{intl l="Product title"}{intl l="Actions"}
{$ID} + {loop type="image" name="cat_image" source="product" source_id="$ID" limit="1" width="50" height="50" resize_mode="crop" backend_context="1"} + + {$TITLE} + + {/loop} + + {$REF}{$TITLE} +
+ {loop type="auth" name="can_change" role="ADMIN" resource="admin.product" access="UPDATE"} + + {/loop} +
+
+
+
+ {* end product search *} + +
+
+ + {module_include location='modules_bottom'} + +
+
+ +{/block} + +{block name="javascript-initialization"} + + + +{/block} \ No newline at end of file diff --git a/templates/default/account.html b/templates/default/account.html index 50d37e7d3..100080768 100644 --- a/templates/default/account.html +++ b/templates/default/account.html @@ -58,7 +58,7 @@
  • - + {intl l="Change my password"}
  • diff --git a/templates/default/cart.html b/templates/default/cart.html index 8619b6e6b..36f4f110f 100644 --- a/templates/default/cart.html +++ b/templates/default/cart.html @@ -70,7 +70,7 @@ {/elseloop} -

    +

    {$TITLE}

    diff --git a/templates/default/layout.tpl b/templates/default/layout.tpl index 37d275aa9..6933dbb26 100644 --- a/templates/default/layout.tpl +++ b/templates/default/layout.tpl @@ -222,22 +222,29 @@ URL: http://www.thelia.net
    -

    Usefull links

    +

    {intl l="Usefull links"}

    -

    Follow us

    +

    {intl l="Follow us"}

    Lorem ipsum dolor sit amet, consectetur adipisicing elit.

      @@ -315,7 +322,7 @@ URL: http://www.thelia.net
      -

      Contact Us

      +

      {intl l="Contact Us"}

      diff --git a/templates/default/order-invoice.html b/templates/default/order-invoice.html index 9c17c15e6..54334647b 100644 --- a/templates/default/order-invoice.html +++ b/templates/default/order-invoice.html @@ -73,12 +73,11 @@ - {assign "cart_count" $LOOP_COUNT} {ifloop rel='product-image'} {loop type="image" name="product-image" product=$PRODUCT_ID limit="1" width="118" height="85" force_return="true"} - Product #{$cart_count} + Product #{$cart_count} {/loop} {/ifloop} {elseloop rel="product-image"} diff --git a/templates/pdf/invoice.html b/templates/pdf/invoice.html index 22e6d2760..828b5786c 100644 --- a/templates/pdf/invoice.html +++ b/templates/pdf/invoice.html @@ -91,7 +91,7 @@ {loop type="order_address" name="delivery_address" id=$DELIVERY_ADDRESS} {loop type="title" name="order-invoice-address-title" id=$TITLE}{$LONG}{/loop}{$FIRSTNAME} {$LASTNAME}
      {$ADDRESS1} {$ADDRESS2} {$ADDRESS3}
      - {$ZIPCODE} {$COUNTRY}
      + {$ZIPCODE} {$CITY}
      {loop type="country" name="country_delivery" id=$COUNTRY}{$TITLE}{/loop} {/loop} @@ -108,7 +108,7 @@ {loop type="order_address" name="delivery_address" id=$INVOICE_ADDRESS} {loop type="title" name="order-invoice-address-title" id=$TITLE}{$LONG}{/loop}{$FIRSTNAME} {$LASTNAME}
      {$ADDRESS1} {$ADDRESS2} {$ADDRESS3}
      - {$ZIPCODE} {$COUNTRY}
      + {$ZIPCODE} {$CITY}
      {loop type="country" name="country_delivery" id=$COUNTRY}{$TITLE}{/loop} {/loop} diff --git a/web/install/config.php b/web/install/config.php index ca937286c..f4e3c9896 100755 --- a/web/install/config.php +++ b/web/install/config.php @@ -96,6 +96,10 @@ $_SESSION['install']['step'] = $step;
      +
      + + +
      diff --git a/web/install/end.php b/web/install/end.php index 9113a8786..e10a18cb6 100755 --- a/web/install/end.php +++ b/web/install/end.php @@ -43,6 +43,10 @@ if($_SESSION['install']['step'] == 5) { \Thelia\Model\ConfigQuery::create() ->filterByName('company_name') ->update(array('Value' => $_POST['company_name'])); + + \Thelia\Model\ConfigQuery::create() + ->filterByName('url_site') + ->update(array('Value' => $_POST['url_site'])); } //clean up cache directories diff --git a/web/phpinfo.php b/web/phpinfo.php deleted file mode 100644 index e657e53d7..000000000 --- a/web/phpinfo.php +++ /dev/null @@ -1,10 +0,0 @@ - - */ - -phpinfo(); \ No newline at end of file