diff --git a/core/lib/Thelia/Coupon/Type/CouponAbstract.php b/core/lib/Thelia/Coupon/Type/CouponAbstract.php index 02336cc2e..6d57b0d38 100644 --- a/core/lib/Thelia/Coupon/Type/CouponAbstract.php +++ b/core/lib/Thelia/Coupon/Type/CouponAbstract.php @@ -278,10 +278,7 @@ abstract class CouponAbstract implements CouponInterface } /** - * Return effects generated by the coupon - * A negative value - * - * @return float Amount removed from the Total Checkout + * @inheritdoc */ public function exec() { diff --git a/core/lib/Thelia/Coupon/Type/RemoveAmountOnCategories.php b/core/lib/Thelia/Coupon/Type/RemoveAmountOnCategories.php index 665a02bff..1c5da8683 100644 --- a/core/lib/Thelia/Coupon/Type/RemoveAmountOnCategories.php +++ b/core/lib/Thelia/Coupon/Type/RemoveAmountOnCategories.php @@ -70,28 +70,24 @@ class RemoveAmountOnCategories extends CouponAbstract } /** - * Get I18n name - * - * @return string + * @inheritdoc */ public function getName() { return $this->facade ->getTranslator() - ->trans('Fixed amount discount on selected categories', array(), 'coupon'); + ->trans('Fixed amount discount for selected categories', array(), 'coupon'); } /** - * Get I18n tooltip - * - * @return string + * @inheritdoc */ public function getToolTip() { $toolTip = $this->facade ->getTranslator() ->trans( - 'This coupon subtracts the specified amount from the order total for each product of 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.', array(), 'coupon' ); @@ -100,10 +96,7 @@ class RemoveAmountOnCategories extends CouponAbstract } /** - * Return effects generated by the coupon - * A negative value - * - * @return float Amount removed from the Total Checkout + * @inheritdoc */ public function exec() { @@ -116,15 +109,17 @@ class RemoveAmountOnCategories extends CouponAbstract /** @var CartItem $cartItem */ foreach ($cartItems as $cartItem) { - $categories = $cartItem->getProduct()->getCategories(); + if (! $cartItem->getPromo() || $this->isAvailableOnSpecialOffers()) { + $categories = $cartItem->getProduct()->getCategories(); - /** @var Category $category */ - foreach ($categories as $category) { + /** @var Category $category */ + foreach ($categories as $category) { - if (in_array($category->getId(), $this->category_list)) { - $discount += $cartItem->getQuantity() * $this->amount; + if (in_array($category->getId(), $this->category_list)) { + $discount += $cartItem->getQuantity() * $this->amount; - break; + break; + } } } } @@ -132,6 +127,9 @@ class RemoveAmountOnCategories extends CouponAbstract return $discount; } + /** + * @inheritdoc + */ public function drawBackOfficeInputs() { return $this->facade->getParser()->render('coupon/type-fragments/remove-amount-on-categories.html', [ @@ -141,18 +139,13 @@ class RemoveAmountOnCategories extends CouponAbstract 'amount_value' => $this->amount, // The categories list field - 'categories_field_id' => self::CATEGORIES_LIST, 'categories_field_name' => $this->makeCouponFieldName(self::CATEGORIES_LIST), - - // The selected categories 'categories_values' => $this->category_list ]); } /** - * Return a list of the fields name for this coupon. - * - * @return array + * @inheritdoc */ protected function getFieldList() { diff --git a/core/lib/Thelia/Coupon/Type/RemoveAmountOnProducts.php b/core/lib/Thelia/Coupon/Type/RemoveAmountOnProducts.php new file mode 100644 index 000000000..cb1fda768 --- /dev/null +++ b/core/lib/Thelia/Coupon/Type/RemoveAmountOnProducts.php @@ -0,0 +1,194 @@ + + * + */ +class RemoveAmountOnProducts extends CouponAbstract +{ + 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 + ); + + $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; + } + + /** + * Get I18n name + * + * @return string + */ + public function getName() + { + return $this->facade + ->getTranslator() + ->trans('Fixed amount discount for selected products', array(), 'coupon'); + } + + /** + * @inheritdoc + */ + public function getToolTip() + { + $toolTip = $this->facade + ->getTranslator() + ->trans( + '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.', + array(), + 'coupon' + ); + + 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) + ]); + } + + /** + * @inheritdoc + */ + protected function getFieldList() + { + return [self::AMOUNT_FIELD_NAME, self::CATEGORY_ID, self::PRODUCTS_LIST]; + } + + /** + * @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 Discount Amount is invalid. Please enter a positive value.', + [ '%val' => $fieldValue] + ) + ); + } + } + 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 new file mode 100644 index 000000000..db05f7f5a --- /dev/null +++ b/core/lib/Thelia/Coupon/Type/RemovePercentageOnCategories.php @@ -0,0 +1,185 @@ + + * + */ +class RemovePercentageOnCategories extends CouponAbstract +{ + 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 + ); + + $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 getName() + { + return $this->facade + ->getTranslator() + ->trans('Percentage discount for selected categories', array(), 'coupon'); + } + + /** + * @inheritdoc + */ + public function getToolTip() + { + $toolTip = $this->facade + ->getTranslator() + ->trans( + '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.', + array(), + 'coupon' + ); + + 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 + ]); + } + + /** + * @inheritdoc + */ + protected function getFieldList() + { + return [self::PERCENTAGE, self::CATEGORIES_LIST]; + } + + /** + * @inheritdoc + */ + protected function checkCouponFieldValue($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] + ) + ); + } + } 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 new file mode 100644 index 000000000..007fa2a57 --- /dev/null +++ b/core/lib/Thelia/Coupon/Type/RemovePercentageOnProducts.php @@ -0,0 +1,199 @@ + + * + */ +class RemovePercentageOnProducts extends CouponAbstract +{ + const CATEGORY_ID = 'category_id'; + const PRODUCTS_LIST = 'products'; + 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; + + $this->percentage = $effects[self::PERCENTAGE]; + + return $this; + } + + /** + * Get I18n name + * + * @return string + */ + public function getName() + { + return $this->facade + ->getTranslator() + ->trans('Percentage discount for selected products', array(), 'coupon'); + } + + /** + * @inheritdoc + */ + public function getToolTip() + { + $toolTip = $this->facade + ->getTranslator() + ->trans( + '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.', + array(), + 'coupon' + ); + + 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) + ]); + } + + /** + * @inheritdoc + */ + protected function getFieldList() + { + return [self::PERCENTAGE, self::CATEGORY_ID, self::PRODUCTS_LIST]; + } + + /** + * @inheritdoc + */ + protected function checkCouponFieldValue($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] + ) + ); + } + } + 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/RemoveXAmount.php b/core/lib/Thelia/Coupon/Type/RemoveXAmount.php index 1f83c6eec..7ded8108c 100644 --- a/core/lib/Thelia/Coupon/Type/RemoveXAmount.php +++ b/core/lib/Thelia/Coupon/Type/RemoveXAmount.php @@ -27,9 +27,7 @@ class RemoveXAmount extends CouponAbstract protected $serviceId = 'thelia.coupon.type.remove_x_amount'; /** - * Get I18n name - * - * @return string + * @inheritdoc */ public function getName() { @@ -39,9 +37,7 @@ class RemoveXAmount extends CouponAbstract } /** - * Get I18n tooltip - * - * @return string + * @inheritdoc */ public function getToolTip() { @@ -56,6 +52,9 @@ class RemoveXAmount extends CouponAbstract return $toolTip; } + /** + * @inheritdoc + */ public function drawBackOfficeInputs() { return $this->facade->getParser()->render('coupon/type-fragments/remove-x-amount.html', [ @@ -65,9 +64,7 @@ class RemoveXAmount extends CouponAbstract } /** - * Return a list of the fields name for this coupon. - * - * @return array + * @inheritdoc */ protected function getFieldList() { diff --git a/core/lib/Thelia/Coupon/Type/RemoveXPercent.php b/core/lib/Thelia/Coupon/Type/RemoveXPercent.php index e1cc20252..554e3f5da 100644 --- a/core/lib/Thelia/Coupon/Type/RemoveXPercent.php +++ b/core/lib/Thelia/Coupon/Type/RemoveXPercent.php @@ -65,22 +65,11 @@ class RemoveXPercent extends CouponAbstract } /** - * Return effects generated by the coupon - * A negative value - * - * @throws \Thelia\Exception\MissingFacadeException - * @throws \InvalidArgumentException - * @return float + * @inheritdoc */ public function exec() { - if ($this->percentage >= 100) { - throw new \InvalidArgumentException( - 'Percentage must be inferior to 100' - ); - } - - return round($this->facade->getCartTotalTaxPrice() * $this->percentage/100, 2); + return round($this->facade->getCartTotalTaxPrice($this->isAvailableOnSpecialOffers()) * $this->percentage/100, 2); } /** @@ -90,7 +79,9 @@ class RemoveXPercent extends CouponAbstract { if ($fieldName === self::INPUT_PERCENTAGE_NAME) { - if (floatval($fieldValue) <= 0) { + $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.', @@ -104,9 +95,7 @@ class RemoveXPercent extends CouponAbstract } /** - * Get I18n name - * - * @return string + * @inheritdoc */ public function getName() { @@ -116,9 +105,7 @@ class RemoveXPercent extends CouponAbstract } /** - * Get I18n tooltip - * - * @return string + * @inheritdoc */ public function getToolTip() { @@ -134,10 +121,7 @@ class RemoveXPercent extends CouponAbstract } /** - * Draw the input displayed in the BackOffice - * allowing Admin to set its Coupon effect - * - * @return string HTML string + * @inheritdoc */ public function drawBackOfficeInputs() { @@ -148,9 +132,7 @@ class RemoveXPercent extends CouponAbstract } /** - * Return a list of the fields name for this coupon. - * - * @return array + * @inheritdoc */ protected function getFieldList() { diff --git a/templates/backOffice/default/coupon/type-fragments/ajax-products-list.html b/templates/backOffice/default/coupon/type-fragments/ajax-products-list.html new file mode 100644 index 000000000..2752f4d0f --- /dev/null +++ b/templates/backOffice/default/coupon/type-fragments/ajax-products-list.html @@ -0,0 +1,3 @@ +{loop type="product" category={$smarty.post.category_id} name="list-of-products" backend_context="1"} + +{/loop} \ No newline at end of file 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 396a1ef01..15c528331 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 @@ -12,7 +12,7 @@ -
+
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 new file mode 100644 index 000000000..57d45684c --- /dev/null +++ b/templates/backOffice/default/coupon/type-fragments/remove-amount-on-products.html @@ -0,0 +1,77 @@ + +
+ + + +
+ + + {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'} +
+ + 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 new file mode 100644 index 000000000..08c3655f1 --- /dev/null +++ b/templates/backOffice/default/coupon/type-fragments/remove-percentage-on-categories.html @@ -0,0 +1,24 @@ + +
+ + + +
+ + +
%
+
+
+ +
+ + + + + + {intl l='Use Ctrl+click to select (or deselect) more that one category'} +
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 new file mode 100644 index 000000000..4787da2ee --- /dev/null +++ b/templates/backOffice/default/coupon/type-fragments/remove-percentage-on-products.html @@ -0,0 +1,75 @@ + +
+ + + +
+ + +
%
+
+
+ +
+ + + + + + {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'} +
+ +