diff --git a/core/lib/Thelia/Action/Coupon.php b/core/lib/Thelia/Action/Coupon.php index aaa827a9d..8fbb4d378 100644 --- a/core/lib/Thelia/Action/Coupon.php +++ b/core/lib/Thelia/Action/Coupon.php @@ -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); diff --git a/core/lib/Thelia/Action/Order.php b/core/lib/Thelia/Action/Order.php index bd8534219..9b710a858 100644 --- a/core/lib/Thelia/Action/Order.php +++ b/core/lib/Thelia/Action/Order.php @@ -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 */ diff --git a/core/lib/Thelia/Config/Resources/coupon.xml b/core/lib/Thelia/Config/Resources/coupon.xml index 68de33c37..68486c969 100644 --- a/core/lib/Thelia/Config/Resources/coupon.xml +++ b/core/lib/Thelia/Config/Resources/coupon.xml @@ -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"> - - - + + + + + + + + + + + @@ -83,5 +91,4 @@ - diff --git a/core/lib/Thelia/Controller/Admin/CouponController.php b/core/lib/Thelia/Controller/Admin/CouponController.php index 2cade8a78..6931d1345 100644 --- a/core/lib/Thelia/Controller/Admin/CouponController.php +++ b/core/lib/Thelia/Controller/Admin/CouponController.php @@ -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); diff --git a/core/lib/Thelia/Controller/Front/BaseFrontController.php b/core/lib/Thelia/Controller/Front/BaseFrontController.php index e9bc4754b..665b63400 100644 --- a/core/lib/Thelia/Controller/Front/BaseFrontController.php +++ b/core/lib/Thelia/Controller/Front/BaseFrontController.php @@ -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) { diff --git a/core/lib/Thelia/Core/Event/Coupon/CouponConsumeEvent.php b/core/lib/Thelia/Core/Event/Coupon/CouponConsumeEvent.php index a6875105a..096efc4e9 100644 --- a/core/lib/Thelia/Core/Event/Coupon/CouponConsumeEvent.php +++ b/core/lib/Thelia/Core/Event/Coupon/CouponConsumeEvent.php @@ -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; } /** diff --git a/core/lib/Thelia/Core/Event/Coupon/CouponCreateOrUpdateEvent.php b/core/lib/Thelia/Core/Event/Coupon/CouponCreateOrUpdateEvent.php index b5a79ba36..041ea9fc3 100644 --- a/core/lib/Thelia/Core/Event/Coupon/CouponCreateOrUpdateEvent.php +++ b/core/lib/Thelia/Core/Event/Coupon/CouponCreateOrUpdateEvent.php @@ -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; } /** diff --git a/core/lib/Thelia/Core/Template/Loop/Coupon.php b/core/lib/Thelia/Core/Template/Loop/Coupon.php index 7d0a3899d..1aca06a12 100644 --- a/core/lib/Thelia/Core/Template/Loop/Coupon.php +++ b/core/lib/Thelia/Core/Template/Loop/Coupon.php @@ -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(); diff --git a/core/lib/Thelia/Core/Template/Smarty/Plugins/DataAccessFunctions.php b/core/lib/Thelia/Core/Template/Smarty/Plugins/DataAccessFunctions.php index d439e7d63..588cbe76d 100644 --- a/core/lib/Thelia/Core/Template/Smarty/Plugins/DataAccessFunctions.php +++ b/core/lib/Thelia/Core/Template/Smarty/Plugins/DataAccessFunctions.php @@ -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': diff --git a/core/lib/Thelia/Core/Template/Smarty/Plugins/Security.php b/core/lib/Thelia/Core/Template/Smarty/Plugins/Security.php index 85ebb4257..83f697025 100644 --- a/core/lib/Thelia/Core/Template/Smarty/Plugins/Security.php +++ b/core/lib/Thelia/Core/Template/Smarty/Plugins/Security.php @@ -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) { diff --git a/core/lib/Thelia/Coupon/BaseFacade.php b/core/lib/Thelia/Coupon/BaseFacade.php index eac753376..3a4a74b33 100644 --- a/core/lib/Thelia/Coupon/BaseFacade.php +++ b/core/lib/Thelia/Coupon/BaseFacade.php @@ -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() . ")"); diff --git a/core/lib/Thelia/Coupon/CouponFactory.php b/core/lib/Thelia/Coupon/CouponFactory.php index e577061b7..271e74847 100644 --- a/core/lib/Thelia/Coupon/CouponFactory.php +++ b/core/lib/Thelia/Coupon/CouponFactory.php @@ -107,7 +107,9 @@ class CouponFactory $model->getIsAvailableOnSpecialOffers(), $model->getIsEnabled(), $model->getMaxUsage(), - $model->getExpirationDate() + $model->getExpirationDate(), + $model->getFreeShippingForCountries(), + $model->getFreeShippingForModules() ); /** @var ConditionFactory $conditionFactory */ diff --git a/core/lib/Thelia/Coupon/CouponManager.php b/core/lib/Thelia/Coupon/CouponManager.php index 779b28c11..6d7b5f433 100644 --- a/core/lib/Thelia/Coupon/CouponManager.php +++ b/core/lib/Thelia/Coupon/CouponManager.php @@ -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; } } diff --git a/core/lib/Thelia/Coupon/Type/CouponAbstract.php b/core/lib/Thelia/Coupon/Type/CouponAbstract.php index dee230edc..8ba08fc35 100644 --- a/core/lib/Thelia/Coupon/Type/CouponAbstract.php +++ b/core/lib/Thelia/Coupon/Type/CouponAbstract.php @@ -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 diff --git a/core/lib/Thelia/Coupon/Type/CouponInterface.php b/core/lib/Thelia/Coupon/Type/CouponInterface.php index 12b54db15..d667b4865 100644 --- a/core/lib/Thelia/Coupon/Type/CouponInterface.php +++ b/core/lib/Thelia/Coupon/Type/CouponInterface.php @@ -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(); } diff --git a/core/lib/Thelia/Coupon/Type/RemoveXPercent.php b/core/lib/Thelia/Coupon/Type/RemoveXPercent.php index 83c625d9c..3cc95737c 100644 --- a/core/lib/Thelia/Coupon/Type/RemoveXPercent.php +++ b/core/lib/Thelia/Coupon/Type/RemoveXPercent.php @@ -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; diff --git a/core/lib/Thelia/Form/CouponCreationForm.php b/core/lib/Thelia/Form/CouponCreationForm.php index dbd271e50..904d8ea7f 100644 --- a/core/lib/Thelia/Form/CouponCreationForm.php +++ b/core/lib/Thelia/Form/CouponCreationForm.php @@ -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', diff --git a/core/lib/Thelia/Model/Coupon.php b/core/lib/Thelia/Model/Coupon.php index 20cb4d24b..7537e29b9 100644 --- a/core/lib/Thelia/Model/Coupon.php +++ b/core/lib/Thelia/Model/Coupon.php @@ -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(); + } } \ No newline at end of file diff --git a/core/lib/Thelia/TaxEngine/TaxEngine.php b/core/lib/Thelia/TaxEngine/TaxEngine.php index 04d5fe4fa..e680902dd 100644 --- a/core/lib/Thelia/TaxEngine/TaxEngine.php +++ b/core/lib/Thelia/TaxEngine/TaxEngine.php @@ -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(); diff --git a/core/lib/Thelia/Tests/Action/OrderTest.php b/core/lib/Thelia/Tests/Action/OrderTest.php index 48527ae7f..0963fafad 100644 --- a/core/lib/Thelia/Tests/Action/OrderTest.php +++ b/core/lib/Thelia/Tests/Action/OrderTest.php @@ -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()); diff --git a/core/lib/Thelia/Tests/Coupon/CouponManagerTest.php b/core/lib/Thelia/Tests/Coupon/CouponManagerTest.php index 79bf4ba9a..af0858c86 100644 --- a/core/lib/Thelia/Tests/Coupon/CouponManagerTest.php +++ b/core/lib/Thelia/Tests/Coupon/CouponManagerTest.php @@ -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( diff --git a/core/lib/Thelia/Tests/Coupon/Type/RemoveXAmountTest.php b/core/lib/Thelia/Tests/Coupon/Type/RemoveXAmountTest.php index b2cd23e13..cee516bc3 100644 --- a/core/lib/Thelia/Tests/Coupon/Type/RemoveXAmountTest.php +++ b/core/lib/Thelia/Tests/Coupon/Type/RemoveXAmountTest.php @@ -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( diff --git a/core/lib/Thelia/Tests/Coupon/Type/RemoveXPercentTest.php b/core/lib/Thelia/Tests/Coupon/Type/RemoveXPercentTest.php index d22918b57..9f21324a7 100644 --- a/core/lib/Thelia/Tests/Coupon/Type/RemoveXPercentTest.php +++ b/core/lib/Thelia/Tests/Coupon/Type/RemoveXPercentTest.php @@ -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( diff --git a/local/modules/Front/Controller/CartController.php b/local/modules/Front/Controller/CartController.php index 431124dbe..cc9cf860a 100644 --- a/local/modules/Front/Controller/CartController.php +++ b/local/modules/Front/Controller/CartController.php @@ -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); diff --git a/local/modules/Front/Controller/CouponController.php b/local/modules/Front/Controller/CouponController.php index 03c57edba..98333dd0a 100644 --- a/local/modules/Front/Controller/CouponController.php +++ b/local/modules/Front/Controller/CouponController.php @@ -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) { diff --git a/templates/backOffice/default/assets/js/coupon.js b/templates/backOffice/default/assets/js/coupon.js index 53f932e12..2004de9a7 100644 --- a/templates/backOffice/default/assets/js/coupon.js +++ b/templates/backOffice/default/assets/js/coupon.js @@ -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(); }); \ No newline at end of file diff --git a/templates/backOffice/default/coupon/condition-fragments/cart-contains-categories-condition.html b/templates/backOffice/default/coupon/condition-fragments/cart-contains-categories-condition.html index 5da1c7469..cf5b72646 100644 --- a/templates/backOffice/default/coupon/condition-fragments/cart-contains-categories-condition.html +++ b/templates/backOffice/default/coupon/condition-fragments/cart-contains-categories-condition.html @@ -6,7 +6,7 @@
diff --git a/templates/backOffice/default/coupon/condition-fragments/cart-contains-products-condition.html b/templates/backOffice/default/coupon/condition-fragments/cart-contains-products-condition.html index 9038a2a10..44054de2d 100644 --- a/templates/backOffice/default/coupon/condition-fragments/cart-contains-products-condition.html +++ b/templates/backOffice/default/coupon/condition-fragments/cart-contains-products-condition.html @@ -6,7 +6,7 @@
diff --git a/templates/backOffice/default/coupon/condition-fragments/countries-condition.html b/templates/backOffice/default/coupon/condition-fragments/countries-condition.html index 0e3fed699..d5a44c712 100644 --- a/templates/backOffice/default/coupon/condition-fragments/countries-condition.html +++ b/templates/backOffice/default/coupon/condition-fragments/countries-condition.html @@ -6,7 +6,7 @@
diff --git a/templates/backOffice/default/coupon/condition-fragments/customers-condition.html b/templates/backOffice/default/coupon/condition-fragments/customers-condition.html index 871222224..ebb507632 100644 --- a/templates/backOffice/default/coupon/condition-fragments/customers-condition.html +++ b/templates/backOffice/default/coupon/condition-fragments/customers-condition.html @@ -6,7 +6,7 @@
diff --git a/templates/backOffice/default/coupon/form.html b/templates/backOffice/default/coupon/form.html index 9690b7619..45017ae8d 100644 --- a/templates/backOffice/default/coupon/form.html +++ b/templates/backOffice/default/coupon/form.html @@ -123,10 +123,9 @@
{intl l='Use Ctrl+click to select (or deselect) more that one country'}
@@ -136,16 +135,14 @@
{intl l='Use Ctrl+click to select (or deselect) more that one shipping method'}
{/form_field}
-