From 8be785e9b37ef4e0912243594a5687459f0d2608 Mon Sep 17 00:00:00 2001 From: gmorel Date: Tue, 10 Sep 2013 20:00:43 +0200 Subject: [PATCH 01/32] WIP - Coupon Add/Edit/Delete rule AJAX --- core/lib/Thelia/Action/Coupon.php | 54 ++-- .../Rule/AvailableForTotalAmountManager.php | 144 ----------- .../Rule/AvailableForXArticlesManager.php | 123 +-------- .../Controller/Admin/CouponController.php | 200 ++++++++------- core/lib/Thelia/Core/Event/TheliaEvents.php | 16 -- core/lib/Thelia/Model/Coupon.php | 92 +++---- templates/admin/default/coupon-create.html | 2 +- templates/admin/default/coupon-update.html | 140 +++++++--- templates/admin/default/coupon/form.html | 240 +++++++++--------- .../admin/default/coupon/rule-input-ajax.html | 14 +- templates/admin/default/coupon/rules.html | 6 +- 11 files changed, 409 insertions(+), 622 deletions(-) diff --git a/core/lib/Thelia/Action/Coupon.php b/core/lib/Thelia/Action/Coupon.php index fee349585..7a7babf01 100755 --- a/core/lib/Thelia/Action/Coupon.php +++ b/core/lib/Thelia/Action/Coupon.php @@ -24,6 +24,7 @@ namespace Thelia\Action; use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Thelia\Constraint\ConstraintFactory; use Thelia\Core\Event\Coupon\CouponCreateOrUpdateEvent; use Thelia\Core\Event\TheliaEvents; use Thelia\Model\Coupon as CouponModel; @@ -68,18 +69,6 @@ class Coupon extends BaseAction implements EventSubscriberInterface $this->createOrUpdate($coupon, $event); } - /** - * Occurring when a Coupon rule is about to be created - * - * @param CouponCreateOrUpdateEvent $event Event creation or update Event - */ - public function createRule(CouponCreateOrUpdateEvent $event) - { - $coupon = $event->getCoupon(); - - $this->createOrUpdate($coupon, $event); - } - /** * Occurring when a Coupon rule is about to be updated * @@ -89,19 +78,7 @@ class Coupon extends BaseAction implements EventSubscriberInterface { $coupon = $event->getCoupon(); - $this->createOrUpdate($coupon, $event); - } - - /** - * Occurring when a Coupon rule is about to be deleted - * - * @param CouponCreateOrUpdateEvent $event Event creation or update Event - */ - public function deleteRule(CouponCreateOrUpdateEvent $event) - { - $coupon = $event->getCoupon(); - - $this->createOrUpdate($coupon, $event); + $this->createOrUpdateRule($coupon, $event); } /** @@ -130,6 +107,7 @@ class Coupon extends BaseAction implements EventSubscriberInterface $event->getTitle(), $event->getAmount(), $event->getEffect(), + $event->isRemovingPostage(), $event->getShortDescription(), $event->getDescription(), $event->isEnabled(), @@ -137,7 +115,28 @@ class Coupon extends BaseAction implements EventSubscriberInterface $event->isAvailableOnSpecialOffers(), $event->isCumulative(), $event->getMaxUsage(), - $event->getRules(), + $event->getLocale() + ); + + $event->setCoupon($coupon); + } + + /** + * Call the Model and delegate the create or delete action + * Feed the Event with the updated model + * + * @param CouponModel $coupon Model to save + * @param CouponCreateOrUpdateEvent $event Event containing data + */ + protected function createOrUpdateRule(CouponModel $coupon, CouponCreateOrUpdateEvent $event) + { + $coupon->setDispatcher($this->getDispatcher()); + + /** @var ConstraintFactory $constraintFactory */ + $constraintFactory = $this->container->get('thelia.constraint.factory'); + + $coupon->createOrUpdateRules( + $constraintFactory->serializeCouponRuleCollection($event->getRules()), $event->getLocale() ); @@ -172,8 +171,7 @@ class Coupon extends BaseAction implements EventSubscriberInterface TheliaEvents::COUPON_DISABLE => array("disable", 128), TheliaEvents::COUPON_ENABLE => array("enable", 128), TheliaEvents::COUPON_CONSUME => array("consume", 128), - TheliaEvents::COUPON_RULE_UPDATE => array("updateRule", 128), - TheliaEvents::COUPON_RULE_DELETE => array("deleteRule", 128) + TheliaEvents::COUPON_RULE_UPDATE => array("updateRule", 128) ); } } diff --git a/core/lib/Thelia/Constraint/Rule/AvailableForTotalAmountManager.php b/core/lib/Thelia/Constraint/Rule/AvailableForTotalAmountManager.php index 6ab746e6c..9f1bf23a0 100644 --- a/core/lib/Thelia/Constraint/Rule/AvailableForTotalAmountManager.php +++ b/core/lib/Thelia/Constraint/Rule/AvailableForTotalAmountManager.php @@ -73,70 +73,6 @@ class AvailableForTotalAmountManager extends CouponRuleAbstract ) ); -// /** @var RuleValidator Price Validator */ -// protected $priceValidator = null; - -// /** -// * Check if backoffice inputs are relevant or not -// * -// * @throws InvalidRuleOperatorException if Operator is not allowed -// * @throws InvalidRuleValueException if Value is not allowed -// * @return bool -// */ -// public function checkBackOfficeInput() -// { -// if (!isset($this->validators) -// || empty($this->validators) -// ||!isset($this->validators[self::PARAM1_PRICE]) -// ||!isset($this->validators[self::PARAM1_PRICE]) -// ) { -// throw new InvalidRuleValueException(get_class(), self::PARAM1_PRICE); -// } -// -// /** @var RuleValidator $ruleValidator */ -// $ruleValidator = $this->validators[self::PARAM1_PRICE]; -// /** @var PriceParam $price */ -// $price = $ruleValidator->getParam(); -// -// if (!$price instanceof PriceParam) { -// throw new InvalidRuleValueException(get_class(), self::PARAM1_PRICE); -// } -// -// $this->checkBackOfficeInputsOperators(); -// -// return $this->isPriceValid($price->getPrice(), $price->getCurrency()); -// } - -// /** -// * Check if Checkout inputs are relevant or not -// * -// * @throws InvalidRuleValueException if Value is not allowed -// * @return bool -// */ -// public function checkCheckoutInput() -// { -// $currency = $this->adapter->getCheckoutCurrency(); -// if (empty($currency)) { -// throw new InvalidRuleValueException( -// get_class(), self::PARAM1_CURRENCY -// ); -// } -// -// $price = $this->adapter->getCartTotalPrice(); -// if (empty($price)) { -// throw new InvalidRuleValueException( -// get_class(), self::PARAM1_PRICE -// ); -// } -// -// $this->paramsToValidate = array( -// self::PARAM1_PRICE => $this->adapter->getCartTotalPrice(), -// self::PARAM1_CURRENCY => $this->adapter->getCheckoutCurrency() -// ); -// -// return $this->isPriceValid($price, $currency); -// } - /** * Check validators relevancy and store them * @@ -249,49 +185,6 @@ class AvailableForTotalAmountManager extends CouponRuleAbstract return false; } -// /** -// * Check if a price is valid -// * -// * @param float $price Price to check -// * @param string $currency Price currency -// * -// * @throws InvalidRuleValueException if Value is not allowed -// * @return bool -// */ -// protected function isPriceValid($price, $currency) -// { -// $priceValidator = $this->priceValidator; -// -// /** @var PriceParam $param */ -// $param = $priceValidator->getParam(); -// if ($currency == $param->getCurrency()) { -// try { -// $priceValidator->getParam()->compareTo($price); -// } catch(\InvalidArgumentException $e) { -// throw new InvalidRuleValueException(get_class(), self::PARAM1_PRICE); -// } -// } else { -// throw new InvalidRuleValueException(get_class(), self::PARAM1_CURRENCY); -// } -// -// return true; -// } - -// /** -// * Generate current Rule param to be validated from adapter -// * -// * @return $this -// */ -// protected function setParametersToValidate() -// { -// $this->paramsToValidate = array( -// self::PARAM1_PRICE => $this->adapter->getCartTotalPrice(), -// self::PARAM1_CURRENCY => $this->adapter->getCheckoutCurrency() -// ); -// -// return $this; -// } - /** * Get I18n name * @@ -377,41 +270,4 @@ class AvailableForTotalAmountManager extends CouponRuleAbstract ); } -// /** -// * Populate a Rule from a form admin -// * -// * @param array $operators Rule Operator set by the Admin -// * @param array $values Rule Values set by the Admin -// * -// * @throws \InvalidArgumentException -// * @return $this -// */ -// public function populateFromForm(array $operators, array $values) -// { -// if ($values[self::PARAM1_PRICE] === null -// || $values[self::PARAM1_CURRENCY] === null -// ) { -// throw new \InvalidArgumentException( -// 'The Rule ' . get_class() . 'needs at least a quantity set (' . self::PARAM1_PRICE . ', ' . self::PARAM1_CURRENCY . ')' -// ); -// } -// -// $this->priceValidator = new RuleValidator( -// $operators[self::PARAM1_PRICE], -// new PriceParam( -// $this->translator, -// $values[self::PARAM1_PRICE], -// $values[self::PARAM1_CURRENCY] -// ) -// ); -// -// $this->validators = array(self::PARAM1_PRICE => $this->priceValidator); -// -// return $this; -// } - - - - - } \ No newline at end of file diff --git a/core/lib/Thelia/Constraint/Rule/AvailableForXArticlesManager.php b/core/lib/Thelia/Constraint/Rule/AvailableForXArticlesManager.php index 20d7eddca..26c7a8aeb 100644 --- a/core/lib/Thelia/Constraint/Rule/AvailableForXArticlesManager.php +++ b/core/lib/Thelia/Constraint/Rule/AvailableForXArticlesManager.php @@ -63,77 +63,6 @@ class AvailableForXArticlesManager extends CouponRuleAbstract ) ); -// /** @var QuantityParam Quantity Validator */ -// protected $quantityValidator = null; - -// /** -// * Check if backoffice inputs are relevant or not -// * -// * @throws InvalidRuleOperatorException if Operator is not allowed -// * @throws InvalidRuleValueException if Value is not allowed -// * @return bool -// */ -// public function checkBackOfficeInput() -// { -// if (!isset($this->validators) -// || empty($this->validators) -// ||!isset($this->validators[self::PARAM1_QUANTITY]) -// ||!isset($this->validators[self::PARAM1_QUANTITY]) -// ) { -// throw new InvalidRuleValueException(get_class(), self::PARAM1_QUANTITY); -// } -// -// /** @var RuleValidator $ruleValidator */ -// $ruleValidator = $this->validators[self::PARAM1_QUANTITY]; -// /** @var QuantityParam $quantity */ -// $quantity = $ruleValidator->getParam(); -// -// if (!$quantity instanceof QuantityParam) { -// throw new InvalidRuleValueException(get_class(), self::PARAM1_QUANTITY); -// } -// -// $this->checkBackOfficeInputsOperators(); -// -// return $this->isQuantityValid($quantity->getInteger()); -// } - -// /** -// * Generate current Rule param to be validated from adapter -// * -// * @param CouponAdapterInterface $adapter allowing to gather -// * all necessary Thelia variables -// * -// * @return $this -// */ -// protected function setParametersToValidate() -// { -// $this->paramsToValidate = array( -// self::PARAM1_QUANTITY => $this->adapter->getNbArticlesInCart() -// ); -// -// return $this; -// } - -// /** -// * Check if Checkout inputs are relevant or not -// * -// * @throws \Thelia\Exception\InvalidRuleValueException -// * @return bool -// */ -// public function checkCheckoutInput() -// { -// if (!isset($this->paramsToValidate) -// || empty($this->paramsToValidate) -// ||!isset($this->paramsToValidate[self::PARAM1_QUANTITY]) -// ) { -// throw new InvalidRuleValueException(get_class(), self::PARAM1_QUANTITY); -// } -// -// $price = $this->paramsToValidate[self::PARAM1_QUANTITY]; -// -// return $this->isQuantityValid($price); -// } - /** * Check validators relevancy and store them * @@ -174,7 +103,7 @@ class AvailableForXArticlesManager extends CouponRuleAbstract ); } - if (!is_int($quantityValue) || $quantityValue <= 0) { + if ((int) $quantityValue <= 0) { throw new \InvalidArgumentException( 'Value for quantity field is not legit' ); @@ -210,26 +139,6 @@ class AvailableForXArticlesManager extends CouponRuleAbstract return false; } -// /** -// * Check if a quantity is valid -// * -// * @param int $quantity Quantity to check -// * -// * @throws InvalidRuleValueException if Value is not allowed -// * @return bool -// */ -// protected function isQuantityValid($quantity) -// { -// $quantityValidator = $this->quantityValidator; -// try { -// $quantityValidator->getParam()->compareTo($quantity); -// } catch(InvalidArgumentException $e) { -// throw new InvalidRuleValueException(get_class(), self::PARAM1_QUANTITY); -// } -// -// return true; -// } - /** * Get I18n name * @@ -267,36 +176,6 @@ class AvailableForXArticlesManager extends CouponRuleAbstract return $toolTip; } -// /** -// * Populate a Rule from a form admin -// * -// * @param array $operators Rule Operator set by the Admin -// * @param array $values Rule Values set by the Admin -// * -// * @throws InvalidArgumentException -// * @return $this -// */ -// public function populateFromForm(array $operators, array $values) -// { -// if ($values[self::PARAM1_QUANTITY] === null) { -// throw new InvalidArgumentException( -// 'The Rule ' . get_class() . 'needs at least a quantity set (' . self::PARAM1_QUANTITY. ')' -// ); -// } -// -// $this->quantityValidator = new RuleValidator( -// $operators[self::PARAM1_QUANTITY], -// new QuantityParam( -// $this->adapter, -// $values[self::PARAM1_QUANTITY] -// ) -// ); -// -// $this->validators = array(self::PARAM1_QUANTITY => $this->quantityValidator); -// -// return $this; -// } - /** * Generate inputs ready to be drawn * diff --git a/core/lib/Thelia/Controller/Admin/CouponController.php b/core/lib/Thelia/Controller/Admin/CouponController.php index e11fcf09e..cd8521d7a 100755 --- a/core/lib/Thelia/Controller/Admin/CouponController.php +++ b/core/lib/Thelia/Controller/Admin/CouponController.php @@ -158,6 +158,13 @@ class CouponController extends BaseAdminController ); } else { // Prepare the data that will hydrate the form + + /** @var ConstraintFactory $constraintFactory */ + $constraintFactory = $this->container->get('thelia.constraint.factory'); + $rules = $constraintFactory->unserializeCouponRuleCollection( + $coupon->getSerializedRules() + ); + $data = array( 'code' => $coupon->getCode(), 'title' => $coupon->getTitle(), @@ -171,18 +178,12 @@ class CouponController extends BaseAdminController 'isCumulative' => ($coupon->getIsCumulative() == 1), 'isRemovingPostage' => ($coupon->getIsRemovingPostage() == 1), 'maxUsage' => $coupon->getMaxUsage(), - 'rules' => new CouponRuleCollection(array()), + 'rules' => $rules, 'locale' => $coupon->getLocale(), ); $args['rulesObject'] = array(); - /** @var ConstraintFactory $constraintFactory */ - $constraintFactory = $this->container->get('thelia.constraint.factory'); - $rules = $constraintFactory->unserializeCouponRuleCollection( - $coupon->getSerializedRules() - ); - /** @var CouponRuleInterface $rule */ foreach ($rules->getRules() as $rule) { $args['rulesObject'][] = array( @@ -193,6 +194,8 @@ class CouponController extends BaseAdminController ); } + $args['rules'] = $this->cleanRuleForTemplate($rules); + // Setup the object form $changeForm = new CouponCreationForm($this->getRequest(), 'form', $data); @@ -216,100 +219,101 @@ class CouponController extends BaseAdminController $args['formAction'] = 'admin/coupon/update/' . $couponId; - return $this->render( - 'coupon-update', - $args - ); + return $this->render('coupon-update', $args); } - /** - * Manage Coupons Rule creation display - * - * @param int $couponId Coupon id - * - * @return \Symfony\Component\HttpFoundation\Response - */ - public function createRuleAction($couponId) - { - // Check current user authorization - $response = $this->checkAuth('admin.coupon.update'); - if ($response !== null) { - return $response; - } - - /** @var Coupon $coupon */ - $coupon = CouponQuery::create()->findOneById($couponId); - if (!$coupon) { - $this->pageNotFound(); - } - - // Parameters given to the template - $args = array(); - - $i18n = new I18n(); - /** @var Lang $lang */ - $lang = $this->getSession()->get('lang'); - $eventToDispatch = TheliaEvents::COUPON_RULE_CREATE; - - if ($this->getRequest()->isMethod('POST')) { - $this->validateCreateOrUpdateForm( - $i18n, - $lang, - $eventToDispatch, - 'updated', - 'update' - ); - } else { - // Prepare the data that will hydrate the form - $data = array( - 'code' => $coupon->getCode(), - 'title' => $coupon->getTitle(), - 'amount' => $coupon->getAmount(), - 'effect' => $coupon->getType(), - 'shortDescription' => $coupon->getShortDescription(), - 'description' => $coupon->getDescription(), - 'isEnabled' => ($coupon->getIsEnabled() == 1), - 'expirationDate' => $coupon->getExpirationDate($lang->getDateFormat()), - 'isAvailableOnSpecialOffers' => ($coupon->getIsAvailableOnSpecialOffers() == 1), - 'isCumulative' => ($coupon->getIsCumulative() == 1), - 'isRemovingPostage' => ($coupon->getIsRemovingPostage() == 1), - 'maxUsage' => $coupon->getMaxUsage(), - 'rules' => new CouponRuleCollection(array()), - 'locale' => $coupon->getLocale(), - ); - - /** @var CouponAdapterInterface $adapter */ - $adapter = $this->container->get('thelia.adapter'); - /** @var Translator $translator */ - $translator = $this->container->get('thelia.translator'); - - $args['rulesObject'] = array(); - /** @var CouponRuleInterface $rule */ - foreach ($coupon->getRules()->getRules() as $rule) { - $args['rulesObject'][] = array( - 'name' => $rule->getName($translator), - 'tooltip' => $rule->getToolTip($translator), - 'validators' => $rule->getValidators() - ); - } - +// /** +// * Manage Coupons Rule creation display +// * +// * @param int $couponId Coupon id +// * +// * @return \Symfony\Component\HttpFoundation\Response +// */ +// public function createRuleAction($couponId) +// { +// // Check current user authorization +// $response = $this->checkAuth('admin.coupon.update'); +// if ($response !== null) { +// return $response; +// } +// +// /** @var Coupon $coupon */ +// $coupon = CouponQuery::create()->findOneById($couponId); +// if (!$coupon) { +// $this->pageNotFound(); +// } +// +// // Parameters given to the template +// $args = array(); +// +// $i18n = new I18n(); +// /** @var Lang $lang */ +// $lang = $this->getSession()->get('lang'); +// $eventToDispatch = TheliaEvents::COUPON_RULE_CREATE; +// +// if ($this->getRequest()->isMethod('POST')) { +// $this->validateCreateOrUpdateForm( +// $i18n, +// $lang, +// $eventToDispatch, +// 'updated', +// 'update' +// ); +// } else { +// // Prepare the data that will hydrate the form +// +// /** @var ConstraintFactory $constraintFactory */ +// $constraintFactory = $this->container->get('thelia.constraint.factory'); +// +// $data = array( +// 'code' => $coupon->getCode(), +// 'title' => $coupon->getTitle(), +// 'amount' => $coupon->getAmount(), +// 'effect' => $coupon->getType(), +// 'shortDescription' => $coupon->getShortDescription(), +// 'description' => $coupon->getDescription(), +// 'isEnabled' => ($coupon->getIsEnabled() == 1), +// 'expirationDate' => $coupon->getExpirationDate($lang->getDateFormat()), +// 'isAvailableOnSpecialOffers' => ($coupon->getIsAvailableOnSpecialOffers() == 1), +// 'isCumulative' => ($coupon->getIsCumulative() == 1), +// 'isRemovingPostage' => ($coupon->getIsRemovingPostage() == 1), +// 'maxUsage' => $coupon->getMaxUsage(), +// 'rules' => $constraintFactory->unserializeCouponRuleCollection($coupon->getSerializedRules()), +// 'locale' => $coupon->getLocale(), +// ); +// +// /** @var CouponAdapterInterface $adapter */ +// $adapter = $this->container->get('thelia.adapter'); +// /** @var Translator $translator */ +// $translator = $this->container->get('thelia.translator'); +// +// $args['rulesObject'] = array(); +// /** @var CouponRuleInterface $rule */ +// foreach ($coupon->getRules()->getRules() as $rule) { +// $args['rulesObject'][] = array( +// 'name' => $rule->getName($translator), +// 'tooltip' => $rule->getToolTip($translator), +// 'validators' => $rule->getValidators() +// ); +// } +// // $args['rules'] = $this->cleanRuleForTemplate($coupon->getRules()->getRules()); - - // Setup the object form - $changeForm = new CouponCreationForm($this->getRequest(), 'form', $data); - - // Pass it to the parser - $this->getParserContext()->addForm($changeForm); - } - - $args['formAction'] = 'admin/coupon/update/' . $couponId; - - return $this->render( - 'coupon-update', - $args - ); - } +// +// // Setup the object form +// $changeForm = new CouponCreationForm($this->getRequest(), 'form', $data); +// +// // Pass it to the parser +// $this->getParserContext()->addForm($changeForm); +// } +// +// $args['formAction'] = 'admin/coupon/update/' . $couponId; +// +// return $this->render( +// 'coupon-update', +// $args +// ); +// } @@ -413,7 +417,6 @@ class CouponController extends BaseAdminController $constraintFactory = $this->container->get('thelia.constraint.factory'); $rulesReceived = json_decode($this->getRequest()->get('rules')); foreach ($rulesReceived as $ruleReceived) { - var_dump('building ', $ruleReceived->values); $rule = $constraintFactory->build( $ruleReceived->serviceId, (array) $ruleReceived->operators, @@ -442,6 +445,7 @@ class CouponController extends BaseAdminController $rules, $coupon->getLocale() ); + $couponEvent->setCoupon($coupon); $eventToDispatch = TheliaEvents::COUPON_RULE_UPDATE; // Dispatch Event to the Action diff --git a/core/lib/Thelia/Core/Event/TheliaEvents.php b/core/lib/Thelia/Core/Event/TheliaEvents.php index 500803f53..de7a09e4a 100755 --- a/core/lib/Thelia/Core/Event/TheliaEvents.php +++ b/core/lib/Thelia/Core/Event/TheliaEvents.php @@ -296,22 +296,6 @@ final class TheliaEvents */ const AFTER_COUPON_RULE_UPDATE = "action.after_update_coupon_rule"; - /** - * Sent when attempting to delete Coupon Rule - */ - const COUPON_RULE_DELETE = "action.delete_coupon_rule"; - - /** - * Sent just before an attempt to delete a Coupon Rule - */ - const BEFORE_COUPON_RULE_DELETE = "action.before_delete_coupon_rule"; - - /** - * Sent just after an attempt to delete a Coupon Rule - */ - const AFTER_COUPON_RULE_DELETE = "action.after_delete_coupon_rule"; - - // -- Configuration management --------------------------------------------- const CONFIG_CREATE = "action.createConfig"; diff --git a/core/lib/Thelia/Model/Coupon.php b/core/lib/Thelia/Model/Coupon.php index f5788ff4f..7a7ce1e4a 100755 --- a/core/lib/Thelia/Model/Coupon.php +++ b/core/lib/Thelia/Model/Coupon.php @@ -49,24 +49,25 @@ class Coupon extends BaseCoupon /** - * Constructor + * Create or Update this Coupon * - * @param string $code Coupon Code - * @param string $title Coupon title - * @param float $amount Amount removed from the Total Checkout - * @param string $effect Coupon effect - * @param string $shortDescription Coupon short description - * @param string $description Coupon description - * @param boolean $isEnabled Enable/Disable - * @param \DateTime $expirationDate Coupon expiration date - * @param boolean $isAvailableOnSpecialOffers Is available on special offers - * @param boolean $isCumulative Is cumulative - * @param boolean $isRemovingPostage Is removing Postage - * @param int $maxUsage Coupon quantity - * @param CouponRuleCollection $rules CouponRuleInterface to add - * @param string $locale Coupon Language code ISO (ex: fr_FR) + * @param string $code Coupon Code + * @param string $title Coupon title + * @param float $amount Amount removed from the Total Checkout + * @param string $effect Coupon effect + * @param bool $isRemovingPostage Is removing Postage + * @param string $shortDescription Coupon short description + * @param string $description Coupon description + * @param boolean $isEnabled Enable/Disable + * @param \DateTime $expirationDate Coupon expiration date + * @param boolean $isAvailableOnSpecialOffers Is available on special offers + * @param boolean $isCumulative Is cumulative + * @param int $maxUsage Coupon quantity + * @param string $locale Coupon Language code ISO (ex: fr_FR) + * + * @throws \Exception */ - function createOrUpdate($code, $title, $amount, $effect, $shortDescription, $description, $isEnabled, $expirationDate, $isAvailableOnSpecialOffers, $isCumulative, $maxUsage, $rules, $locale = null) + function createOrUpdate($code, $title, $amount, $effect, $isRemovingPostage, $shortDescription, $description, $isEnabled, $expirationDate, $isAvailableOnSpecialOffers, $isCumulative, $maxUsage, $locale = null) { $this->setCode($code) ->setTitle($title) @@ -74,13 +75,13 @@ class Coupon extends BaseCoupon ->setDescription($description) ->setType($effect) ->setAmount($amount) + ->setIsRemovingPostage($isRemovingPostage) ->setType($amount) ->setIsEnabled($isEnabled) ->setExpirationDate($expirationDate) ->setIsAvailableOnSpecialOffers($isAvailableOnSpecialOffers) ->setIsCumulative($isCumulative) - ->setMaxUsage($maxUsage) - ->setRules($rules); + ->setMaxUsage($maxUsage); // Set object language (i18n) if (!is_null($locale)) { @@ -99,33 +100,34 @@ class Coupon extends BaseCoupon } } -// /** -// * Set the value of [serialized_rules] column. -// * Convert a CouponRuleCollection into a serialized array of SerializableRule -// * -// * @param CouponRuleCollection $rules A set of Rules -// * -// * @return \Thelia\Model\Coupon The current object (for fluent API support) -// */ -// public function setRules(CouponRuleCollection $rules) -// { -// $serializedRules = null; -// if ($rules !== null) { -// /** @var $rule CouponRuleInterface */ -// foreach ($rules->getRules() as $rule) { -// $serializedRules[] = $rule->getSerializableRule(); -// } -// -// $serializedRules = (string) base64_encode(serialize($serializedRules)); -// } -// -// if ($this->serialized_rules !== $serializedRules) { -// $this->serialized_rules = $serializedRules; -// $this->modifiedColumns[] = CouponTableMap::SERIALIZED_RULES; -// } -// -// return $this; -// } + /** + * Create or Update this coupon rule + * + * @param string $serializableRules Serialized rules ready to be saved + * @param string $locale Coupon Language code ISO (ex: fr_FR) + * + * @throws \Exception + */ + function createOrUpdateRules($serializableRules, $locale) + { + $this->setSerializedRules($serializableRules); + + // Set object language (i18n) + if (!is_null($locale)) { + $this->setLocale($locale); + } + + $con = Propel::getWriteConnection(CouponTableMap::DATABASE_NAME); + $con->beginTransaction(); + try { + $this->save($con); + $con->commit(); + + } catch(\Exception $e) { + $con->rollback(); + throw $e; + } + } diff --git a/templates/admin/default/coupon-create.html b/templates/admin/default/coupon-create.html index 7cb31ee09..e8fcb73f5 100755 --- a/templates/admin/default/coupon-create.html +++ b/templates/admin/default/coupon-create.html @@ -16,7 +16,7 @@ {form name="thelia.admin.coupon.creation"} - {include file='coupon/form.html' formAction={url path={$formAction}}} + {include file='coupon/form.html' formAction={url path={$formAction}} noRules=true} {/form} diff --git a/templates/admin/default/coupon-update.html b/templates/admin/default/coupon-update.html index 9b6387cd7..1971fafff 100755 --- a/templates/admin/default/coupon-update.html +++ b/templates/admin/default/coupon-update.html @@ -16,7 +16,7 @@ {form name="thelia.admin.coupon.creation"} - {include file='coupon/form.html' formAction={url path={$formAction}} form=$form} + {include file='coupon/form.html' formAction={url path={$formAction}} form=$form noRules=false} {/form} @@ -43,11 +43,19 @@ - + Array.prototype.clean = function(deleteValue) { + for (var i = 0; i < this.length; i++) { + if (this[i] == deleteValue) { + this.splice(i, 1); + i--; + } + } + return this; + }; // Init Rules - var initRule = function() { + var initRules = function() { var rules = []; {foreach from=$rulesObject key=k item=rule} var rule = {}; @@ -67,16 +75,13 @@ // Save Rules AJAX var saveRuleAjax = function() { + console.log('rulesToSave'); + console.log(rulesToSave); var $url = '{$urlAjaxUpdateRules}'; - console.log('save'); - console.log('{$urlAjaxUpdateRules}'); - console.log(rules); - console.log(JSON.stringify(rules)); $.ajax({ type: "POST", url: $url, - {*data: {literal}{{/literal}rules:rules{literal}}{/literal},*} - data: {literal}{{/literal}rules:JSON.stringify(rules){literal}}{/literal}, + data: {literal}{{/literal}rules:JSON.stringify(rulesToSave){literal}}{/literal}, statusCode: { 404: function() { $('#constraint-add-operators-values').html( @@ -91,20 +96,83 @@ } // Remove 1 Rule then Save Rules AJAX - var removeRuleAjax = function($id) { - rules.slice($id, 1); + var removeRuleAjax = function(id) { + // Delete rule in temporary array + delete rulesToSave[id]; + rulesToSave.clean(undefined); + + // Save saveRuleAjax(); } - // Add 1 Rule then Save Rules AJAX - var addRuleAjax = function() { - rules.push(ruleToSave); + // Add 1 Rule / or update the temporary Rules array then Save Rules via AJAX + var addRuleAjax = function(id) { + if(typeof id === 'number' && id % 1 == 0) { + rulesToSave[id] = ruleToSave; + } else { + rulesToSave.push(ruleToSave); + } + saveRuleAjax(); } + // Set rule inputs to allow editing + var updateRuleAjax = function(id) { + ruleToSave = rulesToSave[id]; + var ruleToUpdate = ruleToSave; - var rules = initRule(); - console.log(rules); + // Deleting this rule, we will reset it + delete rulesToSave[id]; + + // Set the rule seletor + $("#category-rule option").filter(function() { + return $(this).val() == ruleToSave.serviceId; + }).prop('selected', true); + + // Force rule input refresh + loadRuleInputs(ruleToSave.serviceId, ruleToUpdate, function(ruleToUpdate) { + fillInRuleInputs(ruleToUpdate); + }); + } + + // Fill in rule inputs + var fillInRuleInputs = function(ruleToUpdate) { + var valueId = null; + var operatorId = null; + + for (idName in ruleToUpdate.operators) { + // Setting idName operator input + operatorId = idName + '-operator'; + $('#' + operatorId).val(ruleToUpdate.operators[idName]); + // Setting idName value input + valueId = idName + '-value'; + $('#' + valueId).val(ruleToUpdate.values[idName]); + } + } + + + + + + // Reload rule inputs + var loadRuleInputs = function(ruleId, ruleToSave, callBack) { + $('#constraint-add-operators-values').html('
'); + var url = "{$urlAjaxGetRuleInput}"; + url = url.replace('ruleId', ruleId) + $.ajax({ + url: url, + statusCode: { + 404: function() { + $('#constraint-add-operators-values').html( + '{intl l='Please select another rule'}' + ); + } + } + }).done(function(data) { + $('#constraint-add-operators-values').html(data); + return callBack(ruleToSave); + }); + } // Save rules on click @@ -117,12 +185,24 @@ // Remove rule on click var onClickDeleteRule = function() { - $('#constraint-delete-btn').on('click', function (e) { -// removeRuleAjax(); + $('.constraint-delete-btn').on('click', function (e) { + e.preventDefault(); + var $this = $(this); + removeRuleAjax($this.attr('data-int')); }); } onClickDeleteRule(); + // Remove rule on click + var onClickUpdateRule = function() { + $('.constraint-update-btn').on('click', function (e) { + e.preventDefault(); + var $this = $(this); + updateRuleAjax($this.attr('data-int')); + }); + } + onClickUpdateRule(); + // Reload effect inputs when changing effect var onEffectChange = function() { $('#effect').on('change', function (e) { @@ -135,24 +215,18 @@ // Reload rule inputs when changing effect var onRuleChange = function() { $('#category-rule').on('change', function (e) { - $('#constraint-add-operators-values').html('
'); - var url = "{$urlAjaxGetRuleInput}"; - url = url.replace('ruleId', $(this).val()) - $.ajax({ - url: url, - statusCode: { - 404: function() { - $('#constraint-add-operators-values').html( - '{intl l='Please select another rule'}' - ); - } - } - }).done(function(data) { - $('#constraint-add-operators-values').html(data); - }); + loadRuleInputs($(this).val(), null, function(ruleToSave) {}); }); } onRuleChange(); + + + + + // Rule to save + var ruleToSave = {literal}{}{/literal}; + // Rules which will be saved + var rulesToSave = initRules(); }); diff --git a/templates/admin/default/coupon/form.html b/templates/admin/default/coupon/form.html index e22136d41..5d30d201d 100644 --- a/templates/admin/default/coupon/form.html +++ b/templates/admin/default/coupon/form.html @@ -161,134 +161,122 @@ - -
-
- - - - - - - - - - {include file='coupon/rules.html' rules=$rulesObject} - {*{foreach from=$rulesObject item=rule name=rulesForeach}*} - {**} - {**} - - {**} - {**} - {*{/foreach}*} - -
- {intl l='Rules'} -
{intl l='Conditions'}{intl l='Actions'}
*} - {*{if !$smarty.foreach.rulesForeach.first}*} - {*{intl l='And'}*} - {*{/if}*} - {*{$rule.tooltip nofilter}*} - {**} - {* {intl l='Edit'}*} - {* {intl l='Delete'}*} - {*
-
-
- -
-
- - - - -
- - - + {if $noRules} + {include file='includes/notifications.html' message={intl l='Please save your Coupon in oder to affect it some application fields'}} + {else} +
+
+ + + + + + + + + + {include file='coupon/rules.html' rules=$rules} + +
+ {intl l='Rules'} +
{intl l='Conditions'}{intl l='Actions'}
+
-
- - +
+
+ + + + +
+ + + +
+ +
+ + +
+ +
+ {**} + {*
*} + {*
*} + {**} + {*
*} + {*
*} + {**} + {**} + {*
*} + {*
*} + {**} + + {**} + {*
*} + {*
*} + {**} + {*
*} + {*
*} + {**} + {**} + {*
*} + {*
*} + + {**} + {*
*} + {*
*} + {**} + {*
*} + {*
*} + {**} + {*
*} + {*
*} + {*
*} + {*
*} + {**} + {**} + {**} + {**} + {**} + {**} + {**} + {**} + {**} + {**} + {*
Categories list
*} + {*
*} + {*
*} +
- -
- {**} - {*
*} - {*
*} - {**} - {*
*} - {*
*} - {**} - {**} - {*
*} - {*
*} - {**} - - {**} - {*
*} - {*
*} - {**} - {*
*} - {*
*} - {**} - {**} - {*
*} - {*
*} - - {**} - {*
*} - {*
*} - {**} - {*
*} - {*
*} - {**} - {*
*} - {*
*} - {*
*} - {*
*} - {**} - {**} - {**} - {**} - {**} - {**} - {**} - {**} - {**} - {**} - {*
Categories list
*} - {*
*} - {*
*} -
-
-
+ + {/if} diff --git a/templates/admin/default/coupon/rule-input-ajax.html b/templates/admin/default/coupon/rule-input-ajax.html index cf921932b..d0959a3ad 100644 --- a/templates/admin/default/coupon/rule-input-ajax.html +++ b/templates/admin/default/coupon/rule-input-ajax.html @@ -1,4 +1,3 @@ -{*{$inputs.inputs|var_dump}*} {foreach from=$inputs.inputs key=name item=input}
@@ -71,6 +70,8 @@ {*
*} \ No newline at end of file diff --git a/templates/admin/default/coupon/rules.html b/templates/admin/default/coupon/rules.html index 8dca66c49..199ee44c3 100644 --- a/templates/admin/default/coupon/rules.html +++ b/templates/admin/default/coupon/rules.html @@ -1,4 +1,4 @@ -{foreach from=$rules item=rule name=rulesForeach} +{foreach from=$rules item=rule key=i name=rulesForeach} {if !$smarty.foreach.rulesForeach.first} @@ -7,10 +7,10 @@ {$rule nofilter} - + {intl l='Edit'} - + {intl l='Delete'} From 7e2f57e6187589f724bf7055507be24e533a1c7f Mon Sep 17 00:00:00 2001 From: gmorel Date: Wed, 11 Sep 2013 09:48:33 +0200 Subject: [PATCH 02/32] Working - Coupon Add/Edit/Delete rule AJAX --- templates/admin/default/coupon-update.html | 24 ++++++----- .../admin/default/coupon/rule-input-ajax.html | 40 +++++++++---------- 2 files changed, 31 insertions(+), 33 deletions(-) diff --git a/templates/admin/default/coupon-update.html b/templates/admin/default/coupon-update.html index 1971fafff..3895475b4 100755 --- a/templates/admin/default/coupon-update.html +++ b/templates/admin/default/coupon-update.html @@ -41,8 +41,6 @@ $(function($){ miniBrowser(0, '/test_to_remove/datas_coupon_edit.json'); - - Array.prototype.clean = function(deleteValue) { for (var i = 0; i < this.length; i++) { if (this[i] == deleteValue) { @@ -53,7 +51,6 @@ return this; }; - // Init Rules var initRules = function() { var rules = []; @@ -75,8 +72,6 @@ // Save Rules AJAX var saveRuleAjax = function() { - console.log('rulesToSave'); - console.log(rulesToSave); var $url = '{$urlAjaxUpdateRules}'; $.ajax({ type: "POST", @@ -107,12 +102,14 @@ // Add 1 Rule / or update the temporary Rules array then Save Rules via AJAX var addRuleAjax = function(id) { + // If update if(typeof id === 'number' && id % 1 == 0) { rulesToSave[id] = ruleToSave; - } else { + } else { // If create rulesToSave.push(ruleToSave); } + // Save saveRuleAjax(); } @@ -193,12 +190,15 @@ } onClickDeleteRule(); - // Remove rule on click + // Update rule on click var onClickUpdateRule = function() { $('.constraint-update-btn').on('click', function (e) { e.preventDefault(); var $this = $(this); updateRuleAjax($this.attr('data-int')); + + // Hide row being updated + $this.parent().parent().remove(); }); } onClickUpdateRule(); @@ -215,21 +215,23 @@ // Reload rule inputs when changing effect var onRuleChange = function() { $('#category-rule').on('change', function (e) { - loadRuleInputs($(this).val(), null, function(ruleToSave) {}); + loadRuleInputs($(this).val(), null, function(ruleToSave) {literal}{}{/literal}); }); } onRuleChange(); + // Fill in ready to be saved rule array + // var onInputsChange = function() + // In AJAX response - // Rule to save - var ruleToSave = {literal}{}{/literal}; // Rules which will be saved var rulesToSave = initRules(); }); - + // Rule to save + var ruleToSave = {literal}{}{/literal}; {/block} diff --git a/templates/admin/default/coupon/rule-input-ajax.html b/templates/admin/default/coupon/rule-input-ajax.html index d0959a3ad..4933c6745 100644 --- a/templates/admin/default/coupon/rule-input-ajax.html +++ b/templates/admin/default/coupon/rule-input-ajax.html @@ -72,33 +72,29 @@ \ No newline at end of file From 551c132b76bf99860432ffc82faf13d73b169770 Mon Sep 17 00:00:00 2001 From: Etienne Roudeix Date: Wed, 11 Sep 2013 11:14:54 +0200 Subject: [PATCH 03/32] syntax --- core/lib/Thelia/Core/Thelia.php | 2 +- core/lib/Thelia/TaxEngine/Calculator.php | 12 ++++++------ templates/default_save/category.html | 12 +----------- 3 files changed, 8 insertions(+), 18 deletions(-) diff --git a/core/lib/Thelia/Core/Thelia.php b/core/lib/Thelia/Core/Thelia.php index 402059ddd..eb560a484 100755 --- a/core/lib/Thelia/Core/Thelia.php +++ b/core/lib/Thelia/Core/Thelia.php @@ -83,7 +83,7 @@ class Thelia extends Kernel $con = Propel::getConnection(\Thelia\Model\Map\ProductTableMap::DATABASE_NAME); $con->setAttribute(ConnectionWrapper::PROPEL_ATTR_CACHE_PREPARES, true); if ($this->isDebug()) { - //$serviceContainer->setLogger('defaultLogger', \Thelia\Log\Tlog::getInstance()); + $serviceContainer->setLogger('defaultLogger', \Thelia\Log\Tlog::getInstance()); $con->useDebug(true); } } diff --git a/core/lib/Thelia/TaxEngine/Calculator.php b/core/lib/Thelia/TaxEngine/Calculator.php index 66c4fcbbf..e077a24b8 100755 --- a/core/lib/Thelia/TaxEngine/Calculator.php +++ b/core/lib/Thelia/TaxEngine/Calculator.php @@ -67,29 +67,29 @@ class Calculator return $this; } - public function getTaxAmount($amount) + public function getTaxAmount($untaxedPrice) { if(null === $this->taxRulesGroupedCollection) { throw new TaxEngineException('Tax rules collection is empty in Calculator::getTaxAmount', TaxEngineException::UNDEFINED_TAX_RULES_COLLECTION); } - if(false === filter_var($amount, FILTER_VALIDATE_FLOAT)) { + if(false === filter_var($untaxedPrice, FILTER_VALIDATE_FLOAT)) { throw new TaxEngineException('BAD AMOUNT FORMAT', TaxEngineException::BAD_AMOUNT_FORMAT); } $totalTaxAmount = 0; foreach($this->taxRulesGroupedCollection as $taxRule) { $rateSum = $taxRule->getTaxRuleRateSum(); - $taxAmount = $amount * $rateSum * 0.01; + $taxAmount = $untaxedPrice * $rateSum * 0.01; $totalTaxAmount += $taxAmount; - $amount += $taxAmount; + $untaxedPrice += $taxAmount; } return $totalTaxAmount; } - public function getTaxedPrice($amount) + public function getTaxedPrice($untaxedPrice) { - return $amount + $this->getTaxAmount($amount); + return $untaxedPrice + $this->getTaxAmount($untaxedPrice); } } diff --git a/templates/default_save/category.html b/templates/default_save/category.html index 2e216d0c0..0a8e04460 100755 --- a/templates/default_save/category.html +++ b/templates/default_save/category.html @@ -1,9 +1,3 @@ - - - {debugbar_renderHead} - - -

Category page

@@ -148,8 +142,4 @@ {/loop} -
- - {debugbar_render} - - \ No newline at end of file + \ No newline at end of file From e1d48d2a28e2af161d89e7c22016a3a839ee6f07 Mon Sep 17 00:00:00 2001 From: Manuel Raynaud Date: Wed, 11 Sep 2013 12:30:05 +0200 Subject: [PATCH 04/32] finish registration form --- core/lib/Thelia/Form/CustomerCreation.php | 7 +- templates/default/register.html | 165 ++++++++++++++-------- 2 files changed, 115 insertions(+), 57 deletions(-) diff --git a/core/lib/Thelia/Form/CustomerCreation.php b/core/lib/Thelia/Form/CustomerCreation.php index e6f77c0de..24e64faff 100755 --- a/core/lib/Thelia/Form/CustomerCreation.php +++ b/core/lib/Thelia/Form/CustomerCreation.php @@ -65,7 +65,10 @@ class CustomerCreation extends BaseForm "label_attr" => array( "for" => "address" ), - "label" => Translator::getInstance()->trans("Street Address") + "label" => Translator::getInstance()->trans("Street Address"), + "label_attr" => array( + "for" => "address1" + ) )) ->add("address2", "text", array( "label" => Translator::getInstance()->trans("Address Line 2"), @@ -80,7 +83,7 @@ class CustomerCreation extends BaseForm ) )) ->add("company", "text", array( - "label" => Translator::getInstance()->trans("Company name"), + "label" => Translator::getInstance()->trans("Company Name"), "label_attr" => array( "for" => "company" ) diff --git a/templates/default/register.html b/templates/default/register.html index 3a14ce675..48339b873 100644 --- a/templates/default/register.html +++ b/templates/default/register.html @@ -101,74 +101,129 @@
-
- -
- -
-
+ {form_field form=$form field="company"} +
+ +
+ + {if $error } + {$message} + {elseif $value != "" && !$error} + + {/if} +
+
+ {/form_field} -
- -
- -
-
+ {form_field form=$form field="address1"} +
+ +
+ + {if $error } + {$message} + {elseif $value != "" && !$error} + + {/if} +
+
+ {/form_field} -
- -
- -
-
+ {form_field form=$form field="address2"} +
+ +
+ + {if $error } + {$message} + {elseif $value != "" && !$error} + + {/if} +
+
+ {/form_field} -
- -
- -
-
+ {form_field form=$form field="city"} +
+ +
+ + {if $error } + {$message} + {elseif $value != "" && !$error} + + {/if} +
+
+ {/form_field} -
- -
- -
-
+ {form_field form=$form field="zipcode"} +
+ +
+ + {if $error } + {$message} + {elseif $value != "" && !$error} + + {/if} +
+
+ {/form_field} -
- -
- -
-
+ {form_field form=$form field="country"} +
+ +
+ + {if $error } + {$message} + {elseif $value != "" && !$error} + + {/if} +
+
+ {/form_field}
- 3. Login Information + 3. {intl l="Login Information"}
-
- -
- -
-
+ {form_field form=$form field="password"} +
+ +
+ + {if $error } + {$message} + {elseif $value != "" && !$error} + + {/if} +
+
+ {/form_field} -
- -
- -
-
+ {form_field form=$form field="password_confirm"} +
+ +
+ + {if $error } + {$message} + {elseif $value != "" && !$error} + + {/if} +
+
+ {/form_field}
From 858cc7f4f230d2d4e1100f7cc4c10446a0b7a2f6 Mon Sep 17 00:00:00 2001 From: Manuel Raynaud Date: Wed, 11 Sep 2013 14:32:57 +0200 Subject: [PATCH 05/32] validate customer creation form --- .../Thelia/Config/Resources/routing/front.xml | 6 +- core/lib/Thelia/Controller/BaseController.php | 2 - .../Controller/Front/CustomerController.php | 10 ++- templates/default/register.html | 62 +++++++++++++------ 4 files changed, 57 insertions(+), 23 deletions(-) diff --git a/core/lib/Thelia/Config/Resources/routing/front.xml b/core/lib/Thelia/Config/Resources/routing/front.xml index d06585f73..bb1e9422b 100755 --- a/core/lib/Thelia/Config/Resources/routing/front.xml +++ b/core/lib/Thelia/Config/Resources/routing/front.xml @@ -12,7 +12,7 @@ Thelia\Controller\Front\CustomerController::createAction - connexion + register @@ -57,6 +57,10 @@ + + Thelia\Controller\Front\DefaultController::noAction + cart + Thelia\Controller\Front\CartController::addItem cart diff --git a/core/lib/Thelia/Controller/BaseController.php b/core/lib/Thelia/Controller/BaseController.php index bd2556072..988159be4 100755 --- a/core/lib/Thelia/Controller/BaseController.php +++ b/core/lib/Thelia/Controller/BaseController.php @@ -215,8 +215,6 @@ class BaseController extends ContainerAware $url = $this->getRequest()->get("success_url"); } - echo "url=$url"; - if (null !== $url) $this->redirect($url); } diff --git a/core/lib/Thelia/Controller/Front/CustomerController.php b/core/lib/Thelia/Controller/Front/CustomerController.php index 85db69472..0a60126e6 100755 --- a/core/lib/Thelia/Controller/Front/CustomerController.php +++ b/core/lib/Thelia/Controller/Front/CustomerController.php @@ -44,6 +44,7 @@ use Thelia\Core\Security\Exception\WrongPasswordException; */ class CustomerController extends BaseFrontController { + use \Thelia\Cart\CartTrait; /** * Create a new customer. * On success, redirect to success_url if exists, otherwise, display the same view again. @@ -65,7 +66,12 @@ class CustomerController extends BaseFrontController $this->processLogin($customerCreateEvent->getCustomer()); - $this->redirectSuccess($customerCreation); + $cart = $this->getCart($this->getRequest()); + if($cart->getCartItems()->count() > 0) { + $this->redirectToRoute("cart.view"); + } else { + $this->redirectSuccess($customerCreation); + } } catch (FormValidationException $e) { $message = sprintf("Please check your input: %s", $e->getMessage()); } catch (\Exception $e) { @@ -232,7 +238,7 @@ class CustomerController extends BaseFrontController $data["country"], isset($data["email"])?$data["email"]:null, isset($data["password"]) ? $data["password"]:null, - $this->getRequest()->getSession()->getLang(), + $this->getRequest()->getSession()->getLang()->getId(), isset($data["reseller"])?$data["reseller"]:null, isset($data["sponsor"])?$data["sponsor"]:null, isset($data["discount"])?$data["discount"]:null diff --git a/templates/default/register.html b/templates/default/register.html index 48339b873..9e0caf202 100644 --- a/templates/default/register.html +++ b/templates/default/register.html @@ -19,18 +19,44 @@

{intl l="Create New Account"}

{form name="thelia.customer.creation"}
+ {form_field form=$form field='success_url'} + {* the url the user is redirected to on login success *} + {/form_field} + {form_field form=$form field='error_message'} + {* the url the user is redirected to on login success *} + {/form_field} + {form_hidden_fields form=$form} + {if $form_error}
{$form_error_message}
{/if}
1. {intl l="Personal Informations"}
+ {form_field form=$form field="title"} +
+ +
+ + {if $error } + {$message} + {elseif $value != "" && !$error} + + {/if} +
+
+ {/form_field} {form_field form=$form field="firstname"} -
+
- + {if $error } {$message} {elseif $value != "" && !$error} @@ -40,7 +66,7 @@
{/form_field} {form_field form=$form field="lastname"} -
+
@@ -53,7 +79,7 @@
{/form_field} {form_field form=$form field="email"} -
+
@@ -67,7 +93,7 @@
{/form_field} {form_field form=$form field="phone"} -
+
@@ -80,7 +106,7 @@
{/form_field} {form_field form=$form field="cellphone"} -
+
@@ -102,7 +128,7 @@
{form_field form=$form field="company"} -
+
@@ -116,7 +142,7 @@ {/form_field} {form_field form=$form field="address1"} -
+
@@ -130,7 +156,7 @@ {/form_field} {form_field form=$form field="address2"} -
+
@@ -144,7 +170,7 @@ {/form_field} {form_field form=$form field="city"} -
+
@@ -158,7 +184,7 @@ {/form_field} {form_field form=$form field="zipcode"} -
+
@@ -172,13 +198,13 @@ {/form_field} {form_field form=$form field="country"} -
+
- + {loop type="country" name="country.list"} - + {/loop} {if $error } @@ -198,7 +224,7 @@
{form_field form=$form field="password"} -
+
@@ -212,7 +238,7 @@ {/form_field} {form_field form=$form field="password_confirm"} -
+
@@ -231,7 +257,7 @@
From a9dae509c766a0ef0b2838c8cb5a81bcb68ca5c9 Mon Sep 17 00:00:00 2001 From: gmorel Date: Wed, 11 Sep 2013 14:40:55 +0200 Subject: [PATCH 06/32] WIP - Coupon Add/Edit/Delete rule AJAX - add tests casper JS --- .../Tests/Functionnal/casperjs/conf/dit.js | 3 + .../Tests/Functionnal/casperjs/conf/local.js | 3 + .../Tests/Functionnal/casperjs/conf/uat.js | 3 + .../Functionnal/casperjs/exe/00_parameters.js | 12 ++ .../Functionnal/casperjs/exe/10_login.js | 25 +++ .../Thelia/Tests/Functionnal/casperjs/run.sh | 26 +++ .../Tests/Functionnal/casperjs/run_ci.sh | 4 + templates/admin/default/assets/js/coupon.js | 148 ++++++++++++++++ templates/admin/default/coupon-update.html | 161 +++--------------- .../admin/default/coupon/rule-input-ajax.html | 20 ++- 10 files changed, 257 insertions(+), 148 deletions(-) create mode 100644 core/lib/Thelia/Tests/Functionnal/casperjs/conf/dit.js create mode 100644 core/lib/Thelia/Tests/Functionnal/casperjs/conf/local.js create mode 100644 core/lib/Thelia/Tests/Functionnal/casperjs/conf/uat.js create mode 100644 core/lib/Thelia/Tests/Functionnal/casperjs/exe/00_parameters.js create mode 100644 core/lib/Thelia/Tests/Functionnal/casperjs/exe/10_login.js create mode 100755 core/lib/Thelia/Tests/Functionnal/casperjs/run.sh create mode 100755 core/lib/Thelia/Tests/Functionnal/casperjs/run_ci.sh create mode 100644 templates/admin/default/assets/js/coupon.js diff --git a/core/lib/Thelia/Tests/Functionnal/casperjs/conf/dit.js b/core/lib/Thelia/Tests/Functionnal/casperjs/conf/dit.js new file mode 100644 index 000000000..b89267246 --- /dev/null +++ b/core/lib/Thelia/Tests/Functionnal/casperjs/conf/dit.js @@ -0,0 +1,3 @@ +//DIT = Environnement d'intégration +var copark_base_url = 'http://ws.copark.dit.linux.thelia.fr/'; +casper.test.done(0); diff --git a/core/lib/Thelia/Tests/Functionnal/casperjs/conf/local.js b/core/lib/Thelia/Tests/Functionnal/casperjs/conf/local.js new file mode 100644 index 000000000..366d297f2 --- /dev/null +++ b/core/lib/Thelia/Tests/Functionnal/casperjs/conf/local.js @@ -0,0 +1,3 @@ +//LOCAL = ton pc +var thelia2_base_url = 'http://www.thelia2.dev/index.php/'; +casper.test.done(0); diff --git a/core/lib/Thelia/Tests/Functionnal/casperjs/conf/uat.js b/core/lib/Thelia/Tests/Functionnal/casperjs/conf/uat.js new file mode 100644 index 000000000..02b753869 --- /dev/null +++ b/core/lib/Thelia/Tests/Functionnal/casperjs/conf/uat.js @@ -0,0 +1,3 @@ +//UAT = Recette client +var copark_base_url = 'http://ws.copark.uat.openstudio.fr/'; +casper.test.done(0); \ No newline at end of file diff --git a/core/lib/Thelia/Tests/Functionnal/casperjs/exe/00_parameters.js b/core/lib/Thelia/Tests/Functionnal/casperjs/exe/00_parameters.js new file mode 100644 index 000000000..81b980d41 --- /dev/null +++ b/core/lib/Thelia/Tests/Functionnal/casperjs/exe/00_parameters.js @@ -0,0 +1,12 @@ + +casper.test.comment('Please edit 00_parameters.js to add your configuration'); + +var thelia2_login_admin_url = thelia2_base_url + 'admin/login'; + + +//var findMyId = /([0-9]+)$/; +//var currentId; + +casper.test.comment('Variables are set'); + +casper.test.done(0); diff --git a/core/lib/Thelia/Tests/Functionnal/casperjs/exe/10_login.js b/core/lib/Thelia/Tests/Functionnal/casperjs/exe/10_login.js new file mode 100644 index 000000000..c9c4095db --- /dev/null +++ b/core/lib/Thelia/Tests/Functionnal/casperjs/exe/10_login.js @@ -0,0 +1,25 @@ +casper.test.comment('Testing login'); + +casper.start(thelia2_login_admin_url, function() { + this.echo('\nLOGIN'); + this.test.assertTitle('Welcome - Thelia Back Office', 'Web page title OK'); + this.sendKeys('form[action*="checklogin"] input[name="thelia_admin_login[username]"]', 'thelia2'); + this.sendKeys('form[action*="checklogin"] input[name="thelia_admin_login[password]"]', 'thelia2'); + this.click('form[action*="checklogin"] input[type="submit"]'); +}); + +casper.wait(1000, function() { + this.echo("\nWaiting...."); +}); + +casper.then(function(){ + this.echo('\nDASHBOARD'); + console.log('Now on : ' + this.getCurrentUrl()); + this.test.assertTitle('Back-office home - Thelia Back Office', 'Web page title OK'); + this.test.assertSelectorHasText('#wrapper > div', ' This is the administration home page. Put some interesting statistics here, and display useful information :) ', 'Web page main content OK'); +}); + +//RUN +casper.run(function() { + this.test.done(); +}); \ No newline at end of file diff --git a/core/lib/Thelia/Tests/Functionnal/casperjs/run.sh b/core/lib/Thelia/Tests/Functionnal/casperjs/run.sh new file mode 100755 index 000000000..6e054b152 --- /dev/null +++ b/core/lib/Thelia/Tests/Functionnal/casperjs/run.sh @@ -0,0 +1,26 @@ +#!/bin/bash +# @author Guillaume MOREL + +echo "Force dropping database. All data will be lost." + +cd local/config/ + +echo -e "\n\e[01;34m[INFO] Building Models file\e[00m\n" +../../bin/propel build -v --output-dir=../../core/lib/ + +echo -e "\n\e[01;34m[INFO] Building SQL CREATE file\e[00m\n" +../../bin/propel sql:build -v --output-dir=../../install/ + +echo -e "\n\e[01;34m[INFO] Reloaded Thelia2 database\e[00m\n" +cd ../.. +rm install/sqldb.map +php Thelia thelia:dev:reloadDB + +echo -e "\n\e[01;34m[INFO] Installing fixtures\e[00m\n" +php install/faker.php + +echo -e "\n\e[01;34m[INFO] Adding admin\e[00m\n" +php Thelia thelia:create-admin --login_name thelia2 --password thelia2 --last_name thelia2 --first_name thelia2 + +# casperjs test ./exe --pre=./conf/local.js --direct + diff --git a/core/lib/Thelia/Tests/Functionnal/casperjs/run_ci.sh b/core/lib/Thelia/Tests/Functionnal/casperjs/run_ci.sh new file mode 100755 index 000000000..785d8ee49 --- /dev/null +++ b/core/lib/Thelia/Tests/Functionnal/casperjs/run_ci.sh @@ -0,0 +1,4 @@ +#!/bin/bash +# @author Quentin Dufour + +/usrcasperjs test ./exe --pre=./conf/dit.js --xunit=reports/report.xml diff --git a/templates/admin/default/assets/js/coupon.js b/templates/admin/default/assets/js/coupon.js new file mode 100644 index 000000000..5c52aa097 --- /dev/null +++ b/templates/admin/default/assets/js/coupon.js @@ -0,0 +1,148 @@ +$(function($){ + + // Clean array from deleteValue (undefined) keys + Array.prototype.clean = function(deleteValue) { + for (var i = 0; i < this.length; i++) { + if (this[i] == deleteValue) { + this.splice(i, 1); + i--; + } + } + return this; + }; + + // Remove 1 Rule then Save Rules AJAX + couponManager.removeRuleAjax = function(id) { + // Delete rule in temporary array + delete couponManager.rulesToSave[id]; + couponManager.rulesToSave.clean(undefined); + + // Save + couponManager.saveRuleAjax(); + }; + + // Add 1 Rule / or update the temporary Rules array then Save Rules via AJAX + couponManager.addRuleAjax = function(id) { + console.log('addRuleAjax '+ id); + // If create + if(!id) { + console.log('pushing'); + couponManager.rulesToSave.push(couponManager.ruleToSave); + } else { // else update + console.log('editing ' + id); + couponManager.rulesToSave[id] = couponManager.ruleToSave; + // reset edit mode to off + couponManager.ruleIdToUpdate = false; + } + + // Save + couponManager.saveRuleAjax(); + }; + + // Set rule inputs to allow editing + couponManager.updateRuleAjax = function(id) { + couponManager.ruleToUpdate = couponManager.rulesToSave[id]; + console.log('Set id to edit to ' + id); + couponManager.ruleIdToUpdate = id; + + // Deleting this rule, we will reset it + delete couponManager.rulesToSave[id]; + + // Set the rule selector + $("#category-rule option").filter(function() { + return $(this).val() == couponManager.ruleToUpdate.serviceId; + }).prop('selected', true); + + // Force rule input refresh + couponManager.loadRuleInputs(couponManager.ruleToUpdate.serviceId, function() { + couponManager.fillInRuleInputs(); + }); + }; + + // Fill in rule inputs + couponManager.fillInRuleInputs = function() { + console.log('fillInRuleInputs with'); + console.log(couponManager.ruleToUpdate); + var operatorId = null; + var valueId = null; + var idName = null; + + for (idName in couponManager.ruleToUpdate.operators) { + // Setting idName operator select + operatorId = idName + '-operator'; + $('#' + operatorId).val(couponManager.ruleToUpdate.operators[idName]); + + valueId = idName + '-value'; + // Setting idName value input + $('#' + valueId).val(couponManager.ruleToUpdate.values[idName]); + } + couponManager.ruleToSave = couponManager.ruleToUpdate; + + var id = couponManager.ruleIdToUpdate; + console.log('id to edit = ' + id); + if(id) { + console.log('setint rulesToSave[' + id + ']'); + console.log(couponManager.ruleToSave); + couponManager.rulesToSave[id] = couponManager.ruleToSave; + } + }; + + // Save rules on click + couponManager.onClickSaveRule = function() { + $('#constraint-save-btn').on('click', function () { + couponManager.addRuleAjax(couponManager.ruleIdToUpdate); + }); + }; + couponManager.onClickSaveRule(); + + // Remove rule on click + couponManager.onClickDeleteRule = function() { + $('.constraint-delete-btn').on('click', function (e) { + e.preventDefault(); + var $this = $(this); + couponManager.removeRuleAjax($this.attr('data-int')); + }); + }; + couponManager.onClickDeleteRule(); + + // Update rule on click + couponManager.onClickUpdateRule = function() { + $('.constraint-update-btn').on('click', function (e) { + e.preventDefault(); + var $this = $(this); + couponManager.updateRuleAjax($this.attr('data-int')); + + // Hide row being updated + $this.parent().parent().remove(); + }); + }; + couponManager.onClickUpdateRule(); + + // Reload effect inputs when changing effect + couponManager.onEffectChange = function() { + $('#effect').on('change', function () { + var optionSelected = $("option:selected", this); + $('#effectToolTip').html(optionSelected.attr("data-description")); + }); + }; + couponManager.onEffectChange(); + + // Reload rule inputs when changing effect + couponManager.onRuleChange = function() { + $('#category-rule').on('change', function () { + couponManager.loadRuleInputs($(this).val(), function(ruleToSave) {}); + }); + }; + couponManager.onRuleChange(); + + // Fill in ready to be saved rule array + // var onInputsChange = function() + // In AJAX response + +}); + +// Rule to save + +var couponManager = {}; +couponManager.ruleToSave = {}; +couponManager.ruleIdToUpdate = false; \ No newline at end of file diff --git a/templates/admin/default/coupon-update.html b/templates/admin/default/coupon-update.html index 3895475b4..925296aae 100755 --- a/templates/admin/default/coupon-update.html +++ b/templates/admin/default/coupon-update.html @@ -37,24 +37,19 @@ {/javascripts} + {javascripts file='assets/js/coupon.js'} + + {/javascripts} + {/block} diff --git a/templates/admin/default/coupon/rule-input-ajax.html b/templates/admin/default/coupon/rule-input-ajax.html index 4933c6745..cdf683d21 100644 --- a/templates/admin/default/coupon/rule-input-ajax.html +++ b/templates/admin/default/coupon/rule-input-ajax.html @@ -72,29 +72,31 @@ \ No newline at end of file From 870612f51c8a9aba45e79cdeeccb932cfe34e2f4 Mon Sep 17 00:00:00 2001 From: gmorel Date: Wed, 11 Sep 2013 14:43:09 +0200 Subject: [PATCH 07/32] WIP - Coupon Add/Edit/Delete rule AJAX - add tests casper JS --- core/lib/Thelia/Tests/Functionnal/casperjs/conf/dit.js | 3 --- core/lib/Thelia/Tests/Functionnal/casperjs/conf/uat.js | 3 --- core/lib/Thelia/Tests/Functionnal/casperjs/run_ci.sh | 4 ---- 3 files changed, 10 deletions(-) delete mode 100644 core/lib/Thelia/Tests/Functionnal/casperjs/conf/dit.js delete mode 100644 core/lib/Thelia/Tests/Functionnal/casperjs/conf/uat.js delete mode 100755 core/lib/Thelia/Tests/Functionnal/casperjs/run_ci.sh diff --git a/core/lib/Thelia/Tests/Functionnal/casperjs/conf/dit.js b/core/lib/Thelia/Tests/Functionnal/casperjs/conf/dit.js deleted file mode 100644 index b89267246..000000000 --- a/core/lib/Thelia/Tests/Functionnal/casperjs/conf/dit.js +++ /dev/null @@ -1,3 +0,0 @@ -//DIT = Environnement d'intégration -var copark_base_url = 'http://ws.copark.dit.linux.thelia.fr/'; -casper.test.done(0); diff --git a/core/lib/Thelia/Tests/Functionnal/casperjs/conf/uat.js b/core/lib/Thelia/Tests/Functionnal/casperjs/conf/uat.js deleted file mode 100644 index 02b753869..000000000 --- a/core/lib/Thelia/Tests/Functionnal/casperjs/conf/uat.js +++ /dev/null @@ -1,3 +0,0 @@ -//UAT = Recette client -var copark_base_url = 'http://ws.copark.uat.openstudio.fr/'; -casper.test.done(0); \ No newline at end of file diff --git a/core/lib/Thelia/Tests/Functionnal/casperjs/run_ci.sh b/core/lib/Thelia/Tests/Functionnal/casperjs/run_ci.sh deleted file mode 100755 index 785d8ee49..000000000 --- a/core/lib/Thelia/Tests/Functionnal/casperjs/run_ci.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash -# @author Quentin Dufour - -/usrcasperjs test ./exe --pre=./conf/dit.js --xunit=reports/report.xml From ec245862327d6a3722c4d41c70b87d5562452232 Mon Sep 17 00:00:00 2001 From: Manuel Raynaud Date: Wed, 11 Sep 2013 15:04:47 +0200 Subject: [PATCH 08/32] add some information in propelcollector --- .../DebugBar/DataCollector/PropelCollector.php | 4 ++-- .../modules/DebugBar/Smarty/Plugin/DebugBar.php | 17 ----------------- templates/admin/default/admin-layout.tpl | 2 +- 3 files changed, 3 insertions(+), 20 deletions(-) diff --git a/local/modules/DebugBar/DataCollector/PropelCollector.php b/local/modules/DebugBar/DataCollector/PropelCollector.php index 823a31666..b0d503b18 100644 --- a/local/modules/DebugBar/DataCollector/PropelCollector.php +++ b/local/modules/DebugBar/DataCollector/PropelCollector.php @@ -66,8 +66,8 @@ class PropelCollector extends DataCollector implements Renderable, LoggerInterfa return array( 'nb_statements' => count($this->statements), 'nb_failed_statements' => 0, - 'accumulated_duration' => '10', - 'accumulated_duration_str' => $this->formatDuration(1), + 'accumulated_duration' => $this->accumulatedTime, + 'accumulated_duration_str' => $this->formatDuration($this->accumulatedTime), 'peak_memory_usage' => $this->peakMemory, 'peak_memory_usage_str' => $this->formatBytes($this->peakMemory), 'statements' => $this->statements diff --git a/local/modules/DebugBar/Smarty/Plugin/DebugBar.php b/local/modules/DebugBar/Smarty/Plugin/DebugBar.php index 70a896433..0cd1abee9 100644 --- a/local/modules/DebugBar/Smarty/Plugin/DebugBar.php +++ b/local/modules/DebugBar/Smarty/Plugin/DebugBar.php @@ -104,23 +104,6 @@ class DebugBar extends AbstractSmartyPlugin return $render; } - public function renderHead($params, \Smarty_Internal_Template $template) - { - $render = ""; - if ($this->debugMode) { - $javascriptRenderer = $this->debugBar->getJavascriptRenderer(); - $assets = $javascriptRenderer->getAssets(); - - $cssCollection = $assets[0]; - $jsCollection = $assets[1]; - - $render .= sprintf('', $cssCollection->dump()); - $render .= sprintf('', $jsCollection->dump()); - } - - return $render; - } - /** * @return an array of SmartyPluginDescriptor */ diff --git a/templates/admin/default/admin-layout.tpl b/templates/admin/default/admin-layout.tpl index 942557600..188ba75f4 100644 --- a/templates/admin/default/admin-layout.tpl +++ b/templates/admin/default/admin-layout.tpl @@ -224,7 +224,7 @@ {debugbar_renderjs} - {debugbar_renderresult} + {block name="after-javascript-include"}{/block} From 1ec9e7486d57f803e2dda4bfd45d027b0be01dc0 Mon Sep 17 00:00:00 2001 From: Manuel Raynaud Date: Wed, 11 Sep 2013 15:21:43 +0200 Subject: [PATCH 09/32] just add Propel information in phpDebugBar --- local/modules/DebugBar/Config/config.xml | 2 +- local/modules/DebugBar/Listeners/DebugBarListeners.php | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/local/modules/DebugBar/Config/config.xml b/local/modules/DebugBar/Config/config.xml index 6713c8ce6..12c5ccd24 100644 --- a/local/modules/DebugBar/Config/config.xml +++ b/local/modules/DebugBar/Config/config.xml @@ -30,7 +30,7 @@ - + diff --git a/local/modules/DebugBar/Listeners/DebugBarListeners.php b/local/modules/DebugBar/Listeners/DebugBarListeners.php index 7d0981d5d..336aa952c 100644 --- a/local/modules/DebugBar/Listeners/DebugBarListeners.php +++ b/local/modules/DebugBar/Listeners/DebugBarListeners.php @@ -22,7 +22,11 @@ /*************************************************************************************/ namespace DebugBar\Listeners; +use DebugBar\DataCollector\MemoryCollector; +use DebugBar\DataCollector\MessagesCollector; +use DebugBar\DataCollector\PhpInfoCollector; use DebugBar\DataCollector\PropelCollector; +use DebugBar\DataCollector\TimeDataCollector; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpKernel\KernelEvents; use Thelia\Action\BaseAction; @@ -40,6 +44,12 @@ class DebugBarListeners extends BaseAction implements EventSubscriberInterface { { $debugBar = $this->container->get("debugBar"); + + $debugBar->addCollector(new PhpInfoCollector()); + //$debugBar->addCollector(new MessagesCollector()); + //$debugBar->addCollector(new RequestDataCollector()); + //$debugBar->addCollector(new TimeDataCollector()); + $debugBar->addCollector(new MemoryCollector()); $debugBar->addCollector(new PropelCollector()); } From 769993cc96f21eb37bd0dc7eb1024be8c3985da7 Mon Sep 17 00:00:00 2001 From: Manuel Raynaud Date: Wed, 11 Sep 2013 15:26:47 +0200 Subject: [PATCH 10/32] add TimeDataCollector --- local/modules/DebugBar/Listeners/DebugBarListeners.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/local/modules/DebugBar/Listeners/DebugBarListeners.php b/local/modules/DebugBar/Listeners/DebugBarListeners.php index 336aa952c..f789a9a13 100644 --- a/local/modules/DebugBar/Listeners/DebugBarListeners.php +++ b/local/modules/DebugBar/Listeners/DebugBarListeners.php @@ -48,7 +48,7 @@ class DebugBarListeners extends BaseAction implements EventSubscriberInterface { $debugBar->addCollector(new PhpInfoCollector()); //$debugBar->addCollector(new MessagesCollector()); //$debugBar->addCollector(new RequestDataCollector()); - //$debugBar->addCollector(new TimeDataCollector()); + $debugBar->addCollector(new TimeDataCollector()); $debugBar->addCollector(new MemoryCollector()); $debugBar->addCollector(new PropelCollector()); } From c8b5b9e9fa9800e387e7a3b9eed5fe3af409b000 Mon Sep 17 00:00:00 2001 From: gmorel Date: Wed, 11 Sep 2013 15:35:25 +0200 Subject: [PATCH 11/32] Working - add tests casper JS --- .../Functionnal/casperjs/exe/10_login.js | 25 ----------------- .../casperjs/run.sh => run_casperjs.sh | 3 +-- templates/admin/default/login.html | 4 +-- .../functionnal}/casperjs/conf/local.js | 0 .../casperjs/exe/00_parameters.js | 0 tests/functionnal/casperjs/exe/10_login.js | 27 +++++++++++++++++++ 6 files changed, 30 insertions(+), 29 deletions(-) delete mode 100644 core/lib/Thelia/Tests/Functionnal/casperjs/exe/10_login.js rename core/lib/Thelia/Tests/Functionnal/casperjs/run.sh => run_casperjs.sh (87%) rename {core/lib/Thelia/Tests/Functionnal => tests/functionnal}/casperjs/conf/local.js (100%) rename {core/lib/Thelia/Tests/Functionnal => tests/functionnal}/casperjs/exe/00_parameters.js (100%) create mode 100644 tests/functionnal/casperjs/exe/10_login.js diff --git a/core/lib/Thelia/Tests/Functionnal/casperjs/exe/10_login.js b/core/lib/Thelia/Tests/Functionnal/casperjs/exe/10_login.js deleted file mode 100644 index c9c4095db..000000000 --- a/core/lib/Thelia/Tests/Functionnal/casperjs/exe/10_login.js +++ /dev/null @@ -1,25 +0,0 @@ -casper.test.comment('Testing login'); - -casper.start(thelia2_login_admin_url, function() { - this.echo('\nLOGIN'); - this.test.assertTitle('Welcome - Thelia Back Office', 'Web page title OK'); - this.sendKeys('form[action*="checklogin"] input[name="thelia_admin_login[username]"]', 'thelia2'); - this.sendKeys('form[action*="checklogin"] input[name="thelia_admin_login[password]"]', 'thelia2'); - this.click('form[action*="checklogin"] input[type="submit"]'); -}); - -casper.wait(1000, function() { - this.echo("\nWaiting...."); -}); - -casper.then(function(){ - this.echo('\nDASHBOARD'); - console.log('Now on : ' + this.getCurrentUrl()); - this.test.assertTitle('Back-office home - Thelia Back Office', 'Web page title OK'); - this.test.assertSelectorHasText('#wrapper > div', ' This is the administration home page. Put some interesting statistics here, and display useful information :) ', 'Web page main content OK'); -}); - -//RUN -casper.run(function() { - this.test.done(); -}); \ No newline at end of file diff --git a/core/lib/Thelia/Tests/Functionnal/casperjs/run.sh b/run_casperjs.sh similarity index 87% rename from core/lib/Thelia/Tests/Functionnal/casperjs/run.sh rename to run_casperjs.sh index 6e054b152..88636a9d1 100755 --- a/core/lib/Thelia/Tests/Functionnal/casperjs/run.sh +++ b/run_casperjs.sh @@ -22,5 +22,4 @@ php install/faker.php echo -e "\n\e[01;34m[INFO] Adding admin\e[00m\n" php Thelia thelia:create-admin --login_name thelia2 --password thelia2 --last_name thelia2 --first_name thelia2 -# casperjs test ./exe --pre=./conf/local.js --direct - +casperjs test ./tests/functionnal/casperjs/exe --pre=./tests/functionnal/casperjs/conf/local.js --direct diff --git a/templates/admin/default/login.html b/templates/admin/default/login.html index 8815eb982..2b994359c 100755 --- a/templates/admin/default/login.html +++ b/templates/admin/default/login.html @@ -28,13 +28,13 @@ {form_field form=$form field='username'} - + {/form_field} {form_field form=$form field='password'} - + {/form_field} diff --git a/core/lib/Thelia/Tests/Functionnal/casperjs/conf/local.js b/tests/functionnal/casperjs/conf/local.js similarity index 100% rename from core/lib/Thelia/Tests/Functionnal/casperjs/conf/local.js rename to tests/functionnal/casperjs/conf/local.js diff --git a/core/lib/Thelia/Tests/Functionnal/casperjs/exe/00_parameters.js b/tests/functionnal/casperjs/exe/00_parameters.js similarity index 100% rename from core/lib/Thelia/Tests/Functionnal/casperjs/exe/00_parameters.js rename to tests/functionnal/casperjs/exe/00_parameters.js diff --git a/tests/functionnal/casperjs/exe/10_login.js b/tests/functionnal/casperjs/exe/10_login.js new file mode 100644 index 000000000..81757168d --- /dev/null +++ b/tests/functionnal/casperjs/exe/10_login.js @@ -0,0 +1,27 @@ +casper.test.comment('Testing login'); + +casper.start(thelia2_login_admin_url, function() { + this.echo('\nLOGIN'); + this.test.assertTitle('Welcome - Thelia Back Office', 'Web page title OK'); + this.sendKeys('input#username', 'thelia2'); + this.sendKeys('input#password', 'thelia2'); + this.click('form[action*="checklogin"] button[type="submit"]'); +}); + +casper.wait(1000, function() { + this.echo("\nWaiting...."); +}); + +casper.then(function(){ + this.echo('\nDASHBOARD'); + + console.log('Now on : ' + this.getCurrentUrl()); + // @todo implement dashboard +// this.test.assertTitle('Back-office home - Thelia Back Office', 'Web page title OK'); +// this.test.assertSelectorHasText('#wrapper > div', ' This is the administration home page. Put some interesting statistics here, and display useful information :) ', 'Web page main content OK'); +}); + +//RUN +casper.run(function() { + this.test.done(); +}); \ No newline at end of file From c1edc0e4ffae4248d02d12d4fb9a9372475e4477 Mon Sep 17 00:00:00 2001 From: Manuel Raynaud Date: Wed, 11 Sep 2013 15:48:55 +0200 Subject: [PATCH 12/32] update phpdebugbar dependency --- composer.json | 3 +-- composer.lock | 16 ++++++++-------- .../Thelia/Config/Resources/routing/front.xml | 2 +- templates/default/layout.tpl | 7 +++++++ 4 files changed, 17 insertions(+), 11 deletions(-) diff --git a/composer.json b/composer.json index 9d179a987..2d315bd3a 100755 --- a/composer.json +++ b/composer.json @@ -36,13 +36,12 @@ "simplepie/simplepie": "dev-master", "imagine/imagine": "dev-master", - "symfony/serializer": "dev-master", "symfony/icu": "1.0" }, "require-dev" : { "phpunit/phpunit": "3.7.*", "fzaninotto/faker": "dev-master", - "maximebf/debugbar": "1.*" + "maximebf/debugbar": "dev-master" }, "minimum-stability": "stable", "config" : { diff --git a/composer.lock b/composer.lock index 0215c3d0f..61160ea49 100755 --- a/composer.lock +++ b/composer.lock @@ -3,8 +3,7 @@ "This file locks the dependencies of your project to a known state", "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file" ], - "hash": "ba2f3e0943f00c7c3bf0c086bc611b0f", - + "hash": "28dfdc7a840f9e70df422581f82a871f", "packages": [ { "name": "imagine/imagine", @@ -1621,16 +1620,16 @@ }, { "name": "maximebf/debugbar", - "version": "1.5.1", + "version": "dev-master", "source": { "type": "git", "url": "https://github.com/maximebf/php-debugbar.git", - "reference": "37dccc40da52bf9f85571c30cf302da696db0d05" + "reference": "7fbe0a5d4ffc7f4e205c2b15542382308d34bd0d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/maximebf/php-debugbar/zipball/37dccc40da52bf9f85571c30cf302da696db0d05", - "reference": "37dccc40da52bf9f85571c30cf302da696db0d05", + "url": "https://api.github.com/repos/maximebf/php-debugbar/zipball/7fbe0a5d4ffc7f4e205c2b15542382308d34bd0d", + "reference": "7fbe0a5d4ffc7f4e205c2b15542382308d34bd0d", "shasum": "" }, "require": { @@ -1666,7 +1665,7 @@ "keywords": [ "debug" ], - "time": "2013-08-17 02:02:49" + "time": "2013-09-11 13:01:19" }, { "name": "phpunit/php-code-coverage", @@ -2048,7 +2047,8 @@ "ptachoire/cssembed": 20, "simplepie/simplepie": 20, "imagine/imagine": 20, - "fzaninotto/faker": 20 + "fzaninotto/faker": 20, + "maximebf/debugbar": 20 }, "platform": { "php": ">=5.4" diff --git a/core/lib/Thelia/Config/Resources/routing/front.xml b/core/lib/Thelia/Config/Resources/routing/front.xml index bb1e9422b..aefd77fd1 100755 --- a/core/lib/Thelia/Config/Resources/routing/front.xml +++ b/core/lib/Thelia/Config/Resources/routing/front.xml @@ -34,7 +34,7 @@ login - + Thelia\Controller\Front\CustomerController::logoutAction diff --git a/templates/default/layout.tpl b/templates/default/layout.tpl index 3b2fe5dcd..5ef6f5386 100644 --- a/templates/default/layout.tpl +++ b/templates/default/layout.tpl @@ -84,8 +84,15 @@ URL: http://www.thelia.net {/loop}
diff --git a/templates/default/password.html b/templates/default/password.html new file mode 100644 index 000000000..c65691fb6 --- /dev/null +++ b/templates/default/password.html @@ -0,0 +1,33 @@ +{extends file="layout.tpl"} + +{block name="breadcrumb"} + +{/block} + +{block name="main-content"} +
+
+

{intl l="Password Forgotten"}

+ +
+ +

{intl l="Please enter your email address below. You will receive a link to reset your password."}

+ +
+ + +
+
+ {intl l="Cancel"} + +
+
+
+
+{/block} diff --git a/templates/default/register.html b/templates/default/register.html index 9e0caf202..7100737bc 100644 --- a/templates/default/register.html +++ b/templates/default/register.html @@ -4,7 +4,7 @@ From 25756ef9dd81f414a25cacb40e9347950a8fbd8b Mon Sep 17 00:00:00 2001 From: Etienne Roudeix Date: Wed, 11 Sep 2013 16:56:16 +0200 Subject: [PATCH 17/32] tax engine --- .../Thelia/Exception/TaxEngineException.php | 6 ++++ core/lib/Thelia/Model/Tax.php | 3 +- core/lib/Thelia/Model/TaxRuleQuery.php | 2 +- core/lib/Thelia/TaxEngine/Calculator.php | 5 +++- .../Thelia/TaxEngine/TaxType/BaseTaxType.php | 19 +++++------- .../Thelia/Tests/TaxEngine/CalculatorTest.php | 30 ++++++++++--------- 6 files changed, 35 insertions(+), 30 deletions(-) diff --git a/core/lib/Thelia/Exception/TaxEngineException.php b/core/lib/Thelia/Exception/TaxEngineException.php index 8ce8561ef..93f5b8237 100755 --- a/core/lib/Thelia/Exception/TaxEngineException.php +++ b/core/lib/Thelia/Exception/TaxEngineException.php @@ -30,9 +30,15 @@ class TaxEngineException extends \RuntimeException const BAD_RECORDED_TYPE = 101; const BAD_RECORDED_REQUIREMENTS = 102; + const TAX_TYPE_BAD_ABSTRACT_METHOD = 201; + const TAX_TYPE_REQUIREMENT_NOT_FOUND = 202; + const TAX_TYPE_BAD_REQUIREMENT_VALUE = 203; + const UNDEFINED_PRODUCT = 501; const UNDEFINED_COUNTRY = 502; const UNDEFINED_TAX_RULES_COLLECTION = 503; + const UNDEFINED_REQUIREMENTS = 504; + const UNDEFINED_REQUIREMENT_VALUE = 505; const BAD_AMOUNT_FORMAT = 601; diff --git a/core/lib/Thelia/Model/Tax.php b/core/lib/Thelia/Model/Tax.php index 58144d551..738f16508 100755 --- a/core/lib/Thelia/Model/Tax.php +++ b/core/lib/Thelia/Model/Tax.php @@ -2,7 +2,6 @@ namespace Thelia\Model; -use Symfony\Component\Form\Exception\Exception; use Thelia\Exception\TaxEngineException; use Thelia\Model\Base\Tax as BaseTax; use Thelia\TaxEngine\TaxType\BaseTaxType; @@ -49,7 +48,7 @@ class Tax extends BaseTax if(!$instance instanceof BaseTaxType) { throw new TaxEngineException('Recorded type does not extends BaseTaxType', TaxEngineException::BAD_RECORDED_TYPE); } - + return $instance; } diff --git a/core/lib/Thelia/Model/TaxRuleQuery.php b/core/lib/Thelia/Model/TaxRuleQuery.php index 75a21a453..d5ce47546 100755 --- a/core/lib/Thelia/Model/TaxRuleQuery.php +++ b/core/lib/Thelia/Model/TaxRuleQuery.php @@ -21,7 +21,7 @@ class TaxRuleQuery extends BaseTaxRuleQuery { const ALIAS_FOR_TAX_RULE_COUNTRY_POSITION = 'taxRuleCountryPosition'; - public function getTaxCalculatorGroupedCollection(Product $product, Country $country) + public function getTaxCalculatorCollection(Product $product, Country $country) { $search = TaxQuery::create() ->filterByTaxRuleCountry( diff --git a/core/lib/Thelia/TaxEngine/Calculator.php b/core/lib/Thelia/TaxEngine/Calculator.php index 1630ad550..2708e88c6 100755 --- a/core/lib/Thelia/TaxEngine/Calculator.php +++ b/core/lib/Thelia/TaxEngine/Calculator.php @@ -34,6 +34,9 @@ use Thelia\Model\TaxRuleQuery; */ class Calculator { + /** + * @var TaxRuleQuery + */ protected $taxRuleQuery = null; protected $taxRulesCollection = null; @@ -62,7 +65,7 @@ class Calculator $this->product = $product; $this->country = $country; - $this->taxRulesCollection = $this->taxRuleQuery->getTaxCalculatorGroupedCollection($product, $country); + $this->taxRulesCollection = $this->taxRuleQuery->getTaxCalculatorCollection($product, $country); return $this; } diff --git a/core/lib/Thelia/TaxEngine/TaxType/BaseTaxType.php b/core/lib/Thelia/TaxEngine/TaxType/BaseTaxType.php index d155bb4c0..7f487bf64 100755 --- a/core/lib/Thelia/TaxEngine/TaxType/BaseTaxType.php +++ b/core/lib/Thelia/TaxEngine/TaxType/BaseTaxType.php @@ -22,6 +22,7 @@ /*************************************************************************************/ namespace Thelia\TaxEngine\TaxType; +use Thelia\Exception\TaxEngineException; use Thelia\Type\TypeInterface; /** @@ -42,24 +43,20 @@ abstract class BaseTaxType $this->requirements = $this->getRequirementsList(); if(!is_array($this->requirements)) { - //@todo throw sg - exit('err_1'); + throw new TaxEngineException('getRequirementsList must return an array', TaxEngineException::TAX_TYPE_BAD_ABSTRACT_METHOD); } foreach($this->requirements as $requirement => $requirementType) { if(!$requirementType instanceof TypeInterface) { - //@todo throw sg - exit('err_2'); + throw new TaxEngineException('getRequirementsList must return an array of TypeInterface', TaxEngineException::TAX_TYPE_BAD_ABSTRACT_METHOD); } if(!array_key_exists($requirement, $requirementsValues)) { - //@todo throw sg - exit('err_3'); + throw new TaxEngineException('Cannot load requirements : requirement value for `' . $requirement . '` not found', TaxEngineException::TAX_TYPE_REQUIREMENT_NOT_FOUND); } if(!$requirementType->isValid($requirementsValues[$requirement])) { - //@todo throw sg - exit('err_4'); + throw new TaxEngineException('Requirement value for `' . $requirement . '` does not match required type', TaxEngineException::TAX_TYPE_BAD_REQUIREMENT_VALUE); } $this->requirements[$requirement] = $requirementsValues[$requirement]; @@ -69,13 +66,11 @@ abstract class BaseTaxType public function getRequirement($key) { if($this->requirements === null) { - //@todo throw sg - exit('err_5'); + throw new TaxEngineException('Requirements are empty in BaseTaxType::getRequirement', TaxEngineException::UNDEFINED_REQUIREMENTS); } if(!array_key_exists($key, $this->requirements)) { - //@todo throw sg - exit('err_6'); + throw new TaxEngineException('Requirement value for `' . $key . '` does not exists in BaseTaxType::$requirements', TaxEngineException::UNDEFINED_REQUIREMENT_VALUE); } return $this->requirements[$key]; diff --git a/core/lib/Thelia/Tests/TaxEngine/CalculatorTest.php b/core/lib/Thelia/Tests/TaxEngine/CalculatorTest.php index fac6ca643..719d90835 100755 --- a/core/lib/Thelia/Tests/TaxEngine/CalculatorTest.php +++ b/core/lib/Thelia/Tests/TaxEngine/CalculatorTest.php @@ -83,9 +83,9 @@ class CalculatorTest extends \PHPUnit_Framework_TestCase $calculator = new Calculator(); - $taxRuleQuery = $this->getMock('\Thelia\Model\TaxRuleQuery', array('getTaxCalculatorGroupedCollection')); + $taxRuleQuery = $this->getMock('\Thelia\Model\TaxRuleQuery', array('getTaxCalculatorCollection')); $taxRuleQuery->expects($this->once()) - ->method('getTaxCalculatorGroupedCollection') + ->method('getTaxCalculatorCollection') ->with($productQuery, $countryQuery) ->will($this->returnValue('foo')); @@ -104,7 +104,7 @@ class CalculatorTest extends \PHPUnit_Framework_TestCase ); $this->assertEquals( 'foo', - $this->getProperty('taxRulesGroupedCollection')->getValue($calculator) + $this->getProperty('taxRulesCollection')->getValue($calculator) ); } @@ -124,35 +124,37 @@ class CalculatorTest extends \PHPUnit_Framework_TestCase */ public function testGetTaxAmountBadAmount() { - $taxRulesGroupedCollection = new ObjectCollection(); + $taxRulesCollection = new ObjectCollection(); $calculator = new Calculator(); - $rewritingUrlQuery = $this->getProperty('taxRulesGroupedCollection'); - $rewritingUrlQuery->setValue($calculator, $taxRulesGroupedCollection); + $rewritingUrlQuery = $this->getProperty('taxRulesCollection'); + $rewritingUrlQuery->setValue($calculator, $taxRulesCollection); $calculator->getTaxAmount('foo'); } public function testGetTaxAmountAndGetTaxedPrice() { - $taxRulesGroupedCollection = new ObjectCollection(); - $taxRulesGroupedCollection->setModel('\Thelia\Model\Tax'); + $taxRulesCollection = new ObjectCollection(); + $taxRulesCollection->setModel('\Thelia\Model\Tax'); $tax = new Tax(); - $tax->setVirtualColumn('taxRateSum', 10); + $tax->setType('PricePercentTaxType') + ->setRequirements(array('percent' => 10)); - $taxRulesGroupedCollection->append($tax); + $taxRulesCollection->append($tax); $tax = new Tax(); - $tax->setVirtualColumn('taxRateSum', 8); + $tax->setType('PricePercentTaxType') + ->setRequirements(array('percent' => 8)); - $taxRulesGroupedCollection->append($tax); + $taxRulesCollection->append($tax); $calculator = new Calculator(); - $rewritingUrlQuery = $this->getProperty('taxRulesGroupedCollection'); - $rewritingUrlQuery->setValue($calculator, $taxRulesGroupedCollection); + $rewritingUrlQuery = $this->getProperty('taxRulesCollection'); + $rewritingUrlQuery->setValue($calculator, $taxRulesCollection); $taxAmount = $calculator->getTaxAmount(500); $taxedPrice = $calculator->getTaxedPrice(500); From 8d71bfecc51a2f2f4096ff1c3df93fc403b2c671 Mon Sep 17 00:00:00 2001 From: gmorel Date: Wed, 11 Sep 2013 17:06:04 +0200 Subject: [PATCH 18/32] WIP - add tests casper JS on coupon --- tests/functionnal/casperjs/conf/local.js | 2 +- .../functionnal/casperjs/exe/00_parameters.js | 5 +++ tests/functionnal/casperjs/exe/30_coupons.js | 39 +++++++++++++++++++ 3 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 tests/functionnal/casperjs/exe/30_coupons.js diff --git a/tests/functionnal/casperjs/conf/local.js b/tests/functionnal/casperjs/conf/local.js index 366d297f2..9fa930598 100644 --- a/tests/functionnal/casperjs/conf/local.js +++ b/tests/functionnal/casperjs/conf/local.js @@ -1,3 +1,3 @@ //LOCAL = ton pc -var thelia2_base_url = 'http://www.thelia2.dev/index.php/'; +var thelia2_base_url = 'http://www.thelia2.dev/index_dev.php/'; casper.test.done(0); diff --git a/tests/functionnal/casperjs/exe/00_parameters.js b/tests/functionnal/casperjs/exe/00_parameters.js index 81b980d41..a32ee89b5 100644 --- a/tests/functionnal/casperjs/exe/00_parameters.js +++ b/tests/functionnal/casperjs/exe/00_parameters.js @@ -2,6 +2,11 @@ casper.test.comment('Please edit 00_parameters.js to add your configuration'); var thelia2_login_admin_url = thelia2_base_url + 'admin/login'; +var thelia2_login_coupon_list_url = thelia2_base_url + 'admin/login'; +var thelia2_login_coupon_create_url = thelia2_base_url + 'admin/coupon/create'; +var thelia2_login_coupon_read_url = thelia2_base_url + 'admin/coupon/read/1'; +var thelia2_login_coupon_update_url = thelia2_base_url + 'admin/coupon/update/1'; + //var findMyId = /([0-9]+)$/; diff --git a/tests/functionnal/casperjs/exe/30_coupons.js b/tests/functionnal/casperjs/exe/30_coupons.js new file mode 100644 index 000000000..3f3d0ee50 --- /dev/null +++ b/tests/functionnal/casperjs/exe/30_coupons.js @@ -0,0 +1,39 @@ +casper.test.comment('Testing coupons'); + + +////LIST +// @todo implement + +////CREATE +// @todo implement + +//UPDATE COUPON RULE +casper.start(thelia2_login_coupon_update_url, function() { + console.log('Now on : ' + this.getCurrentUrl()); + this.echo('\nCOUPON RULE - EDIT'); + this.test.assertTitle('Update coupon - Thelia Back Office', 'Web page title OK'); +// this.test.assertSelectorHasText('#content-header > h1', 'Liste des pays', 'Web page main content OK'); + this.test.assertSelectorHasText('tbody#constraint-list tr:nth-child(1)', 'If cart total amount is superior to 40 EUR','1st default rule found'); + this.test.assertSelectorHasText('tbody#constraint-list tr:nth-child(2)', 'If cart total amount is inferior to 400 EUR','2nd default rule found'); + + // Create rule + this.evaluate(function() { +// document.querySelector('select#category-rule').selectedItem = 'thelia.constraint.rule.available_for_x_articles'; + $('#category-rule').val('thelia.constraint.rule.available_for_x_articles').change(); + return true; + }); + this.capture('screenshot-category-rule.png'); +// this.click('constraint-list > tr:last-child > td > a.constraint-update-btn'); +}); + + +////EDIT CHECK +// @todo implement + +////DELETE +// @todo implement + +//RUN +casper.run(function() { + this.test.done(); +}); \ No newline at end of file From 33d6c850523849b752db83e7950edd1792b15dc3 Mon Sep 17 00:00:00 2001 From: gmorel Date: Wed, 11 Sep 2013 17:10:36 +0200 Subject: [PATCH 19/32] WIP - add tests casper JS on coupon --- tests/functionnal/casperjs/exe/30_coupons.js | 9 ++++++++- web/index_dev.php | 18 +++++++++--------- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/tests/functionnal/casperjs/exe/30_coupons.js b/tests/functionnal/casperjs/exe/30_coupons.js index 3f3d0ee50..6031d71f8 100644 --- a/tests/functionnal/casperjs/exe/30_coupons.js +++ b/tests/functionnal/casperjs/exe/30_coupons.js @@ -22,10 +22,17 @@ casper.start(thelia2_login_coupon_update_url, function() { $('#category-rule').val('thelia.constraint.rule.available_for_x_articles').change(); return true; }); - this.capture('screenshot-category-rule.png'); + this.capture('tests/functionnal/casperjs/pictures/screenshot-category-rule.png'); // this.click('constraint-list > tr:last-child > td > a.constraint-update-btn'); }); +casper.wait(1000, function() { + this.echo("\nWaiting...."); +}); + +casper.then(function(){ + +}); ////EDIT CHECK // @todo implement diff --git a/web/index_dev.php b/web/index_dev.php index 4d0063268..587631466 100755 --- a/web/index_dev.php +++ b/web/index_dev.php @@ -32,19 +32,19 @@ $env = 'dev'; require __DIR__ . '/../core/bootstrap.php'; // List of allowed IP -$trustedIp = array( - '::1', - '127.0.0.1' -); +//$trustedIp = array( +// '::1', +// '127.0.0.1' +//); $request = Request::createFromGlobals(); $thelia = new Thelia("dev", true); -if ( false === in_array($request->getClientIp(), $trustedIp)) { - // Redirect 401 Unauthorized - $response = new Response('Unauthorized', 401); - $thelia->terminate($request, $response); -} +//if ( false === in_array($request->getClientIp(), $trustedIp)) { +// // Redirect 401 Unauthorized +// $response = new Response('Unauthorized', 401); +// $thelia->terminate($request, $response); +//} $response = $thelia->handle($request)->prepare($request)->send(); From 9cc31626964bcf12f8faa2cb77e9316d3c7cb3e6 Mon Sep 17 00:00:00 2001 From: Manuel Raynaud Date: Wed, 11 Sep 2013 17:22:23 +0200 Subject: [PATCH 20/32] finishing creating lost password template --- core/lib/Thelia/Config/Resources/config.xml | 1 + .../Thelia/Config/Resources/routing/front.xml | 7 +++- .../Controller/Front/CustomerController.php | 37 +++++++++++++++++++ core/lib/Thelia/Core/Event/TheliaEvents.php | 4 ++ templates/default/password.html | 23 ++++++++---- 5 files changed, 64 insertions(+), 8 deletions(-) diff --git a/core/lib/Thelia/Config/Resources/config.xml b/core/lib/Thelia/Config/Resources/config.xml index 74e1f4629..a73d28434 100755 --- a/core/lib/Thelia/Config/Resources/config.xml +++ b/core/lib/Thelia/Config/Resources/config.xml @@ -41,6 +41,7 @@
+ diff --git a/core/lib/Thelia/Config/Resources/routing/front.xml b/core/lib/Thelia/Config/Resources/routing/front.xml index f0c624290..e83dd7f07 100755 --- a/core/lib/Thelia/Config/Resources/routing/front.xml +++ b/core/lib/Thelia/Config/Resources/routing/front.xml @@ -38,11 +38,16 @@ Thelia\Controller\Front\CustomerController::logoutAction - + Thelia\Controller\Front\DefaultController::noAction password + + Thelia\Controller\Front\CustomerController::newPasswordAction + password + + diff --git a/core/lib/Thelia/Controller/Front/CustomerController.php b/core/lib/Thelia/Controller/Front/CustomerController.php index 0a60126e6..a0fd74abc 100755 --- a/core/lib/Thelia/Controller/Front/CustomerController.php +++ b/core/lib/Thelia/Controller/Front/CustomerController.php @@ -24,11 +24,13 @@ namespace Thelia\Controller\Front; use Thelia\Core\Event\CustomerCreateOrUpdateEvent; use Thelia\Core\Event\CustomerLoginEvent; +use Thelia\Core\Event\LostPasswordEvent; use Thelia\Core\Security\Authentication\CustomerUsernamePasswordFormAuthenticator; use Thelia\Core\Security\Exception\AuthenticationException; use Thelia\Core\Security\Exception\UsernameNotFoundException; use Thelia\Form\CustomerCreation; use Thelia\Form\CustomerLogin; +use Thelia\Form\CustomerLostPasswordForm; use Thelia\Form\CustomerModification; use Thelia\Form\Exception\FormValidationException; use Thelia\Model\Customer; @@ -45,6 +47,41 @@ use Thelia\Core\Security\Exception\WrongPasswordException; class CustomerController extends BaseFrontController { use \Thelia\Cart\CartTrait; + + public function newPasswordAction() + { + if (! $this->getSecurityContext()->hasCustomerUser()) { + $message = false; + + $passwordLost = new CustomerLostPasswordForm($this->getRequest()); + + try { + + $form = $this->validateForm($passwordLost); + + $event = new LostPasswordEvent($form->get("email")->getData()); + + $this->dispatch(TheliaEvents::LOST_PASSWORD, $event); + + } catch (FormValidationException $e) { + $message = sprintf("Please check your input: %s", $e->getMessage()); + } catch (\Exception $e) { + $message = sprintf("Sorry, an error occured: %s", $e->getMessage()); + } + + if ($message !== false) { + Tlog::getInstance()->error(sprintf("Error during customer creation process : %s. Exception was %s", $message, $e->getMessage())); + + $passwordLost->setErrorMessage($message); + + $this->getParserContext() + ->addForm($passwordLost) + ->setGeneralError($message) + ; + } + } + } + /** * Create a new customer. * On success, redirect to success_url if exists, otherwise, display the same view again. diff --git a/core/lib/Thelia/Core/Event/TheliaEvents.php b/core/lib/Thelia/Core/Event/TheliaEvents.php index c19d3a400..8aa024615 100755 --- a/core/lib/Thelia/Core/Event/TheliaEvents.php +++ b/core/lib/Thelia/Core/Event/TheliaEvents.php @@ -71,6 +71,10 @@ final class TheliaEvents */ const CUSTOMER_UPDATEACCOUNT = "action.updateCustomer"; + /** + * sent when a customer need a new password + */ + const LOST_PASSWORD = "action.lostPassword"; /** * Sent before the logout of the administrator. */ diff --git a/templates/default/password.html b/templates/default/password.html index c65691fb6..ec472a1f9 100644 --- a/templates/default/password.html +++ b/templates/default/password.html @@ -14,20 +14,29 @@

{intl l="Password Forgotten"}

+ {form name="thelia.customer.lostpassword"} + - - -

{intl l="Please enter your email address below. You will receive a link to reset your password."}

- -
- - +

{intl l="Please enter your email address below." {intl l="You will receive a link to reset your password."}

+ {form_field form=$form field="email"} +
+ +
+ + {if $error} + {$message} + {elseif !$error && $value != ""} + {intl l="You will receive a link to reset your password."} + {/if} +
+ {/form_field}
{intl l="Cancel"}
+ {/form}
{/block} From 41cf74ccac3eb2c0029c0e6ee3d593587e96b15a Mon Sep 17 00:00:00 2001 From: gmorel Date: Wed, 11 Sep 2013 17:22:31 +0200 Subject: [PATCH 21/32] Working - add ajax loader --- .../admin/default/assets/img/ajax-loader.gif | Bin 2545 -> 13582 bytes .../default/assets/less/thelia/thelia.less | 4 ++-- templates/admin/default/coupon-update.html | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/templates/admin/default/assets/img/ajax-loader.gif b/templates/admin/default/assets/img/ajax-loader.gif index 1321dd374af3334dbcd4e031c15a423a0882a71f..948fa9bdb33274f9338eadd930aa1bbd2752882c 100644 GIT binary patch literal 13582 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 Q?ms&a;tm!#2B>%I-{~VEIsgCw diff --git a/templates/admin/default/assets/less/thelia/thelia.less b/templates/admin/default/assets/less/thelia/thelia.less index 8576272bf..ee85c7510 100644 --- a/templates/admin/default/assets/less/thelia/thelia.less +++ b/templates/admin/default/assets/less/thelia/thelia.less @@ -251,6 +251,6 @@ .loading{ background: url("@{imgDir}/ajax-loader.gif") no-repeat; - height: 24px; - width: 24px; + height: 30px; + width: 30px; } \ No newline at end of file diff --git a/templates/admin/default/coupon-update.html b/templates/admin/default/coupon-update.html index 925296aae..16771539a 100755 --- a/templates/admin/default/coupon-update.html +++ b/templates/admin/default/coupon-update.html @@ -19,6 +19,7 @@ {include file='coupon/form.html' formAction={url path={$formAction}} form=$form noRules=false} {/form} + {/block} From bb5946457a1b1f0696ecf22bdbe3a24d5ca021e3 Mon Sep 17 00:00:00 2001 From: Manuel Raynaud Date: Wed, 11 Sep 2013 17:24:26 +0200 Subject: [PATCH 22/32] add missing files --- .../Thelia/Core/Event/LostPasswordEvent.php | 51 ++++++++++ .../Thelia/Form/CustomerLostPasswordForm.php | 96 +++++++++++++++++++ 2 files changed, 147 insertions(+) create mode 100644 core/lib/Thelia/Core/Event/LostPasswordEvent.php create mode 100644 core/lib/Thelia/Form/CustomerLostPasswordForm.php diff --git a/core/lib/Thelia/Core/Event/LostPasswordEvent.php b/core/lib/Thelia/Core/Event/LostPasswordEvent.php new file mode 100644 index 000000000..fe1f9dc5f --- /dev/null +++ b/core/lib/Thelia/Core/Event/LostPasswordEvent.php @@ -0,0 +1,51 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Core\Event; + + +/** + * Class LostPasswordEvent + * @package Thelia\Core\Event + * @author Manuel Raynaud + */ +class LostPasswordEvent extends ActionEvent { + + protected $email; + + public function __construct($email) + { + $this->email = $email; + } + + /** + * @return mixed + */ + public function getEmail() + { + return $this->email; + } + + + +} \ No newline at end of file diff --git a/core/lib/Thelia/Form/CustomerLostPasswordForm.php b/core/lib/Thelia/Form/CustomerLostPasswordForm.php new file mode 100644 index 000000000..d950bf614 --- /dev/null +++ b/core/lib/Thelia/Form/CustomerLostPasswordForm.php @@ -0,0 +1,96 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Form; + +use Symfony\Component\Validator\Constraints\Callback; +use Symfony\Component\Validator\Constraints\Email; +use Symfony\Component\Validator\Constraints\NotBlank; +use Symfony\Component\Validator\ExecutionContextInterface; +use Thelia\Core\Translation\Translator; +use Thelia\Model\CustomerQuery; + +/** + * Class CustomerLostPasswordForm + * @package Thelia\Form + * @author Manuel Raynaud + */ +class CustomerLostPasswordForm extends BaseForm { + + /** + * + * 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 + */ + protected function buildForm() + { + $this->formBuilder + ->add("email", "email", array( + "constraints" => array( + new NotBlank(), + new Email(), + new Callback(array( + "methods" => array( + array($this, + "verifyExistingEmail") + ) + )) + ), + "label" => Translator::getInstance()->trans("Please enter your email address"), + "label_attr" => array( + "for" => "forgot-email" + ) + )); + } + + public function verifyExistingEmail($value, ExecutionContextInterface $context) + { + $customer = CustomerQuery::create()->findOneByEmail($value); + if (null === $customer) { + $context->addViolation("This email does not exists exists"); + } + } + + /** + * @return string the name of you form. This name must be unique + */ + public function getName() + { + return "thelia_customer_creation"; + } +} \ No newline at end of file From d846d108323c0c0f5a9456e793534c5f5ed2fd13 Mon Sep 17 00:00:00 2001 From: gmorel Date: Wed, 11 Sep 2013 17:47:52 +0200 Subject: [PATCH 23/32] Working - CasperJS : coupon rule --- tests/functionnal/casperjs/exe/30_coupons.js | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/tests/functionnal/casperjs/exe/30_coupons.js b/tests/functionnal/casperjs/exe/30_coupons.js index 6031d71f8..2ac04a759 100644 --- a/tests/functionnal/casperjs/exe/30_coupons.js +++ b/tests/functionnal/casperjs/exe/30_coupons.js @@ -9,7 +9,7 @@ casper.test.comment('Testing coupons'); //UPDATE COUPON RULE casper.start(thelia2_login_coupon_update_url, function() { - console.log('Now on : ' + this.getCurrentUrl()); + this.capture('tests/functionnal/casperjs/screenshot/coupons/init.png'); this.echo('\nCOUPON RULE - EDIT'); this.test.assertTitle('Update coupon - Thelia Back Office', 'Web page title OK'); // this.test.assertSelectorHasText('#content-header > h1', 'Liste des pays', 'Web page main content OK'); @@ -18,12 +18,10 @@ casper.start(thelia2_login_coupon_update_url, function() { // Create rule this.evaluate(function() { -// document.querySelector('select#category-rule').selectedItem = 'thelia.constraint.rule.available_for_x_articles'; $('#category-rule').val('thelia.constraint.rule.available_for_x_articles').change(); return true; }); - this.capture('tests/functionnal/casperjs/pictures/screenshot-category-rule.png'); -// this.click('constraint-list > tr:last-child > td > a.constraint-update-btn'); + this.capture('tests/functionnal/casperjs/screenshot/coupons/rule-selected.png'); }); casper.wait(1000, function() { @@ -31,7 +29,21 @@ casper.wait(1000, function() { }); casper.then(function(){ + this.evaluate(function() { + $('#quantity-operator').val('>=').change(); + return true; + }); + this.sendKeys('input#quantity-value', '4'); + this.click('#constraint-save-btn'); +}); +casper.wait(1000, function() { + this.echo("\nWaiting...."); +}); + +casper.then(function(){ + this.capture('tests/functionnal/casperjs/screenshot/coupons/rule-added.png'); + this.test.assertSelectorHasText('tbody#constraint-list tr:nth-child(3)', ' If cart products quantity is superior or equals to 4','3rd rule found'); }); ////EDIT CHECK From fa5c1aaefc97e08ab8d25ec27212adf215739d32 Mon Sep 17 00:00:00 2001 From: Etienne Roudeix Date: Wed, 11 Sep 2013 19:01:23 +0200 Subject: [PATCH 24/32] tax engine --- core/lib/Thelia/Model/Tax.php | 6 +- core/lib/Thelia/TaxEngine/Calculator.php | 26 ++-- .../TaxEngine/TaxType/FixAmountTaxType.php | 45 +++++++ install/tax_faker.php | 116 ++++++++++++++++++ 4 files changed, 183 insertions(+), 10 deletions(-) create mode 100755 core/lib/Thelia/TaxEngine/TaxType/FixAmountTaxType.php create mode 100755 install/tax_faker.php diff --git a/core/lib/Thelia/Model/Tax.php b/core/lib/Thelia/Model/Tax.php index 738f16508..7b9b22b6f 100755 --- a/core/lib/Thelia/Model/Tax.php +++ b/core/lib/Thelia/Model/Tax.php @@ -40,13 +40,13 @@ class Tax extends BaseTax /* test type */ if(!class_exists($class)) { - throw new TaxEngineException('Recorded type does not exists', TaxEngineException::BAD_RECORDED_TYPE); + throw new TaxEngineException('Recorded type `' . $class . '` does not exists', TaxEngineException::BAD_RECORDED_TYPE); } $instance = new $class; if(!$instance instanceof BaseTaxType) { - throw new TaxEngineException('Recorded type does not extends BaseTaxType', TaxEngineException::BAD_RECORDED_TYPE); + throw new TaxEngineException('Recorded type `' . $class . '` does not extends BaseTaxType', TaxEngineException::BAD_RECORDED_TYPE); } return $instance; @@ -54,7 +54,7 @@ class Tax extends BaseTax public function setRequirements($requirements) { - parent::setSerializedRequirements(base64_encode(json_encode($requirements))); + return parent::setSerializedRequirements(base64_encode(json_encode($requirements))); } public function getRequirements() diff --git a/core/lib/Thelia/TaxEngine/Calculator.php b/core/lib/Thelia/TaxEngine/Calculator.php index 2708e88c6..f49498263 100755 --- a/core/lib/Thelia/TaxEngine/Calculator.php +++ b/core/lib/Thelia/TaxEngine/Calculator.php @@ -39,6 +39,9 @@ class Calculator */ protected $taxRuleQuery = null; + /** + * @var null|\Propel\Runtime\Collection\ObjectCollection + */ protected $taxRulesCollection = null; protected $product = null; @@ -80,19 +83,28 @@ class Calculator throw new TaxEngineException('BAD AMOUNT FORMAT', TaxEngineException::BAD_AMOUNT_FORMAT); } - $totalTaxAmount = 0; + $taxedPrice = $untaxedPrice; + $currentPosition = 1; + $currentTax = 0; + foreach($this->taxRulesCollection as $taxRule) { + $position = (int)$taxRule->getTaxRuleCountryPosition(); + $taxType = $taxRule->getTypeInstance(); + $taxType->loadRequirements( $taxRule->getRequirements() ); - $taxType->loadRequirements($taxRule->getRequirements()); + if($currentPosition !== $position) { + $taxedPrice += $currentTax; + $currentTax = 0; + $currentPosition = $position; + } - $taxAmount = $taxType->calculate($untaxedPrice); - - $totalTaxAmount += $taxAmount; - $untaxedPrice += $taxAmount; + $currentTax += $taxType->calculate($taxedPrice); } - return $totalTaxAmount; + $taxedPrice += $currentTax; + + return $taxedPrice; } public function getTaxedPrice($untaxedPrice) diff --git a/core/lib/Thelia/TaxEngine/TaxType/FixAmountTaxType.php b/core/lib/Thelia/TaxEngine/TaxType/FixAmountTaxType.php new file mode 100755 index 000000000..c533d0ec3 --- /dev/null +++ b/core/lib/Thelia/TaxEngine/TaxType/FixAmountTaxType.php @@ -0,0 +1,45 @@ +. */ +/* */ +/*************************************************************************************/ +namespace Thelia\TaxEngine\TaxType; + +use Thelia\Type\FloatType; + +/** + * + * @author Etienne Roudeix + * + */ +class FixAmountTaxType extends BaseTaxType +{ + public function calculate($untaxedPrice) + { + return $this->getRequirement("amount"); + } + + public function getRequirementsList() + { + return array( + 'amount' => new FloatType(), + ); + } +} diff --git a/install/tax_faker.php b/install/tax_faker.php new file mode 100755 index 000000000..5d534e2ef --- /dev/null +++ b/install/tax_faker.php @@ -0,0 +1,116 @@ +boot(); + +$faker = Faker\Factory::create(); + +$con = \Propel\Runtime\Propel::getConnection( + Thelia\Model\Map\ProductTableMap::DATABASE_NAME +); +$con->beginTransaction(); + +$currency = \Thelia\Model\CurrencyQuery::create()->filterByCode('EUR')->findOne(); + +try { + $stmt = $con->prepare("SET foreign_key_checks = 0"); + $stmt->execute(); + + \Thelia\Model\TaxQuery::create() + ->find() + ->delete(); + + \Thelia\Model\Base\TaxRuleQuery::create() + ->find() + ->delete(); + + \Thelia\Model\Base\TaxRuleCountryQuery::create() + ->find() + ->delete(); + + $stmt = $con->prepare("SET foreign_key_checks = 1"); + $stmt->execute(); + + /* 10% tax */ + $tax10p = new \Thelia\Model\Tax(); + $tax10p->setType('PricePercentTaxType') + ->setRequirements(array('percent' => 10)) + ->save(); + + /* 8% tax */ + $tax8p = new \Thelia\Model\Tax(); + $tax8p->setType('PricePercentTaxType') + ->setRequirements(array('percent' => 8)) + ->save(); + + /* fix 5 tax */ + $tax5 = new \Thelia\Model\Tax(); + $tax5->setType('FixAmountTaxType') + ->setRequirements(array('amount' => 5)) + ->save(); + + /* 1% tax */ + $tax1p = new \Thelia\Model\Tax(); + $tax1p->setType('PricePercentTaxType') + ->setRequirements(array('percent' => 1)) + ->save(); + + /* tax rule */ + $taxRule = new \Thelia\Model\TaxRule(); + $taxRule->save(); + + /* add 4 taxes to the rule for France (64) */ + $taxRuleCountry = new \Thelia\Model\TaxRuleCountry(); + $taxRuleCountry->setTaxRule($taxRule) + ->setCountryId(64) + ->setTax($tax10p) + ->setPosition(1) + ->save(); + + $taxRuleCountry = new \Thelia\Model\TaxRuleCountry(); + $taxRuleCountry->setTaxRule($taxRule) + ->setCountryId(64) + ->setTax($tax8p) + ->setPosition(1) + ->save(); + + $taxRuleCountry = new \Thelia\Model\TaxRuleCountry(); + $taxRuleCountry->setTaxRule($taxRule) + ->setCountryId(64) + ->setTax($tax5) + ->setPosition(2) + ->save(); + + $taxRuleCountry = new \Thelia\Model\TaxRuleCountry(); + $taxRuleCountry->setTaxRule($taxRule) + ->setCountryId(64) + ->setTax($tax1p) + ->setPosition(3) + ->save(); + + foreach(\Thelia\Model\ProductQuery::create()->find() as $productActiveRecord) { + $productActiveRecord->setTaxRule($taxRule) + ->save(); + } + + $con->commit(); + +} catch (Exception $e) { + echo "error : ".$e->getMessage()."\n"; + $con->rollBack(); +} From c35de47f10a649601974739d6e4f1d5ad592ded3 Mon Sep 17 00:00:00 2001 From: Etienne Roudeix Date: Wed, 11 Sep 2013 20:18:34 +0200 Subject: [PATCH 25/32] fix taxengine tests --- core/lib/Thelia/TaxEngine/Calculator.php | 10 ++--- .../Thelia/Tests/TaxEngine/CalculatorTest.php | 42 ++++++++++++++++++- 2 files changed, 45 insertions(+), 7 deletions(-) diff --git a/core/lib/Thelia/TaxEngine/Calculator.php b/core/lib/Thelia/TaxEngine/Calculator.php index f49498263..f8c527cd1 100755 --- a/core/lib/Thelia/TaxEngine/Calculator.php +++ b/core/lib/Thelia/TaxEngine/Calculator.php @@ -74,6 +74,11 @@ class Calculator } public function getTaxAmount($untaxedPrice) + { + return $this->getTaxedPrice($untaxedPrice) - $untaxedPrice; + } + + public function getTaxedPrice($untaxedPrice) { if(null === $this->taxRulesCollection) { throw new TaxEngineException('Tax rules collection is empty in Calculator::getTaxAmount', TaxEngineException::UNDEFINED_TAX_RULES_COLLECTION); @@ -106,9 +111,4 @@ class Calculator return $taxedPrice; } - - public function getTaxedPrice($untaxedPrice) - { - return $untaxedPrice + $this->getTaxAmount($untaxedPrice); - } } diff --git a/core/lib/Thelia/Tests/TaxEngine/CalculatorTest.php b/core/lib/Thelia/Tests/TaxEngine/CalculatorTest.php index 719d90835..165d5d517 100755 --- a/core/lib/Thelia/Tests/TaxEngine/CalculatorTest.php +++ b/core/lib/Thelia/Tests/TaxEngine/CalculatorTest.php @@ -136,18 +136,21 @@ class CalculatorTest extends \PHPUnit_Framework_TestCase public function testGetTaxAmountAndGetTaxedPrice() { + /* consecutives taxes */ $taxRulesCollection = new ObjectCollection(); $taxRulesCollection->setModel('\Thelia\Model\Tax'); $tax = new Tax(); $tax->setType('PricePercentTaxType') - ->setRequirements(array('percent' => 10)); + ->setRequirements(array('percent' => 10)) + ->setVirtualColumn('taxRuleCountryPosition', 1); $taxRulesCollection->append($tax); $tax = new Tax(); $tax->setType('PricePercentTaxType') - ->setRequirements(array('percent' => 8)); + ->setRequirements(array('percent' => 8)) + ->setVirtualColumn('taxRuleCountryPosition', 2); $taxRulesCollection->append($tax); @@ -167,5 +170,40 @@ class CalculatorTest extends \PHPUnit_Framework_TestCase */ $this->assertEquals(94, $taxAmount); $this->assertEquals(594, $taxedPrice); + + /* same position taxes */ + $taxRulesCollection = new ObjectCollection(); + $taxRulesCollection->setModel('\Thelia\Model\Tax'); + + $tax = new Tax(); + $tax->setType('PricePercentTaxType') + ->setRequirements(array('percent' => 10)) + ->setVirtualColumn('taxRuleCountryPosition', 1); + + $taxRulesCollection->append($tax); + + $tax = new Tax(); + $tax->setType('PricePercentTaxType') + ->setRequirements(array('percent' => 8)) + ->setVirtualColumn('taxRuleCountryPosition', 1); + + $taxRulesCollection->append($tax); + + $calculator = new Calculator(); + + $rewritingUrlQuery = $this->getProperty('taxRulesCollection'); + $rewritingUrlQuery->setValue($calculator, $taxRulesCollection); + + $taxAmount = $calculator->getTaxAmount(500); + $taxedPrice = $calculator->getTaxedPrice(500); + + /* + * expect : + * tax 1 = 500*0.10 = 50 // amout with tax 1 : 550 + * tax 2 = 500*0.08 = 40 // amout with tax 2 : 590 + * total tax amount = 90 + */ + $this->assertEquals(90, $taxAmount); + $this->assertEquals(590, $taxedPrice); } } From e8ced10dbb68f1c416ee14bf05629c2b48599c8a Mon Sep 17 00:00:00 2001 From: Etienne Roudeix Date: Wed, 11 Sep 2013 20:22:29 +0200 Subject: [PATCH 26/32] fix template --- templates/default_save/product.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/default_save/product.html b/templates/default_save/product.html index cde8b61eb..eec6f770b 100755 --- a/templates/default_save/product.html +++ b/templates/default_save/product.html @@ -68,7 +68,7 @@ Index : {navigate to="index"}
{$ATTRIBUTE_TITLE} = {$ATTRIBUTE_AVAILABILITY_TITLE}
{/loop}
{$WEIGHT} g -
{if $IS_PROMO == 1} {$PROMO_PRICE} {currency attr="symbol"} HT // TAX : {$PROMO_PRICE_TAX} ; {$TAXED_PROMO_PRICE} {currency attr="symbol"} TTC (instead of {$PRICE_HT} // TAX : {$PRICE_TAX} ; {$TAXED_PRICE} {currency attr="symbol"} TTC){else} {$PRICE} {currency attr="symbol"} HT // TAX : {$PRICE_TAX} ; {$TAXED_PRICE} {currency attr="symbol"} TTC{/if} +
{if $IS_PROMO == 1} {$PROMO_PRICE} {currency attr="symbol"} HT // TAX : {$PROMO_PRICE_TAX} ; {$TAXED_PROMO_PRICE} {currency attr="symbol"} TTC (instead of {$PRICE} HT // TAX : {$PRICE_TAX} ; {$TAXED_PRICE} {currency attr="symbol"} TTC){else} {$PRICE} {currency attr="symbol"} HT // TAX : {$PRICE_TAX} ; {$TAXED_PRICE} {currency attr="symbol"} TTC{/if}

Add