Conflicts:
	core/lib/Thelia/Config/Resources/routing/admin.xml
This commit is contained in:
mespeche
2013-09-16 11:01:00 +02:00
67 changed files with 5471 additions and 2489 deletions

3
.gitignore vendored
View File

@@ -24,4 +24,5 @@ phpdoc*.log
php-cs
xhprof/
phpunit.phar
.DS_Store
.DS_Store
phpmyadmin

View File

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

View File

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

View File

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

View File

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

View File

@@ -67,11 +67,21 @@
<tag name="kernel.event_subscriber"/>
</service>
<service id="thelia.action.feature" class="Thelia\Action\Feature">
<argument type="service" id="service_container"/>
<tag name="kernel.event_subscriber"/>
</service>
<service id="thelia.action.attributeav" class="Thelia\Action\AttributeAv">
<argument type="service" id="service_container"/>
<tag name="kernel.event_subscriber"/>
</service>
<service id="thelia.action.featureav" class="Thelia\Action\FeatureAv">
<argument type="service" id="service_container"/>
<tag name="kernel.event_subscriber"/>
</service>
<service id="thelia.action.httpException" class="Thelia\Action\HttpException">
<argument type="service" id="service_container"/>
<tag name="kernel.event_subscriber"/>

View File

@@ -72,8 +72,13 @@
<form name="thelia.admin.attribute.creation" class="Thelia\Form\AttributeCreationForm"/>
<form name="thelia.admin.attribute.modification" class="Thelia\Form\AttributeModificationForm"/>
<form name="thelia.admin.feature.creation" class="Thelia\Form\FeatureCreationForm"/>
<form name="thelia.admin.feature.modification" class="Thelia\Form\FeatureModificationForm"/>
<form name="thelia.admin.attributeav.creation" class="Thelia\Form\AttributeAvCreationForm"/>
<form name="thelia.admin.featureav.creation" class="Thelia\Form\FeatureAvCreationForm"/>
<form name="thelia.admin.template.creation" class="Thelia\Form\TemplateCreationForm"/>
<form name="thelia.admin.template.modification" class="Thelia\Form\TemplateModificationForm"/>
@@ -235,6 +240,8 @@
<service id="thelia.constraint.factory" class="Thelia\Constraint\ConstraintFactory">
<argument type="service" id="service_container" />
</service>
<service id="thelia.constraint.validator" class="Thelia\Constraint\ConstraintValidator">
</service>
<service id="thelia.constraint.rule.available_for_everyone" class="Thelia\Constraint\Rule\AvailableForEveryoneManager">
<argument type="service" id="thelia.adapter" />
<tag name="thelia.coupon.addRule"/>

View File

@@ -103,25 +103,27 @@
<!-- Route to the Coupon controller (process Coupon browsing) -->
<route id="admin.coupon.list" path="/admin/coupon">
<route id="admin.coupon.list" path="/admin/coupon/">
<default key="_controller">Thelia\Controller\Admin\CouponController::browseAction</default>
</route>
<route id="admin.coupon.create" path="/admin/coupon/create">
<route id="admin.coupon.create" path="/admin/coupon/create/">
<default key="_controller">Thelia\Controller\Admin\CouponController::createAction</default>
</route>
<route id="admin.coupon.update" path="/admin/coupon/update/{couponId}">
<route id="admin.coupon.update" path="/admin/coupon/update/{couponId}/">
<default key="_controller">Thelia\Controller\Admin\CouponController::updateAction</default>
</route>
<route id="admin.coupon.read" path="/admin/coupon/read/{couponId}">
<route id="admin.coupon.read" path="/admin/coupon/read/{couponId}/">
<default key="_controller">Thelia\Controller\Admin\CouponController::readAction</default>
</route>
<route id="admin.coupon.rule.input" path="/admin/coupon/rule/{ruleId}">
<route id="admin.coupon.rule.input" path="/admin/coupon/rule/{ruleId}/">
<default key="_controller">Thelia\Controller\Admin\CouponController::getRuleInputAction</default>
</route>
<route id="admin.coupon.rule.update" path="/admin/coupon/{couponId}/rule/update/">
<default key="_controller">Thelia\Controller\Admin\CouponController::updateRulesAction</default>
</route>
<route id="admin.coupon.consume" path="/admin/coupon/consume/{couponCode}/">
<default key="_controller">Thelia\Controller\Admin\CouponController::consumeAction</default>
</route>
<!-- Routes to the Config (system variables) controller -->
@@ -302,6 +304,63 @@
<!-- end countries routes management -->
<!-- feature and features value management -->
<route id="admin.configuration.features.default" path="/admin/configuration/features">
<default key="_controller">Thelia\Controller\Admin\FeatureController::defaultAction</default>
</route>
<route id="admin.configuration.features.create" path="/admin/configuration/features/create">
<default key="_controller">Thelia\Controller\Admin\FeatureController::createAction</default>
</route>
<route id="admin.configuration.features.update" path="/admin/configuration/features/update">
<default key="_controller">Thelia\Controller\Admin\FeatureController::updateAction</default>
</route>
<route id="admin.configuration.features.save" path="/admin/configuration/features/save">
<default key="_controller">Thelia\Controller\Admin\FeatureController::processUpdateAction</default>
</route>
<route id="admin.configuration.features.delete" path="/admin/configuration/features/delete">
<default key="_controller">Thelia\Controller\Admin\FeatureController::deleteAction</default>
</route>
<route id="admin.configuration.features.update-position" path="/admin/configuration/features/update-position">
<default key="_controller">Thelia\Controller\Admin\FeatureController::updatePositionAction</default>
</route>
<route id="admin.configuration.features.rem-from-all" path="/admin/configuration/features/remove-from-all-templates">
<default key="_controller">Thelia\Controller\Admin\FeatureController::removeFromAllTemplates</default>
</route>
<route id="admin.configuration.features.add-to-all" path="/admin/configuration/features/add-to-all-templates">
<default key="_controller">Thelia\Controller\Admin\FeatureController::addToAllTemplates</default>
</route>
<route id="admin.configuration.features-av.create" path="/admin/configuration/features-av/create">
<default key="_controller">Thelia\Controller\Admin\FeatureAvController::createAction</default>
</route>
<route id="admin.configuration.features-av.update" path="/admin/configuration/features-av/update">
<default key="_controller">Thelia\Controller\Admin\FeatureAvController::updateAction</default>
</route>
<route id="admin.configuration.features-av.save" path="/admin/configuration/features-av/save">
<default key="_controller">Thelia\Controller\Admin\FeatureAvController::processUpdateAction</default>
</route>
<route id="admin.configuration.features-av.delete" path="/admin/configuration/features-av/delete">
<default key="_controller">Thelia\Controller\Admin\FeatureAvController::deleteAction</default>
</route>
<route id="admin.configuration.features-av.update-position" path="/admin/configuration/features-av/update-position">
<default key="_controller">Thelia\Controller\Admin\FeatureAvController::updatePositionAction</default>
</route>
<!-- end feature and feature routes management -->
<!-- The default route, to display a template -->
<route id="admin.processTemplate" path="/admin/{template}">

View File

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

View File

@@ -52,7 +52,7 @@ class ConstraintValidator
*
* @return bool
*/
public function test(CouponRuleCollection $rules)
public function isMatching(CouponRuleCollection $rules)
{
$isMatching = true;
/** @var CouponRuleInterface $rule */

View File

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

View File

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

View File

@@ -82,6 +82,7 @@ abstract class CouponRuleAbstract implements CouponRuleInterface
{
$this->adapter = $adapter;
$this->translator = $adapter->getTranslator();
$this->constraintValidator = $adapter->getConstraintValidator();
}
// /**

View File

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

View File

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

View File

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

View File

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

View File

@@ -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()
{

View File

@@ -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 <gmorel@openstudio.fr>
*
*/
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;
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -155,4 +155,18 @@ interface CouponAdapterInterface
*/
public function getMainCurrency();
/**
* Return request
*
* @return Request
*/
public function getRequest();
/**
* Return Constraint Validator
*
* @return ConstraintValidator
*/
public function getConstraintValidator();
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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:
* <code>
* $query->filterByPromo(1234); // WHERE promo = 1234
* $query->filterByPromo(array(12, 34)); // WHERE promo IN (12, 34)
* $query->filterByPromo(array('min' => 12)); // WHERE promo > 12
* </code>
*
* @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
*

View File

@@ -76,7 +76,6 @@ class Coupon extends BaseCoupon
->setType($effect)
->setAmount($amount)
->setIsRemovingPostage($isRemovingPostage)
->setType($amount)
->setIsEnabled($isEnabled)
->setExpirationDate($expirationDate)
->setIsAvailableOnSpecialOffers($isAvailableOnSpecialOffers)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -146,7 +146,7 @@
{loop name="menu-auth-coupon" type="auth" roles="ADMIN" permissions="admin.coupon.view"}
<li class="{if $admin_current_location == 'coupon'}active{/if}" id="coupon_menu">
<a href="{url path='/admin/coupon-list'}">{intl l="Coupons"}</a>
<a href="{url path='/admin/coupon/'}">{intl l="Coupons"}</a>
</li>
{/loop}

View File

@@ -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 = '<tr>';
while (dowCnt < this.weekStart + 7) {
html += '<th class="dow">'+DPGlobal.dates.daysMin[(dowCnt++)%7]+'</th>';
}
html += '</tr>';
this.picker.find('.datepicker-days thead').append(html);
},
fillMonths: function(){
var html = '';
var i = 0
while (i < 12) {
html += '<span class="month">'+DPGlobal.dates.monthsShort[i++]+'</span>';
}
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('<tr>');
}
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('<td class="day '+clsName+'">'+prevMonth.getDate() + '</td>');
if (prevMonth.getDay() === this.weekEnd) {
html.push('</tr>');
}
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 += '<span class="year'+(i === -1 || i === 10 ? ' old' : '')+(currentYear === year ? ' active' : '')+'">'+year+'</span>';
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: '<thead>'+
'<tr>'+
'<th class="prev">&lsaquo;</th>'+
'<th colspan="5" class="switch"></th>'+
'<th class="next">&rsaquo;</th>'+
'</tr>'+
'</thead>',
contTemplate: '<tbody><tr><td colspan="7"></td></tr></tbody>'
};
DPGlobal.template = '<div class="datepicker dropdown-menu">'+
'<div class="datepicker-days">'+
'<table class=" table-condensed">'+
DPGlobal.headTemplate+
'<tbody></tbody>'+
'</table>'+
'</div>'+
'<div class="datepicker-months">'+
'<table class="table-condensed">'+
DPGlobal.headTemplate+
DPGlobal.contTemplate+
'</table>'+
'</div>'+
'<div class="datepicker-years">'+
'<table class="table-condensed">'+
DPGlobal.headTemplate+
DPGlobal.contTemplate+
'</table>'+
'</div>'+
'</div>';
}( window.jQuery );
///* =========================================================
// * 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 = '<tr>';
// while (dowCnt < this.weekStart + 7) {
// html += '<th class="dow">'+DPGlobal.dates.daysMin[(dowCnt++)%7]+'</th>';
// }
// html += '</tr>';
// this.picker.find('.datepicker-days thead').append(html);
// },
//
// fillMonths: function(){
// var html = '';
// var i = 0
// while (i < 12) {
// html += '<span class="month">'+DPGlobal.dates.monthsShort[i++]+'</span>';
// }
// 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('<tr>');
// }
// 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('<td class="day '+clsName+'">'+prevMonth.getDate() + '</td>');
// if (prevMonth.getDay() === this.weekEnd) {
// html.push('</tr>');
// }
// 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 += '<span class="year'+(i === -1 || i === 10 ? ' old' : '')+(currentYear === year ? ' active' : '')+'">'+year+'</span>';
// 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: '<thead>'+
// '<tr>'+
// '<th class="prev">&lsaquo;</th>'+
// '<th colspan="5" class="switch"></th>'+
// '<th class="next">&rsaquo;</th>'+
// '</tr>'+
// '</thead>',
// contTemplate: '<tbody><tr><td colspan="7"></td></tr></tbody>'
// };
// DPGlobal.template = '<div class="datepicker dropdown-menu">'+
// '<div class="datepicker-days">'+
// '<table class=" table-condensed">'+
// DPGlobal.headTemplate+
// '<tbody></tbody>'+
// '</table>'+
// '</div>'+
// '<div class="datepicker-months">'+
// '<table class="table-condensed">'+
// DPGlobal.headTemplate+
// DPGlobal.contTemplate+
// '</table>'+
// '</div>'+
// '<div class="datepicker-years">'+
// '<table class="table-condensed">'+
// DPGlobal.headTemplate+
// DPGlobal.contTemplate+
// '</table>'+
// '</div>'+
// '</div>';
//
//}( window.jQuery );

View File

@@ -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;
couponManager.ruleToSave.serviceId = false;
couponManager.ruleToSave.operators = {};
couponManager.ruleToSave.values = {};
// Rules payload to save
couponManager.rulesToSave = [];
// Rule being updated id
couponManager.ruleToUpdateId = false;

View File

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

View File

@@ -7,18 +7,19 @@
<nav>
<ul class="breadcrumb">
{include file="includes/coupon_breadcrumb.html"}
<li><a href="{url path='admin/home'}">{intl l='Home'}</a></li>
<li><a href="{url path='admin/coupon/'}">{intl l='Coupon'}</a></li>
<li>{intl l='Create'}</li>
</ul>
</nav>
<div class="page-header">
<h1>Coupons : <small>Add a coupon</small></h1>
<h1>{intl l='Coupons : '}<small>{intl l='Create a new coupon'}</small></h1>
</div>
{form name="thelia.admin.coupon.creation"}
{include file='coupon/form.html' formAction={url path={$formAction}} noRules=true}
{/form}
</section> <!-- #wrapper -->
{include file='includes/confirmation-modal.html'}
@@ -33,9 +34,20 @@
<script src="{$asset_url}"></script>
{/javascripts}
{javascripts file='assets/js/json2.js'}
<script src="{$asset_url}"></script>
{/javascripts}
{javascripts file='assets/js/coupon.js'}
<script src="{$asset_url}"></script>
{/javascripts}
{*<script src="http://code.jquery.com/ui/1.10.3/jquery-ui.js"></script>*}
{*<link rel="stylesheet" href="http://code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css" />*}
<script>
$(function($){
miniBrowser(0, '/test_to_remove/datas_coupon_edit.json');
{*$('.datepicker').datepicker({ dateFormat: "{$dateFormat}", defaultDate: +60, minDate: "+0m" });*}
});
</script>
{/block}

View File

@@ -7,70 +7,50 @@
<nav>
<ul class="breadcrumb">
{include file="includes/coupon_breadcrumb.html"}
<li><a href="{url path='admin/home'}">{intl l='Home'}</a></li>
<li><a href="{url path='admin/coupon/'}">{intl l='Coupon'}</a></li>
<li>{intl l='Browse'}</li>
</ul>
</nav>
<div class="page-header">
<h1>Coupons : <small>List of coupons</small></h1>
<h1>{intl l='Coupons : '}<small>{intl l='List'}</small></h1>
<a href="{$urlCreateCoupon}" class="btn btn-default btn-primary btn-medium">
<span class="glyphicon glyphicon-add"></span> {intl l='Create a new coupon'}
</a>
</div>
<section class="row">
<div class="col-md-12 general-block-decorator">
<table class="table table-striped tablesorter">
<caption>
List of enabled coupons
{intl l='Enabled coupons'}
</caption>
<thead>
<tr>
<th>Code</th>
<th>Title</th>
<th>Expiration date</th>
<th>Usage left</th>
<th class="sorter-false filter-false">Actions</th>
<th>{block name="coupon-label-code"}{intl l='Code'}{/block}</th>
<th>{block name="coupon-label-title"}{intl l='Title'}{/block}</th>
<th>{block name="coupon-label-expiration-date"}{intl l='Expiration date'}{/block}</th>
<th>{block name="coupon-label-usage-left"}{intl l='Usage left'}{/block}</th>
<th class="sorter-false filter-false">{block name="coupon-label-action"}{/block}</th>
</tr>
</thead>
<tbody>
<tr>
<td><a href="#">XMAS13</a></td>
<td>Coupon for XMAS -30 &euro;</td>
<td>18/10/2013</td>
<td>49</td>
<td>
<a href="#url" class="btn btn-default btn-primary btn-medium"><span class="glyphicon glyphicon-edit"></span> Edit</a>
<a href="#url" class="btn btn-default btn-danger btn-medium" data-toggle="confirm" data-target="#disable"><span class="glyphicon glyphicon-off"></span> Disable</a>
</td>
</tr>
<tr>
<td><a href="#">XMAS13</a></td>
<td>Coupon for XMAS -30 &euro;</td>
<td>05/09/2013</td>
<td>20</td>
<td>
<a href="#url" class="btn btn-default btn-primary btn-medium"><span class="glyphicon glyphicon-edit"></span> Edit</a>
<a href="#url" class="btn btn-default btn-danger btn-medium" data-toggle="confirm" data-target="#disable"><span class="glyphicon glyphicon-off"></span> Disable</a>
</td>
</tr>
<tr>
<td><a href="#">XMAS13</a></td>
<td>Coupon for XMAS -30 &euro;</td>
<td>03/12/2013</td>
<td>9</td>
<td>
<a href="#url" class="btn btn-default btn-primary btn-medium"><span class="glyphicon glyphicon-edit"></span> Edit</a>
<a href="#url" class="btn btn-default btn-danger btn-medium" data-toggle="confirm" data-target="#disable"><span class="glyphicon glyphicon-off"></span> Disable</a>
</td>
</tr>
<tr>
<td><a href="#">XMAS13</a></td>
<td>Coupon for XMAS -30 &euro;</td>
<td>25/01/2013</td>
<td>4</td>
<td>
<a href="#url" class="btn btn-default btn-primary btn-medium"><span class="glyphicon glyphicon-edit"></span> Edit</a>
<a href="#url" class="btn btn-default btn-danger btn-medium" data-toggle="confirm" data-target="#disable"><span class="glyphicon glyphicon-off"></span> Disable</a>
</td>
</tr>
{loop type="coupon" name="list_coupon" is_enabled="1" backend_context="true"}
<tr>
<td>{block name="coupon-code"}<a href="{$urlReadCoupon|replace:'couponId':$ID}">{$CODE}</a>{/block}</td>
<td>{block name="coupon-title"}{$TITLE}{/block}</td>
<td>{block name="coupon-expiration-date"}{$EXPIRATION_DATE}{/block}</td>
<td>{block name="coupon-usage-left"}{$USAGE_LEFT}{/block}</td>
<td>
{block name="coupon-action"}
<a href="{$urlEditCoupon|replace:'couponId':$ID}" class="btn btn-default btn-primary btn-medium">
<span class="glyphicon glyphicon-edit"></span> {intl l='Edit'}
</a>
{/block}
</td>
</tr>
{/loop}
</tbody>
</table>
</div>
@@ -80,58 +60,33 @@
<div class="col-md-12 general-block-decorator">
<table class="table table-striped tablesorter">
<caption>
List of disabled coupons
{intl l='Disabled coupons'}
</caption>
<thead>
<tr>
<th>Code</th>
<th>Title</th>
<th>Expiration date</th>
<th>Usage left</th>
<th class="sorter-false filter-false">Actions</th>
<th>{block name="coupon-label-code"}{intl l='Code'}{/block}</th>
<th>{block name="coupon-label-title"}{intl l='Title'}{/block}</th>
<th>{block name="coupon-label-expiration-date"}{intl l='Expiration date'}{/block}</th>
<th>{block name="coupon-label-usage-left"}{intl l='Usage left'}{/block}</th>
<th class="sorter-false filter-false">{block name="coupon-label-action"}{/block}</th>
</tr>
</thead>
<tbody>
<tr>
<td>XMAS13</td>
<td>Coupon for XMAS -30 &euro;</td>
<td>18/10/2013</td>
<td>49</td>
<td>
<a href="#url" class="btn btn-default btn-primary btn-medium"><span class="glyphicon glyphicon-edit"></span> Edit</a>
<a href="#url" class="btn btn-default btn-success btn-medium" data-toggle="confirm" data-target="#enable"><span class="glyphicon glyphicon-ok"></span> Enabled</a>
</td>
</tr>
<tr>
<td>XMAS13</td>
<td>Coupon for XMAS -20 &euro;</td>
<td>05/09/2013</td>
<td>49</td>
<td>
<a href="#url" class="btn btn-default btn-primary btn-medium"><span class="glyphicon glyphicon-edit"></span> Edit</a>
<a href="#url" class="btn btn-default btn-success btn-medium" data-toggle="confirm" data-target="#enable"><span class="glyphicon glyphicon-ok"></span> Enabled</a>
</td>
</tr>
<tr>
<td>XMAS13</td>
<td>Coupon for XMAS -50 &euro;</td>
<td>03/12/2013</td>
<td>49</td>
<td>
<a href="#url" class="btn btn-default btn-primary btn-medium"><span class="glyphicon glyphicon-edit"></span> Edit</a>
<a href="#url" class="btn btn-default btn-success btn-medium" data-toggle="confirm" data-target="#enable"><span class="glyphicon glyphicon-ok"></span> Enabled</a>
</td>
</tr>
<tr>
<td>XMAS13</td>
<td>Coupon for XMAS -5 &euro;</td>
<td>25/01/2013</td>
<td>49</td>
<td>
<a href="#url" class="btn btn-default btn-primary btn-medium"><span class="glyphicon glyphicon-edit"></span> Edit</a>
<a href="#url" class="btn btn-default btn-success btn-medium" data-toggle="confirm" data-target="#enable"><span class="glyphicon glyphicon-ok"></span> Enabled</a>
</td>
</tr>
{loop type="coupon" name="list_coupon" is_enabled="0" backend_context="true"}
<tr>
<td>{block name="coupon-code"}<a href="{$urlReadCoupon|replace:'couponId':$ID}">{$CODE}</a>{/block}</td>
<td>{block name="coupon-title"}{$TITLE}{/block}</td>
<td>{block name="coupon-expiration-date"}{$EXPIRATION_DATE}{/block}</td>
<td>{block name="coupon-usage-left"}{$USAGE_LEFT}{/block}</td>
<td>
{block name="coupon-action"}
<a href="{$urlEditCoupon|replace:'couponId':$ID}" class="btn btn-default btn-primary btn-medium">
<span class="glyphicon glyphicon-edit"></span> {intl l='Edit'}
</a>
{/block}
</td>
</tr>
{/loop}
</tbody>
</table>
</div>
@@ -139,9 +94,6 @@
</section> <!-- #wrapper -->
{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}

View File

@@ -4,112 +4,146 @@
{block name="main-content"}
<section id="wrapper" class="container">
{loop type="coupon" name="read_coupon" id={$couponId} backend_context="true"}
<nav>
<ul class="breadcrumb">
{include file="includes/coupon_breadcrumb.html"}
<li><a href="{url path='admin/home'}">{intl l='Home'}</a></li>
<li><a href="{url path='admin/coupon/'}">{intl l='Coupon'}</a></li>
<li>{$CODE}</li>
</ul>
</nav>
{loop type="coupon" name="read_coupon" id={$couponId} backend_context="true"}
<div class="page-header">
<h1>{intl l='Coupon : '}<small>{$CODE}</small></h1>
</div>
<div class="page-header">
<h1>{intl l='Coupon : '}<small>{$CODE}</small></h1>
</div>
<section class="row">
<div class="col-md-12 general-block-decorator">
<section class="row">
<div class="col-md-12 general-block-decorator">
<div class="alert alert-info">
<span class="glyphicon glyphicon-question-sign"></span>
{if !$IS_ENABLED}{intl l='This coupon is disabled, you can enable to the bottom of this form.'}{/if}
</div>
{if !$IS_ENABLED}
<div class="alert alert-info">
<span class="glyphicon glyphicon-question-sign"></span>
{intl l='This coupon is disabled, you can enable to the bottom of this form.'}
</div>
{/if}
<table class="table table-striped">
<tbody>
<tr>
<td>{intl l='Title'}</td>
<td>{$TITLE}</td>
</tr>
<tr>
<td>{intl l='Expiration date'}</td>
<td>{$EXPIRATION_DATE}</td>
</tr>
<tr>
<td>{intl l='Usage left'}</td>
<td>
{if $USAGE_LEFT}
<span class="label label-success">
{$USAGE_LEFT}
</span>
{else}
<span class="label label-important">
0
</span>
{/if}
</td>
</tr>
<tr>
<td colspan="2">{$SHORT_DESCRIPTION}</td>
</tr>
<tr>
<td colspan="2">{$DESCRIPTION}</td>
</tr>
<tr>
<td colspan="2">
{if $IS_CUMULATIVE}
<span class="label label-success">
{intl l="May be cumulative"}
</span>
{else}
<span class="label label-important">
{intl l="Can't be cumulative"}
</span>
{/if}
</td>
</tr>
<tr>
<td colspan="2">
{if $IS_REMOVING_POSTAGE}
<span class="label label-important">
<table class="table table-striped">
<tbody>
<tr>
<td>{intl l='Title'}</td>
<td>{$TITLE}</td>
</tr>
<tr>
<td colspan="2">
{if $IS_ENABLED}
<span class="label label-success">
{intl l="Is enabled"}
</span>
{else}
<span class="label label-warning">
{intl l="Is disabled"}
</span>
{/if}
</td>
</tr>
<tr>
<td colspan="2">
{$TOOLTIP}
</td>
</tr>
<tr>
<td>{intl l='Amount'}</td>
<td>{$AMOUNT}</td>
</tr>
<tr>
<td>{intl l='Expiration date'}</td>
<td>{$EXPIRATION_DATE} ({$DAY_LEFT_BEFORE_EXPIRATION} {intl l="days left"})</td>
</tr>
<tr>
<td>{intl l='Usage left'}</td>
<td>
{if $USAGE_LEFT}
<span class="label label-success">
{$USAGE_LEFT}
</span>
{else}
<span class="label label-warning">
0
</span>
{/if}
</td>
</tr>
<tr>
<td colspan="2">
{if $IS_CUMULATIVE}
<span class="label label-success">
{intl l="May be cumulative"}
</span>
{else}
<span class="label label-warning">
{intl l="Can't be cumulative"}
</span>
{/if}
</td>
</tr>
<tr>
<td colspan="2">
{if $IS_REMOVING_POSTAGE}
<span class="label label-warning">
{intl l="Will remove postage"}
</span>
{else}
<span class="label label-success">
{else}
<span class="label label-success">
{intl l="Won't remove postage"}
</span>
{/if}
</td>
</tr>
<tr>
<td>{intl l='Amount'}</td>
<td>{$AMOUNT}</td>
</tr>
<tr>
<td>{intl l='Application field'}</td>
<td>
<ul class="list-unstyled">
{foreach from=$APPLICATION_CONDITIONS item=rule name=rulesForeach}
{if !$smarty.foreach.rulesForeach.first}
<li><span class="label label-info">{intl l='And'}</span></li>
{/if}
<li>{$rule nofilter}</li>
{/foreach}
</ul>
</td>
</tr>
<tr>
<td>{intl l='Actions'}</td>
<td>
<a href="#url" class="btn btn-default btn-primary btn-medium"><span class="icon-edit icon-white"></span> {intl l='Edit'}</a>
<a href="#url" class="btn btn-default btn-success btn-medium" data-toggle="confirm" data-target="#enable"><span class="glyphicon glyphicon-ok"></span> {intl l='Enabled'}</a>
</td>
</tr>
</tbody>
</table>
{/loop}
</div>
</section>
{/if}
</td>
</tr>
<tr>
<td colspan="2">
{if $IS_AVAILABLE_ON_SPECIAL_OFFERS}
<span class="label label-warning">
{intl l="Will be available on special offers"}
</span>
{else}
<span class="label label-success">
{intl l="Won't be available on special offers"}
</span>
{/if}
</td>
</tr>
<tr>
<td>{intl l='Application field'}</td>
<td>
<ul class="list-unstyled">
{foreach from=$APPLICATION_CONDITIONS item=rule name=rulesForeach}
{if !$smarty.foreach.rulesForeach.first}
<li><span class="label label-info">{intl l='And'}</span></li>
{/if}
<li>{$rule nofilter}</li>
{/foreach}
</ul>
</td>
</tr>
<tr>
<td colspan="2">{$SHORT_DESCRIPTION}</td>
</tr>
<tr>
<td colspan="2">{$DESCRIPTION}</td>
</tr>
<tr>
<td colspan="2">
<a href="{$urlEditCoupon}" class="btn btn-default btn-primary btn-medium">
<span class="icon-edit icon-white"></span> {intl l='Edit'}
</a>
</td>
</tr>
</tbody>
</table>
</div>
</section>
{/loop}
</section> <!-- #wrapper -->
{include file='includes/confirmation-modal.html' id="enable" message="{intl l='Do you really want to enable this element ?'}"}

View File

@@ -7,19 +7,20 @@
<nav>
<ul class="breadcrumb">
{include file="includes/coupon_breadcrumb.html"}
<li><a href="{url path='admin/home'}">{intl l='Home'}</a></li>
<li><a href="{url path='admin/coupon/'}">{intl l='Coupon'}</a></li>
<li>{intl l='Update'} {$couponCode}</li>
</ul>
</nav>
<div class="page-header">
<h1>Coupons : <small>Update a coupon</small></h1>
<h1>{intl l='Coupons : '}<small>{intl l='Update'} {$couponCode}</small></h1>
</div>
{form name="thelia.admin.coupon.creation"}
{include file='coupon/form.html' formAction={url path={$formAction}} form=$form noRules=false}
{/form}
</section> <!-- #wrapper -->
{/block}
@@ -71,8 +72,6 @@
// Save Rules AJAX
couponManager.saveRuleAjax = function() {
$('#constraint-add-operators-values').html('<div class="loading" ></div>');
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();
});
</script>
{/block}

View File

@@ -11,152 +11,155 @@
{/form_field}
{form_field form=$form field='success_url'}
<input type="hidden" name="{$name}" value="{url path='/admin/coupon/read/{id}'}" />
<input type="hidden" name="{$name}" value="{url path='/admin/coupon/update/{id}/'}" />
{/form_field}
<div class="span4">
<div class="control-group">
<div class="col-md-4">
<div class="form-group">
<label for="code">{intl l='Code :'}</label>
{form_field form=$form field='code'}
{form_field form=$form field='code'}
<div class="form-group {if $error}has-error{/if}">
<label class="control-label" for="code">{intl l='Code :'}</label>
<input id="code" class="form-control" type="text" name="{$name}" value="{$value}" placeholder="{intl l='code'}">
{if $error}{$message}{/if}
{/form_field}
</div>
</div>
{/form_field}
<div class="form-group">
<label for="title">{intl l='Title :'}</label>
{form_field form=$form field='title'}
{form_field form=$form field='title'}
<div class="form-group {if $error}has-error{/if}">
<label for="title" class="control-label" >{intl l='Title :'}</label>
<input id="title" class="form-control" type="text" name="{$name}" value="{$value}" placeholder="{intl l='title'}">
{if $error}{$message}{/if}
{/form_field}
</div>
<div class="form-group">
<label for="enabled" class="checkbox">
{form_field form=$form field='isEnabled'}
<input id="enabled" type="checkbox" name="{$name}" {if $value}value="1" checked{else}value="0"{/if} >
{if $error}{$message}{/if}
{/form_field}
{intl l='Is enabled ?'}
</label>
</div>
<div class="form-group">
<label for="available-on-special-offers" class="checkbox">
{form_field form=$form field='isAvailableOnSpecialOffers'}
<input id="available-on-special-offers" type="checkbox" name="{$name}" {if $value}value="1" checked{else}value="0"{/if} >
{if $error}{$message}{/if}
{/form_field}
{intl l='Is available on special offers ?'}
</label>
</div>
<div class="form-group">
<label for="cumulative" class="checkbox">
{form_field form=$form field='isCumulative'}
<input id="cumulative" type="checkbox" name="{$name}" {if $value}value="1" checked{else}value="0"{/if} >
{if $error}{$message}{/if}
{/form_field}
{intl l='Is cumulative ?'}
</label>
</div>
<div class="form-group">
<label for="renoving-postage" class="checkbox">
{form_field form=$form field='isRemovingPostage'}
<input id="renoving-postage" type="checkbox" name="{$name}" {if $value}value="1" checked{else}value="0"{/if} >
{if $error}{$message}{/if}
{/form_field}
{intl l='Is removing postage ?'}
</label>
</div>
<div class="form-group">
<label for="expiration-date">{intl l='Expiration date :'}</label>
<div class="input-append date" data-date="12/02/2012" data-date-format="dd/mm/yyyy">
{form_field form=$form field='expirationDate'}
<input type="text" id="expiration-date" name="{$name}" value="{if $defaultDate}{$defaultDate}{else}{$value}{/if}">
{if $error}{$message}{/if}
{/form_field}
<span class="add-on"><span class="icon-th"></span></span>
</div>
</div>
{/form_field}
<div class="form-group">
<label for="max-usage">{intl l='Max usage :'}</label>
<label for="is-unlimited" class="checkbox">
<input id="is-unlimited" type="checkbox" name="is-unlimited" checked >
{intl l='Is unlimited ?'}
</label>
{form_field form=$form field='maxUsage'}
{form_field form=$form field='isEnabled'}
<div class="form-group {if $error}has-error{/if}">
<label for="is-enabled" class="checkbox control-label">
<input id="is-enabled" type="checkbox" name="{$name}" {if $value}value="1" checked{else}value="0"{/if} >
{if $error}{$message}{/if}
{intl l='Is enabled'}
</label>
</div>
{/form_field}
{form_field form=$form field='isAvailableOnSpecialOffers'}
<div class="form-group {if $error}has-error{/if}">
<label for="is-available-on-special-offers" class="checkbox control-label">
<input id="is-available-on-special-offers" type="checkbox" name="{$name}" {if $value}value="1" checked{else}value="0"{/if} >
{if $error}{$message}{/if}
{intl l='Is available on special offers'}
</label>
</div>
{/form_field}
{form_field form=$form field='isCumulative'}
<div class="form-group {if $error}has-error{/if}">
<label for="is-cumulative" class="checkbox control-label">
<input id="is-cumulative" type="checkbox" name="{$name}" {if $value}value="1" checked{else}value="0"{/if} >
{if $error}{$message}{/if}
{intl l='Is cumulative'}
</label>
</div>
{/form_field}
{form_field form=$form field='isRemovingPostage'}
<div class="form-group {if $error}has-error{/if}">
<label for="is-removing-postage" class="checkbox control-label">
<input id="is-removing-postage" type="checkbox" name="{$name}" {if $value}value="1" checked{else}value="0"{/if} >
{if $error}{$message}{/if}
{intl l='Is removing postage'}
</label>
</div>
{/form_field}
{form_field form=$form field='expirationDate'}
<div class="form-group {if $error}has-error{/if}">
<label for="expiration-date" class="control-label">{intl l='Expiration date :'}</label>
<div class="input-append date" data-date="12/02/2012" data-date-format="dd/mm/yyyy">
<input type="text" id="expiration-date" name="{$name}" class="form-control datepicker" data-date-format="yyyy-mm-dd" value="{if $defaultDate}{$defaultDate}{else}{$value}{/if}" placeholder="{intl l='yyyy-mm-dd'}">
{if $error}{$message}{/if}
<span class="add-on"><span class="icon-th"></span></span>
</div>
</div>
{/form_field}
{form_field form=$form field='maxUsage'}
<div class="form-group {if $error}has-error{/if}">
<label for="is-unlimited" class="checkbox control-label">
<input id="is-unlimited" type="checkbox" name="is-unlimited" {if $error}{else}checked{/if} >
{intl l='Is unlimited'}
</label>
<label id="max-usage-label" for="max-usage" class="control-label">{intl l='Max usage :'}</label>
<input id="max-usage" type="text" class="form-control" name="{$name}" value="{$value}" placeholder="{intl l='max usage'}">
{if $error}{$message}{/if}
{/form_field}
</div>
</div>
{/form_field}
</div>
<div class="col-md-8">
<div class="well clearfix">
<div class="col-md-6">
<div class="form-group">
<label for="effect">{intl l='Effect :'}</label>
{form_field form=$form field='effect'}
{form_field form=$form field='effect'}
<div class="form-group {if $error}has-error{/if}">
<label for="effect" class="control-label">{intl l='Effect :'}</label>
<select name="{$name}" value="{$value}" id="effect" class="col-md-12 form-control">
<option value="-1" data-description="">{intl l='Please select an effect'}</option>
{foreach from=$availableCoupons item=availableCoupon}
<option value="{$availableCoupon.serviceId}" data-description="{$availableCoupon.toolTip}">{$availableCoupon.name}</option>
<option value="{$availableCoupon.serviceId}" data-description="{$availableCoupon.toolTip}" {if $value == $availableCoupon.serviceId}selected="selected"{/if}>{$availableCoupon.name}</option>
{/foreach}
</select>
{if $error}{$message}{/if}
{/form_field}
<span id="effectToolTip" class="help-block">{$availableCoupons.0.toolTip}</span>
</div>
<span id="effectToolTip" class="help-block">{$availableCoupons.0.toolTip}</span>
</div>
{/form_field}
</div>
<div class="col-md-6">
<div class="form-group">
<label for="amount">{intl l='Amount :'}</label>
{form_field form=$form field='amount'}
{form_field form=$form field='amount'}
<div class="form-group {if $error}has-error{/if}">
{$value}
<label for="amount" class="control-label">{intl l='Amount :'}</label>
<input id="amount" type="text" class="form-control" name="{$name}" value="{$value}" placeholder="{intl l='14.50'}">
{if $error}{$message}{/if}
{/form_field}
</div>
<div class="form-group">
<label for="category">Category :</label>
</div>
{/form_field}
{*<div class="form-group {if $error}has-error{/if}">*}
{*<label for="category">Category :</label>*}
{*form_field form=$form field='category'*}
<select name="{$name}" value="{$value}" id="category" class="form-control">
<option value="1">Category 1</option>
<option value="1">Category 2</option>
<option value="1">Category 3</option>
</select>
{*<select name="{$name}" value="{$value}" id="category" class="form-control">*}
{*<option value="1">Category 1</option>*}
{*<option value="1">Category 2</option>*}
{*<option value="1">Category 3</option>*}
{*</select>*}
{*if $error}{$message}{/if}*}
{*/form_field*}
</div>
{*</div>*}
</div>
</div>
<div class="form-group">
<label for="short-description">{intl l='Short description :'}</label>
{form_field form=$form field='shortDescription'}
<textarea id="short-description" name="{$name}" placeholder="{intl l='short description'}" class="span12" rows="5">{$value nofilter}</textarea>
{form_field form=$form field='shortDescription'}
<div class="form-group {if $error}has-error{/if}">
<label for="short-description" class="control-label">{intl l='Short description :'}</label>
<textarea id="short-description" name="{$name}" class="form-control" placeholder="{intl l='short description'}" class="span12" rows="5">{$value nofilter}</textarea>
{if $error}{$message}{/if}
{/form_field}
</div>
</div>
{/form_field}
</div>
<div class="clearfix"></div>
<div class="col-md-12">
<div class="form-group">
<label for="description">{intl l='Long description :'}</label>
{form_field form=$form field='description'}
{form_field form=$form field='description'}
<div class="form-group {if $error}has-error{/if}">
<label for="description" class="control-label">{intl l='Long description :'}</label>
<textarea id="description" name="{$name}" placeholder="{intl l='long description'}" class="form-control wysiwyg" rows="10">{$value nofilter}</textarea>
{if $error}{$message}{/if}
{/form_field}
</div>
</div>
{/form_field}
<button type="submit" class="btn btn-default btn-primary">{intl l='Save'}</button>
<button id="save-coupon-btn" type="submit" class="btn btn-default btn-primary">{intl l='Save your modifications'}</button>
</div>
</div>
@@ -186,22 +189,23 @@
<section class="row">
<div class="col-md-12 general-block-decorator clearfix">
<a id="constraint-save-btn" title="{intl l='Save this rule'}" class="btn btn-default btn-primary pull-right">
<span class="glyphicon glyphicon-plus-sign"></span>
<span class="glyphicon glyphicon-plus-sign"></span> {intl l='Save this rule'}
</a>
<div id="rule-add-organizer" class="form-group col-md-2">
<label for="type">{intl l='Condition type :'}</label>
<label class="radio">
<input type="radio" name="type" id="type" value="1" checked> {intl l='And'}
<input type="radio" name="type" class="form-control" id="type" value="1" checked> {intl l='And'}
</label>
<label class="radio">
<input type="radio" name="type" value="2"> {intl l='Or'}
<input type="radio" name="type" class="form-control" value="2"> {intl l='Or'}
</label>
</div>
<div id="rule-add-type" class="form-group col-md-4">
<label for="categoryRule">{intl l='Rule\'s category :'}</label>
<select name="categoryRule" id="category-rule" class="form-control">
<option value="-1" >{intl l='Please select a rule category'}</option>
{foreach from=$availableRules item=availableRule}
<option value="{$availableRule.serviceId}" data-description="{$availableRule.toolTip}">{$availableRule.name}</option>
{/foreach}

View File

@@ -3,7 +3,7 @@
<div class="row">
<div class="col-lg-6">
<select class="form-control" id="{$name}-operator" name="{$name}[operator]">
{foreach from=$input.availableOperators key=k item=availableOperator}
{foreach from=$input.availableOperators key=k item=availableOperator name=availableOperators}
<option value="{$k}">{$availableOperator}</option>
{/foreach}
</select>
@@ -11,7 +11,7 @@
<div class="input-group col-lg-6">
{if $input.type == 'select'}
<select class="{$input.class}" id="{$name}-value" name="{$name}[value]">
{foreach from=$input.availableValues key=code item=availableValue}
{foreach from=$input.availableValues key=code item=availableValue name=availableValues}
<option value="{$code}">{$availableValue}</option>
{/foreach}
</select>
@@ -72,12 +72,16 @@
<script>
// Init Rules to set
couponManager.ruleToSave['serviceId'] = '{$ruleId}';
couponManager.ruleToSave['operators'] = {literal}{}{/literal};
couponManager.ruleToSave['values'] = {literal}{}{/literal};
// Update only if no rule are already set
if(!couponManager.ruleToSave){
couponManager.ruleToSave['serviceId'] = '{$ruleId}';
couponManager.ruleToSave['operators'] = {literal}{}{/literal};
couponManager.ruleToSave['values'] = {literal}{}{/literal};
} else {
}
{foreach from=$inputs.inputs key=name item=input}
couponManager.ruleToSave['operators']['{$name nofilter}'] = '{foreach from=$inputs.inputs[$name].availableOperators key=keyOperator item=valueOperator name=operators}{if $smarty.foreach.operators.first}{$keyOperator nofilter}{/if}{/foreach}';
couponManager.ruleToSave['values']['{$name nofilter}'] = '{if count($inputs.inputs[$name].availableValues) != 0}{foreach from=$inputs.inputs[$name].availableValues key=keyValue item=valueValue name=values}{if $smarty.foreach.values.first}{$keyValue nofilter}{/if}{/foreach}{else}to set{/if}';
couponManager.ruleToSave['operators']['{$name nofilter}'] = '{foreach from=$inputs.inputs[$name].availableOperators key=keyOperator item=valueOperator name=operators}{if $smarty.foreach.operators.first}{$keyOperator nofilter}{/if}{/foreach}';
couponManager.ruleToSave['values']['{$name nofilter}'] = '{if count($inputs.inputs[$name].availableValues) != 0}{foreach from=$inputs.inputs[$name].availableValues key=keyValue item=valueValue name=values}{if $smarty.foreach.values.first}{$keyValue nofilter}{/if}{/foreach}{else}to set{/if}';
{/foreach}
@@ -86,13 +90,11 @@
{foreach from=$inputs.inputs key=name item=input}
// Operator selector
$('#{$name}-operator').change(function (e) {
console.log('changin operator');
var $this = $(this);
couponManager.ruleToSave['operators']['{$name nofilter}'] = $this.val();
});
// Value input
$('#{$name}-value').change(function (e) {
console.log('changin value');
var $this = $(this);
couponManager.ruleToSave['values']['{$name nofilter}'] = $this.val();
});

View File

@@ -0,0 +1,316 @@
{extends file="admin-layout.tpl"}
{block name="page-title"}{intl l='Edit an feature'}{/block}
{block name="check-permissions"}admin.configuration.features.edit{/block}
{block name="main-content"}
<div class="features edit-feature">
<div id="wrapper" class="container">
{loop name="feature_edit" type="feature" id=$feature_id backend_context="1" lang=$edit_language_id}
<ul class="breadcrumb">
<li><a href="{url path='/admin/home'}">{intl l="Home"}</a></li>
<li><a href="{url path='/admin/configuration'}">{intl l="Configuration"}</a></li>
<li><a href="{url path='/admin/configuration/features'}">{intl l="Features"}</a></li>
<li>{intl l='Editing feature "%name"' name="{$TITLE}"}</li>
</ul>
<div class="row">
<div class="col-md-12 general-block-decorator">
<div class="row">
<div class="col-md-12 title title-without-tabs">
{intl l="Edit feature $TITLE"}
</div>
<div class="col-md-12">
<div class="form-container">
{form name="thelia.admin.feature.modification"}
<form method="POST" action="{url path='/admin/configuration/features/save'}" {form_enctype form=$form} class="clearfix">
{include file="includes/inner-form-toolbar.html" close_url="{url path='/admin/configuration/features'}"}
<div class="col-md-6">
<p class="title title-without-tabs">{intl l='Feature information'}</p>
{form_field form=$form field='id'}
<input type="hidden" name="{$name}" value="{$feature_id}" />
{/form_field}
{* Be sure to get the feature ID, even if the form could not be validated *}
<input type="hidden" name="feature_id" value="{$feature_id}" />
{form_hidden_fields form=$form}
{form_field form=$form field='success_url'}
<input type="hidden" name="{$name}" value="{url path='/admin/configuration/features'}" />
{/form_field}
{form_field form=$form field='locale'}
<input type="hidden" name="{$name}" value="{$edit_language_locale}" />
{/form_field}
{if $form_error}<div class="alert alert-danger">{$form_error_message}</div>{/if}
{include file="includes/standard-description-form-fields.html" form=$form}
</div>
<div class="col-md-6">
<p class="title title-without-tabs">
{intl l='Feature values'}
{loop type="auth" name="can_create" roles="ADMIN" permissions="admin.configuration.feature-av.create"}
<span class="pull-right">
<a data-toggle="modal" href="#creation_dialog" title="Add a new feature value" class="btn btn-default btn-primary">
<span class="glyphicon glyphicon-plus-sign"></span>
</a>
</span>
{/loop}
</p>
<div class="alert alert-info">
{intl l="Enter here all possible feature values."}
</div>
<table class="table table-striped table-condensed table-left-aligned">
<thead>
<tr>
<th>
{admin_sortable_header
current_order=$featureav_order
order='id'
reverse_order='id_reverse'
request_parameter_name='featureav_order'
path={url path='/admin/configuration/features/update' feature_id=$feature_id}
label="{intl l='ID'}"
}
</th>
<th>
{admin_sortable_header
current_order=$featureav_order
order='alpha'
reverse_order='alpha_reverse'
request_parameter_name='featureav_order'
path={url path='/admin/configuration/features/update' feature_id=$feature_id}
label="{intl l='Value'}"
}
</th>
<th class="text-center">
{admin_sortable_header
current_order=$featureav_order
order='manual'
reverse_order='manual_reverse'
request_parameter_name='featureav_order'
path={url path='/admin/configuration/features/update' feature_id=$feature_id}
label="{intl l="Position"}"
}
</th>
{module_include location='features_value_table_header'}
<th class="actions">{intl l="Actions"}</th>
</tr>
</thead>
<tbody>
{loop name="list" type="feature_availability" feature=$feature_id backend_context="1" lang=$edit_language_id order=$featureav_order}
<tr>
<td>{$ID}</td>
<td>
{* FIXME : integrate this in the encolsing form to provide standard form processing *}
<input class="js-edit form-control" type="text" name="feature_values[{$ID}]" value="{$TITLE}" />
</td>
<td class="text-center">
{admin_position_block
permission="admin.features.edit"
path={url path='/admin/configuration/features-av/update-position' feature_id=$feature_id}
url_parameter="featureav_id"
in_place_edit_class="positionChange"
position="$POSITION"
id="$ID"
}
</td>
{module_include location='features_value_table_row'}
<td class="actions">
<div class="btn-group">
{loop type="auth" name="can_create" roles="ADMIN" permissions="admin.configuration.feature-av.delete"}
<a class="btn btn-default btn-xs value-delete" title="{intl l='Delete this value'}" href="#delete_dialog" data-id="{$ID}" data-toggle="modal">
<span class="glyphicon glyphicon-trash"></span>
</a>
{/loop}
</div>
</td>
</tr>
{/loop}
{elseloop rel="list"}
<tr>
<td colspan="4">
<div class="alert alert-info">
{intl l="No value has been created yet. Click the + button to create one."}
</div>
</td>
</tr>
{/elseloop}
</tbody>
</table>
</div>
</form>
{/form}
</div>
</div>
</div>
</div>
</div>
{/loop}
{elseloop rel="feature_edit"}
<div class="row">
<div class="col-md-12">
<div class="alert alert-error">
{intl l="Sorry, feature ID=$feature_id was not found."}
</div>
</div>
</div>
{/elseloop}
</div>
</div>
{* Adding a new feature *}
{form name="thelia.admin.featureav.creation"}
{* Capture the dialog body, to pass it to the generic dialog *}
{capture "creation_dialog"}
{form_hidden_fields form=$form}
{* Be sure to get the feature ID, even if the form could not be validated *}
<input type="hidden" name="feature_id" value="{$feature_id}" />
{form_field form=$form field='success_url'}
{* on success, redirect to this page *}
<input type="hidden" name="{$name}" value="{url path='/admin/configuration/features/update' feature_id=$feature_id}" />
{/form_field}
{form_field form=$form field='feature_id'}
<input type="hidden" name="{$name}" value="{$feature_id}" />
{/form_field}
{form_field form=$form field='title'}
<div class="form-group {if $error}has-error{/if}">
<label for="{$label_attr.for}" class="control-label">{intl l="{$label}"} : </label>
{loop type="lang" name="current-edit-lang" id="$edit_language_id"}
<div class="input-group">
<input type="text" id="{$label_attr.for}" required="required" name="{$name}" class="form-control" value="{$value}" title="{intl l='Feature title'}" placeholder="{intl l='Title'}">
<span class="input-group-addon"><img src="{image file="assets/img/flags/{$CODE}.gif"}" alt="{intl l=$TITLE}" /></span>
</div>
<div class="help-block">{intl l="Enter here the value in the current edit language ($TITLE)"}</div>
{form_field form=$form field='locale'}
<input type="hidden" name="{$name}" value="{$LOCALE}" />
{/form_field}
{/loop}
</div>
{/form_field}
{module_include location='feature_value_create_form'}
{/capture}
{include
file = "includes/generic-create-dialog.html"
dialog_id = "creation_dialog"
dialog_title = {intl l="Create a new feature value"}
dialog_body = {$smarty.capture.creation_dialog nofilter}
dialog_ok_label = {intl l="Create this value"}
form_action = {url path='/admin/configuration/features-av/create'}
form_enctype = {form_enctype form=$form}
form_error_message = $form_error_message
}
{/form}
{* Delete value confirmation dialog *}
{capture "delete_dialog"}
<input type="hidden" name="feature_id" value="{$feature_id}" />
<input type="hidden" name="featureav_id" id="value_delete_id" value="" />
{/capture}
{include
file = "includes/generic-confirm-dialog.html"
dialog_id = "delete_dialog"
dialog_title = {intl l="Delete feature value"}
dialog_message = {intl l="Do you really want to delete this feature value ?"}
form_action = {url path='/admin/configuration/features-av/delete'}
form_content = {$smarty.capture.delete_dialog nofilter}
}
{/block}
{block name="javascript-initialization"}
{javascripts file='assets/js/bootstrap-editable/bootstrap-editable.js'}
<script src="{$asset_url}"></script>
{/javascripts}
<script>
$(function() {
// Set proper feature ID in delete from
$('a.value-delete').click(function(ev) {
$('#value_delete_id').val($(this).data('id'));
});
// JS stuff for creation form
{include
file = "includes/generic-js-dialog.html"
dialog_id = "creation_dialog"
form_name = "thelia.admin.featureav.creation"
}
{* Inline editing of object position using bootstrap-editable *}
$('.positionChange').editable({
type : 'text',
title : '{intl l="Enter new value position"}',
mode : 'popup',
inputclass : 'input-mini',
placement : 'left',
success : function(response, newValue) {
// The URL template
var url = "{url path='/admin/configuration/features-av/update-position' featureav_id='__ID__' position='__POS__' feature_id=$feature_id}";
// Perform subtitutions
url = url.replace('__ID__', $(this).data('id')).replace('__POS__', newValue);
// Reload the page
location.href = url;
}
});
});
</script>
{/block}

View File

@@ -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"}
<div class="features">
<div id="wrapper" class="container">
<ul class="breadcrumb">
<li><a href="{url path='/admin/home'}">{intl l="Home"}</a></li>
<li><a href="{url path='/admin/configuration'}">{intl l="Configuration"}</a></li>
<li><a href="{url path='/admin/configuration/features'}">{intl l="Product features"}</a></li>
</ul>
{module_include location='features_top'}
<div class="row">
<div class="col-md-12">
<form action="#" method="post">
<div class="general-block-decorator">
<table class="table table-striped table-condensed table-left-aligned">
<caption>
{intl l='Thelia product features'}
{loop type="auth" name="can_create" roles="ADMIN" permissions="admin.configuration.features.create"}
<a class="btn btn-default btn-primary action-btn" title="{intl l='Add a new product feature'}" href="#creation_dialog" data-toggle="modal">
<span class="glyphicon glyphicon-plus-sign"></span>
</a>
{/loop}
</caption>
<thead>
<tr>
<th>
{admin_sortable_header
current_order=$order
order='id'
reverse_order='id_reverse'
path='/admin/configuration/features'
label="{intl l='ID'}"
}
</th>
<th>
{admin_sortable_header
current_order=$order
order='alpha'
reverse_order='alpha_reverse'
path='/admin/configuration/features'
label="{intl l='Title'}"
}
</th>
<th class="text-center">
{admin_sortable_header
current_order=$order
order='manual'
reverse_order='manual_reverse'
path='/admin/configuration/features'
label="{intl l="Position"}"
}
</th>
{module_include location='features_table_header'}
<th class="actions">{intl l="Actions"}</th>
</tr>
</thead>
<tbody>
{loop name="list" type="feature" backend_context="1" lang=$lang_id order=$order}
<tr>
<td>{$ID}</td>
<td>
{loop type="auth" name="can_change" roles="ADMIN" permissions="admin.configuration.features.change"}
<a title="{intl l='Change this feature'}" href="{url path='/admin/configuration/features/update' feature_id=$ID}">{$TITLE}</a>
{/loop}
{elseloop rel="can_change"}
{$TITLE}
{/elseloop}
</td>
<td class="text-center">
{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"
}
</td>
{module_include location='features_table_row'}
<td class="actions">
{loop type="auth" name="can_change" roles="ADMIN" permissions="admin.configuration.features.change"}
<div class="btn-group">
<a class="btn btn-default btn-xs feature-remove-from-all" title="{intl l='Remove this feature from all product templates'}" href="#remove_from_all_dialog" data-id="{$ID}" data-toggle="modal">
<span class="glyphicon glyphicon-minus"></span>
</a>
<a class="btn btn-default btn-xs feature-add-to-all" title="{intl l='Add this feature to all product templates'}" href="#add_to_all_dialog" data-id="{$ID}" data-toggle="modal">
<span class="glyphicon glyphicon-plus"></span>
</a>
</div>
{/loop}
<div class="btn-group">
{loop type="auth" name="can_change" roles="ADMIN" permissions="admin.configuration.features.change"}
<a class="btn btn-default btn-xs feature-change" title="{intl l='Change this product feature'}" href="{url path='/admin/configuration/features/update' feature_id=$ID}"><span class="glyphicon glyphicon-edit"></span></a>
{/loop}
{loop type="auth" name="can_change" roles="ADMIN" permissions="admin.configuration.features.delete"}
<a class="btn btn-default btn-xs feature-delete" title="{intl l='Delete this product feature'}" href="#delete_dialog" data-id="{$ID}" data-toggle="modal"><span class="glyphicon glyphicon-trash"></span></a>
{/loop}
</div>
</td>
</tr>
{/loop}
{elseloop rel="list"}
<tr>
<td colspan="4">
<div class="alert alert-info">
{intl l="No product feature has been created yet. Click the + button to create one."}
</div>
</td>
</tr>
{/elseloop}
</tbody>
</table>
</div>
</form>
</div>
</div>
{module_include location='features_bottom'}
</div>
</div>
{* 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 *}
<input type="hidden" name="{$name}" value="{url path='/admin/configuration/features/update' feature_id='_ID_'}" />
{/form_field}
{form_field form=$form field='title'}
<div class="form-group {if $error}has-error{/if}">
<label for="{$label_attr.for}" class="control-label">{intl l="{$label}"} : </label>
{loop type="lang" name="default-lang" default_only="1"}
<div class="input-group">
<input type="text" id="{$label_attr.for}" required="required" name="{$name}" class="form-control" value="{$value}" title="{intl l='Feature title'}" placeholder="{intl l='Title'}">
<span class="input-group-addon"><img src="{image file="assets/img/flags/{$CODE}.gif"}" alt="{intl l=$TITLE}" /></span>
</div>
<div class="help-block">{intl l="Enter here the feature name in the default language ($TITLE)"}</div>
{* Switch edition to the current locale *}
<input type="hidden" name="edit_language_id" value="{$ID}" />
{form_field form=$form field='locale'}
<input type="hidden" name="{$name}" value="{$LOCALE}" />
{/form_field}
{/loop}
</div>
{/form_field}
{form_field form=$form field='add_to_all'}
<div class="form-group {if $error}has-error{/if}">
<div class="checkbox {if $error}has-error{/if}">
<label for="{$label_attr.for}" class="control-label">
<input type="checkbox" name="{$name}" value="1" {if $value != 0}checked="checked"{/if}>
{$label}
</label>
<span class="help-block">{intl l='Check this box if you want to add this features to all product templates'}</span>
</div>
</div>
{/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"}
<input type="hidden" name="feature_id" id="feature_delete_id" value="" />
{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"}
<input type="hidden" name="feature_id" id="feature_add_to_all_id" value="" />
{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"}
<input type="hidden" name="feature_id" id="feature_remove_from_all_id" value="" />
{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'}
<script src="{$asset_url}"></script>
{/javascripts}
<script>
$(function() {
// Set proper feature ID in delete from
$('a.feature-delete').click(function(ev) {
$('#feature_delete_id').val($(this).data('id'));
});
$('a.feature-add-to-all').click(function(ev) {
$('#feature_add_to_all_id').val($(this).data('id'));
});
$('a.feature-remove-from-all').click(function(ev) {
$('#feature_remove_from_all_id').val($(this).data('id'));
});
// JS stuff for creation form
{include
file = "includes/generic-js-dialog.html"
dialog_id = "creation_dialog"
form_name = "thelia.admin.feature.creation"
}
{* Inline editing of object position using bootstrap-editable *}
$('.positionChange').editable({
type : 'text',
title : '{intl l="Enter new feature position"}',
mode : 'popup',
inputclass : 'input-mini',
placement : 'left',
success : function(response, newValue) {
// The URL template
var url = "{url path='/admin/configuration/features/update-position' feature_id='__ID__' position='__POS__'}";
// Perform subtitutions
url = url.replace('__ID__', $(this).data('id'))
.replace('__POS__', newValue);
// Reload the page
location.href = url;
}
});
});
</script>
{/block}

View File

@@ -1,5 +0,0 @@
{* Breadcrumb for coupon browsing and editing *}
<li><a href="{url path='admin/home'}">Home</a></li>
<li><a href="{url path='admin/coupon'}">Coupon</a></li>
<li><a href="{url path="admin/coupon/browse/$ID"}">Browse</a></li>

View File

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

View File

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

View File

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