Indexes created for all product types

This commit is contained in:
jitendra 2019-12-25 19:57:05 +05:30
parent 795561ea58
commit 7aba45486f
13 changed files with 314 additions and 55 deletions

View File

@ -2,6 +2,70 @@
#### This changelog consists the bug & security fixes and new features being included in the releases listed below.
## **v0.1.9 (20th of December, 2019)** - *Release*
* #1875 [fixed] - Discount gets applied on cart if condition is "Visible Individually" is set to yes and product added in cart is not visible individually.
* #1868 [fixed] - Getting exception on checkout if action Buy X Get Y free is selected in cart rule.
* #1838 [fixed] - Cart rule not working for condition sku(children only) and sku(parent only).
* #1835 [fixed] - Getting exception if condition value remains blank.
* #1831 [fixed] - Negative sign is not required in discount amount.
* #1830 [fixed] - If Coupon type is selected as "No Coupon" then coupon code should not generate for that particular cart rule.
* #1904 [fixed] - Existing tax should display as list on creating catalog rule if in condition "Tax Category" is selected.
* #1903 [fixed] - UI issue in condition field
* #1895 [fixed] - Translation issue Action Type field while creating catalog rule.
* #1883 [fixed] - Free shipping not applied on cart, if from action "Free Shipping" is selected and discount amount is given as zero.
* #1882 [fixed] - If from Action "Apply on shipping " is selected as yes then the discounted amount is applying on both product and shipping charge.
* #1861 [fixed] - Getting exception on checkout if applying invalid coupon code and proceed for checkout.
* #1857 [fixed] - Getting exception when creating cart rule with condition URL KEY(children only).
* #1856 [fixed] - Getting exception on creating cart rule with condition Name(children only).
* #1847 [fixed] - If cart rule condition does not match the cart then on applying coupon it should display message "Coupon cannot be applied".
* #1839 [fixed] - Getting exception on filtering cart rule through id.
* #1836 [fixed] - Back button on Edit cart rule page doesn't work.
* #1834 [fixed] - On editing any cart rule, its priority updates to 1.
* #1833 [fixed] - Discount not applied if "Payment Method", "Shipping Method", "Shipping State" or "Shipping Country" is selected in condition.
* #1832 [fixed] - Able to use coupon irrespective of the number given in "Uses per coupon" field.
* #1828 [fixed] - Updated changes are not saved on editing cart rule.
* #1825 [fixed] - Not able to generate coupon code while creating cart rule.
* #1823 [fixed] - Getting exception after clicking on developement.
* #1929 [fixed] - Actual product amount and discounted amount both should display on product page for configurable product
* #1928 [fixed] - Catalog rule should not apply if any of the condition doesn't match, if condition type"All Condition are true"
* #1931 [fixed] - Catalog rule not applying if in condition type"Any Condition is true" is selected, and some of the condition doesn't match the product.
* #1935 [fixed] - Categories are not displaying if in condition Categories(children only) or Categories(Parent Only) is selected.
* #1938 [fixed] - multiple cart rules are getting applied by using only single coupon.
* #1939 [fixed] - Invalid coupon gets applied, if clicking on apply coupon multiple time, although there is no discount amount but its displaying message that coupon code applied successfully.
* #1942 [fixed] - When editing the cart rule, selected category is not checked.
## **v0.1.8 (4th of October, 2019)** - *Release*
* [feature] - Refund is added for orders.

17
CHANGELOG for v0.2.x.md Normal file
View File

@ -0,0 +1,17 @@
# CHANGELOG for v0.2.x
#### This changelog consists the bug & security fixes and new features being included in the releases listed below.
## **v0.2.0 (23th of December, 2019)** - *Release*
* #1955 [fixed] - Message need to be changed on mouse hover on cross symbol next to applied coupon.
* #1959 [fixed] - if admin has set the same condition twice, then catalog rule is not getting apply
* #1958 [fixed] - getting exception on front end, if action type is Buy x get y free in non couponable cart rule.
* #1957 [fixed] - if action type is Fixed Amount to Whole Cart, then apply to shipping option should get hide.
* #1954 [fixed] - If any different tax category has been assigned to variants in configurable product, then while using tax category condition in cart rule, rule is not working properly.
* #1950 [fixed] - multiple catalog rule should not get get applied, if 1st one has been created as End Other Rules = yes

View File

@ -199,7 +199,7 @@
<div class="control-group" :class="[errors.has('action_type') ? 'has-error' : '']">
<label for="action_type" class="required">{{ __('admin::app.promotions.cart-rules.action-type') }}</label>
<select class="control" id="action_type" name="action_type" v-validate="'required'" data-vv-as="&quot;{{ __('admin::app.promotions.cart-rules.action-type') }}&quot;">
<select class="control" id="action_type" name="action_type" v-validate="'required'" v-model="action_type" data-vv-as="&quot;{{ __('admin::app.promotions.cart-rules.action-type') }}&quot;">
<option value="by_percent" {{ old('action_type') == 'by_percent' ? 'selected' : '' }}>
{{ __('admin::app.promotions.cart-rules.percentage-product-price') }}
</option>
@ -236,7 +236,7 @@
<div class="control-group">
<label for="apply_to_shipping">{{ __('admin::app.promotions.cart-rules.apply-to-shipping') }}</label>
<select class="control" id="apply_to_shipping" name="apply_to_shipping">
<select class="control" id="apply_to_shipping" name="apply_to_shipping" :disabled="action_type == 'cart_fixed'">
<option value="0" {{ ! old('apply_to_shipping') ? 'selected' : '' }}>{{ __('admin::app.promotions.cart-rules.no') }}</option>
<option value="1" {{ old('apply_to_shipping') ? 'selected' : '' }}>{{ __('admin::app.promotions.cart-rules.yes') }}</option>
</select>
@ -380,7 +380,9 @@
condition_type: 1,
conditions: []
conditions: [],
action_type: "{{ old('action_type') ?: 'by_percent' }}"
}
},

View File

@ -164,7 +164,7 @@
</div>
</accordian>
<accordian :title="'{{ __('admin::app.promotions.cart-rules.conditions') }}'" :active="true">
<accordian :title="'{{ __('admin::app.promotions.cart-rules.conditions') }}'" :active="false">
<div slot="body">
<div class="control-group">
@ -205,7 +205,7 @@
<?php $selectedOption = old('action_type') ?: $cartRule->action_type ?>
<select class="control" id="action_type" name="action_type" v-validate="'required'" data-vv-as="&quot;{{ __('admin::app.promotions.cart-rules.action-type') }}&quot;">
<select class="control" id="action_type" name="action_type" v-validate="'required'" v-model="action_type" data-vv-as="&quot;{{ __('admin::app.promotions.cart-rules.action-type') }}&quot;">
<option value="by_percent" {{ $selectedOption == 'by_percent' ? 'selected' : '' }}>
{{ __('admin::app.promotions.cart-rules.percentage-product-price') }}
</option>
@ -246,7 +246,7 @@
<?php $selectedOption = old('apply_to_shipping') ?: $cartRule->apply_to_shipping ?>
<select class="control" id="apply_to_shipping" name="apply_to_shipping">
<select class="control" id="apply_to_shipping" name="apply_to_shipping" :disabled="action_type == 'cart_fixed'">
<option value="0" {{ ! $selectedOption ? 'selected' : '' }}>
{{ __('admin::app.promotions.cart-rules.no') }}
</option>
@ -472,7 +472,9 @@
condition_type: {{ old('condition_type') ?: $cartRule->condition_type }},
conditions: @json($cartRule->conditions ?: [])
conditions: @json($cartRule->conditions ?: []),
action_type: "{{ old('action_type') ?: $cartRule->action_type }}"
}
},

View File

@ -106,6 +106,9 @@ class CartRule
foreach ($cart->items()->get() as $item) {
$this->process($item);
if ($item->children()->count() && $item->product->getTypeInstance()->isChildrenCalculated())
$this->devideDiscount($item);
}
$this->processShippingDiscount($cart);
@ -231,6 +234,8 @@ class CartRule
$quantity = $rule->discount_quantity ? min($item->quantity, $rule->discount_quantity) : $item->quantity;
$discountAmount = $baseDiscountAmount = 0;
switch ($rule->action_type) {
case 'by_percent':
$rulePercent = min(100, $rule->discount_amount);
@ -493,4 +498,26 @@ class CartRule
if (! $coupon || ! in_array($coupon->cart_rule_id, explode(',', $cart->applied_cart_rule_ids)))
Cart::removeCouponCode();
}
/**
* Devide discount amount to children
*
* @param CartItem $item
* @return void
*/
protected function devideDiscount($item)
{
foreach ($item->children as $child) {
$ratio = $item->base_total != 0 ? $child->base_total / $item->base_total : 0;
foreach (['discount_amount', 'base_discount_amount'] as $column) {
if (! $item->{$column})
continue;
$child->{$column} = round(($item->{$column} * $ratio), 4);
$child->save();
}
}
}
}

View File

@ -78,13 +78,12 @@ class CatalogRuleIndex
public function reindexProduct($product)
{
try {
$productIds = [];
if ($product->type == 'configurable') {
$productIds = $product->variants()->pluck('id')->toArray();
} else {
$productIds[] = $product->id;
}
if (! $product->getTypeInstance()->priceRuleCanBeApplied())
return;
$productIds = $product->getTypeInstance()->isComposite()
? $product->getTypeInstance()->getChildrenIds()
: [$product->id];
$this->cleanIndexes($productIds);

View File

@ -133,9 +133,17 @@ class CatalogRuleProduct
if (! $rule->conditions)
return $qb;
$appliedAttributes = [];
foreach ($rule->conditions as $condition) {
if (! $condition['attribute'] || ! isset($condition['value']) || is_null($condition['value']) || $condition['value'] == '')
if (! $condition['attribute']
|| ! isset($condition['value'])
|| is_null($condition['value'])
|| $condition['value'] == ''
|| in_array($condition['attribute'], $appliedAttributes))
continue;
$appliedAttributes[] = $condition['attribute'];
$chunks = explode('|', $condition['attribute']);
@ -148,9 +156,12 @@ class CatalogRuleProduct
$validatedProductIds = [];
foreach ($qb->get() as $product) {
if (! $product->getTypeInstance()->priceRuleCanBeApplied())
continue;
if ($this->validator->validate($rule, $product)) {
if ($product->type == 'configurable') {
$validatedProductIds = array_merge($validatedProductIds, $product->variants()->pluck('id')->toArray());
if ($product->getTypeInstance()->isComposite()) {
$validatedProductIds = array_merge($validatedProductIds, $product->getTypeInstance()->getChildrenIds());
} else {
$validatedProductIds[] = $product->id;
}
@ -208,8 +219,12 @@ class CatalogRuleProduct
->orderBy('catalog_rule_id', 'asc');
if ($product) {
if ($product->type == 'configurable') {
$qb->whereIn('catalog_rule_products.product_id', $product->variants()->pluck('id')->toArray());
if (! $product->getTypeInstance()->priceRuleCanBeApplied())
return $qb;
if ($product->getTypeInstance()->isComposite()) {
$qb->whereIn('catalog_rule_products.product_id', $product->getTypeInstance()->getChildrenIds());
} else {
$qb->where('catalog_rule_products.product_id', $product->id);
}

View File

@ -112,6 +112,13 @@ abstract class AbstractType
*/
protected $hasVariants = false;
/**
* Product children price can be calculated or not
*
* @var boolean
*/
protected $isChildrenCalculated = false;
/**
* Create a new product type instance.
*
@ -250,6 +257,26 @@ abstract class AbstractType
return $this;
}
/**
* Returns children ids
*
* @return array
*/
public function getChildrenIds()
{
return [];
}
/**
* Check if catalog rule can be applied
*
* @return bool
*/
public function priceRuleCanBeApplied()
{
return true;
}
/**
* Return true if this product type is saleable
*
@ -289,11 +316,21 @@ abstract class AbstractType
*
* @return bool
*/
public function hasVariants(): bool
public function hasVariants()
{
return $this->hasVariants;
}
/**
* Product children price can be calculated or not
*
* @return bool
*/
public function isChildrenCalculated()
{
return $this->isChildrenCalculated;
}
/**
* @param integer $qty
* @return bool

View File

@ -68,6 +68,13 @@ class Bundle extends AbstractType
*/
protected $isComposite = true;
/**
* Product children price can be calculated or not
*
* @var boolean
*/
protected $isChildrenCalculated = true;
/**
* Create a new product type instance.
*
@ -126,6 +133,26 @@ class Bundle extends AbstractType
return $product;
}
/**
* Returns children ids
*
* @return array
*/
public function getChildrenIds()
{
return array_unique($this->product->bundle_options()->pluck('product_id')->toArray());
}
/**
* Check if catalog rule can be applied
*
* @return bool
*/
public function priceRuleCanBeApplied()
{
return false;
}
/**
* Get product minimal price
*

View File

@ -286,6 +286,16 @@ class Configurable extends AbstractType
return false;
}
/**
* Returns children ids
*
* @return array
*/
public function getChildrenIds()
{
return $this->product->variants()->pluck('id')->toArray();
}
/**
* @param CartItem $cartItem
* @return bool

View File

@ -104,6 +104,16 @@ class Grouped extends AbstractType
return $product;
}
/**
* Returns children ids
*
* @return array
*/
public function getChildrenIds()
{
return array_unique($this->product->grouped_products()->pluck('product_id')->toArray());
}
/**
* Get product minimal price
*

View File

@ -29,16 +29,14 @@ class Validator
$totalConditionCount++;
$attributeValue = $this->getAttributeValue($condition, $entity);
if ($rule->condition_type == 1) {
if (! $this->validateAttribute($condition['operator'], $attributeValue, $condition['value'])) {
if (! $this->validateObject($condition, $entity)) {
return false;
} else {
$validConditionCount++;
}
} else {
if ($this->validateAttribute($condition['operator'], $attributeValue, $condition['value']))
if ($this->validateObject($condition, $entity))
return true;
}
}
@ -49,8 +47,8 @@ class Validator
/**
* Return value for the attribute
*
* @param array $condition
* @param Cart|CartItem|Product $entity
* @param array $condition
* @param CartItem|Product $entity
* @return boolean
*/
public function getAttributeValue($condition, $entity)
@ -61,8 +59,6 @@ class Validator
$attributeCode = $attributeNameChunks[count($attributeNameChunks) - 1];
$attributeScope = count($attributeNameChunks) == 2 ? $attributeNameChunks[0] : null;
switch (current($chunks)) {
case 'cart':
$cart = $entity instanceof \Webkul\Checkout\Contracts\Cart ? $entity : $entity->cart;
@ -93,18 +89,15 @@ class Validator
case 'product':
if ($attributeCode == 'category_ids') {
$value = $attributeScope == 'children'
? ($entity->child ? $entity->child->product->categories()->pluck('id')->toArray() : [])
: ($entity->product
$value = $entity->product
? $entity->product->categories()->pluck('id')->toArray()
: $entity->categories()->pluck('id')->toArray()
);
: $entity->categories()->pluck('id')->toArray();
return $value;
} else {
$value = $attributeScope == 'children'
? ($entity->child ? $entity->child->product->{$attributeCode} : null)
: ($entity->product ? $entity->product->{$attributeCode} : $entity->{$attributeCode});
$value = $entity->product
? $entity->product->{$attributeCode}
: $entity->{$attributeCode};
if (! in_array($condition['attribute_type'], ['multiselect', 'checkbox']))
return $value;
@ -114,28 +107,85 @@ class Validator
}
}
/**
* Validate object
*
* @param array $condition
* @param CartItem $entity
* @return bool
*/
private function validateObject($condition, $entity)
{
$validated = false;
foreach ($this->getAllItems($this->getAttributeScope($condition), $entity) as $item) {
$attributeValue = $this->getAttributeValue($condition, $item);
if ($validated = $this->validateAttribute($condition, $attributeValue))
break;
}
return $validated;
}
/**
* Return all cart items
*
* @param string $attributeScope
* @param Cart|CartItem|Product $item
* @return array
*/
private function getAllItems($attributeScope, $item)
{
if ($attributeScope === 'parent') {
return [$item];
} elseif ($attributeScope === 'children') {
return $item->children ?: [$item];
} else {
$items = $item->children ?: [];
$items[] = $item;
}
return $items;
}
/**
* Validate object
*
* @param array $condition
* @return string
*/
private function getAttributeScope($condition)
{
$chunks = explode('|', $condition['attribute']);
$attributeNameChunks = explode('::', $chunks[1]);
return count($attributeNameChunks) == 2 ? $attributeNameChunks[0] : null;
}
/**
* Validate attribute value for condition
*
* @param string $operator
* @param mixed $attributeValue
* @param mixed $conditionValue
* @param array $condition
* @param mixed $attributeValue
* @return boolean
*/
public function validateAttribute($operator, $attributeValue, $conditionValue)
public function validateAttribute($condition, $attributeValue)
{
switch ($operator) {
switch ($condition['operator']) {
case '==': case '!=':
if (is_array($conditionValue)) {
if (is_array($condition['value'])) {
if (! is_array($attributeValue))
return false;
$result = ! empty(array_intersect($conditionValue, $attributeValue));
$result = ! empty(array_intersect($condition['value'], $attributeValue));
} else {
if (is_array($attributeValue)) {
$result = count($attributeValue) == 1 && array_shift($attributeValue) == $conditionValue;
$result = count($attributeValue) == 1 && array_shift($attributeValue) == $condition['value'];
} else {
$result = $attributeValue == $conditionValue;
$result = $attributeValue == $condition['value'];
}
}
@ -145,7 +195,7 @@ class Validator
if (! is_scalar($attributeValue))
return false;
$result = $attributeValue <= $conditionValue;
$result = $attributeValue <= $condition['value'];
break;
@ -153,36 +203,36 @@ class Validator
if (! is_scalar($attributeValue))
return false;
$result = $attributeValue >= $conditionValue;
$result = $attributeValue >= $condition['value'];
break;
case '{}': case '!{}':
if (is_scalar($attributeValue) && is_array($conditionValue)) {
foreach ($conditionValue as $item) {
if (is_scalar($attributeValue) && is_array($condition['value'])) {
foreach ($condition['value'] as $item) {
if (stripos($attributeValue, $item) !== false) {
$result = true;
break;
}
}
} else if (is_array($conditionValue)) {
} else if (is_array($condition['value'])) {
if (! is_array($attributeValue))
return false;
$result = ! empty(array_intersect($conditionValue, $attributeValue));
$result = ! empty(array_intersect($condition['value'], $attributeValue));
} else {
if (is_array($attributeValue)) {
$result = in_array($conditionValue, $attributeValue);
$result = in_array($condition['value'], $attributeValue);
} else {
$result = (strpos($attributeValue, $conditionValue) !== false) ? true : false;
$result = (strpos($attributeValue, $condition['value']) !== false) ? true : false;
}
}
break;
}
if (in_array($operator, ['!=', '>', '<', '!{}']))
if (in_array($condition['operator'], ['!=', '>', '<', '!{}']))
$result = ! $result;
return $result;

View File

@ -519,7 +519,6 @@ return [
'cannot-apply-coupon' => 'Cannot Apply Coupon',
'invalid-coupon' => 'Coupon code is invalid.',
'success-coupon' => 'Coupon code applied successfully.',
'remove-coupon' => 'Coupon code removed successfully.',
'coupon-apply-issue' => 'Coupon code can\'t be applied.'
],