Merge branch 'master' of github.com:thelia/thelia

This commit is contained in:
Manuel Raynaud
2013-09-17 20:29:47 +02:00
24 changed files with 534 additions and 62 deletions

View File

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

View File

@@ -24,6 +24,7 @@
<loop class="Thelia\Core\Template\Loop\Order" name="order"/>
<loop class="Thelia\Core\Template\Loop\OrderStatus" name="order-status"/>
<loop class="Thelia\Core\Template\Loop\CategoryPath" name="category-path"/>
<loop class="Thelia\Core\Template\Loop\Payment" name="payment"/>
<loop class="Thelia\Core\Template\Loop\Product" name="product"/>
<loop class="Thelia\Core\Template\Loop\ProductSaleElements" name="product_sale_elements"/>
<loop class="Thelia\Core\Template\Loop\Feed" name="feed"/>
@@ -64,6 +65,7 @@
<form name="thelia.cart.add" class="Thelia\Form\CartAdd"/>
<form name="thelia.order.delivery" class="Thelia\Form\OrderDelivery"/>
<form name="thelia.order.payment" class="Thelia\Form\OrderPayment"/>
<form name="thelia.admin.config.creation" class="Thelia\Form\ConfigCreationForm"/>
<form name="thelia.admin.config.modification" class="Thelia\Form\ConfigModificationForm"/>

View File

@@ -112,16 +112,21 @@
<default key="_view">cart</default>
</route>
<route id="order.delivery" path="/order/delivery" methods="post">
<route id="order.delivery.process" path="/order/delivery" methods="post">
<default key="_controller">Thelia\Controller\Front\OrderController::deliver</default>
<default key="_view">order_delivery</default>
</route>
<route id="order.delivery.process" path="/order/delivery">
<route id="order.delivery" path="/order/delivery">
<default key="_controller">Thelia\Controller\Front\DefaultController::noAction</default>
<default key="_view">order_delivery</default>
</route>
<route id="order.invoice.process" path="/order/invoice" methods="post">
<default key="_controller">Thelia\Controller\Front\OrderController::pay</default>
<default key="_view">order_invoice</default>
</route>
<route id="order.invoice" path="/order/invoice">
<default key="_controller">Thelia\Controller\Front\DefaultController::noAction</default>
<default key="_view">order_invoice</default>

View File

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

View File

@@ -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,25 +61,35 @@ 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()
->filterByDeliveryModuleId($deliveryModuleId)
->count() == 0) {
throw new \Exception("PUKE");
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());

View File

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

View File

@@ -28,8 +28,10 @@ use Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Router;
use Thelia\Core\Template\Exception\ResourceNotFoundException;
use Thelia\Core\Template\ParserInterface;
use Thelia\Exception\OrderException;
use Thelia\Tools\Redirect;
use Thelia\Tools\URL;
use Thelia\Core\Security\Exception\AuthenticationException;
@@ -87,6 +89,19 @@ class ViewListener implements EventSubscriberInterface
// Redirect to the login template
Redirect::exec($this->container->get('thelia.url.manager')->viewUrl($ex->getLoginTemplate()));
} catch (OrderException $e) {
switch($e->getCode()) {
case OrderException::CART_EMPTY:
// Redirect to the cart template
Redirect::exec($this->container->get('router.chainRequest')->generate($e->cartRoute, $e->arguments, Router::ABSOLUTE_URL));
break;
case OrderException::UNDEFINED_DELIVERY:
// Redirect to the delivery choice template
Redirect::exec($this->container->get('router.chainRequest')->generate($e->orderDeliveryRoute, $e->arguments, Router::ABSOLUTE_URL));
break;
}
throw $e;
}
}

View File

@@ -218,6 +218,9 @@ class Session extends BaseSession
return $this;
}
/**
* @return Order
*/
public function getOrder()
{
return $this->get("thelia.order");

View File

@@ -128,7 +128,7 @@ class RewritingRouter implements RouterInterface, RequestMatcherInterface
*/
public function generate($name, $parameters = array(), $referenceType = self::ABSOLUTE_PATH)
{
// TODO: Implement generate() method.
throw new RouteNotFoundException();
}
/**

View File

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

View File

@@ -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 <mraynaud@openstudio.fr>
*/
@@ -93,6 +92,8 @@ class BaseSpecificModule extends BaseI18nLoop
{
$search = ModuleQuery::create();
$search->filterByActivate(1);
if (null !== $id = $this->getId()) {
$search->filterById($id);
}

View File

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

View File

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

View File

@@ -0,0 +1,84 @@
<?php
/*************************************************************************************/
/* */
/* Thelia */
/* */
/* Copyright (c) OpenStudio */
/* email : info@thelia.net */
/* web : http://www.thelia.net */
/* */
/* This program is free software; you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
/* the Free Software Foundation; either version 3 of the License */
/* */
/* This program is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* */
/*************************************************************************************/
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 <eroudeix@gmail.com>
*/
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;
}
}

View File

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

View File

@@ -78,7 +78,17 @@ class Security extends AbstractSmartyPlugin
{
$cart = $this->request->getSession()->getCart();
if($cart===null || $cart->countCartItems() == 0) {
throw new OrderException('Cart must not be empty', OrderException::CART_EMPTY);
throw new OrderException('Cart must not be empty', OrderException::CART_EMPTY, array('empty' => 1));
}
return "";
}
public function checkValidDeliveryFunction($params, &$smarty)
{
$order = $this->request->getSession()->getOrder();
if(null === $order || null === $order->chosenDeliveryAddress || null === $order->getDeliveryModuleId()) {
throw new OrderException('Delivery must be defined', OrderException::UNDEFINED_DELIVERY, array('missing' => 1));
}
return "";
@@ -94,6 +104,7 @@ class Security extends AbstractSmartyPlugin
return array(
new SmartyPluginDescriptor('function', 'check_auth', $this, 'checkAuthFunction'),
new SmartyPluginDescriptor('function', 'check_cart_not_empty', $this, 'checkCartNotEmptyFunction'),
new SmartyPluginDescriptor('function', 'check_valid_delivery', $this, 'checkValidDeliveryFunction'),
);
}
}

View File

@@ -25,12 +25,25 @@ namespace Thelia\Exception;
class OrderException extends \RuntimeException
{
/**
* @var string The cart template name
*/
public $cartRoute = "cart.view";
public $orderDeliveryRoute = "order.delivery";
public $arguments = array();
const UNKNOWN_EXCEPTION = 0;
const CART_EMPTY = 100;
public function __construct($message, $code = null, $previous = null)
const UNDEFINED_DELIVERY = 200;
public function __construct($message, $code = null, $arguments = array(), $previous = null)
{
if(is_array($arguments)) {
$this->arguments = $arguments;
}
if ($code === null) {
$code = self::UNKNOWN_EXCEPTION;
}

View File

@@ -0,0 +1,94 @@
<?php
/*************************************************************************************/
/* */
/* Thelia */
/* */
/* Copyright (c) OpenStudio */
/* email : info@thelia.net */
/* web : http://www.thelia.net */
/* */
/* This program is free software; you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
/* the Free Software Foundation; either version 3 of the License */
/* */
/* This program is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* */
/*************************************************************************************/
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 <eroudeix@openstudio.fr>
*/
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";
}
}

View File

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

View File

@@ -34,5 +34,5 @@ interface DeliveryModuleInterface extends BaseModuleInterface
*
* @return mixed
*/
public function calculate(Country $country);
public function getPostage(Country $country);
}

View File

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

View File

@@ -1124,6 +1124,7 @@ td.product,
> tr {
> td {
&.price,
&.unitprice,
&.qty,
&.subprice { padding: 35px 10px; }
}

View File

@@ -128,7 +128,7 @@
{form_field form=$form field='delivery-module'}
<input type="radio" name="{$name}" {if $value == $ID}checked="checked"{/if} value="{$ID}">
{/form_field}
<strong>{$TITLE}</strong> / {currency attr="symbol"} {$PRICE}
<strong>{$TITLE}</strong> / {currency attr="symbol"} {$POSTAGE}
</label>
</div>
{/loop}

View File

@@ -1,5 +1,11 @@
{extends file="layout.tpl"}
{block name="no-return-functions"}
{check_auth context="front" roles="CUSTOMER" login_tpl="login"}
{check_cart_not_empty}
{check_valid_delivery}
{/block}
{block name="breadcrumb"}
<nav class="nav-breadcrumb" role="navigation" aria-labelledby="breadcrumb-label">
<strong id="breadcrumb-label">You are here: </strong>
@@ -18,13 +24,20 @@
<h1 id="main-label" class="page-header">Your Cart</h1>
<div class="btn-group checkout-progress">
<a href="cart.php" role="button" class="btn btn-step"><span class="step-nb">1</span> <span class="step-label"> <span>Your Cart</span></a>
<a href="cart-step2.php" role="button" class="btn btn-step"><span class="step-nb">2</span> <span class="step-label">Billing and delivery</span></a>
<a href="cart-step3.php" role="button" class="btn btn-step active"><span class="step-nb">3</span> <span class="step-label">Check my order</span></a>
<a href="cart-step4.php" role="button" class="btn btn-step disabled"><span class="step-nb">4</span> <span class="step-label">Secure payment</span></a>
<a href="{url path="/cart"}" role="button" class="btn btn-step"><span class="step-nb">1</span> <span class="step-label"> <span>Your Cart</span></a>
<a href="{url path="/order/delivery"}" role="button" class="btn btn-step"><span class="step-nb">2</span> <span class="step-label">Billing and delivery</span></a>
<a href="#" role="button" class="btn btn-step active"><span class="step-nb">3</span> <span class="step-label">Check my order</span></a>
<a href="#" role="button" class="btn btn-step disabled"><span class="step-nb">4</span> <span class="step-label">Secure payment</span></a>
</div>
<form id="form-cart" action="cart-step4.php" method="post" role="form">
{form name="thelia.order.payment"}
<form id="form-cart-payment" action="{url path="/order/invoice"}" method="post" role="form" {form_enctype form=$form}>
{form_hidden_fields form=$form}
{if $form_error}<div class="alert alert-danger">{$form_error_message}</div>{/if}
<table class="table table-cart">
<colgroup>
<col width="150">
@@ -43,6 +56,10 @@
<span class="hidden-xs">Unit Price</span>
<span class="visible-xs">Price</span>
</th>
<th class="qty">
<span class="hidden-xs">Quantity</span>
<span class="visible-xs">Quantity</span>
</th>
<th class="subprice">
<span class="hidden-xs">Total <abbr title="Tax Inclusive">TTC</abbr></span>
<span class="visible-xs">Total</span>
@@ -96,6 +113,9 @@
<div class="special-price"><span class="price">{currency attr="symbol"} {$TAXED_PRICE}</span></div>
{/if}
</td>
<td class="qty">
<span class="price">{$QUANTITY}</span>
</td>
<td class="subprice">
<span class="price">{currency attr="symbol"} {$real_price * $QUANTITY}</span>
</td>
@@ -106,11 +126,11 @@
</tbody>
<tfoot>
<tr >
<td rowspan="3" colspan="2" class="empty">&nbsp;</td>
<td rowspan="3" colspan="3" class="empty">&nbsp;</td>
<th class="shipping">Shipping Tax</th>
<td class="shipping">
<div class="shipping-price">
<span class="price">{order attr="postage"}</span>
<span class="price">{currency attr="symbol"} {order attr="postage"}</span>
</div>
</td>
</tr>
@@ -129,7 +149,7 @@
<th class="total">Total <abbr title="Tax Inclusive">TTC</abbr></th>
<td class="total">
<div class="total-price">
<span class="price">$200.00</span>
<span class="price">{currency attr="symbol"} {{cart attr="total_taxed_price"} + {order attr="postage"}}</span>
</div>
</td>
</tr>
@@ -138,38 +158,115 @@
<div id="cart-address">
<div class="panel">
{loop type="address" name="delivery-address" id="{order attr="delivery_address"}"}
<div class="panel-heading">Delivery address</div>
<div class="panel-body">
<span class="fn">M. DUPONT Jean</span>
<span class="org">Agency XY</span>
<span class="fn">{loop type="title" name="customer.title.info" id=$TITLE}{$SHORT}{/loop} {$LASTNAME|upper} {$FIRSTNAME|ucwords}</span>
<span class="org">{$COMPANY}</span>
<address class="adr">
<span class="street-address">street name of my business</span><br>
<span class="postal-code">75000</span>
<span class="locality">City, <span class="country-name">Country</span></span>
<span class="street-address">{$ADDRESS1}</span><br>
{if $ADDRESS2 != ""}
<span class="street-address">{$ADDRESS2}</span><br>
{/if}
{if $ADDRESS3 != ""}
<span class="street-address">{$ADDRESS3}</span><br>
{/if}
<span class="postal-code">{$ZIPCODE}</span>
<span class="locality">{$CITY}, <span class="country-name">{loop type="country" name="customer.country.info" id=$COUNTRY}{$TITLE}{/loop}</span></span>
</address>
</div>
{/loop}
</div>
{form_field form=$form field='invoice-address'}
<div class="panel">
<div class="panel-heading">Billing address</div>
{if $error}
<span class="help-block"><span class="icon-remove"></span> {$message}</span>
{/if}
<div class="panel-body">
<span class="fn">M. DUPONT Jean</span>
<span class="org">Agency XY</span>
<table class="col-md-12">
{loop type="address" name="invoice-address" default="{if !$error && $value}*{else}true{/if}" id="{if !$error && $value}{$value}{else}*{/if}"}
<tr>
<td>
<span class="fn">{loop type="title" name="customer.title.info" id=$TITLE}{$SHORT}{/loop} {$LASTNAME|upper} {$FIRSTNAME|ucwords}</span>
<span class="org">{$COMPANY}</span>
<address class="adr">
<span class="street-address">street name of my business</span><br>
<span class="postal-code">75000</span>
<span class="locality">City, <span class="country-name">Country</span></span>
<span class="street-address">{$ADDRESS1}</span><br>
{if $ADDRESS2 != ""}
<span class="street-address">{$ADDRESS2}</span><br>
{/if}
{if $ADDRESS3 != ""}
<span class="street-address">{$ADDRESS3}</span><br>
{/if}
<span class="postal-code">{$ZIPCODE}</span>
<span class="locality">{$CITY}, <span class="country-name">{loop type="country" name="customer.country.info" id=$COUNTRY}{$TITLE}{/loop}</span></span>
</address>
<a href="address.php" class="btn btn-change-address">Change address</a>
</td>
<td>
<input class="js-invoice-address-selector {if !$error}hidden{/if}" type="radio" name="{$name}" value="{$ID}" {if $value == $ID OR !$error}checked="checked"{/if}>
</td>
</tr>
{if !$error}
<tr class="js-change-invoice-address">
<td colspan="2">
<a href="#" class="btn btn-change-address">Change address</a>
</td>
</tr>
{/if}
{/loop}
{loop type="address" name="invoice-address" default="{if !$error && $value}*{else}false{/if}" exclude="{if !$error && $value}{$value}{else}none{/if}"}
<tr class="js-other-invoice-address {if !$error}hidden{/if}">
<td>
<span class="fn">{loop type="title" name="customer.title.info" id=$TITLE}{$SHORT}{/loop} {$LASTNAME|upper} {$FIRSTNAME|ucwords}</span>
<span class="org">{$COMPANY}</span>
<address class="adr">
<span class="street-address">{$ADDRESS1}</span><br>
{if $ADDRESS2 != ""}
<span class="street-address">{$ADDRESS2}</span><br>
{/if}
{if $ADDRESS3 != ""}
<span class="street-address">{$ADDRESS3}</span><br>
{/if}
<span class="postal-code">{$ZIPCODE}</span>
<span class="locality">{$CITY}, <span class="country-name">{loop type="country" name="customer.country.info" id=$COUNTRY}{$TITLE}{/loop}</span></span>
</address>
</td>
<td>
<input class="js-invoice-address-selector {if !$error}hidden{/if}" type="radio" name="{$name}" value="{$ID}" {if $value == $ID}checked="checked"{/if}>
</td>
</tr>
{/loop}
</table>
</div>
</div>
</div>
{/form_field}
{form_field form=$form field='payment-module'}
<div id="payment-method" class="panel">
<div class="panel-heading">Choose your payment method</div>
<div class="panel-body">
<ul class="list-payment">
<?php foreach ($payment as $key => $value) { ?>
{loop type="payment" name="payments" force_return="true"}
<li>
<div class="radio">
<label for="payment_<?php echo $key; ?>">
@@ -178,14 +275,20 @@
</label>
</div>
</li>
<?php } ?>
{/loop}
</div>
</div>
<a href="cart-step2.php" role="button" class="btn btn-back"><span>Back</span></a>
<button type="submit" class="btn btn-checkout-next"><span>Next Step</span></button>
{/form_field}
<a href="{url path="/order/delivery"}" role="button" class="btn btn-back"><span>Back</span></a>
<button type="submit" class="btn btn-checkout-next"><span>TO REMOVE</span></button>
</form>
{/form}
</article>
@@ -196,8 +299,16 @@
{block name="javascript-initialization"}
<script type="text/javascript">
jQuery(function($cart) {
jQuery(function($order) {
$order('.js-change-invoice-address').on('click', 'a', function(e) {
e.preventDefault();
$order('.js-other-invoice-address').removeClass('hidden');
$order('.js-invoice-address-selector').removeClass('hidden');
$order('#js-invoice-address-default-selector').unbind().remove();
$order('.js-change-invoice-address').unbind().remove();
});
});
</script>
{/block}