Free shipping for selected countries and/or shipping methods

This commit is contained in:
Franck Allimant
2014-05-15 20:25:22 +02:00
parent 32542efe28
commit 392abff271
31 changed files with 414 additions and 106 deletions

View File

@@ -202,7 +202,9 @@ class Coupon extends BaseAction implements EventSubscriberInterface
$event->isCumulative(),
$event->getMaxUsage(),
$defaultSerializedRule,
$event->getLocale()
$event->getLocale(),
$event->getFreeShippingForCountries(),
$event->getFreeShippingForMethods()
);
$event->setCouponModel($coupon);
@@ -235,8 +237,9 @@ class Coupon extends BaseAction implements EventSubscriberInterface
*/
public function testFreePostage(OrderEvent $event)
{
if ($this->couponManager->isCouponRemovingPostage()) {
$order = $event->getOrder();
$order = $event->getOrder();
if ($this->couponManager->isCouponRemovingPostage($order)) {
$order->setPostage(0);

View File

@@ -82,7 +82,7 @@ class Order extends BaseAction implements EventSubscriberInterface
{
$order = $event->getOrder();
$order->chosenDeliveryAddress = $event->getDeliveryAddress();
$order->setChoosenDeliveryAddress($event->getDeliveryAddress());
$event->setOrder($order);
}
@@ -125,7 +125,7 @@ class Order extends BaseAction implements EventSubscriberInterface
{
$order = $event->getOrder();
$order->chosenInvoiceAddress = $event->getInvoiceAddress();
$order->setChoosenInvoiceAddress($event->getInvoiceAddress());
$event->setOrder($order);
}
@@ -153,9 +153,9 @@ class Order extends BaseAction implements EventSubscriberInterface
$placedOrder = $sessionOrder->copy();
$placedOrder->setDispatcher($dispatcher);
$deliveryAddress = AddressQuery::create()->findPk($sessionOrder->chosenDeliveryAddress);
$deliveryAddress = AddressQuery::create()->findPk($sessionOrder->getChoosenDeliveryAddress());
$taxCountry = $deliveryAddress->getCountry();
$invoiceAddress = AddressQuery::create()->findPk($sessionOrder->chosenInvoiceAddress);
$invoiceAddress = AddressQuery::create()->findPk($sessionOrder->getChoosenInvoiceAddress());
$cartItems = $cart->getCartItems();
/* fulfill order */

View File

@@ -4,32 +4,40 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://thelia.net/schema/dic/config http://thelia.net/schema/dic/config/thelia-1.0.xsd">
<services>
<!-- Coupon module -->
<service id="thelia.facade" class="Thelia\Coupon\BaseFacade">
<argument type="service" id="service_container" />
</service>
<service id="thelia.coupon.manager" class="Thelia\Coupon\CouponManager">
<argument type="service" id="service_container" />
</service>
<service id="thelia.coupon.factory" class="Thelia\Coupon\CouponFactory">
<argument type="service" id="service_container" />
</service>
<!-- Coupon types -->
<service id="thelia.coupon.type.remove_x_amount" class="Thelia\Coupon\Type\RemoveXAmount">
<argument type="service" id="thelia.facade" />
<tag name="thelia.coupon.addCoupon"/>
</service>
<service id="thelia.coupon.type.remove_x_percent" class="Thelia\Coupon\Type\RemoveXPercent">
<argument type="service" id="thelia.facade" />
<tag name="thelia.coupon.addCoupon"/>
</service>
<service id="thelia.coupon.type.remove_amount_on_categories" class="Thelia\Coupon\Type\RemoveAmountOnCategories">
<argument type="service" id="thelia.facade" />
<tag name="thelia.coupon.addCoupon"/>
</service>
<!-- Condition module -->
<service id="thelia.condition.factory" class="Thelia\Condition\ConditionFactory">
<argument type="service" id="service_container" />
</service>
@@ -83,5 +91,4 @@
</service>
</services>
</config>

View File

@@ -32,6 +32,8 @@ use Thelia\Form\CouponCreationForm;
use Thelia\Form\Exception\FormValidationException;
use Thelia\Log\Tlog;
use Thelia\Model\Coupon;
use Thelia\Model\CouponCountry;
use Thelia\Model\CouponModule;
use Thelia\Model\CouponQuery;
use Thelia\Model\LangQuery;
use Thelia\Tools\Rest\ResponseRest;
@@ -152,6 +154,21 @@ class CouponController extends BaseAdminController
$coupon->getSerializedConditions()
);
$freeShippingForCountries = $freeShippingForModules = [];
/** @var CouponCountry $item */
foreach($coupon->getFreeShippingForCountries() as $item) {
$freeShippingForCountries[] = $item->getCountryId();
}
/** @var CouponModule $item */
foreach($coupon->getFreeShippingForModules() as $item) {
$freeShippingForModules[] = $item->getModuleId();
}
if (empty($freeShippingForCountries)) $freeShippingForCountries[] = 0;
if (empty($freeShippingForModules)) $freeShippingForModules[] = 0;
$data = [
'code' => $coupon->getCode(),
'title' => $coupon->getTitle(),
@@ -167,6 +184,8 @@ class CouponController extends BaseAdminController
'maxUsage' => $coupon->getMaxUsage(),
'conditions' => $conditions,
'locale' => $this->getCurrentEditionLocale(),
'freeShippingForCountries' => $freeShippingForCountries,
'freeShippingForModules' => $freeShippingForModules
];
$args['conditions'] = $this->cleanConditionForTemplate($conditions);
@@ -557,7 +576,7 @@ class CouponController extends BaseAdminController
$condition['serviceId'] = $availableCoupon->getServiceId();
$condition['name'] = $availableCoupon->getName();
$condition['toolTip'] = $availableCoupon->getToolTip();
$condition['inputName'] = $availableCoupon->getInputName();
// $condition['inputName'] = $availableCoupon->getInputName();
$cleanedCoupons[] = $condition;
}
@@ -702,7 +721,7 @@ class CouponController extends BaseAdminController
$couponManager = $this->container->get($serviceId);
$effects = [CouponAbstract::INPUT_AMOUNT_NAME => $data[CouponAbstract::INPUT_AMOUNT_NAME]];
$effects = $this->addExtendedLogic($effects, $couponManager->getExtendedInputs());
var_dump($data);
$couponEvent = new CouponCreateOrUpdateEvent(
$data['code'],
$serviceId,
@@ -716,7 +735,9 @@ class CouponController extends BaseAdminController
$data['isCumulative'],
$data['isRemovingPostage'],
$data['maxUsage'],
$data['locale']
$data['locale'],
$data['freeShippingForCountries'],
$data['freeShippingForModules']
);
// If Update mode
@@ -774,7 +795,9 @@ class CouponController extends BaseAdminController
$coupon->getIsCumulative(),
$coupon->getIsRemovingPostage(),
$coupon->getMaxUsage(),
$coupon->getLocale()
$coupon->getLocale(),
$coupon->getFreeShippingForCountries(),
$coupon->getFreeShippingForModules()
);
$couponEvent->setCouponModel($coupon);
$couponEvent->setConditions($conditions);

View File

@@ -15,10 +15,10 @@ namespace Thelia\Controller\Front;
use Symfony\Component\Routing\Router;
use Thelia\Controller\BaseController;
use Thelia\Core\HttpFoundation\Response;
use Thelia\Core\Template\TemplateDefinition;
use Thelia\Core\Template\TemplateHelper;
use Thelia\Model\AddressQuery;
use Thelia\Model\ModuleQuery;
use Thelia\Tools\URL;
class BaseFrontController extends BaseController
@@ -65,7 +65,15 @@ class BaseFrontController extends BaseController
protected function checkValidDelivery()
{
$order = $this->getSession()->getOrder();
if (null === $order || null === $order->chosenDeliveryAddress || null === $order->getDeliveryModuleId() || null === AddressQuery::create()->findPk($order->chosenDeliveryAddress) || null === ModuleQuery::create()->findPk($order->getDeliveryModuleId())) {
if (null === $order
||
null === $order->getChoosenDeliveryAddress()
||
null === $order->getDeliveryModuleId()
||
null === AddressQuery::create()->findPk($order->getChoosenDeliveryAddress())
||
null === ModuleQuery::create()->findPk($order->getDeliveryModuleId())) {
$this->redirectToRoute("order.delivery");
}
}
@@ -73,13 +81,21 @@ class BaseFrontController extends BaseController
protected function checkValidInvoice()
{
$order = $this->getSession()->getOrder();
if (null === $order || null === $order->chosenInvoiceAddress || null === $order->getPaymentModuleId() || null === AddressQuery::create()->findPk($order->chosenInvoiceAddress) || null === ModuleQuery::create()->findPk($order->getPaymentModuleId())) {
if (null === $order
||
null === $order->getChoosenInvoiceAddress()
||
null === $order->getPaymentModuleId()
||
null === AddressQuery::create()->findPk($order->getChoosenInvoiceAddress())
||
null === ModuleQuery::create()->findPk($order->getPaymentModuleId())) {
$this->redirectToRoute("order.invoice");
}
}
/**
* @return ParserInterface instance parser
* @return TemplateDefinition the template
*/
protected function getParser($template = null)
{

View File

@@ -31,19 +31,41 @@ class CouponConsumeEvent extends ActionEvent
/** @var bool If Coupon is valid or if Customer meets coupon conditions */
protected $isValid = null;
/** @var bool true if coupon offers free shipping */
protected $freeShipping = false;
/**
* Constructor
*
* @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
* @param bool $isValid If Coupon is valid or f Customer meets coupon conditions
* @param bool $freeShipping true if coupon offers free shipping
*/
public function __construct($code, $discount = null, $isValid = null)
public function __construct($code, $discount = null, $isValid = null, $freeShipping = false)
{
$this->code = $code;
$this->discount = $discount;
$this->isValid = $isValid;
$this->discount = $discount;
$this->freeShipping = $freeShipping;
}
/**
* @param boolean $freeShipping
*/
public function setFreeShipping($freeShipping)
{
$this->freeShipping = $freeShipping;
return $this;
}
/**
* @return boolean
*/
public function getFreeShipping()
{
return $this->freeShipping;
}
/**

View File

@@ -73,6 +73,12 @@ class CouponCreateOrUpdateEvent extends ActionEvent
/** @var string Language code ISO (ex: fr_FR) */
protected $locale = null;
/** @var array ID of Countries to which shipping is free */
protected $freeShippingForCountries;
/** @var array ID of Shipping modules for which shipping is free */
protected $freeShippingForMethods;
/**
* Constructor
*
@@ -91,8 +97,13 @@ class CouponCreateOrUpdateEvent extends ActionEvent
* @param boolean $isRemovingPostage Is removing Postage
* @param int $maxUsage Coupon quantity
* @param string $locale Coupon Language code ISO (ex: fr_FR)
* @param array $freeShippingForCountries ID of Countries to which shipping is free
* @param array $freeShippingForMethods ID of Shipping modules for which shipping is free
*/
public function __construct($code, $serviceId, $title, array $effects, $shortDescription, $description, $isEnabled, \DateTime $expirationDate, $isAvailableOnSpecialOffers, $isCumulative, $isRemovingPostage, $maxUsage, $locale)
public function __construct(
$code, $serviceId, $title, array $effects, $shortDescription, $description,
$isEnabled, \DateTime $expirationDate, $isAvailableOnSpecialOffers, $isCumulative,
$isRemovingPostage, $maxUsage, $locale, $freeShippingForCountries, $freeShippingForMethods)
{
$this->code = $code;
$this->description = $description;
@@ -107,6 +118,44 @@ class CouponCreateOrUpdateEvent extends ActionEvent
$this->serviceId = $serviceId;
$this->locale = $locale;
$this->setEffects($effects);
$this->freeShippingForCountries = $freeShippingForCountries;
$this->freeShippingForMethods = $freeShippingForMethods;
}
/**
* @param array $freeShippingForCountries
* @return $this
*/
public function setFreeShippingForCountries($freeShippingForCountries)
{
$this->freeShippingForCountries = $freeShippingForCountries;
return $this;
}
/**
* @return array
*/
public function getFreeShippingForCountries()
{
return $this->freeShippingForCountries;
}
/**
* @param array $freeShippingForMethods
* @return $this
*/
public function setFreeShippingForMethods($freeShippingForMethods)
{
$this->freeShippingForMethods = $freeShippingForMethods;
return $this;
}
/**
* @return array
*/
public function getFreeShippingForMethods()
{
return $this->freeShippingForMethods;
}
/**

View File

@@ -178,7 +178,9 @@ class Coupon extends BaseI18nLoop implements PropelSearchLoopInterface
$coupon->getIsAvailableOnSpecialOffers(),
$coupon->getIsEnabled(),
$coupon->getMaxUsage(),
$coupon->getExpirationDate()
$coupon->getExpirationDate(),
$coupon->getFreeShippingForCountries(),
$coupon->getFreeShippingForModules()
);
$cleanedConditions = array();

View File

@@ -204,9 +204,9 @@ class DataAccessFunctions extends AbstractSmartyPlugin
case 'discount':
return $order->getDiscount();
case 'delivery_address':
return $order->chosenDeliveryAddress;
return $order->getChoosenDeliveryAddress();
case 'invoice_address':
return $order->chosenInvoiceAddress;
return $order->getChoosenInvoiceAddress();
case 'delivery_module':
return $order->getDeliveryModuleId();
case 'payment_module':

View File

@@ -82,7 +82,7 @@ class Security extends AbstractSmartyPlugin
$order = $this->request->getSession()->getOrder();
/* Does address and module still exists ? We assume address owner can't change neither module type */
if ($order !== null) {
$checkAddress = AddressQuery::create()->findPk($order->chosenDeliveryAddress);
$checkAddress = AddressQuery::create()->findPk($order->getChoosenDeliveryAddress());
$checkModule = ModuleQuery::create()->findPk($order->getDeliveryModuleId());
}
if (null === $order || null == $checkAddress || null === $checkModule) {

View File

@@ -77,7 +77,7 @@ class BaseFacade implements FacadeInterface
public function getDeliveryAddress()
{
try {
return AddressQuery::create()->findPk($this->getRequest()->getSession()->getOrder()->chosenDeliveryAddress);
return AddressQuery::create()->findPk($this->getRequest()->getSession()->getOrder()->getChoosenDeliveryAddress());
}
catch(\Exception $ex) {
throw new \LogicException("Failed to get delivery address (" . $ex->getMessage() . ")");

View File

@@ -107,7 +107,9 @@ class CouponFactory
$model->getIsAvailableOnSpecialOffers(),
$model->getIsEnabled(),
$model->getMaxUsage(),
$model->getExpirationDate()
$model->getExpirationDate(),
$model->getFreeShippingForCountries(),
$model->getFreeShippingForModules()
);
/** @var ConditionFactory $conditionFactory */

View File

@@ -15,7 +15,14 @@ namespace Thelia\Coupon;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Thelia\Condition\Implementation\ConditionInterface;
use Thelia\Coupon\Type\CouponInterface;
use Thelia\Log\Tlog;
use Thelia\Model\AddressQuery;
use Thelia\Model\Base\CouponModule;
use Thelia\Model\Coupon;
use Thelia\Model\CouponCountry;
use Thelia\Model\Order;
use Thelia\Model\OrderAddress;
use Thelia\Model\OrderAddressQuery;
/**
* Manage how Coupons could interact with a Checkout
@@ -78,9 +85,10 @@ class CouponManager
* Check if there is a Coupon removing Postage
* @return bool
*/
public function isCouponRemovingPostage()
public function isCouponRemovingPostage(Order $order)
{
$coupons = $this->facade->getCurrentCoupons();
if (count($coupons) == 0) {
return false;
}
@@ -89,7 +97,60 @@ class CouponManager
/** @var CouponInterface $coupon */
foreach ($couponsKept as $coupon) {
if ($coupon->isRemovingPostage()) {
// Check if delivery country is on the list of countries for which delivery is free
// If the list is empty, the shipping is free for all countries.
$couponCountries = $coupon->getFreeShippingForCountries();
if (! $couponCountries->isEmpty()) {
if (null === $deliveryAddress = AddressQuery::create()->findPk($order->getChoosenDeliveryAddress())) {
continue;
}
$countryValid = false;
$deliveryCountryId = $deliveryAddress->getCountryId();
/** @var CouponCountry $couponCountry */
foreach($couponCountries as $couponCountry) {
if ($deliveryCountryId == $couponCountry->getCountryId()) {
$countryValid = true;
break;
}
}
if (! $countryValid) {
continue;
}
}
// Check if shipping method is on the list of methods for which delivery is free
// If the list is empty, the shipping is free for all methods.
$couponModules = $coupon->getFreeShippingForModules();
if (! $couponModules->isEmpty()) {
$moduleValid = false;
$shippingModuleId = $order->getDeliveryModuleId();
/** @var CouponModule $couponModule */
foreach($couponModules as $couponModule) {
if ($shippingModuleId == $couponModule->getModuleId()) {
$moduleValid = true;
break;
}
}
if (! $moduleValid) {
continue;
}
}
// All conditions are met, the shipping is free !
return true;
}
}

View File

@@ -12,11 +12,13 @@
namespace Thelia\Coupon\Type;
use Thelia\Condition\ConditionCollection;
use Thelia\Condition\ConditionEvaluator;
use Thelia\Condition\ConditionOrganizerInterface;
use Thelia\Core\Translation\Translator;
use Thelia\Coupon\FacadeInterface;
use Thelia\Condition\ConditionCollection;
use Thelia\Condition\ConditionOrganizerInterface;
use Thelia\Model\CouponCountry;
use Thelia\Model\CouponModule;
/**
* Assist in writing a CouponInterface
@@ -88,6 +90,12 @@ abstract class CouponAbstract implements CouponInterface
/** @var bool if Coupon is available for Products already on special offers */
protected $isAvailableOnSpecialOffers = false;
/** @var CouponCountry[] list of country IDs for which shipping is free. All if empty*/
protected $freeShippingForCountries = [];
/** @var CouponModule[] list of shipping module IDs for which shippiog is free. All if empty*/
protected $freeShippingForModules = [];
/**
* Constructor
*
@@ -115,23 +123,7 @@ abstract class CouponAbstract implements CouponInterface
}
/**
* Set Coupon
*
* @param FacadeInterface $facade Provides necessary value from Thelia
* @param string $code Coupon code (ex: XMAS)
* @param string $title Coupon title (ex: Coupon for XMAS)
* @param string $shortDescription Coupon short description
* @param string $description Coupon description
* @param array $effects Coupon effects params
* @param bool $isCumulative If Coupon is cumulative
* @param bool $isRemovingPostage If Coupon is removing postage
* @param bool $isAvailableOnSpecialOffers If available on Product already
* on special offer price
* @param bool $isEnabled False if Coupon is disabled by admin
* @param int $maxUsage How many usage left
* @param \Datetime $expirationDate When the Code is expiring
*
* @return $this
* @inheritdoc
*/
public function set(
FacadeInterface $facade,
@@ -145,7 +137,9 @@ abstract class CouponAbstract implements CouponInterface
$isAvailableOnSpecialOffers,
$isEnabled,
$maxUsage,
\DateTime $expirationDate
\DateTime $expirationDate,
$freeShippingForCountries,
$freeShippingForModules
)
{
$this->code = $code;
@@ -165,6 +159,9 @@ abstract class CouponAbstract implements CouponInterface
$this->effects = $effects;
$this->amount = $effects[self::INPUT_AMOUNT_NAME];
$this->freeShippingForCountries = $freeShippingForCountries;
$this->freeShippingForModules = $freeShippingForModules;
return $this;
}
@@ -230,6 +227,20 @@ abstract class CouponAbstract implements CouponInterface
return $this->isRemovingPostage;
}
/**
* @return array list of country IDs for which shipping is free. All if empty
*/
public function getFreeShippingForCountries() {
return $this->freeShippingForCountries;
}
/**
* @return array list of module IDs for which shipping is free. All if empty
*/
public function getFreeShippingForModules() {
return $this->freeShippingForModules;
}
/**
* Return effects generated by the coupon
* A negative value

View File

@@ -12,8 +12,11 @@
namespace Thelia\Coupon\Type;
use Propel\Runtime\Collection\ObjectCollection;
use Thelia\Condition\ConditionCollection;
use Thelia\Coupon\FacadeInterface;
use Thelia\Model\CouponCountry;
use Thelia\Model\CouponModule;
/**
* Represents a Coupon ready to be processed in a Checkout process
@@ -31,13 +34,6 @@ interface CouponInterface
*/
public function getName();
/**
* Get I18n amount input name
*
* @return string
*/
public function getInputName();
/**
* Get I18n tooltip
*
@@ -68,6 +64,9 @@ interface CouponInterface
* @param bool $isEnabled False if Coupon is disabled by admin
* @param int $maxUsage How many usage left
* @param \Datetime $expirationDate When the Code is expiring
* @param ObjectCollection $freeShippingForCountries list of countries which shipping is free. All if empty
* @param ObjectCollection $freeShippingForModules list of modules for which shipping is free. All if empty
*/
public function set(
FacadeInterface $facade,
@@ -81,7 +80,10 @@ interface CouponInterface
$isAvailableOnSpecialOffers,
$isEnabled,
$maxUsage,
\DateTime $expirationDate);
\DateTime $expirationDate,
$freeShippingForCountries,
$freeShippingForModules
);
/**
* Return Coupon code (ex: XMAS)
@@ -218,4 +220,13 @@ interface CouponInterface
*/
public function getExtendedInputs();
/**
* @return ObjectCollection list of country IDs for which shipping is free. All if empty
*/
public function getFreeShippingForCountries();
/**
* @return ObjectCollection list of module IDs for which shipping is free. All if empty
*/
public function getFreeShippingForModules();
}

View File

@@ -35,23 +35,7 @@ class RemoveXPercent extends CouponAbstract
);
/**
* Set Coupon
*
* @param FacadeInterface $facade Provides necessary value from Thelia
* @param string $code Coupon code (ex: XMAS)
* @param string $title Coupon title (ex: Coupon for XMAS)
* @param string $shortDescription Coupon short description
* @param string $description Coupon description
* @param array $effects Coupon effects params
* @param bool $isCumulative If Coupon is cumulative
* @param bool $isRemovingPostage If Coupon is removing postage
* @param bool $isAvailableOnSpecialOffers If available on Product already
* on special offer price
* @param bool $isEnabled False if Coupon is disabled by admin
* @param int $maxUsage How many usage left
* @param \Datetime $expirationDate When the Code is expiring
*
* @return $this
* @inheritdoc
*/
public function set(
FacadeInterface $facade,
@@ -65,12 +49,18 @@ class RemoveXPercent extends CouponAbstract
$isAvailableOnSpecialOffers,
$isEnabled,
$maxUsage,
\DateTime $expirationDate
\DateTime $expirationDate,
$freeShippingForCountries,
$freeShippingForModules
)
{
parent::set(
$facade, $code, $title, $shortDescription, $description, $effects, $isCumulative, $isRemovingPostage, $isAvailableOnSpecialOffers, $isEnabled, $maxUsage, $expirationDate
$facade, $code, $title, $shortDescription, $description, $effects,
$isCumulative, $isRemovingPostage, $isAvailableOnSpecialOffers, $isEnabled, $maxUsage, $expirationDate,
$freeShippingForCountries,
$freeShippingForModules
);
$this->percentage = $effects[self::INPUT_PERCENTAGE_NAME];
return $this;

View File

@@ -18,7 +18,14 @@ use Symfony\Component\Validator\Constraints\NotBlank;
use Symfony\Component\Validator\Constraints\NotEqualTo;
use Symfony\Component\Validator\ExecutionContextInterface;
use Thelia\Core\Translation\Translator;
use Thelia\Model\Base\CountryI18n;
use Thelia\Model\Base\CountryQuery;
use Thelia\Model\Base\LangQuery;
use Thelia\Model\Base\ModuleQuery;
use Thelia\Model\CountryI18nQuery;
use Thelia\Model\Module;
use Thelia\Model\ModuleI18nQuery;
use Thelia\Module\BaseModule;
/**
* Allow to build a form Coupon
@@ -36,6 +43,33 @@ class CouponCreationForm extends BaseForm
*/
protected function buildForm()
{
// Create countries and shipping modules list
$countries = [0 => ' '];
$list = CountryQuery::create()->find();
/** @var Country $item */
foreach($list as $item) {
$countries[$item->getId()] = $item->getTitle();
}
asort($countries);
$countries[0] = Translator::getInstance()->trans("All countries");
$modules = [0 => ' '];
$list = ModuleQuery::create()->filterByActivate(BaseModule::IS_ACTIVATED)->filterByType(BaseModule::DELIVERY_MODULE_TYPE)->find();
/** @var Module $item */
foreach($list as $item) {
$modules[$item->getId()] = $item->getTitle();
}
asort($modules);
$modules[0] = Translator::getInstance()->trans("All shipping methods");
$this->formBuilder
->add(
'code',
@@ -116,6 +150,22 @@ class CouponCreationForm extends BaseForm
'text',
array()
)
->add(
'freeShippingForCountries',
'choice',
array(
'multiple' => true,
'choices' => $countries
)
)
->add(
'freeShippingForModules',
'choice',
array(
'multiple' => true,
'choices' => $modules
)
)
->add(
'isAvailableOnSpecialOffers',
'text',

View File

@@ -25,6 +25,8 @@ namespace Thelia\Model;
use Propel\Runtime\Propel;
use Thelia\Model\Base\Coupon as BaseCoupon;
use Thelia\Model\Base\CouponCountryQuery;
use Thelia\Model\Base\CouponModuleQuery;
use Thelia\Model\Exception\InvalidArgumentException;
use Thelia\Model\Map\CouponTableMap;
use Thelia\Model\Tools\ModelEventDispatcherTrait;
@@ -127,11 +129,13 @@ class Coupon extends BaseCoupon
;
}
$con->commit();
} catch (\Exception $ex) {
$con->rollback();
$con->rollback();
throw $ex;
throw $ex;
}
}
@@ -248,4 +252,21 @@ class Coupon extends BaseCoupon
return $effects;
}
/**
* Return the countries for which free shipping is valid
* @return array|mixed|\Propel\Runtime\Collection\ObjectCollection
*/
public function getFreeShippingForCountries() {
return CouponCountryQuery::create()->filterByCouponId($this->getId())->find();
}
/**
* Return the modules for which free shipping is valid
*
* @return array|mixed|\Propel\Runtime\Collection\ObjectCollection
*/
public function getFreeShippingForModules() {
return CouponModuleQuery::create()->filterByCouponId($this->getId())->find();
}
}

View File

@@ -121,8 +121,8 @@ class TaxEngine
/* is there a logged in customer ? */
if (null !== $customer = $this->session->getCustomerUser()) {
if (null !== $this->session->getOrder()
&& null !== $this->session->getOrder()->chosenDeliveryAddress
&& null !== $currentDeliveryAddress = AddressQuery::create()->findPk($this->session->getOrder()->chosenDeliveryAddress)) {
&& null !== $this->session->getOrder()->getChoosenDeliveryAddress()
&& null !== $currentDeliveryAddress = AddressQuery::create()->findPk($this->session->getOrder()->getChoosenDeliveryAddress())) {
$this->taxCountry = $currentDeliveryAddress->getCountry();
} else {
$customerDefaultAddress = $customer->getDefaultAddress();

View File

@@ -196,7 +196,7 @@ class OrderTest extends \PHPUnit_Framework_TestCase
$this->assertEquals(
321,
$this->orderEvent->getOrder()->chosenDeliveryAddress
$this->orderEvent->getOrder()->getChoosenDeliveryAddress()
);
}
@@ -208,7 +208,7 @@ class OrderTest extends \PHPUnit_Framework_TestCase
$this->assertEquals(
654,
$this->orderEvent->getOrder()->chosenInvoiceAddress
$this->orderEvent->getOrder()->getChoosenInvoiceAddress()
);
}
@@ -263,8 +263,8 @@ class OrderTest extends \PHPUnit_Framework_TestCase
$paymentModuleClass = $paymentModule->getFullNamespace();
$this->container->set(sprintf('module.%s', $paymentModule->getCode()), new $paymentModuleClass());
$this->orderEvent->getOrder()->chosenDeliveryAddress = $validDeliveryAddress->getId();
$this->orderEvent->getOrder()->chosenInvoiceAddress = $validInvoiceAddress->getId();
$this->orderEvent->getOrder()->setChoosenDeliveryAddress($validDeliveryAddress->getId());
$this->orderEvent->getOrder()->setChoosenInvoiceAddress($validInvoiceAddress->getId());
$this->orderEvent->getOrder()->setDeliveryModuleId($deliveryModule->getId());
$this->orderEvent->getOrder()->setPostage(20);
$this->orderEvent->getOrder()->setPaymentModuleId($paymentModule->getId());

View File

@@ -11,6 +11,7 @@
/*************************************************************************************/
namespace Thelia\Coupon;
use Propel\Runtime\Collection\ObjectCollection;
use Thelia\Condition\ConditionCollection;
use Thelia\Condition\ConditionEvaluator;
use Thelia\Condition\ConditionFactory;
@@ -18,7 +19,9 @@ use Thelia\Condition\Implementation\MatchForTotalAmount;
use Thelia\Condition\Operators;
use Thelia\Coupon\Type\RemoveXAmount;
use Thelia\Model\Coupon;
use Thelia\Model\CouponCountry;
use Thelia\Model\CurrencyQuery;
use Thelia\Model\Order;
/**
* Unit Test CouponManager Class
@@ -167,8 +170,13 @@ Sed facilisis pellentesque nisl, eu tincidunt erat scelerisque a. Nullam malesua
$actual = $couponManager->getDiscount();
$expected = 21 + 21.50;
$order = new Order();
$order->setChoosenDeliveryAddress(1);
$order->setDeliveryModuleId(1);
$this->assertEquals($expected, $actual);
$this->assertTrue($couponManager->isCouponRemovingPostage());
$this->assertTrue($couponManager->isCouponRemovingPostage($order));
}
/**
@@ -390,7 +398,12 @@ Sed facilisis pellentesque nisl, eu tincidunt erat scelerisque a. Nullam malesua
$coupon = new RemoveXAmount($stubFacade);
$date = new \DateTime();
$coupon->set($stubFacade, 'XMAS', '', '', '', array('amount' => 21.00), true, true, true, true, 254, $date->setTimestamp(strtotime("today + 3 months")) );
$coupon->set(
$stubFacade, 'XMAS', '', '', '', array('amount' => 21.00),
true, true, true, true, 254, $date->setTimestamp(strtotime("today + 3 months")),
new ObjectCollection(),
new ObjectCollection()
);
$condition1 = new MatchForTotalAmount($stubFacade);
$operators = array(
@@ -455,7 +468,12 @@ Sed facilisis pellentesque nisl, eu tincidunt erat scelerisque a. Nullam malesua
$coupon = new RemoveXAmount($stubFacade);
$date = new \DateTime();
$coupon->set($stubFacade, 'XMAS', '', '', '', array('amount' => 21.00), true, true, true, true, 254, $date->setTimestamp(strtotime("today + 3 months")) );
$coupon->set(
$stubFacade, 'XMAS', '', '', '', array('amount' => 21.00),
true, true, true, true, 254, $date->setTimestamp(strtotime("today + 3 months")),
new ObjectCollection(),
new ObjectCollection()
);
$condition1 = new MatchForTotalAmount($stubFacade);
$operators = array(

View File

@@ -11,6 +11,7 @@
/*************************************************************************************/
namespace Thelia\Coupon\Type;
use Propel\Runtime\Collection\ObjectCollection;
use Thelia\Condition\ConditionCollection;
use Thelia\Condition\ConditionEvaluator;
use Thelia\Condition\Implementation\MatchForTotalAmount;
@@ -114,7 +115,12 @@ class RemoveXAmountTest extends \PHPUnit_Framework_TestCase
Sed facilisis pellentesque nisl, eu tincidunt erat scelerisque a. Nullam malesuada tortor vel erat volutpat tincidunt. In vehicula diam est, a convallis eros scelerisque ut. Donec aliquet venenatis iaculis. Ut a arcu gravida, placerat dui eu, iaculis nisl. Quisque adipiscing orci sit amet dui dignissim lacinia. Sed vulputate lorem non dolor adipiscing ornare. Morbi ornare id nisl id aliquam. Ut fringilla elit ante, nec lacinia enim fermentum sit amet. Aenean rutrum lorem eu convallis pharetra. Cras malesuada varius metus, vitae gravida velit. Nam a varius ipsum, ac commodo dolor. Phasellus nec elementum elit. Etiam vel adipiscing leo.';
$coupon->set($stubFacade, 'XMAS', 'XMAS Coupon', 'Coupon for Springbreak removing 10€ if you have a cart between 40.00€ and 400.00€ (excluded)', $description, array('amount' => 10.00), true, true, true, true, 254, $date->setTimestamp(strtotime("today + 3 months")) );
$coupon->set(
$stubFacade, 'XMAS', 'XMAS Coupon', 'Coupon for Springbreak removing 10€ if you have a cart between 40.00€ and 400.00€ (excluded)',
$description, array('amount' => 10.00), true, true, true, true, 254, $date->setTimestamp(strtotime("today + 3 months")),
new ObjectCollection(),
new ObjectCollection()
);
$condition1 = new MatchForTotalAmount($stubFacade);
$operators = array(

View File

@@ -11,6 +11,7 @@
/*************************************************************************************/
namespace Thelia\Coupon\Type;
use Propel\Runtime\Collection\ObjectCollection;
use Thelia\Condition\ConditionCollection;
use Thelia\Condition\ConditionEvaluator;
use Thelia\Condition\Implementation\MatchForTotalAmount;
@@ -103,7 +104,13 @@ class RemoveXPercentTest extends \PHPUnit_Framework_TestCase
Sed facilisis pellentesque nisl, eu tincidunt erat scelerisque a. Nullam malesuada tortor vel erat volutpat tincidunt. In vehicula diam est, a convallis eros scelerisque ut. Donec aliquet venenatis iaculis. Ut a arcu gravida, placerat dui eu, iaculis nisl. Quisque adipiscing orci sit amet dui dignissim lacinia. Sed vulputate lorem non dolor adipiscing ornare. Morbi ornare id nisl id aliquam. Ut fringilla elit ante, nec lacinia enim fermentum sit amet. Aenean rutrum lorem eu convallis pharetra. Cras malesuada varius metus, vitae gravida velit. Nam a varius ipsum, ac commodo dolor. Phasellus nec elementum elit. Etiam vel adipiscing leo.';
$coupon->set($stubFacade, 'XMAS', 'XMAS Coupon', 'Coupon for Springbreak removing 10% if you have a cart between 40.00€ and 400.00€ (excluded)', $description, array('amount' => 0.00, 'percentage' => 10.00), true, true, true, true, 254, $date->setTimestamp(strtotime("today + 3 months")) );
$coupon->set(
$stubFacade, 'XMAS', 'XMAS Coupon', 'Coupon for Springbreak removing 10% if you have a cart between 40.00€ and 400.00€ (excluded)',
$description, array('amount' => 0.00, 'percentage' => 10.00), true, true, true, true,
254, $date->setTimestamp(strtotime("today + 3 months")),
new ObjectCollection(),
new ObjectCollection()
);
$condition1 = new MatchForTotalAmount($stubFacade);
$operators = array(

View File

@@ -174,7 +174,7 @@ class CartController extends BaseFrontController
$order = $this->getSession()->getOrder();
if (null !== $order) {
$deliveryModule = $order->getModuleRelatedByDeliveryModuleId();
$deliveryAddress = AddressQuery::create()->findPk($order->chosenDeliveryAddress);
$deliveryAddress = AddressQuery::create()->findPk($order->getChoosenDeliveryAddress());
if (null !== $deliveryModule && null !== $deliveryAddress) {
$moduleInstance = $deliveryModule->getModuleInstance($this->container);

View File

@@ -72,7 +72,7 @@ class CouponController extends BaseFrontController
if (null !== $order) {
$deliveryModule = $order->getModuleRelatedByDeliveryModuleId();
$deliveryAddress = AddressQuery::create()->findPk($order->chosenDeliveryAddress);
$deliveryAddress = AddressQuery::create()->findPk($order->getChoosenDeliveryAddress());
if (null !== $deliveryModule && null !== $deliveryAddress) {

View File

@@ -303,5 +303,17 @@ $(function($){
});
};
// Shipping conditions
$('#is-removing-postage').change(function(ev) {
if ($(this).is(':checked')) {
$('.free-postage-conditions').stop().slideDown();
}
else {
$('.free-postage-conditions').stop().slideUp();
}
})
$.couponManager.onUsageUnlimitedChange();
$('#is-removing-postage').change();
});

View File

@@ -6,7 +6,7 @@
<div class="form-group">
<label for="{$categories_field_name}-value">{intl l="The selected categories :"}</label>
<select required multiple size="5" class="form-control" id="{$categories_field_name}-value" name="{$categories_field_name}[value][]">
{loop type="category-tree" category=0 name="list-of-categories"}
{loop type="category-tree" category=0 name="list-of-categories" backend_context=1}
<option style="padding-left: {$LEVEL * 20}px" value="{$ID}" {if in_array($ID, $values)}selected="selected"{/if}>{$TITLE}</option>
{/loop}
</select>

View File

@@ -6,7 +6,7 @@
<div class="form-group">
<label for="{$products_field_name}-value">{intl l="The selected products :"}</label>
<select required multiple size="5" class="form-control" id="{$products_field_name}-value" name="{$products_field_name}[value][]">
{loop type="product" name="list-of-products" order="alpha"}
{loop type="product" name="list-of-products" order="alpha" backend_context=1}
<option value="{$ID}" {if in_array($ID, $values)}selected="selected"{/if}>{$TITLE}</option>
{/loop}
</select>

View File

@@ -6,7 +6,7 @@
<div class="form-group">
<label for="{$countries_field_name}-value">{intl l="The selected countries :"}</label>
<select required multiple size="5" class="form-control" id="{$countries_field_name}-value" name="{$countries_field_name}[value][]">
{loop type="country" name="list-of-countries" order="alpha"}
{loop type="country" name="list-of-countries" order="alpha" backend_context=1}
<option style="padding-left: {$LEVEL * 20}px" value="{$ID}" {if in_array($ID, $values)}selected="selected"{/if}>{$TITLE}</option>
{/loop}
</select>

View File

@@ -6,7 +6,7 @@
<div class="form-group">
<label for="{$customers_field_name}-value">{intl l="The selected customer :"}</label>
<select required multiple size="5" class="form-control" id="{$customers_field_name}-value" name="{$customers_field_name}[value][]">
{loop type="customer" name="list-of-customers" order="lastname,firstname" current="0" backend_context="1"}
{loop type="customer" name="list-of-customers" order="lastname,firstname" current="0" backend_context=1}
<option value="{$ID}" {if in_array($ID, $values)}selected="selected"{/if}>{$LASTNAME} {$FIRSTNAME} {$REF}</option>
{/loop}
</select>

View File

@@ -123,10 +123,9 @@
<div class="form-group {if $error}has-error{/if}">
<label for="for-countries-only">{intl l="Free shipping to countries :"}</label>
<select multiple size="5" class="form-control" id="for-countries-only" name="{$name}">
<option value="">{intl l="All countries"}</option>
{loop type="country" name="list-of-countries" order="alpha" backend_context="1"}
<option style="padding-left: {$LEVEL * 20}px" value="{$ID}">{$TITLE}</option>
{/loop}
{foreach $choices as $choice}
<option value="{$choice->value}" {if in_array($choice->value, $value)}selected="selected"{/if}>{$choice->label}</option>
{/foreach}
</select>
<span class="label-help-block">{intl l='Use Ctrl+click to select (or deselect) more that one country'}</span>
</div>
@@ -136,16 +135,14 @@
<div class="form-group {if $error}has-error{/if}">
<label for="for-modules-only">{intl l="Free shipping for methods :"}</label>
<select multiple size="5" class="form-control" id="for-modules-only" name="{$name}">
<option value="">{intl l="All shipping methods"}</option>
{loop type="module" name="list-of-shipping-moddule" module_type=2 order=alpha backend_context=1}
<option value="{$ID}">{$TITLE}</option>
{/loop}
{foreach $choices as $choice}
<option value="{$choice->value}" {if in_array($choice->value, $value)}selected="selected"{/if}>{$choice->label}</option>
{/foreach}
</select>
<span class="label-help-block">{intl l='Use Ctrl+click to select (or deselect) more that one shipping method'}</span>
</div>
{/form_field}
</div>
</div>
<div class="col-md-3">