From e0079096dd0659193681eb55419df14cc4c45d8a Mon Sep 17 00:00:00 2001 From: Franck Allimant Date: Thu, 17 Apr 2014 18:57:04 +0200 Subject: [PATCH 01/18] Added the AbstractDeliveryModule class, and the isValidDelivery method. --- .../Thelia/Core/Template/Loop/Delivery.php | 217 +++++++++--------- .../Thelia/Module/AbstractDeliveryModule.php | 51 ++++ .../Thelia/Module/DeliveryModuleInterface.php | 19 +- 3 files changed, 178 insertions(+), 109 deletions(-) create mode 100644 core/lib/Thelia/Module/AbstractDeliveryModule.php diff --git a/core/lib/Thelia/Core/Template/Loop/Delivery.php b/core/lib/Thelia/Core/Template/Loop/Delivery.php index 2e7391c95..22ac946e7 100644 --- a/core/lib/Thelia/Core/Template/Loop/Delivery.php +++ b/core/lib/Thelia/Core/Template/Loop/Delivery.php @@ -1,106 +1,111 @@ -. */ -/* */ -/*************************************************************************************/ - -namespace Thelia\Core\Template\Loop; -use Thelia\Core\Template\Element\LoopResult; -use Thelia\Core\Template\Element\LoopResultRow; -use Thelia\Core\Template\Loop\Argument\Argument; -use Thelia\Exception\OrderException; -use Thelia\Model\CountryQuery; -use Thelia\Module\BaseModule; -use Thelia\Module\DeliveryModuleInterface; - -/** - * Class Delivery - * @package Thelia\Core\Template\Loop - * @author Manuel Raynaud - * @author Etienne Roudeix - */ -class Delivery extends BaseSpecificModule -{ - - public function getArgDefinitions() - { - $collection = parent::getArgDefinitions(); - - $collection->addArgument( - Argument::createIntTypeArgument("country") - ); - - return $collection; - } - - public function parseResults(LoopResult $loopResult) - { - $countryId = $this->getCountry(); - if (null !== $countryId) { - $country = CountryQuery::create()->findPk($countryId); - if (null === $country) { - throw new \InvalidArgumentException('Cannot found country id: `' . $countryId . '` in delivery loop'); - } - } else { - $country = $this->container->get('thelia.taxEngine')->getDeliveryCountry(); - } - - foreach ($loopResult->getResultDataCollection() as $deliveryModule) { - $loopResultRow = new LoopResultRow($deliveryModule); - - $moduleInstance = $this->container->get(sprintf('module.%s', $deliveryModule->getCode())); - - if (false === $moduleInstance instanceof DeliveryModuleInterface) { - throw new \RuntimeException(sprintf("delivery module %s is not a Thelia\Module\DeliveryModuleInterface", $deliveryModule->getCode())); - } - - try { - $postage = $moduleInstance->getPostage($country); - } catch (OrderException $e) { - switch ($e->getCode()) { - case OrderException::DELIVERY_MODULE_UNAVAILABLE: - /* do not show this delivery module */ - continue(2); - break; - default: - throw $e; - } - } - - $loopResultRow - ->set('ID', $deliveryModule->getId()) - ->set('TITLE', $deliveryModule->getVirtualColumn('i18n_TITLE')) - ->set('CHAPO', $deliveryModule->getVirtualColumn('i18n_CHAPO')) - ->set('DESCRIPTION', $deliveryModule->getVirtualColumn('i18n_DESCRIPTION')) - ->set('POSTSCRIPTUM', $deliveryModule->getVirtualColumn('i18n_POSTSCRIPTUM')) - ->set('POSTAGE', $postage) - ; - - $loopResult->addRow($loopResultRow); - } - - return $loopResult; - } - - protected function getModuleType() - { - return BaseModule::DELIVERY_MODULE_TYPE; - } -} +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Core\Template\Loop; +use Thelia\Core\Template\Element\LoopResult; +use Thelia\Core\Template\Element\LoopResultRow; +use Thelia\Core\Template\Loop\Argument\Argument; +use Thelia\Exception\OrderException; +use Thelia\Model\CountryQuery; +use Thelia\Model\Module; +use Thelia\Module\BaseModule; +use Thelia\Module\DeliveryModuleInterface; + +/** + * Class Delivery + * @package Thelia\Core\Template\Loop + * @author Manuel Raynaud + * @author Etienne Roudeix + */ +class Delivery extends BaseSpecificModule +{ + + public function getArgDefinitions() + { + $collection = parent::getArgDefinitions(); + + $collection->addArgument( + Argument::createIntTypeArgument("country") + ); + + return $collection; + } + + public function parseResults(LoopResult $loopResult) + { + $countryId = $this->getCountry(); + if (null !== $countryId) { + $country = CountryQuery::create()->findPk($countryId); + if (null === $country) { + throw new \InvalidArgumentException('Cannot found country id: `' . $countryId . '` in delivery loop'); + } + } else { + $country = $this->container->get('thelia.taxEngine')->getDeliveryCountry(); + } + + /** @var Module $deliveryModule */ + foreach ($loopResult->getResultDataCollection() as $deliveryModule) { + $loopResultRow = new LoopResultRow($deliveryModule); + + /** @var DeliveryModuleInterface $moduleInstance */ + $moduleInstance = $this->container->get(sprintf('module.%s', $deliveryModule->getCode())); + + if (false === $moduleInstance instanceof DeliveryModuleInterface) { + throw new \RuntimeException(sprintf("delivery module %s is not a Thelia\Module\DeliveryModuleInterface", $deliveryModule->getCode())); + } + + try { + // Check if module is valid, by calling isValidDelivery(), + // or catching a DELIVERY_MODULE_UNAVAILABLE OrderException. + + if ($moduleInstance->isValidDelivery($country)) { + + $postage = $moduleInstance->getPostage($country); + + $loopResultRow + ->set('ID', $deliveryModule->getId()) + ->set('TITLE', $deliveryModule->getVirtualColumn('i18n_TITLE')) + ->set('CHAPO', $deliveryModule->getVirtualColumn('i18n_CHAPO')) + ->set('DESCRIPTION', $deliveryModule->getVirtualColumn('i18n_DESCRIPTION')) + ->set('POSTSCRIPTUM', $deliveryModule->getVirtualColumn('i18n_POSTSCRIPTUM')) + ->set('POSTAGE', $postage) + ; + + $loopResult->addRow($loopResultRow); + } + } catch (OrderException $ex) { + // Re-throw an unknown exception + if ($ex->getCode() !== OrderException::DELIVERY_MODULE_UNAVAILABLE) { + throw $ex; + } + } + } + + return $loopResult; + } + + protected function getModuleType() + { + return BaseModule::DELIVERY_MODULE_TYPE; + } +} diff --git a/core/lib/Thelia/Module/AbstractDeliveryModule.php b/core/lib/Thelia/Module/AbstractDeliveryModule.php new file mode 100644 index 000000000..80c0072f2 --- /dev/null +++ b/core/lib/Thelia/Module/AbstractDeliveryModule.php @@ -0,0 +1,51 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Module; + +use Thelia\Model\Country; + +abstract class AbstractDeliveryModule extends BaseModule implements DeliveryModuleInterface +{ + /** + * This method is called by the Delivery loop, to check if the current module has to be displayed to the customer. + * Override it to implements your delivery rules/ + * + * If you return true, the delivery method will de displayed to the customer + * If you return false, the delivery method will not be displayed + * + * @param Country $country the country to deliver to. + * + * @return boolean + */ + public abstract function isValidDelivery(Country $country); + + /** + * Calculate and return delivery price in the shop's default currency + * + * @param Country $country the country to deliver to. + * + * @return float the delivery price + */ + public abstract function getPostage(Country $country); +} \ No newline at end of file diff --git a/core/lib/Thelia/Module/DeliveryModuleInterface.php b/core/lib/Thelia/Module/DeliveryModuleInterface.php index 17b000d4f..2cabd5f87 100644 --- a/core/lib/Thelia/Module/DeliveryModuleInterface.php +++ b/core/lib/Thelia/Module/DeliveryModuleInterface.php @@ -28,11 +28,24 @@ use Thelia\Model\Country; interface DeliveryModuleInterface extends BaseModuleInterface { /** - * calculate and return delivery price + * This method is called by the Delivery loop, to check if the current module has to be displayed to the customer. + * Override it to implements your delivery rules/ * - * @param Country $country + * If you return true, the delivery method will de displayed to the customer + * If you return false, the delivery method will not be displayed * - * @return mixed + * @param Country $country the country to deliver to. + * + * @return boolean + */ + public function isValidDelivery(Country $country); + + /** + * Calculate and return delivery price in the shop's default currency + * + * @param Country $country the country to deliver to. + * + * @return float the delivery price */ public function getPostage(Country $country); } From 70b70377684c4f5ea7e88b587d300a9a5d9ac962 Mon Sep 17 00:00:00 2001 From: Franck Allimant Date: Thu, 17 Apr 2014 18:58:23 +0200 Subject: [PATCH 02/18] Use of $this->getContainer() instead of $this->container --- core/lib/Thelia/Module/BaseModule.php | 28 +++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/core/lib/Thelia/Module/BaseModule.php b/core/lib/Thelia/Module/BaseModule.php index 7fc3a16f7..6390785ec 100644 --- a/core/lib/Thelia/Module/BaseModule.php +++ b/core/lib/Thelia/Module/BaseModule.php @@ -30,19 +30,19 @@ use Symfony\Component\DependencyInjection\ContainerAware; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\HttpFoundation\Request; use Thelia\Core\HttpFoundation\Session\Session; +use Thelia\Exception\ModuleException; use Thelia\Model\Cart; use Thelia\Model\Country; -use Thelia\Model\Map\ModuleTableMap; -use Thelia\Model\ModuleI18nQuery; use Thelia\Model\Map\ModuleImageTableMap; +use Thelia\Model\Map\ModuleTableMap; +use Thelia\Model\Module; use Thelia\Model\ModuleI18n; +use Thelia\Model\ModuleI18nQuery; +use Thelia\Model\ModuleImage; +use Thelia\Model\ModuleQuery; use Thelia\Model\Order; use Thelia\TaxEngine\TaxEngine; use Thelia\Tools\Image; -use Thelia\Exception\ModuleException; -use Thelia\Model\Module; -use Thelia\Model\ModuleImage; -use Thelia\Model\ModuleQuery; class BaseModule extends ContainerAware implements BaseModuleInterface { @@ -138,7 +138,7 @@ class BaseModule extends ContainerAware implements BaseModuleInterface { if ($this->hasRequest() === false) { // Try to get request from container. - $this->setRequest($this->container->get('request')); + $this->setRequest($this->getContainer()->get('request')); } if ($this->hasRequest() === false) { @@ -171,7 +171,7 @@ class BaseModule extends ContainerAware implements BaseModuleInterface * Sets a module titles for various languages * * @param Module $module the module. - * @param $titles an associative array of locale => title_string + * @param array $titles an associative array of locale => title_string */ public function setTitle(Module $module, $titles) { @@ -197,8 +197,7 @@ class BaseModule extends ContainerAware implements BaseModuleInterface /** * Ensure the proper deployment of the module's images. * - * TODO : clarify the purpose of ModuleImage. How this table will be used elswhere in Thelia ? - * TODO : this method doesn't take care of internationalization. This is a bug. + * TODO : this method does not take care of internationalization. This is a bug. * * @param Module $module the module * @param string $folderPath the image folder path @@ -223,6 +222,7 @@ class BaseModule extends ContainerAware implements BaseModuleInterface /* browse the directory */ $imagePosition = 1; + /** @var \DirectoryIterator $directoryContent */ foreach ($directoryBrowser as $directoryContent) { /* is it a file ? */ if ($directoryContent->isFile()) { @@ -347,7 +347,7 @@ class BaseModule extends ContainerAware implements BaseModuleInterface $order = $session->getOrder(); /** @var TaxEngine $taxEngine */ - $taxEngine = $this->container->get("thelia.taxengine"); + $taxEngine = $this->getContainer()->get("thelia.taxengine"); /** @var Country $country */ $country = $taxEngine->getDeliveryCountry(); @@ -363,7 +363,7 @@ class BaseModule extends ContainerAware implements BaseModuleInterface /** * - * This method allow adding new compilers to Thelia container + * This method adds new compilers to Thelia container * * You must return an array. This array can contain : * - arrays @@ -409,7 +409,7 @@ class BaseModule extends ContainerAware implements BaseModuleInterface */ public function install(ConnectionInterface $con = null) { - // Implement this method to do something useful. + // Override this method to do something useful. } /** @@ -463,4 +463,4 @@ class BaseModule extends ContainerAware implements BaseModuleInterface { // Override this method to do something useful. } -} +} \ No newline at end of file From 61fc6720fd83d089ac78a3e34e97854679101624 Mon Sep 17 00:00:00 2001 From: Franck Allimant Date: Thu, 17 Apr 2014 18:59:59 +0200 Subject: [PATCH 03/18] Fixed typo in function names (payEment -> payment) --- core/lib/Thelia/Module/AbstractPaymentModule.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/core/lib/Thelia/Module/AbstractPaymentModule.php b/core/lib/Thelia/Module/AbstractPaymentModule.php index 7936dee16..5c2e4cec8 100644 --- a/core/lib/Thelia/Module/AbstractPaymentModule.php +++ b/core/lib/Thelia/Module/AbstractPaymentModule.php @@ -33,7 +33,7 @@ use Thelia\Tools\URL; abstract class AbstractPaymentModule extends BaseModule implements PaymentModuleInterface { /** - * This method is called when the payement gateway needs to be invoked. + * This method is called when the payment gateway needs to be invoked. * * If this method return a Response instance, this response is sent to the browser. Return null if you don't want to * send a response and process the payment yourself. @@ -91,9 +91,9 @@ abstract class AbstractPaymentModule extends BaseModule implements PaymentModule * @param int $order_id the order ID * @return string the order payment success page URL */ - public function getPayementSuccessPageUrl($order_id) + public function getPaymentSuccessPageUrl($order_id) { - $frontOfficeRouter = $this->container->get('router.front'); + $frontOfficeRouter = $this->getContainer()->get('router.front'); return URL::getInstance()->absoluteUrl( $frontOfficeRouter->generate( @@ -112,9 +112,9 @@ abstract class AbstractPaymentModule extends BaseModule implements PaymentModule * * @return string the order payment failure page URL */ - public function getPayementFailurePageUrl($order_id, $message) + public function getPaymentFailurePageUrl($order_id, $message) { - $frontOfficeRouter = $this->container->get('router.front'); + $frontOfficeRouter = $this->getContainer()->get('router.front'); return URL::getInstance()->absoluteUrl( $frontOfficeRouter->generate( @@ -127,4 +127,4 @@ abstract class AbstractPaymentModule extends BaseModule implements PaymentModule ) ); } -} +} \ No newline at end of file From 12c21b1239115300e6c83a7eb08c82f896ed61f7 Mon Sep 17 00:00:00 2001 From: Franck Allimant Date: Thu, 17 Apr 2014 19:46:21 +0200 Subject: [PATCH 04/18] Fixes #308 --- core/lib/Thelia/Action/Order.php | 1015 +++++++++-------- .../Thelia/Core/Template/Loop/Delivery.php | 10 +- .../Thelia/Module/AbstractDeliveryModule.php | 2 + .../Thelia/Module/DeliveryModuleInterface.php | 2 + local/modules/Colissimo/Colissimo.php | 93 +- .../Front/Controller/CartController.php | 358 +++--- .../Front/Controller/CouponController.php | 224 ++-- 7 files changed, 871 insertions(+), 833 deletions(-) diff --git a/core/lib/Thelia/Action/Order.php b/core/lib/Thelia/Action/Order.php index a8a8d5af9..78534b268 100644 --- a/core/lib/Thelia/Action/Order.php +++ b/core/lib/Thelia/Action/Order.php @@ -1,504 +1,511 @@ -. */ -/* */ -/*************************************************************************************/ - -namespace Thelia\Action; - -use Symfony\Component\EventDispatcher\EventDispatcherInterface; -use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Thelia\Cart\CartTrait; -use Thelia\Core\Event\Order\OrderAddressEvent; -use Thelia\Core\Event\Order\OrderEvent; -use Thelia\Core\Event\Order\OrderManualEvent; -use Thelia\Core\Event\Order\OrderPaymentEvent; -use Thelia\Core\Event\TheliaEvents; -use Thelia\Core\HttpFoundation\Request; -use Thelia\Core\Security\SecurityContext; -use Thelia\Core\Template\ParserInterface; -use Thelia\Exception\TheliaProcessException; -use Thelia\Mailer\MailerFactory; -use Thelia\Model\AddressQuery; -use Thelia\Model\Cart as CartModel; -use Thelia\Model\ConfigQuery; -use Thelia\Model\Currency as CurrencyModel; -use Thelia\Model\Customer as CustomerModel; -use Thelia\Model\Lang as LangModel; -use Thelia\Model\Map\OrderTableMap; -use Thelia\Model\MessageQuery; -use Thelia\Model\Order as ModelOrder; -use Thelia\Model\OrderAddress; -use Thelia\Model\OrderProduct; -use Thelia\Model\OrderProductAttributeCombination; -use Thelia\Model\OrderStatus; -use Thelia\Model\OrderStatusQuery; -use Thelia\Tools\I18n; - -/** - * - * Class Order - * @package Thelia\Action - * @author Etienne Roudeix - */ -class Order extends BaseAction implements EventSubscriberInterface -{ - use CartTrait; - - /** - * @var \Thelia\Core\HttpFoundation\Request - */ - protected $request; - /** - * @var MailerFactory - */ - protected $mailer; - /** - * @var ParserInterface - */ - protected $parser; - /** - * @var SecurityContext - */ - protected $securityContext; - - public function __construct(Request $request, ParserInterface $parser, MailerFactory $mailer, SecurityContext $securityContext) - { - $this->request = $request; - $this->parser = $parser; - $this->mailer = $mailer; - $this->securityContext = $securityContext; - } - - /** - * @param \Thelia\Core\Event\Order\OrderEvent $event - */ - public function setDeliveryAddress(OrderEvent $event) - { - $order = $event->getOrder(); - - $order->chosenDeliveryAddress = $event->getDeliveryAddress(); - - $event->setOrder($order); - } - - /** - * @param \Thelia\Core\Event\Order\OrderEvent $event - */ - public function setDeliveryModule(OrderEvent $event) - { - $order = $event->getOrder(); - - $order->setDeliveryModuleId($event->getDeliveryModule()); - - $event->setOrder($order); - } - - /** - * @param \Thelia\Core\Event\Order\OrderEvent $event - */ - public function setPostage(OrderEvent $event) - { - $order = $event->getOrder(); - - $order->setPostage($event->getPostage()); - - $event->setOrder($order); - } - - /** - * @param \Thelia\Core\Event\Order\OrderEvent $event - */ - public function setInvoiceAddress(OrderEvent $event) - { - $order = $event->getOrder(); - - $order->chosenInvoiceAddress = $event->getInvoiceAddress(); - - $event->setOrder($order); - } - - /** - * @param \Thelia\Core\Event\Order\OrderEvent $event - */ - public function setPaymentModule(OrderEvent $event) - { - $order = $event->getOrder(); - - $order->setPaymentModuleId($event->getPaymentModule()); - - $event->setOrder($order); - } - - protected function createOrder(EventDispatcherInterface $dispatcher, ModelOrder $sessionOrder, CurrencyModel $currency, LangModel $lang, CartModel $cart, CustomerModel $customer) - { - $con = \Propel\Runtime\Propel::getConnection( - OrderTableMap::DATABASE_NAME - ); - - $con->beginTransaction(); - - $placedOrder = $sessionOrder->copy(); - $placedOrder->setDispatcher($dispatcher); - - $deliveryAddress = AddressQuery::create()->findPk($sessionOrder->chosenDeliveryAddress); - $taxCountry = $deliveryAddress->getCountry(); - $invoiceAddress = AddressQuery::create()->findPk($sessionOrder->chosenInvoiceAddress); - $cartItems = $cart->getCartItems(); - - /* fulfill order */ - $placedOrder->setCustomerId($customer->getId()); - $placedOrder->setCurrencyId($currency->getId()); - $placedOrder->setCurrencyRate($currency->getRate()); - $placedOrder->setLangId($lang->getId()); - - /* hard save the delivery and invoice addresses */ - $deliveryOrderAddress = new OrderAddress(); - $deliveryOrderAddress - ->setCustomerTitleId($deliveryAddress->getTitleId()) - ->setCompany($deliveryAddress->getCompany()) - ->setFirstname($deliveryAddress->getFirstname()) - ->setLastname($deliveryAddress->getLastname()) - ->setAddress1($deliveryAddress->getAddress1()) - ->setAddress2($deliveryAddress->getAddress2()) - ->setAddress3($deliveryAddress->getAddress3()) - ->setZipcode($deliveryAddress->getZipcode()) - ->setCity($deliveryAddress->getCity()) - ->setPhone($deliveryAddress->getPhone()) - ->setCountryId($deliveryAddress->getCountryId()) - ->save($con) - ; - - $invoiceOrderAddress = new OrderAddress(); - $invoiceOrderAddress - ->setCustomerTitleId($invoiceAddress->getTitleId()) - ->setCompany($invoiceAddress->getCompany()) - ->setFirstname($invoiceAddress->getFirstname()) - ->setLastname($invoiceAddress->getLastname()) - ->setAddress1($invoiceAddress->getAddress1()) - ->setAddress2($invoiceAddress->getAddress2()) - ->setAddress3($invoiceAddress->getAddress3()) - ->setZipcode($invoiceAddress->getZipcode()) - ->setCity($invoiceAddress->getCity()) - ->setPhone($invoiceAddress->getPhone()) - ->setCountryId($invoiceAddress->getCountryId()) - ->save($con) - ; - - $placedOrder->setDeliveryOrderAddressId($deliveryOrderAddress->getId()); - $placedOrder->setInvoiceOrderAddressId($invoiceOrderAddress->getId()); - - $placedOrder->setStatusId( - OrderStatusQuery::getNotPaidStatus()->getId() - ); - - /* memorize discount */ - $placedOrder->setDiscount( - $cart->getDiscount() - ); - - $placedOrder->save($con); - - /* fulfill order_products and decrease stock */ - - foreach ($cartItems as $cartItem) { - $product = $cartItem->getProduct(); - - /* get translation */ - $productI18n = I18n::forceI18nRetrieving($lang->getLocale(), 'Product', $product->getId()); - - $pse = $cartItem->getProductSaleElements(); - - /* check still in stock */ - if ($cartItem->getQuantity() > $pse->getQuantity()) { - throw new TheliaProcessException("Not enough stock", TheliaProcessException::CART_ITEM_NOT_ENOUGH_STOCK, $cartItem); - } - - /* decrease stock */ - $pse->setQuantity( - $pse->getQuantity() - $cartItem->getQuantity() - ); - $pse->save($con); - - /* get tax */ - $taxRuleI18n = I18n::forceI18nRetrieving($lang->getLocale(), 'TaxRule', $product->getTaxRuleId()); - - $taxDetail = $product->getTaxRule()->getTaxDetail( - $product, - $taxCountry, - $cartItem->getPrice(), - $cartItem->getPromoPrice(), - $lang->getLocale() - ); - - $orderProduct = new OrderProduct(); - $orderProduct - ->setOrderId($placedOrder->getId()) - ->setProductRef($product->getRef()) - ->setProductSaleElementsRef($pse->getRef()) - ->setTitle($productI18n->getTitle()) - ->setChapo($productI18n->getChapo()) - ->setDescription($productI18n->getDescription()) - ->setPostscriptum($productI18n->getPostscriptum()) - ->setQuantity($cartItem->getQuantity()) - ->setPrice($cartItem->getPrice()) - ->setPromoPrice($cartItem->getPromoPrice()) - ->setWasNew($pse->getNewness()) - ->setWasInPromo($cartItem->getPromo()) - ->setWeight($pse->getWeight()) - ->setTaxRuleTitle($taxRuleI18n->getTitle()) - ->setTaxRuleDescription($taxRuleI18n->getDescription()) - ->setEanCode($pse->getEanCode()) - ->setCartIemId($cartItem->getId()) - ->setDispatcher($dispatcher) - ->save($con) - ; - - /* fulfill order_product_tax */ - foreach ($taxDetail as $tax) { - $tax->setOrderProductId($orderProduct->getId()); - $tax->save($con); - } - - /* fulfill order_attribute_combination and decrease stock */ - foreach ($pse->getAttributeCombinations() as $attributeCombination) { - $attribute = I18n::forceI18nRetrieving($lang->getLocale(), 'Attribute', $attributeCombination->getAttributeId()); - $attributeAv = I18n::forceI18nRetrieving($lang->getLocale(), 'AttributeAv', $attributeCombination->getAttributeAvId()); - - $orderAttributeCombination = new OrderProductAttributeCombination(); - $orderAttributeCombination - ->setOrderProductId($orderProduct->getId()) - ->setAttributeTitle($attribute->getTitle()) - ->setAttributeChapo($attribute->getChapo()) - ->setAttributeDescription($attribute->getDescription()) - ->setAttributePostscriptum($attribute->getPostscriptum()) - ->setAttributeAvTitle($attributeAv->getTitle()) - ->setAttributeAvChapo($attributeAv->getChapo()) - ->setAttributeAvDescription($attributeAv->getDescription()) - ->setAttributeAvPostscriptum($attributeAv->getPostscriptum()) - ->save($con); - } - } - - $con->commit(); - - return $placedOrder; - } - - /** - * Create an order outside of the front-office context, e.g. manually from the back-office. - */ - public function createManual(OrderManualEvent $event) - { - $placedOrder = $this->createOrder( - $event->getDispatcher(), - $event->getOrder(), - $event->getCurrency(), - $event->getLang(), - $event->getCart(), - $event->getCustomer() - ); - } - - /** - * @param OrderEvent $event - * - * @throws \Thelia\Exception\TheliaProcessException - */ - public function create(OrderEvent $event) - { - $session = $this->getSession(); - - $placedOrder = $this->createOrder( - $event->getDispatcher(), - $event->getOrder(), - $session->getCurrency(), - $session->getLang(), - $session->getCart(), - $this->securityContext->getCustomerUser() - ); - - $event->getDispatcher()->dispatch(TheliaEvents::ORDER_BEFORE_PAYMENT, new OrderEvent($placedOrder)); - - /* but memorize placed order */ - $event->setOrder(new \Thelia\Model\Order()); - $event->setPlacedOrder($placedOrder); - - /* empty cart */ - $dispatcher = $event->getDispatcher(); - - /* call pay method */ - $payEvent = new OrderPaymentEvent($placedOrder); - - $dispatcher->dispatch(TheliaEvents::MODULE_PAY, $payEvent); - - if ($payEvent->hasResponse()) { - $event->setResponse($payEvent->getResponse()); - } - } - - /** - * @param \Thelia\Core\Event\Order\OrderEvent $event - */ - public function sendOrderEmail(OrderEvent $event) - { - $contact_email = ConfigQuery::read('store_email'); - - if ($contact_email) { - - $message = MessageQuery::create() - ->filterByName('order_confirmation') - ->findOne(); - - if (false === $message) { - throw new \Exception("Failed to load message 'order_confirmation'."); - } - - $order = $event->getOrder(); - $customer = $order->getCustomer(); - - $this->parser->assign('order_id', $order->getId()); - $this->parser->assign('order_ref', $order->getRef()); - - $message - ->setLocale($order->getLang()->getLocale()); - - $instance = \Swift_Message::newInstance() - ->addTo($customer->getEmail(), $customer->getFirstname()." ".$customer->getLastname()) - ->addFrom($contact_email, ConfigQuery::read('store_name')) - ; - - // Build subject and body - - $message->buildMessage($this->parser, $instance); - - $this->getMailer()->send($instance); - } - } - - /** - * - * return an instance of \Swift_Mailer with good Transporter configured. - * - * @return \Swift_Mailer - */ - public function getMailer() - { - return $this->mailer->getSwiftMailer(); - } - - /** - * @param OrderEvent $event - */ - public function updateStatus(OrderEvent $event) - { - $order = $event->getOrder(); - - $order->setStatusId($event->getStatus()); - $order->save(); - - $event->setOrder($order); - } - - /** - * @param OrderEvent $event - */ - public function updateDeliveryRef(OrderEvent $event) - { - $order = $event->getOrder(); - - $order->setDeliveryRef($event->getDeliveryRef()); - $order->save(); - - $event->setOrder($order); - } - - /** - * @param OrderAddressEvent $event - */ - public function updateAddress(OrderAddressEvent $event) - { - $orderAddress = $event->getOrderAddress(); - - $orderAddress - ->setCustomerTitleId($event->getTitle()) - ->setCompany($event->getCompany()) - ->setFirstname($event->getFirstname()) - ->setLastname($event->getLastname()) - ->setAddress1($event->getAddress1()) - ->setAddress2($event->getAddress2()) - ->setAddress3($event->getAddress3()) - ->setZipcode($event->getZipcode()) - ->setCity($event->getCity()) - ->setCountryId($event->getCountry()) - ->setPhone($event->getPhone()) - ; - $orderAddress->save(); - - $event->setOrderAddress($orderAddress); - } - - /** - * Returns an array of event names this subscriber wants to listen to. - * - * The array keys are event names and the value can be: - * - * * The method name to call (priority defaults to 0) - * * An array composed of the method name to call and the priority - * * An array of arrays composed of the method names to call and respective - * priorities, or 0 if unset - * - * For instance: - * - * * array('eventName' => 'methodName') - * * array('eventName' => array('methodName', $priority)) - * * array('eventName' => array(array('methodName1', $priority), array('methodName2')) - * - * @return array The event names to listen to - * - * @api - */ - public static function getSubscribedEvents() - { - return array( - TheliaEvents::ORDER_SET_DELIVERY_ADDRESS => array("setDeliveryAddress", 128), - TheliaEvents::ORDER_SET_DELIVERY_MODULE => array("setDeliveryModule", 128), - TheliaEvents::ORDER_SET_POSTAGE => array("setPostage", 128), - TheliaEvents::ORDER_SET_INVOICE_ADDRESS => array("setInvoiceAddress", 128), - TheliaEvents::ORDER_SET_PAYMENT_MODULE => array("setPaymentModule", 128), - TheliaEvents::ORDER_PAY => array("create", 128), - TheliaEvents::ORDER_BEFORE_PAYMENT => array("sendOrderEmail", 128), - TheliaEvents::ORDER_UPDATE_STATUS => array("updateStatus", 128), - TheliaEvents::ORDER_UPDATE_DELIVERY_REF => array("updateDeliveryRef", 128), - TheliaEvents::ORDER_UPDATE_ADDRESS => array("updateAddress", 128), - TheliaEvents::ORDER_CREATE_MANUAL => array("createManual", 128), - ); - } - - /** - * Returns the session from the current request - * - * @return \Thelia\Core\HttpFoundation\Session\Session - */ - protected function getSession() - { - return $this->request->getSession(); - } -} +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Action; + +use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Thelia\Cart\CartTrait; +use Thelia\Core\Event\Order\OrderAddressEvent; +use Thelia\Core\Event\Order\OrderEvent; +use Thelia\Core\Event\Order\OrderManualEvent; +use Thelia\Core\Event\Order\OrderPaymentEvent; +use Thelia\Core\Event\TheliaEvents; +use Thelia\Core\HttpFoundation\Request; +use Thelia\Core\Security\SecurityContext; +use Thelia\Core\Template\ParserInterface; +use Thelia\Exception\TheliaProcessException; +use Thelia\Mailer\MailerFactory; +use Thelia\Model\AddressQuery; +use Thelia\Model\Cart as CartModel; +use Thelia\Model\ConfigQuery; +use Thelia\Model\Currency as CurrencyModel; +use Thelia\Model\Customer as CustomerModel; +use Thelia\Model\Lang as LangModel; +use Thelia\Model\Map\OrderTableMap; +use Thelia\Model\MessageQuery; +use Thelia\Model\Order as ModelOrder; +use Thelia\Model\OrderAddress; +use Thelia\Model\OrderProduct; +use Thelia\Model\OrderProductAttributeCombination; +use Thelia\Model\OrderStatus; +use Thelia\Model\OrderStatusQuery; +use Thelia\Tools\I18n; + +/** + * + * Class Order + * @package Thelia\Action + * @author Etienne Roudeix + */ +class Order extends BaseAction implements EventSubscriberInterface +{ + use CartTrait; + + /** + * @var \Thelia\Core\HttpFoundation\Request + */ + protected $request; + /** + * @var MailerFactory + */ + protected $mailer; + /** + * @var ParserInterface + */ + protected $parser; + /** + * @var SecurityContext + */ + protected $securityContext; + + public function __construct(Request $request, ParserInterface $parser, MailerFactory $mailer, SecurityContext $securityContext) + { + $this->request = $request; + $this->parser = $parser; + $this->mailer = $mailer; + $this->securityContext = $securityContext; + } + + /** + * @param \Thelia\Core\Event\Order\OrderEvent $event + */ + public function setDeliveryAddress(OrderEvent $event) + { + $order = $event->getOrder(); + + $order->chosenDeliveryAddress = $event->getDeliveryAddress(); + + $event->setOrder($order); + } + + /** + * @param \Thelia\Core\Event\Order\OrderEvent $event + */ + public function setDeliveryModule(OrderEvent $event) + { + $order = $event->getOrder(); + + $deliveryModuleId = $event->getDeliveryModule(); + + $order->setDeliveryModuleId($deliveryModuleId); + + // Reset postage cost if the delivery module had been removed + if ($deliveryModuleId <= 0) { + $this->setPostage(0); + } + + $event->setOrder($order); + } + + /** + * @param \Thelia\Core\Event\Order\OrderEvent $event + */ + public function setPostage(OrderEvent $event) + { + $order = $event->getOrder(); + + $order->setPostage($event->getPostage()); + + $event->setOrder($order); + } + + /** + * @param \Thelia\Core\Event\Order\OrderEvent $event + */ + public function setInvoiceAddress(OrderEvent $event) + { + $order = $event->getOrder(); + + $order->chosenInvoiceAddress = $event->getInvoiceAddress(); + + $event->setOrder($order); + } + + /** + * @param \Thelia\Core\Event\Order\OrderEvent $event + */ + public function setPaymentModule(OrderEvent $event) + { + $order = $event->getOrder(); + + $order->setPaymentModuleId($event->getPaymentModule()); + + $event->setOrder($order); + } + + protected function createOrder(EventDispatcherInterface $dispatcher, ModelOrder $sessionOrder, CurrencyModel $currency, LangModel $lang, CartModel $cart, CustomerModel $customer) + { + $con = \Propel\Runtime\Propel::getConnection( + OrderTableMap::DATABASE_NAME + ); + + $con->beginTransaction(); + + $placedOrder = $sessionOrder->copy(); + $placedOrder->setDispatcher($dispatcher); + + $deliveryAddress = AddressQuery::create()->findPk($sessionOrder->chosenDeliveryAddress); + $taxCountry = $deliveryAddress->getCountry(); + $invoiceAddress = AddressQuery::create()->findPk($sessionOrder->chosenInvoiceAddress); + $cartItems = $cart->getCartItems(); + + /* fulfill order */ + $placedOrder->setCustomerId($customer->getId()); + $placedOrder->setCurrencyId($currency->getId()); + $placedOrder->setCurrencyRate($currency->getRate()); + $placedOrder->setLangId($lang->getId()); + + /* hard save the delivery and invoice addresses */ + $deliveryOrderAddress = new OrderAddress(); + $deliveryOrderAddress + ->setCustomerTitleId($deliveryAddress->getTitleId()) + ->setCompany($deliveryAddress->getCompany()) + ->setFirstname($deliveryAddress->getFirstname()) + ->setLastname($deliveryAddress->getLastname()) + ->setAddress1($deliveryAddress->getAddress1()) + ->setAddress2($deliveryAddress->getAddress2()) + ->setAddress3($deliveryAddress->getAddress3()) + ->setZipcode($deliveryAddress->getZipcode()) + ->setCity($deliveryAddress->getCity()) + ->setPhone($deliveryAddress->getPhone()) + ->setCountryId($deliveryAddress->getCountryId()) + ->save($con) + ; + + $invoiceOrderAddress = new OrderAddress(); + $invoiceOrderAddress + ->setCustomerTitleId($invoiceAddress->getTitleId()) + ->setCompany($invoiceAddress->getCompany()) + ->setFirstname($invoiceAddress->getFirstname()) + ->setLastname($invoiceAddress->getLastname()) + ->setAddress1($invoiceAddress->getAddress1()) + ->setAddress2($invoiceAddress->getAddress2()) + ->setAddress3($invoiceAddress->getAddress3()) + ->setZipcode($invoiceAddress->getZipcode()) + ->setCity($invoiceAddress->getCity()) + ->setPhone($invoiceAddress->getPhone()) + ->setCountryId($invoiceAddress->getCountryId()) + ->save($con) + ; + + $placedOrder->setDeliveryOrderAddressId($deliveryOrderAddress->getId()); + $placedOrder->setInvoiceOrderAddressId($invoiceOrderAddress->getId()); + + $placedOrder->setStatusId( + OrderStatusQuery::getNotPaidStatus()->getId() + ); + + /* memorize discount */ + $placedOrder->setDiscount( + $cart->getDiscount() + ); + + $placedOrder->save($con); + + /* fulfill order_products and decrease stock */ + + foreach ($cartItems as $cartItem) { + $product = $cartItem->getProduct(); + + /* get translation */ + $productI18n = I18n::forceI18nRetrieving($lang->getLocale(), 'Product', $product->getId()); + + $pse = $cartItem->getProductSaleElements(); + + /* check still in stock */ + if ($cartItem->getQuantity() > $pse->getQuantity()) { + throw new TheliaProcessException("Not enough stock", TheliaProcessException::CART_ITEM_NOT_ENOUGH_STOCK, $cartItem); + } + + /* decrease stock */ + $pse->setQuantity( + $pse->getQuantity() - $cartItem->getQuantity() + ); + $pse->save($con); + + /* get tax */ + $taxRuleI18n = I18n::forceI18nRetrieving($lang->getLocale(), 'TaxRule', $product->getTaxRuleId()); + + $taxDetail = $product->getTaxRule()->getTaxDetail( + $product, + $taxCountry, + $cartItem->getPrice(), + $cartItem->getPromoPrice(), + $lang->getLocale() + ); + + $orderProduct = new OrderProduct(); + $orderProduct + ->setOrderId($placedOrder->getId()) + ->setProductRef($product->getRef()) + ->setProductSaleElementsRef($pse->getRef()) + ->setTitle($productI18n->getTitle()) + ->setChapo($productI18n->getChapo()) + ->setDescription($productI18n->getDescription()) + ->setPostscriptum($productI18n->getPostscriptum()) + ->setQuantity($cartItem->getQuantity()) + ->setPrice($cartItem->getPrice()) + ->setPromoPrice($cartItem->getPromoPrice()) + ->setWasNew($pse->getNewness()) + ->setWasInPromo($cartItem->getPromo()) + ->setWeight($pse->getWeight()) + ->setTaxRuleTitle($taxRuleI18n->getTitle()) + ->setTaxRuleDescription($taxRuleI18n->getDescription()) + ->setEanCode($pse->getEanCode()) + ->setCartIemId($cartItem->getId()) + ->setDispatcher($dispatcher) + ->save($con) + ; + + /* fulfill order_product_tax */ + foreach ($taxDetail as $tax) { + $tax->setOrderProductId($orderProduct->getId()); + $tax->save($con); + } + + /* fulfill order_attribute_combination and decrease stock */ + foreach ($pse->getAttributeCombinations() as $attributeCombination) { + $attribute = I18n::forceI18nRetrieving($lang->getLocale(), 'Attribute', $attributeCombination->getAttributeId()); + $attributeAv = I18n::forceI18nRetrieving($lang->getLocale(), 'AttributeAv', $attributeCombination->getAttributeAvId()); + + $orderAttributeCombination = new OrderProductAttributeCombination(); + $orderAttributeCombination + ->setOrderProductId($orderProduct->getId()) + ->setAttributeTitle($attribute->getTitle()) + ->setAttributeChapo($attribute->getChapo()) + ->setAttributeDescription($attribute->getDescription()) + ->setAttributePostscriptum($attribute->getPostscriptum()) + ->setAttributeAvTitle($attributeAv->getTitle()) + ->setAttributeAvChapo($attributeAv->getChapo()) + ->setAttributeAvDescription($attributeAv->getDescription()) + ->setAttributeAvPostscriptum($attributeAv->getPostscriptum()) + ->save($con); + } + } + + $con->commit(); + + return $placedOrder; + } + + /** + * Create an order outside of the front-office context, e.g. manually from the back-office. + */ + public function createManual(OrderManualEvent $event) + { + $placedOrder = $this->createOrder( + $event->getDispatcher(), + $event->getOrder(), + $event->getCurrency(), + $event->getLang(), + $event->getCart(), + $event->getCustomer() + ); + } + + /** + * @param OrderEvent $event + * + * @throws \Thelia\Exception\TheliaProcessException + */ + public function create(OrderEvent $event) + { + $session = $this->getSession(); + + $placedOrder = $this->createOrder( + $event->getDispatcher(), + $event->getOrder(), + $session->getCurrency(), + $session->getLang(), + $session->getCart(), + $this->securityContext->getCustomerUser() + ); + + $event->getDispatcher()->dispatch(TheliaEvents::ORDER_BEFORE_PAYMENT, new OrderEvent($placedOrder)); + + /* but memorize placed order */ + $event->setOrder(new \Thelia\Model\Order()); + $event->setPlacedOrder($placedOrder); + + /* empty cart */ + $dispatcher = $event->getDispatcher(); + + /* call pay method */ + $payEvent = new OrderPaymentEvent($placedOrder); + + $dispatcher->dispatch(TheliaEvents::MODULE_PAY, $payEvent); + + if ($payEvent->hasResponse()) { + $event->setResponse($payEvent->getResponse()); + } + } + + /** + * @param \Thelia\Core\Event\Order\OrderEvent $event + */ + public function sendOrderEmail(OrderEvent $event) + { + $contact_email = ConfigQuery::read('store_email'); + + if ($contact_email) { + + $message = MessageQuery::create() + ->filterByName('order_confirmation') + ->findOne(); + + if (false === $message) { + throw new \Exception("Failed to load message 'order_confirmation'."); + } + + $order = $event->getOrder(); + $customer = $order->getCustomer(); + + $this->parser->assign('order_id', $order->getId()); + $this->parser->assign('order_ref', $order->getRef()); + + $message + ->setLocale($order->getLang()->getLocale()); + + $instance = \Swift_Message::newInstance() + ->addTo($customer->getEmail(), $customer->getFirstname()." ".$customer->getLastname()) + ->addFrom($contact_email, ConfigQuery::read('store_name')) + ; + + // Build subject and body + + $message->buildMessage($this->parser, $instance); + + $this->getMailer()->send($instance); + } + } + + /** + * + * return an instance of \Swift_Mailer with good Transporter configured. + * + * @return \Swift_Mailer + */ + public function getMailer() + { + return $this->mailer->getSwiftMailer(); + } + + /** + * @param OrderEvent $event + */ + public function updateStatus(OrderEvent $event) + { + $order = $event->getOrder(); + + $order->setStatusId($event->getStatus()); + $order->save(); + + $event->setOrder($order); + } + + /** + * @param OrderEvent $event + */ + public function updateDeliveryRef(OrderEvent $event) + { + $order = $event->getOrder(); + + $order->setDeliveryRef($event->getDeliveryRef()); + $order->save(); + + $event->setOrder($order); + } + + /** + * @param OrderAddressEvent $event + */ + public function updateAddress(OrderAddressEvent $event) + { + $orderAddress = $event->getOrderAddress(); + + $orderAddress + ->setCustomerTitleId($event->getTitle()) + ->setCompany($event->getCompany()) + ->setFirstname($event->getFirstname()) + ->setLastname($event->getLastname()) + ->setAddress1($event->getAddress1()) + ->setAddress2($event->getAddress2()) + ->setAddress3($event->getAddress3()) + ->setZipcode($event->getZipcode()) + ->setCity($event->getCity()) + ->setCountryId($event->getCountry()) + ->setPhone($event->getPhone()) + ; + $orderAddress->save(); + + $event->setOrderAddress($orderAddress); + } + + /** + * Returns an array of event names this subscriber wants to listen to. + * + * The array keys are event names and the value can be: + * + * * The method name to call (priority defaults to 0) + * * An array composed of the method name to call and the priority + * * An array of arrays composed of the method names to call and respective + * priorities, or 0 if unset + * + * For instance: + * + * * array('eventName' => 'methodName') + * * array('eventName' => array('methodName', $priority)) + * * array('eventName' => array(array('methodName1', $priority), array('methodName2')) + * + * @return array The event names to listen to + * + * @api + */ + public static function getSubscribedEvents() + { + return array( + TheliaEvents::ORDER_SET_DELIVERY_ADDRESS => array("setDeliveryAddress", 128), + TheliaEvents::ORDER_SET_DELIVERY_MODULE => array("setDeliveryModule", 128), + TheliaEvents::ORDER_SET_POSTAGE => array("setPostage", 128), + TheliaEvents::ORDER_SET_INVOICE_ADDRESS => array("setInvoiceAddress", 128), + TheliaEvents::ORDER_SET_PAYMENT_MODULE => array("setPaymentModule", 128), + TheliaEvents::ORDER_PAY => array("create", 128), + TheliaEvents::ORDER_BEFORE_PAYMENT => array("sendOrderEmail", 128), + TheliaEvents::ORDER_UPDATE_STATUS => array("updateStatus", 128), + TheliaEvents::ORDER_UPDATE_DELIVERY_REF => array("updateDeliveryRef", 128), + TheliaEvents::ORDER_UPDATE_ADDRESS => array("updateAddress", 128), + TheliaEvents::ORDER_CREATE_MANUAL => array("createManual", 128), + ); + } + + /** + * Returns the session from the current request + * + * @return \Thelia\Core\HttpFoundation\Session\Session + */ + protected function getSession() + { + return $this->request->getSession(); + } +} diff --git a/core/lib/Thelia/Core/Template/Loop/Delivery.php b/core/lib/Thelia/Core/Template/Loop/Delivery.php index 22ac946e7..a379f9c3a 100644 --- a/core/lib/Thelia/Core/Template/Loop/Delivery.php +++ b/core/lib/Thelia/Core/Template/Loop/Delivery.php @@ -30,6 +30,7 @@ use Thelia\Model\CountryQuery; use Thelia\Model\Module; use Thelia\Module\BaseModule; use Thelia\Module\DeliveryModuleInterface; +use Thelia\Module\Exception\DeliveryException; /** * Class Delivery @@ -76,7 +77,7 @@ class Delivery extends BaseSpecificModule try { // Check if module is valid, by calling isValidDelivery(), - // or catching a DELIVERY_MODULE_UNAVAILABLE OrderException. + // or catching a DeliveryException. if ($moduleInstance->isValidDelivery($country)) { @@ -93,11 +94,8 @@ class Delivery extends BaseSpecificModule $loopResult->addRow($loopResultRow); } - } catch (OrderException $ex) { - // Re-throw an unknown exception - if ($ex->getCode() !== OrderException::DELIVERY_MODULE_UNAVAILABLE) { - throw $ex; - } + } catch (DeliveryException $ex) { + // Module is not available } } diff --git a/core/lib/Thelia/Module/AbstractDeliveryModule.php b/core/lib/Thelia/Module/AbstractDeliveryModule.php index 80c0072f2..9e9710534 100644 --- a/core/lib/Thelia/Module/AbstractDeliveryModule.php +++ b/core/lib/Thelia/Module/AbstractDeliveryModule.php @@ -24,6 +24,7 @@ namespace Thelia\Module; use Thelia\Model\Country; +use Thelia\Module\Exception\DeliveryException; abstract class AbstractDeliveryModule extends BaseModule implements DeliveryModuleInterface { @@ -46,6 +47,7 @@ abstract class AbstractDeliveryModule extends BaseModule implements DeliveryModu * @param Country $country the country to deliver to. * * @return float the delivery price + * @throws DeliveryException if the postage price cannot be calculated. */ public abstract function getPostage(Country $country); } \ No newline at end of file diff --git a/core/lib/Thelia/Module/DeliveryModuleInterface.php b/core/lib/Thelia/Module/DeliveryModuleInterface.php index 2cabd5f87..1f6bc5f70 100644 --- a/core/lib/Thelia/Module/DeliveryModuleInterface.php +++ b/core/lib/Thelia/Module/DeliveryModuleInterface.php @@ -24,6 +24,7 @@ namespace Thelia\Module; use Thelia\Model\Country; +use Thelia\Module\Exception\DeliveryException; interface DeliveryModuleInterface extends BaseModuleInterface { @@ -46,6 +47,7 @@ interface DeliveryModuleInterface extends BaseModuleInterface * @param Country $country the country to deliver to. * * @return float the delivery price + * @throws DeliveryException if the postage price cannot be calculated. */ public function getPostage(Country $country); } diff --git a/local/modules/Colissimo/Colissimo.php b/local/modules/Colissimo/Colissimo.php index 90d32df35..eb6b53dda 100755 --- a/local/modules/Colissimo/Colissimo.php +++ b/local/modules/Colissimo/Colissimo.php @@ -25,15 +25,14 @@ namespace Colissimo; use Colissimo\Model\ColissimoFreeshippingQuery; use Propel\Runtime\Connection\ConnectionInterface; -use Symfony\Component\EventDispatcher\EventDispatcherInterface; -use Symfony\Component\HttpFoundation\Request; +use Thelia\Core\Translation\Translator; use Thelia\Exception\OrderException; use Thelia\Install\Database; use Thelia\Model\Country; -use Thelia\Module\BaseModule; -use Thelia\Module\DeliveryModuleInterface; +use Thelia\Module\AbstractDeliveryModule; +use Thelia\Module\Exception\DeliveryException; -class Colissimo extends BaseModule implements DeliveryModuleInterface +class Colissimo extends AbstractDeliveryModule { protected $request; protected $dispatcher; @@ -44,13 +43,38 @@ class Colissimo extends BaseModule implements DeliveryModuleInterface public static function getPrices() { - if(null === self::$prices) { + if (null === self::$prices) { self::$prices = json_decode(file_get_contents(sprintf('%s%s', __DIR__, self::JSON_PRICE_RESOURCE)), true); } return self::$prices; } + public function isValidDelivery(Country $country) { + + $areaId = $country->getAreaId(); + + $prices = self::getPrices(); + + /* Check if Colissimo delivers the area */ + if (isset($prices[$areaId]) && isset($prices[$areaId]["slices"])) { + + // Yes ! Check if the cart weight is below slice limit + $areaPrices = $prices[$areaId]["slices"]; + ksort($areaPrices); + + /* Check cart weight is below the maximum weight */ + end($areaPrices); + $maxWeight = key($areaPrices); + + $cartWeight = $this->getRequest()->getSession()->getCart()->getWeight(); + + if ($cartWeight <= $maxWeight) return true; + } + + return false; + } + /** * @param $areaId * @param $weight @@ -61,29 +85,36 @@ class Colissimo extends BaseModule implements DeliveryModuleInterface public static function getPostageAmount($areaId, $weight) { $freeshipping = ColissimoFreeshippingQuery::create()->getLast(); - $postage=0; - if(!$freeshipping) { + $postage = 0; + if (!$freeshipping) { $prices = self::getPrices(); /* check if Colissimo delivers the asked area */ - if(!isset($prices[$areaId]) || !isset($prices[$areaId]["slices"])) { - throw new OrderException("Colissimo delivery unavailable for the chosen delivery country", OrderException::DELIVERY_MODULE_UNAVAILABLE); + if (!isset($prices[$areaId]) || !isset($prices[$areaId]["slices"])) { + throw new DeliveryException( + Translator::getInstance()->trans("Colissimo delivery unavailable for the delivery country") + ); } $areaPrices = $prices[$areaId]["slices"]; ksort($areaPrices); - /* check this weight is not too much */ + /* Check cart weight is below the maximum weight */ end($areaPrices); $maxWeight = key($areaPrices); - if($weight > $maxWeight) { - throw new OrderException(sprintf("Colissimo delivery unavailable for this cart weight (%s kg)", $weight), OrderException::DELIVERY_MODULE_UNAVAILABLE); + if ($weight > $maxWeight) { + throw new DeliveryException( + Translator::getInstance()->trans( + "Colissimo delivery unavailable for this cart weight (%weight kg)", + array("%weight" => $weight) + ) + ); } $postage = current($areaPrices); - while(prev($areaPrices)) { - if($weight > key($areaPrices)) { + while (prev($areaPrices)) { + if ($weight > key($areaPrices)) { break; } @@ -94,29 +125,9 @@ class Colissimo extends BaseModule implements DeliveryModuleInterface } - public function setRequest(Request $request) - { - $this->request = $request; - } - - public function getRequest() - { - return $this->request; - } - - public function setDispatcher(EventDispatcherInterface $dispatcher) - { - $this->dispatcher = $dispatcher; - } - - public function getDispatcher() - { - return $this->dispatcher; - } - public function postActivation(ConnectionInterface $con = null) { - $database = new Database($con->getWrappedConnection()); + $database = new Database($con); $database->insertSql(null, array(__DIR__ . '/Config/thelia.sql')); } @@ -131,7 +142,7 @@ class Colissimo extends BaseModule implements DeliveryModuleInterface */ public function getPostage(Country $country) { - $cartWeight = $this->getContainer()->get('request')->getSession()->getCart()->getWeight(); + $cartWeight = $this->getRequest()->getSession()->getCart()->getWeight(); $postage = self::getPostageAmount( $country->getAreaId(), @@ -140,10 +151,4 @@ class Colissimo extends BaseModule implements DeliveryModuleInterface return $postage; } - - public function getCode() - { - return 'Colissimo'; - } - -} +} \ No newline at end of file diff --git a/local/modules/Front/Controller/CartController.php b/local/modules/Front/Controller/CartController.php index 59110d62a..ed3875756 100644 --- a/local/modules/Front/Controller/CartController.php +++ b/local/modules/Front/Controller/CartController.php @@ -1,173 +1,185 @@ -. */ -/* */ -/*************************************************************************************/ -namespace Front\Controller; - -use Propel\Runtime\Exception\PropelException; -use Thelia\Controller\Front\BaseFrontController; -use Thelia\Core\Event\Order\OrderEvent; -use Thelia\Form\Exception\FormValidationException; -use Thelia\Core\Event\Cart\CartEvent; -use Thelia\Core\Event\TheliaEvents; -use Symfony\Component\HttpFoundation\Request; -use Thelia\Form\CartAdd; -use Thelia\Model\AddressQuery; - -class CartController extends BaseFrontController -{ - use \Thelia\Cart\CartTrait; - - public function addItem() - { - $request = $this->getRequest(); - - $cartAdd = $this->getAddCartForm($request); - $message = null; - - try { - $form = $this->validateForm($cartAdd); - - $cartEvent = $this->getCartEvent(); - $cartEvent->setNewness($form->get("newness")->getData()); - $cartEvent->setAppend($form->get("append")->getData()); - $cartEvent->setQuantity($form->get("quantity")->getData()); - $cartEvent->setProductSaleElementsId($form->get("product_sale_elements_id")->getData()); - $cartEvent->setProduct($form->get("product")->getData()); - - $this->getDispatcher()->dispatch(TheliaEvents::CART_ADDITEM, $cartEvent); - - $this->afterModifyCart(); - - $this->redirectSuccess(); - - } catch (PropelException $e) { - \Thelia\Log\Tlog::getInstance()->error(sprintf("Failed to add item to cart with message : %s", $e->getMessage())); - $message = "Failed to add this article to your cart, please try again"; - } catch (FormValidationException $e) { - $message = $e->getMessage(); - } - - // If Ajax Request - if ($this->getRequest()->isXmlHttpRequest()) { - $request = $this->getRequest(); - $request->attributes->set('_view', "includes/mini-cart"); - } - - if ($message) { - $cartAdd->setErrorMessage($message); - $this->getParserContext()->addForm($cartAdd); - } - } - - public function changeItem() - { - $cartEvent = $this->getCartEvent(); - $cartEvent->setCartItem($this->getRequest()->get("cart_item")); - $cartEvent->setQuantity($this->getRequest()->get("quantity")); - - try { - $this->dispatch(TheliaEvents::CART_UPDATEITEM, $cartEvent); - - $this->afterModifyCart(); - - $this->redirectSuccess(); - } catch (PropelException $e) { - $this->getParserContext()->setGeneralError($e->getMessage()); - } - - } - - public function deleteItem() - { - $cartEvent = $this->getCartEvent(); - $cartEvent->setCartItem($this->getRequest()->get("cart_item")); - - try { - $this->getDispatcher()->dispatch(TheliaEvents::CART_DELETEITEM, $cartEvent); - - $this->afterModifyCart(); - - $this->redirectSuccess(); - } catch (PropelException $e) { - \Thelia\Log\Tlog::getInstance()->error(sprintf("error during deleting cartItem with message : %s", $e->getMessage())); - $this->getParserContext()->setGeneralError($e->getMessage()); - } - - } - - /** - * use Thelia\Cart\CartTrait for searching current cart or create a new one - * - * @return \Thelia\Core\Event\Cart\CartEvent - */ - protected function getCartEvent() - { - $cart = $this->getCart($this->getDispatcher(), $this->getRequest()); - - return new CartEvent($cart); - } - - /** - * Find the good way to construct the cart form - * - * @param Request $request - * @return CartAdd - */ - private function getAddCartForm(Request $request) - { - if ($request->isMethod("post")) { - $cartAdd = new CartAdd($request); - } else { - $cartAdd = new CartAdd( - $request, - "form", - array(), - array( - 'csrf_protection' => false, - ) - ); - } - - return $cartAdd; - } - - protected function afterModifyCart() - { - /* recalculate postage amount */ - $order = $this->getSession()->getOrder(); - if (null !== $order) { - $deliveryModule = $order->getModuleRelatedByDeliveryModuleId(); - $deliveryAddress = AddressQuery::create()->findPk($order->chosenDeliveryAddress); - - if (null !== $deliveryModule && null !== $deliveryAddress) { - $moduleInstance = $this->container->get(sprintf('module.%s', $deliveryModule->getCode())); - $postage = $moduleInstance->getPostage($deliveryAddress->getCountry()); - - $orderEvent = new OrderEvent($order); - $orderEvent->setPostage($postage); - - $this->getDispatcher()->dispatch(TheliaEvents::ORDER_SET_POSTAGE, $orderEvent); - } - } - } - -} +. */ +/* */ +/*************************************************************************************/ +namespace Front\Controller; + +use Propel\Runtime\Exception\PropelException; +use Thelia\Controller\Front\BaseFrontController; +use Thelia\Core\Event\Order\OrderEvent; +use Thelia\Form\Exception\FormValidationException; +use Thelia\Core\Event\Cart\CartEvent; +use Thelia\Core\Event\TheliaEvents; +use Symfony\Component\HttpFoundation\Request; +use Thelia\Form\CartAdd; +use Thelia\Model\AddressQuery; +use Thelia\Module\Exception\DeliveryException; + +class CartController extends BaseFrontController +{ + use \Thelia\Cart\CartTrait; + + public function addItem() + { + $request = $this->getRequest(); + + $cartAdd = $this->getAddCartForm($request); + $message = null; + + try { + $form = $this->validateForm($cartAdd); + + $cartEvent = $this->getCartEvent(); + $cartEvent->setNewness($form->get("newness")->getData()); + $cartEvent->setAppend($form->get("append")->getData()); + $cartEvent->setQuantity($form->get("quantity")->getData()); + $cartEvent->setProductSaleElementsId($form->get("product_sale_elements_id")->getData()); + $cartEvent->setProduct($form->get("product")->getData()); + + $this->getDispatcher()->dispatch(TheliaEvents::CART_ADDITEM, $cartEvent); + + $this->afterModifyCart(); + + $this->redirectSuccess(); + + } catch (PropelException $e) { + \Thelia\Log\Tlog::getInstance()->error(sprintf("Failed to add item to cart with message : %s", $e->getMessage())); + $message = "Failed to add this article to your cart, please try again"; + } catch (FormValidationException $e) { + $message = $e->getMessage(); + } + + // If Ajax Request + if ($this->getRequest()->isXmlHttpRequest()) { + $request = $this->getRequest(); + $request->attributes->set('_view', "includes/mini-cart"); + } + + if ($message) { + $cartAdd->setErrorMessage($message); + $this->getParserContext()->addForm($cartAdd); + } + } + + public function changeItem() + { + $cartEvent = $this->getCartEvent(); + $cartEvent->setCartItem($this->getRequest()->get("cart_item")); + $cartEvent->setQuantity($this->getRequest()->get("quantity")); + + try { + $this->dispatch(TheliaEvents::CART_UPDATEITEM, $cartEvent); + + $this->afterModifyCart(); + + $this->redirectSuccess(); + } catch (PropelException $e) { + $this->getParserContext()->setGeneralError($e->getMessage()); + } + + } + + public function deleteItem() + { + $cartEvent = $this->getCartEvent(); + $cartEvent->setCartItem($this->getRequest()->get("cart_item")); + + try { + $this->getDispatcher()->dispatch(TheliaEvents::CART_DELETEITEM, $cartEvent); + + $this->afterModifyCart(); + + $this->redirectSuccess(); + } catch (PropelException $e) { + \Thelia\Log\Tlog::getInstance()->error(sprintf("error during deleting cartItem with message : %s", $e->getMessage())); + $this->getParserContext()->setGeneralError($e->getMessage()); + } + + } + + /** + * use Thelia\Cart\CartTrait for searching current cart or create a new one + * + * @return \Thelia\Core\Event\Cart\CartEvent + */ + protected function getCartEvent() + { + $cart = $this->getCart($this->getDispatcher(), $this->getRequest()); + + return new CartEvent($cart); + } + + /** + * Find the good way to construct the cart form + * + * @param Request $request + * @return CartAdd + */ + private function getAddCartForm(Request $request) + { + if ($request->isMethod("post")) { + $cartAdd = new CartAdd($request); + } else { + $cartAdd = new CartAdd( + $request, + "form", + array(), + array( + 'csrf_protection' => false, + ) + ); + } + + return $cartAdd; + } + + protected function afterModifyCart() + { + /* recalculate postage amount */ + $order = $this->getSession()->getOrder(); + if (null !== $order) { + $deliveryModule = $order->getModuleRelatedByDeliveryModuleId(); + $deliveryAddress = AddressQuery::create()->findPk($order->chosenDeliveryAddress); + + if (null !== $deliveryModule && null !== $deliveryAddress) { + $moduleInstance = $this->container->get(sprintf('module.%s', $deliveryModule->getCode())); + + $orderEvent = new OrderEvent($order); + + try { + $postage = $moduleInstance->getPostage($deliveryAddress->getCountry()); + + $orderEvent->setPostage($postage); + + $this->getDispatcher()->dispatch(TheliaEvents::ORDER_SET_POSTAGE, $orderEvent); + } + catch (DeliveryException $ex) { + // The postage has been chosen, but changes in the cart causes an exception. + // Reset the postage data in the order + $orderEvent->setDeliveryModule(0); + + $this->getDispatcher()->dispatch(TheliaEvents::ORDER_SET_DELIVERY_MODULE, $orderEvent); + } + } + } + } + +} diff --git a/local/modules/Front/Controller/CouponController.php b/local/modules/Front/Controller/CouponController.php index ba7433612..185041ce1 100644 --- a/local/modules/Front/Controller/CouponController.php +++ b/local/modules/Front/Controller/CouponController.php @@ -1,106 +1,118 @@ -. */ -/* */ -/*************************************************************************************/ -namespace Front\Controller; - -use Propel\Runtime\Exception\PropelException; -use Thelia\Controller\Front\BaseFrontController; -use Thelia\Core\Event\Coupon\CouponConsumeEvent; -use Thelia\Core\Event\Order\OrderEvent; -use Thelia\Form\CouponCode; -use Thelia\Form\Exception\FormValidationException; -use Thelia\Core\Event\TheliaEvents; -use Thelia\Log\Tlog; -use Thelia\Model\AddressQuery; - -/** - * Class CouponController - * @package Thelia\Controller\Front - * @author Guillaume MOREL - */ -class CouponController extends BaseFrontController -{ - - /** - * Test Coupon consuming - */ - public function consumeAction() - { - $this->checkAuth(); - $this->checkCartNotEmpty(); - - $message = false; - $couponCodeForm = new CouponCode($this->getRequest()); - - try { - $form = $this->validateForm($couponCodeForm, 'post'); - - $couponCode = $form->get('coupon-code')->getData(); - - if (null === $couponCode || empty($couponCode)) { - $message = true; - throw new \Exception('Coupon code can\'t be empty'); - } - - $couponConsumeEvent = new CouponConsumeEvent($couponCode); - - // Dispatch Event to the Action - $this->getDispatcher()->dispatch(TheliaEvents::COUPON_CONSUME, $couponConsumeEvent); - - /* recalculate postage amount */ - $order = $this->getSession()->getOrder(); - if (null !== $order) { - $deliveryModule = $order->getModuleRelatedByDeliveryModuleId(); - $deliveryAddress = AddressQuery::create()->findPk($order->chosenDeliveryAddress); - - if (null !== $deliveryModule && null !== $deliveryAddress) { - $moduleInstance = $this->container->get(sprintf('module.%s', $deliveryModule->getCode())); - $postage = $moduleInstance->getPostage($deliveryAddress->getCountry()); - - $orderEvent = new OrderEvent($order); - $orderEvent->setPostage($postage); - - $this->getDispatcher()->dispatch(TheliaEvents::ORDER_SET_POSTAGE, $orderEvent); - } - } - - $this->redirect($couponCodeForm->getSuccessUrl()); - - } catch (FormValidationException $e) { - $message = sprintf('Please check your coupon code: %s', $e->getMessage()); - } catch (PropelException $e) { - $this->getParserContext()->setGeneralError($e->getMessage()); - } catch (\Exception $e) { - $message = sprintf('Sorry, an error occurred: %s', $e->getMessage()); - } - - if ($message !== false) { - Tlog::getInstance()->error(sprintf("Error during order delivery process : %s. Exception was %s", $message, $e->getMessage())); - - $couponCodeForm->setErrorMessage($message); - - $this->getParserContext() - ->addForm($couponCodeForm) - ->setGeneralError($message); - } - } -} +. */ +/* */ +/*************************************************************************************/ +namespace Front\Controller; + +use Propel\Runtime\Exception\PropelException; +use Thelia\Controller\Front\BaseFrontController; +use Thelia\Core\Event\Coupon\CouponConsumeEvent; +use Thelia\Core\Event\Order\OrderEvent; +use Thelia\Form\CouponCode; +use Thelia\Form\Exception\FormValidationException; +use Thelia\Core\Event\TheliaEvents; +use Thelia\Log\Tlog; +use Thelia\Model\AddressQuery; +use Thelia\Module\Exception\DeliveryException; + +/** + * Class CouponController + * @package Thelia\Controller\Front + * @author Guillaume MOREL + */ +class CouponController extends BaseFrontController +{ + + /** + * Test Coupon consuming + */ + public function consumeAction() + { + $this->checkAuth(); + $this->checkCartNotEmpty(); + + $message = false; + $couponCodeForm = new CouponCode($this->getRequest()); + + try { + $form = $this->validateForm($couponCodeForm, 'post'); + + $couponCode = $form->get('coupon-code')->getData(); + + if (null === $couponCode || empty($couponCode)) { + $message = true; + throw new \Exception('Coupon code can\'t be empty'); + } + + $couponConsumeEvent = new CouponConsumeEvent($couponCode); + + // Dispatch Event to the Action + $this->getDispatcher()->dispatch(TheliaEvents::COUPON_CONSUME, $couponConsumeEvent); + + /* recalculate postage amount */ + $order = $this->getSession()->getOrder(); + if (null !== $order) { + $deliveryModule = $order->getModuleRelatedByDeliveryModuleId(); + $deliveryAddress = AddressQuery::create()->findPk($order->chosenDeliveryAddress); + + if (null !== $deliveryModule && null !== $deliveryAddress) { + $moduleInstance = $this->container->get(sprintf('module.%s', $deliveryModule->getCode())); + + $orderEvent = new OrderEvent($order); + + try { + $postage = $moduleInstance->getPostage($deliveryAddress->getCountry()); + + $orderEvent->setPostage($postage); + + $this->getDispatcher()->dispatch(TheliaEvents::ORDER_SET_POSTAGE, $orderEvent); + } + catch (DeliveryException $ex) { + // The postage has been chosen, but changes dues to coupon causes an exception. + // Reset the postage data in the order + $orderEvent->setDeliveryModule(0); + + $this->getDispatcher()->dispatch(TheliaEvents::ORDER_SET_DELIVERY_MODULE, $orderEvent); + } + } + } + + $this->redirect($couponCodeForm->getSuccessUrl()); + + } catch (FormValidationException $e) { + $message = sprintf('Please check your coupon code: %s', $e->getMessage()); + } catch (PropelException $e) { + $this->getParserContext()->setGeneralError($e->getMessage()); + } catch (\Exception $e) { + $message = sprintf('Sorry, an error occurred: %s', $e->getMessage()); + } + + if ($message !== false) { + Tlog::getInstance()->error(sprintf("Error during order delivery process : %s. Exception was %s", $message, $e->getMessage())); + + $couponCodeForm->setErrorMessage($message); + + $this->getParserContext() + ->addForm($couponCodeForm) + ->setGeneralError($message); + } + } +} From ed91dcaffe9ca80372ae8a4ae154fb11b8144622 Mon Sep 17 00:00:00 2001 From: Franck Allimant Date: Thu, 17 Apr 2014 19:57:49 +0200 Subject: [PATCH 05/18] Reformated JSON to a human readable form (e.g, with newlines). --- local/modules/Colissimo/Config/prices.json | 121 ++++++++++++++++++++- 1 file changed, 120 insertions(+), 1 deletion(-) diff --git a/local/modules/Colissimo/Config/prices.json b/local/modules/Colissimo/Config/prices.json index 3fc2e0cd7..1b23c825c 100755 --- a/local/modules/Colissimo/Config/prices.json +++ b/local/modules/Colissimo/Config/prices.json @@ -1 +1,120 @@ -{"1":{"_info":"area 1 : France","slices":{"0.25":"5.23","0.5":5.8,"0.75":6.56,"1":7.13,"2":8.08,"3":9.22,"5":11.31,"7":13.4,"10":16.53,"15":19.14,"30":26.93}},"2":{"_info":"area 2 : A Zone - Union Europ\u00e9enne et Suisse","slices":{"1":15.34,"2":16.96,"3":20.47,"4":23.99,"5":27.5,"6":31.02,"7":34.53,"8":38.05,"9":41.56,"10":45.08,"15":51.92,"20":58.76,"25":65.6,"30":72.44}},"3":{"_info":"area 3 : B Zone - Pays de l\u2019Europe de l\u2019Est (hors Union Europ\u00e9enne), Norv\u00e8ge, Maghreb","slices":{"1":18.81,"2":20.62,"3":24.94,"4":29.26,"5":33.58,"6":37.91,"7":42.23,"8":46.55,"9":50.87,"10":55.2,"15":65.08,"20":74.96}},"4":{"_info":"area 4 : C Zone - Pays d\u2019Afrique hors Maghreb, Canada, Etats-Unis, Proche et Moyen Orient","slices":{"1":22.04,"2":29.55,"3":38.86,"4":48.17,"5":57.48,"6":66.79,"7":76.1,"8":85.41,"9":94.72,"10":104.03,"15":126.92,"20":149.82}},"5":{"_info":"area 5 : D Zone - Autres destinations","slices":{"1":25.08,"2":37.72,"3":50.26,"4":62.8,"5":75.34,"6":87.88,"7":100.42,"8":112.96,"9":125.5,"10":138.04,"15":162.74,"20":187.44}},"6":{"_info":"area 6 : France OM1","slices":{"0.5":8.27,"1":12.49,"2":17.05,"3":21.61,"4":26.17,"5":30.73,"6":35.29,"7":39.85,"8":44.41,"9":48.97,"10":53.53,"15":76.33,"20":99.13,"25":121.93,"30":144.73}},"7":{"_info":"area 7 : France OM2","slices":{"0.5":9.88,"1":14.92,"2":26.32,"3":37.72,"4":49.12,"5":60.52,"6":71.92,"7":83.32,"8":94.72,"9":106.12,"10":117.52,"15":174.52,"20":231.52,"25":288.52,"30":345.52}}} \ No newline at end of file +{"1": { + "_info": "area 1 : France", + "slices": { + "0.25": "5.23", + "0.5": 5.8, + "0.75": 6.56, + "1": 7.13, + "2": 8.08, + "3": 9.22, + "5": 11.31, + "7": 13.4, + "10": 16.53, + "15": 19.14, + "30": 26.93 + } +}, "2": { + "_info": "area 2 : A Zone - Union Europ\u00e9enne et Suisse", + "slices": { + "1": 15.34, + "2": 16.96, + "3": 20.47, + "4": 23.99, + "5": 27.5, + "6": 31.02, + "7": 34.53, + "8": 38.05, + "9": 41.56, + "10": 45.08, + "15": 51.92, + "20": 58.76, + "25": 65.6, + "30": 72.44 + } +}, "3": { + "_info": "area 3 : B Zone - Pays de l\u2019Europe de l\u2019Est (hors Union Europ\u00e9enne), Norv\u00e8ge, Maghreb", + "slices": { + "1": 18.81, + "2": 20.62, + "3": 24.94, + "4": 29.26, + "5": 33.58, + "6": 37.91, + "7": 42.23, + "8": 46.55, + "9": 50.87, + "10": 55.2, + "15": 65.08, + "20": 74.96 + } +}, "4": { + "_info": "area 4 : C Zone - Pays d\u2019Afrique hors Maghreb, Canada, Etats-Unis, Proche et Moyen Orient", + "slices": { + "1": 22.04, + "2": 29.55, + "3": 38.86, + "4": 48.17, + "5": 57.48, + "6": 66.79, + "7": 76.1, + "8": 85.41, + "9": 94.72, + "10": 104.03, + "15": 126.92, + "20": 149.82 + } +}, "5": { + "_info": "area 5 : D Zone - Autres destinations", + "slices": { + "1": 25.08, + "2": 37.72, + "3": 50.26, + "4": 62.8, + "5": 75.34, + "6": 87.88, + "7": 100.42, + "8": 112.96, + "9": 125.5, + "10": 138.04, + "15": 162.74, + "20": 187.44 + } +}, "6": { + "_info": "area 6 : France OM1", + "slices": { + "0.5": 8.27, + "1": 12.49, + "2": 17.05, + "3": 21.61, + "4": 26.17, + "5": 30.73, + "6": 35.29, + "7": 39.85, + "8": 44.41, + "9": 48.97, + "10": 53.53, + "15": 76.33, + "20": 99.13, + "25": 121.93, + "30": 144.73 + } +}, "7": { + "_info": "area 7 : France OM2", + "slices": { + "0.5": 9.88, + "1": 14.92, + "2": 26.32, + "3": 37.72, + "4": 49.12, + "5": 60.52, + "6": 71.92, + "7": 83.32, + "8": 94.72, + "9": 106.12, + "10": 117.52, + "15": 174.52, + "20": 231.52, + "25": 288.52, + "30": 345.52 + } +}} \ No newline at end of file From 115d86d82e39e095f9bf3d1d20683c60bdbc7dda Mon Sep 17 00:00:00 2001 From: Franck Allimant Date: Thu, 17 Apr 2014 20:00:46 +0200 Subject: [PATCH 06/18] Initial commit --- .../Module/Exception/DeliveryException.php | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 core/lib/Thelia/Module/Exception/DeliveryException.php diff --git a/core/lib/Thelia/Module/Exception/DeliveryException.php b/core/lib/Thelia/Module/Exception/DeliveryException.php new file mode 100644 index 000000000..12a758d24 --- /dev/null +++ b/core/lib/Thelia/Module/Exception/DeliveryException.php @@ -0,0 +1,28 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Module\Exception; + +class DeliveryException extends \RuntimeException +{ +} From 1603a89cff5ce8538f8cf9e1adf0ae34fb986f9c Mon Sep 17 00:00:00 2001 From: Franck Allimant Date: Thu, 17 Apr 2014 20:50:35 +0200 Subject: [PATCH 07/18] Fixed postage amount reset. --- core/lib/Thelia/Action/Order.php | 2 +- .../backOffice/default/assets/img/flags/TES.png | Bin 0 -> 176 bytes .../backOffice/default/assets/img/flags/TEST.png | Bin 0 -> 176 bytes web/.htaccess | 2 +- 4 files changed, 2 insertions(+), 2 deletions(-) create mode 100644 templates/backOffice/default/assets/img/flags/TES.png create mode 100644 templates/backOffice/default/assets/img/flags/TEST.png diff --git a/core/lib/Thelia/Action/Order.php b/core/lib/Thelia/Action/Order.php index 78534b268..70e181a40 100644 --- a/core/lib/Thelia/Action/Order.php +++ b/core/lib/Thelia/Action/Order.php @@ -112,7 +112,7 @@ class Order extends BaseAction implements EventSubscriberInterface // Reset postage cost if the delivery module had been removed if ($deliveryModuleId <= 0) { - $this->setPostage(0); + $order->setPostage(0); } $event->setOrder($order); diff --git a/templates/backOffice/default/assets/img/flags/TES.png b/templates/backOffice/default/assets/img/flags/TES.png new file mode 100644 index 0000000000000000000000000000000000000000..9d91c7f4b8c00b234e2d9663d7ee141f51e981a4 GIT binary patch literal 176 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`<(@8%Ar`&KKmPx>XI7o@@X^+2 zkwl5d_A_U+v8}nk>ver%sjZ9!>qvFJsMXmU8jb*CWye z&mM*D=+(ZK&nnGOBzQ8B;WOI_flW+>*Bck_nB&(T!H^iB(6q;(Ku_T)!>7+oM|VyP aVrDSUR%x|P6txCAfx*+&&t;ucLK6T}twc`% literal 0 HcmV?d00001 diff --git a/templates/backOffice/default/assets/img/flags/TEST.png b/templates/backOffice/default/assets/img/flags/TEST.png new file mode 100644 index 0000000000000000000000000000000000000000..9d91c7f4b8c00b234e2d9663d7ee141f51e981a4 GIT binary patch literal 176 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`<(@8%Ar`&KKmPx>XI7o@@X^+2 zkwl5d_A_U+v8}nk>ver%sjZ9!>qvFJsMXmU8jb*CWye z&mM*D=+(ZK&nnGOBzQ8B;WOI_flW+>*Bck_nB&(T!H^iB(6q;(Ku_T)!>7+oM|VyP aVrDSUR%x|P6txCAfx*+&&t;ucLK6T}twc`% literal 0 HcmV?d00001 diff --git a/web/.htaccess b/web/.htaccess index dfe03bf51..9bbc5928b 100755 --- a/web/.htaccess +++ b/web/.htaccess @@ -7,7 +7,7 @@ AddDefaultCharset UTF-8 # If thelia is installed in a subdirectory (e.g., thelia2) # define the RewriteBase below to get a proper URL rewriting - # RewriteBase /thelia2 + RewriteBase /thelia2 RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d From a0285c855c620acbc018b5a41cb0f75b793b396b Mon Sep 17 00:00:00 2001 From: Franck Allimant Date: Thu, 17 Apr 2014 23:12:59 +0200 Subject: [PATCH 08/18] Fixed wrong commit --- web/.htaccess | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/.htaccess b/web/.htaccess index 9bbc5928b..5c957964e 100755 --- a/web/.htaccess +++ b/web/.htaccess @@ -1,4 +1,4 @@ -#Options +FollowSymlinks -Indexes +Options +FollowSymlinks -Indexes AddDefaultCharset UTF-8 @@ -7,7 +7,7 @@ AddDefaultCharset UTF-8 # If thelia is installed in a subdirectory (e.g., thelia2) # define the RewriteBase below to get a proper URL rewriting - RewriteBase /thelia2 + # RewriteBase /thelia2 RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d From bf5b6628630450965ca6643e5aa0244dcec14e5e Mon Sep 17 00:00:00 2001 From: Franck Allimant Date: Thu, 17 Apr 2014 23:13:17 +0200 Subject: [PATCH 09/18] Removed files added by mistake --- .../backOffice/default/assets/img/flags/TES.png | Bin 176 -> 0 bytes .../backOffice/default/assets/img/flags/TEST.png | Bin 176 -> 0 bytes 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 templates/backOffice/default/assets/img/flags/TES.png delete mode 100644 templates/backOffice/default/assets/img/flags/TEST.png diff --git a/templates/backOffice/default/assets/img/flags/TES.png b/templates/backOffice/default/assets/img/flags/TES.png deleted file mode 100644 index 9d91c7f4b8c00b234e2d9663d7ee141f51e981a4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 176 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`<(@8%Ar`&KKmPx>XI7o@@X^+2 zkwl5d_A_U+v8}nk>ver%sjZ9!>qvFJsMXmU8jb*CWye z&mM*D=+(ZK&nnGOBzQ8B;WOI_flW+>*Bck_nB&(T!H^iB(6q;(Ku_T)!>7+oM|VyP aVrDSUR%x|P6txCAfx*+&&t;ucLK6T}twc`% diff --git a/templates/backOffice/default/assets/img/flags/TEST.png b/templates/backOffice/default/assets/img/flags/TEST.png deleted file mode 100644 index 9d91c7f4b8c00b234e2d9663d7ee141f51e981a4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 176 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`<(@8%Ar`&KKmPx>XI7o@@X^+2 zkwl5d_A_U+v8}nk>ver%sjZ9!>qvFJsMXmU8jb*CWye z&mM*D=+(ZK&nnGOBzQ8B;WOI_flW+>*Bck_nB&(T!H^iB(6q;(Ku_T)!>7+oM|VyP aVrDSUR%x|P6txCAfx*+&&t;ucLK6T}twc`% From 0bdac598815f4c4047703c1958448ee5f6712580 Mon Sep 17 00:00:00 2001 From: Franck Allimant Date: Thu, 17 Apr 2014 23:41:12 +0200 Subject: [PATCH 10/18] Restored previous version --- core/lib/Thelia/Action/Order.php | 1015 +++++++++++++++--------------- 1 file changed, 504 insertions(+), 511 deletions(-) diff --git a/core/lib/Thelia/Action/Order.php b/core/lib/Thelia/Action/Order.php index 70e181a40..a8a8d5af9 100644 --- a/core/lib/Thelia/Action/Order.php +++ b/core/lib/Thelia/Action/Order.php @@ -1,511 +1,504 @@ -. */ -/* */ -/*************************************************************************************/ - -namespace Thelia\Action; - -use Symfony\Component\EventDispatcher\EventDispatcherInterface; -use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Thelia\Cart\CartTrait; -use Thelia\Core\Event\Order\OrderAddressEvent; -use Thelia\Core\Event\Order\OrderEvent; -use Thelia\Core\Event\Order\OrderManualEvent; -use Thelia\Core\Event\Order\OrderPaymentEvent; -use Thelia\Core\Event\TheliaEvents; -use Thelia\Core\HttpFoundation\Request; -use Thelia\Core\Security\SecurityContext; -use Thelia\Core\Template\ParserInterface; -use Thelia\Exception\TheliaProcessException; -use Thelia\Mailer\MailerFactory; -use Thelia\Model\AddressQuery; -use Thelia\Model\Cart as CartModel; -use Thelia\Model\ConfigQuery; -use Thelia\Model\Currency as CurrencyModel; -use Thelia\Model\Customer as CustomerModel; -use Thelia\Model\Lang as LangModel; -use Thelia\Model\Map\OrderTableMap; -use Thelia\Model\MessageQuery; -use Thelia\Model\Order as ModelOrder; -use Thelia\Model\OrderAddress; -use Thelia\Model\OrderProduct; -use Thelia\Model\OrderProductAttributeCombination; -use Thelia\Model\OrderStatus; -use Thelia\Model\OrderStatusQuery; -use Thelia\Tools\I18n; - -/** - * - * Class Order - * @package Thelia\Action - * @author Etienne Roudeix - */ -class Order extends BaseAction implements EventSubscriberInterface -{ - use CartTrait; - - /** - * @var \Thelia\Core\HttpFoundation\Request - */ - protected $request; - /** - * @var MailerFactory - */ - protected $mailer; - /** - * @var ParserInterface - */ - protected $parser; - /** - * @var SecurityContext - */ - protected $securityContext; - - public function __construct(Request $request, ParserInterface $parser, MailerFactory $mailer, SecurityContext $securityContext) - { - $this->request = $request; - $this->parser = $parser; - $this->mailer = $mailer; - $this->securityContext = $securityContext; - } - - /** - * @param \Thelia\Core\Event\Order\OrderEvent $event - */ - public function setDeliveryAddress(OrderEvent $event) - { - $order = $event->getOrder(); - - $order->chosenDeliveryAddress = $event->getDeliveryAddress(); - - $event->setOrder($order); - } - - /** - * @param \Thelia\Core\Event\Order\OrderEvent $event - */ - public function setDeliveryModule(OrderEvent $event) - { - $order = $event->getOrder(); - - $deliveryModuleId = $event->getDeliveryModule(); - - $order->setDeliveryModuleId($deliveryModuleId); - - // Reset postage cost if the delivery module had been removed - if ($deliveryModuleId <= 0) { - $order->setPostage(0); - } - - $event->setOrder($order); - } - - /** - * @param \Thelia\Core\Event\Order\OrderEvent $event - */ - public function setPostage(OrderEvent $event) - { - $order = $event->getOrder(); - - $order->setPostage($event->getPostage()); - - $event->setOrder($order); - } - - /** - * @param \Thelia\Core\Event\Order\OrderEvent $event - */ - public function setInvoiceAddress(OrderEvent $event) - { - $order = $event->getOrder(); - - $order->chosenInvoiceAddress = $event->getInvoiceAddress(); - - $event->setOrder($order); - } - - /** - * @param \Thelia\Core\Event\Order\OrderEvent $event - */ - public function setPaymentModule(OrderEvent $event) - { - $order = $event->getOrder(); - - $order->setPaymentModuleId($event->getPaymentModule()); - - $event->setOrder($order); - } - - protected function createOrder(EventDispatcherInterface $dispatcher, ModelOrder $sessionOrder, CurrencyModel $currency, LangModel $lang, CartModel $cart, CustomerModel $customer) - { - $con = \Propel\Runtime\Propel::getConnection( - OrderTableMap::DATABASE_NAME - ); - - $con->beginTransaction(); - - $placedOrder = $sessionOrder->copy(); - $placedOrder->setDispatcher($dispatcher); - - $deliveryAddress = AddressQuery::create()->findPk($sessionOrder->chosenDeliveryAddress); - $taxCountry = $deliveryAddress->getCountry(); - $invoiceAddress = AddressQuery::create()->findPk($sessionOrder->chosenInvoiceAddress); - $cartItems = $cart->getCartItems(); - - /* fulfill order */ - $placedOrder->setCustomerId($customer->getId()); - $placedOrder->setCurrencyId($currency->getId()); - $placedOrder->setCurrencyRate($currency->getRate()); - $placedOrder->setLangId($lang->getId()); - - /* hard save the delivery and invoice addresses */ - $deliveryOrderAddress = new OrderAddress(); - $deliveryOrderAddress - ->setCustomerTitleId($deliveryAddress->getTitleId()) - ->setCompany($deliveryAddress->getCompany()) - ->setFirstname($deliveryAddress->getFirstname()) - ->setLastname($deliveryAddress->getLastname()) - ->setAddress1($deliveryAddress->getAddress1()) - ->setAddress2($deliveryAddress->getAddress2()) - ->setAddress3($deliveryAddress->getAddress3()) - ->setZipcode($deliveryAddress->getZipcode()) - ->setCity($deliveryAddress->getCity()) - ->setPhone($deliveryAddress->getPhone()) - ->setCountryId($deliveryAddress->getCountryId()) - ->save($con) - ; - - $invoiceOrderAddress = new OrderAddress(); - $invoiceOrderAddress - ->setCustomerTitleId($invoiceAddress->getTitleId()) - ->setCompany($invoiceAddress->getCompany()) - ->setFirstname($invoiceAddress->getFirstname()) - ->setLastname($invoiceAddress->getLastname()) - ->setAddress1($invoiceAddress->getAddress1()) - ->setAddress2($invoiceAddress->getAddress2()) - ->setAddress3($invoiceAddress->getAddress3()) - ->setZipcode($invoiceAddress->getZipcode()) - ->setCity($invoiceAddress->getCity()) - ->setPhone($invoiceAddress->getPhone()) - ->setCountryId($invoiceAddress->getCountryId()) - ->save($con) - ; - - $placedOrder->setDeliveryOrderAddressId($deliveryOrderAddress->getId()); - $placedOrder->setInvoiceOrderAddressId($invoiceOrderAddress->getId()); - - $placedOrder->setStatusId( - OrderStatusQuery::getNotPaidStatus()->getId() - ); - - /* memorize discount */ - $placedOrder->setDiscount( - $cart->getDiscount() - ); - - $placedOrder->save($con); - - /* fulfill order_products and decrease stock */ - - foreach ($cartItems as $cartItem) { - $product = $cartItem->getProduct(); - - /* get translation */ - $productI18n = I18n::forceI18nRetrieving($lang->getLocale(), 'Product', $product->getId()); - - $pse = $cartItem->getProductSaleElements(); - - /* check still in stock */ - if ($cartItem->getQuantity() > $pse->getQuantity()) { - throw new TheliaProcessException("Not enough stock", TheliaProcessException::CART_ITEM_NOT_ENOUGH_STOCK, $cartItem); - } - - /* decrease stock */ - $pse->setQuantity( - $pse->getQuantity() - $cartItem->getQuantity() - ); - $pse->save($con); - - /* get tax */ - $taxRuleI18n = I18n::forceI18nRetrieving($lang->getLocale(), 'TaxRule', $product->getTaxRuleId()); - - $taxDetail = $product->getTaxRule()->getTaxDetail( - $product, - $taxCountry, - $cartItem->getPrice(), - $cartItem->getPromoPrice(), - $lang->getLocale() - ); - - $orderProduct = new OrderProduct(); - $orderProduct - ->setOrderId($placedOrder->getId()) - ->setProductRef($product->getRef()) - ->setProductSaleElementsRef($pse->getRef()) - ->setTitle($productI18n->getTitle()) - ->setChapo($productI18n->getChapo()) - ->setDescription($productI18n->getDescription()) - ->setPostscriptum($productI18n->getPostscriptum()) - ->setQuantity($cartItem->getQuantity()) - ->setPrice($cartItem->getPrice()) - ->setPromoPrice($cartItem->getPromoPrice()) - ->setWasNew($pse->getNewness()) - ->setWasInPromo($cartItem->getPromo()) - ->setWeight($pse->getWeight()) - ->setTaxRuleTitle($taxRuleI18n->getTitle()) - ->setTaxRuleDescription($taxRuleI18n->getDescription()) - ->setEanCode($pse->getEanCode()) - ->setCartIemId($cartItem->getId()) - ->setDispatcher($dispatcher) - ->save($con) - ; - - /* fulfill order_product_tax */ - foreach ($taxDetail as $tax) { - $tax->setOrderProductId($orderProduct->getId()); - $tax->save($con); - } - - /* fulfill order_attribute_combination and decrease stock */ - foreach ($pse->getAttributeCombinations() as $attributeCombination) { - $attribute = I18n::forceI18nRetrieving($lang->getLocale(), 'Attribute', $attributeCombination->getAttributeId()); - $attributeAv = I18n::forceI18nRetrieving($lang->getLocale(), 'AttributeAv', $attributeCombination->getAttributeAvId()); - - $orderAttributeCombination = new OrderProductAttributeCombination(); - $orderAttributeCombination - ->setOrderProductId($orderProduct->getId()) - ->setAttributeTitle($attribute->getTitle()) - ->setAttributeChapo($attribute->getChapo()) - ->setAttributeDescription($attribute->getDescription()) - ->setAttributePostscriptum($attribute->getPostscriptum()) - ->setAttributeAvTitle($attributeAv->getTitle()) - ->setAttributeAvChapo($attributeAv->getChapo()) - ->setAttributeAvDescription($attributeAv->getDescription()) - ->setAttributeAvPostscriptum($attributeAv->getPostscriptum()) - ->save($con); - } - } - - $con->commit(); - - return $placedOrder; - } - - /** - * Create an order outside of the front-office context, e.g. manually from the back-office. - */ - public function createManual(OrderManualEvent $event) - { - $placedOrder = $this->createOrder( - $event->getDispatcher(), - $event->getOrder(), - $event->getCurrency(), - $event->getLang(), - $event->getCart(), - $event->getCustomer() - ); - } - - /** - * @param OrderEvent $event - * - * @throws \Thelia\Exception\TheliaProcessException - */ - public function create(OrderEvent $event) - { - $session = $this->getSession(); - - $placedOrder = $this->createOrder( - $event->getDispatcher(), - $event->getOrder(), - $session->getCurrency(), - $session->getLang(), - $session->getCart(), - $this->securityContext->getCustomerUser() - ); - - $event->getDispatcher()->dispatch(TheliaEvents::ORDER_BEFORE_PAYMENT, new OrderEvent($placedOrder)); - - /* but memorize placed order */ - $event->setOrder(new \Thelia\Model\Order()); - $event->setPlacedOrder($placedOrder); - - /* empty cart */ - $dispatcher = $event->getDispatcher(); - - /* call pay method */ - $payEvent = new OrderPaymentEvent($placedOrder); - - $dispatcher->dispatch(TheliaEvents::MODULE_PAY, $payEvent); - - if ($payEvent->hasResponse()) { - $event->setResponse($payEvent->getResponse()); - } - } - - /** - * @param \Thelia\Core\Event\Order\OrderEvent $event - */ - public function sendOrderEmail(OrderEvent $event) - { - $contact_email = ConfigQuery::read('store_email'); - - if ($contact_email) { - - $message = MessageQuery::create() - ->filterByName('order_confirmation') - ->findOne(); - - if (false === $message) { - throw new \Exception("Failed to load message 'order_confirmation'."); - } - - $order = $event->getOrder(); - $customer = $order->getCustomer(); - - $this->parser->assign('order_id', $order->getId()); - $this->parser->assign('order_ref', $order->getRef()); - - $message - ->setLocale($order->getLang()->getLocale()); - - $instance = \Swift_Message::newInstance() - ->addTo($customer->getEmail(), $customer->getFirstname()." ".$customer->getLastname()) - ->addFrom($contact_email, ConfigQuery::read('store_name')) - ; - - // Build subject and body - - $message->buildMessage($this->parser, $instance); - - $this->getMailer()->send($instance); - } - } - - /** - * - * return an instance of \Swift_Mailer with good Transporter configured. - * - * @return \Swift_Mailer - */ - public function getMailer() - { - return $this->mailer->getSwiftMailer(); - } - - /** - * @param OrderEvent $event - */ - public function updateStatus(OrderEvent $event) - { - $order = $event->getOrder(); - - $order->setStatusId($event->getStatus()); - $order->save(); - - $event->setOrder($order); - } - - /** - * @param OrderEvent $event - */ - public function updateDeliveryRef(OrderEvent $event) - { - $order = $event->getOrder(); - - $order->setDeliveryRef($event->getDeliveryRef()); - $order->save(); - - $event->setOrder($order); - } - - /** - * @param OrderAddressEvent $event - */ - public function updateAddress(OrderAddressEvent $event) - { - $orderAddress = $event->getOrderAddress(); - - $orderAddress - ->setCustomerTitleId($event->getTitle()) - ->setCompany($event->getCompany()) - ->setFirstname($event->getFirstname()) - ->setLastname($event->getLastname()) - ->setAddress1($event->getAddress1()) - ->setAddress2($event->getAddress2()) - ->setAddress3($event->getAddress3()) - ->setZipcode($event->getZipcode()) - ->setCity($event->getCity()) - ->setCountryId($event->getCountry()) - ->setPhone($event->getPhone()) - ; - $orderAddress->save(); - - $event->setOrderAddress($orderAddress); - } - - /** - * Returns an array of event names this subscriber wants to listen to. - * - * The array keys are event names and the value can be: - * - * * The method name to call (priority defaults to 0) - * * An array composed of the method name to call and the priority - * * An array of arrays composed of the method names to call and respective - * priorities, or 0 if unset - * - * For instance: - * - * * array('eventName' => 'methodName') - * * array('eventName' => array('methodName', $priority)) - * * array('eventName' => array(array('methodName1', $priority), array('methodName2')) - * - * @return array The event names to listen to - * - * @api - */ - public static function getSubscribedEvents() - { - return array( - TheliaEvents::ORDER_SET_DELIVERY_ADDRESS => array("setDeliveryAddress", 128), - TheliaEvents::ORDER_SET_DELIVERY_MODULE => array("setDeliveryModule", 128), - TheliaEvents::ORDER_SET_POSTAGE => array("setPostage", 128), - TheliaEvents::ORDER_SET_INVOICE_ADDRESS => array("setInvoiceAddress", 128), - TheliaEvents::ORDER_SET_PAYMENT_MODULE => array("setPaymentModule", 128), - TheliaEvents::ORDER_PAY => array("create", 128), - TheliaEvents::ORDER_BEFORE_PAYMENT => array("sendOrderEmail", 128), - TheliaEvents::ORDER_UPDATE_STATUS => array("updateStatus", 128), - TheliaEvents::ORDER_UPDATE_DELIVERY_REF => array("updateDeliveryRef", 128), - TheliaEvents::ORDER_UPDATE_ADDRESS => array("updateAddress", 128), - TheliaEvents::ORDER_CREATE_MANUAL => array("createManual", 128), - ); - } - - /** - * Returns the session from the current request - * - * @return \Thelia\Core\HttpFoundation\Session\Session - */ - protected function getSession() - { - return $this->request->getSession(); - } -} +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Action; + +use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Thelia\Cart\CartTrait; +use Thelia\Core\Event\Order\OrderAddressEvent; +use Thelia\Core\Event\Order\OrderEvent; +use Thelia\Core\Event\Order\OrderManualEvent; +use Thelia\Core\Event\Order\OrderPaymentEvent; +use Thelia\Core\Event\TheliaEvents; +use Thelia\Core\HttpFoundation\Request; +use Thelia\Core\Security\SecurityContext; +use Thelia\Core\Template\ParserInterface; +use Thelia\Exception\TheliaProcessException; +use Thelia\Mailer\MailerFactory; +use Thelia\Model\AddressQuery; +use Thelia\Model\Cart as CartModel; +use Thelia\Model\ConfigQuery; +use Thelia\Model\Currency as CurrencyModel; +use Thelia\Model\Customer as CustomerModel; +use Thelia\Model\Lang as LangModel; +use Thelia\Model\Map\OrderTableMap; +use Thelia\Model\MessageQuery; +use Thelia\Model\Order as ModelOrder; +use Thelia\Model\OrderAddress; +use Thelia\Model\OrderProduct; +use Thelia\Model\OrderProductAttributeCombination; +use Thelia\Model\OrderStatus; +use Thelia\Model\OrderStatusQuery; +use Thelia\Tools\I18n; + +/** + * + * Class Order + * @package Thelia\Action + * @author Etienne Roudeix + */ +class Order extends BaseAction implements EventSubscriberInterface +{ + use CartTrait; + + /** + * @var \Thelia\Core\HttpFoundation\Request + */ + protected $request; + /** + * @var MailerFactory + */ + protected $mailer; + /** + * @var ParserInterface + */ + protected $parser; + /** + * @var SecurityContext + */ + protected $securityContext; + + public function __construct(Request $request, ParserInterface $parser, MailerFactory $mailer, SecurityContext $securityContext) + { + $this->request = $request; + $this->parser = $parser; + $this->mailer = $mailer; + $this->securityContext = $securityContext; + } + + /** + * @param \Thelia\Core\Event\Order\OrderEvent $event + */ + public function setDeliveryAddress(OrderEvent $event) + { + $order = $event->getOrder(); + + $order->chosenDeliveryAddress = $event->getDeliveryAddress(); + + $event->setOrder($order); + } + + /** + * @param \Thelia\Core\Event\Order\OrderEvent $event + */ + public function setDeliveryModule(OrderEvent $event) + { + $order = $event->getOrder(); + + $order->setDeliveryModuleId($event->getDeliveryModule()); + + $event->setOrder($order); + } + + /** + * @param \Thelia\Core\Event\Order\OrderEvent $event + */ + public function setPostage(OrderEvent $event) + { + $order = $event->getOrder(); + + $order->setPostage($event->getPostage()); + + $event->setOrder($order); + } + + /** + * @param \Thelia\Core\Event\Order\OrderEvent $event + */ + public function setInvoiceAddress(OrderEvent $event) + { + $order = $event->getOrder(); + + $order->chosenInvoiceAddress = $event->getInvoiceAddress(); + + $event->setOrder($order); + } + + /** + * @param \Thelia\Core\Event\Order\OrderEvent $event + */ + public function setPaymentModule(OrderEvent $event) + { + $order = $event->getOrder(); + + $order->setPaymentModuleId($event->getPaymentModule()); + + $event->setOrder($order); + } + + protected function createOrder(EventDispatcherInterface $dispatcher, ModelOrder $sessionOrder, CurrencyModel $currency, LangModel $lang, CartModel $cart, CustomerModel $customer) + { + $con = \Propel\Runtime\Propel::getConnection( + OrderTableMap::DATABASE_NAME + ); + + $con->beginTransaction(); + + $placedOrder = $sessionOrder->copy(); + $placedOrder->setDispatcher($dispatcher); + + $deliveryAddress = AddressQuery::create()->findPk($sessionOrder->chosenDeliveryAddress); + $taxCountry = $deliveryAddress->getCountry(); + $invoiceAddress = AddressQuery::create()->findPk($sessionOrder->chosenInvoiceAddress); + $cartItems = $cart->getCartItems(); + + /* fulfill order */ + $placedOrder->setCustomerId($customer->getId()); + $placedOrder->setCurrencyId($currency->getId()); + $placedOrder->setCurrencyRate($currency->getRate()); + $placedOrder->setLangId($lang->getId()); + + /* hard save the delivery and invoice addresses */ + $deliveryOrderAddress = new OrderAddress(); + $deliveryOrderAddress + ->setCustomerTitleId($deliveryAddress->getTitleId()) + ->setCompany($deliveryAddress->getCompany()) + ->setFirstname($deliveryAddress->getFirstname()) + ->setLastname($deliveryAddress->getLastname()) + ->setAddress1($deliveryAddress->getAddress1()) + ->setAddress2($deliveryAddress->getAddress2()) + ->setAddress3($deliveryAddress->getAddress3()) + ->setZipcode($deliveryAddress->getZipcode()) + ->setCity($deliveryAddress->getCity()) + ->setPhone($deliveryAddress->getPhone()) + ->setCountryId($deliveryAddress->getCountryId()) + ->save($con) + ; + + $invoiceOrderAddress = new OrderAddress(); + $invoiceOrderAddress + ->setCustomerTitleId($invoiceAddress->getTitleId()) + ->setCompany($invoiceAddress->getCompany()) + ->setFirstname($invoiceAddress->getFirstname()) + ->setLastname($invoiceAddress->getLastname()) + ->setAddress1($invoiceAddress->getAddress1()) + ->setAddress2($invoiceAddress->getAddress2()) + ->setAddress3($invoiceAddress->getAddress3()) + ->setZipcode($invoiceAddress->getZipcode()) + ->setCity($invoiceAddress->getCity()) + ->setPhone($invoiceAddress->getPhone()) + ->setCountryId($invoiceAddress->getCountryId()) + ->save($con) + ; + + $placedOrder->setDeliveryOrderAddressId($deliveryOrderAddress->getId()); + $placedOrder->setInvoiceOrderAddressId($invoiceOrderAddress->getId()); + + $placedOrder->setStatusId( + OrderStatusQuery::getNotPaidStatus()->getId() + ); + + /* memorize discount */ + $placedOrder->setDiscount( + $cart->getDiscount() + ); + + $placedOrder->save($con); + + /* fulfill order_products and decrease stock */ + + foreach ($cartItems as $cartItem) { + $product = $cartItem->getProduct(); + + /* get translation */ + $productI18n = I18n::forceI18nRetrieving($lang->getLocale(), 'Product', $product->getId()); + + $pse = $cartItem->getProductSaleElements(); + + /* check still in stock */ + if ($cartItem->getQuantity() > $pse->getQuantity()) { + throw new TheliaProcessException("Not enough stock", TheliaProcessException::CART_ITEM_NOT_ENOUGH_STOCK, $cartItem); + } + + /* decrease stock */ + $pse->setQuantity( + $pse->getQuantity() - $cartItem->getQuantity() + ); + $pse->save($con); + + /* get tax */ + $taxRuleI18n = I18n::forceI18nRetrieving($lang->getLocale(), 'TaxRule', $product->getTaxRuleId()); + + $taxDetail = $product->getTaxRule()->getTaxDetail( + $product, + $taxCountry, + $cartItem->getPrice(), + $cartItem->getPromoPrice(), + $lang->getLocale() + ); + + $orderProduct = new OrderProduct(); + $orderProduct + ->setOrderId($placedOrder->getId()) + ->setProductRef($product->getRef()) + ->setProductSaleElementsRef($pse->getRef()) + ->setTitle($productI18n->getTitle()) + ->setChapo($productI18n->getChapo()) + ->setDescription($productI18n->getDescription()) + ->setPostscriptum($productI18n->getPostscriptum()) + ->setQuantity($cartItem->getQuantity()) + ->setPrice($cartItem->getPrice()) + ->setPromoPrice($cartItem->getPromoPrice()) + ->setWasNew($pse->getNewness()) + ->setWasInPromo($cartItem->getPromo()) + ->setWeight($pse->getWeight()) + ->setTaxRuleTitle($taxRuleI18n->getTitle()) + ->setTaxRuleDescription($taxRuleI18n->getDescription()) + ->setEanCode($pse->getEanCode()) + ->setCartIemId($cartItem->getId()) + ->setDispatcher($dispatcher) + ->save($con) + ; + + /* fulfill order_product_tax */ + foreach ($taxDetail as $tax) { + $tax->setOrderProductId($orderProduct->getId()); + $tax->save($con); + } + + /* fulfill order_attribute_combination and decrease stock */ + foreach ($pse->getAttributeCombinations() as $attributeCombination) { + $attribute = I18n::forceI18nRetrieving($lang->getLocale(), 'Attribute', $attributeCombination->getAttributeId()); + $attributeAv = I18n::forceI18nRetrieving($lang->getLocale(), 'AttributeAv', $attributeCombination->getAttributeAvId()); + + $orderAttributeCombination = new OrderProductAttributeCombination(); + $orderAttributeCombination + ->setOrderProductId($orderProduct->getId()) + ->setAttributeTitle($attribute->getTitle()) + ->setAttributeChapo($attribute->getChapo()) + ->setAttributeDescription($attribute->getDescription()) + ->setAttributePostscriptum($attribute->getPostscriptum()) + ->setAttributeAvTitle($attributeAv->getTitle()) + ->setAttributeAvChapo($attributeAv->getChapo()) + ->setAttributeAvDescription($attributeAv->getDescription()) + ->setAttributeAvPostscriptum($attributeAv->getPostscriptum()) + ->save($con); + } + } + + $con->commit(); + + return $placedOrder; + } + + /** + * Create an order outside of the front-office context, e.g. manually from the back-office. + */ + public function createManual(OrderManualEvent $event) + { + $placedOrder = $this->createOrder( + $event->getDispatcher(), + $event->getOrder(), + $event->getCurrency(), + $event->getLang(), + $event->getCart(), + $event->getCustomer() + ); + } + + /** + * @param OrderEvent $event + * + * @throws \Thelia\Exception\TheliaProcessException + */ + public function create(OrderEvent $event) + { + $session = $this->getSession(); + + $placedOrder = $this->createOrder( + $event->getDispatcher(), + $event->getOrder(), + $session->getCurrency(), + $session->getLang(), + $session->getCart(), + $this->securityContext->getCustomerUser() + ); + + $event->getDispatcher()->dispatch(TheliaEvents::ORDER_BEFORE_PAYMENT, new OrderEvent($placedOrder)); + + /* but memorize placed order */ + $event->setOrder(new \Thelia\Model\Order()); + $event->setPlacedOrder($placedOrder); + + /* empty cart */ + $dispatcher = $event->getDispatcher(); + + /* call pay method */ + $payEvent = new OrderPaymentEvent($placedOrder); + + $dispatcher->dispatch(TheliaEvents::MODULE_PAY, $payEvent); + + if ($payEvent->hasResponse()) { + $event->setResponse($payEvent->getResponse()); + } + } + + /** + * @param \Thelia\Core\Event\Order\OrderEvent $event + */ + public function sendOrderEmail(OrderEvent $event) + { + $contact_email = ConfigQuery::read('store_email'); + + if ($contact_email) { + + $message = MessageQuery::create() + ->filterByName('order_confirmation') + ->findOne(); + + if (false === $message) { + throw new \Exception("Failed to load message 'order_confirmation'."); + } + + $order = $event->getOrder(); + $customer = $order->getCustomer(); + + $this->parser->assign('order_id', $order->getId()); + $this->parser->assign('order_ref', $order->getRef()); + + $message + ->setLocale($order->getLang()->getLocale()); + + $instance = \Swift_Message::newInstance() + ->addTo($customer->getEmail(), $customer->getFirstname()." ".$customer->getLastname()) + ->addFrom($contact_email, ConfigQuery::read('store_name')) + ; + + // Build subject and body + + $message->buildMessage($this->parser, $instance); + + $this->getMailer()->send($instance); + } + } + + /** + * + * return an instance of \Swift_Mailer with good Transporter configured. + * + * @return \Swift_Mailer + */ + public function getMailer() + { + return $this->mailer->getSwiftMailer(); + } + + /** + * @param OrderEvent $event + */ + public function updateStatus(OrderEvent $event) + { + $order = $event->getOrder(); + + $order->setStatusId($event->getStatus()); + $order->save(); + + $event->setOrder($order); + } + + /** + * @param OrderEvent $event + */ + public function updateDeliveryRef(OrderEvent $event) + { + $order = $event->getOrder(); + + $order->setDeliveryRef($event->getDeliveryRef()); + $order->save(); + + $event->setOrder($order); + } + + /** + * @param OrderAddressEvent $event + */ + public function updateAddress(OrderAddressEvent $event) + { + $orderAddress = $event->getOrderAddress(); + + $orderAddress + ->setCustomerTitleId($event->getTitle()) + ->setCompany($event->getCompany()) + ->setFirstname($event->getFirstname()) + ->setLastname($event->getLastname()) + ->setAddress1($event->getAddress1()) + ->setAddress2($event->getAddress2()) + ->setAddress3($event->getAddress3()) + ->setZipcode($event->getZipcode()) + ->setCity($event->getCity()) + ->setCountryId($event->getCountry()) + ->setPhone($event->getPhone()) + ; + $orderAddress->save(); + + $event->setOrderAddress($orderAddress); + } + + /** + * Returns an array of event names this subscriber wants to listen to. + * + * The array keys are event names and the value can be: + * + * * The method name to call (priority defaults to 0) + * * An array composed of the method name to call and the priority + * * An array of arrays composed of the method names to call and respective + * priorities, or 0 if unset + * + * For instance: + * + * * array('eventName' => 'methodName') + * * array('eventName' => array('methodName', $priority)) + * * array('eventName' => array(array('methodName1', $priority), array('methodName2')) + * + * @return array The event names to listen to + * + * @api + */ + public static function getSubscribedEvents() + { + return array( + TheliaEvents::ORDER_SET_DELIVERY_ADDRESS => array("setDeliveryAddress", 128), + TheliaEvents::ORDER_SET_DELIVERY_MODULE => array("setDeliveryModule", 128), + TheliaEvents::ORDER_SET_POSTAGE => array("setPostage", 128), + TheliaEvents::ORDER_SET_INVOICE_ADDRESS => array("setInvoiceAddress", 128), + TheliaEvents::ORDER_SET_PAYMENT_MODULE => array("setPaymentModule", 128), + TheliaEvents::ORDER_PAY => array("create", 128), + TheliaEvents::ORDER_BEFORE_PAYMENT => array("sendOrderEmail", 128), + TheliaEvents::ORDER_UPDATE_STATUS => array("updateStatus", 128), + TheliaEvents::ORDER_UPDATE_DELIVERY_REF => array("updateDeliveryRef", 128), + TheliaEvents::ORDER_UPDATE_ADDRESS => array("updateAddress", 128), + TheliaEvents::ORDER_CREATE_MANUAL => array("createManual", 128), + ); + } + + /** + * Returns the session from the current request + * + * @return \Thelia\Core\HttpFoundation\Session\Session + */ + protected function getSession() + { + return $this->request->getSession(); + } +} From 68cbc986e1d124bc3dad27021c76f60736fb3a22 Mon Sep 17 00:00:00 2001 From: Franck Allimant Date: Thu, 17 Apr 2014 23:44:19 +0200 Subject: [PATCH 11/18] Fix for #308 --- core/lib/Thelia/Action/Order.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/core/lib/Thelia/Action/Order.php b/core/lib/Thelia/Action/Order.php index a8a8d5af9..a5d4b922c 100644 --- a/core/lib/Thelia/Action/Order.php +++ b/core/lib/Thelia/Action/Order.php @@ -106,7 +106,14 @@ class Order extends BaseAction implements EventSubscriberInterface { $order = $event->getOrder(); - $order->setDeliveryModuleId($event->getDeliveryModule()); + $deliveryModuleId = $event->getDeliveryModule(); + + $order->setDeliveryModuleId($deliveryModuleId); + + // Reset postage cost if the delivery module had been removed + if ($deliveryModuleId <= 0) { + $order->setPostage(0); + } $event->setOrder($order); } From 307217665b1a09dbc1fa4b53bbaf337930adca22 Mon Sep 17 00:00:00 2001 From: Franck Allimant Date: Thu, 17 Apr 2014 23:51:05 +0200 Subject: [PATCH 12/18] Restored previous version --- .../Thelia/Core/Template/Loop/Delivery.php | 215 +++++++++--------- 1 file changed, 106 insertions(+), 109 deletions(-) diff --git a/core/lib/Thelia/Core/Template/Loop/Delivery.php b/core/lib/Thelia/Core/Template/Loop/Delivery.php index a379f9c3a..2e7391c95 100644 --- a/core/lib/Thelia/Core/Template/Loop/Delivery.php +++ b/core/lib/Thelia/Core/Template/Loop/Delivery.php @@ -1,109 +1,106 @@ -. */ -/* */ -/*************************************************************************************/ - -namespace Thelia\Core\Template\Loop; -use Thelia\Core\Template\Element\LoopResult; -use Thelia\Core\Template\Element\LoopResultRow; -use Thelia\Core\Template\Loop\Argument\Argument; -use Thelia\Exception\OrderException; -use Thelia\Model\CountryQuery; -use Thelia\Model\Module; -use Thelia\Module\BaseModule; -use Thelia\Module\DeliveryModuleInterface; -use Thelia\Module\Exception\DeliveryException; - -/** - * Class Delivery - * @package Thelia\Core\Template\Loop - * @author Manuel Raynaud - * @author Etienne Roudeix - */ -class Delivery extends BaseSpecificModule -{ - - public function getArgDefinitions() - { - $collection = parent::getArgDefinitions(); - - $collection->addArgument( - Argument::createIntTypeArgument("country") - ); - - return $collection; - } - - public function parseResults(LoopResult $loopResult) - { - $countryId = $this->getCountry(); - if (null !== $countryId) { - $country = CountryQuery::create()->findPk($countryId); - if (null === $country) { - throw new \InvalidArgumentException('Cannot found country id: `' . $countryId . '` in delivery loop'); - } - } else { - $country = $this->container->get('thelia.taxEngine')->getDeliveryCountry(); - } - - /** @var Module $deliveryModule */ - foreach ($loopResult->getResultDataCollection() as $deliveryModule) { - $loopResultRow = new LoopResultRow($deliveryModule); - - /** @var DeliveryModuleInterface $moduleInstance */ - $moduleInstance = $this->container->get(sprintf('module.%s', $deliveryModule->getCode())); - - if (false === $moduleInstance instanceof DeliveryModuleInterface) { - throw new \RuntimeException(sprintf("delivery module %s is not a Thelia\Module\DeliveryModuleInterface", $deliveryModule->getCode())); - } - - try { - // Check if module is valid, by calling isValidDelivery(), - // or catching a DeliveryException. - - if ($moduleInstance->isValidDelivery($country)) { - - $postage = $moduleInstance->getPostage($country); - - $loopResultRow - ->set('ID', $deliveryModule->getId()) - ->set('TITLE', $deliveryModule->getVirtualColumn('i18n_TITLE')) - ->set('CHAPO', $deliveryModule->getVirtualColumn('i18n_CHAPO')) - ->set('DESCRIPTION', $deliveryModule->getVirtualColumn('i18n_DESCRIPTION')) - ->set('POSTSCRIPTUM', $deliveryModule->getVirtualColumn('i18n_POSTSCRIPTUM')) - ->set('POSTAGE', $postage) - ; - - $loopResult->addRow($loopResultRow); - } - } catch (DeliveryException $ex) { - // Module is not available - } - } - - return $loopResult; - } - - protected function getModuleType() - { - return BaseModule::DELIVERY_MODULE_TYPE; - } -} +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Core\Template\Loop; +use Thelia\Core\Template\Element\LoopResult; +use Thelia\Core\Template\Element\LoopResultRow; +use Thelia\Core\Template\Loop\Argument\Argument; +use Thelia\Exception\OrderException; +use Thelia\Model\CountryQuery; +use Thelia\Module\BaseModule; +use Thelia\Module\DeliveryModuleInterface; + +/** + * Class Delivery + * @package Thelia\Core\Template\Loop + * @author Manuel Raynaud + * @author Etienne Roudeix + */ +class Delivery extends BaseSpecificModule +{ + + public function getArgDefinitions() + { + $collection = parent::getArgDefinitions(); + + $collection->addArgument( + Argument::createIntTypeArgument("country") + ); + + return $collection; + } + + public function parseResults(LoopResult $loopResult) + { + $countryId = $this->getCountry(); + if (null !== $countryId) { + $country = CountryQuery::create()->findPk($countryId); + if (null === $country) { + throw new \InvalidArgumentException('Cannot found country id: `' . $countryId . '` in delivery loop'); + } + } else { + $country = $this->container->get('thelia.taxEngine')->getDeliveryCountry(); + } + + foreach ($loopResult->getResultDataCollection() as $deliveryModule) { + $loopResultRow = new LoopResultRow($deliveryModule); + + $moduleInstance = $this->container->get(sprintf('module.%s', $deliveryModule->getCode())); + + if (false === $moduleInstance instanceof DeliveryModuleInterface) { + throw new \RuntimeException(sprintf("delivery module %s is not a Thelia\Module\DeliveryModuleInterface", $deliveryModule->getCode())); + } + + try { + $postage = $moduleInstance->getPostage($country); + } catch (OrderException $e) { + switch ($e->getCode()) { + case OrderException::DELIVERY_MODULE_UNAVAILABLE: + /* do not show this delivery module */ + continue(2); + break; + default: + throw $e; + } + } + + $loopResultRow + ->set('ID', $deliveryModule->getId()) + ->set('TITLE', $deliveryModule->getVirtualColumn('i18n_TITLE')) + ->set('CHAPO', $deliveryModule->getVirtualColumn('i18n_CHAPO')) + ->set('DESCRIPTION', $deliveryModule->getVirtualColumn('i18n_DESCRIPTION')) + ->set('POSTSCRIPTUM', $deliveryModule->getVirtualColumn('i18n_POSTSCRIPTUM')) + ->set('POSTAGE', $postage) + ; + + $loopResult->addRow($loopResultRow); + } + + return $loopResult; + } + + protected function getModuleType() + { + return BaseModule::DELIVERY_MODULE_TYPE; + } +} From 52ecfe7dade8152087cee6ccbbaeca74260418f6 Mon Sep 17 00:00:00 2001 From: Franck Allimant Date: Thu, 17 Apr 2014 23:52:01 +0200 Subject: [PATCH 13/18] Fix #308 --- .../Thelia/Core/Template/Loop/Delivery.php | 46 ++++++++++--------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/core/lib/Thelia/Core/Template/Loop/Delivery.php b/core/lib/Thelia/Core/Template/Loop/Delivery.php index 2e7391c95..3eb858eb4 100644 --- a/core/lib/Thelia/Core/Template/Loop/Delivery.php +++ b/core/lib/Thelia/Core/Template/Loop/Delivery.php @@ -25,10 +25,11 @@ namespace Thelia\Core\Template\Loop; use Thelia\Core\Template\Element\LoopResult; use Thelia\Core\Template\Element\LoopResultRow; use Thelia\Core\Template\Loop\Argument\Argument; -use Thelia\Exception\OrderException; use Thelia\Model\CountryQuery; +use Thelia\Model\Module; use Thelia\Module\BaseModule; use Thelia\Module\DeliveryModuleInterface; +use Thelia\Module\Exception\DeliveryException; /** * Class Delivery @@ -62,9 +63,11 @@ class Delivery extends BaseSpecificModule $country = $this->container->get('thelia.taxEngine')->getDeliveryCountry(); } + /** @var Module $deliveryModule */ foreach ($loopResult->getResultDataCollection() as $deliveryModule) { $loopResultRow = new LoopResultRow($deliveryModule); + /** @var DeliveryModuleInterface $moduleInstance */ $moduleInstance = $this->container->get(sprintf('module.%s', $deliveryModule->getCode())); if (false === $moduleInstance instanceof DeliveryModuleInterface) { @@ -72,28 +75,27 @@ class Delivery extends BaseSpecificModule } try { - $postage = $moduleInstance->getPostage($country); - } catch (OrderException $e) { - switch ($e->getCode()) { - case OrderException::DELIVERY_MODULE_UNAVAILABLE: - /* do not show this delivery module */ - continue(2); - break; - default: - throw $e; + // Check if module is valid, by calling isValidDelivery(), + // or catching a DeliveryException. + + if ($moduleInstance->isValidDelivery($country)) { + + $postage = $moduleInstance->getPostage($country); + + $loopResultRow + ->set('ID', $deliveryModule->getId()) + ->set('TITLE', $deliveryModule->getVirtualColumn('i18n_TITLE')) + ->set('CHAPO', $deliveryModule->getVirtualColumn('i18n_CHAPO')) + ->set('DESCRIPTION', $deliveryModule->getVirtualColumn('i18n_DESCRIPTION')) + ->set('POSTSCRIPTUM', $deliveryModule->getVirtualColumn('i18n_POSTSCRIPTUM')) + ->set('POSTAGE', $postage) + ; + + $loopResult->addRow($loopResultRow); } + } catch (DeliveryException $ex) { + // Module is not available } - - $loopResultRow - ->set('ID', $deliveryModule->getId()) - ->set('TITLE', $deliveryModule->getVirtualColumn('i18n_TITLE')) - ->set('CHAPO', $deliveryModule->getVirtualColumn('i18n_CHAPO')) - ->set('DESCRIPTION', $deliveryModule->getVirtualColumn('i18n_DESCRIPTION')) - ->set('POSTSCRIPTUM', $deliveryModule->getVirtualColumn('i18n_POSTSCRIPTUM')) - ->set('POSTAGE', $postage) - ; - - $loopResult->addRow($loopResultRow); } return $loopResult; @@ -103,4 +105,4 @@ class Delivery extends BaseSpecificModule { return BaseModule::DELIVERY_MODULE_TYPE; } -} +} \ No newline at end of file From 917b05b65e44b2081a1f9447e1c047d21158cdcb Mon Sep 17 00:00:00 2001 From: Franck Allimant Date: Fri, 18 Apr 2014 00:00:25 +0200 Subject: [PATCH 14/18] Restored previous version --- .../Front/Controller/CartController.php | 358 +++++++++--------- 1 file changed, 173 insertions(+), 185 deletions(-) diff --git a/local/modules/Front/Controller/CartController.php b/local/modules/Front/Controller/CartController.php index ed3875756..59110d62a 100644 --- a/local/modules/Front/Controller/CartController.php +++ b/local/modules/Front/Controller/CartController.php @@ -1,185 +1,173 @@ -. */ -/* */ -/*************************************************************************************/ -namespace Front\Controller; - -use Propel\Runtime\Exception\PropelException; -use Thelia\Controller\Front\BaseFrontController; -use Thelia\Core\Event\Order\OrderEvent; -use Thelia\Form\Exception\FormValidationException; -use Thelia\Core\Event\Cart\CartEvent; -use Thelia\Core\Event\TheliaEvents; -use Symfony\Component\HttpFoundation\Request; -use Thelia\Form\CartAdd; -use Thelia\Model\AddressQuery; -use Thelia\Module\Exception\DeliveryException; - -class CartController extends BaseFrontController -{ - use \Thelia\Cart\CartTrait; - - public function addItem() - { - $request = $this->getRequest(); - - $cartAdd = $this->getAddCartForm($request); - $message = null; - - try { - $form = $this->validateForm($cartAdd); - - $cartEvent = $this->getCartEvent(); - $cartEvent->setNewness($form->get("newness")->getData()); - $cartEvent->setAppend($form->get("append")->getData()); - $cartEvent->setQuantity($form->get("quantity")->getData()); - $cartEvent->setProductSaleElementsId($form->get("product_sale_elements_id")->getData()); - $cartEvent->setProduct($form->get("product")->getData()); - - $this->getDispatcher()->dispatch(TheliaEvents::CART_ADDITEM, $cartEvent); - - $this->afterModifyCart(); - - $this->redirectSuccess(); - - } catch (PropelException $e) { - \Thelia\Log\Tlog::getInstance()->error(sprintf("Failed to add item to cart with message : %s", $e->getMessage())); - $message = "Failed to add this article to your cart, please try again"; - } catch (FormValidationException $e) { - $message = $e->getMessage(); - } - - // If Ajax Request - if ($this->getRequest()->isXmlHttpRequest()) { - $request = $this->getRequest(); - $request->attributes->set('_view', "includes/mini-cart"); - } - - if ($message) { - $cartAdd->setErrorMessage($message); - $this->getParserContext()->addForm($cartAdd); - } - } - - public function changeItem() - { - $cartEvent = $this->getCartEvent(); - $cartEvent->setCartItem($this->getRequest()->get("cart_item")); - $cartEvent->setQuantity($this->getRequest()->get("quantity")); - - try { - $this->dispatch(TheliaEvents::CART_UPDATEITEM, $cartEvent); - - $this->afterModifyCart(); - - $this->redirectSuccess(); - } catch (PropelException $e) { - $this->getParserContext()->setGeneralError($e->getMessage()); - } - - } - - public function deleteItem() - { - $cartEvent = $this->getCartEvent(); - $cartEvent->setCartItem($this->getRequest()->get("cart_item")); - - try { - $this->getDispatcher()->dispatch(TheliaEvents::CART_DELETEITEM, $cartEvent); - - $this->afterModifyCart(); - - $this->redirectSuccess(); - } catch (PropelException $e) { - \Thelia\Log\Tlog::getInstance()->error(sprintf("error during deleting cartItem with message : %s", $e->getMessage())); - $this->getParserContext()->setGeneralError($e->getMessage()); - } - - } - - /** - * use Thelia\Cart\CartTrait for searching current cart or create a new one - * - * @return \Thelia\Core\Event\Cart\CartEvent - */ - protected function getCartEvent() - { - $cart = $this->getCart($this->getDispatcher(), $this->getRequest()); - - return new CartEvent($cart); - } - - /** - * Find the good way to construct the cart form - * - * @param Request $request - * @return CartAdd - */ - private function getAddCartForm(Request $request) - { - if ($request->isMethod("post")) { - $cartAdd = new CartAdd($request); - } else { - $cartAdd = new CartAdd( - $request, - "form", - array(), - array( - 'csrf_protection' => false, - ) - ); - } - - return $cartAdd; - } - - protected function afterModifyCart() - { - /* recalculate postage amount */ - $order = $this->getSession()->getOrder(); - if (null !== $order) { - $deliveryModule = $order->getModuleRelatedByDeliveryModuleId(); - $deliveryAddress = AddressQuery::create()->findPk($order->chosenDeliveryAddress); - - if (null !== $deliveryModule && null !== $deliveryAddress) { - $moduleInstance = $this->container->get(sprintf('module.%s', $deliveryModule->getCode())); - - $orderEvent = new OrderEvent($order); - - try { - $postage = $moduleInstance->getPostage($deliveryAddress->getCountry()); - - $orderEvent->setPostage($postage); - - $this->getDispatcher()->dispatch(TheliaEvents::ORDER_SET_POSTAGE, $orderEvent); - } - catch (DeliveryException $ex) { - // The postage has been chosen, but changes in the cart causes an exception. - // Reset the postage data in the order - $orderEvent->setDeliveryModule(0); - - $this->getDispatcher()->dispatch(TheliaEvents::ORDER_SET_DELIVERY_MODULE, $orderEvent); - } - } - } - } - -} +. */ +/* */ +/*************************************************************************************/ +namespace Front\Controller; + +use Propel\Runtime\Exception\PropelException; +use Thelia\Controller\Front\BaseFrontController; +use Thelia\Core\Event\Order\OrderEvent; +use Thelia\Form\Exception\FormValidationException; +use Thelia\Core\Event\Cart\CartEvent; +use Thelia\Core\Event\TheliaEvents; +use Symfony\Component\HttpFoundation\Request; +use Thelia\Form\CartAdd; +use Thelia\Model\AddressQuery; + +class CartController extends BaseFrontController +{ + use \Thelia\Cart\CartTrait; + + public function addItem() + { + $request = $this->getRequest(); + + $cartAdd = $this->getAddCartForm($request); + $message = null; + + try { + $form = $this->validateForm($cartAdd); + + $cartEvent = $this->getCartEvent(); + $cartEvent->setNewness($form->get("newness")->getData()); + $cartEvent->setAppend($form->get("append")->getData()); + $cartEvent->setQuantity($form->get("quantity")->getData()); + $cartEvent->setProductSaleElementsId($form->get("product_sale_elements_id")->getData()); + $cartEvent->setProduct($form->get("product")->getData()); + + $this->getDispatcher()->dispatch(TheliaEvents::CART_ADDITEM, $cartEvent); + + $this->afterModifyCart(); + + $this->redirectSuccess(); + + } catch (PropelException $e) { + \Thelia\Log\Tlog::getInstance()->error(sprintf("Failed to add item to cart with message : %s", $e->getMessage())); + $message = "Failed to add this article to your cart, please try again"; + } catch (FormValidationException $e) { + $message = $e->getMessage(); + } + + // If Ajax Request + if ($this->getRequest()->isXmlHttpRequest()) { + $request = $this->getRequest(); + $request->attributes->set('_view', "includes/mini-cart"); + } + + if ($message) { + $cartAdd->setErrorMessage($message); + $this->getParserContext()->addForm($cartAdd); + } + } + + public function changeItem() + { + $cartEvent = $this->getCartEvent(); + $cartEvent->setCartItem($this->getRequest()->get("cart_item")); + $cartEvent->setQuantity($this->getRequest()->get("quantity")); + + try { + $this->dispatch(TheliaEvents::CART_UPDATEITEM, $cartEvent); + + $this->afterModifyCart(); + + $this->redirectSuccess(); + } catch (PropelException $e) { + $this->getParserContext()->setGeneralError($e->getMessage()); + } + + } + + public function deleteItem() + { + $cartEvent = $this->getCartEvent(); + $cartEvent->setCartItem($this->getRequest()->get("cart_item")); + + try { + $this->getDispatcher()->dispatch(TheliaEvents::CART_DELETEITEM, $cartEvent); + + $this->afterModifyCart(); + + $this->redirectSuccess(); + } catch (PropelException $e) { + \Thelia\Log\Tlog::getInstance()->error(sprintf("error during deleting cartItem with message : %s", $e->getMessage())); + $this->getParserContext()->setGeneralError($e->getMessage()); + } + + } + + /** + * use Thelia\Cart\CartTrait for searching current cart or create a new one + * + * @return \Thelia\Core\Event\Cart\CartEvent + */ + protected function getCartEvent() + { + $cart = $this->getCart($this->getDispatcher(), $this->getRequest()); + + return new CartEvent($cart); + } + + /** + * Find the good way to construct the cart form + * + * @param Request $request + * @return CartAdd + */ + private function getAddCartForm(Request $request) + { + if ($request->isMethod("post")) { + $cartAdd = new CartAdd($request); + } else { + $cartAdd = new CartAdd( + $request, + "form", + array(), + array( + 'csrf_protection' => false, + ) + ); + } + + return $cartAdd; + } + + protected function afterModifyCart() + { + /* recalculate postage amount */ + $order = $this->getSession()->getOrder(); + if (null !== $order) { + $deliveryModule = $order->getModuleRelatedByDeliveryModuleId(); + $deliveryAddress = AddressQuery::create()->findPk($order->chosenDeliveryAddress); + + if (null !== $deliveryModule && null !== $deliveryAddress) { + $moduleInstance = $this->container->get(sprintf('module.%s', $deliveryModule->getCode())); + $postage = $moduleInstance->getPostage($deliveryAddress->getCountry()); + + $orderEvent = new OrderEvent($order); + $orderEvent->setPostage($postage); + + $this->getDispatcher()->dispatch(TheliaEvents::ORDER_SET_POSTAGE, $orderEvent); + } + } + } + +} From a3883ef1b6a35079393e42d058d81b9ae98bc6ea Mon Sep 17 00:00:00 2001 From: Franck Allimant Date: Fri, 18 Apr 2014 00:01:19 +0200 Subject: [PATCH 15/18] Fix for #308 --- .../Front/Controller/CartController.php | 34 +++++++++++++------ 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/local/modules/Front/Controller/CartController.php b/local/modules/Front/Controller/CartController.php index 59110d62a..ceda20751 100644 --- a/local/modules/Front/Controller/CartController.php +++ b/local/modules/Front/Controller/CartController.php @@ -23,14 +23,16 @@ namespace Front\Controller; use Propel\Runtime\Exception\PropelException; -use Thelia\Controller\Front\BaseFrontController; -use Thelia\Core\Event\Order\OrderEvent; -use Thelia\Form\Exception\FormValidationException; -use Thelia\Core\Event\Cart\CartEvent; -use Thelia\Core\Event\TheliaEvents; use Symfony\Component\HttpFoundation\Request; +use Thelia\Controller\Front\BaseFrontController; +use Thelia\Core\Event\Cart\CartEvent; +use Thelia\Core\Event\Order\OrderEvent; +use Thelia\Core\Event\TheliaEvents; use Thelia\Form\CartAdd; +use Thelia\Form\Exception\FormValidationException; +use Thelia\Log\Tlog; use Thelia\Model\AddressQuery; +use Thelia\Module\Exception\DeliveryException; class CartController extends BaseFrontController { @@ -60,7 +62,7 @@ class CartController extends BaseFrontController $this->redirectSuccess(); } catch (PropelException $e) { - \Thelia\Log\Tlog::getInstance()->error(sprintf("Failed to add item to cart with message : %s", $e->getMessage())); + Tlog::getInstance()->error(sprintf("Failed to add item to cart with message : %s", $e->getMessage())); $message = "Failed to add this article to your cart, please try again"; } catch (FormValidationException $e) { $message = $e->getMessage(); @@ -108,7 +110,7 @@ class CartController extends BaseFrontController $this->redirectSuccess(); } catch (PropelException $e) { - \Thelia\Log\Tlog::getInstance()->error(sprintf("error during deleting cartItem with message : %s", $e->getMessage())); + Tlog::getInstance()->error(sprintf("error during deleting cartItem with message : %s", $e->getMessage())); $this->getParserContext()->setGeneralError($e->getMessage()); } @@ -160,14 +162,24 @@ class CartController extends BaseFrontController if (null !== $deliveryModule && null !== $deliveryAddress) { $moduleInstance = $this->container->get(sprintf('module.%s', $deliveryModule->getCode())); - $postage = $moduleInstance->getPostage($deliveryAddress->getCountry()); $orderEvent = new OrderEvent($order); - $orderEvent->setPostage($postage); - $this->getDispatcher()->dispatch(TheliaEvents::ORDER_SET_POSTAGE, $orderEvent); + try { + $postage = $moduleInstance->getPostage($deliveryAddress->getCountry()); + + $orderEvent->setPostage($postage); + + $this->getDispatcher()->dispatch(TheliaEvents::ORDER_SET_POSTAGE, $orderEvent); + } + catch (DeliveryException $ex) { + // The postage has been chosen, but changes in the cart causes an exception. + // Reset the postage data in the order + $orderEvent->setDeliveryModule(0); + + $this->getDispatcher()->dispatch(TheliaEvents::ORDER_SET_DELIVERY_MODULE, $orderEvent); + } } } } - } From 4b18c4ffbaaebd7a5d95fe3f63376d596a51a4a1 Mon Sep 17 00:00:00 2001 From: Franck Allimant Date: Fri, 18 Apr 2014 00:03:27 +0200 Subject: [PATCH 16/18] Fix comment --- core/lib/Thelia/Form/BaseForm.php | 492 +++++++++++++++--------------- 1 file changed, 246 insertions(+), 246 deletions(-) diff --git a/core/lib/Thelia/Form/BaseForm.php b/core/lib/Thelia/Form/BaseForm.php index 8dff18cfc..9fd287004 100644 --- a/core/lib/Thelia/Form/BaseForm.php +++ b/core/lib/Thelia/Form/BaseForm.php @@ -1,246 +1,246 @@ -. */ -/* */ -/*************************************************************************************/ -namespace Thelia\Form; - -use Symfony\Component\Form\Extension\Validator\ValidatorExtension; -use Symfony\Component\Form\Forms; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\Form\Extension\HttpFoundation\HttpFoundationExtension; -use Symfony\Component\Form\Extension\Csrf\CsrfExtension; -use Symfony\Component\Form\Extension\Csrf\CsrfProvider\SessionCsrfProvider; -use Symfony\Component\Validator\Validation; -use Thelia\Core\Translation\Translator; -use Thelia\Model\ConfigQuery; -use Thelia\Tools\URL; - -/** - * Base form class for creating form objects - * - * Class BaseForm - * @package Thelia\Form - * @author Manuel Raynaud - */ -abstract class BaseForm -{ - /** - * @var \Symfony\Component\Form\FormFactoryInterface - */ - protected $formBuilder; - - /** - * @var \Symfony\Component\Form\Form - */ - protected $form; - - protected $request; - - private $view = null; - - /** - * true if the form has an error, false otherwise. - * @var boolean - */ - private $has_error = false; - - /** - * The form error message. - * @var string - */ - private $error_message = ''; - - public function __construct(Request $request, $type= "form", $data = array(), $options = array()) - { - $this->request = $request; - - $validator = Validation::createValidatorBuilder(); - - if (!isset($options["attr"]["name"])) { - $options["attr"]["thelia_name"] = $this->getName(); - } - - $builder = Forms::createFormFactoryBuilder() - ->addExtension(new HttpFoundationExtension()); - if (!isset($options["csrf_protection"]) || $options["csrf_protection"] !== false) { - $builder->addExtension( - new CsrfExtension( - new SessionCsrfProvider( - $request->getSession(), - isset($options["secret"]) ? $options["secret"] : ConfigQuery::read("form.secret", md5(__DIR__)) - ) - ) - ); - } - - $translator = Translator::getInstance(); - - $validator - ->setTranslationDomain('validators') - ->setTranslator($translator); - $this->formBuilder = $builder - ->addExtension(new ValidatorExtension($validator->getValidator())) - ->getFormFactory() - ->createNamedBuilder($this->getName(), $type, $data, $this->cleanOptions($options)); - ; - - $this->buildForm(); - - // If not already set, define the success_url field - if (! $this->formBuilder->has('success_url')) { - $this->formBuilder->add("success_url", "text"); - } - - if (! $this->formBuilder->has('error_message')) { - $this->formBuilder->add("error_message", "text"); - } - - $this->form = $this->formBuilder->getForm(); - } - - public function getRequest() - { - return $this->request; - } - - protected function cleanOptions($options) - { - unset($options["csrf_protection"]); - - return $options; - } - - /** - * Returns the absolute URL to redirect the user to if the form is successfully processed. - * - * @param string $default the default URL. If not given, the configured base URL is used. - * - * @return string an absolute URL - */ - public function getSuccessUrl($default = null) - { - $successUrl = $this->form->get('success_url')->getData(); - - if (empty($successUrl)) { - - if ($default === null) $default = ConfigQuery::read('base_url', '/'); - - $successUrl = $default; - } - - return URL::getInstance()->absoluteUrl($successUrl); - } - - public function createView() - { - $this->view = $this->form->createView(); - - return $this; - } - - public function getView() - { - if ($this->view === null) throw new \LogicException("View was not created. Please call BaseForm::createView() first."); - return $this->view; - } - - // -- Error and errro message ---------------------------------------------- - - /** - * Set the error status of the form. - * - * @param boolean $has_error - */ - public function setError($has_error = true) - { - $this->has_error = $has_error; - - return $this; - } - - /** - * Get the cuirrent error status of the form. - * - * @return boolean - */ - public function hasError() - { - return $this->has_error; - } - - /** - * Set the error message related to global form error - * - * @param unknown $message - */ - public function setErrorMessage($message) - { - $this->setError(true); - $this->error_message = $message; - - return $this; - } - - /** - * Get the form error message. - * - * @return string - */ - public function getErrorMessage() - { - return $this->error_message; - } - - /** - * @return \Symfony\Component\Form\Form - */ - public function getForm() - { - return $this->form; - } - - /** - * - * in this function you add all the fields you need for your Form. - * Form this you have to call add method on $this->formBuilder attribute : - * - * $this->formBuilder->add("name", "text") - * ->add("email", "email", array( - * "attr" => array( - * "class" => "field" - * ), - * "label" => "email", - * "constraints" => array( - * new \Symfony\Component\Validator\Constraints\NotBlank() - * ) - * ) - * ) - * ->add('age', 'integer'); - * - * @return null - */ - abstract protected function buildForm(); - - /** - * @return string the name of you form. This name must be unique - */ - abstract public function getName(); -} +. */ +/* */ +/*************************************************************************************/ +namespace Thelia\Form; + +use Symfony\Component\Form\Extension\Validator\ValidatorExtension; +use Symfony\Component\Form\Forms; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\Form\Extension\HttpFoundation\HttpFoundationExtension; +use Symfony\Component\Form\Extension\Csrf\CsrfExtension; +use Symfony\Component\Form\Extension\Csrf\CsrfProvider\SessionCsrfProvider; +use Symfony\Component\Validator\Validation; +use Thelia\Core\Translation\Translator; +use Thelia\Model\ConfigQuery; +use Thelia\Tools\URL; + +/** + * Base form class for creating form objects + * + * Class BaseForm + * @package Thelia\Form + * @author Manuel Raynaud + */ +abstract class BaseForm +{ + /** + * @var \Symfony\Component\Form\FormFactoryInterface + */ + protected $formBuilder; + + /** + * @var \Symfony\Component\Form\Form + */ + protected $form; + + protected $request; + + private $view = null; + + /** + * true if the form has an error, false otherwise. + * @var boolean + */ + private $has_error = false; + + /** + * The form error message. + * @var string + */ + private $error_message = ''; + + public function __construct(Request $request, $type= "form", $data = array(), $options = array()) + { + $this->request = $request; + + $validator = Validation::createValidatorBuilder(); + + if (!isset($options["attr"]["name"])) { + $options["attr"]["thelia_name"] = $this->getName(); + } + + $builder = Forms::createFormFactoryBuilder() + ->addExtension(new HttpFoundationExtension()); + if (!isset($options["csrf_protection"]) || $options["csrf_protection"] !== false) { + $builder->addExtension( + new CsrfExtension( + new SessionCsrfProvider( + $request->getSession(), + isset($options["secret"]) ? $options["secret"] : ConfigQuery::read("form.secret", md5(__DIR__)) + ) + ) + ); + } + + $translator = Translator::getInstance(); + + $validator + ->setTranslationDomain('validators') + ->setTranslator($translator); + $this->formBuilder = $builder + ->addExtension(new ValidatorExtension($validator->getValidator())) + ->getFormFactory() + ->createNamedBuilder($this->getName(), $type, $data, $this->cleanOptions($options)); + ; + + $this->buildForm(); + + // If not already set, define the success_url field + if (! $this->formBuilder->has('success_url')) { + $this->formBuilder->add("success_url", "text"); + } + + if (! $this->formBuilder->has('error_message')) { + $this->formBuilder->add("error_message", "text"); + } + + $this->form = $this->formBuilder->getForm(); + } + + public function getRequest() + { + return $this->request; + } + + protected function cleanOptions($options) + { + unset($options["csrf_protection"]); + + return $options; + } + + /** + * Returns the absolute URL to redirect the user to if the form is successfully processed. + * + * @param string $default the default URL. If not given, the configured base URL is used. + * + * @return string an absolute URL + */ + public function getSuccessUrl($default = null) + { + $successUrl = $this->form->get('success_url')->getData(); + + if (empty($successUrl)) { + + if ($default === null) $default = ConfigQuery::read('base_url', '/'); + + $successUrl = $default; + } + + return URL::getInstance()->absoluteUrl($successUrl); + } + + public function createView() + { + $this->view = $this->form->createView(); + + return $this; + } + + public function getView() + { + if ($this->view === null) throw new \LogicException("View was not created. Please call BaseForm::createView() first."); + return $this->view; + } + + // -- Error and errro message ---------------------------------------------- + + /** + * Set the error status of the form. + * + * @param boolean $has_error + */ + public function setError($has_error = true) + { + $this->has_error = $has_error; + + return $this; + } + + /** + * Get the cuirrent error status of the form. + * + * @return boolean + */ + public function hasError() + { + return $this->has_error; + } + + /** + * Set the error message related to global form error + * + * @param string $message + */ + public function setErrorMessage($message) + { + $this->setError(true); + $this->error_message = $message; + + return $this; + } + + /** + * Get the form error message. + * + * @return string + */ + public function getErrorMessage() + { + return $this->error_message; + } + + /** + * @return \Symfony\Component\Form\Form + */ + public function getForm() + { + return $this->form; + } + + /** + * + * in this function you add all the fields you need for your Form. + * Form this you have to call add method on $this->formBuilder attribute : + * + * $this->formBuilder->add("name", "text") + * ->add("email", "email", array( + * "attr" => array( + * "class" => "field" + * ), + * "label" => "email", + * "constraints" => array( + * new \Symfony\Component\Validator\Constraints\NotBlank() + * ) + * ) + * ) + * ->add('age', 'integer'); + * + * @return null + */ + abstract protected function buildForm(); + + /** + * @return string the name of you form. This name must be unique + */ + abstract public function getName(); +} From 784ab68ca53eb3a76d169e3bccc695d10b743bcd Mon Sep 17 00:00:00 2001 From: Franck Allimant Date: Fri, 18 Apr 2014 00:06:49 +0200 Subject: [PATCH 17/18] Restored previous version --- .../Front/Controller/CouponController.php | 224 +++++++++--------- 1 file changed, 106 insertions(+), 118 deletions(-) diff --git a/local/modules/Front/Controller/CouponController.php b/local/modules/Front/Controller/CouponController.php index 185041ce1..ba7433612 100644 --- a/local/modules/Front/Controller/CouponController.php +++ b/local/modules/Front/Controller/CouponController.php @@ -1,118 +1,106 @@ -. */ -/* */ -/*************************************************************************************/ -namespace Front\Controller; - -use Propel\Runtime\Exception\PropelException; -use Thelia\Controller\Front\BaseFrontController; -use Thelia\Core\Event\Coupon\CouponConsumeEvent; -use Thelia\Core\Event\Order\OrderEvent; -use Thelia\Form\CouponCode; -use Thelia\Form\Exception\FormValidationException; -use Thelia\Core\Event\TheliaEvents; -use Thelia\Log\Tlog; -use Thelia\Model\AddressQuery; -use Thelia\Module\Exception\DeliveryException; - -/** - * Class CouponController - * @package Thelia\Controller\Front - * @author Guillaume MOREL - */ -class CouponController extends BaseFrontController -{ - - /** - * Test Coupon consuming - */ - public function consumeAction() - { - $this->checkAuth(); - $this->checkCartNotEmpty(); - - $message = false; - $couponCodeForm = new CouponCode($this->getRequest()); - - try { - $form = $this->validateForm($couponCodeForm, 'post'); - - $couponCode = $form->get('coupon-code')->getData(); - - if (null === $couponCode || empty($couponCode)) { - $message = true; - throw new \Exception('Coupon code can\'t be empty'); - } - - $couponConsumeEvent = new CouponConsumeEvent($couponCode); - - // Dispatch Event to the Action - $this->getDispatcher()->dispatch(TheliaEvents::COUPON_CONSUME, $couponConsumeEvent); - - /* recalculate postage amount */ - $order = $this->getSession()->getOrder(); - if (null !== $order) { - $deliveryModule = $order->getModuleRelatedByDeliveryModuleId(); - $deliveryAddress = AddressQuery::create()->findPk($order->chosenDeliveryAddress); - - if (null !== $deliveryModule && null !== $deliveryAddress) { - $moduleInstance = $this->container->get(sprintf('module.%s', $deliveryModule->getCode())); - - $orderEvent = new OrderEvent($order); - - try { - $postage = $moduleInstance->getPostage($deliveryAddress->getCountry()); - - $orderEvent->setPostage($postage); - - $this->getDispatcher()->dispatch(TheliaEvents::ORDER_SET_POSTAGE, $orderEvent); - } - catch (DeliveryException $ex) { - // The postage has been chosen, but changes dues to coupon causes an exception. - // Reset the postage data in the order - $orderEvent->setDeliveryModule(0); - - $this->getDispatcher()->dispatch(TheliaEvents::ORDER_SET_DELIVERY_MODULE, $orderEvent); - } - } - } - - $this->redirect($couponCodeForm->getSuccessUrl()); - - } catch (FormValidationException $e) { - $message = sprintf('Please check your coupon code: %s', $e->getMessage()); - } catch (PropelException $e) { - $this->getParserContext()->setGeneralError($e->getMessage()); - } catch (\Exception $e) { - $message = sprintf('Sorry, an error occurred: %s', $e->getMessage()); - } - - if ($message !== false) { - Tlog::getInstance()->error(sprintf("Error during order delivery process : %s. Exception was %s", $message, $e->getMessage())); - - $couponCodeForm->setErrorMessage($message); - - $this->getParserContext() - ->addForm($couponCodeForm) - ->setGeneralError($message); - } - } -} +. */ +/* */ +/*************************************************************************************/ +namespace Front\Controller; + +use Propel\Runtime\Exception\PropelException; +use Thelia\Controller\Front\BaseFrontController; +use Thelia\Core\Event\Coupon\CouponConsumeEvent; +use Thelia\Core\Event\Order\OrderEvent; +use Thelia\Form\CouponCode; +use Thelia\Form\Exception\FormValidationException; +use Thelia\Core\Event\TheliaEvents; +use Thelia\Log\Tlog; +use Thelia\Model\AddressQuery; + +/** + * Class CouponController + * @package Thelia\Controller\Front + * @author Guillaume MOREL + */ +class CouponController extends BaseFrontController +{ + + /** + * Test Coupon consuming + */ + public function consumeAction() + { + $this->checkAuth(); + $this->checkCartNotEmpty(); + + $message = false; + $couponCodeForm = new CouponCode($this->getRequest()); + + try { + $form = $this->validateForm($couponCodeForm, 'post'); + + $couponCode = $form->get('coupon-code')->getData(); + + if (null === $couponCode || empty($couponCode)) { + $message = true; + throw new \Exception('Coupon code can\'t be empty'); + } + + $couponConsumeEvent = new CouponConsumeEvent($couponCode); + + // Dispatch Event to the Action + $this->getDispatcher()->dispatch(TheliaEvents::COUPON_CONSUME, $couponConsumeEvent); + + /* recalculate postage amount */ + $order = $this->getSession()->getOrder(); + if (null !== $order) { + $deliveryModule = $order->getModuleRelatedByDeliveryModuleId(); + $deliveryAddress = AddressQuery::create()->findPk($order->chosenDeliveryAddress); + + if (null !== $deliveryModule && null !== $deliveryAddress) { + $moduleInstance = $this->container->get(sprintf('module.%s', $deliveryModule->getCode())); + $postage = $moduleInstance->getPostage($deliveryAddress->getCountry()); + + $orderEvent = new OrderEvent($order); + $orderEvent->setPostage($postage); + + $this->getDispatcher()->dispatch(TheliaEvents::ORDER_SET_POSTAGE, $orderEvent); + } + } + + $this->redirect($couponCodeForm->getSuccessUrl()); + + } catch (FormValidationException $e) { + $message = sprintf('Please check your coupon code: %s', $e->getMessage()); + } catch (PropelException $e) { + $this->getParserContext()->setGeneralError($e->getMessage()); + } catch (\Exception $e) { + $message = sprintf('Sorry, an error occurred: %s', $e->getMessage()); + } + + if ($message !== false) { + Tlog::getInstance()->error(sprintf("Error during order delivery process : %s. Exception was %s", $message, $e->getMessage())); + + $couponCodeForm->setErrorMessage($message); + + $this->getParserContext() + ->addForm($couponCodeForm) + ->setGeneralError($message); + } + } +} From e02d9c161155cc0cdbd4ca7cef82e590bfbb34af Mon Sep 17 00:00:00 2001 From: Franck Allimant Date: Fri, 18 Apr 2014 00:09:26 +0200 Subject: [PATCH 18/18] Fix for #308 --- .../Front/Controller/CouponController.php | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/local/modules/Front/Controller/CouponController.php b/local/modules/Front/Controller/CouponController.php index ba7433612..3c3c025ab 100644 --- a/local/modules/Front/Controller/CouponController.php +++ b/local/modules/Front/Controller/CouponController.php @@ -26,11 +26,12 @@ use Propel\Runtime\Exception\PropelException; use Thelia\Controller\Front\BaseFrontController; use Thelia\Core\Event\Coupon\CouponConsumeEvent; use Thelia\Core\Event\Order\OrderEvent; +use Thelia\Core\Event\TheliaEvents; use Thelia\Form\CouponCode; use Thelia\Form\Exception\FormValidationException; -use Thelia\Core\Event\TheliaEvents; use Thelia\Log\Tlog; use Thelia\Model\AddressQuery; +use Thelia\Module\Exception\DeliveryException; /** * Class CouponController @@ -74,12 +75,23 @@ class CouponController extends BaseFrontController if (null !== $deliveryModule && null !== $deliveryAddress) { $moduleInstance = $this->container->get(sprintf('module.%s', $deliveryModule->getCode())); - $postage = $moduleInstance->getPostage($deliveryAddress->getCountry()); $orderEvent = new OrderEvent($order); - $orderEvent->setPostage($postage); - $this->getDispatcher()->dispatch(TheliaEvents::ORDER_SET_POSTAGE, $orderEvent); + try { + $postage = $moduleInstance->getPostage($deliveryAddress->getCountry()); + + $orderEvent->setPostage($postage); + + $this->getDispatcher()->dispatch(TheliaEvents::ORDER_SET_POSTAGE, $orderEvent); + } + catch (DeliveryException $ex) { + // The postage has been chosen, but changes dues to coupon causes an exception. + // Reset the postage data in the order + $orderEvent->setDeliveryModule(0); + + $this->getDispatcher()->dispatch(TheliaEvents::ORDER_SET_DELIVERY_MODULE, $orderEvent); + } } }