diff --git a/.gitignore b/.gitignore index 2af71adba..3063f9a02 100755 --- a/.gitignore +++ b/.gitignore @@ -24,4 +24,5 @@ phpdoc*.log php-cs xhprof/ phpunit.phar -.DS_Store \ No newline at end of file +.DS_Store +phpmyadmin \ No newline at end of file diff --git a/core/lib/Thelia/Action/Attribute.php b/core/lib/Thelia/Action/Attribute.php index a2e956d8e..44c5968a4 100644 --- a/core/lib/Thelia/Action/Attribute.php +++ b/core/lib/Thelia/Action/Attribute.php @@ -41,6 +41,7 @@ use Thelia\Core\Event\CategoryEvent; use Thelia\Core\Event\AttributeEvent; use Thelia\Model\AttributeTemplate; use Thelia\Model\AttributeTemplateQuery; +use Thelia\Model\TemplateQuery; class Attribute extends BaseAction implements EventSubscriberInterface { @@ -137,23 +138,33 @@ class Attribute extends BaseAction implements EventSubscriberInterface } } - public function addToAllTemplates(AttributeEvent $event) + protected function doAddToAllTemplates(AttributeModel $attribute) { - $templates = AttributeTemplateQuery::create()->find(); + $templates = TemplateQuery::create()->find(); foreach($templates as $template) { - $pat = new AttributeTemplate(); - $pat->setTemplate($template->getId()) - ->setAttributeId($event->getAttribute()->getId()) - ->save(); + $attribute_template = new AttributeTemplate(); + + if (null === AttributeTemplateQuery::create()->filterByAttribute($attribute)->filterByTemplate($template)->findOne()) { + $attribute_template + ->setAttribute($attribute) + ->setTemplate($template) + ->save() + ; + } } } + public function addToAllTemplates(AttributeEvent $event) + { + $this->doAddToAllTemplates($event->getAttribute()); + } + public function removeFromAllTemplates(AttributeEvent $event) { // Delete this attribute from all product templates - AttributeTemplateQuery::create()->filterByAttributeId($event->getAttribute()->getId())->delete(); + AttributeTemplateQuery::create()->filterByAttribute($event->getAttribute())->delete(); } /** diff --git a/core/lib/Thelia/Action/Coupon.php b/core/lib/Thelia/Action/Coupon.php index d50f72aa8..036502c68 100755 --- a/core/lib/Thelia/Action/Coupon.php +++ b/core/lib/Thelia/Action/Coupon.php @@ -23,10 +23,16 @@ namespace Thelia\Action; +use Symfony\Component\Config\Definition\Exception\Exception; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Thelia\Constraint\ConstraintFactory; +use Thelia\Core\Event\Coupon\CouponConsumeEvent; use Thelia\Core\Event\Coupon\CouponCreateOrUpdateEvent; use Thelia\Core\Event\TheliaEvents; +use Thelia\Core\HttpFoundation\Request; +use Thelia\Coupon\CouponFactory; +use Thelia\Coupon\CouponManager; +use Thelia\Coupon\Type\CouponInterface; use Thelia\Model\Coupon as CouponModel; /** @@ -45,7 +51,7 @@ class Coupon extends BaseAction implements EventSubscriberInterface /** * Occurring when a Coupon is about to be created * - * @param CouponCreateOrUpdateEvent $event Event creation or update Event + * @param CouponCreateOrUpdateEvent $event Event creation or update Coupon */ public function create(CouponCreateOrUpdateEvent $event) { @@ -57,7 +63,7 @@ class Coupon extends BaseAction implements EventSubscriberInterface /** * Occurring when a Coupon is about to be updated * - * @param CouponCreateOrUpdateEvent $event Event creation or update Event + * @param CouponCreateOrUpdateEvent $event Event creation or update Coupon */ public function update(CouponCreateOrUpdateEvent $event) { @@ -69,7 +75,7 @@ class Coupon extends BaseAction implements EventSubscriberInterface /** * Occurring when a Coupon rule is about to be updated * - * @param CouponCreateOrUpdateEvent $event Event creation or update Event + * @param CouponCreateOrUpdateEvent $event Event creation or update Coupon Rule */ public function updateRule(CouponCreateOrUpdateEvent $event) { @@ -81,11 +87,43 @@ class Coupon extends BaseAction implements EventSubscriberInterface /** * Occurring when a Coupon rule is about to be consumed * - * @param CouponCreateOrUpdateEvent $event Event creation or update Event + * @param CouponConsumeEvent $event Event consuming Coupon */ - public function consume(CouponCreateOrUpdateEvent $event) + public function consume(CouponConsumeEvent $event) { - // @todo implements + $totalDiscount = 0; + + /** @var CouponFactory $couponFactory */ + $couponFactory = $this->container->get('thelia.coupon.factory'); + + /** @var CouponManager $couponManager */ + $couponManager = $this->container->get('thelia.coupon.manager'); + + /** @var CouponInterface $coupon */ + $coupon = $couponFactory->buildCouponFromCode($event->getCode()); + + $isValid = $coupon->isMatching(); + if ($isValid) { + /** @var Request $request */ + $request = $this->container->get('request'); + $consumedCoupons = $request->getSession()->getConsumedCoupons(); + + if (!isset($consumedCoupons) || !$consumedCoupons) { + $consumedCoupons = array(); + } + + // Prevent accumulation of the same Coupon on a Checkout + $consumedCoupons[$event->getCode()] = $event->getCode(); + + $request->getSession()->setConsumedCoupons($consumedCoupons); + + $totalDiscount = $couponManager->getDiscount(); + + // @todo modify Cart total discount + } + + $event->setIsValid($isValid); + $event->setDiscount($totalDiscount); } /** @@ -165,8 +203,6 @@ class Coupon extends BaseAction implements EventSubscriberInterface return array( TheliaEvents::COUPON_CREATE => array("create", 128), TheliaEvents::COUPON_UPDATE => array("update", 128), - 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) ); diff --git a/core/lib/Thelia/Action/Feature.php b/core/lib/Thelia/Action/Feature.php new file mode 100644 index 000000000..a746ce4e2 --- /dev/null +++ b/core/lib/Thelia/Action/Feature.php @@ -0,0 +1,186 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Action; + +use Symfony\Component\EventDispatcher\EventSubscriberInterface; + +use Thelia\Model\FeatureQuery; +use Thelia\Model\Feature as FeatureModel; + +use Thelia\Core\Event\TheliaEvents; + +use Thelia\Core\Event\FeatureUpdateEvent; +use Thelia\Core\Event\FeatureCreateEvent; +use Thelia\Core\Event\FeatureDeleteEvent; +use Thelia\Model\ConfigQuery; +use Thelia\Model\FeatureAv; +use Thelia\Model\FeatureAvQuery; +use Thelia\Core\Event\UpdatePositionEvent; +use Thelia\Core\Event\CategoryEvent; +use Thelia\Core\Event\FeatureEvent; +use Thelia\Model\FeatureTemplate; +use Thelia\Model\FeatureTemplateQuery; +use Thelia\Model\TemplateQuery; + +class Feature extends BaseAction implements EventSubscriberInterface +{ + /** + * Create a new feature entry + * + * @param FeatureCreateEvent $event + */ + public function create(FeatureCreateEvent $event) + { + $feature = new FeatureModel(); + + $feature + ->setDispatcher($this->getDispatcher()) + + ->setLocale($event->getLocale()) + ->setTitle($event->getTitle()) + + ->save() + ; + + $event->setFeature($feature); + + // Add atribute to all product templates if required + if ($event->getAddToAllTemplates() != 0) { + // TODO: add to all product template + } + } + + /** + * Change a product feature + * + * @param FeatureUpdateEvent $event + */ + public function update(FeatureUpdateEvent $event) + { + $search = FeatureQuery::create(); + + if (null !== $feature = FeatureQuery::create()->findPk($event->getFeatureId())) { + + $feature + ->setDispatcher($this->getDispatcher()) + + ->setLocale($event->getLocale()) + ->setTitle($event->getTitle()) + ->setDescription($event->getDescription()) + ->setChapo($event->getChapo()) + ->setPostscriptum($event->getPostscriptum()) + + ->save(); + + $event->setFeature($feature); + } + } + + /** + * Delete a product feature entry + * + * @param FeatureDeleteEvent $event + */ + public function delete(FeatureDeleteEvent $event) + { + + if (null !== ($feature = FeatureQuery::create()->findPk($event->getFeatureId()))) { + + $feature + ->setDispatcher($this->getDispatcher()) + ->delete() + ; + + $event->setFeature($feature); + } + } + + /** + * Changes position, selecting absolute ou relative change. + * + * @param CategoryChangePositionEvent $event + */ + public function updatePosition(UpdatePositionEvent $event) + { + if (null !== $feature = FeatureQuery::create()->findPk($event->getObjectId())) { + + $feature->setDispatcher($this->getDispatcher()); + + $mode = $event->getMode(); + + if ($mode == UpdatePositionEvent::POSITION_ABSOLUTE) + return $feature->changeAbsolutePosition($event->getPosition()); + else if ($mode == UpdatePositionEvent::POSITION_UP) + return $feature->movePositionUp(); + else if ($mode == UpdatePositionEvent::POSITION_DOWN) + return $feature->movePositionDown(); + } + } + + protected function doAddToAllTemplates(FeatureModel $feature) + { + $templates = TemplateQuery::create()->find(); + + foreach($templates as $template) { + + $feature_template = new FeatureTemplate(); + + if (null === FeatureTemplateQuery::create()->filterByFeature($feature)->filterByTemplate($template)->findOne()) { + $feature_template + ->setFeature($feature) + ->setTemplate($template) + ->save() + ; + } + } + } + + public function addToAllTemplates(FeatureEvent $event) + { + $this->doAddToAllTemplates($event->getFeature()); + } + + public function removeFromAllTemplates(FeatureEvent $event) + { + // Delete this feature from all product templates + FeatureTemplateQuery::create()->filterByFeature($event->getFeature())->delete(); + } + + /** + * {@inheritDoc} + */ + public static function getSubscribedEvents() + { + return array( + TheliaEvents::FEATURE_CREATE => array("create", 128), + TheliaEvents::FEATURE_UPDATE => array("update", 128), + TheliaEvents::FEATURE_DELETE => array("delete", 128), + TheliaEvents::FEATURE_UPDATE_POSITION => array("updatePosition", 128), + + TheliaEvents::FEATURE_REMOVE_FROM_ALL_TEMPLATES => array("removeFromAllTemplates", 128), + TheliaEvents::FEATURE_ADD_TO_ALL_TEMPLATES => array("addToAllTemplates", 128), + + ); + } +} \ No newline at end of file diff --git a/core/lib/Thelia/Action/FeatureAv.php b/core/lib/Thelia/Action/FeatureAv.php new file mode 100644 index 000000000..2bd117b4b --- /dev/null +++ b/core/lib/Thelia/Action/FeatureAv.php @@ -0,0 +1,143 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Action; + +use Symfony\Component\EventDispatcher\EventSubscriberInterface; + +use Thelia\Model\FeatureAvQuery; +use Thelia\Model\FeatureAv as FeatureAvModel; + +use Thelia\Core\Event\TheliaEvents; + +use Thelia\Core\Event\FeatureAvUpdateEvent; +use Thelia\Core\Event\FeatureAvCreateEvent; +use Thelia\Core\Event\FeatureAvDeleteEvent; +use Thelia\Model\ConfigQuery; +use Thelia\Core\Event\UpdatePositionEvent; + +class FeatureAv extends BaseAction implements EventSubscriberInterface +{ + /** + * Create a new feature entry + * + * @param FeatureAvCreateEvent $event + */ + public function create(FeatureAvCreateEvent $event) + { + $feature = new FeatureAvModel(); + + $feature + ->setDispatcher($this->getDispatcher()) + + ->setFeatureId($event->getFeatureId()) + ->setLocale($event->getLocale()) + ->setTitle($event->getTitle()) + + ->save() + ; + + $event->setFeatureAv($feature); + } + + /** + * Change a product feature + * + * @param FeatureAvUpdateEvent $event + */ + public function update(FeatureAvUpdateEvent $event) + { + $search = FeatureAvQuery::create(); + + if (null !== $feature = FeatureAvQuery::create()->findPk($event->getFeatureAvId())) { + + $feature + ->setDispatcher($this->getDispatcher()) + + ->setLocale($event->getLocale()) + ->setTitle($event->getTitle()) + ->setDescription($event->getDescription()) + ->setChapo($event->getChapo()) + ->setPostscriptum($event->getPostscriptum()) + + ->save(); + + $event->setFeatureAv($feature); + } + } + + /** + * Delete a product feature entry + * + * @param FeatureAvDeleteEvent $event + */ + public function delete(FeatureAvDeleteEvent $event) + { + + if (null !== ($feature = FeatureAvQuery::create()->findPk($event->getFeatureAvId()))) { + + $feature + ->setDispatcher($this->getDispatcher()) + ->delete() + ; + + $event->setFeatureAv($feature); + } + } + + /** + * Changes position, selecting absolute ou relative change. + * + * @param CategoryChangePositionEvent $event + */ + public function updatePosition(UpdatePositionEvent $event) + { + if (null !== $feature = FeatureAvQuery::create()->findPk($event->getObjectId())) { + + $feature->setDispatcher($this->getDispatcher()); + + $mode = $event->getMode(); + + if ($mode == UpdatePositionEvent::POSITION_ABSOLUTE) + return $feature->changeAbsolutePosition($event->getPosition()); + else if ($mode == UpdatePositionEvent::POSITION_UP) + return $feature->movePositionUp(); + else if ($mode == UpdatePositionEvent::POSITION_DOWN) + return $feature->movePositionDown(); + } + } + + + /** + * {@inheritDoc} + */ + public static function getSubscribedEvents() + { + return array( + TheliaEvents::FEATURE_AV_CREATE => array("create", 128), + TheliaEvents::FEATURE_AV_UPDATE => array("update", 128), + TheliaEvents::FEATURE_AV_DELETE => array("delete", 128), + TheliaEvents::FEATURE_AV_UPDATE_POSITION => array("updatePosition", 128), + ); + } +} \ No newline at end of file diff --git a/core/lib/Thelia/Config/Resources/action.xml b/core/lib/Thelia/Config/Resources/action.xml index f2fa776c3..a586667d1 100755 --- a/core/lib/Thelia/Config/Resources/action.xml +++ b/core/lib/Thelia/Config/Resources/action.xml @@ -67,11 +67,21 @@ + + + + + + + + + + diff --git a/core/lib/Thelia/Config/Resources/config.xml b/core/lib/Thelia/Config/Resources/config.xml index 8098eb9d4..d8211c6cc 100755 --- a/core/lib/Thelia/Config/Resources/config.xml +++ b/core/lib/Thelia/Config/Resources/config.xml @@ -72,8 +72,13 @@
+ + + + + @@ -235,6 +240,8 @@ + + diff --git a/core/lib/Thelia/Config/Resources/routing/admin.xml b/core/lib/Thelia/Config/Resources/routing/admin.xml index 3ed059e7e..839d84756 100755 --- a/core/lib/Thelia/Config/Resources/routing/admin.xml +++ b/core/lib/Thelia/Config/Resources/routing/admin.xml @@ -103,25 +103,27 @@ - + Thelia\Controller\Admin\CouponController::browseAction - + Thelia\Controller\Admin\CouponController::createAction - + Thelia\Controller\Admin\CouponController::updateAction - + Thelia\Controller\Admin\CouponController::readAction - + Thelia\Controller\Admin\CouponController::getRuleInputAction Thelia\Controller\Admin\CouponController::updateRulesAction - + + Thelia\Controller\Admin\CouponController::consumeAction + @@ -302,6 +304,63 @@ + + + + Thelia\Controller\Admin\FeatureController::defaultAction + + + + Thelia\Controller\Admin\FeatureController::createAction + + + + Thelia\Controller\Admin\FeatureController::updateAction + + + + Thelia\Controller\Admin\FeatureController::processUpdateAction + + + + Thelia\Controller\Admin\FeatureController::deleteAction + + + + Thelia\Controller\Admin\FeatureController::updatePositionAction + + + + Thelia\Controller\Admin\FeatureController::removeFromAllTemplates + + + + Thelia\Controller\Admin\FeatureController::addToAllTemplates + + + + + Thelia\Controller\Admin\FeatureAvController::createAction + + + + Thelia\Controller\Admin\FeatureAvController::updateAction + + + + Thelia\Controller\Admin\FeatureAvController::processUpdateAction + + + + Thelia\Controller\Admin\FeatureAvController::deleteAction + + + + Thelia\Controller\Admin\FeatureAvController::updatePositionAction + + + + diff --git a/core/lib/Thelia/Constraint/ConstraintFactory.php b/core/lib/Thelia/Constraint/ConstraintFactory.php index e96509172..e13d1d2aa 100644 --- a/core/lib/Thelia/Constraint/ConstraintFactory.php +++ b/core/lib/Thelia/Constraint/ConstraintFactory.php @@ -25,6 +25,7 @@ namespace Thelia\Constraint; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\Serializer\Encoder\JsonEncoder; +use Thelia\Constraint\Rule\AvailableForEveryoneManager; use Thelia\Constraint\Rule\AvailableForTotalAmountManager; use Thelia\Constraint\Rule\CouponRuleInterface; use Thelia\Constraint\Rule\SerializableRule; @@ -74,11 +75,22 @@ class ConstraintFactory */ public function serializeCouponRuleCollection(CouponRuleCollection $collection) { + if ($collection->isEmpty()) { + /** @var CouponRuleInterface $ruleNoCondition */ + $ruleNoCondition = $this->container->get( + 'thelia.constraint.rule.available_for_everyone' + ); + $collection->add($ruleNoCondition); + } $serializableRules = array(); $rules = $collection->getRules(); if ($rules !== null) { /** @var $rule CouponRuleInterface */ foreach ($rules as $rule) { + // Remove all rule if the "no condition" rule is found +// if ($rule->getServiceId() == 'thelia.constraint.rule.available_for_everyone') { +// return base64_encode(json_encode(array($rule->getSerializableRule()))); +// } $serializableRules[] = $rule->getSerializableRule(); } } diff --git a/core/lib/Thelia/Constraint/ConstraintValidator.php b/core/lib/Thelia/Constraint/ConstraintValidator.php index edacee317..325faed22 100644 --- a/core/lib/Thelia/Constraint/ConstraintValidator.php +++ b/core/lib/Thelia/Constraint/ConstraintValidator.php @@ -52,7 +52,7 @@ class ConstraintValidator * * @return bool */ - public function test(CouponRuleCollection $rules) + public function isMatching(CouponRuleCollection $rules) { $isMatching = true; /** @var CouponRuleInterface $rule */ diff --git a/core/lib/Thelia/Constraint/Rule/AvailableForTotalAmountManager.php b/core/lib/Thelia/Constraint/Rule/AvailableForTotalAmountManager.php index 9f1bf23a0..30bc86ad6 100644 --- a/core/lib/Thelia/Constraint/Rule/AvailableForTotalAmountManager.php +++ b/core/lib/Thelia/Constraint/Rule/AvailableForTotalAmountManager.php @@ -25,7 +25,6 @@ namespace Thelia\Constraint\Rule; use Symfony\Component\Intl\Exception\NotImplementedException; use Symfony\Component\Translation\Translator; -use Thelia\Constraint\ConstraintValidator; use Thelia\Coupon\CouponAdapterInterface; use Thelia\Constraint\Validator\PriceParam; use Thelia\Constraint\Validator\RuleValidator; @@ -168,13 +167,12 @@ class AvailableForTotalAmountManager extends CouponRuleAbstract return false; } - $constrainValidator = new ConstraintValidator(); - $constraint1 =$constrainValidator->variableOpComparison( + $constraint1 = $this->constraintValidator->variableOpComparison( $this->adapter->getCartTotalPrice(), $this->operators[self::INPUT1], $this->values[self::INPUT1] ); - $constraint2 =$constrainValidator->variableOpComparison( + $constraint2 = $this->constraintValidator->variableOpComparison( $this->adapter->getCheckoutCurrency(), $this->operators[self::INPUT2], $this->values[self::INPUT2] diff --git a/core/lib/Thelia/Constraint/Rule/AvailableForXArticlesManager.php b/core/lib/Thelia/Constraint/Rule/AvailableForXArticlesManager.php index 26c7a8aeb..572d39b1d 100644 --- a/core/lib/Thelia/Constraint/Rule/AvailableForXArticlesManager.php +++ b/core/lib/Thelia/Constraint/Rule/AvailableForXArticlesManager.php @@ -126,8 +126,7 @@ class AvailableForXArticlesManager extends CouponRuleAbstract */ public function isMatching() { - $constrainValidator = new ConstraintValidator(); - $constraint1 =$constrainValidator->variableOpComparison( + $constraint1 = $this->constraintValidator->variableOpComparison( $this->adapter->getNbArticlesInCart(), $this->operators[self::INPUT1], $this->values[self::INPUT1] diff --git a/core/lib/Thelia/Constraint/Rule/CouponRuleAbstract.php b/core/lib/Thelia/Constraint/Rule/CouponRuleAbstract.php index 1cab6c48b..942e48d1f 100644 --- a/core/lib/Thelia/Constraint/Rule/CouponRuleAbstract.php +++ b/core/lib/Thelia/Constraint/Rule/CouponRuleAbstract.php @@ -82,6 +82,7 @@ abstract class CouponRuleAbstract implements CouponRuleInterface { $this->adapter = $adapter; $this->translator = $adapter->getTranslator(); + $this->constraintValidator = $adapter->getConstraintValidator(); } // /** diff --git a/core/lib/Thelia/Constraint/Rule/Operators.php b/core/lib/Thelia/Constraint/Rule/Operators.php index 41640810c..2ed5c2909 100644 --- a/core/lib/Thelia/Constraint/Rule/Operators.php +++ b/core/lib/Thelia/Constraint/Rule/Operators.php @@ -133,21 +133,21 @@ abstract class Operators break; case self::INFERIOR_OR_EQUAL: $ret = $translator->trans( - 'inferior or equals to', + 'inferior or equal to', array(), 'constraint' ); break; case self::EQUAL: $ret = $translator->trans( - 'equals to', + 'equal to', array(), 'constraint' ); break; case self::SUPERIOR_OR_EQUAL: $ret = $translator->trans( - 'superior or equals to', + 'superior or equal to', array(), 'constraint' ); diff --git a/core/lib/Thelia/Controller/Admin/CouponController.php b/core/lib/Thelia/Controller/Admin/CouponController.php index cd8521d7a..6803addfd 100755 --- a/core/lib/Thelia/Controller/Admin/CouponController.php +++ b/core/lib/Thelia/Controller/Admin/CouponController.php @@ -30,6 +30,7 @@ use Thelia\Constraint\ConstraintFactoryTest; use Thelia\Constraint\Rule\AvailableForTotalAmount; use Thelia\Constraint\Rule\CouponRuleInterface; use Thelia\Constraint\Validator\PriceParam; +use Thelia\Core\Event\Coupon\CouponConsumeEvent; use Thelia\Core\Event\Coupon\CouponCreateEvent; use Thelia\Core\Event\Coupon\CouponCreateOrUpdateEvent; use Thelia\Core\Event\Coupon\CouponEvent; @@ -39,6 +40,7 @@ use Thelia\Core\Security\Exception\AuthenticationException; use Thelia\Core\Security\Exception\AuthorizationException; use Thelia\Core\Translation\Translator; use Thelia\Coupon\CouponAdapterInterface; +use Thelia\Coupon\CouponFactory; use Thelia\Coupon\CouponManager; use Thelia\Coupon\CouponRuleCollection; use Thelia\Coupon\Type\CouponInterface; @@ -72,7 +74,54 @@ class CouponController extends BaseAdminController { $this->checkAuth('ADMIN', 'admin.coupon.view'); - return $this->render('coupon-list'); + $args['urlReadCoupon'] = $this->getRoute( + 'admin.coupon.read', + array('couponId' => 'couponId'), + Router::ABSOLUTE_URL + ); + + $args['urlEditCoupon'] = $this->getRoute( + 'admin.coupon.update', + array('couponId' => 'couponId'), + Router::ABSOLUTE_URL + ); + + $args['urlCreateCoupon'] = $this->getRoute( + 'admin.coupon.create', + array(), + Router::ABSOLUTE_URL + ); + + return $this->render('coupon-list', $args); + } + + /** + * Manage Coupons read display + * + * @param int $couponId Coupon Id + * + * @return \Symfony\Component\HttpFoundation\Response + */ + public function readAction($couponId) + { + $this->checkAuth('ADMIN', 'admin.coupon.read'); + + // Database request repeated in the loop but cached + $search = CouponQuery::create(); + $coupon = $search->findOneById($couponId); + + if ($coupon === null) { + return $this->pageNotFound(); + } + + $args['couponId'] = $couponId; + $args['urlEditCoupon'] = $this->getRoute( + 'admin.coupon.update', + array('couponId' => $couponId), + Router::ABSOLUTE_URL + ); + + return $this->render('coupon-read', $args); } /** @@ -93,7 +142,7 @@ class CouponController extends BaseAdminController $i18n = new I18n(); /** @var Lang $lang */ - $lang = $this->getSession()->get('lang'); + $lang = $this->getSession()->getLang(); $eventToDispatch = TheliaEvents::COUPON_CREATE; if ($this->getRequest()->isMethod('POST')) { @@ -108,10 +157,12 @@ class CouponController extends BaseAdminController // If no input for expirationDate, now + 2 months $defaultDate = new \DateTime(); $args['defaultDate'] = $defaultDate->modify('+2 month') - ->format($lang->getDateFormat()); + ->format('Y-m-d'); } - $args['formAction'] = 'admin/coupon/create'; + $args['dateFormat'] = $this->getSession()->getLang()->getDateFormat(); + $args['availableCoupons'] = $this->getAvailableCoupons(); + $args['formAction'] = 'admin/coupon/create/'; return $this->render( 'coupon-create', @@ -135,7 +186,7 @@ class CouponController extends BaseAdminController } /** @var Coupon $coupon */ - $coupon = CouponQuery::create()->findOneById($couponId); + $coupon = CouponQuery::create()->findPk($couponId); if (!$coupon) { $this->pageNotFound(); } @@ -148,6 +199,7 @@ class CouponController extends BaseAdminController $lang = $this->getSession()->getLang(); $eventToDispatch = TheliaEvents::COUPON_UPDATE; + // Create if ($this->getRequest()->isMethod('POST')) { $this->validateCreateOrUpdateForm( $i18n, @@ -156,9 +208,9 @@ class CouponController extends BaseAdminController 'updated', 'update' ); - } else { - // Prepare the data that will hydrate the form + } else { // Update + // Prepare the data that will hydrate the form /** @var ConstraintFactory $constraintFactory */ $constraintFactory = $this->container->get('thelia.constraint.factory'); $rules = $constraintFactory->unserializeCouponRuleCollection( @@ -173,7 +225,7 @@ class CouponController extends BaseAdminController 'shortDescription' => $coupon->getShortDescription(), 'description' => $coupon->getDescription(), 'isEnabled' => ($coupon->getIsEnabled() == 1), - 'expirationDate' => $coupon->getExpirationDate($lang->getDateFormat()), + 'expirationDate' => $coupon->getExpirationDate('Y-m-d'), 'isAvailableOnSpecialOffers' => ($coupon->getIsAvailableOnSpecialOffers() == 1), 'isCumulative' => ($coupon->getIsCumulative() == 1), 'isRemovingPostage' => ($coupon->getIsRemovingPostage() == 1), @@ -202,7 +254,7 @@ class CouponController extends BaseAdminController // Pass it to the parser $this->getParserContext()->addForm($changeForm); } - + $args['couponCode'] = $coupon->getCode(); $args['availableCoupons'] = $this->getAvailableCoupons(); $args['availableRules'] = $this->getAvailableRules(); $args['urlAjaxGetRuleInput'] = $this->getRoute( @@ -222,123 +274,6 @@ class CouponController extends BaseAdminController 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 -// -// /** @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 -// ); -// } - - - - /** - * Manage Coupons read display - * - * @param int $couponId Coupon Id - * - * @return \Symfony\Component\HttpFoundation\Response - */ - public function readAction($couponId) - { - $this->checkAuth('ADMIN', 'admin.coupon.read'); - - // Database request repeated in the loop but cached - $search = CouponQuery::create(); - $coupon = $search->findOneById($couponId); - - if ($coupon === null) { - return $this->pageNotFound(); - } - - return $this->render('coupon-read', array('couponId' => $couponId)); - } - /** * Manage Coupons read display * @@ -350,17 +285,7 @@ class CouponController extends BaseAdminController { $this->checkAuth('ADMIN', 'admin.coupon.read'); - if ($this->isDebug()) { - if (!$this->getRequest()->isXmlHttpRequest()) { - $this->redirect( - $this->getRoute( - 'admin', - array(), - Router::ABSOLUTE_URL - ) - ); - } - } + $this->checkXmlHttpRequest(); /** @var ConstraintFactory $constraintFactory */ $constraintFactory = $this->container->get('thelia.constraint.factory'); @@ -391,17 +316,7 @@ class CouponController extends BaseAdminController { $this->checkAuth('ADMIN', 'admin.coupon.read'); - if ($this->isDebug()) { - if (!$this->getRequest()->isXmlHttpRequest()) { - $this->redirect( - $this->getRoute( - 'admin', - array(), - Router::ABSOLUTE_URL - ) - ); - } - } + $this->checkXmlHttpRequest(); $search = CouponQuery::create(); /** @var Coupon $coupon */ @@ -475,6 +390,29 @@ class CouponController extends BaseAdminController ); } + /** + * Test Coupon consuming + * + * @param string $couponCode Coupon code + * + */ + public function consumeAction($couponCode) + { + // @todo remove (event dispatcher testing purpose) + $couponConsumeEvent = new CouponConsumeEvent($couponCode); + $eventToDispatch = TheliaEvents::COUPON_CONSUME; + + // Dispatch Event to the Action + $this->dispatch( + $eventToDispatch, + $couponConsumeEvent + ); + + var_dump('test', $couponConsumeEvent->getCode(), $couponConsumeEvent->getDiscount(), $couponConsumeEvent->getIsValid()); + + exit(); + } + /** * Build a Coupon from its form * @@ -535,7 +473,7 @@ class CouponController extends BaseAdminController /** * Validate the CreateOrUpdate form * - * @param string $i18n Local code (fr_FR) + * @param I18n $i18n Local code (fr_FR) * @param Lang $lang Local variables container * @param string $eventToDispatch Event which will activate actions * @param string $log created|edited @@ -543,7 +481,7 @@ class CouponController extends BaseAdminController * * @return $this */ - protected function validateCreateOrUpdateForm($i18n, $lang, $eventToDispatch, $log, $action) + protected function validateCreateOrUpdateForm(I18n $i18n, Lang $lang, $eventToDispatch, $log, $action) { // Create the form from the request $creationForm = new CouponCreationForm($this->getRequest()); @@ -563,7 +501,7 @@ class CouponController extends BaseAdminController $data['shortDescription'], $data['description'], $data['isEnabled'], - $i18n->getDateTimeFromForm($lang, $data['expirationDate']), + \DateTime::createFromFormat('Y-m-d', $data['expirationDate']), $data['isAvailableOnSpecialOffers'], $data['isCumulative'], $data['isRemovingPostage'], @@ -651,17 +589,17 @@ class CouponController extends BaseAdminController /** @var CouponManager $couponManager */ $couponManager = $this->container->get('thelia.coupon.manager'); $availableCoupons = $couponManager->getAvailableCoupons(); - $cleanedRules = array(); + $cleanedCoupons = array(); /** @var CouponInterface $availableCoupon */ foreach ($availableCoupons as $availableCoupon) { $rule = array(); $rule['serviceId'] = $availableCoupon->getServiceId(); $rule['name'] = $availableCoupon->getName(); $rule['toolTip'] = $availableCoupon->getToolTip(); - $cleanedRules[] = $rule; + $cleanedCoupons[] = $rule; } - return $cleanedRules; + return $cleanedCoupons; } /** diff --git a/core/lib/Thelia/Controller/Admin/FeatureAvController.php b/core/lib/Thelia/Controller/Admin/FeatureAvController.php new file mode 100644 index 000000000..25c7a5495 --- /dev/null +++ b/core/lib/Thelia/Controller/Admin/FeatureAvController.php @@ -0,0 +1,196 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Controller\Admin; + +use Thelia\Core\Event\FeatureAvDeleteEvent; +use Thelia\Core\Event\TheliaEvents; +use Thelia\Core\Event\FeatureAvUpdateEvent; +use Thelia\Core\Event\FeatureAvCreateEvent; +use Thelia\Model\FeatureAvQuery; +use Thelia\Form\FeatureAvModificationForm; +use Thelia\Form\FeatureAvCreationForm; +use Thelia\Core\Event\UpdatePositionEvent; + +/** + * Manages features-av sent by mail + * + * @author Franck Allimant + */ +class FeatureAvController extends AbstractCrudController +{ + public function __construct() + { + parent::__construct( + 'featureav', + 'manual', + 'order', + + 'admin.configuration.features-av.view', + 'admin.configuration.features-av.create', + 'admin.configuration.features-av.update', + 'admin.configuration.features-av.delete', + + TheliaEvents::FEATURE_AV_CREATE, + TheliaEvents::FEATURE_AV_UPDATE, + TheliaEvents::FEATURE_AV_DELETE, + null, // No visibility toggle + TheliaEvents::FEATURE_AV_UPDATE_POSITION + ); + } + + protected function getCreationForm() + { + return new FeatureAvCreationForm($this->getRequest()); + } + + protected function getUpdateForm() + { + return new FeatureAvModificationForm($this->getRequest()); + } + + protected function getCreationEvent($formData) + { + $createEvent = new FeatureAvCreateEvent(); + + $createEvent + ->setFeatureId($formData['feature_id']) + ->setTitle($formData['title']) + ->setLocale($formData["locale"]) + ; + + return $createEvent; + } + + protected function getUpdateEvent($formData) + { + $changeEvent = new FeatureAvUpdateEvent($formData['id']); + + // Create and dispatch the change event + $changeEvent + ->setLocale($formData["locale"]) + ->setTitle($formData['title']) + ->setChapo($formData['chapo']) + ->setDescription($formData['description']) + ->setPostscriptum($formData['postscriptum']) + ; + + return $changeEvent; + } + + protected function createUpdatePositionEvent($positionChangeMode, $positionValue) + { + return new UpdatePositionEvent( + $this->getRequest()->get('featureav_id', null), + $positionChangeMode, + $positionValue + ); + } + + protected function getDeleteEvent() + { + return new FeatureAvDeleteEvent($this->getRequest()->get('featureav_id')); + } + + protected function eventContainsObject($event) + { + return $event->hasFeatureAv(); + } + + protected function hydrateObjectForm($object) + { + $data = array( + 'id' => $object->getId(), + 'locale' => $object->getLocale(), + 'title' => $object->getTitle(), + 'chapo' => $object->getChapo(), + 'description' => $object->getDescription(), + 'postscriptum' => $object->getPostscriptum() + ); + + // Setup the object form + return new FeatureAvModificationForm($this->getRequest(), "form", $data); + } + + protected function getObjectFromEvent($event) + { + return $event->hasFeatureAv() ? $event->getFeatureAv() : null; + } + + protected function getExistingObject() + { + return FeatureAvQuery::create() + ->joinWithI18n($this->getCurrentEditionLocale()) + ->findOneById($this->getRequest()->get('featureav_id')); + } + + protected function getObjectLabel($object) + { + return $object->getTitle(); + } + + protected function getObjectId($object) + { + return $object->getId(); + } + + protected function getViewArguments() + { + return array( + 'feature_id' => $this->getRequest()->get('feature_id'), + 'order' => $this->getCurrentListOrder() + ); + } + + protected function renderListTemplate($currentOrder) + { + // We always return to the feature edition form + return $this->render( + 'feature-edit', + $this->getViewArguments() + ); + } + + protected function renderEditionTemplate() + { + // We always return to the feature edition form + return $this->render('feature-edit', $this->getViewArguments()); + } + + protected function redirectToEditionTemplate() + { + // We always return to the feature edition form + $this->redirectToRoute( + "admin.configuration.features.update", + $this->getViewArguments() + ); + } + + protected function redirectToListTemplate() + { + $this->redirectToRoute( + "admin.configuration.features.update", + $this->getViewArguments() + ); + } +} \ No newline at end of file diff --git a/core/lib/Thelia/Controller/Admin/FeatureController.php b/core/lib/Thelia/Controller/Admin/FeatureController.php new file mode 100644 index 000000000..92cb89d33 --- /dev/null +++ b/core/lib/Thelia/Controller/Admin/FeatureController.php @@ -0,0 +1,289 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Controller\Admin; + +use Thelia\Core\Event\FeatureDeleteEvent; +use Thelia\Core\Event\TheliaEvents; +use Thelia\Core\Event\FeatureUpdateEvent; +use Thelia\Core\Event\FeatureCreateEvent; +use Thelia\Model\FeatureQuery; +use Thelia\Form\FeatureModificationForm; +use Thelia\Form\FeatureCreationForm; +use Thelia\Core\Event\UpdatePositionEvent; +use Thelia\Model\FeatureAv; +use Thelia\Model\FeatureAvQuery; +use Thelia\Core\Event\FeatureAvUpdateEvent; +use Thelia\Core\Event\FeatureEvent; + +/** + * Manages features sent by mail + * + * @author Franck Allimant + */ +class FeatureController extends AbstractCrudController +{ + public function __construct() + { + parent::__construct( + 'feature', + 'manual', + 'order', + + 'admin.configuration.features.view', + 'admin.configuration.features.create', + 'admin.configuration.features.update', + 'admin.configuration.features.delete', + + TheliaEvents::FEATURE_CREATE, + TheliaEvents::FEATURE_UPDATE, + TheliaEvents::FEATURE_DELETE, + null, // No visibility toggle + TheliaEvents::FEATURE_UPDATE_POSITION + ); + } + + protected function getCreationForm() + { + return new FeatureCreationForm($this->getRequest()); + } + + protected function getUpdateForm() + { + return new FeatureModificationForm($this->getRequest()); + } + + protected function getCreationEvent($formData) + { + $createEvent = new FeatureCreateEvent(); + + $createEvent + ->setTitle($formData['title']) + ->setLocale($formData["locale"]) + ->setAddToAllTemplates($formData['add_to_all']) + ; + + return $createEvent; + } + + protected function getUpdateEvent($formData) + { + $changeEvent = new FeatureUpdateEvent($formData['id']); + + // Create and dispatch the change event + $changeEvent + ->setLocale($formData["locale"]) + ->setTitle($formData['title']) + ->setChapo($formData['chapo']) + ->setDescription($formData['description']) + ->setPostscriptum($formData['postscriptum']) + ; + + return $changeEvent; + } + + /** + * Process the features values (fix it in future version to integrate it in the feature form as a collection) + * + * @see \Thelia\Controller\Admin\AbstractCrudController::performAdditionalUpdateAction() + */ + protected function performAdditionalUpdateAction($updateEvent) + { + $attr_values = $this->getRequest()->get('feature_values', null); + + if ($attr_values !== null) { + + foreach($attr_values as $id => $value) { + + $event = new FeatureAvUpdateEvent($id); + + $event->setTitle($value); + $event->setLocale($this->getCurrentEditionLocale()); + + $this->dispatch(TheliaEvents::FEATURE_AV_UPDATE, $event); + } + } + + return null; + } + + protected function createUpdatePositionEvent($positionChangeMode, $positionValue) + { + return new UpdatePositionEvent( + $this->getRequest()->get('feature_id', null), + $positionChangeMode, + $positionValue + ); + } + + protected function getDeleteEvent() + { + return new FeatureDeleteEvent($this->getRequest()->get('feature_id')); + } + + protected function eventContainsObject($event) + { + return $event->hasFeature(); + } + + protected function hydrateObjectForm($object) + { + + $data = array( + 'id' => $object->getId(), + 'locale' => $object->getLocale(), + 'title' => $object->getTitle(), + 'chapo' => $object->getChapo(), + 'description' => $object->getDescription(), + 'postscriptum' => $object->getPostscriptum() + ); + + // Setup features values + /* + * FIXME : doesn't work. "We get a This form should not contain extra fields." error + $attr_av_list = FeatureAvQuery::create() + ->joinWithI18n($this->getCurrentEditionLocale()) + ->filterByFeatureId($object->getId()) + ->find(); + + $attr_array = array(); + + foreach($attr_av_list as $attr_av) { + $attr_array[$attr_av->getId()] = $attr_av->getTitle(); + } + + $data['feature_values'] = $attr_array; + */ + + // Setup the object form + return new FeatureModificationForm($this->getRequest(), "form", $data); + } + + protected function getObjectFromEvent($event) + { + return $event->hasFeature() ? $event->getFeature() : null; + } + + protected function getExistingObject() + { + return FeatureQuery::create() + ->joinWithI18n($this->getCurrentEditionLocale()) + ->findOneById($this->getRequest()->get('feature_id')); + } + + protected function getObjectLabel($object) + { + return $object->getTitle(); + } + + protected function getObjectId($object) + { + return $object->getId(); + } + + protected function renderListTemplate($currentOrder) + { + return $this->render('features', array('order' => $currentOrder)); + } + + protected function renderEditionTemplate() + { + return $this->render( + 'feature-edit', + array( + 'feature_id' => $this->getRequest()->get('feature_id'), + 'featureav_order' => $this->getFeatureAvListOrder() + ) + ); + } + + protected function redirectToEditionTemplate() + { + $this->redirectToRoute( + "admin.configuration.features.update", + array( + 'feature_id' => $this->getRequest()->get('feature_id'), + 'featureav_order' => $this->getFeatureAvListOrder() + ) + ); + } + + protected function redirectToListTemplate() + { + $this->redirectToRoute('admin.configuration.features.default'); + } + + /** + * Get the Feature value list order. + * + * @return string the current list order + */ + protected function getFeatureAvListOrder() + { + return $this->getListOrderFromSession( + 'featureav', + 'featureav_order', + 'manual' + ); + } + + /** + * Add or Remove from all product templates + */ + protected function addRemoveFromAllTemplates($eventType) + { + // Check current user authorization + if (null !== $response = $this->checkAuth("admin.configuration.features.update")) return $response; + + try { + if (null !== $object = $this->getExistingObject()) { + + $event = new FeatureEvent($object); + + $this->dispatch($eventType, $event); + } + } + catch (\Exception $ex) { + // Any error + return $this->errorPage($ex); + } + + $this->redirectToListTemplate(); + } + + /** + * Remove from all product templates + */ + public function removeFromAllTemplates() + { + return $this->addRemoveFromAllTemplates(TheliaEvents::FEATURE_REMOVE_FROM_ALL_TEMPLATES); + } + + /** + * Add to all product templates + */ + public function addToAllTemplates() + { + return $this->addRemoveFromAllTemplates(TheliaEvents::FEATURE_ADD_TO_ALL_TEMPLATES); + } +} \ No newline at end of file diff --git a/core/lib/Thelia/Controller/BaseController.php b/core/lib/Thelia/Controller/BaseController.php index bd1e68422..19e62a400 100755 --- a/core/lib/Thelia/Controller/BaseController.php +++ b/core/lib/Thelia/Controller/BaseController.php @@ -127,7 +127,7 @@ class BaseController extends ContainerAware /** * Returns the session from the current request * - * @return \Symfony\Component\HttpFoundation\Session\SessionInterface + * @return \Thelia\Core\HttpFoundation\Session\Session */ protected function getSession() { diff --git a/core/lib/Thelia/Core/Event/Coupon/CouponDisableEvent.php b/core/lib/Thelia/Core/Event/Coupon/CouponConsumeEvent.php similarity index 54% rename from core/lib/Thelia/Core/Event/Coupon/CouponDisableEvent.php rename to core/lib/Thelia/Core/Event/Coupon/CouponConsumeEvent.php index db8e14243..df5cef7a9 100644 --- a/core/lib/Thelia/Core/Event/Coupon/CouponDisableEvent.php +++ b/core/lib/Thelia/Core/Event/Coupon/CouponConsumeEvent.php @@ -22,6 +22,8 @@ /**********************************************************************************/ namespace Thelia\Core\Event\Coupon; +use Thelia\Core\Event\ActionEvent; +use Thelia\Coupon\CouponRuleCollection; use Thelia\Model\Coupon; /** @@ -29,75 +31,112 @@ use Thelia\Model\Coupon; * Date: 8/29/13 * Time: 3:45 PM * - * Occurring when a Coupon is disabled + * Occurring when a Coupon is consumed * * @package Coupon * @author Guillaume MOREL * */ -class CouponDisableEvent extends ActionEvent +class CouponConsumeEvent extends ActionEvent { - /** @var int Coupon id */ - protected $couponId; + /** @var string Coupon code */ + protected $code = null; - /** @var Coupon Coupon being disabled */ - protected $disabledCoupon; + /** @var float Total discount given by this coupon */ + protected $discount = 0; + + /** @var bool If Coupon is valid or if Customer meets coupon conditions */ + protected $isValid = null; /** * Constructor * - * @param int $id Coupon Id + * @param string $code Coupon code + * @param float $discount Total discount given by this coupon + * @param bool $isValid If Coupon is valid or + * if Customer meets coupon conditions */ - public function __construct($id) + function __construct($code, $discount = null, $isValid = null) { - $this->id = $id; + $this->code = $code; + $this->discount = $discount; + $this->isValid = $isValid; } /** - * Get Coupon id + * Set Coupon code * - * @return int - */ - public function getId() - { - return $this->id; - } - - /** - * Set Coupon id - * - * @param int $id Coupon id + * @param string $code Coupon code * * @return $this */ - public function setId($id) + public function setCode($code) { - $this->id = $id; + $this->code = $code; return $this; } /** - * Get Coupon being disabled + * Get Coupon code * - * @return Coupon + * @return string */ - public function getDisabledCoupon() + public function getCode() { - return $this->disabledCoupon; + return $this->code; } /** - * Set Coupon to be disabled + * Set total discount given by this coupon * - * @param Coupon $disabledCoupon Coupon to disable + * @param float $discount Total discount given by this coupon * * @return $this */ - public function setDisabledCoupon(Coupon $disabledCoupon) + public function setDiscount($discount) { - $this->disabledCoupon = $disabledCoupon; + $this->discount = $discount; return $this; } + + /** + * Get total discount given by this coupon + * + * @return float + */ + public function getDiscount() + { + return $this->discount; + } + + /** + * Set if Coupon is valid or if Customer meets coupon conditions + * + * @param boolean $isValid if Coupon is valid or + * if Customer meets coupon conditions + * + * @return $this + */ + public function setIsValid($isValid) + { + $this->isValid = $isValid; + + return $this; + } + + /** + * Get if Coupon is valid or if Customer meets coupon conditions + * + * @return boolean + */ + public function getIsValid() + { + return $this->isValid; + } + + + + } diff --git a/core/lib/Thelia/Core/Event/Coupon/CouponEnableEvent.php b/core/lib/Thelia/Core/Event/Coupon/CouponEnableEvent.php deleted file mode 100644 index ab06953e5..000000000 --- a/core/lib/Thelia/Core/Event/Coupon/CouponEnableEvent.php +++ /dev/null @@ -1,103 +0,0 @@ -. */ -/* */ -/**********************************************************************************/ - -namespace Thelia\Core\Event\Coupon; -use Thelia\Model\Coupon; - -/** - * Created by JetBrains PhpStorm. - * Date: 8/29/13 - * Time: 3:45 PM - * - * Occurring when a Coupon is enabled - * - * @package Coupon - * @author Guillaume MOREL - * - */ -class CouponEnableEvent extends ActionEvent -{ - /** @var int Coupon id */ - protected $couponId; - - /** @var Coupon Coupon being enabled */ - protected $enabledCoupon; - - /** - * Constructor - * - * @param int $id Coupon Id - */ - public function __construct($id) - { - $this->id = $id; - } - - /** - * Get Coupon id - * - * @return int - */ - public function getId() - { - return $this->id; - } - - /** - * Set Coupon id - * - * @param int $id Coupon id - * - * @return $this - */ - public function setId($id) - { - $this->id = $id; - - return $this; - } - - /** - * Get Coupon being enabled - * - * @return Coupon - */ - public function getEnabledCoupon() - { - return $this->enabledCoupon; - } - - /** - * Set Coupon to be enabled - * - * @param Coupon $enabledCoupon Coupon to enabled - * - * @return $this - */ - public function setEnabledCoupon(Coupon $enabledCoupon) - { - $this->enabledCoupon = $enabledCoupon; - - return $this; - } -} diff --git a/core/lib/Thelia/Core/Event/FeatureAvCreateEvent.php b/core/lib/Thelia/Core/Event/FeatureAvCreateEvent.php new file mode 100644 index 000000000..2c8fb228e --- /dev/null +++ b/core/lib/Thelia/Core/Event/FeatureAvCreateEvent.php @@ -0,0 +1,68 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Core\Event; + +class FeatureAvCreateEvent extends FeatureAvEvent +{ + protected $title; + protected $locale; + protected $feature_id; + + public function getLocale() + { + return $this->locale; + } + + public function setLocale($locale) + { + $this->locale = $locale; + + return $this; + } + + public function getTitle() + { + return $this->title; + } + + public function setTitle($title) + { + $this->title = $title; + + return $this; + } + + public function getFeatureId() + { + return $this->feature_id; + } + + public function setFeatureId($feature_id) + { + $this->feature_id = $feature_id; + + return $this; + } + +} diff --git a/core/lib/Thelia/Core/Event/FeatureAvDeleteEvent.php b/core/lib/Thelia/Core/Event/FeatureAvDeleteEvent.php new file mode 100644 index 000000000..aa0a3c729 --- /dev/null +++ b/core/lib/Thelia/Core/Event/FeatureAvDeleteEvent.php @@ -0,0 +1,46 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Core\Event; + +class FeatureAvDeleteEvent extends FeatureAvEvent +{ + protected $featureAv_id; + + public function __construct($featureAv_id) + { + $this->setFeatureAvId($featureAv_id); + } + + public function getFeatureAvId() + { + return $this->featureAv_id; + } + + public function setFeatureAvId($featureAv_id) + { + $this->featureAv_id = $featureAv_id; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/FeatureAvEvent.php b/core/lib/Thelia/Core/Event/FeatureAvEvent.php new file mode 100644 index 000000000..225acaf11 --- /dev/null +++ b/core/lib/Thelia/Core/Event/FeatureAvEvent.php @@ -0,0 +1,52 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Core\Event; +use Thelia\Model\FeatureAv; + +class FeatureAvEvent extends ActionEvent +{ + protected $featureAv = null; + + public function __construct(FeatureAv $featureAv = null) + { + $this->featureAv = $featureAv; + } + + public function hasFeatureAv() + { + return ! is_null($this->featureAv); + } + + public function getFeatureAv() + { + return $this->featureAv; + } + + public function setFeatureAv($featureAv) + { + $this->featureAv = $featureAv; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/FeatureAvUpdateEvent.php b/core/lib/Thelia/Core/Event/FeatureAvUpdateEvent.php new file mode 100644 index 000000000..5db9604c2 --- /dev/null +++ b/core/lib/Thelia/Core/Event/FeatureAvUpdateEvent.php @@ -0,0 +1,86 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Core\Event; + +class FeatureAvUpdateEvent extends FeatureAvCreateEvent +{ + protected $featureAv_id; + + protected $description; + protected $chapo; + protected $postscriptum; + + public function __construct($featureAv_id) + { + $this->setFeatureAvId($featureAv_id); + } + + public function getFeatureAvId() + { + return $this->featureAv_id; + } + + public function setFeatureAvId($featureAv_id) + { + $this->featureAv_id = $featureAv_id; + + return $this; + } + + public function getDescription() + { + return $this->description; + } + + public function setDescription($description) + { + $this->description = $description; + + return $this; + } + + public function getChapo() + { + return $this->chapo; + } + + public function setChapo($chapo) + { + $this->chapo = $chapo; + + return $this; + } + + public function getPostscriptum() + { + return $this->postscriptum; + } + + public function setPostscriptum($postscriptum) + { + $this->postscriptum = $postscriptum; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/FeatureCreateEvent.php b/core/lib/Thelia/Core/Event/FeatureCreateEvent.php new file mode 100644 index 000000000..574433084 --- /dev/null +++ b/core/lib/Thelia/Core/Event/FeatureCreateEvent.php @@ -0,0 +1,68 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Core\Event; + +class FeatureCreateEvent extends FeatureEvent +{ + protected $title; + protected $locale; + protected $add_to_all_templates; + + public function getLocale() + { + return $this->locale; + } + + public function setLocale($locale) + { + $this->locale = $locale; + + return $this; + } + + public function getTitle() + { + return $this->title; + } + + public function setTitle($title) + { + $this->title = $title; + + return $this; + } + + public function getAddToAllTemplates() + { + return $this->add_to_all_templates; + } + + public function setAddToAllTemplates($add_to_all_templates) + { + $this->add_to_all_templates = $add_to_all_templates; + + return $this; + } + +} diff --git a/core/lib/Thelia/Core/Event/FeatureDeleteEvent.php b/core/lib/Thelia/Core/Event/FeatureDeleteEvent.php new file mode 100644 index 000000000..1eca57982 --- /dev/null +++ b/core/lib/Thelia/Core/Event/FeatureDeleteEvent.php @@ -0,0 +1,46 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Core\Event; + +class FeatureDeleteEvent extends FeatureEvent +{ + protected $feature_id; + + public function __construct($feature_id) + { + $this->setFeatureId($feature_id); + } + + public function getFeatureId() + { + return $this->feature_id; + } + + public function setFeatureId($feature_id) + { + $this->feature_id = $feature_id; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/FeatureEvent.php b/core/lib/Thelia/Core/Event/FeatureEvent.php new file mode 100644 index 000000000..f1510ac63 --- /dev/null +++ b/core/lib/Thelia/Core/Event/FeatureEvent.php @@ -0,0 +1,52 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Core\Event; +use Thelia\Model\Feature; + +class FeatureEvent extends ActionEvent +{ + protected $feature = null; + + public function __construct(Feature $feature = null) + { + $this->feature = $feature; + } + + public function hasFeature() + { + return ! is_null($this->feature); + } + + public function getFeature() + { + return $this->feature; + } + + public function setFeature($feature) + { + $this->feature = $feature; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/FeatureUpdateEvent.php b/core/lib/Thelia/Core/Event/FeatureUpdateEvent.php new file mode 100644 index 000000000..6bee33ebb --- /dev/null +++ b/core/lib/Thelia/Core/Event/FeatureUpdateEvent.php @@ -0,0 +1,86 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Core\Event; + +class FeatureUpdateEvent extends FeatureCreateEvent +{ + protected $feature_id; + + protected $description; + protected $chapo; + protected $postscriptum; + + public function __construct($feature_id) + { + $this->setFeatureId($feature_id); + } + + public function getFeatureId() + { + return $this->feature_id; + } + + public function setFeatureId($feature_id) + { + $this->feature_id = $feature_id; + + return $this; + } + + public function getDescription() + { + return $this->description; + } + + public function setDescription($description) + { + $this->description = $description; + + return $this; + } + + public function getChapo() + { + return $this->chapo; + } + + public function setChapo($chapo) + { + $this->chapo = $chapo; + + return $this; + } + + public function getPostscriptum() + { + return $this->postscriptum; + } + + public function setPostscriptum($postscriptum) + { + $this->postscriptum = $postscriptum; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/TheliaEvents.php b/core/lib/Thelia/Core/Event/TheliaEvents.php index de8ffa648..6708449b5 100755 --- a/core/lib/Thelia/Core/Event/TheliaEvents.php +++ b/core/lib/Thelia/Core/Event/TheliaEvents.php @@ -258,36 +258,6 @@ final class TheliaEvents */ const AFTER_UPDATE_COUPON = "action.after_update_coupon"; - /** - * Sent when disabling a Coupon - */ - const COUPON_DISABLE = "action.disable_coupon"; - - /** - * Sent just before a successful disable of a new Coupon in the database. - */ - const BEFORE_DISABLE_COUPON = "action.before_disable_coupon"; - - /** - * Sent just after a successful disable of a new Coupon in the database. - */ - const AFTER_DISABLE_COUPON = "action.after_disable_coupon"; - - /** - * Sent when enabling a Coupon - */ - const COUPON_ENABLE = "action.enable_coupon"; - - /** - * Sent just before a successful enable of a new Coupon in the database. - */ - const BEFORE_ENABLE_COUPON = "action.before_enable_coupon"; - - /** - * Sent just after a successful enable of a new Coupon in the database. - */ - const AFTER_ENABLE_COUPON = "action.after_enable_coupon"; - /** * Sent when attempting to use a Coupon */ @@ -401,6 +371,25 @@ final class TheliaEvents const BEFORE_DELETEATTRIBUTE = "action.before_deleteAttribute"; const AFTER_DELETEATTRIBUTE = "action.after_deleteAttribute"; + // -- Features management --------------------------------------------- + + const FEATURE_CREATE = "action.createFeature"; + const FEATURE_UPDATE = "action.updateFeature"; + const FEATURE_DELETE = "action.deleteFeature"; + const FEATURE_UPDATE_POSITION = "action.updateFeaturePosition"; + + const FEATURE_REMOVE_FROM_ALL_TEMPLATES = "action.addFeatureToAllTemplate"; + const FEATURE_ADD_TO_ALL_TEMPLATES = "action.removeFeatureFromAllTemplate"; + + const BEFORE_CREATEFEATURE = "action.before_createFeature"; + const AFTER_CREATEFEATURE = "action.after_createFeature"; + + const BEFORE_UPDATEFEATURE = "action.before_updateFeature"; + const AFTER_UPDATEFEATURE = "action.after_updateFeature"; + + const BEFORE_DELETEFEATURE = "action.before_deleteFeature"; + const AFTER_DELETEFEATURE = "action.after_deleteFeature"; + // -- Attributes values management ---------------------------------------- const ATTRIBUTE_AV_CREATE = "action.createAttributeAv"; @@ -416,4 +405,22 @@ final class TheliaEvents const BEFORE_DELETEATTRIBUTE_AV = "action.before_deleteAttributeAv"; const AFTER_DELETEATTRIBUTE_AV = "action.after_deleteAttributeAv"; + + + // -- Features values management ---------------------------------------- + + const FEATURE_AV_CREATE = "action.createFeatureAv"; + const FEATURE_AV_UPDATE = "action.updateFeatureAv"; + const FEATURE_AV_DELETE = "action.deleteFeatureAv"; + const FEATURE_AV_UPDATE_POSITION = "action.updateFeatureAvPosition"; + + const BEFORE_CREATEFEATURE_AV = "action.before_createFeatureAv"; + const AFTER_CREATEFEATURE_AV = "action.after_createFeatureAv"; + + const BEFORE_UPDATEFEATURE_AV = "action.before_updateFeatureAv"; + const AFTER_UPDATEFEATURE_AV = "action.after_updateFeatureAv"; + + const BEFORE_DELETEFEATURE_AV = "action.before_deleteFeatureAv"; + const AFTER_DELETEFEATURE_AV = "action.after_deleteFeatureAv"; + } diff --git a/core/lib/Thelia/Core/HttpFoundation/Request.php b/core/lib/Thelia/Core/HttpFoundation/Request.php index e86ce8b65..8e77ad865 100755 --- a/core/lib/Thelia/Core/HttpFoundation/Request.php +++ b/core/lib/Thelia/Core/HttpFoundation/Request.php @@ -55,4 +55,15 @@ class Request extends BaseRequest return $uri . $additionalQs; } + + /** + * Gets the Session. + * + * @return \Thelia\Core\HttpFoundation\Session\Session The session + * @api + */ + public function getSession() + { + return parent::getSession(); + } } diff --git a/core/lib/Thelia/Core/HttpFoundation/Session/Session.php b/core/lib/Thelia/Core/HttpFoundation/Session/Session.php index f2eaadc4d..bce8e712a 100755 --- a/core/lib/Thelia/Core/HttpFoundation/Session/Session.php +++ b/core/lib/Thelia/Core/HttpFoundation/Session/Session.php @@ -220,4 +220,29 @@ class Session extends BaseSession { return $this->get("thelia.delivery_id"); } + + + /** + * Set consumed coupons by the Customer + * + * @param array $couponsCode An array of Coupon code + * + * @return $this + */ + public function setConsumedCoupons(array $couponsCode) + { + $this->set('thelia.consumed_coupons', $couponsCode); + + return $this; + } + + /** + * Get Customer consumed coupons + * + * @return array $couponsCode An array of Coupon code + */ + public function getConsumedCoupons() + { + return $this->get('thelia.consumed_coupons'); + } } diff --git a/core/lib/Thelia/Core/Template/Loop/Coupon.php b/core/lib/Thelia/Core/Template/Loop/Coupon.php index 2fb49e8b9..4e8ca3e71 100755 --- a/core/lib/Thelia/Core/Template/Loop/Coupon.php +++ b/core/lib/Thelia/Core/Template/Loop/Coupon.php @@ -24,6 +24,7 @@ namespace Thelia\Core\Template\Loop; use Propel\Runtime\ActiveQuery\Criteria; +use Propel\Runtime\Util\PropelModelPager; use Thelia\Constraint\ConstraintFactory; use Thelia\Constraint\Rule\CouponRuleInterface; use Thelia\Core\HttpFoundation\Request; @@ -34,9 +35,11 @@ use Thelia\Core\Template\Element\LoopResultRow; use Thelia\Core\Template\Loop\Argument\ArgumentCollection; use Thelia\Core\Template\Loop\Argument\Argument; +use Thelia\Coupon\Type\CouponInterface; use Thelia\Model\CouponQuery; use Thelia\Model\Coupon as MCoupon; use Thelia\Type; +use Thelia\Type\BooleanOrBothType; /** * Created by JetBrains PhpStorm. @@ -52,17 +55,22 @@ use Thelia\Type; class Coupon extends BaseI18nLoop { /** + * Define all args used in your loop + * * @return ArgumentCollection */ protected function getArgDefinitions() { return new ArgumentCollection( - Argument::createIntListTypeArgument('id') + Argument::createIntListTypeArgument('id'), + Argument::createBooleanOrBothTypeArgument('is_enabled', 1) ); } /** - * @param $pagination + * Execute Loop + * + * @param PropelModelPager $pagination * * @return \Thelia\Core\Template\Element\LoopResult */ @@ -74,11 +82,16 @@ class Coupon extends BaseI18nLoop $locale = $this->configureI18nProcessing($search, array('TITLE', 'DESCRIPTION', 'SHORT_DESCRIPTION')); $id = $this->getId(); + $isEnabled = $this->getIsEnabled(); if (null !== $id) { $search->filterById($id, Criteria::IN); } + if ($isEnabled != BooleanOrBothType::ANY) { + $search->filterByIsEnabled($isEnabled ? 1 : 0); + } + // Perform search $coupons = $this->search($search, $pagination); @@ -98,9 +111,30 @@ class Coupon extends BaseI18nLoop $coupon->getSerializedRules() ); + /** @var CouponInterface $couponManager */ + $couponManager = $this->container->get($coupon->getType()); + $couponManager->set( + $this->container->get('thelia.adapter'), + $coupon->getCode(), + $coupon->getTitle(), + $coupon->getShortDescription(), + $coupon->getDescription(), + $coupon->getAmount(), + $coupon->getIsCumulative(), + $coupon->getIsRemovingPostage(), + $coupon->getIsAvailableOnSpecialOffers(), + $coupon->getIsEnabled(), + $coupon->getMaxUsage(), + $coupon->getExpirationDate() + ); + + $now = time(); + $datediff = $coupon->getExpirationDate()->getTimestamp() - $now; + $daysLeftBeforeExpiration = floor($datediff/(60*60*24)); + $cleanedRules = array(); /** @var CouponRuleInterface $rule */ - foreach ($rules->getRules() as $key => $rule) { + foreach ($rules->getRules() as $rule) { $cleanedRules[] = $rule->getToolTip(); } $loopResultRow->set("ID", $coupon->getId()) @@ -114,9 +148,13 @@ class Coupon extends BaseI18nLoop ->set("USAGE_LEFT", $coupon->getMaxUsage()) ->set("IS_CUMULATIVE", $coupon->getIsCumulative()) ->set("IS_REMOVING_POSTAGE", $coupon->getIsRemovingPostage()) + ->set("IS_AVAILABLE_ON_SPECIAL_OFFERS", $coupon->getIsAvailableOnSpecialOffers()) ->set("IS_ENABLED", $coupon->getIsEnabled()) ->set("AMOUNT", $coupon->getAmount()) - ->set("APPLICATION_CONDITIONS", $cleanedRules); + ->set("APPLICATION_CONDITIONS", $cleanedRules) + ->set("TOOLTIP", $couponManager->getToolTip()) + ->set("DAY_LEFT_BEFORE_EXPIRATION", $daysLeftBeforeExpiration) + ->set("SERVICE_ID", $couponManager->getServiceId()); $loopResult->addRow($loopResultRow); } diff --git a/core/lib/Thelia/Coupon/CouponAdapterInterface.php b/core/lib/Thelia/Coupon/CouponAdapterInterface.php index 134d061be..b2c168186 100644 --- a/core/lib/Thelia/Coupon/CouponAdapterInterface.php +++ b/core/lib/Thelia/Coupon/CouponAdapterInterface.php @@ -155,4 +155,18 @@ interface CouponAdapterInterface */ public function getMainCurrency(); + /** + * Return request + * + * @return Request + */ + public function getRequest(); + + /** + * Return Constraint Validator + * + * @return ConstraintValidator + */ + public function getConstraintValidator(); + } \ No newline at end of file diff --git a/core/lib/Thelia/Coupon/CouponBaseAdapter.php b/core/lib/Thelia/Coupon/CouponBaseAdapter.php index 3e77a56be..f9fae8651 100644 --- a/core/lib/Thelia/Coupon/CouponBaseAdapter.php +++ b/core/lib/Thelia/Coupon/CouponBaseAdapter.php @@ -27,9 +27,14 @@ use Symfony\Component\DependencyInjection\Container; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\Translation\Translator; use Symfony\Component\Translation\TranslatorInterface; +use Thelia\Constraint\ConstraintValidator; +use Thelia\Core\HttpFoundation\Request; +use Thelia\Core\Security\SecurityContext; use Thelia\Coupon\Type\CouponInterface; use Thelia\Model\Coupon; use Thelia\Model\CouponQuery; +use Thelia\Cart\CartTrait; +use Thelia\Model\Currency; /** * Created by JetBrains PhpStorm. @@ -43,6 +48,10 @@ use Thelia\Model\CouponQuery; */ class CouponBaseAdapter implements CouponAdapterInterface { + use CartTrait { + CartTrait::getCart as getCartFromTrait; + } + /** @var ContainerInterface Service Container */ protected $container = null; @@ -66,7 +75,7 @@ class CouponBaseAdapter implements CouponAdapterInterface */ public function getCart() { - // TODO: Implement getCart() method. + return $this->getCartFromTrait($this->getRequest()); } /** @@ -86,7 +95,7 @@ class CouponBaseAdapter implements CouponAdapterInterface */ public function getCustomer() { - // TODO: Implement getCustomer() method. + return $this->container->get('thelia.securityContext')->getCustomerUser(); } /** @@ -122,11 +131,11 @@ class CouponBaseAdapter implements CouponAdapterInterface /** * Return the Checkout currency EUR|USD * - * @return string + * @return Currency */ public function getCheckoutCurrency() { - // TODO: Implement getCheckoutCurrency() method. + $this->getRequest()->getSession()->getCurrency(); } @@ -147,9 +156,14 @@ class CouponBaseAdapter implements CouponAdapterInterface */ public function getCurrentCoupons() { + // @todo implement +// $consumedCoupons = $this->getRequest()->getSession()->getConsumedCoupons(); + // @todo convert coupon code to coupon Interface + + $couponFactory = $this->container->get('thelia.coupon.factory'); - // @todo Get from Session + // @todo get from cart $couponCodes = array('XMAS', 'SPRINGBREAK'); $coupons = array(); @@ -208,7 +222,7 @@ class CouponBaseAdapter implements CouponAdapterInterface */ public function getContainer() { - // TODO: Implement getContainer() method. + return $this->container; } /** @@ -232,4 +246,24 @@ class CouponBaseAdapter implements CouponAdapterInterface { // TODO: Implement getMainCurrency() method. } + + /** + * Return request + * + * @return Request + */ + public function getRequest() + { + return $this->container->get('request'); + } + + /** + * Return Constraint Validator + * + * @return ConstraintValidator + */ + public function getConstraintValidator() + { + return $this->container->get('thelia.constraint.validator'); + } } diff --git a/core/lib/Thelia/Coupon/CouponManager.php b/core/lib/Thelia/Coupon/CouponManager.php index 93cdd21fe..d8575c3e6 100644 --- a/core/lib/Thelia/Coupon/CouponManager.php +++ b/core/lib/Thelia/Coupon/CouponManager.php @@ -183,6 +183,7 @@ class CouponManager $discount = 0.00; /** @var CouponInterface $coupon */ foreach ($coupons as $coupon) { + // @todo modify Cart with discount for each cart item $discount += $coupon->getDiscount($this->adapter); } diff --git a/core/lib/Thelia/Coupon/Type/CouponAbstract.php b/core/lib/Thelia/Coupon/Type/CouponAbstract.php index 647635024..45e1427f1 100644 --- a/core/lib/Thelia/Coupon/Type/CouponAbstract.php +++ b/core/lib/Thelia/Coupon/Type/CouponAbstract.php @@ -26,6 +26,7 @@ namespace Thelia\Coupon\Type; use Symfony\Component\Intl\Exception\NotImplementedException; use Thelia\Constraint\ConstraintManager; use Thelia\Constraint\ConstraintValidator; +use Thelia\Core\Translation\Translator; use Thelia\Coupon\CouponAdapterInterface; use Thelia\Coupon\CouponRuleCollection; use Thelia\Coupon\RuleOrganizerInterface; @@ -44,9 +45,6 @@ use Thelia\Exception\InvalidRuleException; */ abstract class CouponAbstract implements CouponInterface { - /** @var string Service Id */ - protected $serviceId = null; - /** @var CouponAdapterInterface Provide necessary value from Thelia */ protected $adapter = null; @@ -62,9 +60,19 @@ abstract class CouponAbstract implements CouponInterface /** @var ConstraintValidator Constraint validator */ protected $constraintValidator = null; + + + /** @var string Service Id */ + protected $serviceId = null; + + /** @var float Amount that will be removed from the Checkout (Coupon Effect) */ + protected $amount = 0; + /** @var string Coupon code (ex: XMAS) */ protected $code = null; + + /** @var string Coupon title (ex: Coupon for XMAS) */ protected $title = null; @@ -74,6 +82,8 @@ abstract class CouponAbstract implements CouponInterface /** @var string Coupon description */ protected $description = null; + + /** @var bool if Coupon is enabled */ protected $isEnabled = false; @@ -86,9 +96,6 @@ abstract class CouponAbstract implements CouponInterface /** @var bool if Coupon is removing postage */ protected $isRemovingPostage = false; - /** @var float Amount that will be removed from the Checkout (Coupon Effect) */ - protected $amount = 0; - /** @var int Max time a Coupon can be used (-1 = unlimited) */ protected $maxUsage = -1; @@ -105,6 +112,7 @@ abstract class CouponAbstract implements CouponInterface { $this->adapter = $adapter; $this->translator = $adapter->getTranslator(); + $this->constraintValidator = $adapter->getConstraintValidator(); } /** @@ -220,17 +228,6 @@ abstract class CouponAbstract implements CouponInterface return $this; } - /** - * Check if the current Coupon is matching its conditions (Rules) - * Thelia variables are given by the CouponAdapterInterface - * - * @return bool - */ - public function isMatching() - { - return $this->constraintValidator->test($this->rules); - } - /** * Return Coupon expiration date * @@ -302,4 +299,16 @@ abstract class CouponAbstract implements CouponInterface } + /** + * Check if the current Coupon is matching its conditions (Rules) + * Thelia variables are given by the CouponAdapterInterface + * + * @return bool + */ + public function isMatching() + { + return $this->constraintValidator->isMatching($this->rules); + } + + } diff --git a/core/lib/Thelia/Coupon/Type/CouponInterface.php b/core/lib/Thelia/Coupon/Type/CouponInterface.php index f0426298f..be76c1878 100644 --- a/core/lib/Thelia/Coupon/Type/CouponInterface.php +++ b/core/lib/Thelia/Coupon/Type/CouponInterface.php @@ -39,6 +39,27 @@ use Thelia\Coupon\CouponRuleCollection; */ interface CouponInterface { + /** + * Get I18n name + * + * @return string + */ + public function getName(); + + /** + * Get I18n tooltip + * + * @return string + */ + public function getToolTip(); + + /** + * Get Coupon Manager service Id + * + * @return string + */ + public function getServiceId(); + /** * Set Coupon * @@ -114,18 +135,7 @@ interface CouponInterface */ public function isRemovingPostage(); - /** - * Return effects generated by the coupon - * A positive value - * - * Effects could also affect something else than the final Checkout price - * CouponAdapter $adapter could be use to directly pass a Session value - * some would wish to modify - * Hence affecting a wide variety of Thelia elements - * - * @return float Amount removed from the Total Checkout - */ - public function getDiscount(); + /** * Return condition to validate the Coupon or not @@ -134,14 +144,6 @@ interface CouponInterface */ public function getRules(); - /** - * Check if the current Coupon is matching its conditions (Rules) - * Thelia variables are given by the CouponAdapterInterface - * - * @return bool - */ - public function isMatching(); - /** * Replace the existing Rules by those given in parameter * If one Rule is badly implemented, no Rule will be added @@ -191,25 +193,26 @@ interface CouponInterface */ public function isExpired(); - /** - * Get I18n name - * - * @return string - */ - public function getName(); /** - * Get I18n tooltip + * Return effects generated by the coupon + * A positive value * - * @return string + * Effects could also affect something else than the final Checkout price + * CouponAdapter $adapter could be use to directly pass a Session value + * some would wish to modify + * Hence affecting a wide variety of Thelia elements + * + * @return float Amount removed from the Total Checkout */ - public function getToolTip(); + public function getDiscount(); /** - * Get Coupon Manager service Id + * Check if the current Coupon is matching its conditions (Rules) + * Thelia variables are given by the CouponAdapterInterface * - * @return string + * @return bool */ - public function getServiceId(); + public function isMatching(); } diff --git a/core/lib/Thelia/Form/CouponCreationForm.php b/core/lib/Thelia/Form/CouponCreationForm.php index d63a4284d..1625ab685 100755 --- a/core/lib/Thelia/Form/CouponCreationForm.php +++ b/core/lib/Thelia/Form/CouponCreationForm.php @@ -23,7 +23,11 @@ namespace Thelia\Form; +use Symfony\Component\Validator\Constraints\Date; +use Symfony\Component\Validator\Constraints\DateTime; +use Symfony\Component\Validator\Constraints\GreaterThanOrEqual; use Symfony\Component\Validator\Constraints\NotBlank; +use Symfony\Component\Validator\Constraints\NotEqualTo; /** * Created by JetBrains PhpStorm. @@ -68,7 +72,6 @@ class CouponCreationForm extends BaseForm 'shortDescription', 'text', array( - 'invalid_message' => 'test', 'constraints' => array( new NotBlank() ) @@ -78,7 +81,6 @@ class CouponCreationForm extends BaseForm 'description', 'textarea', array( - 'invalid_message' => 'test', 'constraints' => array( new NotBlank() ) @@ -88,16 +90,23 @@ class CouponCreationForm extends BaseForm 'effect', 'text', array( - 'invalid_message' => 'test', 'constraints' => array( - new NotBlank() + new NotBlank(), + new NotEqualTo( + array( + 'value' => -1 + ) + ) ) ) ) ->add( 'amount', 'money', - array() + array( + 'constraints' => array( + new NotBlank() + )) ) ->add( 'isEnabled', @@ -109,7 +118,8 @@ class CouponCreationForm extends BaseForm 'text', array( 'constraints' => array( - new NotBlank() + new NotBlank(), + new Date() ) ) ) @@ -133,7 +143,12 @@ class CouponCreationForm extends BaseForm 'text', array( 'constraints' => array( - new NotBlank() + new NotBlank(), + new GreaterThanOrEqual( + array( + 'value' => -1 + ) + ) ) ) ) diff --git a/core/lib/Thelia/Form/FeatureAvCreationForm.php b/core/lib/Thelia/Form/FeatureAvCreationForm.php new file mode 100644 index 000000000..504cc9338 --- /dev/null +++ b/core/lib/Thelia/Form/FeatureAvCreationForm.php @@ -0,0 +1,62 @@ +. */ +/* */ +/*************************************************************************************/ +namespace Thelia\Form; + +use Symfony\Component\Validator\Constraints; +use Thelia\Model\CurrencyQuery; +use Symfony\Component\Validator\ExecutionContextInterface; +use Symfony\Component\Validator\Constraints\NotBlank; +use Thelia\Core\Translation\Translator; + +class FeatureAvCreationForm extends BaseForm +{ + protected function buildForm() + { + $this->formBuilder + ->add("title" , "text" , array( + "constraints" => array( + new NotBlank() + ), + "label" => Translator::getInstance()->trans("Title *"), + "label_attr" => array( + "for" => "title" + )) + ) + ->add("locale" , "text" , array( + "constraints" => array( + new NotBlank() + )) + ) + ->add("feature_id", "hidden", array( + "constraints" => array( + new NotBlank() + )) + ) + ; + } + + public function getName() + { + return "thelia_featureav_creation"; + } +} \ No newline at end of file diff --git a/core/lib/Thelia/Form/FeatureCreationForm.php b/core/lib/Thelia/Form/FeatureCreationForm.php new file mode 100644 index 000000000..1977bd78b --- /dev/null +++ b/core/lib/Thelia/Form/FeatureCreationForm.php @@ -0,0 +1,66 @@ +. */ +/* */ +/*************************************************************************************/ +namespace Thelia\Form; + +use Symfony\Component\Validator\Constraints; +use Thelia\Model\CurrencyQuery; +use Symfony\Component\Validator\ExecutionContextInterface; +use Symfony\Component\Validator\Constraints\NotBlank; +use Thelia\Core\Translation\Translator; + +class FeatureCreationForm extends BaseForm +{ + protected function buildForm() + { + $this->formBuilder + ->add("title" , "text" , array( + "constraints" => array( + new NotBlank() + ), + "label" => Translator::getInstance()->trans("Title *"), + "label_attr" => array( + "for" => "title" + )) + ) + ->add("locale" , "text" , array( + "constraints" => array( + new NotBlank() + )) + ) + ->add("add_to_all" , "checkbox" , array( + "constraints" => array( + new NotBlank() + ), + "label" => Translator::getInstance()->trans("Add to all product templates"), + "label_attr" => array( + "for" => "add_to_all" + )) + ) + ; + } + + public function getName() + { + return "thelia_feature_creation"; + } +} diff --git a/core/lib/Thelia/Form/FeatureModificationForm.php b/core/lib/Thelia/Form/FeatureModificationForm.php new file mode 100644 index 000000000..1702f299e --- /dev/null +++ b/core/lib/Thelia/Form/FeatureModificationForm.php @@ -0,0 +1,62 @@ +. */ +/* */ +/*************************************************************************************/ +namespace Thelia\Form; + +use Symfony\Component\Validator\Constraints; +use Thelia\Model\CurrencyQuery; +use Symfony\Component\Validator\ExecutionContextInterface; +use Symfony\Component\Validator\Constraints\NotBlank; +use Thelia\Core\Translation\Translator; +use Symfony\Component\Validator\Constraints\GreaterThan; + +class FeatureModificationForm extends FeatureCreationForm +{ + use StandardDescriptionFieldsTrait; + + protected function buildForm() + { + $this->formBuilder + ->add("id", "hidden", array( + "constraints" => array( + new GreaterThan( + array('value' => 0) + ) + ) + )) +/* FIXME: doesn't work + ->add('feature_values', 'collection', array( + 'type' => 'text', + 'options' => array('required' => false) + )) +*/ + ; + + // Add standard description fields + $this->addStandardDescFields(); + } + + public function getName() + { + return "thelia_feature_modification"; + } +} diff --git a/core/lib/Thelia/Model/Base/CartItem.php b/core/lib/Thelia/Model/Base/CartItem.php index 5dd573d39..e785ae0a5 100644 --- a/core/lib/Thelia/Model/Base/CartItem.php +++ b/core/lib/Thelia/Model/Base/CartItem.php @@ -116,6 +116,12 @@ abstract class CartItem implements ActiveRecordInterface */ protected $discount; + /** + * The value for the promo field. + * @var int + */ + protected $promo; + /** * The value for the created_at field. * @var string @@ -527,6 +533,17 @@ abstract class CartItem implements ActiveRecordInterface return $this->discount; } + /** + * Get the [promo] column value. + * + * @return int + */ + public function getPromo() + { + + return $this->promo; + } + /** * Get the [optionally formatted] temporal [created_at] column value. * @@ -768,6 +785,27 @@ abstract class CartItem implements ActiveRecordInterface return $this; } // setDiscount() + /** + * Set the value of [promo] column. + * + * @param int $v new value + * @return \Thelia\Model\CartItem The current object (for fluent API support) + */ + public function setPromo($v) + { + if ($v !== null) { + $v = (int) $v; + } + + if ($this->promo !== $v) { + $this->promo = $v; + $this->modifiedColumns[] = CartItemTableMap::PROMO; + } + + + return $this; + } // setPromo() + /** * Sets the value of [created_at] column to a normalized version of the date/time value specified. * @@ -885,13 +923,16 @@ abstract class CartItem implements ActiveRecordInterface $col = $row[TableMap::TYPE_NUM == $indexType ? 8 + $startcol : CartItemTableMap::translateFieldName('Discount', TableMap::TYPE_PHPNAME, $indexType)]; $this->discount = (null !== $col) ? (double) $col : null; - $col = $row[TableMap::TYPE_NUM == $indexType ? 9 + $startcol : CartItemTableMap::translateFieldName('CreatedAt', TableMap::TYPE_PHPNAME, $indexType)]; + $col = $row[TableMap::TYPE_NUM == $indexType ? 9 + $startcol : CartItemTableMap::translateFieldName('Promo', TableMap::TYPE_PHPNAME, $indexType)]; + $this->promo = (null !== $col) ? (int) $col : null; + + $col = $row[TableMap::TYPE_NUM == $indexType ? 10 + $startcol : CartItemTableMap::translateFieldName('CreatedAt', TableMap::TYPE_PHPNAME, $indexType)]; if ($col === '0000-00-00 00:00:00') { $col = null; } $this->created_at = (null !== $col) ? PropelDateTime::newInstance($col, null, '\DateTime') : null; - $col = $row[TableMap::TYPE_NUM == $indexType ? 10 + $startcol : CartItemTableMap::translateFieldName('UpdatedAt', TableMap::TYPE_PHPNAME, $indexType)]; + $col = $row[TableMap::TYPE_NUM == $indexType ? 11 + $startcol : CartItemTableMap::translateFieldName('UpdatedAt', TableMap::TYPE_PHPNAME, $indexType)]; if ($col === '0000-00-00 00:00:00') { $col = null; } @@ -904,7 +945,7 @@ abstract class CartItem implements ActiveRecordInterface $this->ensureConsistency(); } - return $startcol + 11; // 11 = CartItemTableMap::NUM_HYDRATE_COLUMNS. + return $startcol + 12; // 12 = CartItemTableMap::NUM_HYDRATE_COLUMNS. } catch (Exception $e) { throw new PropelException("Error populating \Thelia\Model\CartItem object", 0, $e); @@ -1189,6 +1230,9 @@ abstract class CartItem implements ActiveRecordInterface if ($this->isColumnModified(CartItemTableMap::DISCOUNT)) { $modifiedColumns[':p' . $index++] = 'DISCOUNT'; } + if ($this->isColumnModified(CartItemTableMap::PROMO)) { + $modifiedColumns[':p' . $index++] = 'PROMO'; + } if ($this->isColumnModified(CartItemTableMap::CREATED_AT)) { $modifiedColumns[':p' . $index++] = 'CREATED_AT'; } @@ -1233,6 +1277,9 @@ abstract class CartItem implements ActiveRecordInterface case 'DISCOUNT': $stmt->bindValue($identifier, $this->discount, PDO::PARAM_STR); break; + case 'PROMO': + $stmt->bindValue($identifier, $this->promo, PDO::PARAM_INT); + break; case 'CREATED_AT': $stmt->bindValue($identifier, $this->created_at ? $this->created_at->format("Y-m-d H:i:s") : null, PDO::PARAM_STR); break; @@ -1329,9 +1376,12 @@ abstract class CartItem implements ActiveRecordInterface return $this->getDiscount(); break; case 9: - return $this->getCreatedAt(); + return $this->getPromo(); break; case 10: + return $this->getCreatedAt(); + break; + case 11: return $this->getUpdatedAt(); break; default: @@ -1372,8 +1422,9 @@ abstract class CartItem implements ActiveRecordInterface $keys[6] => $this->getPromoPrice(), $keys[7] => $this->getPriceEndOfLife(), $keys[8] => $this->getDiscount(), - $keys[9] => $this->getCreatedAt(), - $keys[10] => $this->getUpdatedAt(), + $keys[9] => $this->getPromo(), + $keys[10] => $this->getCreatedAt(), + $keys[11] => $this->getUpdatedAt(), ); $virtualColumns = $this->virtualColumns; foreach($virtualColumns as $key => $virtualColumn) @@ -1453,9 +1504,12 @@ abstract class CartItem implements ActiveRecordInterface $this->setDiscount($value); break; case 9: - $this->setCreatedAt($value); + $this->setPromo($value); break; case 10: + $this->setCreatedAt($value); + break; + case 11: $this->setUpdatedAt($value); break; } // switch() @@ -1491,8 +1545,9 @@ abstract class CartItem implements ActiveRecordInterface if (array_key_exists($keys[6], $arr)) $this->setPromoPrice($arr[$keys[6]]); if (array_key_exists($keys[7], $arr)) $this->setPriceEndOfLife($arr[$keys[7]]); if (array_key_exists($keys[8], $arr)) $this->setDiscount($arr[$keys[8]]); - if (array_key_exists($keys[9], $arr)) $this->setCreatedAt($arr[$keys[9]]); - if (array_key_exists($keys[10], $arr)) $this->setUpdatedAt($arr[$keys[10]]); + if (array_key_exists($keys[9], $arr)) $this->setPromo($arr[$keys[9]]); + if (array_key_exists($keys[10], $arr)) $this->setCreatedAt($arr[$keys[10]]); + if (array_key_exists($keys[11], $arr)) $this->setUpdatedAt($arr[$keys[11]]); } /** @@ -1513,6 +1568,7 @@ abstract class CartItem implements ActiveRecordInterface if ($this->isColumnModified(CartItemTableMap::PROMO_PRICE)) $criteria->add(CartItemTableMap::PROMO_PRICE, $this->promo_price); if ($this->isColumnModified(CartItemTableMap::PRICE_END_OF_LIFE)) $criteria->add(CartItemTableMap::PRICE_END_OF_LIFE, $this->price_end_of_life); if ($this->isColumnModified(CartItemTableMap::DISCOUNT)) $criteria->add(CartItemTableMap::DISCOUNT, $this->discount); + if ($this->isColumnModified(CartItemTableMap::PROMO)) $criteria->add(CartItemTableMap::PROMO, $this->promo); if ($this->isColumnModified(CartItemTableMap::CREATED_AT)) $criteria->add(CartItemTableMap::CREATED_AT, $this->created_at); if ($this->isColumnModified(CartItemTableMap::UPDATED_AT)) $criteria->add(CartItemTableMap::UPDATED_AT, $this->updated_at); @@ -1586,6 +1642,7 @@ abstract class CartItem implements ActiveRecordInterface $copyObj->setPromoPrice($this->getPromoPrice()); $copyObj->setPriceEndOfLife($this->getPriceEndOfLife()); $copyObj->setDiscount($this->getDiscount()); + $copyObj->setPromo($this->getPromo()); $copyObj->setCreatedAt($this->getCreatedAt()); $copyObj->setUpdatedAt($this->getUpdatedAt()); if ($makeNew) { @@ -1783,6 +1840,7 @@ abstract class CartItem implements ActiveRecordInterface $this->promo_price = null; $this->price_end_of_life = null; $this->discount = null; + $this->promo = null; $this->created_at = null; $this->updated_at = null; $this->alreadyInSave = false; diff --git a/core/lib/Thelia/Model/Base/CartItemQuery.php b/core/lib/Thelia/Model/Base/CartItemQuery.php index 83705aeac..79d5d3cfe 100644 --- a/core/lib/Thelia/Model/Base/CartItemQuery.php +++ b/core/lib/Thelia/Model/Base/CartItemQuery.php @@ -30,6 +30,7 @@ use Thelia\Model\Map\CartItemTableMap; * @method ChildCartItemQuery orderByPromoPrice($order = Criteria::ASC) Order by the promo_price column * @method ChildCartItemQuery orderByPriceEndOfLife($order = Criteria::ASC) Order by the price_end_of_life column * @method ChildCartItemQuery orderByDiscount($order = Criteria::ASC) Order by the discount column + * @method ChildCartItemQuery orderByPromo($order = Criteria::ASC) Order by the promo column * @method ChildCartItemQuery orderByCreatedAt($order = Criteria::ASC) Order by the created_at column * @method ChildCartItemQuery orderByUpdatedAt($order = Criteria::ASC) Order by the updated_at column * @@ -42,6 +43,7 @@ use Thelia\Model\Map\CartItemTableMap; * @method ChildCartItemQuery groupByPromoPrice() Group by the promo_price column * @method ChildCartItemQuery groupByPriceEndOfLife() Group by the price_end_of_life column * @method ChildCartItemQuery groupByDiscount() Group by the discount column + * @method ChildCartItemQuery groupByPromo() Group by the promo column * @method ChildCartItemQuery groupByCreatedAt() Group by the created_at column * @method ChildCartItemQuery groupByUpdatedAt() Group by the updated_at column * @@ -73,6 +75,7 @@ use Thelia\Model\Map\CartItemTableMap; * @method ChildCartItem findOneByPromoPrice(double $promo_price) Return the first ChildCartItem filtered by the promo_price column * @method ChildCartItem findOneByPriceEndOfLife(string $price_end_of_life) Return the first ChildCartItem filtered by the price_end_of_life column * @method ChildCartItem findOneByDiscount(double $discount) Return the first ChildCartItem filtered by the discount column + * @method ChildCartItem findOneByPromo(int $promo) Return the first ChildCartItem filtered by the promo column * @method ChildCartItem findOneByCreatedAt(string $created_at) Return the first ChildCartItem filtered by the created_at column * @method ChildCartItem findOneByUpdatedAt(string $updated_at) Return the first ChildCartItem filtered by the updated_at column * @@ -85,6 +88,7 @@ use Thelia\Model\Map\CartItemTableMap; * @method array findByPromoPrice(double $promo_price) Return ChildCartItem objects filtered by the promo_price column * @method array findByPriceEndOfLife(string $price_end_of_life) Return ChildCartItem objects filtered by the price_end_of_life column * @method array findByDiscount(double $discount) Return ChildCartItem objects filtered by the discount column + * @method array findByPromo(int $promo) Return ChildCartItem objects filtered by the promo column * @method array findByCreatedAt(string $created_at) Return ChildCartItem objects filtered by the created_at column * @method array findByUpdatedAt(string $updated_at) Return ChildCartItem objects filtered by the updated_at column * @@ -175,7 +179,7 @@ abstract class CartItemQuery extends ModelCriteria */ protected function findPkSimple($key, $con) { - $sql = 'SELECT ID, CART_ID, PRODUCT_ID, QUANTITY, PRODUCT_SALE_ELEMENTS_ID, PRICE, PROMO_PRICE, PRICE_END_OF_LIFE, DISCOUNT, CREATED_AT, UPDATED_AT FROM cart_item WHERE ID = :p0'; + $sql = 'SELECT ID, CART_ID, PRODUCT_ID, QUANTITY, PRODUCT_SALE_ELEMENTS_ID, PRICE, PROMO_PRICE, PRICE_END_OF_LIFE, DISCOUNT, PROMO, CREATED_AT, UPDATED_AT FROM cart_item WHERE ID = :p0'; try { $stmt = $con->prepare($sql); $stmt->bindValue(':p0', $key, PDO::PARAM_INT); @@ -641,6 +645,47 @@ abstract class CartItemQuery extends ModelCriteria return $this->addUsingAlias(CartItemTableMap::DISCOUNT, $discount, $comparison); } + /** + * Filter the query on the promo column + * + * Example usage: + * + * $query->filterByPromo(1234); // WHERE promo = 1234 + * $query->filterByPromo(array(12, 34)); // WHERE promo IN (12, 34) + * $query->filterByPromo(array('min' => 12)); // WHERE promo > 12 + * + * + * @param mixed $promo The value to use as filter. + * Use scalar values for equality. + * Use array values for in_array() equivalent. + * Use associative array('min' => $minValue, 'max' => $maxValue) for intervals. + * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL + * + * @return ChildCartItemQuery The current query, for fluid interface + */ + public function filterByPromo($promo = null, $comparison = null) + { + if (is_array($promo)) { + $useMinMax = false; + if (isset($promo['min'])) { + $this->addUsingAlias(CartItemTableMap::PROMO, $promo['min'], Criteria::GREATER_EQUAL); + $useMinMax = true; + } + if (isset($promo['max'])) { + $this->addUsingAlias(CartItemTableMap::PROMO, $promo['max'], Criteria::LESS_EQUAL); + $useMinMax = true; + } + if ($useMinMax) { + return $this; + } + if (null === $comparison) { + $comparison = Criteria::IN; + } + } + + return $this->addUsingAlias(CartItemTableMap::PROMO, $promo, $comparison); + } + /** * Filter the query on the created_at column * diff --git a/core/lib/Thelia/Model/Coupon.php b/core/lib/Thelia/Model/Coupon.php index 7a7ce1e4a..032de412a 100755 --- a/core/lib/Thelia/Model/Coupon.php +++ b/core/lib/Thelia/Model/Coupon.php @@ -76,7 +76,6 @@ class Coupon extends BaseCoupon ->setType($effect) ->setAmount($amount) ->setIsRemovingPostage($isRemovingPostage) - ->setType($amount) ->setIsEnabled($isEnabled) ->setExpirationDate($expirationDate) ->setIsAvailableOnSpecialOffers($isAvailableOnSpecialOffers) diff --git a/core/lib/Thelia/Model/Feature.php b/core/lib/Thelia/Model/Feature.php index ce7c57b1d..cf0284d2b 100755 --- a/core/lib/Thelia/Model/Feature.php +++ b/core/lib/Thelia/Model/Feature.php @@ -3,7 +3,70 @@ namespace Thelia\Model; use Thelia\Model\Base\Feature as BaseFeature; +use Propel\Runtime\Connection\ConnectionInterface; +use Thelia\Core\Event\TheliaEvents; +use Thelia\Core\Event\FeatureEvent; class Feature extends BaseFeature { + use \Thelia\Model\Tools\ModelEventDispatcherTrait; + use \Thelia\Model\Tools\PositionManagementTrait; + + /** + * {@inheritDoc} + */ + public function preInsert(ConnectionInterface $con = null) + { + $this->dispatchEvent(TheliaEvents::BEFORE_CREATEFEATURE, new FeatureEvent($this)); + + // Set the current position for the new object + $this->setPosition($this->getNextPosition()); + + return true; + } + + /** + * {@inheritDoc} + */ + public function postInsert(ConnectionInterface $con = null) + { + $this->dispatchEvent(TheliaEvents::AFTER_CREATEFEATURE, new FeatureEvent($this)); + } + + /** + * {@inheritDoc} + */ + public function preUpdate(ConnectionInterface $con = null) + { + $this->dispatchEvent(TheliaEvents::BEFORE_UPDATEFEATURE, new FeatureEvent($this)); + + return true; + } + + /** + * {@inheritDoc} + */ + public function postUpdate(ConnectionInterface $con = null) + { + $this->dispatchEvent(TheliaEvents::AFTER_UPDATEFEATURE, new FeatureEvent($this)); + } + + /** + * {@inheritDoc} + */ + public function preDelete(ConnectionInterface $con = null) + { + $this->dispatchEvent(TheliaEvents::BEFORE_DELETEFEATURE, new FeatureEvent($this)); + + return true; + } + + /** + * {@inheritDoc} + */ + public function postDelete(ConnectionInterface $con = null) + { + $this->dispatchEvent(TheliaEvents::AFTER_DELETEFEATURE, new FeatureEvent($this)); + } + } diff --git a/core/lib/Thelia/Model/FeatureAv.php b/core/lib/Thelia/Model/FeatureAv.php index 68b6fa92a..ae6e35087 100755 --- a/core/lib/Thelia/Model/FeatureAv.php +++ b/core/lib/Thelia/Model/FeatureAv.php @@ -3,7 +3,78 @@ namespace Thelia\Model; use Thelia\Model\Base\FeatureAv as BaseFeatureAv; +use Thelia\Core\Event\TheliaEvents; +use Propel\Runtime\Connection\ConnectionInterface; +use Thelia\Core\Event\FeatureAvEvent; class FeatureAv extends BaseFeatureAv { + use \Thelia\Model\Tools\ModelEventDispatcherTrait; + + use \Thelia\Model\Tools\PositionManagementTrait; + + /** + * when dealing with position, be sure to work insite the current feature. + */ + protected function addCriteriaToPositionQuery($query) { + $query->filterByFeatureId($this->getFeatureId()); + } + + /** + * {@inheritDoc} + */ + public function preInsert(ConnectionInterface $con = null) + { + // Set the current position for the new object + $this->setPosition($this->getNextPosition()); + + $this->dispatchEvent(TheliaEvents::BEFORE_CREATEFEATURE_AV, new FeatureAvEvent($this)); + + return true; + } + + /** + * {@inheritDoc} + */ + public function postInsert(ConnectionInterface $con = null) + { + $this->dispatchEvent(TheliaEvents::AFTER_CREATEFEATURE_AV, new FeatureAvEvent($this)); + } + + /** + * {@inheritDoc} + */ + public function preUpdate(ConnectionInterface $con = null) + { + $this->dispatchEvent(TheliaEvents::BEFORE_UPDATEFEATURE_AV, new FeatureAvEvent($this)); + + return true; + } + + /** + * {@inheritDoc} + */ + public function postUpdate(ConnectionInterface $con = null) + { + $this->dispatchEvent(TheliaEvents::AFTER_UPDATEFEATURE_AV, new FeatureAvEvent($this)); + } + + /** + * {@inheritDoc} + */ + public function preDelete(ConnectionInterface $con = null) + { + $this->dispatchEvent(TheliaEvents::BEFORE_DELETEFEATURE_AV, new FeatureAvEvent($this)); + + return true; + } + + /** + * {@inheritDoc} + */ + public function postDelete(ConnectionInterface $con = null) + { + $this->dispatchEvent(TheliaEvents::AFTER_DELETEFEATURE_AV, new FeatureAvEvent($this)); + } + } diff --git a/core/lib/Thelia/Model/Map/CartItemTableMap.php b/core/lib/Thelia/Model/Map/CartItemTableMap.php index 7520b39c9..c48d298e0 100644 --- a/core/lib/Thelia/Model/Map/CartItemTableMap.php +++ b/core/lib/Thelia/Model/Map/CartItemTableMap.php @@ -57,7 +57,7 @@ class CartItemTableMap extends TableMap /** * The total number of columns */ - const NUM_COLUMNS = 11; + const NUM_COLUMNS = 12; /** * The number of lazy-loaded columns @@ -67,7 +67,7 @@ class CartItemTableMap extends TableMap /** * The number of columns to hydrate (NUM_COLUMNS - NUM_LAZY_LOAD_COLUMNS) */ - const NUM_HYDRATE_COLUMNS = 11; + const NUM_HYDRATE_COLUMNS = 12; /** * the column name for the ID field @@ -114,6 +114,11 @@ class CartItemTableMap extends TableMap */ const DISCOUNT = 'cart_item.DISCOUNT'; + /** + * the column name for the PROMO field + */ + const PROMO = 'cart_item.PROMO'; + /** * the column name for the CREATED_AT field */ @@ -136,12 +141,12 @@ class CartItemTableMap extends TableMap * e.g. self::$fieldNames[self::TYPE_PHPNAME][0] = 'Id' */ protected static $fieldNames = array ( - self::TYPE_PHPNAME => array('Id', 'CartId', 'ProductId', 'Quantity', 'ProductSaleElementsId', 'Price', 'PromoPrice', 'PriceEndOfLife', 'Discount', 'CreatedAt', 'UpdatedAt', ), - self::TYPE_STUDLYPHPNAME => array('id', 'cartId', 'productId', 'quantity', 'productSaleElementsId', 'price', 'promoPrice', 'priceEndOfLife', 'discount', 'createdAt', 'updatedAt', ), - self::TYPE_COLNAME => array(CartItemTableMap::ID, CartItemTableMap::CART_ID, CartItemTableMap::PRODUCT_ID, CartItemTableMap::QUANTITY, CartItemTableMap::PRODUCT_SALE_ELEMENTS_ID, CartItemTableMap::PRICE, CartItemTableMap::PROMO_PRICE, CartItemTableMap::PRICE_END_OF_LIFE, CartItemTableMap::DISCOUNT, CartItemTableMap::CREATED_AT, CartItemTableMap::UPDATED_AT, ), - self::TYPE_RAW_COLNAME => array('ID', 'CART_ID', 'PRODUCT_ID', 'QUANTITY', 'PRODUCT_SALE_ELEMENTS_ID', 'PRICE', 'PROMO_PRICE', 'PRICE_END_OF_LIFE', 'DISCOUNT', 'CREATED_AT', 'UPDATED_AT', ), - self::TYPE_FIELDNAME => array('id', 'cart_id', 'product_id', 'quantity', 'product_sale_elements_id', 'price', 'promo_price', 'price_end_of_life', 'discount', 'created_at', 'updated_at', ), - self::TYPE_NUM => array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, ) + self::TYPE_PHPNAME => array('Id', 'CartId', 'ProductId', 'Quantity', 'ProductSaleElementsId', 'Price', 'PromoPrice', 'PriceEndOfLife', 'Discount', 'Promo', 'CreatedAt', 'UpdatedAt', ), + self::TYPE_STUDLYPHPNAME => array('id', 'cartId', 'productId', 'quantity', 'productSaleElementsId', 'price', 'promoPrice', 'priceEndOfLife', 'discount', 'promo', 'createdAt', 'updatedAt', ), + self::TYPE_COLNAME => array(CartItemTableMap::ID, CartItemTableMap::CART_ID, CartItemTableMap::PRODUCT_ID, CartItemTableMap::QUANTITY, CartItemTableMap::PRODUCT_SALE_ELEMENTS_ID, CartItemTableMap::PRICE, CartItemTableMap::PROMO_PRICE, CartItemTableMap::PRICE_END_OF_LIFE, CartItemTableMap::DISCOUNT, CartItemTableMap::PROMO, CartItemTableMap::CREATED_AT, CartItemTableMap::UPDATED_AT, ), + self::TYPE_RAW_COLNAME => array('ID', 'CART_ID', 'PRODUCT_ID', 'QUANTITY', 'PRODUCT_SALE_ELEMENTS_ID', 'PRICE', 'PROMO_PRICE', 'PRICE_END_OF_LIFE', 'DISCOUNT', 'PROMO', 'CREATED_AT', 'UPDATED_AT', ), + self::TYPE_FIELDNAME => array('id', 'cart_id', 'product_id', 'quantity', 'product_sale_elements_id', 'price', 'promo_price', 'price_end_of_life', 'discount', 'promo', 'created_at', 'updated_at', ), + self::TYPE_NUM => array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, ) ); /** @@ -151,12 +156,12 @@ class CartItemTableMap extends TableMap * e.g. self::$fieldKeys[self::TYPE_PHPNAME]['Id'] = 0 */ protected static $fieldKeys = array ( - self::TYPE_PHPNAME => array('Id' => 0, 'CartId' => 1, 'ProductId' => 2, 'Quantity' => 3, 'ProductSaleElementsId' => 4, 'Price' => 5, 'PromoPrice' => 6, 'PriceEndOfLife' => 7, 'Discount' => 8, 'CreatedAt' => 9, 'UpdatedAt' => 10, ), - self::TYPE_STUDLYPHPNAME => array('id' => 0, 'cartId' => 1, 'productId' => 2, 'quantity' => 3, 'productSaleElementsId' => 4, 'price' => 5, 'promoPrice' => 6, 'priceEndOfLife' => 7, 'discount' => 8, 'createdAt' => 9, 'updatedAt' => 10, ), - self::TYPE_COLNAME => array(CartItemTableMap::ID => 0, CartItemTableMap::CART_ID => 1, CartItemTableMap::PRODUCT_ID => 2, CartItemTableMap::QUANTITY => 3, CartItemTableMap::PRODUCT_SALE_ELEMENTS_ID => 4, CartItemTableMap::PRICE => 5, CartItemTableMap::PROMO_PRICE => 6, CartItemTableMap::PRICE_END_OF_LIFE => 7, CartItemTableMap::DISCOUNT => 8, CartItemTableMap::CREATED_AT => 9, CartItemTableMap::UPDATED_AT => 10, ), - self::TYPE_RAW_COLNAME => array('ID' => 0, 'CART_ID' => 1, 'PRODUCT_ID' => 2, 'QUANTITY' => 3, 'PRODUCT_SALE_ELEMENTS_ID' => 4, 'PRICE' => 5, 'PROMO_PRICE' => 6, 'PRICE_END_OF_LIFE' => 7, 'DISCOUNT' => 8, 'CREATED_AT' => 9, 'UPDATED_AT' => 10, ), - self::TYPE_FIELDNAME => array('id' => 0, 'cart_id' => 1, 'product_id' => 2, 'quantity' => 3, 'product_sale_elements_id' => 4, 'price' => 5, 'promo_price' => 6, 'price_end_of_life' => 7, 'discount' => 8, 'created_at' => 9, 'updated_at' => 10, ), - self::TYPE_NUM => array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, ) + self::TYPE_PHPNAME => array('Id' => 0, 'CartId' => 1, 'ProductId' => 2, 'Quantity' => 3, 'ProductSaleElementsId' => 4, 'Price' => 5, 'PromoPrice' => 6, 'PriceEndOfLife' => 7, 'Discount' => 8, 'Promo' => 9, 'CreatedAt' => 10, 'UpdatedAt' => 11, ), + self::TYPE_STUDLYPHPNAME => array('id' => 0, 'cartId' => 1, 'productId' => 2, 'quantity' => 3, 'productSaleElementsId' => 4, 'price' => 5, 'promoPrice' => 6, 'priceEndOfLife' => 7, 'discount' => 8, 'promo' => 9, 'createdAt' => 10, 'updatedAt' => 11, ), + self::TYPE_COLNAME => array(CartItemTableMap::ID => 0, CartItemTableMap::CART_ID => 1, CartItemTableMap::PRODUCT_ID => 2, CartItemTableMap::QUANTITY => 3, CartItemTableMap::PRODUCT_SALE_ELEMENTS_ID => 4, CartItemTableMap::PRICE => 5, CartItemTableMap::PROMO_PRICE => 6, CartItemTableMap::PRICE_END_OF_LIFE => 7, CartItemTableMap::DISCOUNT => 8, CartItemTableMap::PROMO => 9, CartItemTableMap::CREATED_AT => 10, CartItemTableMap::UPDATED_AT => 11, ), + self::TYPE_RAW_COLNAME => array('ID' => 0, 'CART_ID' => 1, 'PRODUCT_ID' => 2, 'QUANTITY' => 3, 'PRODUCT_SALE_ELEMENTS_ID' => 4, 'PRICE' => 5, 'PROMO_PRICE' => 6, 'PRICE_END_OF_LIFE' => 7, 'DISCOUNT' => 8, 'PROMO' => 9, 'CREATED_AT' => 10, 'UPDATED_AT' => 11, ), + self::TYPE_FIELDNAME => array('id' => 0, 'cart_id' => 1, 'product_id' => 2, 'quantity' => 3, 'product_sale_elements_id' => 4, 'price' => 5, 'promo_price' => 6, 'price_end_of_life' => 7, 'discount' => 8, 'promo' => 9, 'created_at' => 10, 'updated_at' => 11, ), + self::TYPE_NUM => array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, ) ); /** @@ -184,6 +189,7 @@ class CartItemTableMap extends TableMap $this->addColumn('PROMO_PRICE', 'PromoPrice', 'FLOAT', false, null, null); $this->addColumn('PRICE_END_OF_LIFE', 'PriceEndOfLife', 'TIMESTAMP', false, null, null); $this->addColumn('DISCOUNT', 'Discount', 'FLOAT', false, null, 0); + $this->addColumn('PROMO', 'Promo', 'INTEGER', false, null, null); $this->addColumn('CREATED_AT', 'CreatedAt', 'TIMESTAMP', false, null, null); $this->addColumn('UPDATED_AT', 'UpdatedAt', 'TIMESTAMP', false, null, null); } // initialize() @@ -358,6 +364,7 @@ class CartItemTableMap extends TableMap $criteria->addSelectColumn(CartItemTableMap::PROMO_PRICE); $criteria->addSelectColumn(CartItemTableMap::PRICE_END_OF_LIFE); $criteria->addSelectColumn(CartItemTableMap::DISCOUNT); + $criteria->addSelectColumn(CartItemTableMap::PROMO); $criteria->addSelectColumn(CartItemTableMap::CREATED_AT); $criteria->addSelectColumn(CartItemTableMap::UPDATED_AT); } else { @@ -370,6 +377,7 @@ class CartItemTableMap extends TableMap $criteria->addSelectColumn($alias . '.PROMO_PRICE'); $criteria->addSelectColumn($alias . '.PRICE_END_OF_LIFE'); $criteria->addSelectColumn($alias . '.DISCOUNT'); + $criteria->addSelectColumn($alias . '.PROMO'); $criteria->addSelectColumn($alias . '.CREATED_AT'); $criteria->addSelectColumn($alias . '.UPDATED_AT'); } diff --git a/core/lib/Thelia/Tests/Constraint/ConstraintValidatorTest.php b/core/lib/Thelia/Tests/Constraint/ConstraintValidatorTest.php index 01e9dde69..17b6b49e1 100644 --- a/core/lib/Thelia/Tests/Constraint/ConstraintValidatorTest.php +++ b/core/lib/Thelia/Tests/Constraint/ConstraintValidatorTest.php @@ -79,7 +79,7 @@ class ConstraintValidatorTest extends \PHPUnit_Framework_TestCase $rules = new CouponRuleCollection(); $rules->add($rule1); - $isValid = $ConstraintValidator->test($rules); + $isValid = $ConstraintValidator->isMatching($rules); $expected = true; $actual =$isValid; @@ -113,7 +113,7 @@ class ConstraintValidatorTest extends \PHPUnit_Framework_TestCase $rules = new CouponRuleCollection(); $rules->add($rule1); - $isValid = $ConstraintValidator->test($rules); + $isValid = $ConstraintValidator->isMatching($rules); $expected = false; $actual =$isValid; @@ -160,7 +160,7 @@ class ConstraintValidatorTest extends \PHPUnit_Framework_TestCase $rules->add($rule1); $rules->add($rule2); - $isValid = $ConstraintValidator->test($rules); + $isValid = $ConstraintValidator->isMatching($rules); $expected = true; $actual =$isValid; @@ -207,7 +207,7 @@ class ConstraintValidatorTest extends \PHPUnit_Framework_TestCase $rules->add($rule1); $rules->add($rule2); - $isValid = $ConstraintValidator->test($rules); + $isValid = $ConstraintValidator->isMatching($rules); $expected = false; $actual =$isValid; diff --git a/install/insert.sql b/install/insert.sql index 1cc7c55e6..03fbc690c 100755 --- a/install/insert.sql +++ b/install/insert.sql @@ -1,6 +1,6 @@ INSERT INTO `lang`(`id`,`title`,`code`,`locale`,`url`,`date_format`,`time_format`,`datetime_format`,`decimal_separator`,`thousands_separator`,`decimals`,`by_default`,`created_at`,`updated_at`)VALUES -(1, 'Français', 'fr', 'fr_FR', '', 'd/m/Y', 'H:i:s', 'd/m/y H:i:s', ',', ' ', '2', '1', NOW(), NOW()), -(2, 'English', 'en', 'en_US', '', 'm-d-Y', 'h:i:s', 'm-d-Y h:i:s', '.', ' ', '2', '0', NOW(), NOW()), +(1, 'Français', 'fr', 'fr_FR', '', 'd/m/Y', 'H:i:s', 'd/m/y H:i:s', ',', ' ', '2', '0', NOW(), NOW()), +(2, 'English', 'en', 'en_US', '', 'm-d-Y', 'h:i:s', 'm-d-Y h:i:s', '.', ' ', '2', '1', NOW(), NOW()), (3, 'castellano', 'es', 'es_ES', '', 'm-d-Y', 'h:i:s', 'm-d-Y h:i:s', ',', '.', '2', '0', NOW(), NOW()), (4, 'Italiano', 'it', 'it_IT', '', 'd/m/Y', 'H:i:s', 'd/m/y H:i:s', ',', ' ', '2', '0', NOW(), NOW()); diff --git a/install/thelia.sql b/install/thelia.sql index 5aa478da5..7e1818ef6 100755 --- a/install/thelia.sql +++ b/install/thelia.sql @@ -45,7 +45,7 @@ CREATE TABLE `product` PRIMARY KEY (`id`), UNIQUE INDEX `ref_UNIQUE` (`ref`), INDEX `idx_product_tax_rule_id` (`tax_rule_id`), - INDEX `fk_product_template1_idx` (`template_id`), + INDEX `fk_product_template_id` (`template_id`), CONSTRAINT `fk_product_tax_rule_id` FOREIGN KEY (`tax_rule_id`) REFERENCES `tax_rule` (`id`) @@ -1198,6 +1198,7 @@ CREATE TABLE `cart_item` `promo_price` FLOAT, `price_end_of_life` DATETIME, `discount` FLOAT DEFAULT 0, + `promo` INTEGER, `created_at` DATETIME, `updated_at` DATETIME, PRIMARY KEY (`id`), diff --git a/local/config/schema.xml b/local/config/schema.xml index 1ffeb028a..77dcf7c37 100755 --- a/local/config/schema.xml +++ b/local/config/schema.xml @@ -1,1162 +1,1163 @@ - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - -
- - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - -
- - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - -
- - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
- - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - -
- - - - - -
- - - - - - - - - - - -
- - - - - - - - - - - - - - -
- - - - - - - - - - - - - - -
- - - - - - - - - - - -
- - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
- - - - - - - - -
- - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
- - - - - - - -
-
+ + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + +
+ + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + +
+ + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + +
+ + + + + + + +
+
diff --git a/templates/admin/default/admin-layout.tpl b/templates/admin/default/admin-layout.tpl index b15c624f3..3b97c069b 100644 --- a/templates/admin/default/admin-layout.tpl +++ b/templates/admin/default/admin-layout.tpl @@ -146,7 +146,7 @@ {loop name="menu-auth-coupon" type="auth" roles="ADMIN" permissions="admin.coupon.view"}
  • - {intl l="Coupons"} + {intl l="Coupons"}
  • {/loop} diff --git a/templates/admin/default/assets/bootstrap-datepicker/js/bootstrap-datepicker.js b/templates/admin/default/assets/bootstrap-datepicker/js/bootstrap-datepicker.js index bf3a56df0..97a3d67ed 100755 --- a/templates/admin/default/assets/bootstrap-datepicker/js/bootstrap-datepicker.js +++ b/templates/admin/default/assets/bootstrap-datepicker/js/bootstrap-datepicker.js @@ -1,474 +1,474 @@ -/* ========================================================= - * bootstrap-datepicker.js - * http://www.eyecon.ro/bootstrap-datepicker - * ========================================================= - * Copyright 2012 Stefan Petre - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ========================================================= */ - -!function( $ ) { - - // Picker object - - var Datepicker = function(element, options){ - this.element = $(element); - this.format = DPGlobal.parseFormat(options.format||this.element.data('date-format')||'mm/dd/yyyy'); - this.picker = $(DPGlobal.template) - .appendTo('body') - .on({ - click: $.proxy(this.click, this)//, - //mousedown: $.proxy(this.mousedown, this) - }); - this.isInput = this.element.is('input'); - this.component = this.element.is('.date') ? this.element.find('.add-on') : false; - - if (this.isInput) { - this.element.on({ - focus: $.proxy(this.show, this), - //blur: $.proxy(this.hide, this), - keyup: $.proxy(this.update, this) - }); - } else { - if (this.component){ - this.component.on('click', $.proxy(this.show, this)); - } else { - this.element.on('click', $.proxy(this.show, this)); - } - } - - this.minViewMode = options.minViewMode||this.element.data('date-minviewmode')||0; - if (typeof this.minViewMode === 'string') { - switch (this.minViewMode) { - case 'months': - this.minViewMode = 1; - break; - case 'years': - this.minViewMode = 2; - break; - default: - this.minViewMode = 0; - break; - } - } - this.viewMode = options.viewMode||this.element.data('date-viewmode')||0; - if (typeof this.viewMode === 'string') { - switch (this.viewMode) { - case 'months': - this.viewMode = 1; - break; - case 'years': - this.viewMode = 2; - break; - default: - this.viewMode = 0; - break; - } - } - this.startViewMode = this.viewMode; - this.weekStart = options.weekStart||this.element.data('date-weekstart')||0; - this.weekEnd = this.weekStart === 0 ? 6 : this.weekStart - 1; - this.onRender = options.onRender; - this.fillDow(); - this.fillMonths(); - this.update(); - this.showMode(); - }; - - Datepicker.prototype = { - constructor: Datepicker, - - show: function(e) { - this.picker.show(); - this.height = this.component ? this.component.outerHeight() : this.element.outerHeight(); - this.place(); - $(window).on('resize', $.proxy(this.place, this)); - if (e ) { - e.stopPropagation(); - e.preventDefault(); - } - if (!this.isInput) { - } - var that = this; - $(document).on('mousedown', function(ev){ - if ($(ev.target).closest('.datepicker').length == 0) { - that.hide(); - } - }); - this.element.trigger({ - type: 'show', - date: this.date - }); - }, - - hide: function(){ - this.picker.hide(); - $(window).off('resize', this.place); - this.viewMode = this.startViewMode; - this.showMode(); - if (!this.isInput) { - $(document).off('mousedown', this.hide); - } - //this.set(); - this.element.trigger({ - type: 'hide', - date: this.date - }); - }, - - set: function() { - var formated = DPGlobal.formatDate(this.date, this.format); - if (!this.isInput) { - if (this.component){ - this.element.find('input').prop('value', formated); - } - this.element.data('date', formated); - } else { - this.element.prop('value', formated); - } - }, - - setValue: function(newDate) { - if (typeof newDate === 'string') { - this.date = DPGlobal.parseDate(newDate, this.format); - } else { - this.date = new Date(newDate); - } - this.set(); - this.viewDate = new Date(this.date.getFullYear(), this.date.getMonth(), 1, 0, 0, 0, 0); - this.fill(); - }, - - place: function(){ - var offset = this.component ? this.component.offset() : this.element.offset(); - this.picker.css({ - top: offset.top + this.height, - left: offset.left - }); - }, - - update: function(newDate){ - this.date = DPGlobal.parseDate( - typeof newDate === 'string' ? newDate : (this.isInput ? this.element.prop('value') : this.element.data('date')), - this.format - ); - this.viewDate = new Date(this.date.getFullYear(), this.date.getMonth(), 1, 0, 0, 0, 0); - this.fill(); - }, - - fillDow: function(){ - var dowCnt = this.weekStart; - var html = ''; - while (dowCnt < this.weekStart + 7) { - html += ''+DPGlobal.dates.daysMin[(dowCnt++)%7]+''; - } - html += ''; - this.picker.find('.datepicker-days thead').append(html); - }, - - fillMonths: function(){ - var html = ''; - var i = 0 - while (i < 12) { - html += ''+DPGlobal.dates.monthsShort[i++]+''; - } - this.picker.find('.datepicker-months td').append(html); - }, - - fill: function() { - var d = new Date(this.viewDate), - year = d.getFullYear(), - month = d.getMonth(), - currentDate = this.date.valueOf(); - this.picker.find('.datepicker-days th:eq(1)') - .text(DPGlobal.dates.months[month]+' '+year); - var prevMonth = new Date(year, month-1, 28,0,0,0,0), - day = DPGlobal.getDaysInMonth(prevMonth.getFullYear(), prevMonth.getMonth()); - prevMonth.setDate(day); - prevMonth.setDate(day - (prevMonth.getDay() - this.weekStart + 7)%7); - var nextMonth = new Date(prevMonth); - nextMonth.setDate(nextMonth.getDate() + 42); - nextMonth = nextMonth.valueOf(); - var html = []; - var clsName, - prevY, - prevM; - while(prevMonth.valueOf() < nextMonth) { - if (prevMonth.getDay() === this.weekStart) { - html.push(''); - } - clsName = this.onRender(prevMonth); - prevY = prevMonth.getFullYear(); - prevM = prevMonth.getMonth(); - if ((prevM < month && prevY === year) || prevY < year) { - clsName += ' old'; - } else if ((prevM > month && prevY === year) || prevY > year) { - clsName += ' new'; - } - if (prevMonth.valueOf() === currentDate) { - clsName += ' active'; - } - html.push(''+prevMonth.getDate() + ''); - if (prevMonth.getDay() === this.weekEnd) { - html.push(''); - } - prevMonth.setDate(prevMonth.getDate()+1); - } - this.picker.find('.datepicker-days tbody').empty().append(html.join('')); - var currentYear = this.date.getFullYear(); - - var months = this.picker.find('.datepicker-months') - .find('th:eq(1)') - .text(year) - .end() - .find('span').removeClass('active'); - if (currentYear === year) { - months.eq(this.date.getMonth()).addClass('active'); - } - - html = ''; - year = parseInt(year/10, 10) * 10; - var yearCont = this.picker.find('.datepicker-years') - .find('th:eq(1)') - .text(year + '-' + (year + 9)) - .end() - .find('td'); - year -= 1; - for (var i = -1; i < 11; i++) { - html += ''+year+''; - year += 1; - } - yearCont.html(html); - }, - - click: function(e) { - e.stopPropagation(); - e.preventDefault(); - var target = $(e.target).closest('span, td, th'); - if (target.length === 1) { - switch(target[0].nodeName.toLowerCase()) { - case 'th': - switch(target[0].className) { - case 'switch': - this.showMode(1); - break; - case 'prev': - case 'next': - this.viewDate['set'+DPGlobal.modes[this.viewMode].navFnc].call( - this.viewDate, - this.viewDate['get'+DPGlobal.modes[this.viewMode].navFnc].call(this.viewDate) + - DPGlobal.modes[this.viewMode].navStep * (target[0].className === 'prev' ? -1 : 1) - ); - this.fill(); - this.set(); - break; - } - break; - case 'span': - if (target.is('.month')) { - var month = target.parent().find('span').index(target); - this.viewDate.setMonth(month); - } else { - var year = parseInt(target.text(), 10)||0; - this.viewDate.setFullYear(year); - } - if (this.viewMode !== 0) { - this.date = new Date(this.viewDate); - this.element.trigger({ - type: 'changeDate', - date: this.date, - viewMode: DPGlobal.modes[this.viewMode].clsName - }); - } - this.showMode(-1); - this.fill(); - this.set(); - break; - case 'td': - if (target.is('.day') && !target.is('.disabled')){ - var day = parseInt(target.text(), 10)||1; - var month = this.viewDate.getMonth(); - if (target.is('.old')) { - month -= 1; - } else if (target.is('.new')) { - month += 1; - } - var year = this.viewDate.getFullYear(); - this.date = new Date(year, month, day,0,0,0,0); - this.viewDate = new Date(year, month, Math.min(28, day),0,0,0,0); - this.fill(); - this.set(); - this.element.trigger({ - type: 'changeDate', - date: this.date, - viewMode: DPGlobal.modes[this.viewMode].clsName - }); - } - break; - } - } - }, - - mousedown: function(e){ - e.stopPropagation(); - e.preventDefault(); - }, - - showMode: function(dir) { - if (dir) { - this.viewMode = Math.max(this.minViewMode, Math.min(2, this.viewMode + dir)); - } - this.picker.find('>div').hide().filter('.datepicker-'+DPGlobal.modes[this.viewMode].clsName).show(); - } - }; - - $.fn.datepicker = function ( option, val ) { - return this.each(function () { - var $this = $(this), - data = $this.data('datepicker'), - options = typeof option === 'object' && option; - if (!data) { - $this.data('datepicker', (data = new Datepicker(this, $.extend({}, $.fn.datepicker.defaults,options)))); - } - if (typeof option === 'string') data[option](val); - }); - }; - - $.fn.datepicker.defaults = { - onRender: function(date) { - return ''; - } - }; - $.fn.datepicker.Constructor = Datepicker; - - var DPGlobal = { - modes: [ - { - clsName: 'days', - navFnc: 'Month', - navStep: 1 - }, - { - clsName: 'months', - navFnc: 'FullYear', - navStep: 1 - }, - { - clsName: 'years', - navFnc: 'FullYear', - navStep: 10 - }], - dates:{ - days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"], - daysShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"], - daysMin: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"], - months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"], - monthsShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"] - }, - isLeapYear: function (year) { - return (((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0)) - }, - getDaysInMonth: function (year, month) { - return [31, (DPGlobal.isLeapYear(year) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month] - }, - parseFormat: function(format){ - var separator = format.match(/[.\/\-\s].*?/), - parts = format.split(/\W+/); - if (!separator || !parts || parts.length === 0){ - throw new Error("Invalid date format."); - } - return {separator: separator, parts: parts}; - }, - parseDate: function(date, format) { - var parts = date.split(format.separator), - date = new Date(), - val; - date.setHours(0); - date.setMinutes(0); - date.setSeconds(0); - date.setMilliseconds(0); - if (parts.length === format.parts.length) { - var year = date.getFullYear(), day = date.getDate(), month = date.getMonth(); - for (var i=0, cnt = format.parts.length; i < cnt; i++) { - val = parseInt(parts[i], 10)||1; - switch(format.parts[i]) { - case 'dd': - case 'd': - day = val; - date.setDate(val); - break; - case 'mm': - case 'm': - month = val - 1; - date.setMonth(val - 1); - break; - case 'yy': - year = 2000 + val; - date.setFullYear(2000 + val); - break; - case 'yyyy': - year = val; - date.setFullYear(val); - break; - } - } - date = new Date(year, month, day, 0 ,0 ,0); - } - return date; - }, - formatDate: function(date, format){ - var val = { - d: date.getDate(), - m: date.getMonth() + 1, - yy: date.getFullYear().toString().substring(2), - yyyy: date.getFullYear() - }; - val.dd = (val.d < 10 ? '0' : '') + val.d; - val.mm = (val.m < 10 ? '0' : '') + val.m; - var date = []; - for (var i=0, cnt = format.parts.length; i < cnt; i++) { - date.push(val[format.parts[i]]); - } - return date.join(format.separator); - }, - headTemplate: ''+ - ''+ - '‹'+ - ''+ - '›'+ - ''+ - '', - contTemplate: '' - }; - DPGlobal.template = ''; - -}( window.jQuery ); \ No newline at end of file +///* ========================================================= +// * bootstrap-datepicker.js +// * http://www.eyecon.ro/bootstrap-datepicker +// * ========================================================= +// * Copyright 2012 Stefan Petre +// * +// * Licensed under the Apache License, Version 2.0 (the "License"); +// * you may not use this file except in compliance with the License. +// * You may obtain a copy of the License at +// * +// * http://www.apache.org/licenses/LICENSE-2.0 +// * +// * Unless required by applicable law or agreed to in writing, software +// * distributed under the License is distributed on an "AS IS" BASIS, +// * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// * See the License for the specific language governing permissions and +// * limitations under the License. +// * ========================================================= */ +// +//!function( $ ) { +// +// // Picker object +// +// var Datepicker = function(element, options){ +// this.element = $(element); +// this.format = DPGlobal.parseFormat(options.format||this.element.data('date-format')||'mm/dd/yyyy'); +// this.picker = $(DPGlobal.template) +// .appendTo('body') +// .on({ +// click: $.proxy(this.click, this)//, +// //mousedown: $.proxy(this.mousedown, this) +// }); +// this.isInput = this.element.is('input'); +// this.component = this.element.is('.date') ? this.element.find('.add-on') : false; +// +// if (this.isInput) { +// this.element.on({ +// focus: $.proxy(this.show, this), +// //blur: $.proxy(this.hide, this), +// keyup: $.proxy(this.update, this) +// }); +// } else { +// if (this.component){ +// this.component.on('click', $.proxy(this.show, this)); +// } else { +// this.element.on('click', $.proxy(this.show, this)); +// } +// } +// +// this.minViewMode = options.minViewMode||this.element.data('date-minviewmode')||0; +// if (typeof this.minViewMode === 'string') { +// switch (this.minViewMode) { +// case 'months': +// this.minViewMode = 1; +// break; +// case 'years': +// this.minViewMode = 2; +// break; +// default: +// this.minViewMode = 0; +// break; +// } +// } +// this.viewMode = options.viewMode||this.element.data('date-viewmode')||0; +// if (typeof this.viewMode === 'string') { +// switch (this.viewMode) { +// case 'months': +// this.viewMode = 1; +// break; +// case 'years': +// this.viewMode = 2; +// break; +// default: +// this.viewMode = 0; +// break; +// } +// } +// this.startViewMode = this.viewMode; +// this.weekStart = options.weekStart||this.element.data('date-weekstart')||0; +// this.weekEnd = this.weekStart === 0 ? 6 : this.weekStart - 1; +// this.onRender = options.onRender; +// this.fillDow(); +// this.fillMonths(); +// this.update(); +// this.showMode(); +// }; +// +// Datepicker.prototype = { +// constructor: Datepicker, +// +// show: function(e) { +// this.picker.show(); +// this.height = this.component ? this.component.outerHeight() : this.element.outerHeight(); +// this.place(); +// $(window).on('resize', $.proxy(this.place, this)); +// if (e ) { +// e.stopPropagation(); +// e.preventDefault(); +// } +// if (!this.isInput) { +// } +// var that = this; +// $(document).on('mousedown', function(ev){ +// if ($(ev.target).closest('.datepicker').length == 0) { +// that.hide(); +// } +// }); +// this.element.trigger({ +// type: 'show', +// date: this.date +// }); +// }, +// +// hide: function(){ +// this.picker.hide(); +// $(window).off('resize', this.place); +// this.viewMode = this.startViewMode; +// this.showMode(); +// if (!this.isInput) { +// $(document).off('mousedown', this.hide); +// } +// //this.set(); +// this.element.trigger({ +// type: 'hide', +// date: this.date +// }); +// }, +// +// set: function() { +// var formated = DPGlobal.formatDate(this.date, this.format); +// if (!this.isInput) { +// if (this.component){ +// this.element.find('input').prop('value', formated); +// } +// this.element.data('date', formated); +// } else { +// this.element.prop('value', formated); +// } +// }, +// +// setValue: function(newDate) { +// if (typeof newDate === 'string') { +// this.date = DPGlobal.parseDate(newDate, this.format); +// } else { +// this.date = new Date(newDate); +// } +// this.set(); +// this.viewDate = new Date(this.date.getFullYear(), this.date.getMonth(), 1, 0, 0, 0, 0); +// this.fill(); +// }, +// +// place: function(){ +// var offset = this.component ? this.component.offset() : this.element.offset(); +// this.picker.css({ +// top: offset.top + this.height, +// left: offset.left +// }); +// }, +// +// update: function(newDate){ +// this.date = DPGlobal.parseDate( +// typeof newDate === 'string' ? newDate : (this.isInput ? this.element.prop('value') : this.element.data('date')), +// this.format +// ); +// this.viewDate = new Date(this.date.getFullYear(), this.date.getMonth(), 1, 0, 0, 0, 0); +// this.fill(); +// }, +// +// fillDow: function(){ +// var dowCnt = this.weekStart; +// var html = ''; +// while (dowCnt < this.weekStart + 7) { +// html += ''+DPGlobal.dates.daysMin[(dowCnt++)%7]+''; +// } +// html += ''; +// this.picker.find('.datepicker-days thead').append(html); +// }, +// +// fillMonths: function(){ +// var html = ''; +// var i = 0 +// while (i < 12) { +// html += ''+DPGlobal.dates.monthsShort[i++]+''; +// } +// this.picker.find('.datepicker-months td').append(html); +// }, +// +// fill: function() { +// var d = new Date(this.viewDate), +// year = d.getFullYear(), +// month = d.getMonth(), +// currentDate = this.date.valueOf(); +// this.picker.find('.datepicker-days th:eq(1)') +// .text(DPGlobal.dates.months[month]+' '+year); +// var prevMonth = new Date(year, month-1, 28,0,0,0,0), +// day = DPGlobal.getDaysInMonth(prevMonth.getFullYear(), prevMonth.getMonth()); +// prevMonth.setDate(day); +// prevMonth.setDate(day - (prevMonth.getDay() - this.weekStart + 7)%7); +// var nextMonth = new Date(prevMonth); +// nextMonth.setDate(nextMonth.getDate() + 42); +// nextMonth = nextMonth.valueOf(); +// var html = []; +// var clsName, +// prevY, +// prevM; +// while(prevMonth.valueOf() < nextMonth) { +// if (prevMonth.getDay() === this.weekStart) { +// html.push(''); +// } +// clsName = this.onRender(prevMonth); +// prevY = prevMonth.getFullYear(); +// prevM = prevMonth.getMonth(); +// if ((prevM < month && prevY === year) || prevY < year) { +// clsName += ' old'; +// } else if ((prevM > month && prevY === year) || prevY > year) { +// clsName += ' new'; +// } +// if (prevMonth.valueOf() === currentDate) { +// clsName += ' active'; +// } +// html.push(''+prevMonth.getDate() + ''); +// if (prevMonth.getDay() === this.weekEnd) { +// html.push(''); +// } +// prevMonth.setDate(prevMonth.getDate()+1); +// } +// this.picker.find('.datepicker-days tbody').empty().append(html.join('')); +// var currentYear = this.date.getFullYear(); +// +// var months = this.picker.find('.datepicker-months') +// .find('th:eq(1)') +// .text(year) +// .end() +// .find('span').removeClass('active'); +// if (currentYear === year) { +// months.eq(this.date.getMonth()).addClass('active'); +// } +// +// html = ''; +// year = parseInt(year/10, 10) * 10; +// var yearCont = this.picker.find('.datepicker-years') +// .find('th:eq(1)') +// .text(year + '-' + (year + 9)) +// .end() +// .find('td'); +// year -= 1; +// for (var i = -1; i < 11; i++) { +// html += ''+year+''; +// year += 1; +// } +// yearCont.html(html); +// }, +// +// click: function(e) { +// e.stopPropagation(); +// e.preventDefault(); +// var target = $(e.target).closest('span, td, th'); +// if (target.length === 1) { +// switch(target[0].nodeName.toLowerCase()) { +// case 'th': +// switch(target[0].className) { +// case 'switch': +// this.showMode(1); +// break; +// case 'prev': +// case 'next': +// this.viewDate['set'+DPGlobal.modes[this.viewMode].navFnc].call( +// this.viewDate, +// this.viewDate['get'+DPGlobal.modes[this.viewMode].navFnc].call(this.viewDate) + +// DPGlobal.modes[this.viewMode].navStep * (target[0].className === 'prev' ? -1 : 1) +// ); +// this.fill(); +// this.set(); +// break; +// } +// break; +// case 'span': +// if (target.is('.month')) { +// var month = target.parent().find('span').index(target); +// this.viewDate.setMonth(month); +// } else { +// var year = parseInt(target.text(), 10)||0; +// this.viewDate.setFullYear(year); +// } +// if (this.viewMode !== 0) { +// this.date = new Date(this.viewDate); +// this.element.trigger({ +// type: 'changeDate', +// date: this.date, +// viewMode: DPGlobal.modes[this.viewMode].clsName +// }); +// } +// this.showMode(-1); +// this.fill(); +// this.set(); +// break; +// case 'td': +// if (target.is('.day') && !target.is('.disabled')){ +// var day = parseInt(target.text(), 10)||1; +// var month = this.viewDate.getMonth(); +// if (target.is('.old')) { +// month -= 1; +// } else if (target.is('.new')) { +// month += 1; +// } +// var year = this.viewDate.getFullYear(); +// this.date = new Date(year, month, day,0,0,0,0); +// this.viewDate = new Date(year, month, Math.min(28, day),0,0,0,0); +// this.fill(); +// this.set(); +// this.element.trigger({ +// type: 'changeDate', +// date: this.date, +// viewMode: DPGlobal.modes[this.viewMode].clsName +// }); +// } +// break; +// } +// } +// }, +// +// mousedown: function(e){ +// e.stopPropagation(); +// e.preventDefault(); +// }, +// +// showMode: function(dir) { +// if (dir) { +// this.viewMode = Math.max(this.minViewMode, Math.min(2, this.viewMode + dir)); +// } +// this.picker.find('>div').hide().filter('.datepicker-'+DPGlobal.modes[this.viewMode].clsName).show(); +// } +// }; +// +// $.fn.datepicker = function ( option, val ) { +// return this.each(function () { +// var $this = $(this), +// data = $this.data('datepicker'), +// options = typeof option === 'object' && option; +// if (!data) { +// $this.data('datepicker', (data = new Datepicker(this, $.extend({}, $.fn.datepicker.defaults,options)))); +// } +// if (typeof option === 'string') data[option](val); +// }); +// }; +// +// $.fn.datepicker.defaults = { +// onRender: function(date) { +// return ''; +// } +// }; +// $.fn.datepicker.Constructor = Datepicker; +// +// var DPGlobal = { +// modes: [ +// { +// clsName: 'days', +// navFnc: 'Month', +// navStep: 1 +// }, +// { +// clsName: 'months', +// navFnc: 'FullYear', +// navStep: 1 +// }, +// { +// clsName: 'years', +// navFnc: 'FullYear', +// navStep: 10 +// }], +// dates:{ +// days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"], +// daysShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"], +// daysMin: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"], +// months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"], +// monthsShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"] +// }, +// isLeapYear: function (year) { +// return (((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0)) +// }, +// getDaysInMonth: function (year, month) { +// return [31, (DPGlobal.isLeapYear(year) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month] +// }, +// parseFormat: function(format){ +// var separator = format.match(/[.\/\-\s].*?/), +// parts = format.split(/\W+/); +// if (!separator || !parts || parts.length === 0){ +// throw new Error("Invalid date format."); +// } +// return {separator: separator, parts: parts}; +// }, +// parseDate: function(date, format) { +// var parts = date.split(format.separator), +// date = new Date(), +// val; +// date.setHours(0); +// date.setMinutes(0); +// date.setSeconds(0); +// date.setMilliseconds(0); +// if (parts.length === format.parts.length) { +// var year = date.getFullYear(), day = date.getDate(), month = date.getMonth(); +// for (var i=0, cnt = format.parts.length; i < cnt; i++) { +// val = parseInt(parts[i], 10)||1; +// switch(format.parts[i]) { +// case 'dd': +// case 'd': +// day = val; +// date.setDate(val); +// break; +// case 'mm': +// case 'm': +// month = val - 1; +// date.setMonth(val - 1); +// break; +// case 'yy': +// year = 2000 + val; +// date.setFullYear(2000 + val); +// break; +// case 'yyyy': +// year = val; +// date.setFullYear(val); +// break; +// } +// } +// date = new Date(year, month, day, 0 ,0 ,0); +// } +// return date; +// }, +// formatDate: function(date, format){ +// var val = { +// d: date.getDate(), +// m: date.getMonth() + 1, +// yy: date.getFullYear().toString().substring(2), +// yyyy: date.getFullYear() +// }; +// val.dd = (val.d < 10 ? '0' : '') + val.d; +// val.mm = (val.m < 10 ? '0' : '') + val.m; +// var date = []; +// for (var i=0, cnt = format.parts.length; i < cnt; i++) { +// date.push(val[format.parts[i]]); +// } +// return date.join(format.separator); +// }, +// headTemplate: ''+ +// ''+ +// '‹'+ +// ''+ +// '›'+ +// ''+ +// '', +// contTemplate: '' +// }; +// DPGlobal.template = ''; +// +//}( window.jQuery ); \ No newline at end of file diff --git a/templates/admin/default/assets/js/coupon.js b/templates/admin/default/assets/js/coupon.js index 5c52aa097..41e0c1430 100644 --- a/templates/admin/default/assets/js/coupon.js +++ b/templates/admin/default/assets/js/coupon.js @@ -22,17 +22,15 @@ $(function($){ }; // Add 1 Rule / or update the temporary Rules array then Save Rules via AJAX - couponManager.addRuleAjax = function(id) { - console.log('addRuleAjax '+ id); + couponManager.createOrUpdateRuleAjax = function() { + var id = couponManager.ruleToUpdateId; // 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; + couponManager.ruleToUpdateId = false; } // Save @@ -40,57 +38,54 @@ $(function($){ }; // 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]; + couponManager.updateRuleSelectAjax = function(id) { + couponManager.ruleToUpdateId = id; + couponManager.ruleToSave = couponManager.rulesToSave[id]; // Set the rule selector $("#category-rule option").filter(function() { - return $(this).val() == couponManager.ruleToUpdate.serviceId; + return $(this).val() == couponManager.ruleToSave.serviceId; }).prop('selected', true); // Force rule input refresh - couponManager.loadRuleInputs(couponManager.ruleToUpdate.serviceId, function() { + couponManager.loadRuleInputs(couponManager.ruleToSave.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) { + var id = couponManager.ruleToUpdateId; + if(id) { + couponManager.ruleToSave = couponManager.rulesToSave[id]; + } + + for (idName in couponManager.ruleToSave.operators) { // Setting idName operator select operatorId = idName + '-operator'; - $('#' + operatorId).val(couponManager.ruleToUpdate.operators[idName]); + $('#' + operatorId).val(couponManager.ruleToSave.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; + valueId = idName + '-value'; + $('#' + valueId).val(couponManager.ruleToSave.values[idName]); } }; // Save rules on click couponManager.onClickSaveRule = function() { $('#constraint-save-btn').on('click', function () { - couponManager.addRuleAjax(couponManager.ruleIdToUpdate); + if($('#category-rule').val() == 'thelia.constraint.rule.available_for_everyone') { + // @todo translate + modal + var r= confirm("Do you really want to set this coupon available to everyone ?"); + if (r == true) { + couponManager.createOrUpdateRuleAjax(); + } + } + }); }; couponManager.onClickSaveRule(); @@ -110,7 +105,7 @@ $(function($){ $('.constraint-update-btn').on('click', function (e) { e.preventDefault(); var $this = $(this); - couponManager.updateRuleAjax($this.attr('data-int')); + couponManager.updateRuleSelectAjax($this.attr('data-int')); // Hide row being updated $this.parent().parent().remove(); @@ -120,6 +115,8 @@ $(function($){ // Reload effect inputs when changing effect couponManager.onEffectChange = function() { + var optionSelected = $("option:selected", this); + $('#effectToolTip').html(optionSelected.attr("data-description")); $('#effect').on('change', function () { var optionSelected = $("option:selected", this); $('#effectToolTip').html(optionSelected.attr("data-description")); @@ -130,7 +127,7 @@ $(function($){ // Reload rule inputs when changing effect couponManager.onRuleChange = function() { $('#category-rule').on('change', function () { - couponManager.loadRuleInputs($(this).val(), function(ruleToSave) {}); + couponManager.loadRuleInputs($(this).val(), function() {}); }); }; couponManager.onRuleChange(); @@ -139,10 +136,37 @@ $(function($){ // var onInputsChange = function() // In AJAX response + // Set max usage to unlimited or not + couponManager.onUsageUnlimitedChange = function() { + if (!$('#max-usage').parent().hasClass('has-error')) { + $('#max-usage').hide().attr('value', '-1'); + $('#max-usage-label').hide(); + } + $('#is-unlimited').change(function(){ + var $this = $(this); + if ($this.is(':checked')) { + $('#max-usage').hide().attr('value', '-1'); + $('#max-usage-label').hide(); + } else { + $('#max-usage').show().val('').attr('value', ''); + $('#max-usage-label').show(); + } + }); + }; + couponManager.onUsageUnlimitedChange(); + }); // Rule to save var couponManager = {}; +// Rule to be saved couponManager.ruleToSave = {}; -couponManager.ruleIdToUpdate = false; \ No newline at end of file +couponManager.ruleToSave.serviceId = false; +couponManager.ruleToSave.operators = {}; +couponManager.ruleToSave.values = {}; +// Rules payload to save +couponManager.rulesToSave = []; +// Rule being updated id +couponManager.ruleToUpdateId = false; + diff --git a/templates/admin/default/assets/js/main.js b/templates/admin/default/assets/js/main.js index d472a22a9..094dfe623 100644 --- a/templates/admin/default/assets/js/main.js +++ b/templates/admin/default/assets/js/main.js @@ -40,34 +40,7 @@ }); }*/ - // -- Effect description - if($('[name=effect]').length){ - var $effectSelect = $('[name=effect]'), - $helpBlock = $effectSelect.next('.help-block'); - $effectSelect.change(function(){ - var description = $(this).find(":selected").data('description'); - $helpBlock.text(description); - }); - } - - // -- Max usage -- - if($('#is-unlimited').length){ - - if($('#is-unlimited').is(':checked')){ - $('#max-usage').hide().attr('value', '-1'); - } - - $('#is-unlimited').change(function(){ - if($('#is-unlimited').is(':checked')){ - $('#max-usage').hide().attr('value', '-1'); - } - else{ - $('#max-usage').show().val('').attr('value', ''); - } - }); - - } // -- Bootstrap tooltip -- if($('[rel="tooltip"]').length){ diff --git a/templates/admin/default/coupon-create.html b/templates/admin/default/coupon-create.html index e8fcb73f5..f8a0411e1 100755 --- a/templates/admin/default/coupon-create.html +++ b/templates/admin/default/coupon-create.html @@ -7,18 +7,19 @@ {form name="thelia.admin.coupon.creation"} {include file='coupon/form.html' formAction={url path={$formAction}} noRules=true} {/form} - {include file='includes/confirmation-modal.html'} @@ -33,9 +34,20 @@ {/javascripts} + {javascripts file='assets/js/json2.js'} + + {/javascripts} + + {javascripts file='assets/js/coupon.js'} + + {/javascripts} + + {**} + {**} + {/block} diff --git a/templates/admin/default/coupon-list.html b/templates/admin/default/coupon-list.html index e4a1d5e36..2eafde586 100755 --- a/templates/admin/default/coupon-list.html +++ b/templates/admin/default/coupon-list.html @@ -7,70 +7,50 @@
    - - - - - + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + {loop type="coupon" name="list_coupon" is_enabled="1" backend_context="true"} + + + + + + + + {/loop}
    - List of enabled coupons + {intl l='Enabled coupons'}
    CodeTitleExpiration dateUsage leftActions{block name="coupon-label-code"}{intl l='Code'}{/block}{block name="coupon-label-title"}{intl l='Title'}{/block}{block name="coupon-label-expiration-date"}{intl l='Expiration date'}{/block}{block name="coupon-label-usage-left"}{intl l='Usage left'}{/block}{block name="coupon-label-action"}{/block}
    XMAS13Coupon for XMAS -30 €18/10/201349 - Edit - Disable -
    XMAS13Coupon for XMAS -30 €05/09/201320 - Edit - Disable -
    XMAS13Coupon for XMAS -30 €03/12/20139 - Edit - Disable -
    XMAS13Coupon for XMAS -30 €25/01/20134 - Edit - Disable -
    {block name="coupon-code"}{$CODE}{/block}{block name="coupon-title"}{$TITLE}{/block}{block name="coupon-expiration-date"}{$EXPIRATION_DATE}{/block}{block name="coupon-usage-left"}{$USAGE_LEFT}{/block} + {block name="coupon-action"} + + {intl l='Edit'} + + {/block} +
    @@ -80,58 +60,33 @@
    - - - - - + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + {loop type="coupon" name="list_coupon" is_enabled="0" backend_context="true"} + + + + + + + + {/loop}
    - List of disabled coupons + {intl l='Disabled coupons'}
    CodeTitleExpiration dateUsage leftActions{block name="coupon-label-code"}{intl l='Code'}{/block}{block name="coupon-label-title"}{intl l='Title'}{/block}{block name="coupon-label-expiration-date"}{intl l='Expiration date'}{/block}{block name="coupon-label-usage-left"}{intl l='Usage left'}{/block}{block name="coupon-label-action"}{/block}
    XMAS13Coupon for XMAS -30 €18/10/201349 - Edit - Enabled -
    XMAS13Coupon for XMAS -20 €05/09/201349 - Edit - Enabled -
    XMAS13Coupon for XMAS -50 €03/12/201349 - Edit - Enabled -
    XMAS13Coupon for XMAS -5 €25/01/201349 - Edit - Enabled -
    {block name="coupon-code"}{$CODE}{/block}{block name="coupon-title"}{$TITLE}{/block}{block name="coupon-expiration-date"}{$EXPIRATION_DATE}{/block}{block name="coupon-usage-left"}{$USAGE_LEFT}{/block} + {block name="coupon-action"} + + {intl l='Edit'} + + {/block} +
    @@ -139,9 +94,6 @@
    -{include file='includes/confirmation-modal.html' id="disable" message="{intl l='Do you really want to disable this element ?'}"} -{include file='includes/confirmation-modal.html' id="enable" message="{intl l='Do you really want to enable this element ?'}"} - {/block} diff --git a/templates/admin/default/coupon-read.html b/templates/admin/default/coupon-read.html index d0a86ac72..4ae5e5c68 100755 --- a/templates/admin/default/coupon-read.html +++ b/templates/admin/default/coupon-read.html @@ -4,112 +4,146 @@ {block name="main-content"}
    - + {loop type="coupon" name="read_coupon" id={$couponId} backend_context="true"} - {loop type="coupon" name="read_coupon" id={$couponId} backend_context="true"} - + -
    -
    +
    +
    -
    - - {if !$IS_ENABLED}{intl l='This coupon is disabled, you can enable to the bottom of this form.'}{/if} -
    + {if !$IS_ENABLED} +
    + + {intl l='This coupon is disabled, you can enable to the bottom of this form.'} +
    + {/if} - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + +
    {intl l='Title'}{$TITLE}
    {intl l='Expiration date'}{$EXPIRATION_DATE}
    {intl l='Usage left'} - {if $USAGE_LEFT} - - {$USAGE_LEFT} - - {else} - - 0 - - {/if} -
    {$SHORT_DESCRIPTION}
    {$DESCRIPTION}
    - {if $IS_CUMULATIVE} - - {intl l="May be cumulative"} - - {else} - - {intl l="Can't be cumulative"} - - {/if} -
    - {if $IS_REMOVING_POSTAGE} - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - -
    {intl l='Title'}{$TITLE}
    + {if $IS_ENABLED} + + {intl l="Is enabled"} + + {else} + + {intl l="Is disabled"} + + {/if} +
    + {$TOOLTIP} +
    {intl l='Amount'}{$AMOUNT}
    {intl l='Expiration date'}{$EXPIRATION_DATE} ({$DAY_LEFT_BEFORE_EXPIRATION} {intl l="days left"})
    {intl l='Usage left'} + {if $USAGE_LEFT} + + {$USAGE_LEFT} + + {else} + + 0 + + {/if} +
    + {if $IS_CUMULATIVE} + + {intl l="May be cumulative"} + + {else} + + {intl l="Can't be cumulative"} + + {/if} +
    + {if $IS_REMOVING_POSTAGE} + {intl l="Will remove postage"} - {else} - + {else} + {intl l="Won't remove postage"} - {/if} -
    {intl l='Amount'}{$AMOUNT}
    {intl l='Application field'} -
      - {foreach from=$APPLICATION_CONDITIONS item=rule name=rulesForeach} - {if !$smarty.foreach.rulesForeach.first} -
    • {intl l='And'}
    • - {/if} -
    • {$rule nofilter}
    • - {/foreach} -
    -
    {intl l='Actions'} - {intl l='Edit'} - {intl l='Enabled'} -
    - {/loop} - - + {/if} +
    + {if $IS_AVAILABLE_ON_SPECIAL_OFFERS} + + {intl l="Will be available on special offers"} + + {else} + + {intl l="Won't be available on special offers"} + + {/if} +
    {intl l='Application field'} +
      + {foreach from=$APPLICATION_CONDITIONS item=rule name=rulesForeach} + {if !$smarty.foreach.rulesForeach.first} +
    • {intl l='And'}
    • + {/if} +
    • {$rule nofilter}
    • + {/foreach} +
    +
    {$SHORT_DESCRIPTION}
    {$DESCRIPTION}
    + + {intl l='Edit'} + +
    +
    +
    + {/loop}
    {include file='includes/confirmation-modal.html' id="enable" message="{intl l='Do you really want to enable this element ?'}"} diff --git a/templates/admin/default/coupon-update.html b/templates/admin/default/coupon-update.html index 16771539a..0902dae4c 100755 --- a/templates/admin/default/coupon-update.html +++ b/templates/admin/default/coupon-update.html @@ -7,19 +7,20 @@ {form name="thelia.admin.coupon.creation"} {include file='coupon/form.html' formAction={url path={$formAction}} form=$form noRules=false} {/form} -
    {/block} @@ -71,8 +72,6 @@ // Save Rules AJAX couponManager.saveRuleAjax = function() { $('#constraint-add-operators-values').html('
    '); - console.log('about to save'); - console.log(couponManager.rulesToSave); var $url = '{$urlAjaxUpdateRules}'; $.ajax({ type: "POST", @@ -88,6 +87,11 @@ }).done(function(data) { $('#constraint-list').html(data); $('#constraint-add-operators-values').html(''); + // Set the rule selector + $("#category-rule option").filter(function() { + return $(this).val() == 'thelia.constraint.rule.available_for_everyone'; + }).prop('selected', true); + couponManager.onClickUpdateRule(); couponManager.onClickDeleteRule(); }); @@ -109,13 +113,22 @@ } }).done(function(data) { $('#constraint-add-operators-values').html(data); - + couponManager.ruleToSave.serviceId = ruleId; + if (ruleId == -1) { + // Placeholder can't be saved + $('#constraint-save-btn').hide(); + } else { + $('#constraint-save-btn').show(); + } return callBack(); }); }; // Rules which will be saved couponManager.rulesToSave = couponManager.initRules(); + + $('#constraint-save-btn').hide(); + }); {/block} diff --git a/templates/admin/default/coupon/form.html b/templates/admin/default/coupon/form.html index 5d30d201d..a4ec8b14a 100644 --- a/templates/admin/default/coupon/form.html +++ b/templates/admin/default/coupon/form.html @@ -11,152 +11,155 @@ {/form_field} {form_field form=$form field='success_url'} - + {/form_field}
    -
    - - {form_field form=$form field='code'} + {form_field form=$form field='code'} +
    + {if $error}{$message}{/if} - {/form_field} -
    +
    + {/form_field} -
    - - {form_field form=$form field='title'} + {form_field form=$form field='title'} +
    + {if $error}{$message}{/if} - {/form_field} -
    - -
    - -
    - -
    - -
    - -
    - -
    - -
    - -
    - -
    - -
    - {form_field form=$form field='expirationDate'} - - {if $error}{$message}{/if} - {/form_field} -
    -
    + {/form_field} -
    - - - {form_field form=$form field='maxUsage'} + {form_field form=$form field='isEnabled'} +
    + +
    + {/form_field} + + {form_field form=$form field='isAvailableOnSpecialOffers'} +
    + +
    + {/form_field} + + {form_field form=$form field='isCumulative'} +
    + +
    + {/form_field} + + {form_field form=$form field='isRemovingPostage'} +
    + +
    + {/form_field} + + {form_field form=$form field='expirationDate'} +
    + +
    + + {if $error}{$message}{/if} + +
    +
    + {/form_field} + + {form_field form=$form field='maxUsage'} +
    + + + {if $error}{$message}{/if} - {/form_field} -
    +
    + {/form_field}
    -
    - - {form_field form=$form field='effect'} + {form_field form=$form field='effect'} +
    + {if $error}{$message}{/if} - {/form_field} - {$availableCoupons.0.toolTip} -
    + {$availableCoupons.0.toolTip} +
    + {/form_field}
    -
    - - {form_field form=$form field='amount'} + {form_field form=$form field='amount'} +
    + {$value} + {if $error}{$message}{/if} - {/form_field} -
    -
    - +
    + {/form_field} + {*
    *} + {**} {*form_field form=$form field='category'*} - + {**} {*if $error}{$message}{/if}*} {*/form_field*} -
    + {*
    *}
    -
    - - {form_field form=$form field='shortDescription'} - + {form_field form=$form field='shortDescription'} +
    + + {if $error}{$message}{/if} - {/form_field} -
    +
    + {/form_field}
    -
    - - {form_field form=$form field='description'} + {form_field form=$form field='description'} +
    + {if $error}{$message}{/if} - {/form_field} -
    +
    + {/form_field} - +
    @@ -186,22 +189,23 @@
    - + {intl l='Save this rule'}
    - {foreach from=$input.availableOperators key=k item=availableOperator} + {foreach from=$input.availableOperators key=k item=availableOperator name=availableOperators} {/foreach} @@ -11,7 +11,7 @@
    {if $input.type == 'select'} @@ -72,12 +72,16 @@ + {/javascripts} + + +{/block} \ No newline at end of file diff --git a/templates/admin/default/features.html b/templates/admin/default/features.html new file mode 100644 index 000000000..69ed1d5d4 --- /dev/null +++ b/templates/admin/default/features.html @@ -0,0 +1,326 @@ +{extends file="admin-layout.tpl"} + +{block name="page-title"}{intl l='Thelia Product Features'}{/block} + +{block name="check-permissions"}admin.configuration.features.view{/block} + +{block name="main-content"} +
    + +
    + + + + {module_include location='features_top'} + +
    +
    + +
    + + + + + + + + + + + {module_include location='features_table_header'} + + + + + + + {loop name="list" type="feature" backend_context="1" lang=$lang_id order=$order} + + + + + + + + {module_include location='features_table_row'} + + + + {/loop} + + {elseloop rel="list"} + + + + {/elseloop} + +
    + {intl l='Thelia product features'} + + {loop type="auth" name="can_create" roles="ADMIN" permissions="admin.configuration.features.create"} + + + + {/loop} +
    + {admin_sortable_header + current_order=$order + order='id' + reverse_order='id_reverse' + path='/admin/configuration/features' + label="{intl l='ID'}" + } + + {admin_sortable_header + current_order=$order + order='alpha' + reverse_order='alpha_reverse' + path='/admin/configuration/features' + label="{intl l='Title'}" + } + + {admin_sortable_header + current_order=$order + order='manual' + reverse_order='manual_reverse' + path='/admin/configuration/features' + label="{intl l="Position"}" + } + {intl l="Actions"}
    {$ID} + {loop type="auth" name="can_change" roles="ADMIN" permissions="admin.configuration.features.change"} + {$TITLE} + {/loop} + {elseloop rel="can_change"} + {$TITLE} + {/elseloop} + + {admin_position_block + permission="admin.features.edit" + path="/admin/configuration/features/update-position" + url_parameter="feature_id" + in_place_edit_class="positionChange" + position="$POSITION" + id="$ID" + } + + {loop type="auth" name="can_change" roles="ADMIN" permissions="admin.configuration.features.change"} + + {/loop} + +
    + {loop type="auth" name="can_change" roles="ADMIN" permissions="admin.configuration.features.change"} + + {/loop} + + {loop type="auth" name="can_change" roles="ADMIN" permissions="admin.configuration.features.delete"} + + {/loop} +
    +
    +
    + {intl l="No product feature has been created yet. Click the + button to create one."} +
    +
    +
    + +
    +
    + + {module_include location='features_bottom'} + +
    +
    + +{* Adding a new feature *} + +{form name="thelia.admin.feature.creation"} + + {* Capture the dialog body, to pass it to the generic dialog *} + {capture "creation_dialog"} + {form_hidden_fields form=$form} + + {form_field form=$form field='success_url'} + {* on success, redirect to the edition page, _ID_ is replaced with the created feature ID, see controller *} + + {/form_field} + + {form_field form=$form field='title'} +
    + + + {loop type="lang" name="default-lang" default_only="1"} +
    + + {intl l=$TITLE} +
    + +
    {intl l="Enter here the feature name in the default language ($TITLE)"}
    + + {* Switch edition to the current locale *} + + + {form_field form=$form field='locale'} + + {/form_field} + {/loop} +
    + {/form_field} + + {form_field form=$form field='add_to_all'} +
    +
    + + {intl l='Check this box if you want to add this features to all product templates'} +
    +
    + {/form_field} + + {module_include location='feature_create_form'} + + {/capture} + + {include + file = "includes/generic-create-dialog.html" + + dialog_id = "creation_dialog" + dialog_title = {intl l="Create a new feature"} + dialog_body = {$smarty.capture.creation_dialog nofilter} + + dialog_ok_label = {intl l="Create this feature"} + + form_action = {url path='/admin/configuration/features/create'} + form_enctype = {form_enctype form=$form} + form_error_message = $form_error_message + } +{/form} + +{* Delete confirmation dialog *} + +{capture "delete_dialog"} + + + {module_include location='feature_delete_form'} + +{/capture} + +{include + file = "includes/generic-confirm-dialog.html" + + dialog_id = "delete_dialog" + dialog_title = {intl l="Delete feature"} + dialog_message = {intl l="Do you really want to delete this feature ? It will be removed from all product templates."} + + form_action = {url path='/admin/configuration/features/delete'} + form_content = {$smarty.capture.delete_dialog nofilter} +} + + +{* Add to all dialog *} + +{capture "add_to_all_dialog"} + + + {module_include location='feature_add_to_all_form'} + +{/capture} + +{include + file = "includes/generic-confirm-dialog.html" + + dialog_id = "add_to_all_dialog" + dialog_title = {intl l="Add to all product templates"} + dialog_message = {intl l="Do you really want to add this feature to all product templates ?"} + + form_action = {url path='/admin/configuration/features/add-to-all-templates'} + form_content = {$smarty.capture.add_to_all_dialog nofilter} +} + +{* Remove from all dialog *} + +{capture "remove_from_all_dialog"} + + + {module_include location='feature_add_to_all_form'} + +{/capture} + +{include + file = "includes/generic-confirm-dialog.html" + + dialog_id = "remove_from_all_dialog" + dialog_title = {intl l="Remove from all product templates"} + dialog_message = {intl l="Do you really want to remove this feature from all product templates ? You'll loose all product related data for this feature."} + + form_action = {url path='/admin/configuration/features/remove-from-all-templates'} + form_content = {$smarty.capture.remove_from_all_dialog nofilter} +} + +{/block} + +{block name="javascript-initialization"} + + {javascripts file='assets/js/bootstrap-editable/bootstrap-editable.js'} + + {/javascripts} + + +{/block} \ No newline at end of file diff --git a/templates/admin/default/includes/coupon_breadcrumb.html b/templates/admin/default/includes/coupon_breadcrumb.html deleted file mode 100755 index 878d9605d..000000000 --- a/templates/admin/default/includes/coupon_breadcrumb.html +++ /dev/null @@ -1,5 +0,0 @@ -{* Breadcrumb for coupon browsing and editing *} - -
  • Home
  • -
  • Coupon
  • -
  • Browse
  • \ No newline at end of file diff --git a/tests/functionnal/casperjs/exe/00_parameters.js b/tests/functionnal/casperjs/exe/00_parameters.js index a32ee89b5..df5470229 100644 --- a/tests/functionnal/casperjs/exe/00_parameters.js +++ b/tests/functionnal/casperjs/exe/00_parameters.js @@ -3,7 +3,7 @@ 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_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'; diff --git a/tests/functionnal/casperjs/exe/30_coupons.js b/tests/functionnal/casperjs/exe/30_coupons.js index 2ac04a759..2147c14cf 100644 --- a/tests/functionnal/casperjs/exe/30_coupons.js +++ b/tests/functionnal/casperjs/exe/30_coupons.js @@ -1,51 +1,151 @@ -casper.test.comment('Testing coupons'); +// +//var casper = require('casper').create({ +// viewportSize:{ +// width:1024, height:768 +// }, +// pageSettings:{ +// userAgent:'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_2) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.79 Safari/535.11' +// }, +// verbose:true +//}); +casper.test.comment('Testing coupons'); ////LIST // @todo implement ////CREATE -// @todo implement - -//UPDATE COUPON RULE -casper.start(thelia2_login_coupon_update_url, function() { +casper.start(thelia2_login_coupon_create_url, function() { + this.test.assertHttpStatus(200); + this.test.comment('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'); - 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'); + this.test.comment('COUPON - CREATE EMPTY'); - // Create rule + // Click on is unlimited button + this.click("form #is-unlimited"); + this.sendKeys('input#max-usage', '-2'); + + // cleaning expiration date default value this.evaluate(function() { - $('#category-rule').val('thelia.constraint.rule.available_for_x_articles').change(); + $("#expiration-date").val('').change(); return true; }); - this.capture('tests/functionnal/casperjs/screenshot/coupons/rule-selected.png'); + + this.capture('tests/functionnal/casperjs/screenshot/coupons/creating-new-coupon.png'); + this.click("form .control-group .btn.btn-default.btn-primary"); + }); casper.wait(1000, function() { this.echo("\nWaiting...."); }); +// Test Coupon creation if no input casper.then(function(){ - this.evaluate(function() { - $('#quantity-operator').val('>=').change(); - return true; - }); - this.sendKeys('input#quantity-value', '4'); - this.click('#constraint-save-btn'); + this.test.assertHttpStatus(200); + this.capture('tests/functionnal/casperjs/screenshot/coupons/created-new-empty-coupon.png'); + this.test.assertExists('.has-error #code', 'Error on code input found'); + this.test.assertExists('.has-error #title', 'Error on title input found'); + + this.test.assertExists('.has-error #expiration-date', 'Error on expiration date input found'); + this.test.assertExists('.has-error #max-usage', 'Error on max usage input found'); + this.test.assertExists('.has-error #description', 'Error on description input found'); + this.test.assertExists('.has-error #effect', 'Error on effect input found'); + this.test.assertExists('.has-error #amount', 'Error on amount input found'); + this.test.assertExists('.has-error #short-description', 'Error on short-description input found'); }); -casper.wait(1000, function() { +// Test Coupon creation if good input +casper.then(function(){ + + this.sendKeys('input#code', 'XMAS10'); + this.sendKeys('input#title', 'christmas'); + this.click("form #is-enabled"); + this.click("form #is-available-on-special-offers"); + this.click("form #is-cumulative"); + this.click("form #is-removing-postage"); + + this.evaluate(function() { + $("#expiration-date").val('2013-11-14').change(); + return true; + }); + + // Click on is unlimited button + this.click("form #is-unlimited"); + this.sendKeys('input#max-usage', '40'); + + this.evaluate(function() { + $('#effect').val('thelia.coupon.type.remove_x_amount').change(); + return true; + }); + + this.test.assertSelectorHasText( + '#effectToolTip', + this.evaluate(function () { + return $("#effect option[value^='thelia.coupon.type.remove_x_amount']").attr('data-description'); + }), + 'Tooltip found' + ); + this.sendKeys('input#amount', '42.12'); + this.sendKeys('#short-description', 'Mauris sed risus imperdiet, blandit arcu ac, tempus metus. Aliquam erat volutpat. Nullam dictum sed.'); + this.sendKeys('#description', 'Etiam sodales non nisi a condimentum. Morbi luctus mauris mattis sem ornare; ac blandit tortor porta! Sed vel viverra dolor. Nulla eget viverra eros. Donec rutrum felis ut quam blandit, eu massa nunc.'); + + this.capture('tests/functionnal/casperjs/screenshot/coupons/coupon-created-ready-to-be-saved.png'); + this.click("#save-coupon-btn"); +}); + +casper.wait(2000, function() { this.echo("\nWaiting...."); }); +// Test Coupon creation if good input is well saved 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'); -}); + this.test.assertHttpStatus(302); + this.test.comment('Now on : ' + this.getCurrentUrl()); + this.capture('tests/functionnal/casperjs/screenshot/coupons/created-new-coupon.png'); + this.test.assertField('thelia_coupon_creation[code]', 'XMAS10', 'Code found'); + this.test.assertField('thelia_coupon_creation[title]', 'christmas', 'Title found'); + this.test.assert(this.evaluate(function () { + return document.getElementById('is-enabled').checked; + }), 'Checkbox is enabled checked'); + this.test.assert(this.evaluate(function () { + return document.getElementById('is-available-on-special-offers').checked; + }), 'Checkbox is available on special offers checked'); + this.test.assert(this.evaluate(function () { + return document.getElementById('is-cumulative').checked; + }), 'Checkbox is cumulative checked'); + this.test.assert(this.evaluate(function () { + return document.getElementById('is-removing-postage').checked; + }), 'Checkbox is cumulative checked'); + + this.test.assertField('thelia_coupon_creation[expirationDate]', '2013-11-14', 'Expiration date found'); + this.test.assertField('thelia_coupon_creation[maxUsage]', '40', 'Max usage found'); + this.test.assert(this.evaluate(function () { + return !document.getElementById('is-unlimited').checked; + }), 'Checkbox is unlimited not checked'); + + this.test.assert( + this.evaluate(function () { + return $("#effect").val(); + }), + 'thelia.coupon.type.remove_x_amount', + 'Effect found' + ); + this.test.assertSelectorHasText( + '#effectToolTip', + this.evaluate(function () { + return $("#effect option[value^='thelia.coupon.type.remove_x_amount']").attr('data-description'); + }), + 'Tooltip found' + ); + this.test.assertField('thelia_coupon_creation[amount]', '42.12', 'Amount found'); + + this.test.assertField('thelia_coupon_creation[shortDescription]', 'Mauris sed risus imperdiet, blandit arcu ac, tempus metus. Aliquam erat volutpat. Nullam dictum sed.', 'Short description found'); + this.test.assertField('thelia_coupon_creation[description]', 'Etiam sodales non nisi a condimentum. Morbi luctus mauris mattis sem ornare; ac blandit tortor porta! Sed vel viverra dolor. Nulla eget viverra eros. Donec rutrum felis ut quam blandit, eu massa nunc.', 'Description found'); + + +}); ////EDIT CHECK // @todo implement diff --git a/tests/functionnal/casperjs/exe/31_coupons_rule.js b/tests/functionnal/casperjs/exe/31_coupons_rule.js new file mode 100644 index 000000000..66706aada --- /dev/null +++ b/tests/functionnal/casperjs/exe/31_coupons_rule.js @@ -0,0 +1,312 @@ +//// +////var casper = require('casper').create({ +//// viewportSize:{ +//// width:1024, height:768 +//// }, +//// pageSettings:{ +//// userAgent:'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_2) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.79 Safari/535.11' +//// }, +//// verbose:true +////}); +// +//casper.test.comment('Testing coupons rules'); +// +////UPDATE COUPON RULE +//casper.start(thelia2_login_coupon_update_url, function() { +// this.test.assertHttpStatus(200); +// this.test.comment('Now on : ' + this.getCurrentUrl()); +// this.capture('tests/functionnal/casperjs/screenshot/coupons/init.png'); +// this.test.comment('COUPON RULE - EDIT'); +// this.test.assertTitle('Update coupon - Thelia Back Office', 'Web page title OK'); +// this.test.assertSelectorHasText('tbody#constraint-list tr:nth-child(1)', 'If cart total amount is superior to 40 EUR','1) 1st default rule found'); +// this.test.assertSelectorHasText('tbody#constraint-list tr:nth-child(2)', 'If cart total amount is inferior to 400 EUR','1) 2nd default rule found'); +// +// // Create rule +// this.evaluate(function() { +// $('#category-rule').val('thelia.constraint.rule.available_for_x_articles').change(); +// return true; +// }); +// this.capture('tests/functionnal/casperjs/screenshot/coupons/rule-selected.png'); +//}); +// +//casper.wait(1000, function() { +// this.echo("\nWaiting...."); +//}); +// +//// Test Rule updating +//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(1)', 'If cart total amount is superior to 40 EUR','2) 1st default rule found'); +// this.test.assertSelectorHasText('tbody#constraint-list tr:nth-child(2)', 'If cart total amount is inferior to 400 EUR','2) 2nd default rule found'); +// this.test.assertSelectorHasText('tbody#constraint-list tr:nth-child(3)', ' If cart products quantity is superior or equal to 4','2) 3rd rule found'); +// +// // Click on Edit button +// this.click('tbody#constraint-list tr:nth-child(3) .constraint-update-btn'); +//}); +// +//casper.wait(2000, function() { +// this.echo("\nWaiting...."); +//}); +// +//casper.then(function(){ +// this.evaluate(function() { +// $('#quantity-operator').val('==').change(); +// return true; +// }); +// +// // Removing old value +//// casper.evaluate(function triggerKeyDownEvent() { +//// var e = $.Event("keydown"); +//// e.which = 8; +//// e.keyCode = 8; +//// $("#quantity-value").trigger(e); +//// }); +// this.evaluate(function() { +// $("#quantity-value").val('').change(); +// return true; +// }); +// +// // Adding new value +// this.sendKeys('#quantity-value', '5'); +// this.capture('tests/functionnal/casperjs/screenshot/coupons/rule-being-edited.png'); +// this.click('#constraint-save-btn'); +//}); +// +//casper.wait(2000, function() { +// this.echo("\nWaiting...."); +//}); +//// Check if updated rule has been saved and list refreshed +//casper.then(function(){ +// this.capture('tests/functionnal/casperjs/screenshot/coupons/rule-edited.png'); +// this.test.assertSelectorHasText('tbody#constraint-list tr:nth-child(1)', 'If cart total amount is superior to 40 EUR','3) 1st default rule found'); +// this.test.assertSelectorHasText('tbody#constraint-list tr:nth-child(2)', 'If cart total amount is inferior to 400 EUR','3) 2nd default rule found'); +// this.test.assertSelectorHasText('tbody#constraint-list tr:nth-child(3)', 'If cart products quantity is equal to 5','3) 3rd rule updated found'); +//}); +// +//// Check if updated rule has been well saved +//casper.thenOpen(thelia2_login_coupon_update_url, function() { +// this.test.assertHttpStatus(200); +// this.test.comment('Now on : ' + this.getCurrentUrl()); +// this.capture('tests/functionnal/casperjs/screenshot/coupons/rule-edited-refreshed.png'); +// this.test.assertSelectorHasText('tbody#constraint-list tr:nth-child(1)', 'If cart total amount is superior to 40 EUR','4) 1st default rule found'); +// this.test.assertSelectorHasText('tbody#constraint-list tr:nth-child(2)', 'If cart total amount is inferior to 400 EUR','4) 2nd default rule found'); +// this.test.assertSelectorHasText('tbody#constraint-list tr:nth-child(3)', 'If cart products quantity is equal to 5','4) 3rd rule updated found'); +// +// // Click on Delete button +// this.click('tbody#constraint-list tr:nth-child(2) .constraint-delete-btn'); +//}); +// +//casper.wait(2000, function() { +// this.echo("\nWaiting...."); +//}); +// +//casper.then(function(){ +// this.test.assertSelectorHasText('tbody#constraint-list tr:nth-child(1)', 'If cart total amount is superior to 40 EUR','5) 1st default rule found'); +// this.test.assertSelectorDoesntHaveText('tbody#constraint-list tr:nth-child(2)', 'If cart total amount is inferior to 400 EUR','5) 2nd default rule found'); +// this.test.assertSelectorHasText('tbody#constraint-list tr:nth-child(2)', 'If cart products quantity is equal to 5','5) 3rd rule updated found'); +//}); +// +//// Check if updated rule has been well saved +//casper.thenOpen(thelia2_login_coupon_update_url, function() { +// this.test.assertHttpStatus(200); +// this.test.comment('Now on : ' + this.getCurrentUrl()); +// this.capture('tests/functionnal/casperjs/screenshot/coupons/rule-deleted-refreshed.png'); +// this.test.assertSelectorHasText('tbody#constraint-list tr:nth-child(1)', 'If cart total amount is superior to 40 EUR','6) 1st default rule found'); +// this.test.assertSelectorDoesntHaveText('tbody#constraint-list tr:nth-child(2)', 'If cart total amount is inferior to 400 EUR','6) 2nd default rule found'); +// this.test.assertSelectorHasText('tbody#constraint-list tr:nth-child(2)', 'If cart products quantity is equal to 5','6) 3rd rule updated found'); +//}); +// +//// Test creating rule that won't be edited +//casper.then(function(){ +//// Create rule +// this.evaluate(function() { +// $('#category-rule').val('thelia.constraint.rule.available_for_total_amount').change(); +// return true; +// }); +// this.capture('tests/functionnal/casperjs/screenshot/coupons/rule-selected2.png'); +//}); +// +//casper.wait(2000, function() { +// this.echo("\nWaiting...."); +//}); +// +//// Test Rule creation +//casper.then(function(){ +// this.evaluate(function() { +// $('#price-operator').val('<=').change(); +// return true; +// }); +// // Removing old value +//// casper.evaluate(function triggerKeyDownEvent() { +//// var e = $.Event("keydown"); +//// e.which = 8; +//// e.keyCode = 8; +//// $("input#price-value").trigger(e); +//// }); +// this.evaluate(function() { +// $("input#price-value").val('').change(); +// return true; +// }); +// +// // Changing 400 to 401 +// this.sendKeys('input#price-value', '401'); +// this.evaluate(function() { +// $('#currency-value').val('GBP').change(); +// return true; +// }); +// this.capture('tests/functionnal/casperjs/screenshot/coupons/rule-saved-edited-before-click-save.png'); +// this.click('#constraint-save-btn'); +//}); +// +//casper.wait(2000, function() { +// this.echo("\nWaiting...."); +//}); +// +//casper.then(function(){ +// this.test.assertSelectorHasText('tbody#constraint-list tr:nth-child(1)', 'If cart total amount is superior to 40 EUR','7) 1st default rule found'); +// this.test.assertSelectorDoesntHaveText('tbody#constraint-list tr:nth-child(2)', 'If cart total amount is inferior to 400 EUR','7) 2nd default rule found'); +// this.test.assertSelectorHasText('tbody#constraint-list tr:nth-child(2)', 'If cart products quantity is equal to 5','7) 3rd rule updated found'); +// this.test.assertSelectorHasText('tbody#constraint-list tr:nth-child(3)', 'If cart total amount is inferior or equal to 401 GBP','7) 4rd rule created found'); +//}); +// +//// Check if created rule has been well saved +//casper.thenOpen(thelia2_login_coupon_update_url, function() { +// this.test.assertHttpStatus(200); +// this.test.comment('Now on : ' + this.getCurrentUrl()); +// this.capture('tests/functionnal/casperjs/screenshot/coupons/rule-added-refreshed.png'); +// this.test.assertSelectorHasText('tbody#constraint-list tr:nth-child(1)', 'If cart total amount is superior to 40 EUR','8) 1st default rule found'); +// this.test.assertSelectorDoesntHaveText('tbody#constraint-list tr:nth-child(2)', 'If cart total amount is inferior to 400 EUR','8) 2nd default rule found'); +// this.test.assertSelectorHasText('tbody#constraint-list tr:nth-child(2)', 'If cart products quantity is equal to 5','8) 3rd rule updated found'); +// this.test.assertSelectorHasText('tbody#constraint-list tr:nth-child(3)', 'If cart total amount is inferior or equal to 401 GBP','8) 4rd rule created found'); +//}); +// +//// Testing deleting all rules +//casper.then(function(){ +//// Click on Delete button +// this.click('tbody#constraint-list tr:nth-child(1) .constraint-delete-btn'); +//}); +//casper.wait(1000, function() { +// this.echo("\nWaiting...."); +//}); +//casper.then(function(){ +//// Click on Delete button +// this.click('tbody#constraint-list tr:nth-child(1) .constraint-delete-btn'); +//}); +//casper.wait(1000, function() { +// this.echo("\nWaiting...."); +//}); +//casper.then(function(){ +//// Click on Delete button +// this.click('tbody#constraint-list tr:nth-child(1) .constraint-delete-btn'); +//}); +//casper.wait(1000, function() { +// this.echo("\nWaiting...."); +//}); +//casper.then(function(){ +// this.capture('tests/functionnal/casperjs/screenshot/coupons/rule-all-deleted.png'); +// this.test.assertSelectorHasText('tbody#constraint-list tr:nth-child(1)', 'No conditions','9) 1st default rule found'); +// test.assertDoesntExist('tbody#constraint-list tr:nth-child(2)'); +//}); +// +//// Check if created rule has been well saved +//casper.thenOpen(thelia2_login_coupon_update_url, function() { +// this.test.assertHttpStatus(200); +// this.test.comment('Now on : ' + this.getCurrentUrl()); +// this.capture('tests/functionnal/casperjs/screenshot/coupons/rule-all-deleted-refreshed.png'); +// this.test.assertSelectorHasText('tbody#constraint-list tr:nth-child(1)', 'No conditions','10) 1st default rule found'); +// test.assertDoesntExist('tbody#constraint-list tr:nth-child(2)'); +//}); +// +// +//// Test add no condition rule +//casper.then(function(){ +// this.evaluate(function() { +// $('#category-rule').val('thelia.constraint.rule.available_for_x_articles').change(); +// return true; +// }); +//}); +// +//casper.wait(1000, function() { +// this.echo("\nWaiting...."); +//}); +// +//// Test Rule updating +//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-all-deleted.png'); +// this.test.assertSelectorHasText('tbody#constraint-list tr:nth-child(1)', 'If cart products quantity is superior to 4', '11) 1st default rule found'); +// test.assertDoesntExist('tbody#constraint-list tr:nth-child(2)'); +//}); +// +//// Check if created rule has been well saved +//casper.thenOpen(thelia2_login_coupon_update_url, function() { +// this.test.assertHttpStatus(200); +// this.test.comment('Now on : ' + this.getCurrentUrl()); +// this.capture('tests/functionnal/casperjs/screenshot/coupons/rule-all-deleted-refreshed.png'); +// this.test.assertSelectorHasText('tbody#constraint-list tr:nth-child(1)', 'If cart products quantity is superior to 4','12) 1st default rule found'); +// test.assertDoesntExist('tbody#constraint-list tr:nth-child(2)'); +//}); +// +//casper.then(function(){ +// this.evaluate(function() { +// $('#category-rule').val('thelia.constraint.rule.available_for_everyone').change(); +// return true; +// }); +//}); +// +//casper.wait(1000, function() { +// this.echo("\nWaiting...."); +//}); +// +//// Test Rule updating +//casper.then(function(){ +// this.click('#constraint-save-btn'); +//}); +// +//casper.wait(1000, function() { +// this.echo("\nWaiting...."); +//}); +//casper.then(function(){ +// this.capture('tests/functionnal/casperjs/screenshot/coupons/rule-all-deleted.png'); +// this.test.assertSelectorHasText('tbody#constraint-list tr:nth-child(1)', 'No conditions','13) 1st default rule found'); +// test.assertDoesntExist('tbody#constraint-list tr:nth-child(2)'); +//}); +// +//// Check if created rule has been well saved +//casper.thenOpen(thelia2_login_coupon_update_url, function() { +// this.test.assertHttpStatus(200); +// this.test.comment('Now on : ' + this.getCurrentUrl()); +// this.capture('tests/functionnal/casperjs/screenshot/coupons/rule-all-deleted-refreshed.png'); +// this.test.assertSelectorHasText('tbody#constraint-list tr:nth-child(1)', 'No conditions','14) 1st default rule found'); +// test.assertDoesntExist('tbody#constraint-list tr:nth-child(2)'); +//}); +// +////RUN +//casper.run(function() { +// this.test.done(); +//}); \ No newline at end of file