From 8be785e9b37ef4e0912243594a5687459f0d2608 Mon Sep 17 00:00:00 2001 From: gmorel Date: Tue, 10 Sep 2013 20:00:43 +0200 Subject: [PATCH] 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'}