From 147d4a70f1c769617e6a25ed742153a55c4179d3 Mon Sep 17 00:00:00 2001 From: Franck Allimant Date: Thu, 12 Jun 2014 12:12:31 +0200 Subject: [PATCH 01/22] Improved coupon UI --- .../backOffice/default/assets/js/coupon.js | 14 +++---- templates/backOffice/default/coupon/form.html | 42 +++++++++++-------- 2 files changed, 32 insertions(+), 24 deletions(-) diff --git a/templates/backOffice/default/assets/js/coupon.js b/templates/backOffice/default/assets/js/coupon.js index dae6d9574..1c7d962eb 100644 --- a/templates/backOffice/default/assets/js/coupon.js +++ b/templates/backOffice/default/assets/js/coupon.js @@ -214,10 +214,10 @@ $(function($){ // *********************************************** $.couponManager.displayEfffect = function(optionSelected) { - var mainDiv = $('#coupon-type'); - mainDiv.find('.typeToolTip').html(optionSelected.data('description')); + var typeDiv = $('#coupon-type'); + typeDiv.find('.typeToolTip').html(optionSelected.data('description')); - var inputsDiv = mainDiv.find('.inputs'); + var inputsDiv = $('.inputs', $('#coupon-inputs')); inputsDiv.html('
'); var url = $.couponManager.urlAjaxAdminCouponDrawInputs; url = url.replace('couponServiceId', optionSelected.val()); @@ -248,11 +248,11 @@ $(function($){ // Reload effect inputs when changing effect $.couponManager.onEffectChange = function() { - var mainDiv = $('#coupon-type'); - var optionSelected = mainDiv.find('#type option:selected'); - mainDiv.find('.typeToolTip').html(optionSelected.data('description')); + var typeDiv = $('#coupon-type'); + var optionSelected = typeDiv.find('#type option:selected'); + typeDiv.find('.typeToolTip').html(optionSelected.data('description')); - mainDiv.find('#type').on('change', function () { + typeDiv.find('#type').on('change', function () { var optionSelected = $('option:selected', this); $.couponManager.displayEfffect(optionSelected); diff --git a/templates/backOffice/default/coupon/form.html b/templates/backOffice/default/coupon/form.html index bdb8b7226..cc39b6574 100644 --- a/templates/backOffice/default/coupon/form.html +++ b/templates/backOffice/default/coupon/form.html @@ -54,7 +54,31 @@ {if $error}{$message}{/if} {/form_field} + +
+
+ {form_field form=$form field='type'} +
+ + + {if $error}{$message}{/if} + {$availableCoupons.0.toolTip} +
+ {/form_field} +
+
+ + +
+
{form_field form=$form field='isEnabled'}
-
- {form_field form=$form field='type'} -
- - - {if $error}{$message}{/if} - {$availableCoupons.0.toolTip} -
- {/form_field} - +
{$couponInputsHtml nofilter}
From db29505feed11427322d3d817692e13ef0de3832 Mon Sep 17 00:00:00 2001 From: Franck Allimant Date: Thu, 12 Jun 2014 13:14:07 +0200 Subject: [PATCH 02/22] Added Attribute value related coupons --- core/lib/Thelia/Config/Resources/coupon.xml | 18 ++ .../Type/AbstractRemoveOnAttributeValues.php | 174 ++++++++++++++++++ .../Type/RemoveAmountOnAttributeValues.php | 108 +++++++++++ .../RemovePercentageOnAttributeValues.php | 114 ++++++++++++ .../base-remove-on-attributes.html | 63 +++++++ .../remove-amount-on-attributes.html | 16 ++ .../remove-percentage-on-attributes.html | 14 ++ 7 files changed, 507 insertions(+) create mode 100644 core/lib/Thelia/Coupon/Type/AbstractRemoveOnAttributeValues.php create mode 100644 core/lib/Thelia/Coupon/Type/RemoveAmountOnAttributeValues.php create mode 100644 core/lib/Thelia/Coupon/Type/RemovePercentageOnAttributeValues.php create mode 100644 templates/backOffice/default/coupon/type-fragments/base-remove-on-attributes.html create mode 100644 templates/backOffice/default/coupon/type-fragments/remove-amount-on-attributes.html create mode 100644 templates/backOffice/default/coupon/type-fragments/remove-percentage-on-attributes.html diff --git a/core/lib/Thelia/Config/Resources/coupon.xml b/core/lib/Thelia/Config/Resources/coupon.xml index f08746d22..530a36d56 100644 --- a/core/lib/Thelia/Config/Resources/coupon.xml +++ b/core/lib/Thelia/Config/Resources/coupon.xml @@ -51,6 +51,24 @@ + + + + + + + + + + + + + + + + + + diff --git a/core/lib/Thelia/Coupon/Type/AbstractRemoveOnAttributeValues.php b/core/lib/Thelia/Coupon/Type/AbstractRemoveOnAttributeValues.php new file mode 100644 index 000000000..eee1db95c --- /dev/null +++ b/core/lib/Thelia/Coupon/Type/AbstractRemoveOnAttributeValues.php @@ -0,0 +1,174 @@ + + */ +abstract class AbstractRemoveOnAttributeValues extends CouponAbstract +{ + const ATTRIBUTES_AV_LIST = 'attribute_avs'; + const ATTRIBUTE = 'attribute_id'; + + public $attributeAvList = array(); + public $attribute = 0; + + /** + * Set the value of specific coupon fields. + * @param Array $effects the Coupon effects params + */ + protected abstract function setFieldsValue($effects); + + /** + * Get the discount for a specific cart item. + * + * @param CartItem $cartItem the cart item + * @return float the discount value + */ + protected abstract function getCartItemDiscount($cartItem); + + /** + * @inheritdoc + */ + public function set( + FacadeInterface $facade, + $code, + $title, + $shortDescription, + $description, + array $effects, + $isCumulative, + $isRemovingPostage, + $isAvailableOnSpecialOffers, + $isEnabled, + $maxUsage, + \DateTime $expirationDate, + $freeShippingForCountries, + $freeShippingForModules, + $perCustomerUsageCount + ) + { + parent::set( + $facade, $code, $title, $shortDescription, $description, $effects, + $isCumulative, $isRemovingPostage, $isAvailableOnSpecialOffers, $isEnabled, $maxUsage, $expirationDate, + $freeShippingForCountries, + $freeShippingForModules, + $perCustomerUsageCount + ); + + $this->attributeAvList = isset($effects[self::ATTRIBUTES_AV_LIST]) ? $effects[self::ATTRIBUTES_AV_LIST] : array(); + + if (! is_array($this->attributeAvList)) $this->attributeAvList = array($this->attributeAvList); + + $this->attribute = isset($effects[self::ATTRIBUTE]) ? $effects[self::ATTRIBUTE] : 0; + + $this->setFieldsValue($effects); + + return $this; + } + + /** + * @inheritdoc + */ + public function exec() + { + // This coupon subtracts the specified amount from the order total + // for each product which uses the selected attributes + $discount = 0; + + $cartItems = $this->facade->getCart()->getCartItems(); + + /** @var CartItem $cartItem */ + foreach ($cartItems as $cartItem) { + + if (! $cartItem->getPromo() || $this->isAvailableOnSpecialOffers()) { + $productSaleElements = $cartItem->getProductSaleElements(); + + $combinations = $productSaleElements->getAttributeCombinations(); + + /** @var AttributeCombination $combination */ + foreach ($combinations as $combination) { + + $attrValue = $combination->getAttributeAvId(); + + if (in_array($attrValue, $this->attributeAvList)) { + $discount += $this->getCartItemDiscount($cartItem); + + break; + } + } + } + } + + return $discount; + } + + /** + * @inheritdoc + */ + public function drawBaseBackOfficeInputs($templateName, $otherFields) + { + return $this->facade->getParser()->render($templateName, array_merge($otherFields, [ + + // The attributes list field + 'attribute_field_name' => $this->makeCouponFieldName(self::ATTRIBUTE), + 'attribute_value' => $this->attribute, + + // The attributes list field + 'attribute_av_field_name' => $this->makeCouponFieldName(self::ATTRIBUTES_AV_LIST), + 'attribute_av_values' => $this->attributeAvList + ])); + } + + /** + * @inheritdoc + */ + protected function getBaseFieldList($otherFields) + { + return array_merge($otherFields, [self::ATTRIBUTE, self::ATTRIBUTES_AV_LIST]); + } + + /** + * @inheritdoc + */ + protected function checkBaseCouponFieldValue($fieldName, $fieldValue) + { + if ($fieldName === self::ATTRIBUTE) { + if (empty($fieldValue)) { + throw new \InvalidArgumentException( + Translator::getInstance()->trans( + 'Please select an attribute' + ) + ); + } + } elseif ($fieldName === self::ATTRIBUTES_AV_LIST) { + if (empty($fieldValue)) { + throw new \InvalidArgumentException( + Translator::getInstance()->trans( + 'Please select at least one attribute value' + ) + ); + } + } + + return $fieldValue; + } +} diff --git a/core/lib/Thelia/Coupon/Type/RemoveAmountOnAttributeValues.php b/core/lib/Thelia/Coupon/Type/RemoveAmountOnAttributeValues.php new file mode 100644 index 000000000..523365d08 --- /dev/null +++ b/core/lib/Thelia/Coupon/Type/RemoveAmountOnAttributeValues.php @@ -0,0 +1,108 @@ + + */ +class RemoveAmountOnAttributeValues extends AbstractRemoveOnAttributeValues +{ + /** @var string Service Id */ + protected $serviceId = 'thelia.coupon.type.remove_amount_on_attribute_av'; + + /** + * @inheritdoc + */ + protected function setFieldsValue($effects) { + // Nothing to do, the amount is processed by CouponAbstract. + } + + /** + * @inheritdoc + */ + public function getCartItemDiscount($cartItem) { + return $cartItem->getQuantity() * $this->amount; + } + + /** + * @inheritdoc + */ + public function getName() + { + return $this->facade + ->getTranslator() + ->trans('Fixed amount discount for selected attribute values', array(), 'coupon'); + } + + /** + * @inheritdoc + */ + public function getToolTip() + { + $toolTip = $this->facade + ->getTranslator() + ->trans( + 'This coupon subtracts the specified amount from the order total for each product which uses the selected attribute values. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.', + array(), + 'coupon' + ); + + return $toolTip; + } + + /** + * @inheritdoc + */ + public function drawBackOfficeInputs() + { + return $this->drawBaseBackOfficeInputs('coupon/type-fragments/remove-amount-on-attributes.html', [ + 'amount_field_name' => $this->makeCouponFieldName(self::AMOUNT_FIELD_NAME), + 'amount_value' => $this->amount + ]); + } + + /** + * @inheritdoc + */ + protected function getFieldList() + { + return $this->getBaseFieldList([self::AMOUNT_FIELD_NAME]); + } + + /** + * @inheritdoc + */ + protected function checkCouponFieldValue($fieldName, $fieldValue) + { + $this->checkBaseCouponFieldValue($fieldName, $fieldValue); + + if ($fieldName === self::AMOUNT_FIELD_NAME) { + + if (floatval($fieldValue) < 0) { + throw new \InvalidArgumentException( + Translator::getInstance()->trans( + 'Value %val for Discount Amount is invalid. Please enter a positive value.', + [ '%val' => $fieldValue] + ) + ); + } + } + + return $fieldValue; + } +} diff --git a/core/lib/Thelia/Coupon/Type/RemovePercentageOnAttributeValues.php b/core/lib/Thelia/Coupon/Type/RemovePercentageOnAttributeValues.php new file mode 100644 index 000000000..26c55022c --- /dev/null +++ b/core/lib/Thelia/Coupon/Type/RemovePercentageOnAttributeValues.php @@ -0,0 +1,114 @@ + + */ +class RemovePercentageOnAttributeValues extends AbstractRemoveOnAttributeValues +{ + const PERCENTAGE = 'percentage'; + + public $percentage = 0; + + /** @var string Service Id */ + protected $serviceId = 'thelia.coupon.type.remove_percentage_on_attribute_av'; + + /** + * @inheritdoc + */ + protected function setFieldsValue($effects) { + $this->percentage = $effects[self::PERCENTAGE]; + } + + /** + * @inheritdoc + */ + public function getCartItemDiscount($cartItem) { + return $cartItem->getQuantity() * $cartItem->getPrice() * $this->percentage; + } + + /** + * @inheritdoc + */ + public function getName() + { + return $this->facade + ->getTranslator() + ->trans('Percentage discount for selected attribute values', array(), 'coupon'); + } + + /** + * @inheritdoc + */ + public function getToolTip() + { + $toolTip = $this->facade + ->getTranslator() + ->trans( + 'This coupon subtracts from the order total the specified percentage of each product price which uses the selected attribute values. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.', + array(), + 'coupon' + ); + + return $toolTip; + } + + /** + * @inheritdoc + */ + public function drawBackOfficeInputs() + { + return $this->drawBaseBackOfficeInputs('coupon/type-fragments/remove-percentage-on-attributes.html', [ + 'percentage_field_name' => $this->makeCouponFieldName(self::PERCENTAGE), + 'percentage_value' => $this->percentage, + ]); + } + + /** + * @inheritdoc + */ + protected function getFieldList() + { + return $this->getBaseFieldList([self::PERCENTAGE]); + } + + /** + * @inheritdoc + */ + protected function checkCouponFieldValue($fieldName, $fieldValue) + { + $this->checkBaseCouponFieldValue($fieldName, $fieldValue); + + if ($fieldName === self::PERCENTAGE) { + + $pcent = floatval($fieldValue); + + if ($pcent <= 0 || $pcent > 100) { + throw new \InvalidArgumentException( + Translator::getInstance()->trans( + 'Value %val for Percent Discount is invalid. Please enter a positive value between 1 and 100.', + [ '%val' => $fieldValue] + ) + ); + } + } + + return $fieldValue; + } +} diff --git a/templates/backOffice/default/coupon/type-fragments/base-remove-on-attributes.html b/templates/backOffice/default/coupon/type-fragments/base-remove-on-attributes.html new file mode 100644 index 000000000..073cdedbf --- /dev/null +++ b/templates/backOffice/default/coupon/type-fragments/base-remove-on-attributes.html @@ -0,0 +1,63 @@ +{block name="discount-field"}{/block} + +
+ + + + +
+ + + +
+ + + + + + {intl l='Use Ctrl+click to select (or deselect) more that one attribute value'} +
+ + diff --git a/templates/backOffice/default/coupon/type-fragments/remove-amount-on-attributes.html b/templates/backOffice/default/coupon/type-fragments/remove-amount-on-attributes.html new file mode 100644 index 000000000..17f68cc28 --- /dev/null +++ b/templates/backOffice/default/coupon/type-fragments/remove-amount-on-attributes.html @@ -0,0 +1,16 @@ +{extends file="coupon/type-fragments/base-remove-on-attributes.html"} + +{block name="discount-field"} +
+ + + +
+ + + {loop type="currency" name="get-symbol" default_only="true"} +
{$SYMBOL}
+ {/loop} +
+
+{/block} \ No newline at end of file diff --git a/templates/backOffice/default/coupon/type-fragments/remove-percentage-on-attributes.html b/templates/backOffice/default/coupon/type-fragments/remove-percentage-on-attributes.html new file mode 100644 index 000000000..262c10d97 --- /dev/null +++ b/templates/backOffice/default/coupon/type-fragments/remove-percentage-on-attributes.html @@ -0,0 +1,14 @@ +{extends file="coupon/type-fragments/base-remove-on-attributes.html"} + +{block name="discount-field"} +
+ + + +
+ + +
%
+
+
+{/block} \ No newline at end of file From 95841809c4bf1005f2c801735518f4ddde2cbbc6 Mon Sep 17 00:00:00 2001 From: Franck Allimant Date: Thu, 12 Jun 2014 13:14:46 +0200 Subject: [PATCH 03/22] Refactored coupons to reduce code duplication --- .../Type/AbstractRemoveOnCategories.php | 150 ++++++++++++++++ .../Coupon/Type/AbstractRemoveOnProducts.php | 162 ++++++++++++++++++ .../Coupon/Type/RemoveAmountOnCategories.php | 107 ++---------- .../Coupon/Type/RemoveAmountOnProducts.php | 116 ++----------- .../Type/RemovePercentageOnCategories.php | 101 ++--------- .../Type/RemovePercentageOnProducts.php | 114 ++---------- .../ajax-attribute-avs-list.html | 3 + .../base-remove-on-categories.html | 14 ++ .../base-remove-on-products.html | 63 +++++++ .../remove-amount-on-categories.html | 32 ++-- .../remove-amount-on-products.html | 83 ++------- .../remove-percentage-on-categories.html | 28 +-- .../remove-percentage-on-products.html | 79 +-------- 13 files changed, 502 insertions(+), 550 deletions(-) create mode 100644 core/lib/Thelia/Coupon/Type/AbstractRemoveOnCategories.php create mode 100644 core/lib/Thelia/Coupon/Type/AbstractRemoveOnProducts.php create mode 100644 templates/backOffice/default/coupon/type-fragments/ajax-attribute-avs-list.html create mode 100644 templates/backOffice/default/coupon/type-fragments/base-remove-on-categories.html create mode 100644 templates/backOffice/default/coupon/type-fragments/base-remove-on-products.html diff --git a/core/lib/Thelia/Coupon/Type/AbstractRemoveOnCategories.php b/core/lib/Thelia/Coupon/Type/AbstractRemoveOnCategories.php new file mode 100644 index 000000000..6d6622126 --- /dev/null +++ b/core/lib/Thelia/Coupon/Type/AbstractRemoveOnCategories.php @@ -0,0 +1,150 @@ + + */ +abstract class AbstractRemoveOnCategories extends CouponAbstract +{ + const CATEGORIES_LIST = 'categories'; + + protected $category_list = array(); + + /** + * Set the value of specific coupon fields. + * + * @param Array $effects the Coupon effects params + */ + protected abstract function setFieldsValue($effects); + + /** + * Get the discount for a specific cart item. + * + * @param CartItem $cartItem the cart item + * @return float the discount value + */ + protected abstract function getCartItemDiscount($cartItem); + + /** + * @inheritdoc + */ + public function set( + FacadeInterface $facade, + $code, + $title, + $shortDescription, + $description, + array $effects, + $isCumulative, + $isRemovingPostage, + $isAvailableOnSpecialOffers, + $isEnabled, + $maxUsage, + \DateTime $expirationDate, + $freeShippingForCountries, + $freeShippingForModules, + $perCustomerUsageCount + ) + { + parent::set( + $facade, $code, $title, $shortDescription, $description, $effects, + $isCumulative, $isRemovingPostage, $isAvailableOnSpecialOffers, $isEnabled, $maxUsage, $expirationDate, + $freeShippingForCountries, + $freeShippingForModules, + $perCustomerUsageCount + ); + + $this->category_list = isset($effects[self::CATEGORIES_LIST]) ? $effects[self::CATEGORIES_LIST] : array(); + + if (! is_array($this->category_list)) $this->category_list = array($this->category_list); + + return $this; + } + /** + * @inheritdoc + */ + public function exec() + { + // This coupon subtracts the specified amount from the order total + // for each product of the selected categories. + $discount = 0; + + $cartItems = $this->facade->getCart()->getCartItems(); + + /** @var CartItem $cartItem */ + foreach ($cartItems as $cartItem) { + if (! $cartItem->getPromo() || $this->isAvailableOnSpecialOffers()) { + $categories = $cartItem->getProduct()->getCategories(); + + /** @var Category $category */ + foreach ($categories as $category) { + + if (in_array($category->getId(), $this->category_list)) { + $discount += $this->getCartItemDiscount($cartItem); + + break; + } + } + } + } + + return $discount; + } + + /** + * @inheritdoc + */ + public function drawBaseBackOfficeInputs($templateName, $otherFields) + { + return $this->facade->getParser()->render($templateName, array_merge($otherFields, [ + + // The categories list field + 'categories_field_name' => $this->makeCouponFieldName(self::CATEGORIES_LIST), + 'categories_values' => $this->category_list + ])); + } + + /** + * @inheritdoc + */ + protected function getBaseFieldList($otherFields) + { + return array_merge($otherFields, [self::CATEGORIES_LIST]); + } + + /** + * @inheritdoc + */ + protected function checkBaseCouponFieldValue($fieldName, $fieldValue) + { + if ($fieldName === self::CATEGORIES_LIST) { + if (empty($fieldValue)) { + throw new \InvalidArgumentException( + Translator::getInstance()->trans( + 'Please select at least one category' + ) + ); + } + } + + return $fieldValue; + } +} \ No newline at end of file diff --git a/core/lib/Thelia/Coupon/Type/AbstractRemoveOnProducts.php b/core/lib/Thelia/Coupon/Type/AbstractRemoveOnProducts.php new file mode 100644 index 000000000..2bb5ecea8 --- /dev/null +++ b/core/lib/Thelia/Coupon/Type/AbstractRemoveOnProducts.php @@ -0,0 +1,162 @@ + + */ +abstract class AbstractRemoveOnProducts extends CouponAbstract +{ + const CATEGORY_ID = 'category_id'; + const PRODUCTS_LIST = 'products'; + + public $category_id = 0; + public $product_list = array(); + + /** + * Set the value of specific coupon fields. + * + * @param Array $effects the Coupon effects params + */ + protected abstract function setFieldsValue($effects); + + /** + * Get the discount for a specific cart item. + * + * @param CartItem $cartItem the cart item + * @return float the discount value + */ + protected abstract function getCartItemDiscount($cartItem); + + /** + * @inheritdoc + */ + public function set( + FacadeInterface $facade, + $code, + $title, + $shortDescription, + $description, + array $effects, + $isCumulative, + $isRemovingPostage, + $isAvailableOnSpecialOffers, + $isEnabled, + $maxUsage, + \DateTime $expirationDate, + $freeShippingForCountries, + $freeShippingForModules, + $perCustomerUsageCount + ) + { + parent::set( + $facade, $code, $title, $shortDescription, $description, $effects, + $isCumulative, $isRemovingPostage, $isAvailableOnSpecialOffers, $isEnabled, $maxUsage, $expirationDate, + $freeShippingForCountries, + $freeShippingForModules, + $perCustomerUsageCount + ); + + $this->product_list = isset($effects[self::PRODUCTS_LIST]) ? $effects[self::PRODUCTS_LIST] : array(); + + if (! is_array($this->product_list)) $this->product_list = array($this->product_list); + + $this->category_id = isset($effects[self::CATEGORY_ID]) ? $effects[self::CATEGORY_ID] : 0; + + $this->setFieldsValue($effects); + + return $this; + } + + /** + * @inheritdoc + */ + public function exec() + { + // This coupon subtracts the specified amount from the order total + // for each product of the selected products. + $discount = 0; + + $cartItems = $this->facade->getCart()->getCartItems(); + + /** @var CartItem $cartItem */ + foreach ($cartItems as $cartItem) { + if (in_array($cartItem->getProduct()->getId(), $this->product_list)) { + if (! $cartItem->getPromo() || $this->isAvailableOnSpecialOffers()) { + $discount += $this->getCartItemDiscount($cartItem); + } + } + } + + return $discount; + } + + /** + * @inheritdoc + */ + public function drawBaseBackOfficeInputs($templateName, $otherFields) + { + return $this->facade->getParser()->render($templateName, array_merge($otherFields, [ + + // The category ID field + 'category_id_field_name' => $this->makeCouponFieldName(self::CATEGORY_ID), + 'category_id_value' => $this->category_id, + + // The products list field + 'products_field_name' => $this->makeCouponFieldName(self::PRODUCTS_LIST), + 'products_values' => $this->product_list, + 'products_values_csv' => implode(', ', $this->product_list) + ])); + } + + /** + * @inheritdoc + */ + protected function getBaseFieldList($otherFields) + { + return array_merge($otherFields, [self::CATEGORY_ID, self::PRODUCTS_LIST]); + } + + /** + * @inheritdoc + */ + protected function checkBaseCouponFieldValue($fieldName, $fieldValue) + { + if ($fieldName === self::CATEGORY_ID) { + if (empty($fieldValue)) { + throw new \InvalidArgumentException( + Translator::getInstance()->trans( + 'Please select a category' + ) + ); + } + } elseif ($fieldName === self::PRODUCTS_LIST) { + if (empty($fieldValue)) { + throw new \InvalidArgumentException( + Translator::getInstance()->trans( + 'Please select at least one product' + ) + ); + } + } + + return $fieldValue; + } +} diff --git a/core/lib/Thelia/Coupon/Type/RemoveAmountOnCategories.php b/core/lib/Thelia/Coupon/Type/RemoveAmountOnCategories.php index d65b462f7..e5f3070b0 100644 --- a/core/lib/Thelia/Coupon/Type/RemoveAmountOnCategories.php +++ b/core/lib/Thelia/Coupon/Type/RemoveAmountOnCategories.php @@ -21,56 +21,30 @@ use Thelia\Model\Category; * Allow to remove an amount from the checkout total * * @package Coupon - * @author Guillaume MOREL - * + * @author Franck Allimant */ -class RemoveAmountOnCategories extends CouponAbstract +class RemoveAmountOnCategories extends AbstractRemoveOnCategories { - const CATEGORIES_LIST = 'categories'; - /** @var string Service Id */ protected $serviceId = 'thelia.coupon.type.remove_amount_on_categories'; - public $category_list = array(); - /** * @inheritdoc */ - public function set( - FacadeInterface $facade, - $code, - $title, - $shortDescription, - $description, - array $effects, - $isCumulative, - $isRemovingPostage, - $isAvailableOnSpecialOffers, - $isEnabled, - $maxUsage, - \DateTime $expirationDate, - $freeShippingForCountries, - $freeShippingForModules, - $perCustomerUsageCount - ) - { - parent::set( - $facade, $code, $title, $shortDescription, $description, $effects, - $isCumulative, $isRemovingPostage, $isAvailableOnSpecialOffers, $isEnabled, $maxUsage, $expirationDate, - $freeShippingForCountries, - $freeShippingForModules, - $perCustomerUsageCount - ); - - $this->category_list = isset($effects[self::CATEGORIES_LIST]) ? $effects[self::CATEGORIES_LIST] : array(); - - if (! is_array($this->category_list)) $this->category_list = array($this->category_list); - return $this; + protected function setFieldsValue($effects) { + // Nothing to do, the amount is processed by CouponAbstract. } /** * @inheritdoc */ + public function getCartItemDiscount($cartItem) { + return $cartItem->getQuantity() * $this->amount; + } + + /** + * @inheritdoc + */ public function getName() { return $this->facade @@ -94,53 +68,15 @@ class RemoveAmountOnCategories extends CouponAbstract return $toolTip; } - /** - * @inheritdoc - */ - public function exec() - { - // This coupon subtracts the specified amount from the order total - // for each product of the selected categories. - $discount = 0; - - $cartItems = $this->facade->getCart()->getCartItems(); - - /** @var CartItem $cartItem */ - foreach ($cartItems as $cartItem) { - - if (! $cartItem->getPromo() || $this->isAvailableOnSpecialOffers()) { - $categories = $cartItem->getProduct()->getCategories(); - - /** @var Category $category */ - foreach ($categories as $category) { - - if (in_array($category->getId(), $this->category_list)) { - $discount += $cartItem->getQuantity() * $this->amount; - - break; - } - } - } - } - - return $discount; - } - /** * @inheritdoc */ public function drawBackOfficeInputs() { - return $this->facade->getParser()->render('coupon/type-fragments/remove-amount-on-categories.html', [ - - // The standard "Amount" field - 'amount_field_name' => $this->makeCouponFieldName(self::AMOUNT_FIELD_NAME), - 'amount_value' => $this->amount, - - // The categories list field - 'categories_field_name' => $this->makeCouponFieldName(self::CATEGORIES_LIST), - 'categories_values' => $this->category_list - ]); + return $this->drawBaseBackOfficeInputs('coupon/type-fragments/remove-amount-on-categories.html', [ + 'amount_field_name' => $this->makeCouponFieldName(self::AMOUNT_FIELD_NAME), + 'amount_value' => $this->amount + ]); } /** @@ -148,7 +84,7 @@ class RemoveAmountOnCategories extends CouponAbstract */ protected function getFieldList() { - return [self::AMOUNT_FIELD_NAME, self::CATEGORIES_LIST]; + return $this->getBaseFieldList([self::AMOUNT_FIELD_NAME]); } /** @@ -156,6 +92,8 @@ class RemoveAmountOnCategories extends CouponAbstract */ protected function checkCouponFieldValue($fieldName, $fieldValue) { + $this->checkBaseCouponFieldValue($fieldName, $fieldValue); + if ($fieldName === self::AMOUNT_FIELD_NAME) { if (floatval($fieldValue) < 0) { @@ -166,17 +104,8 @@ class RemoveAmountOnCategories extends CouponAbstract ) ); } - } elseif ($fieldName === self::CATEGORIES_LIST) { - if (empty($fieldValue)) { - throw new \InvalidArgumentException( - Translator::getInstance()->trans( - 'Please select at least one category' - ) - ); - } } return $fieldValue; } - } diff --git a/core/lib/Thelia/Coupon/Type/RemoveAmountOnProducts.php b/core/lib/Thelia/Coupon/Type/RemoveAmountOnProducts.php index 9a3fb8b93..1061171e6 100644 --- a/core/lib/Thelia/Coupon/Type/RemoveAmountOnProducts.php +++ b/core/lib/Thelia/Coupon/Type/RemoveAmountOnProducts.php @@ -21,56 +21,25 @@ use Thelia\Model\Product; * Allow to remove an amount from the checkout total * * @package Coupon - * @author Guillaume MOREL - * + * @author Franck Allimant */ -class RemoveAmountOnProducts extends CouponAbstract +class RemoveAmountOnProducts extends AbstractRemoveOnProducts { - const CATEGORY_ID = 'category_id'; - const PRODUCTS_LIST = 'products'; - /** @var string Service Id */ protected $serviceId = 'thelia.coupon.type.remove_amount_on_products'; - public $category_id = 0; - public $product_list = array(); - /** * @inheritdoc */ - public function set( - FacadeInterface $facade, - $code, - $title, - $shortDescription, - $description, - array $effects, - $isCumulative, - $isRemovingPostage, - $isAvailableOnSpecialOffers, - $isEnabled, - $maxUsage, - \DateTime $expirationDate, - $freeShippingForCountries, - $freeShippingForModules, - $perCustomerUsageCount - ) - { - parent::set( - $facade, $code, $title, $shortDescription, $description, $effects, - $isCumulative, $isRemovingPostage, $isAvailableOnSpecialOffers, $isEnabled, $maxUsage, $expirationDate, - $freeShippingForCountries, - $freeShippingForModules, - $perCustomerUsageCount - ); + protected function setFieldsValue($effects) { + // Nothing to do: amount is processed by CouponAbstract + } - $this->product_list = isset($effects[self::PRODUCTS_LIST]) ? $effects[self::PRODUCTS_LIST] : array(); - - if (! is_array($this->product_list)) $this->product_list = array($this->product_list); - - $this->category_id = isset($effects[self::CATEGORY_ID]) ? $effects[self::CATEGORY_ID] : 0; - - return $this; + /** + * @inheritdoc + */ + protected function getCartItemDiscount($cartItem) { + return $cartItem->getQuantity() * $this->amount; } /** @@ -101,58 +70,23 @@ class RemoveAmountOnProducts extends CouponAbstract return $toolTip; } - /** - * @inheritdoc - */ - public function exec() - { - // This coupon subtracts the specified amount from the order total - // for each product of the selected products. - $discount = 0; - - $cartItems = $this->facade->getCart()->getCartItems(); - - /** @var CartItem $cartItem */ - foreach ($cartItems as $cartItem) { - - if (in_array($cartItem->getProduct()->getId(), $this->product_list)) { - if (! $cartItem->getPromo() || $this->isAvailableOnSpecialOffers()) { - $discount += $cartItem->getQuantity() * $this->amount; - } - } - } - - return $discount; - } - /** * @inheritdoc */ public function drawBackOfficeInputs() { - return $this->facade->getParser()->render('coupon/type-fragments/remove-amount-on-products.html', [ - - // The standard "Amount" field - 'amount_field_name' => $this->makeCouponFieldName(self::AMOUNT_FIELD_NAME), - 'amount_value' => $this->amount, - - // The category ID field - 'category_id_field_name' => $this->makeCouponFieldName(self::CATEGORY_ID), - 'category_id_value' => $this->category_id, - - // The products list field - 'products_field_name' => $this->makeCouponFieldName(self::PRODUCTS_LIST), - 'products_values' => $this->product_list, - 'products_values_csv' => implode(', ', $this->product_list) + return $this->drawBaseBackOfficeInputs('coupon/type-fragments/remove-amount-on-products.html', [ + 'amount_field_name' => $this->makeCouponFieldName(self::AMOUNT_FIELD_NAME), + 'amount_value' => $this->amount ]); - } + } /** * @inheritdoc */ protected function getFieldList() { - return [self::AMOUNT_FIELD_NAME, self::CATEGORY_ID, self::PRODUCTS_LIST]; + return $this->getBaseFieldList([self::AMOUNT_FIELD_NAME]); } /** @@ -160,6 +94,8 @@ class RemoveAmountOnProducts extends CouponAbstract */ protected function checkCouponFieldValue($fieldName, $fieldValue) { + $this->checkBaseCouponFieldValue($fieldName, $fieldValue); + if ($fieldName === self::AMOUNT_FIELD_NAME) { if (floatval($fieldValue) < 0) { @@ -170,24 +106,8 @@ class RemoveAmountOnProducts extends CouponAbstract ) ); } - } elseif ($fieldName === self::CATEGORY_ID) { - if (empty($fieldValue)) { - throw new \InvalidArgumentException( - Translator::getInstance()->trans( - 'Please select a category' - ) - ); - } - } elseif ($fieldName === self::PRODUCTS_LIST) { - if (empty($fieldValue)) { - throw new \InvalidArgumentException( - Translator::getInstance()->trans( - 'Please select at least one product' - ) - ); - } } return $fieldValue; } -} +} \ No newline at end of file diff --git a/core/lib/Thelia/Coupon/Type/RemovePercentageOnCategories.php b/core/lib/Thelia/Coupon/Type/RemovePercentageOnCategories.php index 892984a14..dc5a533bd 100644 --- a/core/lib/Thelia/Coupon/Type/RemovePercentageOnCategories.php +++ b/core/lib/Thelia/Coupon/Type/RemovePercentageOnCategories.php @@ -19,54 +19,28 @@ use Thelia\Model\Category; /** * @author Franck Allimant - * */ -class RemovePercentageOnCategories extends CouponAbstract +class RemovePercentageOnCategories extends AbstractRemoveOnCategories { - const CATEGORIES_LIST = 'categories'; const PERCENTAGE = 'percentage'; /** @var string Service Id */ protected $serviceId = 'thelia.coupon.type.remove_percentage_on_categories'; - protected $category_list = array(); - protected $percentage = 0; /** * @inheritdoc */ - public function set( - FacadeInterface $facade, - $code, - $title, - $shortDescription, - $description, - array $effects, - $isCumulative, - $isRemovingPostage, - $isAvailableOnSpecialOffers, - $isEnabled, - $maxUsage, - \DateTime $expirationDate, - $freeShippingForCountries, - $freeShippingForModules, - $perCustomerUsageCount - ) - { - parent::set( - $facade, $code, $title, $shortDescription, $description, $effects, - $isCumulative, $isRemovingPostage, $isAvailableOnSpecialOffers, $isEnabled, $maxUsage, $expirationDate, - $freeShippingForCountries, - $freeShippingForModules, - $perCustomerUsageCount - ); + protected function setFieldsValue($effects) { + $this->percentage = $effects[self::PERCENTAGE]; + } - $this->category_list = isset($effects[self::CATEGORIES_LIST]) ? $effects[self::CATEGORIES_LIST] : array(); - $this->percentage = isset($effects[self::PERCENTAGE]) ? $effects[self::PERCENTAGE] : 0; - - if (! is_array($this->category_list)) $this->category_list = array($this->category_list); - return $this; + /** + * @inheritdoc + */ + public function getCartItemDiscount($cartItem) { + return $cartItem->getQuantity() * $cartItem->getPrice() * $this->percentage; } /** @@ -95,52 +69,15 @@ class RemovePercentageOnCategories extends CouponAbstract return $toolTip; } - /** - * @inheritdoc - */ - public function exec() - { - // This coupon subtracts the specified amount from the order total - // for each product of the selected categories. - $discount = 0; - - $cartItems = $this->facade->getCart()->getCartItems(); - - /** @var CartItem $cartItem */ - foreach ($cartItems as $cartItem) { - if (! $cartItem->getPromo() || $this->isAvailableOnSpecialOffers()) { - $categories = $cartItem->getProduct()->getCategories(); - - /** @var Category $category */ - foreach ($categories as $category) { - - if (in_array($category->getId(), $this->category_list)) { - $discount += $cartItem->getPrice() * $this->percentage; - - break; - } - } - } - } - - return $discount; - } - /** * @inheritdoc */ public function drawBackOfficeInputs() { - return $this->facade->getParser()->render('coupon/type-fragments/remove-percentage-on-categories.html', [ - - // The standard "Amount" field - 'percentage_field_name' => $this->makeCouponFieldName(self::PERCENTAGE), - 'percentage_value' => $this->percentage, - - // The categories list field - 'categories_field_name' => $this->makeCouponFieldName(self::CATEGORIES_LIST), - 'categories_values' => $this->category_list - ]); + return $this->drawBaseBackOfficeInputs('coupon/type-fragments/remove-percentage-on-categories.html', [ + 'percentage_field_name' => $this->makeCouponFieldName(self::PERCENTAGE), + 'percentage_value' => $this->percentage, + ]); } /** @@ -148,7 +85,7 @@ class RemovePercentageOnCategories extends CouponAbstract */ protected function getFieldList() { - return [self::PERCENTAGE, self::CATEGORIES_LIST]; + return $this->getBaseFieldList([self::PERCENTAGE]); } /** @@ -156,6 +93,8 @@ class RemovePercentageOnCategories extends CouponAbstract */ protected function checkCouponFieldValue($fieldName, $fieldValue) { + $this->checkBaseCouponFieldValue($fieldName, $fieldValue); + if ($fieldName === self::PERCENTAGE) { $pcent = floatval($fieldValue); @@ -168,14 +107,6 @@ class RemovePercentageOnCategories extends CouponAbstract ) ); } - } elseif ($fieldName === self::CATEGORIES_LIST) { - if (empty($fieldValue)) { - throw new \InvalidArgumentException( - Translator::getInstance()->trans( - 'Please select at least one category' - ) - ); - } } return $fieldValue; diff --git a/core/lib/Thelia/Coupon/Type/RemovePercentageOnProducts.php b/core/lib/Thelia/Coupon/Type/RemovePercentageOnProducts.php index 030a87c23..332d0feed 100644 --- a/core/lib/Thelia/Coupon/Type/RemovePercentageOnProducts.php +++ b/core/lib/Thelia/Coupon/Type/RemovePercentageOnProducts.php @@ -21,60 +21,30 @@ use Thelia\Model\Product; * Allow to remove an amount from the checkout total * * @package Coupon - * @author Guillaume MOREL - * + * @author Franck Allimant */ -class RemovePercentageOnProducts extends CouponAbstract +class RemovePercentageOnProducts extends AbstractRemoveOnProducts { - const CATEGORY_ID = 'category_id'; - const PRODUCTS_LIST = 'products'; - const PERCENTAGE = 'percentage'; + const PERCENTAGE = 'percentage'; /** @var string Service Id */ protected $serviceId = 'thelia.coupon.type.remove_percentage_on_products'; - public $category_id = 0; - public $product_list = array(); public $percentage = 0; /** * @inheritdoc */ - public function set( - FacadeInterface $facade, - $code, - $title, - $shortDescription, - $description, - array $effects, - $isCumulative, - $isRemovingPostage, - $isAvailableOnSpecialOffers, - $isEnabled, - $maxUsage, - \DateTime $expirationDate, - $freeShippingForCountries, - $freeShippingForModules, - $perCustomerUsageCount - ) - { - parent::set( - $facade, $code, $title, $shortDescription, $description, $effects, - $isCumulative, $isRemovingPostage, $isAvailableOnSpecialOffers, $isEnabled, $maxUsage, $expirationDate, - $freeShippingForCountries, - $freeShippingForModules, - $perCustomerUsageCount - ); - - $this->product_list = isset($effects[self::PRODUCTS_LIST]) ? $effects[self::PRODUCTS_LIST] : array(); - - if (! is_array($this->product_list)) $this->product_list = array($this->product_list); - - $this->category_id = isset($effects[self::CATEGORY_ID]) ? $effects[self::CATEGORY_ID] : 0; + protected function setFieldsValue($effects) { $this->percentage = $effects[self::PERCENTAGE]; + } - return $this; + /** + * @inheritdoc + */ + protected function getCartItemDiscount($cartItem) { + return $cartItem->getQuantity() * $cartItem->getPrice() * $this->percentage; } /** @@ -105,49 +75,15 @@ class RemovePercentageOnProducts extends CouponAbstract return $toolTip; } - /** - * @inheritdoc - */ - public function exec() - { - // This coupon subtracts the specified amount from the order total - // for each product of the selected products. - $discount = 0; - - $cartItems = $this->facade->getCart()->getCartItems(); - - /** @var CartItem $cartItem */ - foreach ($cartItems as $cartItem) { - if (in_array($cartItem->getProduct()->getId(), $this->product_list)) { - if (! $cartItem->getPromo() || $this->isAvailableOnSpecialOffers()) { - $discount += $cartItem->getQuantity() * $cartItem->getPrice() * $this->percentage; - } - } - } - - return $discount; - } - /** * @inheritdoc */ public function drawBackOfficeInputs() { - return $this->facade->getParser()->render('coupon/type-fragments/remove-percentage-on-products.html', [ - - // The standard "Amount" field - 'percentage_field_name' => $this->makeCouponFieldName(self::PERCENTAGE), - 'percentage_value' => $this->percentage, - - // The category ID field - 'category_id_field_name' => $this->makeCouponFieldName(self::CATEGORY_ID), - 'category_id_value' => $this->category_id, - - // The products list field - 'products_field_name' => $this->makeCouponFieldName(self::PRODUCTS_LIST), - 'products_values' => $this->product_list, - 'products_values_csv' => implode(', ', $this->product_list) - ]); + return $this->drawBaseBackOfficeInputs('coupon/type-fragments/remove-percentage-on-products.html', [ + 'percentage_field_name' => $this->makeCouponFieldName(self::PERCENTAGE), + 'percentage_value' => $this->percentage, + ]); } /** @@ -155,7 +91,7 @@ class RemovePercentageOnProducts extends CouponAbstract */ protected function getFieldList() { - return [self::PERCENTAGE, self::CATEGORY_ID, self::PRODUCTS_LIST]; + return $this->getBaseFieldList([self::PERCENTAGE]); } /** @@ -163,6 +99,8 @@ class RemovePercentageOnProducts extends CouponAbstract */ protected function checkCouponFieldValue($fieldName, $fieldValue) { + $this->checkBaseCouponFieldValue($fieldName, $fieldValue); + if ($fieldName === self::PERCENTAGE) { $pcent = floatval($fieldValue); @@ -175,24 +113,8 @@ class RemovePercentageOnProducts extends CouponAbstract ) ); } - } elseif ($fieldName === self::CATEGORY_ID) { - if (empty($fieldValue)) { - throw new \InvalidArgumentException( - Translator::getInstance()->trans( - 'Please select a category' - ) - ); - } - } elseif ($fieldName === self::PRODUCTS_LIST) { - if (empty($fieldValue)) { - throw new \InvalidArgumentException( - Translator::getInstance()->trans( - 'Please select at least one product' - ) - ); - } } return $fieldValue; } -} +} \ No newline at end of file diff --git a/templates/backOffice/default/coupon/type-fragments/ajax-attribute-avs-list.html b/templates/backOffice/default/coupon/type-fragments/ajax-attribute-avs-list.html new file mode 100644 index 000000000..3033f94c9 --- /dev/null +++ b/templates/backOffice/default/coupon/type-fragments/ajax-attribute-avs-list.html @@ -0,0 +1,3 @@ +{loop type="attribute_availability" attribute={$smarty.post.attribute_id} name="list-of-attribute_avs" backend_context="1"} + +{/loop} \ No newline at end of file diff --git a/templates/backOffice/default/coupon/type-fragments/base-remove-on-categories.html b/templates/backOffice/default/coupon/type-fragments/base-remove-on-categories.html new file mode 100644 index 000000000..39b81e4c1 --- /dev/null +++ b/templates/backOffice/default/coupon/type-fragments/base-remove-on-categories.html @@ -0,0 +1,14 @@ +{block name="discount-field"}{/block} + +
+ + + + + + {intl l='Use Ctrl+click to select (or deselect) more that one category'} +
diff --git a/templates/backOffice/default/coupon/type-fragments/base-remove-on-products.html b/templates/backOffice/default/coupon/type-fragments/base-remove-on-products.html new file mode 100644 index 000000000..3f5cc4a94 --- /dev/null +++ b/templates/backOffice/default/coupon/type-fragments/base-remove-on-products.html @@ -0,0 +1,63 @@ +{block name="discount-field"}{/block} + +
+ + + + +
+ + + +
+ + + + + + {intl l='Use Ctrl+click to select (or deselect) more that one product'} +
+ + diff --git a/templates/backOffice/default/coupon/type-fragments/remove-amount-on-categories.html b/templates/backOffice/default/coupon/type-fragments/remove-amount-on-categories.html index 15c528331..7f6a82c72 100644 --- a/templates/backOffice/default/coupon/type-fragments/remove-amount-on-categories.html +++ b/templates/backOffice/default/coupon/type-fragments/remove-amount-on-categories.html @@ -1,26 +1,16 @@ +{extends file="coupon/type-fragments/base-remove-on-categories.html"} -
+{block name="discount-field"} +
- + -
- +
+ - {loop type="currency" name="get-symbol" default_only="true"} -
{$SYMBOL}
- {/loop} + {loop type="currency" name="get-symbol" default_only="true"} +
{$SYMBOL}
+ {/loop} +
-
- -
- - - - - - {intl l='Use Ctrl+click to select (or deselect) more that one category'} -
+{/block} \ No newline at end of file diff --git a/templates/backOffice/default/coupon/type-fragments/remove-amount-on-products.html b/templates/backOffice/default/coupon/type-fragments/remove-amount-on-products.html index 57d45684c..033adeee1 100644 --- a/templates/backOffice/default/coupon/type-fragments/remove-amount-on-products.html +++ b/templates/backOffice/default/coupon/type-fragments/remove-amount-on-products.html @@ -1,77 +1,16 @@ +{extends file="coupon/type-fragments/base-remove-on-products.html"} -
+{block name="discount-field"} +
- + -
- +
+ - {loop type="currency" name="get-symbol" default_only="true"} -
{$SYMBOL}
- {/loop} + {loop type="currency" name="get-symbol" default_only="true"} +
{$SYMBOL}
+ {/loop} +
-
- -
- - - - - - {intl l='Use Ctrl+click to select (or deselect) more that one category'} -
- - - -
- - - - - - {intl l='Use Ctrl+click to select (or deselect) more that one category'} -
- - +{/block} \ No newline at end of file diff --git a/templates/backOffice/default/coupon/type-fragments/remove-percentage-on-categories.html b/templates/backOffice/default/coupon/type-fragments/remove-percentage-on-categories.html index 08c3655f1..8a45e1a7a 100644 --- a/templates/backOffice/default/coupon/type-fragments/remove-percentage-on-categories.html +++ b/templates/backOffice/default/coupon/type-fragments/remove-percentage-on-categories.html @@ -1,24 +1,14 @@ +{extends file="coupon/type-fragments/base-remove-on-categories.html"} -
+{block name="discount-field"} +
- + -
- +
+ -
%
+
%
+
-
- -
- - - - - - {intl l='Use Ctrl+click to select (or deselect) more that one category'} -
+{/block} \ No newline at end of file diff --git a/templates/backOffice/default/coupon/type-fragments/remove-percentage-on-products.html b/templates/backOffice/default/coupon/type-fragments/remove-percentage-on-products.html index 4787da2ee..f60b2bf11 100644 --- a/templates/backOffice/default/coupon/type-fragments/remove-percentage-on-products.html +++ b/templates/backOffice/default/coupon/type-fragments/remove-percentage-on-products.html @@ -1,75 +1,14 @@ +{extends file="coupon/type-fragments/base-remove-on-products.html"} -
+{block name="discount-field"} +
- + -
- +
+ -
%
+
%
+
-
- -
- - - - - - {intl l='Use Ctrl+click to select (or deselect) more that one category'} -
- - - -
- - - - - - {intl l='Use Ctrl+click to select (or deselect) more that one category'} -
- - +{/block} \ No newline at end of file From 96ebcf188038bf63b9705a898f698828165c78f8 Mon Sep 17 00:00:00 2001 From: Franck Allimant Date: Thu, 12 Jun 2014 16:39:27 +0200 Subject: [PATCH 04/22] Added the COUPON_CLEAR_ALL event, and a route to trigger it. --- core/lib/Thelia/Action/Coupon.php | 41 ++++++++++++------- core/lib/Thelia/Core/Event/TheliaEvents.php | 6 +++ local/modules/Front/Config/front.xml | 5 +++ .../Front/Controller/CouponController.php | 9 +++- 4 files changed, 45 insertions(+), 16 deletions(-) diff --git a/core/lib/Thelia/Action/Coupon.php b/core/lib/Thelia/Action/Coupon.php index b8e2a7553..da8862d54 100644 --- a/core/lib/Thelia/Action/Coupon.php +++ b/core/lib/Thelia/Action/Coupon.php @@ -109,6 +109,14 @@ class Coupon extends BaseAction implements EventSubscriberInterface $this->createOrUpdateCondition($modelCoupon, $event); } + /** + * Clear all coupons in session. + */ + public function clearAllCoupons() { + + $this->request->getSession()->setConsumedCoupons(array()); + } + /** * Occurring when a Coupon condition is about to be consumed * @@ -139,21 +147,22 @@ class Coupon extends BaseAction implements EventSubscriberInterface $consumedCoupons[$event->getCode()] = $event->getCode(); $this->request->getSession()->setConsumedCoupons($consumedCoupons); - - $totalDiscount = $this->couponManager->getDiscount(); - - $this->request - ->getSession() - ->getCart() - ->setDiscount($totalDiscount) - ->save(); - $this->request - ->getSession() - ->getOrder() - ->setDiscount($totalDiscount) - ; } - } + + $totalDiscount = $this->couponManager->getDiscount(); + + $this->request + ->getSession() + ->getCart() + ->setDiscount($totalDiscount) + ->save(); + + $this->request + ->getSession() + ->getOrder() + ->setDiscount($totalDiscount) + ; + } } $event->setIsValid($isValid); @@ -339,7 +348,8 @@ class Coupon extends BaseAction implements EventSubscriberInterface } } - $this->request->getSession()->setConsumedCoupons(array()); + // Clear all coupouns. + $event->getDispatcher()->dispatch(TheliaEvents::COUPON_CLEAR_ALL); } /** @@ -368,6 +378,7 @@ class Coupon extends BaseAction implements EventSubscriberInterface TheliaEvents::COUPON_CREATE => array("create", 128), TheliaEvents::COUPON_UPDATE => array("update", 128), TheliaEvents::COUPON_CONSUME => array("consume", 128), + TheliaEvents::COUPON_CLEAR_ALL => array("clearAllCoupons", 128), TheliaEvents::COUPON_CONDITION_UPDATE => array("updateCondition", 128), TheliaEvents::ORDER_SET_POSTAGE => array("testFreePostage", 132), TheliaEvents::ORDER_BEFORE_PAYMENT => array("afterOrder", 128), diff --git a/core/lib/Thelia/Core/Event/TheliaEvents.php b/core/lib/Thelia/Core/Event/TheliaEvents.php index 69c12fb73..9d67366cc 100644 --- a/core/lib/Thelia/Core/Event/TheliaEvents.php +++ b/core/lib/Thelia/Core/Event/TheliaEvents.php @@ -464,6 +464,12 @@ final class TheliaEvents */ const COUPON_CONSUME = "action.consume_coupon"; + /** + * Sent when all coupons in the current session should be cleared + */ + const COUPON_CLEAR_ALL = "action.clear_all_coupon"; + + /** * Sent just before an attempt to use a Coupon */ diff --git a/local/modules/Front/Config/front.xml b/local/modules/Front/Config/front.xml index 0a987eaa2..c37b119ad 100644 --- a/local/modules/Front/Config/front.xml +++ b/local/modules/Front/Config/front.xml @@ -160,6 +160,11 @@ order-invoice + + Front\Controller\CouponController::clearAllCouponsAction + order-invoice + + Front\Controller\OrderController::pay diff --git a/local/modules/Front/Controller/CouponController.php b/local/modules/Front/Controller/CouponController.php index 98333dd0a..8bce7b206 100644 --- a/local/modules/Front/Controller/CouponController.php +++ b/local/modules/Front/Controller/CouponController.php @@ -40,9 +40,16 @@ use Thelia\Module\Exception\DeliveryException; */ class CouponController extends BaseFrontController { + /** + * Clear all coupons. + */ + public function clearAllCouponsAction() { + // Dispatch Event to the Action + $this->getDispatcher()->dispatch(TheliaEvents::COUPON_CLEAR_ALL); + } /** - * Test Coupon consuming + * Coupon consuming */ public function consumeAction() { From 992100f1451f6e2c7bcd79bf243043d2add3e4cd Mon Sep 17 00:00:00 2001 From: Franck Allimant Date: Thu, 12 Jun 2014 16:40:07 +0200 Subject: [PATCH 05/22] Added helper to chek if number of uses is reached --- core/lib/Thelia/Model/Coupon.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/core/lib/Thelia/Model/Coupon.php b/core/lib/Thelia/Model/Coupon.php index 921078eda..616a7d040 100644 --- a/core/lib/Thelia/Model/Coupon.php +++ b/core/lib/Thelia/Model/Coupon.php @@ -41,6 +41,9 @@ use Thelia\Model\Tools\ModelEventDispatcherTrait; class Coupon extends BaseCoupon { + // Define the value of an unlimited coupon usage. + const UNLIMITED_COUPON_USE = -1; + use ModelEventDispatcherTrait; /** @@ -265,6 +268,9 @@ class Coupon extends BaseCoupon return CouponModuleQuery::create()->filterByCouponId($this->getId())->find(); } + public function isUsageUnlimited() { + return $this->getMaxUsage() == self::UNLIMITED_COUPON_USE; + } /** * Get coupon usage left, either overall, or per customer. * From b34f1c35c71bf88e8dba49ac2ccc8ec43d4e3ccf Mon Sep 17 00:00:00 2001 From: Franck Allimant Date: Thu, 12 Jun 2014 16:42:00 +0200 Subject: [PATCH 06/22] Fixed the checking of maximum coupon usage count --- core/lib/Thelia/Coupon/CouponFactory.php | 2 +- core/lib/Thelia/Coupon/CouponManager.php | 83 +++++++++++++----------- 2 files changed, 45 insertions(+), 40 deletions(-) diff --git a/core/lib/Thelia/Coupon/CouponFactory.php b/core/lib/Thelia/Coupon/CouponFactory.php index 40a4f0483..f1b87ae19 100644 --- a/core/lib/Thelia/Coupon/CouponFactory.php +++ b/core/lib/Thelia/Coupon/CouponFactory.php @@ -69,7 +69,7 @@ class CouponFactory } // Check coupon usage count - if ($couponModel->getUsagesLeft($this->facade->getCustomer()->getId()) <= 0) { + if (! $couponModel->isUsageUnlimited() && $couponModel->getUsagesLeft($this->facade->getCustomer()->getId()) <= 0) { throw new CouponNoUsageLeftException($couponCode); } diff --git a/core/lib/Thelia/Coupon/CouponManager.php b/core/lib/Thelia/Coupon/CouponManager.php index ecb491673..b4280f4a3 100644 --- a/core/lib/Thelia/Coupon/CouponManager.php +++ b/core/lib/Thelia/Coupon/CouponManager.php @@ -278,57 +278,62 @@ class CouponManager */ public function decrementQuantity(Coupon $coupon, $customerId = null) { - $ret = false; + if ($coupon->isUsageUnlimited()) { + $ret = true; + } + else { + $ret = false; - try { + try { - $usageLeft = $coupon->getUsagesLeft($customerId); + $usageLeft = $coupon->getUsagesLeft($customerId); - if ($usageLeft > 0) { + if ($usageLeft > 0) { - // If the coupon usage is per user, add an entry to coupon customer usage count table - if ($coupon->getPerCustomerUsageCount()) { + // If the coupon usage is per user, add an entry to coupon customer usage count table + if ($coupon->getPerCustomerUsageCount()) { - if (null == $customerId) { - throw new \LogicException("Customer should not be null at this time."); - } + if (null == $customerId) { + throw new \LogicException("Customer should not be null at this time."); + } - $ccc = CouponCustomerCountQuery::create() - ->filterByCouponId($coupon->getId()) - ->filterByCustomerId($customerId) - ->findOne() - ; + $ccc = CouponCustomerCountQuery::create() + ->filterByCouponId($coupon->getId()) + ->filterByCustomerId($customerId) + ->findOne() + ; - if ($ccc === null) { - $ccc = new CouponCustomerCount(); + if ($ccc === null) { + $ccc = new CouponCustomerCount(); + + $ccc + ->setCustomerId($customerId) + ->setCouponId($coupon->getId()) + ->setCount(0); + } + + $newCount = 1 + $ccc->getCount(); $ccc - ->setCustomerId($customerId) - ->setCouponId($coupon->getId()) - ->setCount(0); + ->setCount($newCount) + ->save() + ; + + $ret = $usageLeft - $newCount; + } else { + $usageLeft--; + + $coupon->setMaxUsage($usageLeft); + + $coupon->save(); + + $ret = $usageLeft; } - - $newCount = 1 + $ccc->getCount(); - - $ccc - ->setCount($newCount) - ->save() - ; - - $ret = $usageLeft - $newCount; - } else { - $usageLeft--; - - $coupon->setMaxUsage($usageLeft); - - $coupon->save(); - - $ret = $usageLeft; } + } catch (\Exception $ex) { + // Just log the problem. + Tlog::getInstance()->addError(sprintf("Failed to decrement coupon %s: %s", $coupon->getCode(), $ex->getMessage())); } - } catch (\Exception $ex) { - // Just log the problem. - Tlog::getInstance()->addError(sprintf("Failed to decrement coupon %s: %s", $coupon->getCode(), $ex->getMessage())); } return $ret; From e9a0661938aa82b8913729055e04a279bc037fd9 Mon Sep 17 00:00:00 2001 From: Franck Allimant Date: Thu, 12 Jun 2014 17:00:17 +0200 Subject: [PATCH 07/22] Pushed forward the refactoring, using traits --- core/lib/Thelia/Action/Coupon.php | 2 +- .../lib/Thelia/Coupon/Type/AbstractRemove.php | 129 ++++++++++++++++++ .../Type/AbstractRemoveOnAttributeValues.php | 18 ++- .../Type/AbstractRemoveOnCategories.php | 10 +- .../Coupon/Type/AbstractRemoveOnProducts.php | 10 +- .../AmountAndPercentageCouponInterface.php | 64 +++++++++ .../Thelia/Coupon/Type/AmountCouponTrait.php | 91 ++++++++++++ .../lib/Thelia/Coupon/Type/CouponAbstract.php | 2 +- .../Coupon/Type/PercentageCouponTrait.php | 90 ++++++++++++ .../Type/RemoveAmountOnAttributeValues.php | 52 +------ .../Coupon/Type/RemoveAmountOnCategories.php | 51 +------ .../Coupon/Type/RemoveAmountOnProducts.php | 51 +------ .../RemovePercentageOnAttributeValues.php | 52 +------ .../Type/RemovePercentageOnCategories.php | 55 +------- .../Type/RemovePercentageOnProducts.php | 55 +------- core/lib/Thelia/Coupon/Type/RemoveXAmount.php | 54 +++----- .../lib/Thelia/Coupon/Type/RemoveXPercent.php | 81 ++--------- .../base-remove-on-attributes.html | 2 +- .../type-fragments/remove-x-amount.html | 2 +- .../type-fragments/remove-x-percent.html | 2 +- 20 files changed, 461 insertions(+), 412 deletions(-) create mode 100644 core/lib/Thelia/Coupon/Type/AbstractRemove.php create mode 100644 core/lib/Thelia/Coupon/Type/AmountAndPercentageCouponInterface.php create mode 100644 core/lib/Thelia/Coupon/Type/AmountCouponTrait.php create mode 100644 core/lib/Thelia/Coupon/Type/PercentageCouponTrait.php diff --git a/core/lib/Thelia/Action/Coupon.php b/core/lib/Thelia/Action/Coupon.php index da8862d54..9de27bf58 100644 --- a/core/lib/Thelia/Action/Coupon.php +++ b/core/lib/Thelia/Action/Coupon.php @@ -148,7 +148,7 @@ class Coupon extends BaseAction implements EventSubscriberInterface $this->request->getSession()->setConsumedCoupons($consumedCoupons); } - + $totalDiscount = $this->couponManager->getDiscount(); $this->request diff --git a/core/lib/Thelia/Coupon/Type/AbstractRemove.php b/core/lib/Thelia/Coupon/Type/AbstractRemove.php new file mode 100644 index 000000000..f96a660e9 --- /dev/null +++ b/core/lib/Thelia/Coupon/Type/AbstractRemove.php @@ -0,0 +1,129 @@ + + */ +abstract class AbstractRemove extends CouponAbstract implements AmountAndPercentageCouponInterface +{ + /** + * Set the value of specific coupon fields. + * + * @param Array $effects the Coupon effects params + */ + public abstract function setFieldsValue($effects); + + /** + * Get the discount for a specific cart item. + * + * @param CartItem $cartItem the cart item + * @return float the discount value + */ + public abstract function getCartItemDiscount($cartItem); + + /** + * @inheritdoc + */ + public function set( + FacadeInterface $facade, + $code, + $title, + $shortDescription, + $description, + array $effects, + $isCumulative, + $isRemovingPostage, + $isAvailableOnSpecialOffers, + $isEnabled, + $maxUsage, + \DateTime $expirationDate, + $freeShippingForCountries, + $freeShippingForModules, + $perCustomerUsageCount + ) + { + parent::set( + $facade, $code, $title, $shortDescription, $description, $effects, + $isCumulative, $isRemovingPostage, $isAvailableOnSpecialOffers, $isEnabled, $maxUsage, $expirationDate, + $freeShippingForCountries, + $freeShippingForModules, + $perCustomerUsageCount + ); + + $this->setFieldsValue($effects); + + return $this; + } + /** + * @inheritdoc + */ + public function exec() + { + // This coupon subtracts the specified amount from the order total + // for each product of the selected categories. + $discount = 0; + + $cartItems = $this->facade->getCart()->getCartItems(); + + /** @var CartItem $cartItem */ + foreach ($cartItems as $cartItem) { + if (! $cartItem->getPromo() || $this->isAvailableOnSpecialOffers()) { + $categories = $cartItem->getProduct()->getCategories(); + + /** @var Category $category */ + foreach ($categories as $category) { + + if (in_array($category->getId(), $this->category_list)) { + $discount += $this->getCartItemDiscount($cartItem); + + break; + } + } + } + } + + return $discount; + } + + /** + * @inheritdoc + */ + public function drawBaseBackOfficeInputs($templateName, $otherFields) + { + return $this->facade->getParser()->render($templateName, $otherFields); + } + + /** + * @inheritdoc + */ + public function getBaseFieldList($otherFields) + { + return array_merge($otherFields); + } + + /** + * @inheritdoc + */ + public function checkBaseCouponFieldValue($fieldName, $fieldValue) + { + return $fieldValue; + } +} \ No newline at end of file diff --git a/core/lib/Thelia/Coupon/Type/AbstractRemoveOnAttributeValues.php b/core/lib/Thelia/Coupon/Type/AbstractRemoveOnAttributeValues.php index eee1db95c..c0c6f3844 100644 --- a/core/lib/Thelia/Coupon/Type/AbstractRemoveOnAttributeValues.php +++ b/core/lib/Thelia/Coupon/Type/AbstractRemoveOnAttributeValues.php @@ -23,7 +23,7 @@ use Thelia\Model\CartItem; * @package Coupon * @author Franck Allimant */ -abstract class AbstractRemoveOnAttributeValues extends CouponAbstract +abstract class AbstractRemoveOnAttributeValues extends CouponAbstract implements AmountAndPercentageCouponInterface { const ATTRIBUTES_AV_LIST = 'attribute_avs'; const ATTRIBUTE = 'attribute_id'; @@ -35,7 +35,7 @@ abstract class AbstractRemoveOnAttributeValues extends CouponAbstract * Set the value of specific coupon fields. * @param Array $effects the Coupon effects params */ - protected abstract function setFieldsValue($effects); + public abstract function setFieldsValue($effects); /** * Get the discount for a specific cart item. @@ -43,7 +43,7 @@ abstract class AbstractRemoveOnAttributeValues extends CouponAbstract * @param CartItem $cartItem the cart item * @return float the discount value */ - protected abstract function getCartItemDiscount($cartItem); + public abstract function getCartItemDiscount($cartItem); /** * @inheritdoc @@ -122,7 +122,13 @@ abstract class AbstractRemoveOnAttributeValues extends CouponAbstract } /** - * @inheritdoc + * Renders the template which implements coupon specific user-input, + * using the provided template file, and a list of specific input fields. + * + * @param string $templateName the path to the template + * @param array $otherFields the list of additional fields fields + * + * @return string the rendered template. */ public function drawBaseBackOfficeInputs($templateName, $otherFields) { @@ -141,7 +147,7 @@ abstract class AbstractRemoveOnAttributeValues extends CouponAbstract /** * @inheritdoc */ - protected function getBaseFieldList($otherFields) + public function getBaseFieldList($otherFields) { return array_merge($otherFields, [self::ATTRIBUTE, self::ATTRIBUTES_AV_LIST]); } @@ -149,7 +155,7 @@ abstract class AbstractRemoveOnAttributeValues extends CouponAbstract /** * @inheritdoc */ - protected function checkBaseCouponFieldValue($fieldName, $fieldValue) + public function checkBaseCouponFieldValue($fieldName, $fieldValue) { if ($fieldName === self::ATTRIBUTE) { if (empty($fieldValue)) { diff --git a/core/lib/Thelia/Coupon/Type/AbstractRemoveOnCategories.php b/core/lib/Thelia/Coupon/Type/AbstractRemoveOnCategories.php index 6d6622126..174c6f7c3 100644 --- a/core/lib/Thelia/Coupon/Type/AbstractRemoveOnCategories.php +++ b/core/lib/Thelia/Coupon/Type/AbstractRemoveOnCategories.php @@ -22,7 +22,7 @@ use Thelia\Model\CartItem; * @package Coupon * @author Franck Allimant */ -abstract class AbstractRemoveOnCategories extends CouponAbstract +abstract class AbstractRemoveOnCategories extends CouponAbstract implements AmountAndPercentageCouponInterface { const CATEGORIES_LIST = 'categories'; @@ -33,7 +33,7 @@ abstract class AbstractRemoveOnCategories extends CouponAbstract * * @param Array $effects the Coupon effects params */ - protected abstract function setFieldsValue($effects); + public abstract function setFieldsValue($effects); /** * Get the discount for a specific cart item. @@ -41,7 +41,7 @@ abstract class AbstractRemoveOnCategories extends CouponAbstract * @param CartItem $cartItem the cart item * @return float the discount value */ - protected abstract function getCartItemDiscount($cartItem); + public abstract function getCartItemDiscount($cartItem); /** * @inheritdoc @@ -125,7 +125,7 @@ abstract class AbstractRemoveOnCategories extends CouponAbstract /** * @inheritdoc */ - protected function getBaseFieldList($otherFields) + public function getBaseFieldList($otherFields) { return array_merge($otherFields, [self::CATEGORIES_LIST]); } @@ -133,7 +133,7 @@ abstract class AbstractRemoveOnCategories extends CouponAbstract /** * @inheritdoc */ - protected function checkBaseCouponFieldValue($fieldName, $fieldValue) + public function checkBaseCouponFieldValue($fieldName, $fieldValue) { if ($fieldName === self::CATEGORIES_LIST) { if (empty($fieldValue)) { diff --git a/core/lib/Thelia/Coupon/Type/AbstractRemoveOnProducts.php b/core/lib/Thelia/Coupon/Type/AbstractRemoveOnProducts.php index 2bb5ecea8..c06df1f29 100644 --- a/core/lib/Thelia/Coupon/Type/AbstractRemoveOnProducts.php +++ b/core/lib/Thelia/Coupon/Type/AbstractRemoveOnProducts.php @@ -22,7 +22,7 @@ use Thelia\Model\CartItem; * @package Coupon * @author Franck Allimant */ -abstract class AbstractRemoveOnProducts extends CouponAbstract +abstract class AbstractRemoveOnProducts extends CouponAbstract implements AmountAndPercentageCouponInterface { const CATEGORY_ID = 'category_id'; const PRODUCTS_LIST = 'products'; @@ -35,7 +35,7 @@ abstract class AbstractRemoveOnProducts extends CouponAbstract * * @param Array $effects the Coupon effects params */ - protected abstract function setFieldsValue($effects); + public abstract function setFieldsValue($effects); /** * Get the discount for a specific cart item. @@ -43,7 +43,7 @@ abstract class AbstractRemoveOnProducts extends CouponAbstract * @param CartItem $cartItem the cart item * @return float the discount value */ - protected abstract function getCartItemDiscount($cartItem); + public abstract function getCartItemDiscount($cartItem); /** * @inheritdoc @@ -129,7 +129,7 @@ abstract class AbstractRemoveOnProducts extends CouponAbstract /** * @inheritdoc */ - protected function getBaseFieldList($otherFields) + public function getBaseFieldList($otherFields) { return array_merge($otherFields, [self::CATEGORY_ID, self::PRODUCTS_LIST]); } @@ -137,7 +137,7 @@ abstract class AbstractRemoveOnProducts extends CouponAbstract /** * @inheritdoc */ - protected function checkBaseCouponFieldValue($fieldName, $fieldValue) + public function checkBaseCouponFieldValue($fieldName, $fieldValue) { if ($fieldName === self::CATEGORY_ID) { if (empty($fieldValue)) { diff --git a/core/lib/Thelia/Coupon/Type/AmountAndPercentageCouponInterface.php b/core/lib/Thelia/Coupon/Type/AmountAndPercentageCouponInterface.php new file mode 100644 index 000000000..7bc28857f --- /dev/null +++ b/core/lib/Thelia/Coupon/Type/AmountAndPercentageCouponInterface.php @@ -0,0 +1,64 @@ + + * + */ +interface AmountAndPercentageCouponInterface +{ + + /** + * Set the value of specific coupon fields. + * @param Array $effects the Coupon effects params + */ + public function setFieldsValue($effects); + + /** + * Get the discount for a specific cart item. + * + * @param CartItem $cartItem the cart item + * @return float the discount value + */ + public function getCartItemDiscount($cartItem); + + + /** + * Renders the template which implements coupon specific user-input, + * using the provided template file, and a list of specific input fields. + * + * @param string $templateName the path to the template + * @param array $otherFields the list of additional fields fields + * + * @return string the rendered template. + */ + public function drawBaseBackOfficeInputs($templateName, $otherFields); + + /** + * @inheritdoc + */ + public function getBaseFieldList($otherFields); + + /** + * + */ + public function checkBaseCouponFieldValue($fieldName, $fieldValue); +} \ No newline at end of file diff --git a/core/lib/Thelia/Coupon/Type/AmountCouponTrait.php b/core/lib/Thelia/Coupon/Type/AmountCouponTrait.php new file mode 100644 index 000000000..e743f7b4d --- /dev/null +++ b/core/lib/Thelia/Coupon/Type/AmountCouponTrait.php @@ -0,0 +1,91 @@ + + * @package Thelia\Coupon\Type + */ +Trait AmountCouponTrait { + + // The amount is already defined in CouponAbstract, and should not be redefined here. + // protected $amount = 0; + + /** + * Should return the amount field name, defined in the parent class. + * + * @return string the percentage field name + */ + protected abstract function getAmountFieldName(); + + /** + * @inheritdoc + */ + protected function setFieldsValue($effects) { + $this->amount = $effects[$this->getAmountFieldName()]; + } + + /** + * @inheritdoc + */ + public function getCartItemDiscount($cartItem) { + return $cartItem->getQuantity() * $this->amount; + } + + /** + * @inheritdoc + */ + public function callDrawBackOfficeInputs($templateName) + { + return $this->drawBaseBackOfficeInputs($templateName, [ + 'amount_field_name' => $this->makeCouponFieldName($this->getAmountFieldName()), + 'amount_value' => $this->amount + ]); + } + + /** + * @inheritdoc + */ + protected function getFieldList() + { + return $this->getBaseFieldList([$this->getAmountFieldName()]); + } + + /** + * @inheritdoc + */ + protected function checkCouponFieldValue($fieldName, $fieldValue) + { + $this->checkBaseCouponFieldValue($fieldName, $fieldValue); + + if ($fieldName === $this->getAmountFieldName()) { + + if (floatval($fieldValue) < 0) { + throw new \InvalidArgumentException( + Translator::getInstance()->trans( + 'Value %val for Discount Amount is invalid. Please enter a positive value.', + [ '%val' => $fieldValue] + ) + ); + } + } + + return $fieldValue; + } +} \ No newline at end of file diff --git a/core/lib/Thelia/Coupon/Type/CouponAbstract.php b/core/lib/Thelia/Coupon/Type/CouponAbstract.php index 6d57b0d38..71b986fcb 100644 --- a/core/lib/Thelia/Coupon/Type/CouponAbstract.php +++ b/core/lib/Thelia/Coupon/Type/CouponAbstract.php @@ -499,4 +499,4 @@ abstract class CouponAbstract implements CouponInterface return $effects; } -} +} \ No newline at end of file diff --git a/core/lib/Thelia/Coupon/Type/PercentageCouponTrait.php b/core/lib/Thelia/Coupon/Type/PercentageCouponTrait.php new file mode 100644 index 000000000..0b05d126b --- /dev/null +++ b/core/lib/Thelia/Coupon/Type/PercentageCouponTrait.php @@ -0,0 +1,90 @@ + + * @package Thelia\Coupon\Type + */ +Trait PercentageCouponTrait { + + public $percentage = 0; + + /** + * Should return the percentage field name, defined in the parent class. + * + * @return string the percentage field name + */ + protected abstract function getPercentageFieldName(); + + /** + * @inheritdoc + */ + protected function setFieldsValue($effects) { + $this->percentage = $effects[$this->getPercentageFieldName()]; + } + + /** + * @inheritdoc + */ + public function getCartItemDiscount($cartItem) { + return $cartItem->getQuantity() * $cartItem->getPrice() * ($this->percentage / 100); + } + + /** + * @inheritdoc + */ + public function callDrawBackOfficeInputs($templateName) + { + return $this->drawBaseBackOfficeInputs($templateName, [ + 'percentage_field_name' => $this->makeCouponFieldName($this->getPercentageFieldName()), + 'percentage_value' => $this->percentage, + ]); + } + + /** + * @inheritdoc + */ + protected function getFieldList() + { + return $this->getBaseFieldList([$this->getPercentageFieldName()]); + } + + /** + * @inheritdoc + */ + protected function checkCouponFieldValue($fieldName, $fieldValue) + { + $this->checkBaseCouponFieldValue($fieldName, $fieldValue); + + if ($fieldName === $this->getPercentageFieldName()) { + + $pcent = floatval($fieldValue); + + if ($pcent <= 0 || $pcent > 100) { + throw new \InvalidArgumentException( + Translator::getInstance()->trans( + 'Value %val for Percent Discount is invalid. Please enter a positive value between 1 and 100.', + [ '%val' => $fieldValue] + ) + ); + } + } + + return $fieldValue; + } +} \ No newline at end of file diff --git a/core/lib/Thelia/Coupon/Type/RemoveAmountOnAttributeValues.php b/core/lib/Thelia/Coupon/Type/RemoveAmountOnAttributeValues.php index 523365d08..495c908dc 100644 --- a/core/lib/Thelia/Coupon/Type/RemoveAmountOnAttributeValues.php +++ b/core/lib/Thelia/Coupon/Type/RemoveAmountOnAttributeValues.php @@ -22,23 +22,14 @@ use Thelia\Core\Translation\Translator; */ class RemoveAmountOnAttributeValues extends AbstractRemoveOnAttributeValues { + use AmountCouponTrait; + /** @var string Service Id */ protected $serviceId = 'thelia.coupon.type.remove_amount_on_attribute_av'; - /** - * @inheritdoc - */ - protected function setFieldsValue($effects) { - // Nothing to do, the amount is processed by CouponAbstract. + protected function getAmountFieldName() { + return self::AMOUNT_FIELD_NAME; } - - /** - * @inheritdoc - */ - public function getCartItemDiscount($cartItem) { - return $cartItem->getQuantity() * $this->amount; - } - /** * @inheritdoc */ @@ -70,39 +61,6 @@ class RemoveAmountOnAttributeValues extends AbstractRemoveOnAttributeValues */ public function drawBackOfficeInputs() { - return $this->drawBaseBackOfficeInputs('coupon/type-fragments/remove-amount-on-attributes.html', [ - 'amount_field_name' => $this->makeCouponFieldName(self::AMOUNT_FIELD_NAME), - 'amount_value' => $this->amount - ]); - } - - /** - * @inheritdoc - */ - protected function getFieldList() - { - return $this->getBaseFieldList([self::AMOUNT_FIELD_NAME]); - } - - /** - * @inheritdoc - */ - protected function checkCouponFieldValue($fieldName, $fieldValue) - { - $this->checkBaseCouponFieldValue($fieldName, $fieldValue); - - if ($fieldName === self::AMOUNT_FIELD_NAME) { - - if (floatval($fieldValue) < 0) { - throw new \InvalidArgumentException( - Translator::getInstance()->trans( - 'Value %val for Discount Amount is invalid. Please enter a positive value.', - [ '%val' => $fieldValue] - ) - ); - } - } - - return $fieldValue; + return $this->callDrawBackOfficeInputs('coupon/type-fragments/remove-amount-on-attributes.html'); } } diff --git a/core/lib/Thelia/Coupon/Type/RemoveAmountOnCategories.php b/core/lib/Thelia/Coupon/Type/RemoveAmountOnCategories.php index e5f3070b0..8843a07d8 100644 --- a/core/lib/Thelia/Coupon/Type/RemoveAmountOnCategories.php +++ b/core/lib/Thelia/Coupon/Type/RemoveAmountOnCategories.php @@ -25,21 +25,13 @@ use Thelia\Model\Category; */ class RemoveAmountOnCategories extends AbstractRemoveOnCategories { + use AmountCouponTrait; + /** @var string Service Id */ protected $serviceId = 'thelia.coupon.type.remove_amount_on_categories'; - /** - * @inheritdoc - */ - protected function setFieldsValue($effects) { - // Nothing to do, the amount is processed by CouponAbstract. - } - - /** - * @inheritdoc - */ - public function getCartItemDiscount($cartItem) { - return $cartItem->getQuantity() * $this->amount; + protected function getAmountFieldName() { + return self::AMOUNT_FIELD_NAME; } /** @@ -73,39 +65,6 @@ class RemoveAmountOnCategories extends AbstractRemoveOnCategories */ public function drawBackOfficeInputs() { - return $this->drawBaseBackOfficeInputs('coupon/type-fragments/remove-amount-on-categories.html', [ - 'amount_field_name' => $this->makeCouponFieldName(self::AMOUNT_FIELD_NAME), - 'amount_value' => $this->amount - ]); - } - - /** - * @inheritdoc - */ - protected function getFieldList() - { - return $this->getBaseFieldList([self::AMOUNT_FIELD_NAME]); - } - - /** - * @inheritdoc - */ - protected function checkCouponFieldValue($fieldName, $fieldValue) - { - $this->checkBaseCouponFieldValue($fieldName, $fieldValue); - - if ($fieldName === self::AMOUNT_FIELD_NAME) { - - if (floatval($fieldValue) < 0) { - throw new \InvalidArgumentException( - Translator::getInstance()->trans( - 'Value %val for Discount Amount is invalid. Please enter a positive value.', - [ '%val' => $fieldValue] - ) - ); - } - } - - return $fieldValue; + return $this->callDrawBackOfficeInputs('coupon/type-fragments/remove-amount-on-categories.html'); } } diff --git a/core/lib/Thelia/Coupon/Type/RemoveAmountOnProducts.php b/core/lib/Thelia/Coupon/Type/RemoveAmountOnProducts.php index 1061171e6..4d6d05906 100644 --- a/core/lib/Thelia/Coupon/Type/RemoveAmountOnProducts.php +++ b/core/lib/Thelia/Coupon/Type/RemoveAmountOnProducts.php @@ -25,21 +25,13 @@ use Thelia\Model\Product; */ class RemoveAmountOnProducts extends AbstractRemoveOnProducts { + use AmountCouponTrait; + /** @var string Service Id */ protected $serviceId = 'thelia.coupon.type.remove_amount_on_products'; - /** - * @inheritdoc - */ - protected function setFieldsValue($effects) { - // Nothing to do: amount is processed by CouponAbstract - } - - /** - * @inheritdoc - */ - protected function getCartItemDiscount($cartItem) { - return $cartItem->getQuantity() * $this->amount; + protected function getAmountFieldName() { + return self::AMOUNT_FIELD_NAME; } /** @@ -75,39 +67,6 @@ class RemoveAmountOnProducts extends AbstractRemoveOnProducts */ public function drawBackOfficeInputs() { - return $this->drawBaseBackOfficeInputs('coupon/type-fragments/remove-amount-on-products.html', [ - 'amount_field_name' => $this->makeCouponFieldName(self::AMOUNT_FIELD_NAME), - 'amount_value' => $this->amount - ]); - } - - /** - * @inheritdoc - */ - protected function getFieldList() - { - return $this->getBaseFieldList([self::AMOUNT_FIELD_NAME]); - } - - /** - * @inheritdoc - */ - protected function checkCouponFieldValue($fieldName, $fieldValue) - { - $this->checkBaseCouponFieldValue($fieldName, $fieldValue); - - if ($fieldName === self::AMOUNT_FIELD_NAME) { - - if (floatval($fieldValue) < 0) { - throw new \InvalidArgumentException( - Translator::getInstance()->trans( - 'Value %val for Discount Amount is invalid. Please enter a positive value.', - [ '%val' => $fieldValue] - ) - ); - } - } - - return $fieldValue; + return $this->callDrawBackOfficeInputs('coupon/type-fragments/remove-amount-on-products.html'); } } \ No newline at end of file diff --git a/core/lib/Thelia/Coupon/Type/RemovePercentageOnAttributeValues.php b/core/lib/Thelia/Coupon/Type/RemovePercentageOnAttributeValues.php index 26c55022c..509472e9d 100644 --- a/core/lib/Thelia/Coupon/Type/RemovePercentageOnAttributeValues.php +++ b/core/lib/Thelia/Coupon/Type/RemovePercentageOnAttributeValues.php @@ -24,23 +24,16 @@ class RemovePercentageOnAttributeValues extends AbstractRemoveOnAttributeValues { const PERCENTAGE = 'percentage'; - public $percentage = 0; + use PercentageCouponTrait; /** @var string Service Id */ protected $serviceId = 'thelia.coupon.type.remove_percentage_on_attribute_av'; - /** + /** * @inheritdoc */ - protected function setFieldsValue($effects) { - $this->percentage = $effects[self::PERCENTAGE]; - } - - /** - * @inheritdoc - */ - public function getCartItemDiscount($cartItem) { - return $cartItem->getQuantity() * $cartItem->getPrice() * $this->percentage; + protected function getPercentageFieldName() { + return self::PERCENTAGE; } /** @@ -74,41 +67,6 @@ class RemovePercentageOnAttributeValues extends AbstractRemoveOnAttributeValues */ public function drawBackOfficeInputs() { - return $this->drawBaseBackOfficeInputs('coupon/type-fragments/remove-percentage-on-attributes.html', [ - 'percentage_field_name' => $this->makeCouponFieldName(self::PERCENTAGE), - 'percentage_value' => $this->percentage, - ]); - } - - /** - * @inheritdoc - */ - protected function getFieldList() - { - return $this->getBaseFieldList([self::PERCENTAGE]); - } - - /** - * @inheritdoc - */ - protected function checkCouponFieldValue($fieldName, $fieldValue) - { - $this->checkBaseCouponFieldValue($fieldName, $fieldValue); - - if ($fieldName === self::PERCENTAGE) { - - $pcent = floatval($fieldValue); - - if ($pcent <= 0 || $pcent > 100) { - throw new \InvalidArgumentException( - Translator::getInstance()->trans( - 'Value %val for Percent Discount is invalid. Please enter a positive value between 1 and 100.', - [ '%val' => $fieldValue] - ) - ); - } - } - - return $fieldValue; + return $this->callDrawBackOfficeInputs('coupon/type-fragments/remove-percentage-on-attributes.html'); } } diff --git a/core/lib/Thelia/Coupon/Type/RemovePercentageOnCategories.php b/core/lib/Thelia/Coupon/Type/RemovePercentageOnCategories.php index dc5a533bd..0106a1ead 100644 --- a/core/lib/Thelia/Coupon/Type/RemovePercentageOnCategories.php +++ b/core/lib/Thelia/Coupon/Type/RemovePercentageOnCategories.php @@ -22,25 +22,18 @@ use Thelia\Model\Category; */ class RemovePercentageOnCategories extends AbstractRemoveOnCategories { - const PERCENTAGE = 'percentage'; + const PERCENTAGE = 'percentage'; + + use PercentageCouponTrait; /** @var string Service Id */ protected $serviceId = 'thelia.coupon.type.remove_percentage_on_categories'; - protected $percentage = 0; - /** * @inheritdoc */ - protected function setFieldsValue($effects) { - $this->percentage = $effects[self::PERCENTAGE]; - } - - /** - * @inheritdoc - */ - public function getCartItemDiscount($cartItem) { - return $cartItem->getQuantity() * $cartItem->getPrice() * $this->percentage; + protected function getPercentageFieldName() { + return self::PERCENTAGE; } /** @@ -74,42 +67,6 @@ class RemovePercentageOnCategories extends AbstractRemoveOnCategories */ public function drawBackOfficeInputs() { - return $this->drawBaseBackOfficeInputs('coupon/type-fragments/remove-percentage-on-categories.html', [ - 'percentage_field_name' => $this->makeCouponFieldName(self::PERCENTAGE), - 'percentage_value' => $this->percentage, - ]); + return $this->callDrawBackOfficeInputs('coupon/type-fragments/remove-percentage-on-categories.html'); } - - /** - * @inheritdoc - */ - protected function getFieldList() - { - return $this->getBaseFieldList([self::PERCENTAGE]); - } - - /** - * @inheritdoc - */ - protected function checkCouponFieldValue($fieldName, $fieldValue) - { - $this->checkBaseCouponFieldValue($fieldName, $fieldValue); - - if ($fieldName === self::PERCENTAGE) { - - $pcent = floatval($fieldValue); - - if ($pcent <= 0 || $pcent > 100) { - throw new \InvalidArgumentException( - Translator::getInstance()->trans( - 'Value %val for Percent Discount is invalid. Please enter a positive value between 1 and 100.', - [ '%val' => $fieldValue] - ) - ); - } - } - - return $fieldValue; - } - } diff --git a/core/lib/Thelia/Coupon/Type/RemovePercentageOnProducts.php b/core/lib/Thelia/Coupon/Type/RemovePercentageOnProducts.php index 332d0feed..df48abf31 100644 --- a/core/lib/Thelia/Coupon/Type/RemovePercentageOnProducts.php +++ b/core/lib/Thelia/Coupon/Type/RemovePercentageOnProducts.php @@ -25,26 +25,18 @@ use Thelia\Model\Product; */ class RemovePercentageOnProducts extends AbstractRemoveOnProducts { - const PERCENTAGE = 'percentage'; + const PERCENTAGE = 'percentage'; + + use PercentageCouponTrait; /** @var string Service Id */ protected $serviceId = 'thelia.coupon.type.remove_percentage_on_products'; - public $percentage = 0; - /** * @inheritdoc */ - protected function setFieldsValue($effects) { - - $this->percentage = $effects[self::PERCENTAGE]; - } - - /** - * @inheritdoc - */ - protected function getCartItemDiscount($cartItem) { - return $cartItem->getQuantity() * $cartItem->getPrice() * $this->percentage; + protected function getPercentageFieldName() { + return self::PERCENTAGE; } /** @@ -80,41 +72,6 @@ class RemovePercentageOnProducts extends AbstractRemoveOnProducts */ public function drawBackOfficeInputs() { - return $this->drawBaseBackOfficeInputs('coupon/type-fragments/remove-percentage-on-products.html', [ - 'percentage_field_name' => $this->makeCouponFieldName(self::PERCENTAGE), - 'percentage_value' => $this->percentage, - ]); - } - - /** - * @inheritdoc - */ - protected function getFieldList() - { - return $this->getBaseFieldList([self::PERCENTAGE]); - } - - /** - * @inheritdoc - */ - protected function checkCouponFieldValue($fieldName, $fieldValue) - { - $this->checkBaseCouponFieldValue($fieldName, $fieldValue); - - if ($fieldName === self::PERCENTAGE) { - - $pcent = floatval($fieldValue); - - if ($pcent <= 0 || $pcent > 100) { - throw new \InvalidArgumentException( - Translator::getInstance()->trans( - 'Value %val for Percent Discount is invalid. Please enter a positive value between 1 and 100.', - [ '%val' => $fieldValue] - ) - ); - } - } - - return $fieldValue; + return $this->callDrawBackOfficeInputs('coupon/type-fragments/remove-percentage-on-products.html'); } } \ No newline at end of file diff --git a/core/lib/Thelia/Coupon/Type/RemoveXAmount.php b/core/lib/Thelia/Coupon/Type/RemoveXAmount.php index 7ded8108c..64fcfe033 100644 --- a/core/lib/Thelia/Coupon/Type/RemoveXAmount.php +++ b/core/lib/Thelia/Coupon/Type/RemoveXAmount.php @@ -18,14 +18,20 @@ use Thelia\Core\Translation\Translator; * Allow to remove an amount from the checkout total * * @package Coupon - * @author Guillaume MOREL + * @author Guillaume MOREL , Franck Allimant * */ -class RemoveXAmount extends CouponAbstract +class RemoveXAmount extends AbstractRemove { + use AmountCouponTrait; + /** @var string Service Id */ protected $serviceId = 'thelia.coupon.type.remove_x_amount'; + protected function getAmountFieldName() { + return self::AMOUNT_FIELD_NAME; + } + /** * @inheritdoc */ @@ -52,43 +58,19 @@ class RemoveXAmount extends CouponAbstract return $toolTip; } + /** + * @inheritdoc + */ + public function exec() + { + return $this->amount; + } + /** * @inheritdoc */ public function drawBackOfficeInputs() { - return $this->facade->getParser()->render('coupon/type-fragments/remove-x-amount.html', [ - 'fieldName' => $this->makeCouponFieldName(self::AMOUNT_FIELD_NAME), - 'value' => $this->amount - ]); + return $this->callDrawBackOfficeInputs('coupon/type-fragments/remove-x-amount.html'); } - - /** - * @inheritdoc - */ - protected function getFieldList() - { - return [self::AMOUNT_FIELD_NAME]; - } - - /** - * @inheritdoc - */ - protected function checkCouponFieldValue($fieldName, $fieldValue) - { - if ($fieldName === self::AMOUNT_FIELD_NAME) { - - if (floatval($fieldValue) < 0) { - throw new \InvalidArgumentException( - Translator::getInstance()->trans( - 'Value %val for Disount Amount is invalid. Please enter a positive value.', - [ '%val' => $fieldValue] - ) - ); - } - } - - return $fieldValue; - } - -} +} \ No newline at end of file diff --git a/core/lib/Thelia/Coupon/Type/RemoveXPercent.php b/core/lib/Thelia/Coupon/Type/RemoveXPercent.php index 554e3f5da..2799cf948 100644 --- a/core/lib/Thelia/Coupon/Type/RemoveXPercent.php +++ b/core/lib/Thelia/Coupon/Type/RemoveXPercent.php @@ -17,81 +17,23 @@ use Thelia\Coupon\FacadeInterface; /** * @package Coupon - * @author Guillaume MOREL + * @author Guillaume MOREL , Franck Allimant * */ -class RemoveXPercent extends CouponAbstract +class RemoveXPercent extends AbstractRemove { const INPUT_PERCENTAGE_NAME = 'percentage'; + use PercentageCouponTrait; + /** @var string Service Id */ protected $serviceId = 'thelia.coupon.type.remove_x_percent'; - /** @var float Percentage removed from the Cart */ - protected $percentage = 0; - /** * @inheritdoc */ - public function set( - FacadeInterface $facade, - $code, - $title, - $shortDescription, - $description, - array $effects, - $isCumulative, - $isRemovingPostage, - $isAvailableOnSpecialOffers, - $isEnabled, - $maxUsage, - \DateTime $expirationDate, - $freeShippingForCountries, - $freeShippingForModules, - $perCustomerUsageCount - ) - { - parent::set( - $facade, $code, $title, $shortDescription, $description, $effects, - $isCumulative, $isRemovingPostage, $isAvailableOnSpecialOffers, $isEnabled, $maxUsage, $expirationDate, - $freeShippingForCountries, - $freeShippingForModules, - $perCustomerUsageCount - ); - - $this->percentage = $effects[self::INPUT_PERCENTAGE_NAME]; - - return $this; - } - - /** - * @inheritdoc - */ - public function exec() - { - return round($this->facade->getCartTotalTaxPrice($this->isAvailableOnSpecialOffers()) * $this->percentage/100, 2); - } - - /** - * @inheritdoc - */ - protected function checkCouponFieldValue($fieldName, $fieldValue) - { - if ($fieldName === self::INPUT_PERCENTAGE_NAME) { - - $pcent = floatval($fieldValue); - - if ($pcent <= 0 || $pcent > 100) { - throw new \InvalidArgumentException( - Translator::getInstance()->trans( - 'Value %val for Percent Discount is invalid. Please enter a positive value between 1 and 100.', - [ '%val' => $fieldValue] - ) - ); - } - } - - return $fieldValue; + protected function getPercentageFieldName() { + return self::INPUT_PERCENTAGE_NAME; } /** @@ -123,19 +65,16 @@ class RemoveXPercent extends CouponAbstract /** * @inheritdoc */ - public function drawBackOfficeInputs() + public function exec() { - return $this->facade->getParser()->render('coupon/type-fragments/remove-x-percent.html', [ - 'fieldName' => $this->makeCouponFieldName(self::INPUT_PERCENTAGE_NAME), - 'value' => $this->percentage - ]); + return round($this->facade->getCartTotalTaxPrice($this->isAvailableOnSpecialOffers()) * $this->percentage/100, 2); } /** * @inheritdoc */ - protected function getFieldList() + public function drawBackOfficeInputs() { - return [self::INPUT_PERCENTAGE_NAME]; + return $this->callDrawBackOfficeInputs('coupon/type-fragments/remove-x-percent.html'); } } diff --git a/templates/backOffice/default/coupon/type-fragments/base-remove-on-attributes.html b/templates/backOffice/default/coupon/type-fragments/base-remove-on-attributes.html index 073cdedbf..c809002b8 100644 --- a/templates/backOffice/default/coupon/type-fragments/base-remove-on-attributes.html +++ b/templates/backOffice/default/coupon/type-fragments/base-remove-on-attributes.html @@ -2,7 +2,7 @@
- + + {loop type="currency" name="get-symbol" default_only="true"}
{$SYMBOL}
diff --git a/templates/backOffice/default/coupon/type-fragments/remove-x-percent.html b/templates/backOffice/default/coupon/type-fragments/remove-x-percent.html index f06b42a6a..25fe083b0 100644 --- a/templates/backOffice/default/coupon/type-fragments/remove-x-percent.html +++ b/templates/backOffice/default/coupon/type-fragments/remove-x-percent.html @@ -3,7 +3,7 @@
- +
%
From ec26ebac32833c2affed0234d386347df70586bc Mon Sep 17 00:00:00 2001 From: Franck Allimant Date: Thu, 12 Jun 2014 17:10:38 +0200 Subject: [PATCH 08/22] php-cs fixer passed. --- core/lib/Thelia/Action/Coupon.php | 4 ++-- core/lib/Thelia/Core/Event/TheliaEvents.php | 1 - core/lib/Thelia/Coupon/CouponManager.php | 3 +-- core/lib/Thelia/Coupon/Type/AbstractRemove.php | 11 +++++------ .../Coupon/Type/AbstractRemoveOnAttributeValues.php | 10 +++++----- .../Coupon/Type/AbstractRemoveOnCategories.php | 11 +++++------ .../Thelia/Coupon/Type/AbstractRemoveOnProducts.php | 8 ++++---- .../Type/AmountAndPercentageCouponInterface.php | 13 ++++--------- core/lib/Thelia/Coupon/Type/AmountCouponTrait.php | 10 ++++++---- core/lib/Thelia/Coupon/Type/CouponAbstract.php | 2 +- .../Thelia/Coupon/Type/PercentageCouponTrait.php | 10 ++++++---- .../Coupon/Type/RemoveAmountOnAttributeValues.php | 5 ++--- .../Thelia/Coupon/Type/RemoveAmountOnCategories.php | 8 ++------ .../Thelia/Coupon/Type/RemoveAmountOnProducts.php | 8 +++----- .../Type/RemovePercentageOnAttributeValues.php | 5 ++--- .../Coupon/Type/RemovePercentageOnCategories.php | 8 ++------ .../Coupon/Type/RemovePercentageOnProducts.php | 8 +++----- core/lib/Thelia/Coupon/Type/RemoveXAmount.php | 7 +++---- core/lib/Thelia/Coupon/Type/RemoveXPercent.php | 6 ++---- core/lib/Thelia/Model/Coupon.php | 3 ++- 20 files changed, 60 insertions(+), 81 deletions(-) diff --git a/core/lib/Thelia/Action/Coupon.php b/core/lib/Thelia/Action/Coupon.php index 9de27bf58..2c8fa9b01 100644 --- a/core/lib/Thelia/Action/Coupon.php +++ b/core/lib/Thelia/Action/Coupon.php @@ -112,8 +112,8 @@ class Coupon extends BaseAction implements EventSubscriberInterface /** * Clear all coupons in session. */ - public function clearAllCoupons() { - + public function clearAllCoupons() + { $this->request->getSession()->setConsumedCoupons(array()); } diff --git a/core/lib/Thelia/Core/Event/TheliaEvents.php b/core/lib/Thelia/Core/Event/TheliaEvents.php index 9d67366cc..571604b69 100644 --- a/core/lib/Thelia/Core/Event/TheliaEvents.php +++ b/core/lib/Thelia/Core/Event/TheliaEvents.php @@ -469,7 +469,6 @@ final class TheliaEvents */ const COUPON_CLEAR_ALL = "action.clear_all_coupon"; - /** * Sent just before an attempt to use a Coupon */ diff --git a/core/lib/Thelia/Coupon/CouponManager.php b/core/lib/Thelia/Coupon/CouponManager.php index b4280f4a3..b84fb97c8 100644 --- a/core/lib/Thelia/Coupon/CouponManager.php +++ b/core/lib/Thelia/Coupon/CouponManager.php @@ -280,8 +280,7 @@ class CouponManager { if ($coupon->isUsageUnlimited()) { $ret = true; - } - else { + } else { $ret = false; try { diff --git a/core/lib/Thelia/Coupon/Type/AbstractRemove.php b/core/lib/Thelia/Coupon/Type/AbstractRemove.php index f96a660e9..4cf89c3d6 100644 --- a/core/lib/Thelia/Coupon/Type/AbstractRemove.php +++ b/core/lib/Thelia/Coupon/Type/AbstractRemove.php @@ -12,7 +12,6 @@ namespace Thelia\Coupon\Type; -use Thelia\Core\Translation\Translator; use Thelia\Coupon\FacadeInterface; use Thelia\Model\CartItem; @@ -29,15 +28,15 @@ abstract class AbstractRemove extends CouponAbstract implements AmountAndPercent * * @param Array $effects the Coupon effects params */ - public abstract function setFieldsValue($effects); + abstract public function setFieldsValue($effects); /** * Get the discount for a specific cart item. * - * @param CartItem $cartItem the cart item - * @return float the discount value + * @param CartItem $cartItem the cart item + * @return float the discount value */ - public abstract function getCartItemDiscount($cartItem); + abstract public function getCartItemDiscount($cartItem); /** * @inheritdoc @@ -126,4 +125,4 @@ abstract class AbstractRemove extends CouponAbstract implements AmountAndPercent { return $fieldValue; } -} \ No newline at end of file +} diff --git a/core/lib/Thelia/Coupon/Type/AbstractRemoveOnAttributeValues.php b/core/lib/Thelia/Coupon/Type/AbstractRemoveOnAttributeValues.php index c0c6f3844..3b54ce0e7 100644 --- a/core/lib/Thelia/Coupon/Type/AbstractRemoveOnAttributeValues.php +++ b/core/lib/Thelia/Coupon/Type/AbstractRemoveOnAttributeValues.php @@ -35,15 +35,15 @@ abstract class AbstractRemoveOnAttributeValues extends CouponAbstract implements * Set the value of specific coupon fields. * @param Array $effects the Coupon effects params */ - public abstract function setFieldsValue($effects); + abstract public function setFieldsValue($effects); /** * Get the discount for a specific cart item. * - * @param CartItem $cartItem the cart item - * @return float the discount value + * @param CartItem $cartItem the cart item + * @return float the discount value */ - public abstract function getCartItemDiscount($cartItem); + abstract public function getCartItemDiscount($cartItem); /** * @inheritdoc @@ -126,7 +126,7 @@ abstract class AbstractRemoveOnAttributeValues extends CouponAbstract implements * using the provided template file, and a list of specific input fields. * * @param string $templateName the path to the template - * @param array $otherFields the list of additional fields fields + * @param array $otherFields the list of additional fields fields * * @return string the rendered template. */ diff --git a/core/lib/Thelia/Coupon/Type/AbstractRemoveOnCategories.php b/core/lib/Thelia/Coupon/Type/AbstractRemoveOnCategories.php index 174c6f7c3..6b14b43c3 100644 --- a/core/lib/Thelia/Coupon/Type/AbstractRemoveOnCategories.php +++ b/core/lib/Thelia/Coupon/Type/AbstractRemoveOnCategories.php @@ -33,15 +33,15 @@ abstract class AbstractRemoveOnCategories extends CouponAbstract implements Amou * * @param Array $effects the Coupon effects params */ - public abstract function setFieldsValue($effects); + abstract public function setFieldsValue($effects); /** * Get the discount for a specific cart item. * - * @param CartItem $cartItem the cart item - * @return float the discount value + * @param CartItem $cartItem the cart item + * @return float the discount value */ - public abstract function getCartItemDiscount($cartItem); + abstract public function getCartItemDiscount($cartItem); /** * @inheritdoc @@ -75,7 +75,6 @@ abstract class AbstractRemoveOnCategories extends CouponAbstract implements Amou $this->category_list = isset($effects[self::CATEGORIES_LIST]) ? $effects[self::CATEGORIES_LIST] : array(); if (! is_array($this->category_list)) $this->category_list = array($this->category_list); - return $this; } /** @@ -147,4 +146,4 @@ abstract class AbstractRemoveOnCategories extends CouponAbstract implements Amou return $fieldValue; } -} \ No newline at end of file +} diff --git a/core/lib/Thelia/Coupon/Type/AbstractRemoveOnProducts.php b/core/lib/Thelia/Coupon/Type/AbstractRemoveOnProducts.php index c06df1f29..aa407041a 100644 --- a/core/lib/Thelia/Coupon/Type/AbstractRemoveOnProducts.php +++ b/core/lib/Thelia/Coupon/Type/AbstractRemoveOnProducts.php @@ -35,15 +35,15 @@ abstract class AbstractRemoveOnProducts extends CouponAbstract implements Amount * * @param Array $effects the Coupon effects params */ - public abstract function setFieldsValue($effects); + abstract public function setFieldsValue($effects); /** * Get the discount for a specific cart item. * - * @param CartItem $cartItem the cart item - * @return float the discount value + * @param CartItem $cartItem the cart item + * @return float the discount value */ - public abstract function getCartItemDiscount($cartItem); + abstract public function getCartItemDiscount($cartItem); /** * @inheritdoc diff --git a/core/lib/Thelia/Coupon/Type/AmountAndPercentageCouponInterface.php b/core/lib/Thelia/Coupon/Type/AmountAndPercentageCouponInterface.php index 7bc28857f..8fa76e5bb 100644 --- a/core/lib/Thelia/Coupon/Type/AmountAndPercentageCouponInterface.php +++ b/core/lib/Thelia/Coupon/Type/AmountAndPercentageCouponInterface.php @@ -12,10 +12,6 @@ namespace Thelia\Coupon\Type; -use Propel\Runtime\Collection\ObjectCollection; -use Thelia\Condition\ConditionCollection; -use Thelia\Coupon\FacadeInterface; - /** * Represents a Coupon ready to be processed in a Checkout process * @@ -35,18 +31,17 @@ interface AmountAndPercentageCouponInterface /** * Get the discount for a specific cart item. * - * @param CartItem $cartItem the cart item - * @return float the discount value + * @param CartItem $cartItem the cart item + * @return float the discount value */ public function getCartItemDiscount($cartItem); - /** * Renders the template which implements coupon specific user-input, * using the provided template file, and a list of specific input fields. * * @param string $templateName the path to the template - * @param array $otherFields the list of additional fields fields + * @param array $otherFields the list of additional fields fields * * @return string the rendered template. */ @@ -61,4 +56,4 @@ interface AmountAndPercentageCouponInterface * */ public function checkBaseCouponFieldValue($fieldName, $fieldValue); -} \ No newline at end of file +} diff --git a/core/lib/Thelia/Coupon/Type/AmountCouponTrait.php b/core/lib/Thelia/Coupon/Type/AmountCouponTrait.php index e743f7b4d..86c3f65b1 100644 --- a/core/lib/Thelia/Coupon/Type/AmountCouponTrait.php +++ b/core/lib/Thelia/Coupon/Type/AmountCouponTrait.php @@ -32,19 +32,21 @@ Trait AmountCouponTrait { * * @return string the percentage field name */ - protected abstract function getAmountFieldName(); + abstract protected function getAmountFieldName(); /** * @inheritdoc */ - protected function setFieldsValue($effects) { + protected function setFieldsValue($effects) + { $this->amount = $effects[$this->getAmountFieldName()]; } /** * @inheritdoc */ - public function getCartItemDiscount($cartItem) { + public function getCartItemDiscount($cartItem) + { return $cartItem->getQuantity() * $this->amount; } @@ -88,4 +90,4 @@ Trait AmountCouponTrait { return $fieldValue; } -} \ No newline at end of file +} diff --git a/core/lib/Thelia/Coupon/Type/CouponAbstract.php b/core/lib/Thelia/Coupon/Type/CouponAbstract.php index 71b986fcb..6d57b0d38 100644 --- a/core/lib/Thelia/Coupon/Type/CouponAbstract.php +++ b/core/lib/Thelia/Coupon/Type/CouponAbstract.php @@ -499,4 +499,4 @@ abstract class CouponAbstract implements CouponInterface return $effects; } -} \ No newline at end of file +} diff --git a/core/lib/Thelia/Coupon/Type/PercentageCouponTrait.php b/core/lib/Thelia/Coupon/Type/PercentageCouponTrait.php index 0b05d126b..caa446cd7 100644 --- a/core/lib/Thelia/Coupon/Type/PercentageCouponTrait.php +++ b/core/lib/Thelia/Coupon/Type/PercentageCouponTrait.php @@ -29,19 +29,21 @@ Trait PercentageCouponTrait { * * @return string the percentage field name */ - protected abstract function getPercentageFieldName(); + abstract protected function getPercentageFieldName(); /** * @inheritdoc */ - protected function setFieldsValue($effects) { + protected function setFieldsValue($effects) + { $this->percentage = $effects[$this->getPercentageFieldName()]; } /** * @inheritdoc */ - public function getCartItemDiscount($cartItem) { + public function getCartItemDiscount($cartItem) + { return $cartItem->getQuantity() * $cartItem->getPrice() * ($this->percentage / 100); } @@ -87,4 +89,4 @@ Trait PercentageCouponTrait { return $fieldValue; } -} \ No newline at end of file +} diff --git a/core/lib/Thelia/Coupon/Type/RemoveAmountOnAttributeValues.php b/core/lib/Thelia/Coupon/Type/RemoveAmountOnAttributeValues.php index 495c908dc..625de5302 100644 --- a/core/lib/Thelia/Coupon/Type/RemoveAmountOnAttributeValues.php +++ b/core/lib/Thelia/Coupon/Type/RemoveAmountOnAttributeValues.php @@ -12,8 +12,6 @@ namespace Thelia\Coupon\Type; -use Thelia\Core\Translation\Translator; - /** * Allow to remove an amount from the checkout total * @@ -27,7 +25,8 @@ class RemoveAmountOnAttributeValues extends AbstractRemoveOnAttributeValues /** @var string Service Id */ protected $serviceId = 'thelia.coupon.type.remove_amount_on_attribute_av'; - protected function getAmountFieldName() { + protected function getAmountFieldName() + { return self::AMOUNT_FIELD_NAME; } /** diff --git a/core/lib/Thelia/Coupon/Type/RemoveAmountOnCategories.php b/core/lib/Thelia/Coupon/Type/RemoveAmountOnCategories.php index 8843a07d8..54a0bcc17 100644 --- a/core/lib/Thelia/Coupon/Type/RemoveAmountOnCategories.php +++ b/core/lib/Thelia/Coupon/Type/RemoveAmountOnCategories.php @@ -12,11 +12,6 @@ namespace Thelia\Coupon\Type; -use Thelia\Core\Translation\Translator; -use Thelia\Coupon\FacadeInterface; -use Thelia\Model\CartItem; -use Thelia\Model\Category; - /** * Allow to remove an amount from the checkout total * @@ -30,7 +25,8 @@ class RemoveAmountOnCategories extends AbstractRemoveOnCategories /** @var string Service Id */ protected $serviceId = 'thelia.coupon.type.remove_amount_on_categories'; - protected function getAmountFieldName() { + protected function getAmountFieldName() + { return self::AMOUNT_FIELD_NAME; } diff --git a/core/lib/Thelia/Coupon/Type/RemoveAmountOnProducts.php b/core/lib/Thelia/Coupon/Type/RemoveAmountOnProducts.php index 4d6d05906..867f959aa 100644 --- a/core/lib/Thelia/Coupon/Type/RemoveAmountOnProducts.php +++ b/core/lib/Thelia/Coupon/Type/RemoveAmountOnProducts.php @@ -12,9 +12,6 @@ namespace Thelia\Coupon\Type; -use Thelia\Core\Translation\Translator; -use Thelia\Coupon\FacadeInterface; -use Thelia\Model\CartItem; use Thelia\Model\Product; /** @@ -30,7 +27,8 @@ class RemoveAmountOnProducts extends AbstractRemoveOnProducts /** @var string Service Id */ protected $serviceId = 'thelia.coupon.type.remove_amount_on_products'; - protected function getAmountFieldName() { + protected function getAmountFieldName() + { return self::AMOUNT_FIELD_NAME; } @@ -69,4 +67,4 @@ class RemoveAmountOnProducts extends AbstractRemoveOnProducts { return $this->callDrawBackOfficeInputs('coupon/type-fragments/remove-amount-on-products.html'); } -} \ No newline at end of file +} diff --git a/core/lib/Thelia/Coupon/Type/RemovePercentageOnAttributeValues.php b/core/lib/Thelia/Coupon/Type/RemovePercentageOnAttributeValues.php index 509472e9d..6d2dafebf 100644 --- a/core/lib/Thelia/Coupon/Type/RemovePercentageOnAttributeValues.php +++ b/core/lib/Thelia/Coupon/Type/RemovePercentageOnAttributeValues.php @@ -12,8 +12,6 @@ namespace Thelia\Coupon\Type; -use Thelia\Core\Translation\Translator; - /** * Allow to remove an amount from the checkout total * @@ -32,7 +30,8 @@ class RemovePercentageOnAttributeValues extends AbstractRemoveOnAttributeValues /** * @inheritdoc */ - protected function getPercentageFieldName() { + protected function getPercentageFieldName() + { return self::PERCENTAGE; } diff --git a/core/lib/Thelia/Coupon/Type/RemovePercentageOnCategories.php b/core/lib/Thelia/Coupon/Type/RemovePercentageOnCategories.php index 0106a1ead..e2db763d4 100644 --- a/core/lib/Thelia/Coupon/Type/RemovePercentageOnCategories.php +++ b/core/lib/Thelia/Coupon/Type/RemovePercentageOnCategories.php @@ -12,11 +12,6 @@ namespace Thelia\Coupon\Type; -use Thelia\Core\Translation\Translator; -use Thelia\Coupon\FacadeInterface; -use Thelia\Model\CartItem; -use Thelia\Model\Category; - /** * @author Franck Allimant */ @@ -32,7 +27,8 @@ class RemovePercentageOnCategories extends AbstractRemoveOnCategories /** * @inheritdoc */ - protected function getPercentageFieldName() { + protected function getPercentageFieldName() + { return self::PERCENTAGE; } diff --git a/core/lib/Thelia/Coupon/Type/RemovePercentageOnProducts.php b/core/lib/Thelia/Coupon/Type/RemovePercentageOnProducts.php index df48abf31..cab227442 100644 --- a/core/lib/Thelia/Coupon/Type/RemovePercentageOnProducts.php +++ b/core/lib/Thelia/Coupon/Type/RemovePercentageOnProducts.php @@ -12,9 +12,6 @@ namespace Thelia\Coupon\Type; -use Thelia\Core\Translation\Translator; -use Thelia\Coupon\FacadeInterface; -use Thelia\Model\CartItem; use Thelia\Model\Product; /** @@ -35,7 +32,8 @@ class RemovePercentageOnProducts extends AbstractRemoveOnProducts /** * @inheritdoc */ - protected function getPercentageFieldName() { + protected function getPercentageFieldName() + { return self::PERCENTAGE; } @@ -74,4 +72,4 @@ class RemovePercentageOnProducts extends AbstractRemoveOnProducts { return $this->callDrawBackOfficeInputs('coupon/type-fragments/remove-percentage-on-products.html'); } -} \ No newline at end of file +} diff --git a/core/lib/Thelia/Coupon/Type/RemoveXAmount.php b/core/lib/Thelia/Coupon/Type/RemoveXAmount.php index 64fcfe033..c1ffb0675 100644 --- a/core/lib/Thelia/Coupon/Type/RemoveXAmount.php +++ b/core/lib/Thelia/Coupon/Type/RemoveXAmount.php @@ -12,8 +12,6 @@ namespace Thelia\Coupon\Type; -use Thelia\Core\Translation\Translator; - /** * Allow to remove an amount from the checkout total * @@ -28,7 +26,8 @@ class RemoveXAmount extends AbstractRemove /** @var string Service Id */ protected $serviceId = 'thelia.coupon.type.remove_x_amount'; - protected function getAmountFieldName() { + protected function getAmountFieldName() + { return self::AMOUNT_FIELD_NAME; } @@ -73,4 +72,4 @@ class RemoveXAmount extends AbstractRemove { return $this->callDrawBackOfficeInputs('coupon/type-fragments/remove-x-amount.html'); } -} \ No newline at end of file +} diff --git a/core/lib/Thelia/Coupon/Type/RemoveXPercent.php b/core/lib/Thelia/Coupon/Type/RemoveXPercent.php index 2799cf948..623cb7078 100644 --- a/core/lib/Thelia/Coupon/Type/RemoveXPercent.php +++ b/core/lib/Thelia/Coupon/Type/RemoveXPercent.php @@ -12,9 +12,6 @@ namespace Thelia\Coupon\Type; -use Thelia\Core\Translation\Translator; -use Thelia\Coupon\FacadeInterface; - /** * @package Coupon * @author Guillaume MOREL , Franck Allimant @@ -32,7 +29,8 @@ class RemoveXPercent extends AbstractRemove /** * @inheritdoc */ - protected function getPercentageFieldName() { + protected function getPercentageFieldName() + { return self::INPUT_PERCENTAGE_NAME; } diff --git a/core/lib/Thelia/Model/Coupon.php b/core/lib/Thelia/Model/Coupon.php index 616a7d040..c8b15d43d 100644 --- a/core/lib/Thelia/Model/Coupon.php +++ b/core/lib/Thelia/Model/Coupon.php @@ -268,7 +268,8 @@ class Coupon extends BaseCoupon return CouponModuleQuery::create()->filterByCouponId($this->getId())->find(); } - public function isUsageUnlimited() { + public function isUsageUnlimited() + { return $this->getMaxUsage() == self::UNLIMITED_COUPON_USE; } /** From ae6eaefd25559cab76a530ec4143893b07d21897 Mon Sep 17 00:00:00 2001 From: Franck Allimant Date: Sat, 14 Jun 2014 16:10:52 +0200 Subject: [PATCH 09/22] Fixed @param and @return annotations --- core/lib/Thelia/Core/Event/Cart/CartEvent.php | 31 ++++++++++++------- 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/core/lib/Thelia/Core/Event/Cart/CartEvent.php b/core/lib/Thelia/Core/Event/Cart/CartEvent.php index 1c719c0ae..1595f09ce 100644 --- a/core/lib/Thelia/Core/Event/Cart/CartEvent.php +++ b/core/lib/Thelia/Core/Event/Cart/CartEvent.php @@ -14,6 +14,7 @@ namespace Thelia\Core\Event\Cart; use Thelia\Core\Event\ActionEvent; use Thelia\Model\Cart; +use Thelia\Model\CartItem; class CartEvent extends ActionEvent { @@ -31,7 +32,8 @@ class CartEvent extends ActionEvent } /** - * @param mixed $append + * @param bool $append + * @return CartEvent */ public function setAppend($append) { @@ -41,7 +43,7 @@ class CartEvent extends ActionEvent } /** - * @return mixed + * @return bool */ public function getAppend() { @@ -49,7 +51,8 @@ class CartEvent extends ActionEvent } /** - * @param mixed $cartItem + * @param CartItem $cartItem + * @return CartEvent */ public function setCartItem($cartItem) { @@ -59,7 +62,7 @@ class CartEvent extends ActionEvent } /** - * @return mixed + * @return CartItem */ public function getCartItem() { @@ -67,7 +70,8 @@ class CartEvent extends ActionEvent } /** - * @param mixed $newness + * @param bool $newness + * @return CartEvent */ public function setNewness($newness) { @@ -77,7 +81,7 @@ class CartEvent extends ActionEvent } /** - * @return mixed + * @return bool */ public function getNewness() { @@ -85,7 +89,8 @@ class CartEvent extends ActionEvent } /** - * @param mixed $product + * @param int $product the product ID + * @return CartEvent */ public function setProduct($product) { @@ -95,7 +100,7 @@ class CartEvent extends ActionEvent } /** - * @return mixed + * @return int the product ID */ public function getProduct() { @@ -103,7 +108,8 @@ class CartEvent extends ActionEvent } /** - * @param mixed $productSaleElementsId + * @param int $productSaleElementsId + * @return CartEvent */ public function setProductSaleElementsId($productSaleElementsId) { @@ -113,7 +119,7 @@ class CartEvent extends ActionEvent } /** - * @return mixed + * @return int */ public function getProductSaleElementsId() { @@ -121,7 +127,8 @@ class CartEvent extends ActionEvent } /** - * @param mixed $quantity + * @param int $quantity + * @return CartEvent */ public function setQuantity($quantity) { @@ -131,7 +138,7 @@ class CartEvent extends ActionEvent } /** - * @return mixed + * @return int */ public function getQuantity() { From ee47488cc8640aec22b0c2d1c106b5eddd6bbb46 Mon Sep 17 00:00:00 2001 From: Franck Allimant Date: Sat, 14 Jun 2014 17:45:05 +0200 Subject: [PATCH 10/22] getDefaultSaleElements() returns a single ProductSaleElement --- core/lib/Thelia/Model/Product.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/lib/Thelia/Model/Product.php b/core/lib/Thelia/Model/Product.php index 4028ef680..1d73c939d 100644 --- a/core/lib/Thelia/Model/Product.php +++ b/core/lib/Thelia/Model/Product.php @@ -61,7 +61,7 @@ class Product extends BaseProduct */ public function getDefaultSaleElements() { - return ProductSaleElementsQuery::create()->filterByProductId($this->id)->filterByIsDefault(true)->find(); + return ProductSaleElementsQuery::create()->filterByProductId($this->id)->filterByIsDefault(true)->findOne(); } /** From 2edfb0b3895987ca89f01c8566a76314cf576b23 Mon Sep 17 00:00:00 2001 From: Franck Allimant Date: Tue, 17 Jun 2014 00:34:57 +0200 Subject: [PATCH 11/22] Added clear method. --- core/lib/Thelia/Coupon/Type/CouponAbstract.php | 7 +++++++ core/lib/Thelia/Coupon/Type/CouponInterface.php | 5 +++++ 2 files changed, 12 insertions(+) diff --git a/core/lib/Thelia/Coupon/Type/CouponAbstract.php b/core/lib/Thelia/Coupon/Type/CouponAbstract.php index 6d57b0d38..5a434a8cf 100644 --- a/core/lib/Thelia/Coupon/Type/CouponAbstract.php +++ b/core/lib/Thelia/Coupon/Type/CouponAbstract.php @@ -499,4 +499,11 @@ abstract class CouponAbstract implements CouponInterface return $effects; } + + /** + * @inheritdoc + */ + public function clear() { + // Does nothing. Override this function as needed. + } } diff --git a/core/lib/Thelia/Coupon/Type/CouponInterface.php b/core/lib/Thelia/Coupon/Type/CouponInterface.php index a9382749f..d8190f3d7 100644 --- a/core/lib/Thelia/Coupon/Type/CouponInterface.php +++ b/core/lib/Thelia/Coupon/Type/CouponInterface.php @@ -239,4 +239,9 @@ interface CouponInterface */ public function getEffects($data); + /** + * Clear all the data the coupon may have stored, called after an order is completed. + */ + public function clear(); + } From 6b6687c85cfc301315fd56d48cee4303fc64d6e6 Mon Sep 17 00:00:00 2001 From: Franck Allimant Date: Tue, 17 Jun 2014 00:35:12 +0200 Subject: [PATCH 12/22] Added clear() method --- core/lib/Thelia/Coupon/CouponManager.php | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/core/lib/Thelia/Coupon/CouponManager.php b/core/lib/Thelia/Coupon/CouponManager.php index b84fb97c8..309861171 100644 --- a/core/lib/Thelia/Coupon/CouponManager.php +++ b/core/lib/Thelia/Coupon/CouponManager.php @@ -58,14 +58,15 @@ class CouponManager /** * Get Discount for the given Coupons - * * @api * @return float checkout discount */ public function getDiscount() { $discount = 0.00; + $coupons = $this->facade->getCurrentCoupons(); + if (count($coupons) > 0) { $couponsKept = $this->sortCoupons($coupons); @@ -73,6 +74,7 @@ class CouponManager // Just In Case test $checkoutTotalPrice = $this->facade->getCartTotalTaxPrice(); + if ($discount >= $checkoutTotalPrice) { $discount = $checkoutTotalPrice; } @@ -83,6 +85,9 @@ class CouponManager /** * Check if there is a Coupon removing Postage + * + * @param Order $order the order for which we have to check if postage is free + * * @return bool */ public function isCouponRemovingPostage(Order $order) @@ -266,6 +271,19 @@ class CouponManager return $this->availableConditions; } + /** + * Clear all data kept by coupons + */ + public function clear() { + + $coupons = $this->facade->getCurrentCoupons(); + + /** @var CouponInterface $coupon */ + foreach ($coupons as $coupon) { + $coupon->clear(); + } + } + /** * Decrement this coupon quantity * From 17ad1ed6fa5af3923fe1a15abd825963fd4df344 Mon Sep 17 00:00:00 2001 From: Franck Allimant Date: Tue, 17 Jun 2014 00:35:52 +0200 Subject: [PATCH 13/22] The CouponManager clear() method is now invoked. --- core/lib/Thelia/Action/Coupon.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/core/lib/Thelia/Action/Coupon.php b/core/lib/Thelia/Action/Coupon.php index 2c8fa9b01..4dc708394 100644 --- a/core/lib/Thelia/Action/Coupon.php +++ b/core/lib/Thelia/Action/Coupon.php @@ -114,6 +114,9 @@ class Coupon extends BaseAction implements EventSubscriberInterface */ public function clearAllCoupons() { + // Tell coupons to clear any data they may have stored + $this->couponManager->clear(); + $this->request->getSession()->setConsumedCoupons(array()); } @@ -348,7 +351,7 @@ class Coupon extends BaseAction implements EventSubscriberInterface } } - // Clear all coupouns. + // Clear all coupons. $event->getDispatcher()->dispatch(TheliaEvents::COUPON_CLEAR_ALL); } From f3ccf8ec156238f0a6df665d142802d13b6de2ab Mon Sep 17 00:00:00 2001 From: Franck Allimant Date: Tue, 17 Jun 2014 00:36:23 +0200 Subject: [PATCH 14/22] Updated translation after finishing coupons --- core/lib/Thelia/Config/I18n/en_US.php | 14 +++++++++++++- core/lib/Thelia/Config/I18n/fr_FR.php | 14 +++++++++++++- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/core/lib/Thelia/Config/I18n/en_US.php b/core/lib/Thelia/Config/I18n/en_US.php index 6b7e79092..6b92a7fb6 100644 --- a/core/lib/Thelia/Config/I18n/en_US.php +++ b/core/lib/Thelia/Config/I18n/en_US.php @@ -50,6 +50,7 @@ return array( 'Cart item count is' => 'Cart item count is', 'Cart total amount' => 'Cart total amount', 'Cart total amount is' => 'Cart total amount is', + 'Catalog' => 'Catalog', 'Category title *' => 'Category title *', 'Cellphone' => 'Cellphone', 'Chapo' => 'Chapo', @@ -111,14 +112,18 @@ return array( 'First Name' => 'First Name', 'Firstname' => 'Firstname', 'Fixed Amount Discount' => 'Fixed Amount Discount', + 'Fixed amount discount for selected attribute values' => 'Fixed amount discount for selected attribute values', 'Fixed amount discount for selected categories' => 'Fixed amount discount for selected categories', 'Fixed amount discount for selected products' => 'Fixed amount discount for selected products', + 'Folder' => 'Folder', 'Folder title *' => 'Folder title *', 'For one ore more customers' => 'For one ore more customers', + 'Free product when buying one or more selected products' => 'Free product when buying one or more selected products', 'Full Name' => 'Full Name', 'Greater than' => 'Greater than', 'Greater than or equals' => 'Greater than or equals', 'HTML Message' => 'HTML Message', + 'Home' => 'Home', 'Host' => 'Host', 'I would like to receive the newsletter or the latest news.' => 'I would like to receive the newsletter or the latest news.', 'ISO 4217 code *' => 'ISO 4217 code *', @@ -190,6 +195,7 @@ return array( 'Password *' => 'Password *', 'Password confirmation' => 'Password confirmation', 'Per customer' => 'Per customer', + 'Percentage discount for selected attribute values' => 'Percentage discount for selected attribute values', 'Percentage discount for selected categories' => 'Percentage discount for selected categories', 'Percentage discount for selected products' => 'Percentage discount for selected products', 'Percentage of the product price' => 'Percentage of the product price', @@ -199,8 +205,12 @@ return array( 'Please enter your email address' => 'Please enter your email address', 'Please enter your password' => 'Please enter your password', 'Please select a category' => 'Please select a category', + 'Please select an attribute' => 'Please select an attribute', + 'Please select at least one attribute value' => 'Please select at least one attribute value', 'Please select at least one category' => 'Please select at least one category', 'Please select at least one product' => 'Please select at least one product', + 'Please select the category of the offred product' => 'Please select the category of the offred product', + 'Please select the offered product' => 'Please select the offered product', 'Please specify either \'path\' or \'file\' parameter in {url} function.' => 'Please specify either \'path\' or \'file\' parameter in {url} function.', 'Port' => 'Port', 'Post Scriptum' => 'Post Scriptum', @@ -288,10 +298,13 @@ return array( 'This category is online.' => 'This category is online.', 'This condition is always true' => 'This condition is always true', 'This content is online.' => 'This content is online.', + 'This coupon adds a free product to the cart if one of the selected products is in the cart.' => 'This coupon adds a free product to the cart if one of the selected products is in the cart.', 'This coupon does not exists' => 'This coupon does not exists', 'This coupon subtracts from the order total a percentage of the price of each product which belongs to the selected categories. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'This coupon subtracts from the order total a percentage of the price of each product which belongs to the selected categories. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.', + 'This coupon subtracts from the order total the specified percentage of each product price which uses the selected attribute values. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'This coupon subtracts from the order total the specified percentage of each product price which uses the selected attribute values. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.', 'This coupon subtracts from the order total the specified percentage of each selected product price. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'This coupon subtracts from the order total the specified percentage of each selected product price. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.', 'This coupon subtracts the specified amount from the order total for each product which belongs to the selected categories. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'This coupon subtracts the specified amount from the order total for each product which belongs to the selected categories. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.', + 'This coupon subtracts the specified amount from the order total for each product which uses the selected attribute values. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'This coupon subtracts the specified amount from the order total for each product which uses the selected attribute values. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.', 'This coupon subtracts the specified amount from the order total for each selected product. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'This coupon subtracts the specified amount from the order total for each selected product. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.', 'This coupon will offert a flat percentage off a shopper\'s entire order (not applied to shipping costs or tax rates). If the discount is greater than the total order corst, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'This coupon will offert a flat percentage off a shopper\'s entire order (not applied to shipping costs or tax rates). If the discount is greater than the total order corst, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.', 'This coupon will subtracts a set amount from the total cost of an order. If the discount is greater than the total order corst, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'This coupon will subtracts a set amount from the total cost of an order. If the discount is greater than the total order corst, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.', @@ -324,7 +337,6 @@ return array( 'Valid only from %date% to the coupon expiration date' => 'Valide à partir du %date% jusqu\'à la date d\'expiration', 'Value' => 'Value', 'Value %val for Discount Amount is invalid. Please enter a positive value.' => 'Value %val for Discount Amount is invalid. Please enter a positive value.', - 'Value %val for Disount Amount is invalid. Please enter a positive value.' => 'Value %val for Disount Amount is invalid. Please enter a positive value.', 'Value %val for Percent Discount is invalid. Please enter a positive value between 1 and 100.' => 'Value %val for Percent Discount is invalid. Please enter a positive value between 1 and 100.', 'Value *' => 'Value *', 'Warnings' => 'Warnings', diff --git a/core/lib/Thelia/Config/I18n/fr_FR.php b/core/lib/Thelia/Config/I18n/fr_FR.php index a9f14dbee..9d73c6420 100644 --- a/core/lib/Thelia/Config/I18n/fr_FR.php +++ b/core/lib/Thelia/Config/I18n/fr_FR.php @@ -50,6 +50,7 @@ return array( 'Cart item count is' => 'Le nombre d\'articles dans le panier est', 'Cart total amount' => 'Montant total du panier', 'Cart total amount is' => 'Le total du panier est', + 'Catalog' => 'Catalogue', 'Category title *' => 'Titre de la catégorie *', 'Cellphone' => 'Numéro de portable', 'Chapo' => 'Chapeau', @@ -111,14 +112,18 @@ return array( 'First Name' => 'Prénom', 'Firstname' => 'Prénom', 'Fixed Amount Discount' => 'Remise d\'un montant fixe', + 'Fixed amount discount for selected attribute values' => 'Remise constante pour certaines valeurs de déclinaison', 'Fixed amount discount for selected categories' => 'Remise fixe pour certaines catégories', 'Fixed amount discount for selected products' => 'Remise fixe pour certains produits', + 'Folder' => 'Dossier', 'Folder title *' => 'Titre du dossier *', 'For one ore more customers' => 'Valable pour un ou plusieurs clients', + 'Free product when buying one or more selected products' => 'Un produit offert pour l\'achat d\'un ou plusieurs produits', 'Full Name' => 'Nom complet', 'Greater than' => 'Supérieur à', 'Greater than or equals' => 'Supérieur ou égal à', 'HTML Message' => 'Message au format HTML', + 'Home' => 'Accueil', 'Host' => 'Nom de l\'hôte', 'I would like to receive the newsletter or the latest news.' => 'Je souhaite recevoir la lettre d\'information ou les dernières actualités.', 'ISO 4217 code *' => 'Code ISO 4217 *', @@ -190,6 +195,7 @@ return array( 'Password *' => 'Mot de passe *', 'Password confirmation' => 'Confirmation du mot de passe.', 'Per customer' => 'Par client', + 'Percentage discount for selected attribute values' => 'Remise en pourcentage pour certaines valeurs de déclinaison', 'Percentage discount for selected categories' => 'Remise en pourcentage pour certaines catégories', 'Percentage discount for selected products' => 'Remise en pourcentage pour certains produits', 'Percentage of the product price' => 'Pourcentage du prix du produit', @@ -199,8 +205,12 @@ return array( 'Please enter your email address' => 'Renseignez votre adresse mail', 'Please enter your password' => 'Entrez votre mot de passe.', 'Please select a category' => 'Merci de choisir une catégorie', + 'Please select an attribute' => 'Merci de choisir une déclinaison', + 'Please select at least one attribute value' => 'Merci de choisir au moins une valeur de déclinaison', 'Please select at least one category' => 'Merci de choisir au moins une catégorie.', 'Please select at least one product' => 'Merci de choisir au moins un produit', + 'Please select the category of the offred product' => 'Merci de choisir la catégorie du produit offert', + 'Please select the offered product' => 'Merci de choisir le produit offert', 'Please specify either \'path\' or \'file\' parameter in {url} function.' => 'Veuillez spécifier soit le paramètre \'chemin\' ou \'fichier\' dans la fonction {url}', 'Port' => 'Port', 'Post Scriptum' => 'Post-scriptum', @@ -288,10 +298,13 @@ return array( 'This category is online.' => 'Cette catégorie est en ligne.', 'This condition is always true' => 'Cette condition est troujours vérifiée', 'This content is online.' => 'Ce contenu est en ligne.', + 'This coupon adds a free product to the cart if one of the selected products is in the cart.' => 'Ce coupon ajoute un produit gratuit (sous forme de remise) au panier, si un des produits indiqués est présent dans le panier.', 'This coupon does not exists' => 'Ce code promo n\'existe pas', 'This coupon subtracts from the order total a percentage of the price of each product which belongs to the selected categories. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Ce code promo retire du total de la commande le pourcentage indiqué du prix de chacun des produits appartenant aux catégories sélectionnées. Si la remise est supérieure au total de la commande, seul le port sera dû, à moins que le code promo n\'offre aussi le port.', + 'This coupon subtracts from the order total the specified percentage of each product price which uses the selected attribute values. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Ce code promo retire du total de la commande le pourcentage indiqué du prix de chacun des produits ayant au moins une des valeurs de déclinaisons indiquées. Si la remise est supérieure au total de la commande, seul le port sera dû, à moins que le code promo n\'offre aussi le port.', 'This coupon subtracts from the order total the specified percentage of each selected product price. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Ce code promo retire du total de la commande le pourcentage indiqué du prix de chacun des produits sélectionnés. Si la remise est supérieure au total de la commande, seul le port sera dû, à moins que le code promo n\'offre aussi le port.', 'This coupon subtracts the specified amount from the order total for each product which belongs to the selected categories. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Ce code promo retire le montant indiqué du total de la commande pour chacun des produits appartenant aux catégories sélectionnées. Si la remise est supérieure au total de la commande, seul le port sera dû, à moins que le code promo n\'offre aussi le port.', + 'This coupon subtracts the specified amount from the order total for each product which uses the selected attribute values. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Ce code promo retire le montant indiqué du total de la commande pour chacun des produits ayant au moins une des valeurs de déclinaisons indiquées. Si la remise est supérieure au total de la commande, seul le port sera dû, à moins que le code promo n\'offre aussi le port.', 'This coupon subtracts the specified amount from the order total for each selected product. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Ce code promo retire le montant indiqué du total de la commande pour chacun des produits sélectionnés. Si la remise est supérieure au total de la commande, seul le port sera dû, à moins que le code promo n\'offre aussi le port.', 'This coupon will offert a flat percentage off a shopper\'s entire order (not applied to shipping costs or tax rates). If the discount is greater than the total order corst, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Ce code promo retire le pourcentage indiqué du total de la commande, hors frais de port et taxes. Si la remise est supérieur au total de la commande, seul le port sera facturé, à moins que le code promo n\'offre aussi les frais port.', 'This coupon will subtracts a set amount from the total cost of an order. If the discount is greater than the total order corst, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Ce code promo retire le montant indiqué du total de la commande, hors frais de port et taxes. Si la remise est supérieur au total de la commande, seul le port sera facturé, à moins que le code promo n\'offre aussi les frais port.', @@ -324,7 +337,6 @@ return array( 'Valid only from %date% to the coupon expiration date' => 'Valide à partir de %date% jusqu\'à la date d\'expoiration', 'Value' => 'Valeur', 'Value %val for Discount Amount is invalid. Please enter a positive value.' => 'La valeur %val pour le montant de la remise est invalide. Merci d\'indiquer une valeur positive.', - 'Value %val for Disount Amount is invalid. Please enter a positive value.' => 'La valeur %val pour le montant de la remise est invalide. Merci d\'indiquer une valeur positive.', 'Value %val for Percent Discount is invalid. Please enter a positive value between 1 and 100.' => 'La valeur %val pour le pourcentage de remise est invalide. Merci d\'indiquer un nombre entre 1 et 100', 'Value *' => 'Valeur *', 'Warnings' => 'Avertissements', From e3dc87dd6aab78a9711aa0910ed41b9515a62da8 Mon Sep 17 00:00:00 2001 From: Franck Allimant Date: Tue, 17 Jun 2014 00:37:06 +0200 Subject: [PATCH 15/22] Updated translations after finishing coupons --- templates/backOffice/default/I18n/en_US.php | 10 ++++++++-- templates/backOffice/default/I18n/fr_FR.php | 14 ++++++++++++-- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/templates/backOffice/default/I18n/en_US.php b/templates/backOffice/default/I18n/en_US.php index 025f1fb20..934dad7df 100644 --- a/templates/backOffice/default/I18n/en_US.php +++ b/templates/backOffice/default/I18n/en_US.php @@ -62,6 +62,7 @@ return array( 'Amount, e.g. 12.50' => 'Amount, e.g. 12.50', 'An error occured' => 'An error occured', 'And' => 'And', + 'Applies to attribute values :' => 'Applies to attribute values :', 'Applies to products :' => 'Applies to products :', 'Applies to products in categories :' => 'Applies to products in categories :', 'Apply' => 'Apply', @@ -97,6 +98,7 @@ return array( 'Catalog' => 'Catalog', 'Categories' => 'Categories', 'Categories in %cat' => 'Categories in %cat', + 'Category' => 'Category', 'Category created on %date_create. Last modification: %date_change' => 'Category created on %date_create. Last modification: %date_change', 'Category title' => 'Category title', 'Cellular phone' => 'Cellular phone', @@ -143,6 +145,7 @@ return array( 'Confirm' => 'Confirm', 'Confirm changes' => 'Confirm changes', 'Confirmation' => 'Confirmation', + 'Content' => 'Content', 'Content title' => 'Content title', 'Contents in %fold' => 'Contents in %fold', 'Copy source text in input field' => 'Copy source text in input field', @@ -331,7 +334,6 @@ return array( 'Do you really want to remove this zone ?' => 'Do you really want to remove this zone ?', 'Do you really want to set this coupon available to everyone ?' => 'Do you really want to set this coupon available to everyone ?', 'Do you really want to use this address by default ?' => 'Do you really want to use this address by default ?', - 'Document' => 'Document', 'Document informations' => 'Document information', 'Documents' => 'Documents', 'Don\'t repeat keywords over and over in a row. Rather, put in keyword phrases.' => 'Don\'t repeat keywords over and over in a row. Rather, put in keyword phrases.', @@ -493,6 +495,7 @@ return array( 'Flush the Thelia internal cache' => 'Flush the Thelia internal cache', 'Flush the assets cache directory' => 'Flush the assets cache directory', 'Flush the images and documents cache' => 'Flush the images and documents cache', + 'Folder' => 'Folder', 'Folder created on %date_create. Last modification: %date_change' => 'Folder created on %date_create. Last modification: %date_change', 'Folder title' => 'Folder title', 'Folders' => 'Folders', @@ -529,7 +532,6 @@ return array( 'If a translation is missing or incomplete :' => 'If a translation is missing or incomplete :', 'If yes, redirections through Redirect::exec() will be displayed as links' => 'If yes, redirections through Redirect::exec() will be displayed as links', 'Il seems that this string contains a Smarty variable ($). If \'s the case, it cannot be transleted properly.' => 'Il seems that this string contains a Smarty variable ($). If \'s the case, it cannot be transleted properly.', - 'Image' => 'Image', 'Image information' => 'Image information', 'Images' => 'Images', 'Impossible to change default country. Please contact your administrator or try later' => 'Impossible to change default country. Please contact your administrator or try later', @@ -766,8 +768,11 @@ return array( 'Select an attribute and click (+) to view available values' => 'Select an attribute and click (+) to view available values', 'Select an attribute value...' => 'Select an attribute value...', 'Select an attribute...' => 'Select an attribute...', + 'Select attribute :' => 'Select attribute :', 'Select attribute values to combine. You may enter a default value for some of the fields of the generated combinations.' => 'Select attribute values to combine. You may enter a default value for some of the fields of the generated combinations.', 'Select here the tax applicable to this product' => 'Select here the tax applicable to this product', + 'Select offered product :' => 'Select offered product :', + 'Select offrered product category :' => 'Select offrered product category :', 'Select product category :' => 'Select product category :', 'Send a mail to this customer' => 'Send a mail to this customer', 'Send files' => 'Send files', @@ -939,6 +944,7 @@ return array( 'Update this image' => 'Update this image', 'Usage count' => 'Usages left', 'Usages left' => 'Usages left', + 'Use Ctrl+click to select (or deselect) more that one attribute value' => 'Use Ctrl+click to select (or deselect) more that one attribute value', 'Use Ctrl+click to select (or deselect) more that one category' => 'Use Ctrl+click to select (or deselect) more that one category', 'Use Ctrl+click to select (or deselect) more that one country' => 'Utiliser Ctrl+clic pour sélectionner (ou dé-sélectionner) plusieurs pays.', 'Use Ctrl+click to select (or deselect) more that one product' => 'Use Ctrl+click to select (or deselect) more that one product', diff --git a/templates/backOffice/default/I18n/fr_FR.php b/templates/backOffice/default/I18n/fr_FR.php index 97b8e40ef..c00aea57c 100755 --- a/templates/backOffice/default/I18n/fr_FR.php +++ b/templates/backOffice/default/I18n/fr_FR.php @@ -59,8 +59,12 @@ return array( 'Alpha code 2' => 'Code alpha 2', 'Alpha code 3' => 'Code alpha 3', 'Amount' => 'Montant', + 'Amount, e.g. 12.50' => 'Montant, par ex. 12.50', 'An error occured' => 'Une erreur est survenue', 'And' => 'Et', + 'Applies to attribute values :' => 'Pour les valeurs de déclinaison :', + 'Applies to products :' => 'Pour les produits', + 'Applies to products in categories :' => 'Pour les produits des catégories :', 'Apply' => 'Appliquer', 'Associated countries' => 'Pays dans la zone', 'Associations' => 'Associations', @@ -286,6 +290,7 @@ return array( 'Disabled' => 'Désactivé', 'Discount' => 'Remise', 'Discount amount' => 'Montant de réduction', + 'Discount percentage' => 'Pourcentage de remise', 'Do not use a product template' => 'Ne pas utiliser de gabarit', 'Do you really want to add this attribute to all product templates ?' => 'Voulez-vous vraiment ajouter cette déclinaison de tous les gabarits de produit ?', 'Do you really want to add this feature to all product templates ?' => 'Voulez-vous vraiment ajouter cette caractéristique à tous les gabarits de produit ?', @@ -329,7 +334,6 @@ return array( 'Do you really want to remove this zone ?' => 'Voulez-vous vraiment supprimer cette zone ?', 'Do you really want to set this coupon available to everyone ?' => 'êtes-vous sur de vouloir rendre ce code promo disponible à tout le monde ?', 'Do you really want to use this address by default ?' => 'Voulez-vous vraiment utiliser cette adresse comme adresse par défaut ?', - 'Document' => 'Document', 'Document informations' => 'Informations du document', 'Documents' => 'Documents', 'Don\'t repeat keywords over and over in a row. Rather, put in keyword phrases.' => 'Ne répétez pas sans cesse les même mots-clés dans une ligne. Préférez utiliser des expressions de mots-clés', @@ -528,7 +532,6 @@ return array( 'If a translation is missing or incomplete :' => 'Si une traduction est manquante ou incomplète :', 'If yes, redirections through Redirect::exec() will be displayed as links' => 'Si oui, les redirections générés pas Redirect::exec seront affichés par des liens', 'Il seems that this string contains a Smarty variable ($). If \'s the case, it cannot be transleted properly.' => 'La chaîne semble contient une variable smarty ($). Si c\'est le cas elle ne peut pas être traduite correctement', - 'Image' => 'Image', 'Image information' => 'Information de l\'image', 'Images' => 'Images', 'Impossible to change default country. Please contact your administrator or try later' => 'Impossible de modifier le pays par défaut. Veuillez contacter votre administrateur ou réessayer plus tard', @@ -639,6 +642,7 @@ return array( 'Payment information' => 'Informations de paiement', 'Payment module' => 'Module de paiement', 'Payment modules' => 'Modules de payment', + 'Percent Discount' => 'Pourcentage de remise', 'Period' => 'Période', 'Phone' => 'Téléphone', 'Phone number' => 'Numéro de téléphone', @@ -655,6 +659,7 @@ return array( 'Please select the PDF template to translate' => 'Sélectionnez le template PDF à traduire', 'Please select the module component' => 'Choisissez un composant du module', 'Please select the module to translate' => 'Sélectionnez le module à traduire', + 'Please select...' => 'Merci de choisir...', 'Please wait, loading' => 'Chargement, veuillez patienter', 'Port' => 'Port', 'Port :' => 'Port : ', @@ -763,8 +768,12 @@ return array( 'Select an attribute and click (+) to view available values' => 'Sélectionnez une déclinaison et cliquez sur (+) pour voir les valeurs disponibles', 'Select an attribute value...' => 'Sélectionnez une valeur de déclinaison...', 'Select an attribute...' => 'Sélectionnez une déclinaison...', + 'Select attribute :' => 'Choisissez une déclinaison', 'Select attribute values to combine. You may enter a default value for some of the fields of the generated combinations.' => 'Sélectionnez les valeurs de déclinaison à combiner. Vous pouvez entrer une valeur par défaut pour certains champs des combinaisons générées.', 'Select here the tax applicable to this product' => 'Sélectionnez ici la taxe applicable sur ce produit', + 'Select offered product :' => 'Produit offert :', + 'Select offrered product category :' => 'Catégorie du produit offert :', + 'Select product category :' => 'Catégorie des propduits :', 'Send a mail to this customer' => 'Contacter ce client par mail', 'Send files' => 'Envoyer des fichiers', 'Sequential number of log line' => 'Sequential number of log line', @@ -935,6 +944,7 @@ return array( 'Update this image' => 'Modifier cette image', 'Usage count' => 'Nombre d\'utilisations', 'Usages left' => 'Utulisations restantes', + 'Use Ctrl+click to select (or deselect) more that one attribute value' => 'Ctrl+clic permet de séléctionner (ou dé-selectionner) plusieurs valeurs de déclinaison.', 'Use Ctrl+click to select (or deselect) more that one category' => 'Ctrl+Clic permet de sélectionner ou dé-sélectionner plus d\'une catégorie', 'Use Ctrl+click to select (or deselect) more that one country' => 'Ctrl+Clic permet de sélectionner ou dé-sélectionner plus d\'un pays', 'Use Ctrl+click to select (or deselect) more that one product' => 'Ctrl+Clic permet de sélectionner ou dé-sélectionner plus d\'un produit', From 749487e9678696de104cee22539a7d690e881481 Mon Sep 17 00:00:00 2001 From: Franck Allimant Date: Tue, 17 Jun 2014 00:37:53 +0200 Subject: [PATCH 16/22] Added getDeliveryCountry() method --- core/lib/Thelia/Coupon/BaseFacade.php | 10 ++++++++++ core/lib/Thelia/Coupon/FacadeInterface.php | 6 ++++++ 2 files changed, 16 insertions(+) diff --git a/core/lib/Thelia/Coupon/BaseFacade.php b/core/lib/Thelia/Coupon/BaseFacade.php index 5794df673..6df4675ea 100644 --- a/core/lib/Thelia/Coupon/BaseFacade.php +++ b/core/lib/Thelia/Coupon/BaseFacade.php @@ -21,6 +21,7 @@ use Thelia\Core\HttpFoundation\Request; use Thelia\Core\Template\ParserInterface; use Thelia\Core\Template\TemplateHelper; use Thelia\Model\AddressQuery; +use Thelia\Model\Country; use Thelia\Model\Coupon; use Thelia\Model\CouponQuery; use Thelia\Cart\CartTrait; @@ -149,6 +150,15 @@ class BaseFacade implements FacadeInterface return $total; } + + /** + * @return Country the delivery country + */ + public function getDeliveryCountry() + { + return $this->getContainer()->get('thelia.taxEngine')->getDeliveryCountry(); + } + /** * Return the Checkout currency EUR|USD * diff --git a/core/lib/Thelia/Coupon/FacadeInterface.php b/core/lib/Thelia/Coupon/FacadeInterface.php index 8a4d004a3..2201dfb69 100644 --- a/core/lib/Thelia/Coupon/FacadeInterface.php +++ b/core/lib/Thelia/Coupon/FacadeInterface.php @@ -18,6 +18,7 @@ use Symfony\Component\Translation\TranslatorInterface; use Thelia\Condition\ConditionEvaluator; use Thelia\Core\HttpFoundation\Request; use Thelia\Core\Template\ParserInterface; +use Thelia\Model\Country; use Thelia\Model\Coupon; /** @@ -51,6 +52,11 @@ interface FacadeInterface */ public function getDeliveryAddress(); + /** + * @return Country the delivery country + */ + public function getDeliveryCountry(); + /** * Return an Customer a CouponManager can process * From c87c6e2793b2411ae63179a400cf30ff89433a31 Mon Sep 17 00:00:00 2001 From: Franck Allimant Date: Tue, 17 Jun 2014 00:38:18 +0200 Subject: [PATCH 17/22] Added free product coupon. --- core/lib/Thelia/Config/Resources/coupon.xml | 7 +- core/lib/Thelia/Coupon/Type/FreeProduct.php | 347 ++++++++++++++++++++ 2 files changed, 351 insertions(+), 3 deletions(-) create mode 100644 core/lib/Thelia/Coupon/Type/FreeProduct.php diff --git a/core/lib/Thelia/Config/Resources/coupon.xml b/core/lib/Thelia/Config/Resources/coupon.xml index 530a36d56..06e8f7bb6 100644 --- a/core/lib/Thelia/Config/Resources/coupon.xml +++ b/core/lib/Thelia/Config/Resources/coupon.xml @@ -66,9 +66,10 @@ - - - + + + + diff --git a/core/lib/Thelia/Coupon/Type/FreeProduct.php b/core/lib/Thelia/Coupon/Type/FreeProduct.php new file mode 100644 index 000000000..7b06f5dd9 --- /dev/null +++ b/core/lib/Thelia/Coupon/Type/FreeProduct.php @@ -0,0 +1,347 @@ + + */ +class FreeProduct extends AbstractRemoveOnProducts +{ + const OFFERED_PRODUCT_ID = 'offered_product_id'; + const OFFERED_CATEGORY_ID = 'offered_category_id'; + + /** @var string Service Id */ + protected $serviceId = 'thelia.coupon.type.free_product'; + + protected $offeredProductId; + protected $offeredCategoryId; + + /** + * This constant is user to mark a free product as in the process of being added to the cart, + * but the CartItem ID is not yet been defined. + */ + const ADD_TO_CART_IN_PROCESS = -1; + + /** + * @inheritdoc + */ + public function setFieldsValue($effects) + { + $this->offeredProductId = $effects[self::OFFERED_PRODUCT_ID]; + $this->offeredCategoryId = $effects[self::OFFERED_CATEGORY_ID]; + } + + /** + * @inheritdoc + */ + public function getCartItemDiscount($cartItem) + { + // This method is not used, we use our own implementation of exec(); + return 0; + } + + /** + * @return string The session variable where the cart item IDs for the free products are stored + */ + protected function getSessionVarName() { + return "coupon.free_product.cart_items." . $this->getCode(); + } + /** + * Return the cart item id which contains the free product related to a given product + * + * @param Product $product the product in the cart which triggered the discount + * + * @return bool|int|CartItem the cart item which contains the free product, or false if the product is no longer in the cart, or ADD_TO_CART_IN_PROCESS if the adding process is not finished + */ + protected function getRelatedCartItem($product) { + + $cartItemIdList = $this->facade->getRequest()->getSession()->get( + $this->getSessionVarName(), + array() + ); + + if (isset($cartItemIdList[$product->getId()])) { + + $cartItemId = $cartItemIdList[$product->getId()]; + + if ($cartItemId == self::ADD_TO_CART_IN_PROCESS) { + return self::ADD_TO_CART_IN_PROCESS; + } + else if (null !== $cartItem = CartItemQuery::create()->findPk($cartItemId)) { + return $cartItem; + } + } + else { + // Maybe the product we're offering is already in the cart ? Search it. + $cartItems = $this->facade->getCart()->getCartItems(); + + /** @var CartItem $cartItem */ + foreach ($cartItems as $cartItem) { + if ($cartItem->getProduct()->getId() == $this->offeredProductId) { + + // We found the product. Store its cart item as the free product container. + $this->setRelatedCartItem($product, $cartItem->getId()); + + return $cartItem; + } + } + + } + + return false; + } + + /** + * Set the cart item id which contains the free product related to a given product + * + * @param Product $product the product in the cart which triggered the discount + * @param bool|int $cartItemId the cart item ID which contains the free product, or just true if the free product is not yet added. + */ + protected function setRelatedCartItem($product, $cartItemId) { + + $cartItemIdList = $this->facade->getRequest()->getSession()->get( + $this->getSessionVarName(), + array() + ); + + if (! is_array($cartItemIdList)) $cartItemIdList = array(); + + $cartItemIdList[$product->getId()] = $cartItemId; + + $this->facade->getRequest()->getSession()->set( + $this->getSessionVarName(), + $cartItemIdList + ); + } + + /** + * Get the product id / cart item id list. + * + * @return array an array where the free product ID is the key, and the related cart item id the value. + */ + protected function getFreeProductsCartItemIds() { + return $this->facade->getRequest()->getSession()->get( + $this->getSessionVarName(), + array() + ); + } + + /** + * Clear the session variable. + */ + protected function clearFreeProductsCartItemIds() { + return $this->facade->getRequest()->getSession()->remove($this->getSessionVarName()); + } + + /** + * We overload this method here to remove the free products when the + * coupons conditions are no longer met. + * + * @inheritdoc + */ + public function isMatching() { + $match = parent::isMatching(); + + if (! $match) { + // Cancel coupon effect (but no not remove the product) + $this->clearFreeProductsCartItemIds(); + } + + return $match; + } + + /** + * @inheritdoc + */ + public function exec() + { + $discount = 0; + + $cartItems = $this->facade->getCart()->getCartItems(); + + /** @var Product $eligibleProduct */ + $eligibleProduct = null; + + /** @var CartItem $cartItem */ + foreach ($cartItems as $cartItem) { + if (in_array($cartItem->getProduct()->getId(), $this->product_list)) { + if (! $cartItem->getPromo() || $this->isAvailableOnSpecialOffers()) { + $eligibleProduct = $cartItem; + break; + } + } + } + + if ($eligibleProduct !== null) { + + // Get the cart item for the eligible product + $freeProductCartItem = $this->getRelatedCartItem($eligibleProduct); + + // We add the free product it only if it not yet in the cart. + if ($freeProductCartItem === false) { + + if (null !== $freeProduct = ProductQuery::create()->findPk($this->offeredProductId)) { + + // Store in the session that the free product is added to the cart, + // so that we don't enter the following infinite loop : + // + // 1) exec() adds a product by firing a CART_ADDITEM event, + // 2) the event is processed by Action\Coupon::updateOrderDiscount(), + // 3) Action\Coupon::updateOrderDiscount() calls CouponManager::getDiscount() + // 4) CouponManager::getDiscount() calls exec() -> Infinite loop !! + + // Store a marker first, we do not have the cart item id yet. + $this->setRelatedCartItem($eligibleProduct, self::ADD_TO_CART_IN_PROCESS); + + $cartEvent = new CartEvent($this->facade->getCart()); + + $cartEvent->setNewness(true); + $cartEvent->setAppend(false); + $cartEvent->setQuantity(1); + $cartEvent->setProductSaleElementsId($freeProduct->getDefaultSaleElements()->getId()); + $cartEvent->setProduct($this->offeredProductId); + + $this->facade->getDispatcher()->dispatch(TheliaEvents::CART_ADDITEM, $cartEvent); + + // Store the final cart item ID. + $this->setRelatedCartItem($eligibleProduct, $cartEvent->getCartItem()->getId()); + + $freeProductCartItem = $cartEvent->getCartItem(); + + // Setting product price is dangerous, as the customer could change the ordered quantity of this product. + // We will instead add the product price to the order discount. + // $cartEvent->getCartItem()->setPrice(0)->save(); + } + } + + if ($freeProductCartItem instanceof CartItem) { + + $taxCountry = $this->facade->getDeliveryCountry(); + + // The discount is the product price. + $discount = $freeProductCartItem->getPromo() ? + $freeProductCartItem->getPromoPrice() : $freeProductCartItem->getPrice(); + } + } + // No eligible product was found ! + else { + // Remove all free products for this coupon, but no not remove the product from the cart. + $this->clearFreeProductsCartItemIds(); + } + + return $discount; + } + + /** + * @inheritdoc + */ + protected function getFieldList() + { + return $this->getBaseFieldList([self::OFFERED_CATEGORY_ID, self::OFFERED_PRODUCT_ID]); + } + + /** + * @inheritdoc + */ + protected function checkCouponFieldValue($fieldName, $fieldValue) + { + $this->checkBaseCouponFieldValue($fieldName, $fieldValue); + + if ($fieldName === self::OFFERED_PRODUCT_ID) { + + if (floatval($fieldValue) < 0) { + throw new \InvalidArgumentException( + Translator::getInstance()->trans( + 'Please select the offered product' + ) + ); + } + } + else if ($fieldName === self::OFFERED_CATEGORY_ID) { + if (empty($fieldValue)) { + throw new \InvalidArgumentException( + Translator::getInstance()->trans( + 'Please select the category of the offred product' + ) + ); + } + } + + return $fieldValue; + } + + + /** + * Get I18n name + * + * @return string + */ + public function getName() + { + return $this->facade + ->getTranslator() + ->trans('Free product when buying one or more selected products', array(), 'coupon'); + } + + /** + * @inheritdoc + */ + public function getToolTip() + { + $toolTip = $this->facade + ->getTranslator() + ->trans( + 'This coupon adds a free product to the cart if one of the selected products is in the cart.', + array(), + 'coupon' + ); + + return $toolTip; + } + + /** + * @inheritdoc + */ + public function drawBackOfficeInputs() + { + return $this->drawBaseBackOfficeInputs("coupon/type-fragments/free-product.html", [ + 'offered_category_field_name' => $this->makeCouponFieldName(self::OFFERED_CATEGORY_ID), + 'offered_category_value' => $this->offeredCategoryId, + + 'offered_product_field_name' => $this->makeCouponFieldName(self::OFFERED_PRODUCT_ID), + 'offered_product_value' => $this->offeredProductId + ]); + } + + /** + * @inheritdoc + */ + public function clear() + { + // Clear the session variable when the coupon is cleared. + $this->clearFreeProductsCartItemIds(); + } +} \ No newline at end of file From 63f00d82b9cdbf371f818657fa55572cbc2b3eba Mon Sep 17 00:00:00 2001 From: Franck Allimant Date: Tue, 17 Jun 2014 00:39:00 +0200 Subject: [PATCH 18/22] Using 0 as default value if some loop parameters are not defined --- .../base-remove-on-attributes.html | 6 +- .../base-remove-on-categories.html | 6 ++ .../base-remove-on-products.html | 8 ++- .../coupon/type-fragments/free-product.html | 69 +++++++++++++++++++ 4 files changed, 84 insertions(+), 5 deletions(-) create mode 100644 templates/backOffice/default/coupon/type-fragments/free-product.html diff --git a/templates/backOffice/default/coupon/type-fragments/base-remove-on-attributes.html b/templates/backOffice/default/coupon/type-fragments/base-remove-on-attributes.html index c809002b8..232ab68de 100644 --- a/templates/backOffice/default/coupon/type-fragments/base-remove-on-attributes.html +++ b/templates/backOffice/default/coupon/type-fragments/base-remove-on-attributes.html @@ -19,7 +19,7 @@ @@ -59,5 +59,7 @@ }); } }); - }; + + {block name="javascript-init"}{/block} + } diff --git a/templates/backOffice/default/coupon/type-fragments/base-remove-on-categories.html b/templates/backOffice/default/coupon/type-fragments/base-remove-on-categories.html index 39b81e4c1..1987c6fbf 100644 --- a/templates/backOffice/default/coupon/type-fragments/base-remove-on-categories.html +++ b/templates/backOffice/default/coupon/type-fragments/base-remove-on-categories.html @@ -12,3 +12,9 @@ {intl l='Use Ctrl+click to select (or deselect) more that one category'}
+ + diff --git a/templates/backOffice/default/coupon/type-fragments/base-remove-on-products.html b/templates/backOffice/default/coupon/type-fragments/base-remove-on-products.html index 3f5cc4a94..db799b5d0 100644 --- a/templates/backOffice/default/coupon/type-fragments/base-remove-on-products.html +++ b/templates/backOffice/default/coupon/type-fragments/base-remove-on-products.html @@ -19,8 +19,8 @@ @@ -59,5 +59,7 @@ }); } }); - }; + + {block name="javascript-init"}{/block} + } diff --git a/templates/backOffice/default/coupon/type-fragments/free-product.html b/templates/backOffice/default/coupon/type-fragments/free-product.html new file mode 100644 index 000000000..05e7bfe14 --- /dev/null +++ b/templates/backOffice/default/coupon/type-fragments/free-product.html @@ -0,0 +1,69 @@ +{extends file="coupon/type-fragments/base-remove-on-products.html"} + +{block name="discount-field"} +
+ + + + +
+ + + +
+ + + + +
+{/block} + +{block name="javascript-init"} + + // Hide selected products category selection if the + // offered product is not yet selected. + if ({$offered_category_value|default:0} == 0) { + $('.input-coupon-category-id').hide(); + } + + var $freeCatSelect = $('#free-product-category-id'); + + $freeCatSelect.change(function(ev) { + + var $category_id = $(this).val(); + + $('.input-coupon-category-id').hide(); + $('#input-free-products-id').hide(); + $('#free-products-id').html(''); + + if ($category_id != 0) { + + $('#input-free-products-id-loading').show(); + + $.ajax({ + url: "{url path='/admin/coupon/type-fragments/ajax-products-list'}", + type: 'POST', + data: { + category_id: $category_id + }, + success: function(options) { + $('.input-coupon-category-id').show(); + $('#free-products-id').html(options); + $('#input-free-products-id').show(); + }, + complete: function() { + $('#input-free-products-id-loading').hide(); + } + }); + } + }); +{/block} \ No newline at end of file From 8b74eae911f88c7343c57a168c743ec9374a6580 Mon Sep 17 00:00:00 2001 From: Franck Allimant Date: Tue, 17 Jun 2014 00:43:10 +0200 Subject: [PATCH 19/22] php-cs pass --- core/lib/Thelia/Core/Event/Cart/CartEvent.php | 12 +++--- core/lib/Thelia/Coupon/BaseFacade.php | 1 - core/lib/Thelia/Coupon/CouponManager.php | 4 +- .../lib/Thelia/Coupon/Type/CouponAbstract.php | 3 +- core/lib/Thelia/Coupon/Type/FreeProduct.php | 38 +++++++++---------- 5 files changed, 28 insertions(+), 30 deletions(-) diff --git a/core/lib/Thelia/Core/Event/Cart/CartEvent.php b/core/lib/Thelia/Core/Event/Cart/CartEvent.php index 1595f09ce..d6a100c16 100644 --- a/core/lib/Thelia/Core/Event/Cart/CartEvent.php +++ b/core/lib/Thelia/Core/Event/Cart/CartEvent.php @@ -32,7 +32,7 @@ class CartEvent extends ActionEvent } /** - * @param bool $append + * @param bool $append * @return CartEvent */ public function setAppend($append) @@ -51,7 +51,7 @@ class CartEvent extends ActionEvent } /** - * @param CartItem $cartItem + * @param CartItem $cartItem * @return CartEvent */ public function setCartItem($cartItem) @@ -70,7 +70,7 @@ class CartEvent extends ActionEvent } /** - * @param bool $newness + * @param bool $newness * @return CartEvent */ public function setNewness($newness) @@ -89,7 +89,7 @@ class CartEvent extends ActionEvent } /** - * @param int $product the product ID + * @param int $product the product ID * @return CartEvent */ public function setProduct($product) @@ -108,7 +108,7 @@ class CartEvent extends ActionEvent } /** - * @param int $productSaleElementsId + * @param int $productSaleElementsId * @return CartEvent */ public function setProductSaleElementsId($productSaleElementsId) @@ -127,7 +127,7 @@ class CartEvent extends ActionEvent } /** - * @param int $quantity + * @param int $quantity * @return CartEvent */ public function setQuantity($quantity) diff --git a/core/lib/Thelia/Coupon/BaseFacade.php b/core/lib/Thelia/Coupon/BaseFacade.php index 6df4675ea..25a177996 100644 --- a/core/lib/Thelia/Coupon/BaseFacade.php +++ b/core/lib/Thelia/Coupon/BaseFacade.php @@ -150,7 +150,6 @@ class BaseFacade implements FacadeInterface return $total; } - /** * @return Country the delivery country */ diff --git a/core/lib/Thelia/Coupon/CouponManager.php b/core/lib/Thelia/Coupon/CouponManager.php index 309861171..e92aaaa86 100644 --- a/core/lib/Thelia/Coupon/CouponManager.php +++ b/core/lib/Thelia/Coupon/CouponManager.php @@ -274,8 +274,8 @@ class CouponManager /** * Clear all data kept by coupons */ - public function clear() { - + public function clear() + { $coupons = $this->facade->getCurrentCoupons(); /** @var CouponInterface $coupon */ diff --git a/core/lib/Thelia/Coupon/Type/CouponAbstract.php b/core/lib/Thelia/Coupon/Type/CouponAbstract.php index 5a434a8cf..9766b7fbe 100644 --- a/core/lib/Thelia/Coupon/Type/CouponAbstract.php +++ b/core/lib/Thelia/Coupon/Type/CouponAbstract.php @@ -503,7 +503,8 @@ abstract class CouponAbstract implements CouponInterface /** * @inheritdoc */ - public function clear() { + public function clear() + { // Does nothing. Override this function as needed. } } diff --git a/core/lib/Thelia/Coupon/Type/FreeProduct.php b/core/lib/Thelia/Coupon/Type/FreeProduct.php index 7b06f5dd9..5fe65b1b0 100644 --- a/core/lib/Thelia/Coupon/Type/FreeProduct.php +++ b/core/lib/Thelia/Coupon/Type/FreeProduct.php @@ -15,13 +15,11 @@ namespace Thelia\Coupon\Type; use Thelia\Core\Event\Cart\CartEvent; use Thelia\Core\Event\TheliaEvents; use Thelia\Core\Translation\Translator; -use Thelia\Coupon\FacadeInterface; use Thelia\Model\CartItem; use Thelia\Model\CartItemQuery; use Thelia\Model\Product; use Thelia\Model\ProductQuery; - /** * Allow to remove an amount from the checkout total * @@ -66,7 +64,8 @@ class FreeProduct extends AbstractRemoveOnProducts /** * @return string The session variable where the cart item IDs for the free products are stored */ - protected function getSessionVarName() { + protected function getSessionVarName() + { return "coupon.free_product.cart_items." . $this->getCode(); } /** @@ -76,8 +75,8 @@ class FreeProduct extends AbstractRemoveOnProducts * * @return bool|int|CartItem the cart item which contains the free product, or false if the product is no longer in the cart, or ADD_TO_CART_IN_PROCESS if the adding process is not finished */ - protected function getRelatedCartItem($product) { - + protected function getRelatedCartItem($product) + { $cartItemIdList = $this->facade->getRequest()->getSession()->get( $this->getSessionVarName(), array() @@ -89,12 +88,10 @@ class FreeProduct extends AbstractRemoveOnProducts if ($cartItemId == self::ADD_TO_CART_IN_PROCESS) { return self::ADD_TO_CART_IN_PROCESS; - } - else if (null !== $cartItem = CartItemQuery::create()->findPk($cartItemId)) { + } elseif (null !== $cartItem = CartItemQuery::create()->findPk($cartItemId)) { return $cartItem; } - } - else { + } else { // Maybe the product we're offering is already in the cart ? Search it. $cartItems = $this->facade->getCart()->getCartItems(); @@ -117,11 +114,11 @@ class FreeProduct extends AbstractRemoveOnProducts /** * Set the cart item id which contains the free product related to a given product * - * @param Product $product the product in the cart which triggered the discount - * @param bool|int $cartItemId the cart item ID which contains the free product, or just true if the free product is not yet added. + * @param Product $product the product in the cart which triggered the discount + * @param bool|int $cartItemId the cart item ID which contains the free product, or just true if the free product is not yet added. */ - protected function setRelatedCartItem($product, $cartItemId) { - + protected function setRelatedCartItem($product, $cartItemId) + { $cartItemIdList = $this->facade->getRequest()->getSession()->get( $this->getSessionVarName(), array() @@ -142,7 +139,8 @@ class FreeProduct extends AbstractRemoveOnProducts * * @return array an array where the free product ID is the key, and the related cart item id the value. */ - protected function getFreeProductsCartItemIds() { + protected function getFreeProductsCartItemIds() + { return $this->facade->getRequest()->getSession()->get( $this->getSessionVarName(), array() @@ -152,7 +150,8 @@ class FreeProduct extends AbstractRemoveOnProducts /** * Clear the session variable. */ - protected function clearFreeProductsCartItemIds() { + protected function clearFreeProductsCartItemIds() + { return $this->facade->getRequest()->getSession()->remove($this->getSessionVarName()); } @@ -162,7 +161,8 @@ class FreeProduct extends AbstractRemoveOnProducts * * @inheritdoc */ - public function isMatching() { + public function isMatching() + { $match = parent::isMatching(); if (! $match) { @@ -279,8 +279,7 @@ class FreeProduct extends AbstractRemoveOnProducts ) ); } - } - else if ($fieldName === self::OFFERED_CATEGORY_ID) { + } elseif ($fieldName === self::OFFERED_CATEGORY_ID) { if (empty($fieldValue)) { throw new \InvalidArgumentException( Translator::getInstance()->trans( @@ -293,7 +292,6 @@ class FreeProduct extends AbstractRemoveOnProducts return $fieldValue; } - /** * Get I18n name * @@ -344,4 +342,4 @@ class FreeProduct extends AbstractRemoveOnProducts // Clear the session variable when the coupon is cleared. $this->clearFreeProductsCartItemIds(); } -} \ No newline at end of file +} From 5534780e3cf47b62f7d4c0edc9fac37f261a0d05 Mon Sep 17 00:00:00 2001 From: Franck Allimant Date: Tue, 17 Jun 2014 00:45:55 +0200 Subject: [PATCH 20/22] Added the FreeProduct coupon. --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0e9c46442..a707ba34b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +#2.0.3 +- New coupon type: Free product if selected products are in the cart. + #2.0.2 - Coupon UI has been redesigned. - New coupon types: From 6f128828500ba06e4126a8b54873e8d0d2a78046 Mon Sep 17 00:00:00 2001 From: Franck Allimant Date: Tue, 17 Jun 2014 15:28:35 +0200 Subject: [PATCH 21/22] Added missing $this->setFieldsValue($effects); --- core/lib/Thelia/Coupon/Type/AbstractRemoveOnCategories.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/core/lib/Thelia/Coupon/Type/AbstractRemoveOnCategories.php b/core/lib/Thelia/Coupon/Type/AbstractRemoveOnCategories.php index 6b14b43c3..355cf596a 100644 --- a/core/lib/Thelia/Coupon/Type/AbstractRemoveOnCategories.php +++ b/core/lib/Thelia/Coupon/Type/AbstractRemoveOnCategories.php @@ -75,6 +75,9 @@ abstract class AbstractRemoveOnCategories extends CouponAbstract implements Amou $this->category_list = isset($effects[self::CATEGORIES_LIST]) ? $effects[self::CATEGORIES_LIST] : array(); if (! is_array($this->category_list)) $this->category_list = array($this->category_list); + + $this->setFieldsValue($effects); + return $this; } /** From cbf2eae842bc2f4f79a249496f5d9c8159654e70 Mon Sep 17 00:00:00 2001 From: Franck Allimant Date: Tue, 17 Jun 2014 19:58:56 +0200 Subject: [PATCH 22/22] Written coupons unit tests --- .../Condition/Implementation/StartDate.php | 2 + .../CartContainsCategoriesTest.php | 365 ++++++++++++++++ .../CartContainsProductsTest.php | 365 ++++++++++++++++ .../Implementation/ForSomeCustomersTest.php | 304 +++++++++++++ .../MatchBillingCountriesTest.php | 312 +++++++++++++ .../MatchDeliveryCountriesTest.php | 304 +++++++++++++ .../Implementation/MatchForEveryoneTest.php | 1 - .../MatchForTotalAmountTest.php | 3 +- .../Implementation/StartDateTest.php | 329 ++++++++++++++ .../Tests/Coupon/Type/FreeProductTest.php | 412 ++++++++++++++++++ .../RemoveAmountOnAttributeValuesTest.php | 398 +++++++++++++++++ .../Type/RemoveAmountOnCategoriesTest.php | 330 ++++++++++++++ .../Type/RemoveAmountOnProductsTest.php | 343 +++++++++++++++ .../RemovePercentageOnAttributeValuesTest.php | 412 ++++++++++++++++++ .../Type/RemovePercentageOnCategoriesTest.php | 346 +++++++++++++++ .../Type/RemovePercentageOnProductsTest.php | 360 +++++++++++++++ 16 files changed, 4583 insertions(+), 3 deletions(-) create mode 100644 core/lib/Thelia/Tests/Condition/Implementation/CartContainsCategoriesTest.php create mode 100644 core/lib/Thelia/Tests/Condition/Implementation/CartContainsProductsTest.php create mode 100644 core/lib/Thelia/Tests/Condition/Implementation/ForSomeCustomersTest.php create mode 100644 core/lib/Thelia/Tests/Condition/Implementation/MatchBillingCountriesTest.php create mode 100644 core/lib/Thelia/Tests/Condition/Implementation/MatchDeliveryCountriesTest.php create mode 100644 core/lib/Thelia/Tests/Condition/Implementation/StartDateTest.php create mode 100644 core/lib/Thelia/Tests/Coupon/Type/FreeProductTest.php create mode 100644 core/lib/Thelia/Tests/Coupon/Type/RemoveAmountOnAttributeValuesTest.php create mode 100644 core/lib/Thelia/Tests/Coupon/Type/RemoveAmountOnCategoriesTest.php create mode 100644 core/lib/Thelia/Tests/Coupon/Type/RemoveAmountOnProductsTest.php create mode 100644 core/lib/Thelia/Tests/Coupon/Type/RemovePercentageOnAttributeValuesTest.php create mode 100644 core/lib/Thelia/Tests/Coupon/Type/RemovePercentageOnCategoriesTest.php create mode 100644 core/lib/Thelia/Tests/Coupon/Type/RemovePercentageOnProductsTest.php diff --git a/core/lib/Thelia/Condition/Implementation/StartDate.php b/core/lib/Thelia/Condition/Implementation/StartDate.php index 251ba395b..2524e1b6d 100644 --- a/core/lib/Thelia/Condition/Implementation/StartDate.php +++ b/core/lib/Thelia/Condition/Implementation/StartDate.php @@ -55,6 +55,8 @@ class StartDate extends ConditionAbstract */ public function setValidatorsFromForm(array $operators, array $values) { + $this->checkComparisonOperatorValue($operators, self::START_DATE); + if (! isset($values[self::START_DATE])) { $values[self::START_DATE] = time(); } diff --git a/core/lib/Thelia/Tests/Condition/Implementation/CartContainsCategoriesTest.php b/core/lib/Thelia/Tests/Condition/Implementation/CartContainsCategoriesTest.php new file mode 100644 index 000000000..1a5259b5e --- /dev/null +++ b/core/lib/Thelia/Tests/Condition/Implementation/CartContainsCategoriesTest.php @@ -0,0 +1,365 @@ + + */ +class CartContainsCategoriesTest extends \PHPUnit_Framework_TestCase +{ + + /** + * Sets up the fixture, for example, opens a network connection. + * This method is called before a test is executed. + */ + protected function setUp() + { + + } + + /** + * Generate adapter stub + * + * @param int $cartTotalPrice Cart total price + * @param string $checkoutCurrency Checkout currency + * @param string $i18nOutput Output from each translation + * + * @return \PHPUnit_Framework_MockObject_MockObject + */ + public function generateFacadeStub($cartTotalPrice = 400, $checkoutCurrency = 'EUR', $i18nOutput = '') + { + $stubFacade = $this->getMockBuilder('\Thelia\Coupon\BaseFacade') + ->disableOriginalConstructor() + ->getMock(); + + $stubFacade->expects($this->any()) + ->method('getCartTotalPrice') + ->will($this->returnValue($cartTotalPrice)); + + $stubFacade->expects($this->any()) + ->method('getCheckoutCurrency') + ->will($this->returnValue($checkoutCurrency)); + + $stubFacade->expects($this->any()) + ->method('getConditionEvaluator') + ->will($this->returnValue(new ConditionEvaluator())); + + $stubTranslator = $this->getMockBuilder('\Thelia\Core\Translation\Translator') + ->disableOriginalConstructor() + ->getMock(); + $stubTranslator->expects($this->any()) + ->method('trans') + ->will($this->returnValue($i18nOutput)); + + $stubFacade->expects($this->any()) + ->method('getTranslator') + ->will($this->returnValue($stubTranslator)); + + $category1 = new Category(); + $category1->setId(10); + + $category2 = new Category(); + $category2->setId(20); + + $category3 = new Category(); + $category3->setId(30); + + $product1 = new Product(); + $product1->addCategory($category1)->addCategory($category2); + + $product2 = new Product(); + $product2->addCategory($category3); + + $cartItem1Stub = $this->getMockBuilder('\Thelia\Model\CartItem') + ->disableOriginalConstructor() + ->getMock(); + + $cartItem1Stub + ->expects($this->any()) + ->method('getProduct') + ->will($this->returnValue($product1)) + ; + + $cartItem1Stub + ->expects($this->any()) + ->method('getQuantity') + ->will($this->returnValue(1)) + ; + + $cartItem2Stub = $this->getMockBuilder('\Thelia\Model\CartItem') + ->disableOriginalConstructor() + ->getMock(); + + $cartItem2Stub + ->expects($this->any()) + ->method('getProduct') + ->will($this->returnValue($product2)); + + $cartItem2Stub + ->expects($this->any()) + ->method('getQuantity') + ->will($this->returnValue(2)) + ; + + $cartStub = $this->getMockBuilder('\Thelia\Model\Cart') + ->disableOriginalConstructor() + ->getMock(); + + $cartStub + ->expects($this->any()) + ->method('getCartItems') + ->will($this->returnValue([$cartItem1Stub, $cartItem2Stub])); + + $stubFacade->expects($this->any()) + ->method('getCart') + ->will($this->returnValue($cartStub)); + + return $stubFacade; + } + + /** + * Check if validity test on BackOffice inputs are working + * + * @covers Thelia\Condition\Implementation\CartContainsCategories::setValidators + * @expectedException \Thelia\Exception\InvalidConditionOperatorException + */ + public function testInValidBackOfficeInputOperator() + { + /** @var FacadeInterface $stubFacade */ + $stubFacade = $this->generateFacadeStub(); + + $condition1 = new CartContainsCategories($stubFacade); + $operators = array( + CartContainsCategories::CATEGORIES_LIST => Operators::INFERIOR_OR_EQUAL + ); + $values = array( + CartContainsCategories::CATEGORIES_LIST => array() + ); + $condition1->setValidatorsFromForm($operators, $values); + + $isValid = $condition1->isMatching(); + + $expected = true; + $actual =$isValid; + $this->assertEquals($expected, $actual); + } + + /** + * Check if validity test on BackOffice inputs are working + * + * @covers Thelia\Condition\Implementation\CartContainsCategories::setValidators + * @expectedException \Thelia\Exception\InvalidConditionValueException + */ + public function testInValidBackOfficeInputValue() + { + /** @var FacadeInterface $stubFacade */ + $stubFacade = $this->generateFacadeStub(); + + $condition1 = new CartContainsCategories($stubFacade); + $operators = array( + CartContainsCategories::CATEGORIES_LIST => Operators::IN + ); + $values = array( + CartContainsCategories::CATEGORIES_LIST => array() + ); + + $condition1->setValidatorsFromForm($operators, $values); + } + + /** + * Check if test inferior operator is working + * + * @covers Thelia\Condition\Implementation\CartContainsCategories::isMatching + * + */ + public function testMatchingRule() + { + /** @var FacadeInterface $stubFacade */ + $stubFacade = $this->generateFacadeStub(); + + $condition1 = new CartContainsCategories($stubFacade); + $operators = array( + CartContainsCategories::CATEGORIES_LIST => Operators::IN + ); + $values = array( + CartContainsCategories::CATEGORIES_LIST => array(10, 20) + ); + + $condition1->setValidatorsFromForm($operators, $values); + + $isValid = $condition1->isMatching(); + + $expected = true; + $actual =$isValid; + $this->assertEquals($expected, $actual); + } + + /** + * Check if test inferior operator is working + * + * @covers Thelia\Condition\Implementation\CartContainsCategories::isMatching + * + */ + public function testNotMatching() + { + /** @var FacadeInterface $stubFacade */ + $stubFacade = $this->generateFacadeStub(); + + $condition1 = new CartContainsCategories($stubFacade); + + $operators = array( + CartContainsCategories::CATEGORIES_LIST => Operators::IN + ); + $values = array( + CartContainsCategories::CATEGORIES_LIST => array(50, 60) + ); + + $condition1->setValidatorsFromForm($operators, $values); + + $isValid = $condition1->isMatching(); + + $expected = false; + $actual =$isValid; + $this->assertEquals($expected, $actual); + } + + public function testGetSerializableRule() + { + /** @var FacadeInterface $stubFacade */ + $stubFacade = $this->generateFacadeStub(); + + $condition1 = new CartContainsCategories($stubFacade); + + $operators = array( + CartContainsCategories::CATEGORIES_LIST => Operators::IN + ); + $values = array( + CartContainsCategories::CATEGORIES_LIST => array(50, 60) + ); + + $condition1->setValidatorsFromForm($operators, $values); + + $serializableRule = $condition1->getSerializableCondition(); + + $expected = new SerializableCondition(); + $expected->conditionServiceId = $condition1->getServiceId(); + $expected->operators = $operators; + $expected->values = $values; + + $actual = $serializableRule; + + $this->assertEquals($expected, $actual); + + } + + /** + * Check getName i18n + * + * @covers Thelia\Condition\Implementation\CartContainsCategories::getName + * + */ + public function testGetName() + { + $stubFacade = $this->generateFacadeStub(399, 'EUR', 'Number of articles in cart'); + + /** @var FacadeInterface $stubFacade */ + $condition1 = new CartContainsCategories($stubFacade); + + $actual = $condition1->getName(); + $expected = 'Number of articles in cart'; + $this->assertEquals($expected, $actual); + } + + /** + * Check tooltip i18n + * + * @covers Thelia\Condition\Implementation\CartContainsCategories::getToolTip + * + */ + public function testGetToolTip() + { + $stubFacade = $this->generateFacadeStub(399, 'EUR', 'Sample coupon condition'); + + /** @var FacadeInterface $stubFacade */ + $condition1 = new CartContainsCategories($stubFacade); + + $actual = $condition1->getToolTip(); + $expected = 'Sample coupon condition'; + $this->assertEquals($expected, $actual); + } + + /** + * Check validator + * + * @covers Thelia\Condition\Implementation\CartContainsCategories::generateInputs + * + */ + public function testGetValidator() + { + $stubFacade = $this->generateFacadeStub(399, 'EUR', 'Price'); + + /** @var FacadeInterface $stubFacade */ + $condition1 = new CartContainsCategories($stubFacade); + + $operators = array( + CartContainsCategories::CATEGORIES_LIST => Operators::IN + ); + $values = array( + CartContainsCategories::CATEGORIES_LIST => array(50, 60) + ); + + $condition1->setValidatorsFromForm($operators, $values); + + $actual = $condition1->getValidators(); + + $validators = array( + 'inputs' => array( + CartContainsCategories::CATEGORIES_LIST => array( + 'availableOperators' => array( + 'in' => 'Price', + 'out' => 'Price', + ), + 'value' => '', + 'selectedOperator' => 'in' + ) + ), + 'setOperators' => array( + 'categories' => 'in' + ), + 'setValues' => array( + 'categories' => array(50, 60) + ) + ); + $expected = $validators; + + $this->assertEquals($expected, $actual); + + } + + /** + * Tears down the fixture, for example, closes a network connection. + * This method is called after a test is executed. + */ + protected function tearDown() + { + } + +} diff --git a/core/lib/Thelia/Tests/Condition/Implementation/CartContainsProductsTest.php b/core/lib/Thelia/Tests/Condition/Implementation/CartContainsProductsTest.php new file mode 100644 index 000000000..f24dea73a --- /dev/null +++ b/core/lib/Thelia/Tests/Condition/Implementation/CartContainsProductsTest.php @@ -0,0 +1,365 @@ + + */ +class CartContainsProductsTest extends \PHPUnit_Framework_TestCase +{ + + /** + * Sets up the fixture, for example, opens a network connection. + * This method is called before a test is executed. + */ + protected function setUp() + { + + } + + /** + * Generate adapter stub + * + * @param int $cartTotalPrice Cart total price + * @param string $checkoutCurrency Checkout currency + * @param string $i18nOutput Output from each translation + * + * @return \PHPUnit_Framework_MockObject_MockObject + */ + public function generateFacadeStub($cartTotalPrice = 400, $checkoutCurrency = 'EUR', $i18nOutput = '') + { + $stubFacade = $this->getMockBuilder('\Thelia\Coupon\BaseFacade') + ->disableOriginalConstructor() + ->getMock(); + + $stubFacade->expects($this->any()) + ->method('getCartTotalPrice') + ->will($this->returnValue($cartTotalPrice)); + + $stubFacade->expects($this->any()) + ->method('getCheckoutCurrency') + ->will($this->returnValue($checkoutCurrency)); + + $stubFacade->expects($this->any()) + ->method('getConditionEvaluator') + ->will($this->returnValue(new ConditionEvaluator())); + + $stubTranslator = $this->getMockBuilder('\Thelia\Core\Translation\Translator') + ->disableOriginalConstructor() + ->getMock(); + $stubTranslator->expects($this->any()) + ->method('trans') + ->will($this->returnValue($i18nOutput)); + + $stubFacade->expects($this->any()) + ->method('getTranslator') + ->will($this->returnValue($stubTranslator)); + + $category1 = new Category(); + $category1->setId(10); + + $category2 = new Category(); + $category2->setId(20); + + $category3 = new Category(); + $category3->setId(30); + + $product1 = new Product(); + $product1->setId(10)->addCategory($category1)->addCategory($category2); + + $product2 = new Product(); + $product2->setId(20)->addCategory($category3); + + $cartItem1Stub = $this->getMockBuilder('\Thelia\Model\CartItem') + ->disableOriginalConstructor() + ->getMock(); + + $cartItem1Stub + ->expects($this->any()) + ->method('getProduct') + ->will($this->returnValue($product1)) + ; + + $cartItem1Stub + ->expects($this->any()) + ->method('getQuantity') + ->will($this->returnValue(1)) + ; + + $cartItem2Stub = $this->getMockBuilder('\Thelia\Model\CartItem') + ->disableOriginalConstructor() + ->getMock(); + + $cartItem2Stub + ->expects($this->any()) + ->method('getProduct') + ->will($this->returnValue($product2)); + + $cartItem2Stub + ->expects($this->any()) + ->method('getQuantity') + ->will($this->returnValue(2)) + ; + + $cartStub = $this->getMockBuilder('\Thelia\Model\Cart') + ->disableOriginalConstructor() + ->getMock(); + + $cartStub + ->expects($this->any()) + ->method('getCartItems') + ->will($this->returnValue([$cartItem1Stub, $cartItem2Stub])); + + $stubFacade->expects($this->any()) + ->method('getCart') + ->will($this->returnValue($cartStub)); + + return $stubFacade; + } + + /** + * Check if validity test on BackOffice inputs are working + * + * @covers Thelia\Condition\Implementation\CartContainsProducts::setValidators + * @expectedException \Thelia\Exception\InvalidConditionOperatorException + */ + public function testInValidBackOfficeInputOperator() + { + /** @var FacadeInterface $stubFacade */ + $stubFacade = $this->generateFacadeStub(); + + $condition1 = new CartContainsProducts($stubFacade); + $operators = array( + CartContainsProducts::PRODUCTS_LIST => Operators::INFERIOR_OR_EQUAL + ); + $values = array( + CartContainsProducts::PRODUCTS_LIST => array() + ); + $condition1->setValidatorsFromForm($operators, $values); + + $isValid = $condition1->isMatching(); + + $expected = true; + $actual =$isValid; + $this->assertEquals($expected, $actual); + } + + /** + * Check if validity test on BackOffice inputs are working + * + * @covers Thelia\Condition\Implementation\CartContainsProducts::setValidators + * @expectedException \Thelia\Exception\InvalidConditionValueException + */ + public function testInValidBackOfficeInputValue() + { + /** @var FacadeInterface $stubFacade */ + $stubFacade = $this->generateFacadeStub(); + + $condition1 = new CartContainsProducts($stubFacade); + $operators = array( + CartContainsProducts::PRODUCTS_LIST => Operators::IN + ); + $values = array( + CartContainsProducts::PRODUCTS_LIST => array() + ); + + $condition1->setValidatorsFromForm($operators, $values); + } + + /** + * Check if test inferior operator is working + * + * @covers Thelia\Condition\Implementation\CartContainsProducts::isMatching + * + */ + public function testMatchingRule() + { + /** @var FacadeInterface $stubFacade */ + $stubFacade = $this->generateFacadeStub(); + + $condition1 = new CartContainsProducts($stubFacade); + $operators = array( + CartContainsProducts::PRODUCTS_LIST => Operators::IN + ); + $values = array( + CartContainsProducts::PRODUCTS_LIST => array(10, 20) + ); + + $condition1->setValidatorsFromForm($operators, $values); + + $isValid = $condition1->isMatching(); + + $expected = true; + $actual =$isValid; + $this->assertEquals($expected, $actual); + } + + /** + * Check if test inferior operator is working + * + * @covers Thelia\Condition\Implementation\CartContainsProducts::isMatching + * + */ + public function testNotMatching() + { + /** @var FacadeInterface $stubFacade */ + $stubFacade = $this->generateFacadeStub(); + + $condition1 = new CartContainsProducts($stubFacade); + + $operators = array( + CartContainsProducts::PRODUCTS_LIST => Operators::IN + ); + $values = array( + CartContainsProducts::PRODUCTS_LIST => array(50, 60) + ); + + $condition1->setValidatorsFromForm($operators, $values); + + $isValid = $condition1->isMatching(); + + $expected = false; + $actual =$isValid; + $this->assertEquals($expected, $actual); + } + + public function testGetSerializableRule() + { + /** @var FacadeInterface $stubFacade */ + $stubFacade = $this->generateFacadeStub(); + + $condition1 = new CartContainsProducts($stubFacade); + + $operators = array( + CartContainsProducts::PRODUCTS_LIST => Operators::IN + ); + $values = array( + CartContainsProducts::PRODUCTS_LIST => array(50, 60) + ); + + $condition1->setValidatorsFromForm($operators, $values); + + $serializableRule = $condition1->getSerializableCondition(); + + $expected = new SerializableCondition(); + $expected->conditionServiceId = $condition1->getServiceId(); + $expected->operators = $operators; + $expected->values = $values; + + $actual = $serializableRule; + + $this->assertEquals($expected, $actual); + + } + + /** + * Check getName i18n + * + * @covers Thelia\Condition\Implementation\CartContainsProducts::getName + * + */ + public function testGetName() + { + $stubFacade = $this->generateFacadeStub(399, 'EUR', 'Number of articles in cart'); + + /** @var FacadeInterface $stubFacade */ + $condition1 = new CartContainsProducts($stubFacade); + + $actual = $condition1->getName(); + $expected = 'Number of articles in cart'; + $this->assertEquals($expected, $actual); + } + + /** + * Check tooltip i18n + * + * @covers Thelia\Condition\Implementation\CartContainsProducts::getToolTip + * + */ + public function testGetToolTip() + { + $stubFacade = $this->generateFacadeStub(399, 'EUR', 'Sample coupon condition'); + + /** @var FacadeInterface $stubFacade */ + $condition1 = new CartContainsProducts($stubFacade); + + $actual = $condition1->getToolTip(); + $expected = 'Sample coupon condition'; + $this->assertEquals($expected, $actual); + } + + /** + * Check validator + * + * @covers Thelia\Condition\Implementation\CartContainsProducts::generateInputs + * + */ + public function testGetValidator() + { + $stubFacade = $this->generateFacadeStub(399, 'EUR', 'Price'); + + /** @var FacadeInterface $stubFacade */ + $condition1 = new CartContainsProducts($stubFacade); + + $operators = array( + CartContainsProducts::PRODUCTS_LIST => Operators::IN + ); + $values = array( + CartContainsProducts::PRODUCTS_LIST => array(50, 60) + ); + + $condition1->setValidatorsFromForm($operators, $values); + + $actual = $condition1->getValidators(); + + $validators = array( + 'inputs' => array( + CartContainsProducts::PRODUCTS_LIST => array( + 'availableOperators' => array( + 'in' => 'Price', + 'out' => 'Price', + ), + 'value' => '', + 'selectedOperator' => 'in' + ) + ), + 'setOperators' => array( + 'products' => 'in' + ), + 'setValues' => array( + 'products' => array(50, 60) + ) + ); + $expected = $validators; + + $this->assertEquals($expected, $actual); + + } + + /** + * Tears down the fixture, for example, closes a network connection. + * This method is called after a test is executed. + */ + protected function tearDown() + { + } + +} diff --git a/core/lib/Thelia/Tests/Condition/Implementation/ForSomeCustomersTest.php b/core/lib/Thelia/Tests/Condition/Implementation/ForSomeCustomersTest.php new file mode 100644 index 000000000..018d7210d --- /dev/null +++ b/core/lib/Thelia/Tests/Condition/Implementation/ForSomeCustomersTest.php @@ -0,0 +1,304 @@ + + */ +class ForSomeCustomersTest extends \PHPUnit_Framework_TestCase +{ + + /** + * Sets up the fixture, for example, opens a network connection. + * This method is called before a test is executed. + */ + protected function setUp() + { + + } + + /** + * Generate adapter stub + * + * @param int $cartTotalPrice Cart total price + * @param string $checkoutCurrency Checkout currency + * @param string $i18nOutput Output from each translation + * + * @return \PHPUnit_Framework_MockObject_MockObject + */ + public function generateFacadeStub($cartTotalPrice = 400, $checkoutCurrency = 'EUR', $i18nOutput = '') + { + $stubFacade = $this->getMockBuilder('\Thelia\Coupon\BaseFacade') + ->disableOriginalConstructor() + ->getMock(); + + $customer = new Customer(); + $customer->setId(10); + + $stubFacade->expects($this->any()) + ->method('getCustomer') + ->will($this->returnValue($customer)); + + $stubFacade->expects($this->any()) + ->method('getConditionEvaluator') + ->will($this->returnValue(new ConditionEvaluator())); + + $stubTranslator = $this->getMockBuilder('\Thelia\Core\Translation\Translator') + ->disableOriginalConstructor() + ->getMock(); + $stubTranslator->expects($this->any()) + ->method('trans') + ->will($this->returnValue($i18nOutput)); + + $stubFacade->expects($this->any()) + ->method('getTranslator') + ->will($this->returnValue($stubTranslator)); + + return $stubFacade; + } + + /** + * Check if validity test on BackOffice inputs are working + * + * @covers Thelia\Condition\Implementation\ForSomeCustomers::setValidators + * @expectedException \Thelia\Exception\InvalidConditionOperatorException + */ + public function testInValidBackOfficeInputOperator() + { + /** @var FacadeInterface $stubFacade */ + $stubFacade = $this->generateFacadeStub(); + + $condition1 = new ForSomeCustomers($stubFacade); + $operators = array( + ForSomeCustomers::CUSTOMERS_LIST => Operators::INFERIOR_OR_EQUAL + ); + $values = array( + ForSomeCustomers::CUSTOMERS_LIST => array() + ); + $condition1->setValidatorsFromForm($operators, $values); + + $isValid = $condition1->isMatching(); + + $expected = true; + $actual =$isValid; + $this->assertEquals($expected, $actual); + } + + /** + * Check if validity test on BackOffice inputs are working + * + * @covers Thelia\Condition\Implementation\ForSomeCustomers::setValidators + * @expectedException \Thelia\Exception\InvalidConditionValueException + */ + public function testInValidBackOfficeInputValue() + { + /** @var FacadeInterface $stubFacade */ + $stubFacade = $this->generateFacadeStub(); + + $condition1 = new ForSomeCustomers($stubFacade); + $operators = array( + ForSomeCustomers::CUSTOMERS_LIST => Operators::IN + ); + $values = array( + ForSomeCustomers::CUSTOMERS_LIST => array() + ); + + $condition1->setValidatorsFromForm($operators, $values); + } + + /** + * Check if test inferior operator is working + * + * @covers Thelia\Condition\Implementation\ForSomeCustomers::isMatching + * + */ + public function testMatchingRule() + { + /** @var FacadeInterface $stubFacade */ + $stubFacade = $this->generateFacadeStub(); + + $condition1 = new ForSomeCustomers($stubFacade); + $operators = array( + ForSomeCustomers::CUSTOMERS_LIST => Operators::IN + ); + $values = array( + ForSomeCustomers::CUSTOMERS_LIST => array(10, 20) + ); + + $condition1->setValidatorsFromForm($operators, $values); + + $isValid = $condition1->isMatching(); + + $expected = true; + $actual =$isValid; + $this->assertEquals($expected, $actual); + } + + /** + * Check if test inferior operator is working + * + * @covers Thelia\Condition\Implementation\ForSomeCustomers::isMatching + * + */ + public function testNotMatching() + { + /** @var FacadeInterface $stubFacade */ + $stubFacade = $this->generateFacadeStub(); + + $condition1 = new ForSomeCustomers($stubFacade); + + $operators = array( + ForSomeCustomers::CUSTOMERS_LIST => Operators::IN + ); + $values = array( + ForSomeCustomers::CUSTOMERS_LIST => array(50, 60) + ); + + $condition1->setValidatorsFromForm($operators, $values); + + $isValid = $condition1->isMatching(); + + $expected = false; + $actual =$isValid; + $this->assertEquals($expected, $actual); + } + + public function testGetSerializableRule() + { + /** @var FacadeInterface $stubFacade */ + $stubFacade = $this->generateFacadeStub(); + + $condition1 = new ForSomeCustomers($stubFacade); + + $operators = array( + ForSomeCustomers::CUSTOMERS_LIST => Operators::IN + ); + $values = array( + ForSomeCustomers::CUSTOMERS_LIST => array(50, 60) + ); + + $condition1->setValidatorsFromForm($operators, $values); + + $serializableRule = $condition1->getSerializableCondition(); + + $expected = new SerializableCondition(); + $expected->conditionServiceId = $condition1->getServiceId(); + $expected->operators = $operators; + $expected->values = $values; + + $actual = $serializableRule; + + $this->assertEquals($expected, $actual); + + } + + /** + * Check getName i18n + * + * @covers Thelia\Condition\Implementation\ForSomeCustomers::getName + * + */ + public function testGetName() + { + $stubFacade = $this->generateFacadeStub(399, 'EUR', 'Number of articles in cart'); + + /** @var FacadeInterface $stubFacade */ + $condition1 = new ForSomeCustomers($stubFacade); + + $actual = $condition1->getName(); + $expected = 'Number of articles in cart'; + $this->assertEquals($expected, $actual); + } + + /** + * Check tooltip i18n + * + * @covers Thelia\Condition\Implementation\ForSomeCustomers::getToolTip + * + */ + public function testGetToolTip() + { + $stubFacade = $this->generateFacadeStub(399, 'EUR', 'Sample coupon condition'); + + /** @var FacadeInterface $stubFacade */ + $condition1 = new ForSomeCustomers($stubFacade); + + $actual = $condition1->getToolTip(); + $expected = 'Sample coupon condition'; + $this->assertEquals($expected, $actual); + } + + /** + * Check validator + * + * @covers Thelia\Condition\Implementation\ForSomeCustomers::generateInputs + * + */ + public function testGetValidator() + { + $stubFacade = $this->generateFacadeStub(399, 'EUR', 'Price'); + + /** @var FacadeInterface $stubFacade */ + $condition1 = new ForSomeCustomers($stubFacade); + + $operators = array( + ForSomeCustomers::CUSTOMERS_LIST => Operators::IN + ); + $values = array( + ForSomeCustomers::CUSTOMERS_LIST => array(50, 60) + ); + + $condition1->setValidatorsFromForm($operators, $values); + + $actual = $condition1->getValidators(); + + $validators = array( + 'inputs' => array( + ForSomeCustomers::CUSTOMERS_LIST => array( + 'availableOperators' => array( + 'in' => 'Price', + 'out' => 'Price', + ), + 'value' => '', + 'selectedOperator' => 'in' + ) + ), + 'setOperators' => array( + 'customers' => 'in' + ), + 'setValues' => array( + 'customers' => array(50, 60) + ) + ); + $expected = $validators; + + $this->assertEquals($expected, $actual); + + } + + /** + * Tears down the fixture, for example, closes a network connection. + * This method is called after a test is executed. + */ + protected function tearDown() + { + } + +} diff --git a/core/lib/Thelia/Tests/Condition/Implementation/MatchBillingCountriesTest.php b/core/lib/Thelia/Tests/Condition/Implementation/MatchBillingCountriesTest.php new file mode 100644 index 000000000..61ac53c2a --- /dev/null +++ b/core/lib/Thelia/Tests/Condition/Implementation/MatchBillingCountriesTest.php @@ -0,0 +1,312 @@ + + */ +class MatchBillingCountriesTest extends \PHPUnit_Framework_TestCase +{ + + /** + * Sets up the fixture, for example, opens a network connection. + * This method is called before a test is executed. + */ + protected function setUp() + { + + } + + /** + * Generate adapter stub + * + * @param int $cartTotalPrice Cart total price + * @param string $checkoutCurrency Checkout currency + * @param string $i18nOutput Output from each translation + * + * @return \PHPUnit_Framework_MockObject_MockObject + */ + public function generateFacadeStub($cartTotalPrice = 400, $checkoutCurrency = 'EUR', $i18nOutput = '') + { + $stubFacade = $this->getMockBuilder('\Thelia\Coupon\BaseFacade') + ->disableOriginalConstructor() + ->getMock(); + + $address = new Address(); + $address->setCountryId(10); + + $stubCustomer = $this->getMockBuilder('\Thelia\Model\Customer') + ->disableOriginalConstructor() + ->getMock(); + + $stubCustomer->expects($this->any()) + ->method('getDefaultAddress') + ->will($this->returnValue($address)); + + $stubFacade->expects($this->any()) + ->method('getCustomer') + ->will($this->returnValue($stubCustomer)); + + $stubFacade->expects($this->any()) + ->method('getConditionEvaluator') + ->will($this->returnValue(new ConditionEvaluator())); + + $stubTranslator = $this->getMockBuilder('\Thelia\Core\Translation\Translator') + ->disableOriginalConstructor() + ->getMock(); + $stubTranslator->expects($this->any()) + ->method('trans') + ->will($this->returnValue($i18nOutput)); + + $stubFacade->expects($this->any()) + ->method('getTranslator') + ->will($this->returnValue($stubTranslator)); + + return $stubFacade; + } + + /** + * Check if validity test on BackOffice inputs are working + * + * @covers Thelia\Condition\Implementation\MatchBillingCountries::setValidators + * @expectedException \Thelia\Exception\InvalidConditionOperatorException + */ + public function testInValidBackOfficeInputOperator() + { + /** @var FacadeInterface $stubFacade */ + $stubFacade = $this->generateFacadeStub(); + + $condition1 = new MatchBillingCountries($stubFacade); + $operators = array( + MatchBillingCountries::COUNTRIES_LIST => Operators::INFERIOR_OR_EQUAL + ); + $values = array( + MatchBillingCountries::COUNTRIES_LIST => array() + ); + $condition1->setValidatorsFromForm($operators, $values); + + $isValid = $condition1->isMatching(); + + $expected = true; + $actual =$isValid; + $this->assertEquals($expected, $actual); + } + + /** + * Check if validity test on BackOffice inputs are working + * + * @covers Thelia\Condition\Implementation\MatchBillingCountries::setValidators + * @expectedException \Thelia\Exception\InvalidConditionValueException + */ + public function testInValidBackOfficeInputValue() + { + /** @var FacadeInterface $stubFacade */ + $stubFacade = $this->generateFacadeStub(); + + $condition1 = new MatchBillingCountries($stubFacade); + $operators = array( + MatchBillingCountries::COUNTRIES_LIST => Operators::IN + ); + $values = array( + MatchBillingCountries::COUNTRIES_LIST => array() + ); + + $condition1->setValidatorsFromForm($operators, $values); + } + + /** + * Check if test inferior operator is working + * + * @covers Thelia\Condition\Implementation\MatchBillingCountries::isMatching + * + */ + public function testMatchingRule() + { + /** @var FacadeInterface $stubFacade */ + $stubFacade = $this->generateFacadeStub(); + + $condition1 = new MatchBillingCountries($stubFacade); + $operators = array( + MatchBillingCountries::COUNTRIES_LIST => Operators::IN + ); + $values = array( + MatchBillingCountries::COUNTRIES_LIST => array(10, 20) + ); + + $condition1->setValidatorsFromForm($operators, $values); + + $isValid = $condition1->isMatching(); + + $expected = true; + $actual =$isValid; + $this->assertEquals($expected, $actual); + } + + /** + * Check if test inferior operator is working + * + * @covers Thelia\Condition\Implementation\MatchBillingCountries::isMatching + * + */ + public function testNotMatching() + { + /** @var FacadeInterface $stubFacade */ + $stubFacade = $this->generateFacadeStub(); + + $condition1 = new MatchBillingCountries($stubFacade); + + $operators = array( + MatchBillingCountries::COUNTRIES_LIST => Operators::IN + ); + $values = array( + MatchBillingCountries::COUNTRIES_LIST => array(50, 60) + ); + + $condition1->setValidatorsFromForm($operators, $values); + + $isValid = $condition1->isMatching(); + + $expected = false; + $actual =$isValid; + $this->assertEquals($expected, $actual); + } + + public function testGetSerializableRule() + { + /** @var FacadeInterface $stubFacade */ + $stubFacade = $this->generateFacadeStub(); + + $condition1 = new MatchBillingCountries($stubFacade); + + $operators = array( + MatchBillingCountries::COUNTRIES_LIST => Operators::IN + ); + $values = array( + MatchBillingCountries::COUNTRIES_LIST => array(50, 60) + ); + + $condition1->setValidatorsFromForm($operators, $values); + + $serializableRule = $condition1->getSerializableCondition(); + + $expected = new SerializableCondition(); + $expected->conditionServiceId = $condition1->getServiceId(); + $expected->operators = $operators; + $expected->values = $values; + + $actual = $serializableRule; + + $this->assertEquals($expected, $actual); + + } + + /** + * Check getName i18n + * + * @covers Thelia\Condition\Implementation\MatchBillingCountries::getName + * + */ + public function testGetName() + { + $stubFacade = $this->generateFacadeStub(399, 'EUR', 'Number of articles in cart'); + + /** @var FacadeInterface $stubFacade */ + $condition1 = new MatchBillingCountries($stubFacade); + + $actual = $condition1->getName(); + $expected = 'Number of articles in cart'; + $this->assertEquals($expected, $actual); + } + + /** + * Check tooltip i18n + * + * @covers Thelia\Condition\Implementation\MatchBillingCountries::getToolTip + * + */ + public function testGetToolTip() + { + $stubFacade = $this->generateFacadeStub(399, 'EUR', 'Sample coupon condition'); + + /** @var FacadeInterface $stubFacade */ + $condition1 = new MatchBillingCountries($stubFacade); + + $actual = $condition1->getToolTip(); + $expected = 'Sample coupon condition'; + $this->assertEquals($expected, $actual); + } + + /** + * Check validator + * + * @covers Thelia\Condition\Implementation\MatchBillingCountries::generateInputs + * + */ + public function testGetValidator() + { + $stubFacade = $this->generateFacadeStub(399, 'EUR', 'Price'); + + /** @var FacadeInterface $stubFacade */ + $condition1 = new MatchBillingCountries($stubFacade); + + $operators = array( + MatchBillingCountries::COUNTRIES_LIST => Operators::IN + ); + $values = array( + MatchBillingCountries::COUNTRIES_LIST => array(50, 60) + ); + + $condition1->setValidatorsFromForm($operators, $values); + + $actual = $condition1->getValidators(); + + $validators = array( + 'inputs' => array( + MatchBillingCountries::COUNTRIES_LIST => array( + 'availableOperators' => array( + 'in' => 'Price', + 'out' => 'Price', + ), + 'value' => '', + 'selectedOperator' => 'in' + ) + ), + 'setOperators' => array( + 'countries' => 'in' + ), + 'setValues' => array( + 'countries' => array(50, 60) + ) + ); + $expected = $validators; + + $this->assertEquals($expected, $actual); + + } + + /** + * Tears down the fixture, for example, closes a network connection. + * This method is called after a test is executed. + */ + protected function tearDown() + { + } + +} diff --git a/core/lib/Thelia/Tests/Condition/Implementation/MatchDeliveryCountriesTest.php b/core/lib/Thelia/Tests/Condition/Implementation/MatchDeliveryCountriesTest.php new file mode 100644 index 000000000..623a1aeef --- /dev/null +++ b/core/lib/Thelia/Tests/Condition/Implementation/MatchDeliveryCountriesTest.php @@ -0,0 +1,304 @@ + + */ +class MatchDeliveryCountriesTest extends \PHPUnit_Framework_TestCase +{ + + /** + * Sets up the fixture, for example, opens a network connection. + * This method is called before a test is executed. + */ + protected function setUp() + { + + } + + /** + * Generate adapter stub + * + * @param int $cartTotalPrice Cart total price + * @param string $checkoutCurrency Checkout currency + * @param string $i18nOutput Output from each translation + * + * @return \PHPUnit_Framework_MockObject_MockObject + */ + public function generateFacadeStub($cartTotalPrice = 400, $checkoutCurrency = 'EUR', $i18nOutput = '') + { + $stubFacade = $this->getMockBuilder('\Thelia\Coupon\BaseFacade') + ->disableOriginalConstructor() + ->getMock(); + + $address = new Address(); + $address->setCountryId(10); + + $stubFacade->expects($this->any()) + ->method('getDeliveryAddress') + ->will($this->returnValue($address)); + + $stubFacade->expects($this->any()) + ->method('getConditionEvaluator') + ->will($this->returnValue(new ConditionEvaluator())); + + $stubTranslator = $this->getMockBuilder('\Thelia\Core\Translation\Translator') + ->disableOriginalConstructor() + ->getMock(); + $stubTranslator->expects($this->any()) + ->method('trans') + ->will($this->returnValue($i18nOutput)); + + $stubFacade->expects($this->any()) + ->method('getTranslator') + ->will($this->returnValue($stubTranslator)); + + return $stubFacade; + } + + /** + * Check if validity test on BackOffice inputs are working + * + * @covers Thelia\Condition\Implementation\MatchDeliveryCountries::setValidators + * @expectedException \Thelia\Exception\InvalidConditionOperatorException + */ + public function testInValidBackOfficeInputOperator() + { + /** @var FacadeInterface $stubFacade */ + $stubFacade = $this->generateFacadeStub(); + + $condition1 = new MatchDeliveryCountries($stubFacade); + $operators = array( + MatchDeliveryCountries::COUNTRIES_LIST => Operators::INFERIOR_OR_EQUAL + ); + $values = array( + MatchDeliveryCountries::COUNTRIES_LIST => array() + ); + $condition1->setValidatorsFromForm($operators, $values); + + $isValid = $condition1->isMatching(); + + $expected = true; + $actual =$isValid; + $this->assertEquals($expected, $actual); + } + + /** + * Check if validity test on BackOffice inputs are working + * + * @covers Thelia\Condition\Implementation\MatchDeliveryCountries::setValidators + * @expectedException \Thelia\Exception\InvalidConditionValueException + */ + public function testInValidBackOfficeInputValue() + { + /** @var FacadeInterface $stubFacade */ + $stubFacade = $this->generateFacadeStub(); + + $condition1 = new MatchDeliveryCountries($stubFacade); + $operators = array( + MatchDeliveryCountries::COUNTRIES_LIST => Operators::IN + ); + $values = array( + MatchDeliveryCountries::COUNTRIES_LIST => array() + ); + + $condition1->setValidatorsFromForm($operators, $values); + } + + /** + * Check if test inferior operator is working + * + * @covers Thelia\Condition\Implementation\MatchDeliveryCountries::isMatching + * + */ + public function testMatchingRule() + { + /** @var FacadeInterface $stubFacade */ + $stubFacade = $this->generateFacadeStub(); + + $condition1 = new MatchDeliveryCountries($stubFacade); + $operators = array( + MatchDeliveryCountries::COUNTRIES_LIST => Operators::IN + ); + $values = array( + MatchDeliveryCountries::COUNTRIES_LIST => array(10, 20) + ); + + $condition1->setValidatorsFromForm($operators, $values); + + $isValid = $condition1->isMatching(); + + $expected = true; + $actual =$isValid; + $this->assertEquals($expected, $actual); + } + + /** + * Check if test inferior operator is working + * + * @covers Thelia\Condition\Implementation\MatchDeliveryCountries::isMatching + * + */ + public function testNotMatching() + { + /** @var FacadeInterface $stubFacade */ + $stubFacade = $this->generateFacadeStub(); + + $condition1 = new MatchDeliveryCountries($stubFacade); + + $operators = array( + MatchDeliveryCountries::COUNTRIES_LIST => Operators::IN + ); + $values = array( + MatchDeliveryCountries::COUNTRIES_LIST => array(50, 60) + ); + + $condition1->setValidatorsFromForm($operators, $values); + + $isValid = $condition1->isMatching(); + + $expected = false; + $actual =$isValid; + $this->assertEquals($expected, $actual); + } + + public function testGetSerializableRule() + { + /** @var FacadeInterface $stubFacade */ + $stubFacade = $this->generateFacadeStub(); + + $condition1 = new MatchDeliveryCountries($stubFacade); + + $operators = array( + MatchDeliveryCountries::COUNTRIES_LIST => Operators::IN + ); + $values = array( + MatchDeliveryCountries::COUNTRIES_LIST => array(50, 60) + ); + + $condition1->setValidatorsFromForm($operators, $values); + + $serializableRule = $condition1->getSerializableCondition(); + + $expected = new SerializableCondition(); + $expected->conditionServiceId = $condition1->getServiceId(); + $expected->operators = $operators; + $expected->values = $values; + + $actual = $serializableRule; + + $this->assertEquals($expected, $actual); + + } + + /** + * Check getName i18n + * + * @covers Thelia\Condition\Implementation\MatchDeliveryCountries::getName + * + */ + public function testGetName() + { + $stubFacade = $this->generateFacadeStub(399, 'EUR', 'Number of articles in cart'); + + /** @var FacadeInterface $stubFacade */ + $condition1 = new MatchDeliveryCountries($stubFacade); + + $actual = $condition1->getName(); + $expected = 'Number of articles in cart'; + $this->assertEquals($expected, $actual); + } + + /** + * Check tooltip i18n + * + * @covers Thelia\Condition\Implementation\MatchDeliveryCountries::getToolTip + * + */ + public function testGetToolTip() + { + $stubFacade = $this->generateFacadeStub(399, 'EUR', 'Sample coupon condition'); + + /** @var FacadeInterface $stubFacade */ + $condition1 = new MatchDeliveryCountries($stubFacade); + + $actual = $condition1->getToolTip(); + $expected = 'Sample coupon condition'; + $this->assertEquals($expected, $actual); + } + + /** + * Check validator + * + * @covers Thelia\Condition\Implementation\MatchDeliveryCountries::generateInputs + * + */ + public function testGetValidator() + { + $stubFacade = $this->generateFacadeStub(399, 'EUR', 'Price'); + + /** @var FacadeInterface $stubFacade */ + $condition1 = new MatchDeliveryCountries($stubFacade); + + $operators = array( + MatchDeliveryCountries::COUNTRIES_LIST => Operators::IN + ); + $values = array( + MatchDeliveryCountries::COUNTRIES_LIST => array(50, 60) + ); + + $condition1->setValidatorsFromForm($operators, $values); + + $actual = $condition1->getValidators(); + + $validators = array( + 'inputs' => array( + MatchDeliveryCountries::COUNTRIES_LIST => array( + 'availableOperators' => array( + 'in' => 'Price', + 'out' => 'Price', + ), + 'value' => '', + 'selectedOperator' => 'in' + ) + ), + 'setOperators' => array( + 'countries' => 'in' + ), + 'setValues' => array( + 'countries' => array(50, 60) + ) + ); + $expected = $validators; + + $this->assertEquals($expected, $actual); + + } + + /** + * Tears down the fixture, for example, closes a network connection. + * This method is called after a test is executed. + */ + protected function tearDown() + { + } + +} diff --git a/core/lib/Thelia/Tests/Condition/Implementation/MatchForEveryoneTest.php b/core/lib/Thelia/Tests/Condition/Implementation/MatchForEveryoneTest.php index ddf3d25ae..84b57afb1 100644 --- a/core/lib/Thelia/Tests/Condition/Implementation/MatchForEveryoneTest.php +++ b/core/lib/Thelia/Tests/Condition/Implementation/MatchForEveryoneTest.php @@ -13,7 +13,6 @@ namespace Thelia\Condition\Implementation; use Thelia\Condition\ConditionEvaluator; - use Thelia\Coupon\FacadeInterface; use Thelia\Model\Currency; diff --git a/core/lib/Thelia/Tests/Condition/Implementation/MatchForTotalAmountTest.php b/core/lib/Thelia/Tests/Condition/Implementation/MatchForTotalAmountTest.php index bffbda092..fa599a866 100644 --- a/core/lib/Thelia/Tests/Condition/Implementation/MatchForTotalAmountTest.php +++ b/core/lib/Thelia/Tests/Condition/Implementation/MatchForTotalAmountTest.php @@ -12,13 +12,12 @@ namespace Thelia\Tests\Condition\Implementation; +use Thelia\Condition\ConditionCollection; use Thelia\Condition\ConditionEvaluator; use Thelia\Condition\ConditionFactory; use Thelia\Condition\Implementation\MatchForTotalAmount; use Thelia\Condition\Operators; -use Thelia\Condition\ConditionCollection; use Thelia\Coupon\FacadeInterface; - use Thelia\Model\Currency; use Thelia\Model\CurrencyQuery; diff --git a/core/lib/Thelia/Tests/Condition/Implementation/StartDateTest.php b/core/lib/Thelia/Tests/Condition/Implementation/StartDateTest.php new file mode 100644 index 000000000..6df0fddbb --- /dev/null +++ b/core/lib/Thelia/Tests/Condition/Implementation/StartDateTest.php @@ -0,0 +1,329 @@ + + */ +class StartDateTest extends \PHPUnit_Framework_TestCase +{ + + var $startDate; + /** + * Sets up the fixture, for example, opens a network connection. + * This method is called before a test is executed. + */ + protected function setUp() + { + $this->startDate = time() - 2000; + } + + /** + * Generate adapter stub + * + * @param int $cartTotalPrice Cart total price + * @param string $checkoutCurrency Checkout currency + * @param string $i18nOutput Output from each translation + * + * @return \PHPUnit_Framework_MockObject_MockObject + */ + public function generateFacadeStub($cartTotalPrice = 400, $checkoutCurrency = 'EUR', $i18nOutput = '') + { + $stubFacade = $this->getMockBuilder('\Thelia\Coupon\BaseFacade') + ->disableOriginalConstructor() + ->getMock(); + + $address = new Address(); + $address->setCountryId(10); + + $stubFacade->expects($this->any()) + ->method('getDeliveryAddress') + ->will($this->returnValue($address)); + + $stubFacade->expects($this->any()) + ->method('getConditionEvaluator') + ->will($this->returnValue(new ConditionEvaluator())); + + $stubTranslator = $this->getMockBuilder('\Thelia\Core\Translation\Translator') + ->disableOriginalConstructor() + ->getMock(); + $stubTranslator->expects($this->any()) + ->method('trans') + ->will($this->returnValue($i18nOutput)); + + $stubFacade->expects($this->any()) + ->method('getTranslator') + ->will($this->returnValue($stubTranslator)); + + $lang = new Lang(); + $lang->setDateFormat("d/m/Y"); + + $stubSession = $this->getMockBuilder('\Thelia\Core\HttpFoundation\Session\Session') + ->disableOriginalConstructor() + ->getMock(); + + $stubSession->expects($this->any()) + ->method('getLang') + ->will($this->returnValue($lang)); + + $stubRequest = $this->getMockBuilder('\Thelia\Core\HttpFoundation\Request') + ->disableOriginalConstructor() + ->getMock(); + + $stubRequest->expects($this->any()) + ->method('getSession') + ->will($this->returnValue($stubSession)); + + $stubFacade->expects($this->any()) + ->method('getRequest') + ->will($this->returnValue($stubRequest)); + + return $stubFacade; + } + + /** + * Check if validity test on BackOffice inputs are working + * + * @covers Thelia\Condition\Implementation\StartDate::setValidators + * @expectedException \Thelia\Exception\InvalidConditionOperatorException + */ + public function testInValidBackOfficeInputOperator() + { + /** @var FacadeInterface $stubFacade */ + $stubFacade = $this->generateFacadeStub(); + + $condition1 = new StartDate($stubFacade); + + $operators = array( + StartDate::START_DATE => 'petite licorne' + ); + $values = array( + StartDate::START_DATE => $this->startDate + ); + $condition1->setValidatorsFromForm($operators, $values); + + $isValid = $condition1->isMatching(); + + $expected = true; + $actual =$isValid; + $this->assertEquals($expected, $actual); + } + + /** + * Check if validity test on BackOffice inputs are working + * + * @covers Thelia\Condition\Implementation\StartDate::setValidators + * @expectedException \Thelia\Exception\InvalidConditionValueException + */ + public function testInValidBackOfficeInputValue() + { + /** @var FacadeInterface $stubFacade */ + $stubFacade = $this->generateFacadeStub(); + + $condition1 = new StartDate($stubFacade); + $operators = array( + StartDate::START_DATE => Operators::SUPERIOR_OR_EQUAL + ); + $values = array( + StartDate::START_DATE => 'petit poney' + ); + + $condition1->setValidatorsFromForm($operators, $values); + } + + /** + * Check if test inferior operator is working + * + * @covers Thelia\Condition\Implementation\StartDate::isMatching + * + */ + public function testMatchingRule() + { + /** @var FacadeInterface $stubFacade */ + $stubFacade = $this->generateFacadeStub(); + + $condition1 = new StartDate($stubFacade); + $operators = array( + StartDate::START_DATE => Operators::SUPERIOR_OR_EQUAL + ); + $values = array( + StartDate::START_DATE => $this->startDate + ); + + $condition1->setValidatorsFromForm($operators, $values); + + $isValid = $condition1->isMatching(); + + $expected = true; + $actual =$isValid; + $this->assertEquals($expected, $actual); + } + + /** + * Check if test inferior operator is working + * + * @covers Thelia\Condition\Implementation\StartDate::isMatching + * + */ + public function testNotMatching() + { + /** @var FacadeInterface $stubFacade */ + $stubFacade = $this->generateFacadeStub(); + + $condition1 = new StartDate($stubFacade); + + $operators = array( + StartDate::START_DATE => Operators::SUPERIOR_OR_EQUAL + ); + $values = array( + StartDate::START_DATE => time() + 2000 + ); + + $condition1->setValidatorsFromForm($operators, $values); + + $isValid = $condition1->isMatching(); + + $expected = false; + $actual =$isValid; + $this->assertEquals($expected, $actual); + } + + public function testGetSerializableRule() + { + /** @var FacadeInterface $stubFacade */ + $stubFacade = $this->generateFacadeStub(); + + $condition1 = new StartDate($stubFacade); + + $operators = array( + StartDate::START_DATE => Operators::SUPERIOR_OR_EQUAL + ); + $values = array( + StartDate::START_DATE => $this->startDate + ); + + $condition1->setValidatorsFromForm($operators, $values); + + $serializableRule = $condition1->getSerializableCondition(); + + $expected = new SerializableCondition(); + $expected->conditionServiceId = $condition1->getServiceId(); + $expected->operators = $operators; + $expected->values = $values; + + $actual = $serializableRule; + + $this->assertEquals($expected, $actual); + + } + + /** + * Check getName i18n + * + * @covers Thelia\Condition\Implementation\StartDate::getName + * + */ + public function testGetName() + { + $stubFacade = $this->generateFacadeStub(399, 'EUR', 'Number of articles in cart'); + + /** @var FacadeInterface $stubFacade */ + $condition1 = new StartDate($stubFacade); + + $actual = $condition1->getName(); + $expected = 'Number of articles in cart'; + $this->assertEquals($expected, $actual); + } + + /** + * Check tooltip i18n + * + * @covers Thelia\Condition\Implementation\StartDate::getToolTip + * + */ + public function testGetToolTip() + { + $stubFacade = $this->generateFacadeStub(399, 'EUR', 'Sample coupon condition'); + + /** @var FacadeInterface $stubFacade */ + $condition1 = new StartDate($stubFacade); + + $actual = $condition1->getToolTip(); + $expected = 'Sample coupon condition'; + $this->assertEquals($expected, $actual); + } + + /** + * Check validator + * + * @covers Thelia\Condition\Implementation\StartDate::generateInputs + * + */ + public function testGetValidator() + { + $stubFacade = $this->generateFacadeStub(399, 'EUR', 'Price'); + + /** @var FacadeInterface $stubFacade */ + $condition1 = new StartDate($stubFacade); + + $operators = array( + StartDate::START_DATE => Operators::SUPERIOR_OR_EQUAL + ); + $values = array( + StartDate::START_DATE => $this->startDate + ); + + $condition1->setValidatorsFromForm($operators, $values); + + $actual = $condition1->getValidators(); + + $validators = array( + 'inputs' => array( + StartDate::START_DATE => array( + 'availableOperators' => array( + '>=' => 'Price', + ), + 'value' => '', + 'selectedOperator' => '>=' + ) + ), + 'setOperators' => array( + 'start_date' => '>=' + ), + 'setValues' => array( + 'start_date' => $this->startDate + ) + ); + $expected = $validators; + + $this->assertEquals($expected, $actual); + + } + + /** + * Tears down the fixture, for example, closes a network connection. + * This method is called after a test is executed. + */ + protected function tearDown() + { + } + +} diff --git a/core/lib/Thelia/Tests/Coupon/Type/FreeProductTest.php b/core/lib/Thelia/Tests/Coupon/Type/FreeProductTest.php new file mode 100644 index 000000000..72be02204 --- /dev/null +++ b/core/lib/Thelia/Tests/Coupon/Type/FreeProductTest.php @@ -0,0 +1,412 @@ + + */ +class FreeProductTest extends \PHPUnit_Framework_TestCase +{ + + /** @var Product $freeProduct */ + var $freeProduct; + var $originalPrice; + var $originalPromo; + + /** + * Sets up the fixture, for example, opens a network connection. + * This method is called before a test is executed. + */ + protected function setUp() + { + $currency = CurrencyQuery::create()->filterByCode('EUR')->findOne(); + + // Find a product + $this->freeProduct = ProductQuery::create()->findOne(); + + $this->originalPrice = $this->freeProduct->getDefaultSaleElements()->getPricesByCurrency($currency)->getPrice(); + $this->originalPromo = $this->freeProduct->getDefaultSaleElements()->getPromo(); + + $this->freeProduct->getDefaultSaleElements()->setPromo(false)->save(); + } + + /** + * Generate adapter stub + * + * @param int $cartTotalPrice Cart total price + * @param string $checkoutCurrency Checkout currency + * @param string $i18nOutput Output from each translation + * + * @return \PHPUnit_Framework_MockObject_MockObject + */ + public function generateFacadeStub($cartTotalPrice = 400, $checkoutCurrency = 'EUR', $i18nOutput = '') + { + $stubFacade = $this->getMockBuilder('\Thelia\Coupon\BaseFacade') + ->disableOriginalConstructor() + ->getMock(); + + $currencies = CurrencyQuery::create(); + $currencies = $currencies->find(); + $stubFacade->expects($this->any()) + ->method('getAvailableCurrencies') + ->will($this->returnValue($currencies)); + + $stubFacade->expects($this->any()) + ->method('getCartTotalPrice') + ->will($this->returnValue($cartTotalPrice)); + + $stubFacade->expects($this->any()) + ->method('getCheckoutCurrency') + ->will($this->returnValue($checkoutCurrency)); + + $stubFacade->expects($this->any()) + ->method('getConditionEvaluator') + ->will($this->returnValue(new ConditionEvaluator())); + + $stubTranslator = $this->getMockBuilder('\Thelia\Core\Translation\Translator') + ->disableOriginalConstructor() + ->getMock(); + $stubTranslator->expects($this->any()) + ->method('trans') + ->will($this->returnValue($i18nOutput)); + + $stubFacade->expects($this->any()) + ->method('getTranslator') + ->will($this->returnValue($stubTranslator)); + + $stubDispatcher = $this->getMockBuilder('\Symfony\Component\EventDispatcher\EventDispatcher') + ->disableOriginalConstructor() + ->getMock(); + + $stubDispatcher->expects($this->any()) + ->method('dispatch') + ->will($this->returnCallback(function($dummy, $cartEvent) { + $ci = new CartItem(); + $ci->setId(3)->setPrice(123)->setPromo(0); + + $cartEvent->setCartItem($ci); + })); + + $stubFacade->expects($this->any()) + ->method('getDispatcher') + ->will($this->returnValue($stubDispatcher)); + + $stubSession = $this->getMockBuilder('\Thelia\Core\HttpFoundation\Session\Session') + ->disableOriginalConstructor() + ->getMock(); + + $stubSession->expects($this->any()) + ->method('get') + ->will($this->onConsecutiveCalls(-1, 3)); + + $stubRequest = $this->getMockBuilder('\Thelia\Core\HttpFoundation\Request') + ->disableOriginalConstructor() + ->getMock(); + + $stubRequest->expects($this->any()) + ->method('getSession') + ->will($this->returnValue($stubSession)); + + $stubFacade->expects($this->any()) + ->method('getRequest') + ->will($this->returnValue($stubRequest)); + + return $stubFacade; + } + + public function generateMatchingCart(\PHPUnit_Framework_MockObject_MockObject $stubFacade, $count) { + + $product1 = new Product(); + $product1->setId(10); + + $product2 = new Product(); + $product2->setId(20); + + $cartItem1Stub = $this->getMockBuilder('\Thelia\Model\CartItem') + ->disableOriginalConstructor() + ->getMock(); + + $cartItem1Stub + ->expects($this->any()) + ->method('getProduct') + ->will($this->returnValue($product1)) + ; + $cartItem1Stub + ->expects($this->any()) + ->method('getQuantity') + ->will($this->returnValue(1)) + ; + $cartItem1Stub + ->expects($this->any()) + ->method('getPrice') + ->will($this->returnValue(100)) + ; + + $cartItem2Stub = $this->getMockBuilder('\Thelia\Model\CartItem') + ->disableOriginalConstructor() + ->getMock(); + + $cartItem2Stub + ->expects($this->any()) + ->method('getProduct') + ->will($this->returnValue($product2)); + + $cartItem2Stub + ->expects($this->any()) + ->method('getQuantity') + ->will($this->returnValue(2)) + ; + $cartItem2Stub + ->expects($this->any()) + ->method('getPrice') + ->will($this->returnValue(150)) + + ; + + $cartStub = $this->getMockBuilder('\Thelia\Model\Cart') + ->disableOriginalConstructor() + ->getMock(); + + if ($count == 1) + $ret = [$cartItem1Stub]; + else + $ret = [$cartItem1Stub, $cartItem2Stub]; + + $cartStub + ->expects($this->any()) + ->method('getCartItems') + ->will($this->returnValue($ret)); + + $stubFacade->expects($this->any()) + ->method('getCart') + ->will($this->returnValue($cartStub)); + } + + public function generateNoMatchingCart(\PHPUnit_Framework_MockObject_MockObject $stubFacade) { + + $product2 = new Product(); + $product2->setId(30); + + $cartItem2Stub = $this->getMockBuilder('\Thelia\Model\CartItem') + ->disableOriginalConstructor() + ->getMock(); + + $cartItem2Stub->expects($this->any()) + ->method('getProduct') + ->will($this->returnValue($product2)) + ; + $cartItem2Stub->expects($this->any()) + ->method('getQuantity') + ->will($this->returnValue(2)) + ; + $cartItem2Stub + ->expects($this->any()) + ->method('getPrice') + ->will($this->returnValue(11000)) + ; + + $cartStub = $this->getMockBuilder('\Thelia\Model\Cart') + ->disableOriginalConstructor() + ->getMock(); + + $cartStub + ->expects($this->any()) + ->method('getCartItems') + ->will($this->returnValue([$cartItem2Stub])); + + $stubFacade->expects($this->any()) + ->method('getCart') + ->will($this->returnValue($cartStub)); + } + + public function testSet() + { + $stubFacade = $this->generateFacadeStub(); + + $coupon = new FreeProduct($stubFacade); + + $date = new \DateTime(); + + $coupon->set( + $stubFacade, + 'TEST', 'TEST Coupon', 'This is a test coupon title', 'This is a test coupon description', + array('percentage' => 10.00, 'products' => [10, 20], 'offered_product_id' => $this->freeProduct->getId(), 'offered_category_id' => 1), + true, true, true, true, + 254, + $date->setTimestamp(strtotime("today + 3 months")), + new ObjectCollection(), + new ObjectCollection(), + false + ); + + $condition1 = new MatchForTotalAmount($stubFacade); + $operators = array( + MatchForTotalAmount::CART_TOTAL => Operators::SUPERIOR, + MatchForTotalAmount::CART_CURRENCY => Operators::EQUAL + ); + $values = array( + MatchForTotalAmount::CART_TOTAL => 40.00, + MatchForTotalAmount::CART_CURRENCY => 'EUR' + ); + $condition1->setValidatorsFromForm($operators, $values); + + $condition2 = new MatchForTotalAmount($stubFacade); + $operators = array( + MatchForTotalAmount::CART_TOTAL => Operators::INFERIOR, + MatchForTotalAmount::CART_CURRENCY => Operators::EQUAL + ); + $values = array( + MatchForTotalAmount::CART_TOTAL => 400.00, + MatchForTotalAmount::CART_CURRENCY => 'EUR' + ); + $condition2->setValidatorsFromForm($operators, $values); + + $conditions = new ConditionCollection(); + $conditions[] = $condition1; + $conditions[] = $condition2; + $coupon->setConditions($conditions); + + $this->assertEquals('TEST', $coupon->getCode()); + $this->assertEquals('TEST Coupon', $coupon->getTitle()); + $this->assertEquals('This is a test coupon title', $coupon->getShortDescription()); + $this->assertEquals('This is a test coupon description', $coupon->getDescription()); + + $this->assertEquals(true, $coupon->isCumulative()); + $this->assertEquals(true, $coupon->isRemovingPostage()); + $this->assertEquals(true, $coupon->isAvailableOnSpecialOffers()); + $this->assertEquals(true, $coupon->isEnabled()); + + $this->assertEquals(254, $coupon->getMaxUsage()); + $this->assertEquals($date, $coupon->getExpirationDate()); + } + + public function testMatchOne() + { + $stubFacade = $this->generateFacadeStub(); + + $coupon = new FreeProduct($stubFacade); + + $date = new \DateTime(); + + $coupon->set( + $stubFacade, + 'TEST', 'TEST Coupon', 'This is a test coupon title', 'This is a test coupon description', + array('percentage' => 10.00, 'products' => [10, 20], 'offered_product_id' => $this->freeProduct->getId(), 'offered_category_id' => 1), + true, true, true, true, + 254, + $date->setTimestamp(strtotime("today + 3 months")), + new ObjectCollection(), + new ObjectCollection(), + false + ); + + $this->generateMatchingCart($stubFacade, 1); + + $this->assertEquals(123.00, $coupon->exec()); + } + + public function testMatchSeveral() + { + $stubFacade = $this->generateFacadeStub(); + + $coupon = new FreeProduct($stubFacade); + + $date = new \DateTime(); + + $coupon->set( + $stubFacade, + 'TEST', 'TEST Coupon', 'This is a test coupon title', 'This is a test coupon description', + array('percentage' => 10.00, 'products' => [10, 20], 'offered_product_id' => $this->freeProduct->getId(), 'offered_category_id' => 1), + true, true, true, true, + 254, + $date->setTimestamp(strtotime("today + 3 months")), + new ObjectCollection(), + new ObjectCollection(), + false + ); + + $this->generateMatchingCart($stubFacade, 2); + + $this->assertEquals(123.00, $coupon->exec()); + } + + public function testNoMatch() + { + $stubFacade = $this->generateFacadeStub(); + + $coupon = new FreeProduct($stubFacade); + + $date = new \DateTime(); + + $coupon->set( + $stubFacade, + 'TEST', 'TEST Coupon', 'This is a test coupon title', 'This is a test coupon description', + array('percentage' => 10.00, 'products' => [10, 20], 'offered_product_id' => $this->freeProduct->getId(), 'offered_category_id' => 1), + true, true, true, true, + 254, + $date->setTimestamp(strtotime("today + 3 months")), + new ObjectCollection(), + new ObjectCollection(), + false + ); + + $this->generateNoMatchingCart($stubFacade); + + $this->assertEquals(0.00, $coupon->exec()); + } + + public function testGetName() + { + $stubFacade = $this->generateFacadeStub(399, 'EUR', 'Coupon test name'); + + /** @var FacadeInterface $stubFacade */ + $coupon = new FreeProduct($stubFacade); + + $actual = $coupon->getName(); + $expected = 'Coupon test name'; + $this->assertEquals($expected, $actual); + } + + public function testGetToolTip() + { + $tooltip = 'Coupon test tooltip'; + $stubFacade = $this->generateFacadeStub(399, 'EUR', $tooltip); + + /** @var FacadeInterface $stubFacade */ + $coupon = new FreeProduct($stubFacade); + + $actual = $coupon->getToolTip(); + $expected = $tooltip; + $this->assertEquals($expected, $actual); + } + + /** + * Tears down the fixture, for example, closes a network connection. + * This method is called after a test is executed. + */ + protected function tearDown() + { + $this->freeProduct->getDefaultSaleElements()->setPromo($this->originalPromo)->save(); + } +} diff --git a/core/lib/Thelia/Tests/Coupon/Type/RemoveAmountOnAttributeValuesTest.php b/core/lib/Thelia/Tests/Coupon/Type/RemoveAmountOnAttributeValuesTest.php new file mode 100644 index 000000000..67bd1ce60 --- /dev/null +++ b/core/lib/Thelia/Tests/Coupon/Type/RemoveAmountOnAttributeValuesTest.php @@ -0,0 +1,398 @@ + + */ +class RemoveAmountOnAttributeValuesTest extends \PHPUnit_Framework_TestCase +{ + + /** + * Sets up the fixture, for example, opens a network connection. + * This method is called before a test is executed. + */ + protected function setUp() + { + } + + /** + * Generate adapter stub + * + * @param int $cartTotalPrice Cart total price + * @param string $checkoutCurrency Checkout currency + * @param string $i18nOutput Output from each translation + * + * @return \PHPUnit_Framework_MockObject_MockObject + */ + public function generateFacadeStub($cartTotalPrice = 400, $checkoutCurrency = 'EUR', $i18nOutput = '') + { + $stubFacade = $this->getMockBuilder('\Thelia\Coupon\BaseFacade') + ->disableOriginalConstructor() + ->getMock(); + + $currencies = CurrencyQuery::create(); + $currencies = $currencies->find(); + $stubFacade->expects($this->any()) + ->method('getAvailableCurrencies') + ->will($this->returnValue($currencies)); + + $stubFacade->expects($this->any()) + ->method('getCartTotalPrice') + ->will($this->returnValue($cartTotalPrice)); + + $stubFacade->expects($this->any()) + ->method('getCheckoutCurrency') + ->will($this->returnValue($checkoutCurrency)); + + $stubFacade->expects($this->any()) + ->method('getConditionEvaluator') + ->will($this->returnValue(new ConditionEvaluator())); + + $stubTranslator = $this->getMockBuilder('\Thelia\Core\Translation\Translator') + ->disableOriginalConstructor() + ->getMock(); + $stubTranslator->expects($this->any()) + ->method('trans') + ->will($this->returnValue($i18nOutput)); + + $stubFacade->expects($this->any()) + ->method('getTranslator') + ->will($this->returnValue($stubTranslator)); + + return $stubFacade; + } + + public function generateMatchingCart(\PHPUnit_Framework_MockObject_MockObject $stubFacade, $count) { + + $attrCombination1 = $this->getMockBuilder('\Thelia\Model\AttributeCombination') + ->disableOriginalConstructor() + ->getMock() + ; + + $attrCombination1 + ->expects($this->any()) + ->method('getAttributeAvId') + ->will($this->returnValue(10)) + ; + + $attrCombination2 = $this->getMockBuilder('\Thelia\Model\AttributeCombination') + ->disableOriginalConstructor() + ->getMock() + ; + + $attrCombination2 + ->expects($this->any()) + ->method('getAttributeAvId') + ->will($this->returnValue(20)) + ; + + $pse1 = $this->getMockBuilder('\Thelia\Model\ProductSaleElements') + ->disableOriginalConstructor() + ->getMock() + ; + $pse1 + ->expects($this->any()) + ->method('getAttributeCombinations') + ->will($this->returnValue([$attrCombination1])) + ; + + $pse2 = $this->getMockBuilder('\Thelia\Model\ProductSaleElements') + ->disableOriginalConstructor() + ->getMock(); + ; + $pse2 + ->expects($this->any()) + ->method('getAttributeCombinations') + ->will($this->returnValue([$attrCombination1, $attrCombination2])) + ; + + $cartItem1Stub = $this->getMockBuilder('\Thelia\Model\CartItem') + ->disableOriginalConstructor() + ->getMock() + ; + $cartItem1Stub + ->expects($this->any()) + ->method('getProductSaleElements') + ->will($this->returnValue($pse1)) + ; + $cartItem1Stub + ->expects($this->any()) + ->method('getQuantity') + ->will($this->returnValue(1)) + ; + + + $cartItem2Stub = $this->getMockBuilder('\Thelia\Model\CartItem') + ->disableOriginalConstructor() + ->getMock() + ; + $cartItem2Stub + ->expects($this->any()) + ->method('getProductSaleElements') + ->will($this->returnValue($pse2)) + ; + $cartItem2Stub + ->expects($this->any()) + ->method('getQuantity') + ->will($this->returnValue(2)) + ; + + $cartStub = $this->getMockBuilder('\Thelia\Model\Cart') + ->disableOriginalConstructor() + ->getMock(); + + if ($count == 1) + $ret = [$cartItem1Stub]; + else + $ret = [$cartItem1Stub, $cartItem2Stub]; + + $cartStub + ->expects($this->any()) + ->method('getCartItems') + ->will($this->returnValue($ret)); + + $stubFacade->expects($this->any()) + ->method('getCart') + ->will($this->returnValue($cartStub)); + } + + public function generateNoMatchingCart(\PHPUnit_Framework_MockObject_MockObject $stubFacade) { + + $attrCombination1 = $this->getMockBuilder('\Thelia\Model\AttributeCombination') + ->disableOriginalConstructor() + ->getMock() + ; + + $attrCombination1 + ->expects($this->any()) + ->method('getAttributeAvId') + ->will($this->returnValue(30)) + ; + + $pse1 = $this->getMockBuilder('\Thelia\Model\ProductSaleElements') + ->disableOriginalConstructor() + ->getMock() + ; + $pse1 + ->expects($this->any()) + ->method('getAttributeCombinations') + ->will($this->returnValue([$attrCombination1])) + ; + + $cartItem1Stub = $this->getMockBuilder('\Thelia\Model\CartItem') + ->disableOriginalConstructor() + ->getMock() + ; + $cartItem1Stub + ->expects($this->any()) + ->method('getProductSaleElements') + ->will($this->returnValue($pse1)) + ; + $cartItem1Stub + ->expects($this->any()) + ->method('getQuantity') + ->will($this->returnValue(1)) + ; + + $cartStub = $this->getMockBuilder('\Thelia\Model\Cart') + ->disableOriginalConstructor() + ->getMock(); + + $cartStub + ->expects($this->any()) + ->method('getCartItems') + ->will($this->returnValue([$cartItem1Stub])); + + $stubFacade->expects($this->any()) + ->method('getCart') + ->will($this->returnValue($cartStub)); + } + + public function testSet() + { + $stubFacade = $this->generateFacadeStub(); + + $coupon = new RemoveAmountOnAttributeValues($stubFacade); + + $date = new \DateTime(); + + $coupon->set( + $stubFacade, + 'TEST', 'TEST Coupon', 'This is a test coupon title', 'This is a test coupon description', + array('amount' => 10.00, 'attribute_avs' => [10, 20]), + true, true, true, true, + 254, + $date->setTimestamp(strtotime("today + 3 months")), + new ObjectCollection(), + new ObjectCollection(), + false + ); + + $condition1 = new MatchForTotalAmount($stubFacade); + $operators = array( + MatchForTotalAmount::CART_TOTAL => Operators::SUPERIOR, + MatchForTotalAmount::CART_CURRENCY => Operators::EQUAL + ); + $values = array( + MatchForTotalAmount::CART_TOTAL => 40.00, + MatchForTotalAmount::CART_CURRENCY => 'EUR' + ); + $condition1->setValidatorsFromForm($operators, $values); + + $condition2 = new MatchForTotalAmount($stubFacade); + $operators = array( + MatchForTotalAmount::CART_TOTAL => Operators::INFERIOR, + MatchForTotalAmount::CART_CURRENCY => Operators::EQUAL + ); + $values = array( + MatchForTotalAmount::CART_TOTAL => 400.00, + MatchForTotalAmount::CART_CURRENCY => 'EUR' + ); + $condition2->setValidatorsFromForm($operators, $values); + + $conditions = new ConditionCollection(); + $conditions[] = $condition1; + $conditions[] = $condition2; + $coupon->setConditions($conditions); + + $this->assertEquals('TEST', $coupon->getCode()); + $this->assertEquals('TEST Coupon', $coupon->getTitle()); + $this->assertEquals('This is a test coupon title', $coupon->getShortDescription()); + $this->assertEquals('This is a test coupon description', $coupon->getDescription()); + + $this->assertEquals(true, $coupon->isCumulative()); + $this->assertEquals(true, $coupon->isRemovingPostage()); + $this->assertEquals(true, $coupon->isAvailableOnSpecialOffers()); + $this->assertEquals(true, $coupon->isEnabled()); + + $this->assertEquals(254, $coupon->getMaxUsage()); + $this->assertEquals($date, $coupon->getExpirationDate()); + } + + public function testMatchOne() + { + $stubFacade = $this->generateFacadeStub(); + + $coupon = new RemoveAmountOnAttributeValues($stubFacade); + + $date = new \DateTime(); + + $coupon->set( + $stubFacade, + 'TEST', 'TEST Coupon', 'This is a test coupon title', 'This is a test coupon description', + array('amount' => 10.00, 'attribute_avs' => [10, 20]), + true, true, true, true, + 254, + $date->setTimestamp(strtotime("today + 3 months")), + new ObjectCollection(), + new ObjectCollection(), + false + ); + + $this->generateMatchingCart($stubFacade, 1); + + $this->assertEquals(10.00, $coupon->exec()); + } + + public function testMatchSeveral() + { + $stubFacade = $this->generateFacadeStub(); + + $coupon = new RemoveAmountOnAttributeValues($stubFacade); + + $date = new \DateTime(); + + $coupon->set( + $stubFacade, + 'TEST', 'TEST Coupon', 'This is a test coupon title', 'This is a test coupon description', + array('amount' => 10.00, 'attribute_avs' => [10, 20]), + true, true, true, true, + 254, + $date->setTimestamp(strtotime("today + 3 months")), + new ObjectCollection(), + new ObjectCollection(), + false + ); + + $this->generateMatchingCart($stubFacade, 2); + + $this->assertEquals(30.00, $coupon->exec()); + } + + public function testNoMatch() + { + $stubFacade = $this->generateFacadeStub(); + + $coupon = new RemoveAmountOnAttributeValues($stubFacade); + + $date = new \DateTime(); + + $coupon->set( + $stubFacade, + 'TEST', 'TEST Coupon', 'This is a test coupon title', 'This is a test coupon description', + array('amount' => 10.00, 'attribute_avs' => [10, 20]), + true, true, true, true, + 254, + $date->setTimestamp(strtotime("today + 3 months")), + new ObjectCollection(), + new ObjectCollection(), + false + ); + + $this->generateNoMatchingCart($stubFacade); + + $this->assertEquals(0.00, $coupon->exec()); + } + + public function testGetName() + { + $stubFacade = $this->generateFacadeStub(399, 'EUR', 'Coupon test name'); + + /** @var FacadeInterface $stubFacade */ + $coupon = new RemoveAmountOnAttributeValues($stubFacade); + + $actual = $coupon->getName(); + $expected = 'Coupon test name'; + $this->assertEquals($expected, $actual); + } + + public function testGetToolTip() + { + $tooltip = 'Coupon test tooltip'; + $stubFacade = $this->generateFacadeStub(399, 'EUR', $tooltip); + + /** @var FacadeInterface $stubFacade */ + $coupon = new RemoveAmountOnAttributeValues($stubFacade); + + $actual = $coupon->getToolTip(); + $expected = $tooltip; + $this->assertEquals($expected, $actual); + } + + /** + * Tears down the fixture, for example, closes a network connection. + * This method is called after a test is executed. + */ + protected function tearDown() + { + } +} diff --git a/core/lib/Thelia/Tests/Coupon/Type/RemoveAmountOnCategoriesTest.php b/core/lib/Thelia/Tests/Coupon/Type/RemoveAmountOnCategoriesTest.php new file mode 100644 index 000000000..01be96bde --- /dev/null +++ b/core/lib/Thelia/Tests/Coupon/Type/RemoveAmountOnCategoriesTest.php @@ -0,0 +1,330 @@ + + */ +class RemoveAmountOnCategoriesTest extends \PHPUnit_Framework_TestCase +{ + + /** + * Sets up the fixture, for example, opens a network connection. + * This method is called before a test is executed. + */ + protected function setUp() + { + } + + /** + * Generate adapter stub + * + * @param int $cartTotalPrice Cart total price + * @param string $checkoutCurrency Checkout currency + * @param string $i18nOutput Output from each translation + * + * @return \PHPUnit_Framework_MockObject_MockObject + */ + public function generateFacadeStub($cartTotalPrice = 400, $checkoutCurrency = 'EUR', $i18nOutput = '') + { + $stubFacade = $this->getMockBuilder('\Thelia\Coupon\BaseFacade') + ->disableOriginalConstructor() + ->getMock(); + + $currencies = CurrencyQuery::create(); + $currencies = $currencies->find(); + $stubFacade->expects($this->any()) + ->method('getAvailableCurrencies') + ->will($this->returnValue($currencies)); + + $stubFacade->expects($this->any()) + ->method('getCartTotalPrice') + ->will($this->returnValue($cartTotalPrice)); + + $stubFacade->expects($this->any()) + ->method('getCheckoutCurrency') + ->will($this->returnValue($checkoutCurrency)); + + $stubFacade->expects($this->any()) + ->method('getConditionEvaluator') + ->will($this->returnValue(new ConditionEvaluator())); + + $stubTranslator = $this->getMockBuilder('\Thelia\Core\Translation\Translator') + ->disableOriginalConstructor() + ->getMock(); + $stubTranslator->expects($this->any()) + ->method('trans') + ->will($this->returnValue($i18nOutput)); + + $stubFacade->expects($this->any()) + ->method('getTranslator') + ->will($this->returnValue($stubTranslator)); + + return $stubFacade; + } + + public function generateMatchingCart(\PHPUnit_Framework_MockObject_MockObject $stubFacade) { + + $category1 = new Category(); + $category1->setId(10); + + $category2 = new Category(); + $category2->setId(20); + + $category3 = new Category(); + $category3->setId(30); + + $product1 = new Product(); + $product1->addCategory($category1)->addCategory($category2); + + $product2 = new Product(); + $product2->addCategory($category3); + + $cartItem1Stub = $this->getMockBuilder('\Thelia\Model\CartItem') + ->disableOriginalConstructor() + ->getMock(); + + $cartItem1Stub + ->expects($this->any()) + ->method('getProduct') + ->will($this->returnValue($product1)) + ; + + $cartItem1Stub + ->expects($this->any()) + ->method('getQuantity') + ->will($this->returnValue(1)) + ; + + $cartItem2Stub = $this->getMockBuilder('\Thelia\Model\CartItem') + ->disableOriginalConstructor() + ->getMock(); + + $cartItem2Stub + ->expects($this->any()) + ->method('getProduct') + ->will($this->returnValue($product2)); + + $cartItem2Stub + ->expects($this->any()) + ->method('getQuantity') + ->will($this->returnValue(2)) + ; + + $cartStub = $this->getMockBuilder('\Thelia\Model\Cart') + ->disableOriginalConstructor() + ->getMock(); + + $cartStub + ->expects($this->any()) + ->method('getCartItems') + ->will($this->returnValue([$cartItem1Stub, $cartItem2Stub])); + + $stubFacade->expects($this->any()) + ->method('getCart') + ->will($this->returnValue($cartStub)); + } + + public function generateNoMatchingCart(\PHPUnit_Framework_MockObject_MockObject $stubFacade) { + + $category3 = new Category(); + $category3->setId(30); + + $product2 = new Product(); + $product2->addCategory($category3); + + $cartItem2Stub = $this->getMockBuilder('\Thelia\Model\CartItem') + ->disableOriginalConstructor() + ->getMock(); + + $cartItem2Stub->expects($this->any()) + ->method('getProduct') + ->will($this->returnValue($product2)); + + $cartItem2Stub->expects($this->any()) + ->method('getQuantity') + ->will($this->returnValue(2)); + + + $cartStub = $this->getMockBuilder('\Thelia\Model\Cart') + ->disableOriginalConstructor() + ->getMock(); + + $cartStub + ->expects($this->any()) + ->method('getCartItems') + ->will($this->returnValue([$cartItem2Stub])); + + $stubFacade->expects($this->any()) + ->method('getCart') + ->will($this->returnValue($cartStub)); + } + + public function testSet() + { + $stubFacade = $this->generateFacadeStub(); + + $coupon = new RemoveAmountOnCategories($stubFacade); + + $date = new \DateTime(); + + $coupon->set( + $stubFacade, + 'TEST', 'TEST Coupon', 'This is a test coupon title', 'This is a test coupon description', + array('amount' => 10.00, 'categories' => [10, 20]), + true, true, true, true, + 254, + $date->setTimestamp(strtotime("today + 3 months")), + new ObjectCollection(), + new ObjectCollection(), + false + ); + + $condition1 = new MatchForTotalAmount($stubFacade); + $operators = array( + MatchForTotalAmount::CART_TOTAL => Operators::SUPERIOR, + MatchForTotalAmount::CART_CURRENCY => Operators::EQUAL + ); + $values = array( + MatchForTotalAmount::CART_TOTAL => 40.00, + MatchForTotalAmount::CART_CURRENCY => 'EUR' + ); + $condition1->setValidatorsFromForm($operators, $values); + + $condition2 = new MatchForTotalAmount($stubFacade); + $operators = array( + MatchForTotalAmount::CART_TOTAL => Operators::INFERIOR, + MatchForTotalAmount::CART_CURRENCY => Operators::EQUAL + ); + $values = array( + MatchForTotalAmount::CART_TOTAL => 400.00, + MatchForTotalAmount::CART_CURRENCY => 'EUR' + ); + $condition2->setValidatorsFromForm($operators, $values); + + $conditions = new ConditionCollection(); + $conditions[] = $condition1; + $conditions[] = $condition2; + $coupon->setConditions($conditions); + + $this->assertEquals('TEST', $coupon->getCode()); + $this->assertEquals('TEST Coupon', $coupon->getTitle()); + $this->assertEquals('This is a test coupon title', $coupon->getShortDescription()); + $this->assertEquals('This is a test coupon description', $coupon->getDescription()); + + $this->assertEquals(true, $coupon->isCumulative()); + $this->assertEquals(true, $coupon->isRemovingPostage()); + $this->assertEquals(true, $coupon->isAvailableOnSpecialOffers()); + $this->assertEquals(true, $coupon->isEnabled()); + + $this->assertEquals(254, $coupon->getMaxUsage()); + $this->assertEquals($date, $coupon->getExpirationDate()); + + $this->generateMatchingCart($stubFacade); + + $this->assertEquals(10.00, $coupon->exec()); + } + + public function testMatch() + { + $stubFacade = $this->generateFacadeStub(); + + $coupon = new RemoveAmountOnCategories($stubFacade); + + $date = new \DateTime(); + + $coupon->set( + $stubFacade, + 'TEST', 'TEST Coupon', 'This is a test coupon title', 'This is a test coupon description', + array('amount' => 10.00, 'categories' => [10, 20]), + true, true, true, true, + 254, + $date->setTimestamp(strtotime("today + 3 months")), + new ObjectCollection(), + new ObjectCollection(), + false + ); + + $this->generateMatchingCart($stubFacade); + + $this->assertEquals(10.00, $coupon->exec()); + } + + public function testNoMatch() + { + $stubFacade = $this->generateFacadeStub(); + + $coupon = new RemoveAmountOnCategories($stubFacade); + + $date = new \DateTime(); + + $coupon->set( + $stubFacade, + 'TEST', 'TEST Coupon', 'This is a test coupon title', 'This is a test coupon description', + array('amount' => 10.00, 'categories' => [10, 20]), + true, true, true, true, + 254, + $date->setTimestamp(strtotime("today + 3 months")), + new ObjectCollection(), + new ObjectCollection(), + false + ); + + $this->generateNoMatchingCart($stubFacade); + + $this->assertEquals(0.00, $coupon->exec()); + } + + public function testGetName() + { + $stubFacade = $this->generateFacadeStub(399, 'EUR', 'Coupon test name'); + + /** @var FacadeInterface $stubFacade */ + $coupon = new RemoveAmountOnCategories($stubFacade); + + $actual = $coupon->getName(); + $expected = 'Coupon test name'; + $this->assertEquals($expected, $actual); + } + + public function testGetToolTip() + { + $tooltip = 'Coupon test tooltip'; + $stubFacade = $this->generateFacadeStub(399, 'EUR', $tooltip); + + /** @var FacadeInterface $stubFacade */ + $coupon = new RemoveAmountOnCategories($stubFacade); + + $actual = $coupon->getToolTip(); + $expected = $tooltip; + $this->assertEquals($expected, $actual); + } + + /** + * Tears down the fixture, for example, closes a network connection. + * This method is called after a test is executed. + */ + protected function tearDown() + { + } +} diff --git a/core/lib/Thelia/Tests/Coupon/Type/RemoveAmountOnProductsTest.php b/core/lib/Thelia/Tests/Coupon/Type/RemoveAmountOnProductsTest.php new file mode 100644 index 000000000..55e64f861 --- /dev/null +++ b/core/lib/Thelia/Tests/Coupon/Type/RemoveAmountOnProductsTest.php @@ -0,0 +1,343 @@ + + */ +class RemoveAmountOnProductsTest extends \PHPUnit_Framework_TestCase +{ + + /** + * Sets up the fixture, for example, opens a network connection. + * This method is called before a test is executed. + */ + protected function setUp() + { + } + + /** + * Generate adapter stub + * + * @param int $cartTotalPrice Cart total price + * @param string $checkoutCurrency Checkout currency + * @param string $i18nOutput Output from each translation + * + * @return \PHPUnit_Framework_MockObject_MockObject + */ + public function generateFacadeStub($cartTotalPrice = 400, $checkoutCurrency = 'EUR', $i18nOutput = '') + { + $stubFacade = $this->getMockBuilder('\Thelia\Coupon\BaseFacade') + ->disableOriginalConstructor() + ->getMock(); + + $currencies = CurrencyQuery::create(); + $currencies = $currencies->find(); + $stubFacade->expects($this->any()) + ->method('getAvailableCurrencies') + ->will($this->returnValue($currencies)); + + $stubFacade->expects($this->any()) + ->method('getCartTotalPrice') + ->will($this->returnValue($cartTotalPrice)); + + $stubFacade->expects($this->any()) + ->method('getCheckoutCurrency') + ->will($this->returnValue($checkoutCurrency)); + + $stubFacade->expects($this->any()) + ->method('getConditionEvaluator') + ->will($this->returnValue(new ConditionEvaluator())); + + $stubTranslator = $this->getMockBuilder('\Thelia\Core\Translation\Translator') + ->disableOriginalConstructor() + ->getMock(); + $stubTranslator->expects($this->any()) + ->method('trans') + ->will($this->returnValue($i18nOutput)); + + $stubFacade->expects($this->any()) + ->method('getTranslator') + ->will($this->returnValue($stubTranslator)); + + return $stubFacade; + } + + public function generateMatchingCart(\PHPUnit_Framework_MockObject_MockObject $stubFacade, $count) { + + $product1 = new Product(); + $product1->setId(10); + + $product2 = new Product(); + $product2->setId(20); + + $cartItem1Stub = $this->getMockBuilder('\Thelia\Model\CartItem') + ->disableOriginalConstructor() + ->getMock(); + + $cartItem1Stub + ->expects($this->any()) + ->method('getProduct') + ->will($this->returnValue($product1)) + ; + + $cartItem1Stub + ->expects($this->any()) + ->method('getQuantity') + ->will($this->returnValue(1)) + ; + + $cartItem2Stub = $this->getMockBuilder('\Thelia\Model\CartItem') + ->disableOriginalConstructor() + ->getMock(); + + $cartItem2Stub + ->expects($this->any()) + ->method('getProduct') + ->will($this->returnValue($product2)); + + $cartItem2Stub + ->expects($this->any()) + ->method('getQuantity') + ->will($this->returnValue(2)) + ; + + $cartStub = $this->getMockBuilder('\Thelia\Model\Cart') + ->disableOriginalConstructor() + ->getMock(); + + if ($count == 1) + $ret = [$cartItem1Stub]; + else + $ret = [$cartItem1Stub, $cartItem2Stub]; + + $cartStub + ->expects($this->any()) + ->method('getCartItems') + ->will($this->returnValue($ret)); + + $stubFacade->expects($this->any()) + ->method('getCart') + ->will($this->returnValue($cartStub)); + } + + public function generateNoMatchingCart(\PHPUnit_Framework_MockObject_MockObject $stubFacade) { + + $product2 = new Product(); + $product2->setId(30); + + $cartItem2Stub = $this->getMockBuilder('\Thelia\Model\CartItem') + ->disableOriginalConstructor() + ->getMock(); + + $cartItem2Stub->expects($this->any()) + ->method('getProduct') + ->will($this->returnValue($product2)); + + $cartItem2Stub->expects($this->any()) + ->method('getQuantity') + ->will($this->returnValue(2)); + + + $cartStub = $this->getMockBuilder('\Thelia\Model\Cart') + ->disableOriginalConstructor() + ->getMock(); + + $cartStub + ->expects($this->any()) + ->method('getCartItems') + ->will($this->returnValue([$cartItem2Stub])); + + $stubFacade->expects($this->any()) + ->method('getCart') + ->will($this->returnValue($cartStub)); + } + + public function testSet() + { + $stubFacade = $this->generateFacadeStub(); + + $coupon = new RemoveAmountOnProducts($stubFacade); + + $date = new \DateTime(); + + $coupon->set( + $stubFacade, + 'TEST', 'TEST Coupon', 'This is a test coupon title', 'This is a test coupon description', + array('amount' => 10.00, 'products' => [10, 20]), + true, true, true, true, + 254, + $date->setTimestamp(strtotime("today + 3 months")), + new ObjectCollection(), + new ObjectCollection(), + false + ); + + $condition1 = new MatchForTotalAmount($stubFacade); + $operators = array( + MatchForTotalAmount::CART_TOTAL => Operators::SUPERIOR, + MatchForTotalAmount::CART_CURRENCY => Operators::EQUAL + ); + $values = array( + MatchForTotalAmount::CART_TOTAL => 40.00, + MatchForTotalAmount::CART_CURRENCY => 'EUR' + ); + $condition1->setValidatorsFromForm($operators, $values); + + $condition2 = new MatchForTotalAmount($stubFacade); + $operators = array( + MatchForTotalAmount::CART_TOTAL => Operators::INFERIOR, + MatchForTotalAmount::CART_CURRENCY => Operators::EQUAL + ); + $values = array( + MatchForTotalAmount::CART_TOTAL => 400.00, + MatchForTotalAmount::CART_CURRENCY => 'EUR' + ); + $condition2->setValidatorsFromForm($operators, $values); + + $conditions = new ConditionCollection(); + $conditions[] = $condition1; + $conditions[] = $condition2; + $coupon->setConditions($conditions); + + $this->assertEquals('TEST', $coupon->getCode()); + $this->assertEquals('TEST Coupon', $coupon->getTitle()); + $this->assertEquals('This is a test coupon title', $coupon->getShortDescription()); + $this->assertEquals('This is a test coupon description', $coupon->getDescription()); + + $this->assertEquals(true, $coupon->isCumulative()); + $this->assertEquals(true, $coupon->isRemovingPostage()); + $this->assertEquals(true, $coupon->isAvailableOnSpecialOffers()); + $this->assertEquals(true, $coupon->isEnabled()); + + $this->assertEquals(254, $coupon->getMaxUsage()); + $this->assertEquals($date, $coupon->getExpirationDate()); + } + + public function testMatchOne() + { + $stubFacade = $this->generateFacadeStub(); + + $coupon = new RemoveAmountOnProducts($stubFacade); + + $date = new \DateTime(); + + $coupon->set( + $stubFacade, + 'TEST', 'TEST Coupon', 'This is a test coupon title', 'This is a test coupon description', + array('amount' => 10.00, 'products' => [10, 20]), + true, true, true, true, + 254, + $date->setTimestamp(strtotime("today + 3 months")), + new ObjectCollection(), + new ObjectCollection(), + false + ); + + $this->generateMatchingCart($stubFacade, 1); + + $this->assertEquals(10.00, $coupon->exec()); + } + + public function testMatchSeveral() + { + $stubFacade = $this->generateFacadeStub(); + + $coupon = new RemoveAmountOnProducts($stubFacade); + + $date = new \DateTime(); + + $coupon->set( + $stubFacade, + 'TEST', 'TEST Coupon', 'This is a test coupon title', 'This is a test coupon description', + array('amount' => 10.00, 'products' => [10, 20]), + true, true, true, true, + 254, + $date->setTimestamp(strtotime("today + 3 months")), + new ObjectCollection(), + new ObjectCollection(), + false + ); + + $this->generateMatchingCart($stubFacade, 2); + + $this->assertEquals(30.00, $coupon->exec()); + } + + public function testNoMatch() + { + $stubFacade = $this->generateFacadeStub(); + + $coupon = new RemoveAmountOnProducts($stubFacade); + + $date = new \DateTime(); + + $coupon->set( + $stubFacade, + 'TEST', 'TEST Coupon', 'This is a test coupon title', 'This is a test coupon description', + array('amount' => 10.00, 'products' => [10, 20]), + true, true, true, true, + 254, + $date->setTimestamp(strtotime("today + 3 months")), + new ObjectCollection(), + new ObjectCollection(), + false + ); + + $this->generateNoMatchingCart($stubFacade); + + $this->assertEquals(0.00, $coupon->exec()); + } + + public function testGetName() + { + $stubFacade = $this->generateFacadeStub(399, 'EUR', 'Coupon test name'); + + /** @var FacadeInterface $stubFacade */ + $coupon = new RemoveAmountOnProducts($stubFacade); + + $actual = $coupon->getName(); + $expected = 'Coupon test name'; + $this->assertEquals($expected, $actual); + } + + public function testGetToolTip() + { + $tooltip = 'Coupon test tooltip'; + $stubFacade = $this->generateFacadeStub(399, 'EUR', $tooltip); + + /** @var FacadeInterface $stubFacade */ + $coupon = new RemoveAmountOnProducts($stubFacade); + + $actual = $coupon->getToolTip(); + $expected = $tooltip; + $this->assertEquals($expected, $actual); + } + + /** + * Tears down the fixture, for example, closes a network connection. + * This method is called after a test is executed. + */ + protected function tearDown() + { + } +} diff --git a/core/lib/Thelia/Tests/Coupon/Type/RemovePercentageOnAttributeValuesTest.php b/core/lib/Thelia/Tests/Coupon/Type/RemovePercentageOnAttributeValuesTest.php new file mode 100644 index 000000000..eaa5e4de9 --- /dev/null +++ b/core/lib/Thelia/Tests/Coupon/Type/RemovePercentageOnAttributeValuesTest.php @@ -0,0 +1,412 @@ + + */ +class RemovePercentageOnAttributeValuesTest extends \PHPUnit_Framework_TestCase +{ + /** + * Sets up the fixture, for example, opens a network connection. + * This method is called before a test is executed. + */ + protected function setUp() + { + } + + /** + * Generate adapter stub + * + * @param int $cartTotalPrice Cart total price + * @param string $checkoutCurrency Checkout currency + * @param string $i18nOutput Output from each translation + * + * @return \PHPUnit_Framework_MockObject_MockObject + */ + public function generateFacadeStub($cartTotalPrice = 400, $checkoutCurrency = 'EUR', $i18nOutput = '') + { + $stubFacade = $this->getMockBuilder('\Thelia\Coupon\BaseFacade') + ->disableOriginalConstructor() + ->getMock(); + + $currencies = CurrencyQuery::create(); + $currencies = $currencies->find(); + $stubFacade->expects($this->any()) + ->method('getAvailableCurrencies') + ->will($this->returnValue($currencies)); + + $stubFacade->expects($this->any()) + ->method('getCartTotalPrice') + ->will($this->returnValue($cartTotalPrice)); + + $stubFacade->expects($this->any()) + ->method('getCheckoutCurrency') + ->will($this->returnValue($checkoutCurrency)); + + $stubFacade->expects($this->any()) + ->method('getConditionEvaluator') + ->will($this->returnValue(new ConditionEvaluator())); + + $stubTranslator = $this->getMockBuilder('\Thelia\Core\Translation\Translator') + ->disableOriginalConstructor() + ->getMock(); + $stubTranslator->expects($this->any()) + ->method('trans') + ->will($this->returnValue($i18nOutput)); + + $stubFacade->expects($this->any()) + ->method('getTranslator') + ->will($this->returnValue($stubTranslator)); + + return $stubFacade; + } + + public function generateMatchingCart(\PHPUnit_Framework_MockObject_MockObject $stubFacade, $count) { + + $attrCombination1 = $this->getMockBuilder('\Thelia\Model\AttributeCombination') + ->disableOriginalConstructor() + ->getMock() + ; + + $attrCombination1 + ->expects($this->any()) + ->method('getAttributeAvId') + ->will($this->returnValue(10)) + ; + + $attrCombination2 = $this->getMockBuilder('\Thelia\Model\AttributeCombination') + ->disableOriginalConstructor() + ->getMock() + ; + + $attrCombination2 + ->expects($this->any()) + ->method('getAttributeAvId') + ->will($this->returnValue(20)) + ; + + $pse1 = $this->getMockBuilder('\Thelia\Model\ProductSaleElements') + ->disableOriginalConstructor() + ->getMock() + ; + $pse1 + ->expects($this->any()) + ->method('getAttributeCombinations') + ->will($this->returnValue([$attrCombination1])) + ; + + $pse2 = $this->getMockBuilder('\Thelia\Model\ProductSaleElements') + ->disableOriginalConstructor() + ->getMock(); + ; + $pse2 + ->expects($this->any()) + ->method('getAttributeCombinations') + ->will($this->returnValue([$attrCombination1, $attrCombination2])) + ; + + $cartItem1Stub = $this->getMockBuilder('\Thelia\Model\CartItem') + ->disableOriginalConstructor() + ->getMock() + ; + $cartItem1Stub + ->expects($this->any()) + ->method('getProductSaleElements') + ->will($this->returnValue($pse1)) + ; + $cartItem1Stub + ->expects($this->any()) + ->method('getQuantity') + ->will($this->returnValue(1)) + ; + $cartItem1Stub + ->expects($this->any()) + ->method('getPrice') + ->will($this->returnValue(100)) + ; + + + $cartItem2Stub = $this->getMockBuilder('\Thelia\Model\CartItem') + ->disableOriginalConstructor() + ->getMock() + ; + $cartItem2Stub + ->expects($this->any()) + ->method('getProductSaleElements') + ->will($this->returnValue($pse2)) + ; + $cartItem2Stub + ->expects($this->any()) + ->method('getQuantity') + ->will($this->returnValue(2)) + ; + $cartItem2Stub + ->expects($this->any()) + ->method('getPrice') + ->will($this->returnValue(150)) + ; + + $cartStub = $this->getMockBuilder('\Thelia\Model\Cart') + ->disableOriginalConstructor() + ->getMock(); + + if ($count == 1) + $ret = [$cartItem1Stub]; + else + $ret = [$cartItem1Stub, $cartItem2Stub]; + + $cartStub + ->expects($this->any()) + ->method('getCartItems') + ->will($this->returnValue($ret)); + + $stubFacade->expects($this->any()) + ->method('getCart') + ->will($this->returnValue($cartStub)); + } + + public function generateNoMatchingCart(\PHPUnit_Framework_MockObject_MockObject $stubFacade) { + + $attrCombination1 = $this->getMockBuilder('\Thelia\Model\AttributeCombination') + ->disableOriginalConstructor() + ->getMock() + ; + + $attrCombination1 + ->expects($this->any()) + ->method('getAttributeAvId') + ->will($this->returnValue(30)) + ; + + $pse1 = $this->getMockBuilder('\Thelia\Model\ProductSaleElements') + ->disableOriginalConstructor() + ->getMock() + ; + $pse1 + ->expects($this->any()) + ->method('getAttributeCombinations') + ->will($this->returnValue([$attrCombination1])) + ; + + $cartItem1Stub = $this->getMockBuilder('\Thelia\Model\CartItem') + ->disableOriginalConstructor() + ->getMock() + ; + $cartItem1Stub + ->expects($this->any()) + ->method('getProductSaleElements') + ->will($this->returnValue($pse1)) + ; + $cartItem1Stub + ->expects($this->any()) + ->method('getQuantity') + ->will($this->returnValue(1)) + ; + $cartItem1Stub + ->expects($this->any()) + ->method('getPrice') + ->will($this->returnValue(100)) + ; + + $cartStub = $this->getMockBuilder('\Thelia\Model\Cart') + ->disableOriginalConstructor() + ->getMock(); + + $cartStub + ->expects($this->any()) + ->method('getCartItems') + ->will($this->returnValue([$cartItem1Stub])); + + $stubFacade->expects($this->any()) + ->method('getCart') + ->will($this->returnValue($cartStub)); + } + + public function testSet() + { + $stubFacade = $this->generateFacadeStub(); + + $coupon = new RemovePercentageOnAttributeValues($stubFacade); + + $date = new \DateTime(); + + $coupon->set( + $stubFacade, + 'TEST', 'TEST Coupon', 'This is a test coupon title', 'This is a test coupon description', + array('percentage' => 10.00, 'attribute_avs' => [10, 20]), + true, true, true, true, + 254, + $date->setTimestamp(strtotime("today + 3 months")), + new ObjectCollection(), + new ObjectCollection(), + false + ); + + $condition1 = new MatchForTotalAmount($stubFacade); + $operators = array( + MatchForTotalAmount::CART_TOTAL => Operators::SUPERIOR, + MatchForTotalAmount::CART_CURRENCY => Operators::EQUAL + ); + $values = array( + MatchForTotalAmount::CART_TOTAL => 40.00, + MatchForTotalAmount::CART_CURRENCY => 'EUR' + ); + $condition1->setValidatorsFromForm($operators, $values); + + $condition2 = new MatchForTotalAmount($stubFacade); + $operators = array( + MatchForTotalAmount::CART_TOTAL => Operators::INFERIOR, + MatchForTotalAmount::CART_CURRENCY => Operators::EQUAL + ); + $values = array( + MatchForTotalAmount::CART_TOTAL => 400.00, + MatchForTotalAmount::CART_CURRENCY => 'EUR' + ); + $condition2->setValidatorsFromForm($operators, $values); + + $conditions = new ConditionCollection(); + $conditions[] = $condition1; + $conditions[] = $condition2; + $coupon->setConditions($conditions); + + $this->assertEquals('TEST', $coupon->getCode()); + $this->assertEquals('TEST Coupon', $coupon->getTitle()); + $this->assertEquals('This is a test coupon title', $coupon->getShortDescription()); + $this->assertEquals('This is a test coupon description', $coupon->getDescription()); + + $this->assertEquals(true, $coupon->isCumulative()); + $this->assertEquals(true, $coupon->isRemovingPostage()); + $this->assertEquals(true, $coupon->isAvailableOnSpecialOffers()); + $this->assertEquals(true, $coupon->isEnabled()); + + $this->assertEquals(254, $coupon->getMaxUsage()); + $this->assertEquals($date, $coupon->getExpirationDate()); + } + + public function testMatchOne() + { + $stubFacade = $this->generateFacadeStub(); + + $coupon = new RemovePercentageOnAttributeValues($stubFacade); + + $date = new \DateTime(); + + $coupon->set( + $stubFacade, + 'TEST', 'TEST Coupon', 'This is a test coupon title', 'This is a test coupon description', + array('percentage' => 10.00, 'attribute_avs' => [10, 20]), + true, true, true, true, + 254, + $date->setTimestamp(strtotime("today + 3 months")), + new ObjectCollection(), + new ObjectCollection(), + false + ); + + $this->generateMatchingCart($stubFacade, 1); + + $this->assertEquals(10.00, $coupon->exec()); + } + + public function testMatchSeveral() + { + $stubFacade = $this->generateFacadeStub(); + + $coupon = new RemovePercentageOnAttributeValues($stubFacade); + + $date = new \DateTime(); + + $coupon->set( + $stubFacade, + 'TEST', 'TEST Coupon', 'This is a test coupon title', 'This is a test coupon description', + array('percentage' => 10.00, 'attribute_avs' => [10, 20]), + true, true, true, true, + 254, + $date->setTimestamp(strtotime("today + 3 months")), + new ObjectCollection(), + new ObjectCollection(), + false + ); + + $this->generateMatchingCart($stubFacade, 2); + + $this->assertEquals(40.00, $coupon->exec()); + } + + public function testNoMatch() + { + $stubFacade = $this->generateFacadeStub(); + + $coupon = new RemovePercentageOnAttributeValues($stubFacade); + + $date = new \DateTime(); + + $coupon->set( + $stubFacade, + 'TEST', 'TEST Coupon', 'This is a test coupon title', 'This is a test coupon description', + array('percentage' => 10.00, 'attribute_avs' => [10, 20]), + true, true, true, true, + 254, + $date->setTimestamp(strtotime("today + 3 months")), + new ObjectCollection(), + new ObjectCollection(), + false + ); + + $this->generateNoMatchingCart($stubFacade); + + $this->assertEquals(0.00, $coupon->exec()); + } + + public function testGetName() + { + $stubFacade = $this->generateFacadeStub(399, 'EUR', 'Coupon test name'); + + /** @var FacadeInterface $stubFacade */ + $coupon = new RemovePercentageOnAttributeValues($stubFacade); + + $actual = $coupon->getName(); + $expected = 'Coupon test name'; + $this->assertEquals($expected, $actual); + } + + public function testGetToolTip() + { + $tooltip = 'Coupon test tooltip'; + $stubFacade = $this->generateFacadeStub(399, 'EUR', $tooltip); + + /** @var FacadeInterface $stubFacade */ + $coupon = new RemovePercentageOnAttributeValues($stubFacade); + + $actual = $coupon->getToolTip(); + $expected = $tooltip; + $this->assertEquals($expected, $actual); + } + + /** + * Tears down the fixture, for example, closes a network connection. + * This method is called after a test is executed. + */ + protected function tearDown() + { + } +} diff --git a/core/lib/Thelia/Tests/Coupon/Type/RemovePercentageOnCategoriesTest.php b/core/lib/Thelia/Tests/Coupon/Type/RemovePercentageOnCategoriesTest.php new file mode 100644 index 000000000..90b845531 --- /dev/null +++ b/core/lib/Thelia/Tests/Coupon/Type/RemovePercentageOnCategoriesTest.php @@ -0,0 +1,346 @@ + + */ +class RemovePercentageOnCategoriesTest extends \PHPUnit_Framework_TestCase +{ + + /** + * Sets up the fixture, for example, opens a network connection. + * This method is called before a test is executed. + */ + protected function setUp() + { + } + + /** + * Generate adapter stub + * + * @param int $cartTotalPrice Cart total price + * @param string $checkoutCurrency Checkout currency + * @param string $i18nOutput Output from each translation + * + * @return \PHPUnit_Framework_MockObject_MockObject + */ + public function generateFacadeStub($cartTotalPrice = 400, $checkoutCurrency = 'EUR', $i18nOutput = '') + { + $stubFacade = $this->getMockBuilder('\Thelia\Coupon\BaseFacade') + ->disableOriginalConstructor() + ->getMock(); + + $currencies = CurrencyQuery::create(); + $currencies = $currencies->find(); + $stubFacade->expects($this->any()) + ->method('getAvailableCurrencies') + ->will($this->returnValue($currencies)); + + $stubFacade->expects($this->any()) + ->method('getCartTotalPrice') + ->will($this->returnValue($cartTotalPrice)); + + $stubFacade->expects($this->any()) + ->method('getCheckoutCurrency') + ->will($this->returnValue($checkoutCurrency)); + + $stubFacade->expects($this->any()) + ->method('getConditionEvaluator') + ->will($this->returnValue(new ConditionEvaluator())); + + $stubTranslator = $this->getMockBuilder('\Thelia\Core\Translation\Translator') + ->disableOriginalConstructor() + ->getMock(); + $stubTranslator->expects($this->any()) + ->method('trans') + ->will($this->returnValue($i18nOutput)); + + $stubFacade->expects($this->any()) + ->method('getTranslator') + ->will($this->returnValue($stubTranslator)); + + return $stubFacade; + } + + public function generateMatchingCart(\PHPUnit_Framework_MockObject_MockObject $stubFacade) { + + $category1 = new Category(); + $category1->setId(10); + + $category2 = new Category(); + $category2->setId(20); + + $category3 = new Category(); + $category3->setId(30); + + $product1 = new Product(); + $product1->addCategory($category1)->addCategory($category2); + + $product2 = new Product(); + $product2->addCategory($category3); + + $cartItem1Stub = $this->getMockBuilder('\Thelia\Model\CartItem') + ->disableOriginalConstructor() + ->getMock(); + + $cartItem1Stub + ->expects($this->any()) + ->method('getProduct') + ->will($this->returnValue($product1)) + ; + $cartItem1Stub + ->expects($this->any()) + ->method('getQuantity') + ->will($this->returnValue(1)) + ; + $cartItem1Stub + ->expects($this->any()) + ->method('getPrice') + ->will($this->returnValue(100)) + ; + + $cartItem2Stub = $this->getMockBuilder('\Thelia\Model\CartItem') + ->disableOriginalConstructor() + ->getMock(); + + $cartItem2Stub + ->expects($this->any()) + ->method('getProduct') + ->will($this->returnValue($product2)) + ; + $cartItem2Stub + ->expects($this->any()) + ->method('getQuantity') + ->will($this->returnValue(2)) + ; + $cartItem2Stub + ->expects($this->any()) + ->method('getPrice') + ->will($this->returnValue(200)) + ; + + $cartStub = $this->getMockBuilder('\Thelia\Model\Cart') + ->disableOriginalConstructor() + ->getMock(); + + $cartStub + ->expects($this->any()) + ->method('getCartItems') + ->will($this->returnValue([$cartItem1Stub, $cartItem2Stub])); + + $stubFacade->expects($this->any()) + ->method('getCart') + ->will($this->returnValue($cartStub)); + } + + public function generateNoMatchingCart(\PHPUnit_Framework_MockObject_MockObject $stubFacade) { + + $category3 = new Category(); + $category3->setId(30); + + $product2 = new Product(); + $product2->addCategory($category3); + + $cartItem2Stub = $this->getMockBuilder('\Thelia\Model\CartItem') + ->disableOriginalConstructor() + ->getMock(); + + $cartItem2Stub->expects($this->any()) + ->method('getProduct') + ->will($this->returnValue($product2)); + + $cartItem2Stub->expects($this->any()) + ->method('getQuantity') + ->will($this->returnValue(2)); + + $cartItem2Stub + ->expects($this->any()) + ->method('getPrice') + ->will($this->returnValue(200000)) + ; + + $cartStub = $this->getMockBuilder('\Thelia\Model\Cart') + ->disableOriginalConstructor() + ->getMock(); + + $cartStub + ->expects($this->any()) + ->method('getCartItems') + ->will($this->returnValue([$cartItem2Stub])); + + $stubFacade->expects($this->any()) + ->method('getCart') + ->will($this->returnValue($cartStub)); + } + + public function testSet() + { + $stubFacade = $this->generateFacadeStub(); + + $coupon = new RemovePercentageOnCategories($stubFacade); + + $date = new \DateTime(); + + $coupon->set( + $stubFacade, + 'TEST', 'TEST Coupon', 'This is a test coupon title', 'This is a test coupon description', + array('percentage' => 10, 'categories' => [10, 20]), + true, true, true, true, + 254, + $date->setTimestamp(strtotime("today + 3 months")), + new ObjectCollection(), + new ObjectCollection(), + false + ); + + $condition1 = new MatchForTotalAmount($stubFacade); + $operators = array( + MatchForTotalAmount::CART_TOTAL => Operators::SUPERIOR, + MatchForTotalAmount::CART_CURRENCY => Operators::EQUAL + ); + $values = array( + MatchForTotalAmount::CART_TOTAL => 40.00, + MatchForTotalAmount::CART_CURRENCY => 'EUR' + ); + $condition1->setValidatorsFromForm($operators, $values); + + $condition2 = new MatchForTotalAmount($stubFacade); + $operators = array( + MatchForTotalAmount::CART_TOTAL => Operators::INFERIOR, + MatchForTotalAmount::CART_CURRENCY => Operators::EQUAL + ); + $values = array( + MatchForTotalAmount::CART_TOTAL => 400.00, + MatchForTotalAmount::CART_CURRENCY => 'EUR' + ); + $condition2->setValidatorsFromForm($operators, $values); + + $conditions = new ConditionCollection(); + $conditions[] = $condition1; + $conditions[] = $condition2; + $coupon->setConditions($conditions); + + $this->assertEquals('TEST', $coupon->getCode()); + $this->assertEquals('TEST Coupon', $coupon->getTitle()); + $this->assertEquals('This is a test coupon title', $coupon->getShortDescription()); + $this->assertEquals('This is a test coupon description', $coupon->getDescription()); + + $this->assertEquals(true, $coupon->isCumulative()); + $this->assertEquals(true, $coupon->isRemovingPostage()); + $this->assertEquals(true, $coupon->isAvailableOnSpecialOffers()); + $this->assertEquals(true, $coupon->isEnabled()); + + $this->assertEquals(254, $coupon->getMaxUsage()); + $this->assertEquals($date, $coupon->getExpirationDate()); + } + + public function testMatch() + { + $stubFacade = $this->generateFacadeStub(); + + $coupon = new RemovePercentageOnCategories($stubFacade); + + $date = new \DateTime(); + + $coupon->set( + $stubFacade, + 'TEST', 'TEST Coupon', 'This is a test coupon title', 'This is a test coupon description', + array('percentage' => 10, 'categories' => [10, 20]), + true, true, true, true, + 254, + $date->setTimestamp(strtotime("today + 3 months")), + new ObjectCollection(), + new ObjectCollection(), + false + ); + + $this->generateMatchingCart($stubFacade); + + $this->assertEquals(10.00, $coupon->exec()); + } + + public function testNoMatch() + { + $stubFacade = $this->generateFacadeStub(); + + $coupon = new RemovePercentageOnCategories($stubFacade); + + $date = new \DateTime(); + + $coupon->set( + $stubFacade, + 'TEST', 'TEST Coupon', 'This is a test coupon title', 'This is a test coupon description', + array('percentage' => 10, 'categories' => [10, 20]), + true, true, true, true, + 254, + $date->setTimestamp(strtotime("today + 3 months")), + new ObjectCollection(), + new ObjectCollection(), + false + ); + + $this->generateNoMatchingCart($stubFacade); + + $this->assertEquals(0.00, $coupon->exec()); + } + + /** + * @covers Thelia\Coupon\Type\RemoveXAmount::getName + */ + public function testGetName() + { + $stubFacade = $this->generateFacadeStub(399, 'EUR', 'Coupon test name'); + + /** @var FacadeInterface $stubFacade */ + $coupon = new RemovePercentageOnCategories($stubFacade); + + $actual = $coupon->getName(); + $expected = 'Coupon test name'; + $this->assertEquals($expected, $actual); + } + + /** + * @covers Thelia\Coupon\Type\RemoveXAmount::getToolTip + */ + public function testGetToolTip() + { + $tooltip = 'Coupon test tooltip'; + $stubFacade = $this->generateFacadeStub(399, 'EUR', $tooltip); + + /** @var FacadeInterface $stubFacade */ + $coupon = new RemovePercentageOnCategories($stubFacade); + + $actual = $coupon->getToolTip(); + $expected = $tooltip; + $this->assertEquals($expected, $actual); + } + + /** + * Tears down the fixture, for example, closes a network connection. + * This method is called after a test is executed. + */ + protected function tearDown() + { + } +} diff --git a/core/lib/Thelia/Tests/Coupon/Type/RemovePercentageOnProductsTest.php b/core/lib/Thelia/Tests/Coupon/Type/RemovePercentageOnProductsTest.php new file mode 100644 index 000000000..4c150b969 --- /dev/null +++ b/core/lib/Thelia/Tests/Coupon/Type/RemovePercentageOnProductsTest.php @@ -0,0 +1,360 @@ + + */ +class RemovePercentageOnProductsTest extends \PHPUnit_Framework_TestCase +{ + + /** + * Sets up the fixture, for example, opens a network connection. + * This method is called before a test is executed. + */ + protected function setUp() + { + } + + /** + * Generate adapter stub + * + * @param int $cartTotalPrice Cart total price + * @param string $checkoutCurrency Checkout currency + * @param string $i18nOutput Output from each translation + * + * @return \PHPUnit_Framework_MockObject_MockObject + */ + public function generateFacadeStub($cartTotalPrice = 400, $checkoutCurrency = 'EUR', $i18nOutput = '') + { + $stubFacade = $this->getMockBuilder('\Thelia\Coupon\BaseFacade') + ->disableOriginalConstructor() + ->getMock(); + + $currencies = CurrencyQuery::create(); + $currencies = $currencies->find(); + $stubFacade->expects($this->any()) + ->method('getAvailableCurrencies') + ->will($this->returnValue($currencies)); + + $stubFacade->expects($this->any()) + ->method('getCartTotalPrice') + ->will($this->returnValue($cartTotalPrice)); + + $stubFacade->expects($this->any()) + ->method('getCheckoutCurrency') + ->will($this->returnValue($checkoutCurrency)); + + $stubFacade->expects($this->any()) + ->method('getConditionEvaluator') + ->will($this->returnValue(new ConditionEvaluator())); + + $stubTranslator = $this->getMockBuilder('\Thelia\Core\Translation\Translator') + ->disableOriginalConstructor() + ->getMock(); + $stubTranslator->expects($this->any()) + ->method('trans') + ->will($this->returnValue($i18nOutput)); + + $stubFacade->expects($this->any()) + ->method('getTranslator') + ->will($this->returnValue($stubTranslator)); + + return $stubFacade; + } + + public function generateMatchingCart(\PHPUnit_Framework_MockObject_MockObject $stubFacade, $count) { + + $product1 = new Product(); + $product1->setId(10); + + $product2 = new Product(); + $product2->setId(20); + + $cartItem1Stub = $this->getMockBuilder('\Thelia\Model\CartItem') + ->disableOriginalConstructor() + ->getMock(); + + $cartItem1Stub + ->expects($this->any()) + ->method('getProduct') + ->will($this->returnValue($product1)) + ; + + $cartItem1Stub + ->expects($this->any()) + ->method('getQuantity') + ->will($this->returnValue(1)) + ; + $cartItem1Stub + ->expects($this->any()) + ->method('getPrice') + ->will($this->returnValue(100)) + + ; + + $cartItem2Stub = $this->getMockBuilder('\Thelia\Model\CartItem') + ->disableOriginalConstructor() + ->getMock(); + + $cartItem2Stub + ->expects($this->any()) + ->method('getProduct') + ->will($this->returnValue($product2)); + + $cartItem2Stub + ->expects($this->any()) + ->method('getQuantity') + ->will($this->returnValue(2)) + ; + $cartItem2Stub + ->expects($this->any()) + ->method('getPrice') + ->will($this->returnValue(150)) + + ; + + $cartStub = $this->getMockBuilder('\Thelia\Model\Cart') + ->disableOriginalConstructor() + ->getMock(); + + if ($count == 1) + $ret = [$cartItem1Stub]; + else + $ret = [$cartItem1Stub, $cartItem2Stub]; + + $cartStub + ->expects($this->any()) + ->method('getCartItems') + ->will($this->returnValue($ret)); + + $stubFacade->expects($this->any()) + ->method('getCart') + ->will($this->returnValue($cartStub)); + } + + public function generateNoMatchingCart(\PHPUnit_Framework_MockObject_MockObject $stubFacade) { + + $product2 = new Product(); + $product2->setId(30); + + $cartItem2Stub = $this->getMockBuilder('\Thelia\Model\CartItem') + ->disableOriginalConstructor() + ->getMock(); + + $cartItem2Stub->expects($this->any()) + ->method('getProduct') + ->will($this->returnValue($product2)) + ; + $cartItem2Stub->expects($this->any()) + ->method('getQuantity') + ->will($this->returnValue(2)) + ; + $cartItem2Stub + ->expects($this->any()) + ->method('getPrice') + ->will($this->returnValue(11000)) + ; + + $cartStub = $this->getMockBuilder('\Thelia\Model\Cart') + ->disableOriginalConstructor() + ->getMock(); + + $cartStub + ->expects($this->any()) + ->method('getCartItems') + ->will($this->returnValue([$cartItem2Stub])); + + $stubFacade->expects($this->any()) + ->method('getCart') + ->will($this->returnValue($cartStub)); + } + + public function testSet() + { + $stubFacade = $this->generateFacadeStub(); + + $coupon = new RemovePercentageOnProducts($stubFacade); + + $date = new \DateTime(); + + $coupon->set( + $stubFacade, + 'TEST', 'TEST Coupon', 'This is a test coupon title', 'This is a test coupon description', + array('percentage' => 10.00, 'products' => [10, 20]), + true, true, true, true, + 254, + $date->setTimestamp(strtotime("today + 3 months")), + new ObjectCollection(), + new ObjectCollection(), + false + ); + + $condition1 = new MatchForTotalAmount($stubFacade); + $operators = array( + MatchForTotalAmount::CART_TOTAL => Operators::SUPERIOR, + MatchForTotalAmount::CART_CURRENCY => Operators::EQUAL + ); + $values = array( + MatchForTotalAmount::CART_TOTAL => 40.00, + MatchForTotalAmount::CART_CURRENCY => 'EUR' + ); + $condition1->setValidatorsFromForm($operators, $values); + + $condition2 = new MatchForTotalAmount($stubFacade); + $operators = array( + MatchForTotalAmount::CART_TOTAL => Operators::INFERIOR, + MatchForTotalAmount::CART_CURRENCY => Operators::EQUAL + ); + $values = array( + MatchForTotalAmount::CART_TOTAL => 400.00, + MatchForTotalAmount::CART_CURRENCY => 'EUR' + ); + $condition2->setValidatorsFromForm($operators, $values); + + $conditions = new ConditionCollection(); + $conditions[] = $condition1; + $conditions[] = $condition2; + $coupon->setConditions($conditions); + + $this->assertEquals('TEST', $coupon->getCode()); + $this->assertEquals('TEST Coupon', $coupon->getTitle()); + $this->assertEquals('This is a test coupon title', $coupon->getShortDescription()); + $this->assertEquals('This is a test coupon description', $coupon->getDescription()); + + $this->assertEquals(true, $coupon->isCumulative()); + $this->assertEquals(true, $coupon->isRemovingPostage()); + $this->assertEquals(true, $coupon->isAvailableOnSpecialOffers()); + $this->assertEquals(true, $coupon->isEnabled()); + + $this->assertEquals(254, $coupon->getMaxUsage()); + $this->assertEquals($date, $coupon->getExpirationDate()); + } + + public function testMatchOne() + { + $stubFacade = $this->generateFacadeStub(); + + $coupon = new RemovePercentageOnProducts($stubFacade); + + $date = new \DateTime(); + + $coupon->set( + $stubFacade, + 'TEST', 'TEST Coupon', 'This is a test coupon title', 'This is a test coupon description', + array('percentage' => 10.00, 'products' => [10, 20]), + true, true, true, true, + 254, + $date->setTimestamp(strtotime("today + 3 months")), + new ObjectCollection(), + new ObjectCollection(), + false + ); + + $this->generateMatchingCart($stubFacade, 1); + + $this->assertEquals(10.00, $coupon->exec()); + } + + public function testMatchSeveral() + { + $stubFacade = $this->generateFacadeStub(); + + $coupon = new RemovePercentageOnProducts($stubFacade); + + $date = new \DateTime(); + + $coupon->set( + $stubFacade, + 'TEST', 'TEST Coupon', 'This is a test coupon title', 'This is a test coupon description', + array('percentage' => 10.00, 'products' => [10, 20]), + true, true, true, true, + 254, + $date->setTimestamp(strtotime("today + 3 months")), + new ObjectCollection(), + new ObjectCollection(), + false + ); + + $this->generateMatchingCart($stubFacade, 2); + + $this->assertEquals(40.00, $coupon->exec()); + } + + public function testNoMatch() + { + $stubFacade = $this->generateFacadeStub(); + + $coupon = new RemovePercentageOnProducts($stubFacade); + + $date = new \DateTime(); + + $coupon->set( + $stubFacade, + 'TEST', 'TEST Coupon', 'This is a test coupon title', 'This is a test coupon description', + array('percentage' => 10.00, 'products' => [10, 20]), + true, true, true, true, + 254, + $date->setTimestamp(strtotime("today + 3 months")), + new ObjectCollection(), + new ObjectCollection(), + false + ); + + $this->generateNoMatchingCart($stubFacade); + + $this->assertEquals(0.00, $coupon->exec()); + } + + public function testGetName() + { + $stubFacade = $this->generateFacadeStub(399, 'EUR', 'Coupon test name'); + + /** @var FacadeInterface $stubFacade */ + $coupon = new RemovePercentageOnProducts($stubFacade); + + $actual = $coupon->getName(); + $expected = 'Coupon test name'; + $this->assertEquals($expected, $actual); + } + + public function testGetToolTip() + { + $tooltip = 'Coupon test tooltip'; + $stubFacade = $this->generateFacadeStub(399, 'EUR', $tooltip); + + /** @var FacadeInterface $stubFacade */ + $coupon = new RemovePercentageOnProducts($stubFacade); + + $actual = $coupon->getToolTip(); + $expected = $tooltip; + $this->assertEquals($expected, $actual); + } + + /** + * Tears down the fixture, for example, closes a network connection. + * This method is called after a test is executed. + */ + protected function tearDown() + { + } +}