diff --git a/core/lib/Thelia/Action/Order.php b/core/lib/Thelia/Action/Order.php index a0d98265e..15266fac1 100755 --- a/core/lib/Thelia/Action/Order.php +++ b/core/lib/Thelia/Action/Order.php @@ -61,9 +61,8 @@ class Order extends BaseAction implements EventSubscriberInterface { $order = $event->getOrder(); - $deliveryAddress = $event->getDeliveryAddress(); - $order->setDeliveryModuleId($event->getDeliveryModule()); + $order->setPostage($event->getPostage()); $event->setOrder($order); } diff --git a/core/lib/Thelia/Config/Resources/config.xml b/core/lib/Thelia/Config/Resources/config.xml index 41e49d7d7..326f52145 100755 --- a/core/lib/Thelia/Config/Resources/config.xml +++ b/core/lib/Thelia/Config/Resources/config.xml @@ -64,6 +64,7 @@
+ diff --git a/core/lib/Thelia/Config/Resources/routing/front.xml b/core/lib/Thelia/Config/Resources/routing/front.xml index e702a1938..c1e153af0 100755 --- a/core/lib/Thelia/Config/Resources/routing/front.xml +++ b/core/lib/Thelia/Config/Resources/routing/front.xml @@ -122,6 +122,11 @@ order_delivery + + Thelia\Controller\Front\OrderController::pay + order_invoice + + Thelia\Controller\Front\DefaultController::noAction order_invoice diff --git a/core/lib/Thelia/Controller/Front/BaseFrontController.php b/core/lib/Thelia/Controller/Front/BaseFrontController.php index 69ea8553d..74e918b2d 100755 --- a/core/lib/Thelia/Controller/Front/BaseFrontController.php +++ b/core/lib/Thelia/Controller/Front/BaseFrontController.php @@ -65,4 +65,14 @@ class BaseFrontController extends BaseController $this->redirectToRoute("cart.view"); } } + + protected function checkValidDelivery() + { + $order = $this->getSession()->getOrder(); + if(null === $order || null === $order->chosenDeliveryAddress || null === $order->getDeliveryModuleId()) { + $this->redirectToRoute("order.delivery"); + } + + + } } diff --git a/core/lib/Thelia/Controller/Front/OrderController.php b/core/lib/Thelia/Controller/Front/OrderController.php index 393f71ebd..75fa91b36 100755 --- a/core/lib/Thelia/Controller/Front/OrderController.php +++ b/core/lib/Thelia/Controller/Front/OrderController.php @@ -28,9 +28,12 @@ use Thelia\Core\Event\OrderEvent; use Thelia\Core\Event\TheliaEvents; use Symfony\Component\HttpFoundation\Request; use Thelia\Form\OrderDelivery; +use Thelia\Form\OrderPayment; use Thelia\Log\Tlog; use Thelia\Model\AddressQuery; use Thelia\Model\AreaDeliveryModuleQuery; +use Thelia\Model\CountryQuery; +use Thelia\Model\ModuleQuery; use Thelia\Model\Order; /** @@ -41,7 +44,6 @@ use Thelia\Model\Order; class OrderController extends BaseFrontController { /** - * set billing address * set delivery address * set delivery module */ @@ -59,14 +61,16 @@ class OrderController extends BaseFrontController $deliveryAddressId = $form->get("delivery-address")->getData(); $deliveryModuleId = $form->get("delivery-module")->getData(); + $deliveryAddress = AddressQuery::create()->findPk($deliveryAddressId); + $deliveryModule = ModuleQuery::create()->findPk($deliveryModuleId); - /* check that the delivery address belong to the current customer */ + /* check that the delivery address belongs to the current customer */ $deliveryAddress = AddressQuery::create()->findPk($deliveryAddressId); if($deliveryAddress->getCustomerId() !== $this->getSecurityContext()->getCustomerUser()->getId()) { - throw new \Exception("Address does not belong to the current customer"); + throw new \Exception("Delivery address does not belong to the current customer"); } - /* check that the delivery module fetch the delivery address area */ + /* check that the delivery module fetches the delivery address area */ if(AreaDeliveryModuleQuery::create() ->filterByAreaId($deliveryAddress->getCountry()->getAreaId()) ->filterByDeliveryModuleId($deliveryModuleId) @@ -74,10 +78,18 @@ class OrderController extends BaseFrontController throw new \Exception("Delivery module cannot be use with selected delivery address"); } + /* try to get postage amount */ + $moduleReflection = new \ReflectionClass($deliveryModule->getFullNamespace()); + if ($moduleReflection->isSubclassOf("Thelia\Module\DeliveryModuleInterface") === false) { + throw new \RuntimeException(sprintf("delivery module %s is not a Thelia\Module\DeliveryModuleInterface", $deliveryModule->getCode())); + } + $moduleInstance = $moduleReflection->newInstance(); + $postage = $moduleInstance->getPostage($deliveryAddress->getCountry()); $orderEvent = $this->getOrderEvent(); $orderEvent->setDeliveryAddress($deliveryAddressId); $orderEvent->setDeliveryModule($deliveryModuleId); + $orderEvent->setPostage($postage); $this->getDispatcher()->dispatch(TheliaEvents::ORDER_SET_DELIVERY_ADDRESS, $orderEvent); $this->getDispatcher()->dispatch(TheliaEvents::ORDER_SET_DELIVERY_MODULE, $orderEvent); @@ -105,6 +117,62 @@ class OrderController extends BaseFrontController } + /** + * set invoice address + * set payment module + */ + public function pay() + { + $this->checkAuth(); + $this->checkCartNotEmpty(); + $this->checkValidDelivery(); + + $message = false; + + $orderPayment = new OrderPayment($this->getRequest()); + + try { + $form = $this->validateForm($orderPayment, "post"); + + $deliveryAddressId = $form->get("delivery-address")->getData(); + $deliveryModuleId = $form->get("delivery-module")->getData(); + + /* check that the invoice address belongs to the current customer */ + $deliveryAddress = AddressQuery::create()->findPk($deliveryAddressId); + if($deliveryAddress->getCustomerId() !== $this->getSecurityContext()->getCustomerUser()->getId()) { + throw new \Exception("Invoice address does not belong to the current customer"); + } + + $orderEvent = $this->getOrderEvent(); + $orderEvent->setInvoiceAddress($deliveryAddressId); + $orderEvent->setPaymentModule($deliveryModuleId); + + $this->getDispatcher()->dispatch(TheliaEvents::ORDER_SET_DELIVERY_ADDRESS, $orderEvent); + $this->getDispatcher()->dispatch(TheliaEvents::ORDER_SET_DELIVERY_MODULE, $orderEvent); + + $this->redirectToRoute("order.invoice"); + + } catch (FormValidationException $e) { + $message = sprintf("Please check your input: %s", $e->getMessage()); + } catch (PropelException $e) { + $this->getParserContext()->setGeneralError($e->getMessage()); + } catch (\Exception $e) { + $message = sprintf("Sorry, an error occured: %s", $e->getMessage()); + } + + if ($message !== false) { + Tlog::getInstance()->error(sprintf("Error during order delivery process : %s. Exception was %s", $message, $e->getMessage())); + + $orderPayment->setErrorMessage($message); + + $this->getParserContext() + ->addForm($orderPayment) + ->setGeneralError($message) + ; + } + + } + protected function getOrderEvent() { $order = $this->getOrder($this->getRequest()); diff --git a/core/lib/Thelia/Core/Event/OrderEvent.php b/core/lib/Thelia/Core/Event/OrderEvent.php index 6c2b5ff4b..349fd53a1 100755 --- a/core/lib/Thelia/Core/Event/OrderEvent.php +++ b/core/lib/Thelia/Core/Event/OrderEvent.php @@ -23,17 +23,16 @@ namespace Thelia\Core\Event; -use Thelia\Model\Address; -use Thelia\Model\AddressQuery; -use Thelia\Model\Module; use Thelia\Model\Order; class OrderEvent extends ActionEvent { protected $order = null; - protected $billingAddress = null; + protected $invoiceAddress = null; protected $deliveryAddress = null; protected $deliveryModule = null; + protected $paymentModule = null; + protected $postage = null; /** * @param Order $order @@ -54,7 +53,7 @@ class OrderEvent extends ActionEvent /** * @param $address */ - public function setBillingAddress($address) + public function setInvoiceAddress($address) { $this->deliveryAddress = $address; } @@ -75,6 +74,22 @@ class OrderEvent extends ActionEvent $this->deliveryModule = $module; } + /** + * @param $module + */ + public function setPaymentModule($module) + { + $this->paymentModule = $module; + } + + /** + * @param $postage + */ + public function setPostage($postage) + { + $this->postage = $postage; + } + /** * @return null|Order */ @@ -84,15 +99,15 @@ class OrderEvent extends ActionEvent } /** - * @return array|mixed|Address + * @return null|int */ - public function getBillingAddress() + public function getInvoiceAddress() { - return $this->billingAddress; + return $this->invoiceAddress; } /** - * @return array|mixed|Address + * @return null|int */ public function getDeliveryAddress() { @@ -100,10 +115,26 @@ class OrderEvent extends ActionEvent } /** - * @return array|mixed|Address + * @return null|int */ public function getDeliveryModule() { return $this->deliveryModule; } + + /** + * @return null|int + */ + public function getPaymentModule() + { + return $this->paymentModule; + } + + /** + * @return null|int + */ + public function getPostage() + { + return $this->postage; + } } diff --git a/core/lib/Thelia/Core/Template/Loop/Address.php b/core/lib/Thelia/Core/Template/Loop/Address.php index 1321592f4..9ca4352e9 100755 --- a/core/lib/Thelia/Core/Template/Loop/Address.php +++ b/core/lib/Thelia/Core/Template/Loop/Address.php @@ -54,7 +54,13 @@ class Address extends BaseLoop protected function getArgDefinitions() { return new ArgumentCollection( - Argument::createIntListTypeArgument('id'), + new Argument( + 'id', + new TypeCollection( + new Type\IntListType(), + new Type\EnumType(array('*', 'any')) + ) + ), new Argument( 'customer', new TypeCollection( @@ -63,8 +69,14 @@ class Address extends BaseLoop ), 'current' ), - Argument::createBooleanTypeArgument('default'), - Argument::createIntListTypeArgument('exclude') + Argument::createBooleanOrBothTypeArgument('default'), + new Argument( + 'exclude', + new TypeCollection( + new Type\IntListType(), + new Type\EnumType(array('none')) + ) + ) ); } @@ -79,7 +91,7 @@ class Address extends BaseLoop $id = $this->getId(); - if (null !== $id) { + if (null !== $id && !in_array($id, array('*', 'any'))) { $search->filterById($id, Criteria::IN); } @@ -106,7 +118,7 @@ class Address extends BaseLoop $exclude = $this->getExclude(); - if (!is_null($exclude)) { + if (null !== $exclude && 'none' !== $exclude) { $search->filterById($exclude, Criteria::NOT_IN); } diff --git a/core/lib/Thelia/Core/Template/Loop/BaseSpecificModule.php b/core/lib/Thelia/Core/Template/Loop/BaseSpecificModule.php index 2aaa173dc..6f5f23707 100644 --- a/core/lib/Thelia/Core/Template/Loop/BaseSpecificModule.php +++ b/core/lib/Thelia/Core/Template/Loop/BaseSpecificModule.php @@ -29,7 +29,6 @@ use Thelia\Core\Template\Loop\Argument\ArgumentCollection; use Thelia\Model\ModuleQuery; /** - * Class Delivery * @package Thelia\Core\Template\Loop * @author Manuel Raynaud */ @@ -93,6 +92,8 @@ class BaseSpecificModule extends BaseI18nLoop { $search = ModuleQuery::create(); + $search->filterByActivate(1); + if (null !== $id = $this->getId()) { $search->filterById($id); } diff --git a/core/lib/Thelia/Core/Template/Loop/Country.php b/core/lib/Thelia/Core/Template/Loop/Country.php index f14b97efc..3a05b684a 100755 --- a/core/lib/Thelia/Core/Template/Loop/Country.php +++ b/core/lib/Thelia/Core/Template/Loop/Country.php @@ -87,7 +87,7 @@ class Country extends BaseI18nLoop if (true === $withArea) { $search->filterByAreaId(null, Criteria::ISNOTNULL); - } elseif (false == $withArea) { + } elseif (false === $withArea) { $search->filterByAreaId(null, Criteria::ISNULL); } diff --git a/core/lib/Thelia/Core/Template/Loop/Delivery.php b/core/lib/Thelia/Core/Template/Loop/Delivery.php index dea302797..5d33d398d 100644 --- a/core/lib/Thelia/Core/Template/Loop/Delivery.php +++ b/core/lib/Thelia/Core/Template/Loop/Delivery.php @@ -89,7 +89,7 @@ class Delivery extends BaseSpecificModule ->set('CHAPO', $deliveryModule->getVirtualColumn('i18n_CHAPO')) ->set('DESCRIPTION', $deliveryModule->getVirtualColumn('i18n_DESCRIPTION')) ->set('POSTSCRIPTUM', $deliveryModule->getVirtualColumn('i18n_POSTSCRIPTUM')) - ->set('PRICE', $moduleInstance->calculate($country)) + ->set('POSTAGE', $moduleInstance->getPostage($country)) ; $loopResult->addRow($loopResultRow); diff --git a/core/lib/Thelia/Core/Template/Loop/Payment.php b/core/lib/Thelia/Core/Template/Loop/Payment.php new file mode 100644 index 000000000..542ffb590 --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/Payment.php @@ -0,0 +1,84 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Core\Template\Loop; +use Propel\Runtime\ActiveQuery\Criteria; +use Thelia\Core\Template\Element\LoopResult; +use Thelia\Core\Template\Element\LoopResultRow; +use Thelia\Core\Template\Loop\Argument\Argument; +use Thelia\Module\BaseModule; + +/** + * Class Payment + * @package Thelia\Core\Template\Loop + * @author Etienne Roudeix + */ +class Payment extends BaseSpecificModule +{ + + public function getArgDefinitions() + { + $collection = parent::getArgDefinitions(); + + return $collection; + } + + public function exec(&$pagination) + { + $search = parent::exec($pagination); + /* manage translations */ + $locale = $this->configureI18nProcessing($search); + + $search->filterByType(BaseModule::PAYMENT_MODULE_TYPE, Criteria::EQUAL); + + /* perform search */ + $paymentModules = $this->search($search, $pagination); + + $loopResult = new LoopResult($paymentModules); + + foreach ($paymentModules as $paymentModule) { + $loopResultRow = new LoopResultRow($loopResult, $paymentModule, $this->versionable, $this->timestampable, $this->countable); + + $moduleReflection = new \ReflectionClass($paymentModule->getFullNamespace()); + if ($moduleReflection->isSubclassOf("Thelia\Module\PaymentModuleInterface") === false) { + throw new \RuntimeException(sprintf("payment module %s is not a Thelia\Module\PaymentModuleInterface", $paymentModule->getCode())); + } + $moduleInstance = $moduleReflection->newInstance(); + + $moduleInstance->setRequest($this->request); + $moduleInstance->setDispatcher($this->dispatcher); + + $loopResultRow + ->set('ID', $paymentModule->getId()) + ->set('TITLE', $paymentModule->getVirtualColumn('i18n_TITLE')) + ->set('CHAPO', $paymentModule->getVirtualColumn('i18n_CHAPO')) + ->set('DESCRIPTION', $paymentModule->getVirtualColumn('i18n_DESCRIPTION')) + ->set('POSTSCRIPTUM', $paymentModule->getVirtualColumn('i18n_POSTSCRIPTUM')) + ; + + $loopResult->addRow($loopResultRow); + } + + return $loopResult; + } +} diff --git a/core/lib/Thelia/Core/Template/Smarty/Plugins/DataAccessFunctions.php b/core/lib/Thelia/Core/Template/Smarty/Plugins/DataAccessFunctions.php index 41341f789..ffad52785 100755 --- a/core/lib/Thelia/Core/Template/Smarty/Plugins/DataAccessFunctions.php +++ b/core/lib/Thelia/Core/Template/Smarty/Plugins/DataAccessFunctions.php @@ -188,7 +188,16 @@ class DataAccessFunctions extends AbstractSmartyPlugin public function orderDataAccess($params, &$smarty) { - return $this->dataAccess("Order", $params, $this->request->getSession()->getOrder()); + $order = $this->request->getSession()->getOrder(); + $attribute = $this->getNormalizedParam($params, array('attribute', 'attrib', 'attr')); + switch($attribute) { + case 'postage': + return $order->getPostage(); + case 'delivery_address': + return $order->chosenDeliveryAddress; + } + + throw new \InvalidArgumentException(sprintf("%s has no '%s' attribute", 'Order', $attribute)); } /** @@ -196,6 +205,8 @@ class DataAccessFunctions extends AbstractSmartyPlugin * * @param $params * @param $smarty + * + * @return string */ public function langDataAccess($params, $smarty) { @@ -294,6 +305,7 @@ class DataAccessFunctions extends AbstractSmartyPlugin */ public function getPluginDescriptors() { + return array( new SmartyPluginDescriptor('function', 'admin', $this, 'adminDataAccess'), new SmartyPluginDescriptor('function', 'customer', $this, 'customerDataAccess'), diff --git a/core/lib/Thelia/Form/OrderPayment.php b/core/lib/Thelia/Form/OrderPayment.php new file mode 100755 index 000000000..d3ebe4daf --- /dev/null +++ b/core/lib/Thelia/Form/OrderPayment.php @@ -0,0 +1,94 @@ +. */ +/* */ +/*************************************************************************************/ +namespace Thelia\Form; + +use Symfony\Component\Validator\Constraints; +use Symfony\Component\Validator\ExecutionContextInterface; +use Thelia\Model\AddressQuery; +use Thelia\Model\ConfigQuery; +use Thelia\Core\Translation\Translator; +use Thelia\Model\ModuleQuery; +use Thelia\Module\BaseModule; + +/** + * Class OrderPayment + * @package Thelia\Form + * @author Etienne Roudeix + */ +class OrderPayment extends BaseForm +{ + protected function buildForm() + { + $this->formBuilder + ->add("invoice-address", "integer", array( + "required" => true, + "constraints" => array( + new Constraints\NotBlank(), + new Constraints\Callback(array( + "methods" => array( + array($this, "verifyInvoiceAddress") + ) + )) + ) + )) + ->add("payment-module", "integer", array( + "required" => true, + "constraints" => array( + new Constraints\NotBlank(), + new Constraints\Callback(array( + "methods" => array( + array($this, "verifyPaymentModule") + ) + )) + ) + )); + } + + public function verifyInvoiceAddress($value, ExecutionContextInterface $context) + { + $address = AddressQuery::create() + ->findPk($value); + + if(null === $address) { + $context->addViolation("Address ID not found"); + } + } + + public function verifyPaymentModule($value, ExecutionContextInterface $context) + { + $module = ModuleQuery::create() + ->filterByType(BaseModule::PAYMENT_MODULE_TYPE) + ->filterByActivate(1) + ->filterById($value) + ->find(); + + if(null === $module) { + $context->addViolation("Payment module ID not found"); + } + } + + public function getName() + { + return "thelia_order_payment"; + } +} \ No newline at end of file diff --git a/core/lib/Thelia/Model/Order.php b/core/lib/Thelia/Model/Order.php index 2bc014d27..e2eb43971 100755 --- a/core/lib/Thelia/Model/Order.php +++ b/core/lib/Thelia/Model/Order.php @@ -7,7 +7,7 @@ use Thelia\Model\Base\Order as BaseOrder; class Order extends BaseOrder { public $chosenDeliveryAddress = null; - public $chosenInvoiceModule = null; + public $chosenInvoiceAddress = null; /** * calculate the total amount diff --git a/core/lib/Thelia/Module/DeliveryModuleInterface.php b/core/lib/Thelia/Module/DeliveryModuleInterface.php index 72f8769bc..17b000d4f 100644 --- a/core/lib/Thelia/Module/DeliveryModuleInterface.php +++ b/core/lib/Thelia/Module/DeliveryModuleInterface.php @@ -34,5 +34,5 @@ interface DeliveryModuleInterface extends BaseModuleInterface * * @return mixed */ - public function calculate(Country $country); + public function getPostage(Country $country); } diff --git a/local/modules/Colissimo/Colissimo.php b/local/modules/Colissimo/Colissimo.php index 2fe9cd0b9..14ad36b0d 100755 --- a/local/modules/Colissimo/Colissimo.php +++ b/local/modules/Colissimo/Colissimo.php @@ -61,7 +61,7 @@ class Colissimo extends BaseModule implements DeliveryModuleInterface * @param Country $country * @return mixed */ - public function calculate(Country $country) + public function getPostage(Country $country) { // TODO: Implement calculate() method. return 2; diff --git a/templates/default/order_delivery.html b/templates/default/order_delivery.html index d72cfedf2..46a5be64e 100644 --- a/templates/default/order_delivery.html +++ b/templates/default/order_delivery.html @@ -128,7 +128,7 @@ {form_field form=$form field='delivery-module'} {/form_field} - {$TITLE} / {currency attr="symbol"} {$PRICE} + {$TITLE} / {currency attr="symbol"} {$POSTAGE} {/loop} diff --git a/templates/default/order_invoice.html b/templates/default/order_invoice.html index 2b76454e9..033c46838 100644 --- a/templates/default/order_invoice.html +++ b/templates/default/order_invoice.html @@ -25,12 +25,19 @@ - + {form name="thelia.order.payment"} + + + + {form_hidden_fields form=$form} + + {if $form_error}
{$form_error_message}
{/if} + @@ -123,7 +130,7 @@ @@ -151,32 +158,105 @@
+ {loop type="address" name="delivery-address" id="{order attr="delivery_address"}"}
Delivery address
- M. DUPONT Jean - Agency XY + {loop type="title" name="customer.title.info" id=$TITLE}{$SHORT}{/loop} {$LASTNAME|upper} {$FIRSTNAME|ucwords} + {$COMPANY}
- street name of my business
- 75000 - City, Country + {$ADDRESS1}
+ {if $ADDRESS2 != ""} + {$ADDRESS2}
+ {/if} + {if $ADDRESS3 != ""} + {$ADDRESS3}
+ {/if} + {$ZIPCODE} + {$CITY}, {loop type="country" name="customer.country.info" id=$COUNTRY}{$TITLE}{/loop}
+ {/loop}
+ + {form_field form=$form field='invoice-address'} +
Billing address
+ + {if $error} + {$message} + {/if} +
- M. DUPONT Jean - Agency XY -
- street name of my business
- 75000 - City, Country -
- Change address + +
Shipping Tax
- {order attr="postage"} + {currency attr="symbol"} {order attr="postage"}
+ + {loop type="address" name="invoice-address" default="{if !$error && $value}*{else}true{/if}" id="{if !$error && $value}{$value}{else}*{/if}"} + + + + + + + {if !$error} + + + + {/if} + + {/loop} + + {loop type="address" name="invoice-address" default="{if !$error && $value}*{else}false{/if}" exclude="{if !$error && $value}{$value}{else}none{/if}"} + + + + + + + {/loop} + +
+ {loop type="title" name="customer.title.info" id=$TITLE}{$SHORT}{/loop} {$LASTNAME|upper} {$FIRSTNAME|ucwords} + {$COMPANY} +
+ {$ADDRESS1}
+ {if $ADDRESS2 != ""} + {$ADDRESS2}
+ {/if} + {if $ADDRESS3 != ""} + {$ADDRESS3}
+ {/if} + {$ZIPCODE} + {$CITY}, {loop type="country" name="customer.country.info" id=$COUNTRY}{$TITLE}{/loop} +
+
+ +
+ Change address +
+ {loop type="title" name="customer.title.info" id=$TITLE}{$SHORT}{/loop} {$LASTNAME|upper} {$FIRSTNAME|ucwords} + {$COMPANY} +
+ {$ADDRESS1}
+ {if $ADDRESS2 != ""} + {$ADDRESS2}
+ {/if} + {if $ADDRESS3 != ""} + {$ADDRESS3}
+ {/if} + {$ZIPCODE} + {$CITY}, {loop type="country" name="customer.country.info" id=$COUNTRY}{$TITLE}{/loop} +
+
+ +
+ + + {/form_field}
Choose your payment method
@@ -195,10 +275,12 @@
- Back - + Back + + {/form} + @@ -209,8 +291,16 @@ {block name="javascript-initialization"} {/block} \ No newline at end of file