Added Attribute value related coupons
This commit is contained in:
@@ -51,6 +51,24 @@
|
||||
<tag name="thelia.coupon.addCoupon"/>
|
||||
</service>
|
||||
|
||||
<service id="thelia.coupon.type.remove_percentage_on_products" class="Thelia\Coupon\Type\RemovePercentageOnProducts">
|
||||
<argument type="service" id="thelia.facade" />
|
||||
<tag name="thelia.coupon.addCoupon"/>
|
||||
</service>
|
||||
|
||||
<service id="thelia.coupon.type.remove_amount_on_attribute_av" class="Thelia\Coupon\Type\RemoveAmountOnAttributeValues">
|
||||
<argument type="service" id="thelia.facade" />
|
||||
<tag name="thelia.coupon.addCoupon"/>
|
||||
</service>
|
||||
|
||||
<service id="thelia.coupon.type.remove_percentage_on_attribute_av" class="Thelia\Coupon\Type\RemovePercentageOnAttributeValues">
|
||||
<argument type="service" id="thelia.facade" />
|
||||
<tag name="thelia.coupon.addCoupon"/>
|
||||
</service>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<!-- Condition module -->
|
||||
|
||||
|
||||
174
core/lib/Thelia/Coupon/Type/AbstractRemoveOnAttributeValues.php
Normal file
174
core/lib/Thelia/Coupon/Type/AbstractRemoveOnAttributeValues.php
Normal file
@@ -0,0 +1,174 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Coupon\Type;
|
||||
|
||||
use Thelia\Core\Translation\Translator;
|
||||
use Thelia\Coupon\FacadeInterface;
|
||||
use Thelia\Model\AttributeCombination;
|
||||
use Thelia\Model\CartItem;
|
||||
|
||||
/**
|
||||
* The base class to process a discount related to Attribute values.
|
||||
*
|
||||
* @package Coupon
|
||||
* @author Franck Allimant <franck@cqfdev.fr>
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}
|
||||
108
core/lib/Thelia/Coupon/Type/RemoveAmountOnAttributeValues.php
Normal file
108
core/lib/Thelia/Coupon/Type/RemoveAmountOnAttributeValues.php
Normal file
@@ -0,0 +1,108 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Coupon\Type;
|
||||
|
||||
use Thelia\Core\Translation\Translator;
|
||||
|
||||
/**
|
||||
* Allow to remove an amount from the checkout total
|
||||
*
|
||||
* @package Coupon
|
||||
* @author Franck Allimant <franck@cqfdev.fr>
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Coupon\Type;
|
||||
|
||||
use Thelia\Core\Translation\Translator;
|
||||
|
||||
/**
|
||||
* Allow to remove an amount from the checkout total
|
||||
*
|
||||
* @package Coupon
|
||||
* @author Franck Allimant <franck@cqfdev.fr>
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
{block name="discount-field"}{/block}
|
||||
|
||||
<div class="form-group input-coupon-attribute-id">
|
||||
|
||||
<label for="coupon-category-id">{intl l="Select attribute :"} = {$attribute_value}</label>
|
||||
|
||||
<select required class="form-control" id="coupon-attribute-id" name="{$attribute_field_name}">
|
||||
<option value="0">{intl l="Please select..."}</option>
|
||||
{loop type="attribute" name="list-of-attributes" order="alpha" backend_context="1"}
|
||||
<option value="{$ID}" {if $ID == $attribute_value}selected="selected"{/if}>{$TITLE}</option>
|
||||
{/loop}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="loading" id="input-coupon-attributeAvs-id-loading" style="display: none"></div>
|
||||
|
||||
<div class="form-group" id="input-coupon-attributeAvs-id" {if $attribute_value == 0}style="display: none"{/if}>
|
||||
|
||||
<label for="coupon-products-id">{intl l="Applies to attribute values :"}</label>
|
||||
|
||||
<select required multiple size="10" class="form-control" id="coupon-attributeAvs-id" name="{$attribute_av_field_name}[]">
|
||||
{loop type="attribute_availability" attribute=$attribute_value name="list-of-attribute_avs" backend_context="1"}
|
||||
<option value="{$ID}" {if in_array($ID, $attribute_av_values)}selected="selected"{/if}>{$TITLE}</option>
|
||||
{/loop}
|
||||
</select>
|
||||
|
||||
<span class="label-help-block">{intl l='Use Ctrl+click to select (or deselect) more that one attribute value'}</span>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function couponInputFormSetup() {
|
||||
|
||||
var $catSelect = $('#coupon-attribute-id');
|
||||
|
||||
$catSelect.change(function(ev) {
|
||||
|
||||
var $attribute_id = $(this).val();
|
||||
|
||||
$('#input-coupon-attributeAvs-id').hide();
|
||||
$('#coupon-attributeAvs-id').html('');
|
||||
|
||||
if ($attribute_id != 0) {
|
||||
|
||||
$('#input-coupon-attributeAvs-id-loading').show();
|
||||
|
||||
$.ajax({
|
||||
url: "{url path='/admin/coupon/type-fragments/ajax-attribute-avs-list'}",
|
||||
type: 'POST',
|
||||
data: {
|
||||
attribute_id: $attribute_id
|
||||
},
|
||||
success: function(options) {
|
||||
$('#coupon-attributeAvs-id').html(options);
|
||||
$('#input-coupon-attributeAvs-id').show();
|
||||
},
|
||||
complete: function() {
|
||||
$('#input-coupon-attributeAvs-id-loading').hide();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
</script>
|
||||
@@ -0,0 +1,16 @@
|
||||
{extends file="coupon/type-fragments/base-remove-on-attributes.html"}
|
||||
|
||||
{block name="discount-field"}
|
||||
<div class="form-group input-coupon-amount">
|
||||
|
||||
<label for="coupon-amount" class="control-label">{intl l="Discount amount"}</label>
|
||||
|
||||
<div class="input-group">
|
||||
<input id="coupon-amount" type="money" class="form-control" name="{$amount_field_name}" value="{$amount_value}" placeholder="14.50">
|
||||
|
||||
{loop type="currency" name="get-symbol" default_only="true"}
|
||||
<div class="input-group-addon">{$SYMBOL}</div>
|
||||
{/loop}
|
||||
</div>
|
||||
</div>
|
||||
{/block}
|
||||
@@ -0,0 +1,14 @@
|
||||
{extends file="coupon/type-fragments/base-remove-on-attributes.html"}
|
||||
|
||||
{block name="discount-field"}
|
||||
<div class="form-group input-coupon-percentage">
|
||||
|
||||
<label for="coupon-percentage" class="control-label">{intl l="Discount percentage"}</label>
|
||||
|
||||
<div class="input-group">
|
||||
<input id="coupon-percentage" type="number" class="form-control" name="{$percentage_field_name}" value="{$percentage_value}" placeholder="5">
|
||||
|
||||
<div class="input-group-addon">%</div>
|
||||
</div>
|
||||
</div>
|
||||
{/block}
|
||||
Reference in New Issue
Block a user