refactroring of vart rules

This commit is contained in:
Prashant Singh 2019-08-05 05:06:51 +05:30
parent e4a5e84fb6
commit cff0b7f4b2
13 changed files with 348 additions and 212 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,4 +1,4 @@
{
"/js/admin.js": "/js/admin.js?id=0afa8deaa3ea01b81abf",
"/css/admin.css": "/css/admin.css?id=8159ebe203858f2396c2"
"/js/admin.js": "/js/admin.js?id=d27aed3da0c62eb237be",
"/css/admin.css": "/css/admin.css?id=96d341f257529071e8e7"
}

View File

@ -253,13 +253,13 @@
<span class="control-error" v-if="errors.has('disc_amount')">@{{ errors.first('disc_amount') }}</span>
</div>
<div class="control-group" :class="[errors.has('disc_threshold') ? 'has-error' : '']">
{{-- <div class="control-group" :class="[errors.has('disc_threshold') ? 'has-error' : '']">
<label for="disc_threshold" class="required">{{ __('admin::app.promotion.cart.buy-atleast') }}</label>
<input type="number" step="1" class="control" name="disc_threshold" v-model="disc_threshold" v-validate="'required|numeric|min_value:1'" value="{{ old('disc_threshold') }}" data-vv-as="&quot;{{ __('admin::app.promotion.cart.buy-atleast') }}&quot;">
<span class="control-error" v-if="errors.has('disc_threshold')">@{{ errors.first('disc_threshold') }}</span>
</div>
</div> --}}
<div class="control-group" :class="[errors.has('disc_quantity') ? 'has-error' : '']">
<label for="disc_quantity" class="required">{{ __('admin::app.promotion.general-info.disc_qty') }}</label>
@ -448,7 +448,7 @@
apply_prct: false,
apply_to_shipping: 0,
disc_amount: null,
disc_threshold: null,
// disc_threshold: null,
disc_quantity: null,
end_other_rules: 0,
coupon_type: null,

View File

@ -259,13 +259,13 @@
<span class="control-error" v-if="errors.has('disc_amount')">@{{ errors.first('disc_amount') }}</span>
</div>
<div class="control-group" :class="[errors.has('disc_threshold') ? 'has-error' : '']">
{{-- <div class="control-group" :class="[errors.has('disc_threshold') ? 'has-error' : '']">
<label for="disc_threshold" class="required">{{ __('admin::app.promotion.cart.buy-atleast') }}</label>
<input type="number" step="1" class="control" name="disc_threshold" v-model="disc_threshold" v-validate="'required|numeric|min_value:1'" value="{{ old('disc_threshold') }}" data-vv-as="&quot;{{ __('admin::app.promotion.cart.buy-atleast') }}&quot;">
<span class="control-error" v-if="errors.has('disc_threshold')">@{{ errors.first('disc_threshold') }}</span>
</div>
</div> --}}
<div class="control-group" :class="[errors.has('disc_quantity') ? 'has-error' : '']">
<label for="disc_amount" class="required">{{ __('admin::app.promotion.general-info.disc_qty') }}</label>
@ -446,9 +446,8 @@
apply_amt: false,
apply_prct: false,
apply_to_shipping: null,
buy_atleast: null,
disc_amount: null,
disc_threshold: null,
// disc_threshold: null,
disc_quantity: null,
end_other_rules: null,
coupon_type: null,
@ -547,9 +546,8 @@
this.apply_amt = false;
this.apply_prct = false;
this.apply_to_shipping = data.apply_to_shipping;
this.buy_atleast = data.disc_threshold;
this.disc_amount = data.disc_amount;
this.disc_threshold = data.disc_threshold;
// this.disc_threshold = data.disc_threshold;
this.disc_quantity = data.disc_quantity;
this.end_other_rules = data.end_other_rules;
this.coupon_type = data.coupon_type;

View File

@ -6,59 +6,75 @@ use Webkul\Discount\Actions\Action;
class FixedAmount extends Action
{
public function calculate($rule, $items, $cart)
public function calculate($rule)
{
$report = collect();
$totalDiscount = 0;
$cart = \Cart::getCart();
$items = $cart->items;
$impact = collect();
$impact->discount = $rule->disc_amount;
$impact->formatted_discount = core()->currency($impact->discount);
if ($rule->uses_attribute_conditions) {
$productIDs = $rule->product_ids;
$productIDs = explode(',', $productIDs);
$matchCount = 0;
foreach ($productIDs as $productID) {
foreach ($items as $item) {
if ($item->product_id == $productID) {
$matchCount++;
}
}
}
if ($matchCount > 0) {
$discountPerItem = $impact->discount / $matchCount;
}
foreach ($productIDs as $productID) {
foreach ($items as $item) {
if ($item->product_id == $productID) {
$report = array();
$report['item_id'] = $item->id;
$report['product_id'] = $item->product_id;
$report['discount'] = round($discountPerItem, 4);
$report['formatted_discount'] = core()->currency(round($discountPerItem, 4));
$impact->push($report);
unset($report);
}
}
}
} else {
$discountPerItem = $impact->discount / $cart->items_qty;
foreach ($items as $item) {
$amountDiscounted = 0;
$itemReport = array();
$report = array();
// calculate discount amount
$action_type = $rule->action_type; // action type used
$disc_threshold = $rule->disc_threshold; // atleast quantity by default 1 --> may be omitted in near future
$disc_amount = $rule->disc_amount; // value of discount
$disc_quantity = $rule->disc_quantity; //max quantity allowed to be discounted
$report['item_id'] = $item->id;
$report['product_id'] = $item->product_id;
$report['discount'] = round($discountPerItem, 4);
$report['formatted_discount'] = core()->currency(round($discountPerItem, 4));
$realQty = $item['quantity'];
$impact->push($report);
if ($cart->items_qty >= $disc_threshold) {
$amountDiscounted = $disc_amount;
if ($realQty > $disc_quantity) {
$amountDiscounted = $amountDiscounted * $disc_quantity;
} else {
$amountDiscounted = $amountDiscounted * $realQty;
}
if ($amountDiscounted > $item['base_price'] && $realQty == 1) {
$amountDiscounted = $item['base_price'];
unset($report);
}
}
$totalDiscount = $totalDiscount + $amountDiscounted;
$itemReport['item_id'] = $item->id;
$itemReport['product_id'] = $item->product_id;
$itemReport['discount'] = $amountDiscounted;
$itemReport['formatted_discount'] = core()->currency($amountDiscounted);
$report->push($itemReport);
unset($itemReport);
}
$report->discount = $totalDiscount;
$report->formatted_discount = core()->currency($totalDiscount);
return $report;
return $impact;
}
/**
* Calculates the impact on the shipping amount if the rule is apply_to_shipping enabled
*/
public function calculateOnShipping($cart)
public function calculateOnShipping()
{
$cart = \Cart::getCart();

View File

@ -12,50 +12,46 @@ class PercentOfProduct extends Action
$items = $cart->items;
$impact = collect();
$totalDiscount = 0;
if ($rule->discount_amount >= 100) {
$impact->discount = $cart->base_grand_total;
$impact->formatted_discount = core()->currency($impact->discount);
} else {
if ($rule->uses_attribute_conditions) {
$productIds = $rule->product_ids;
$productIDs = $rule->product_ids;
$productIds = explode(',', $productIds);
$productIDs = explode(',', $productIDs);
$matchCount = 0;
foreach ($productIDs as $productID) {
foreach ($items as $item) {
$product = $item->product;
if ($product->type == 'configurable') {
$product = $item->child->product;
if ($item->product_id == $productID) {
$matchCount++;
}
}
}
foreach ($productIds as $productId) {
$disc_threshold = $rule->disc_threshold;
$disc_amount = $rule->disc_amount;
$disc_quantity = $rule->disc_quantity;
$amountDiscounted = 0;
foreach ($productIDs as $productID) {
foreach ($items as $item) {
$itemPrice = $item->base_price;
if ($item->product->type == 'configurable') {
$itemProductId = $item->child->product_id;
} else {
$itemProductId = $item->product_id;
}
$discount = round(($itemPrice * $impact->discount) / 100, 4);
if ($itemProductId == $productID) {
$report = array();
$realQty = $item->quantity;
if ($productId == $product->id && $cart->items_qty >= $disc_threshold) {
// distribute the discount according to ratios in case when rule is getting applied on multiple items
$amountDiscounted = $item->base_price * ($disc_amount / 100);
if ($realQty > $disc_quantity) {
$amountDiscounted = $amountDiscounted * $disc_quantity;
} else {
$amountDiscounted = $amountDiscounted * $realQty;
}
if ($amountDiscounted > $item->base_price && $realQty == 1) {
$amountDiscounted = $item->base_price;
}
$totalDiscount = $totalDiscount + $amountDiscounted;
$report['item_id'] = $item->id;
$report['product_id'] = $productId;
$report['discount'] = $amountDiscounted;
$report['formatted_discount'] = core()->currency($amountDiscounted);
$report['product_id'] = $item->product_id;
$report['discount'] = $discount;
$report['formatted_discount'] = core()->currency($discount);
$impact->push($report);
@ -64,44 +60,23 @@ class PercentOfProduct extends Action
}
}
} else {
$productIds = null;
foreach ($items as $item) {
$product = $item->product;
$itemPrice = $item->base_price;
if ($product->type == 'configurable') {
$product = $item->child->product;
if ($item->product->type == 'configurable') {
$itemProductId = $item->child->product_id;
} else {
$itemProductId = $item->product_id;
}
$disc_threshold = $rule->disc_threshold;
$disc_amount = $rule->disc_amount;
$disc_quantity = $rule->disc_quantity;
$amountDiscounted = 0;
$discount = round(($itemPrice * $impact->discount) / 100, 4);
$report = array();
$realQty = $item->quantity;
if ($productId == $product->id && $cart->items_qty >= $disc_threshold) {
// distribute the discount according to ratios in case when rule is getting applied on multiple items
$amountDiscounted = $item->base_price * ($disc_amount / 100);
if ($realQty > $disc_quantity) {
$amountDiscounted = $amountDiscounted * $disc_quantity;
} else {
$amountDiscounted = $amountDiscounted * $realQty;
}
if ($amountDiscounted > $item->base_price && $realQty == 1) {
$amountDiscounted = $item->base_price;
}
$totalDiscount = $totalDiscount + $amountDiscounted;
$report['item_id'] = $item->id;
$report['product_id'] = $productId;
$report['discount'] = $amountDiscounted;
$report['formatted_discount'] = core()->currency($amountDiscounted);
$report['product_id'] = $item->product_id;
$report['discount'] = $discount;
$report['formatted_discount'] = core()->currency($discount);
$impact->push($report);
@ -110,16 +85,6 @@ class PercentOfProduct extends Action
}
}
// if (isset($rule->apply_on_shipping) && ! $rule->free_shipping) {
// $impact->discount_on_shipping = $this->calculateOnShipping();
// } else {
// $rule->discount_on_shipping = 0;
// $rule->base_discount_on_shipping = 0;
// }
$impact->discount = $totalDiscount;
$impact->formatted_discount = core()->currency($totalDiscount);
return $impact;
}

View File

@ -6,29 +6,83 @@ use Webkul\Discount\Actions\Action;
class WholeCartToFixed extends Action
{
public function calculate($rule, $items, $cart)
public function calculate($rule)
{
$report = collect();
$cart = \Cart::getCart();
$items = $cart->items;
$totalDiscount = 0;
$impact = collect();
$impact->discount = $rule->disc_amount;
$impact->formatted_discount = core()->currency($impact->discount);
if ($rule->uses_attribute_conditions) {
$productIDs = $rule->product_ids;
$productIDs = explode(',', $productIDs);
$matchCount = 0;
foreach ($productIDs as $productID) {
foreach ($items as $item) {
$itemReport = array();
$itemReport['item_id'] = $item->id;
$itemReport['product_id'] = $item->product_id;
$itemReport['discount'] = 0;
$itemReport['formatted_discount'] = core()->currency(0);
$report->push($itemReport);
unset($itemReport);
if ($item->product_id == $productID) {
$matchCount++;
}
}
}
$report->discount = $cart->base_grand_total - $rule->discount_amount;
$report->formatted_discount = core()->currency($report->discount);
foreach ($productIDs as $productID) {
foreach ($items as $item) {
$itemPrice = $item->base_price;
return $report;
if ($item->product->type == 'configurable') {
$itemProductId = $item->child->product_id;
} else {
$itemProductId = $item->product_id;
}
$discount = round(($itemPrice * $impact->discount) / 100, 4);
if ($itemProductId == $productID) {
$report = array();
$report['item_id'] = $item->id;
$report['product_id'] = $item->product_id;
$report['discount'] = $discount;
$report['formatted_discount'] = core()->currency($discount);
$impact->push($report);
unset($report);
}
}
}
} else {
foreach ($items as $item) {
$itemPrice = $item->base_price;
if ($item->product->type == 'configurable') {
$itemProductId = $item->child->product_id;
} else {
$itemProductId = $item->product_id;
}
$discount = round(($itemPrice * $impact->discount) / 100, 4);
$report = array();
$report['item_id'] = $item->id;
$report['product_id'] = $item->product_id;
$report['discount'] = $discount;
$report['formatted_discount'] = core()->currency($discount);
$impact->push($report);
unset($report);
}
}
return $impact;
}
/**

View File

@ -21,7 +21,6 @@ class WholeCartToPercent extends Action
$items = $cart->items;
$impact = collect();
$totalDiscount = 0;
if ($rule->discount_amount >= 100) {
$impact->discount = $cart->base_grand_total;
@ -57,8 +56,8 @@ class WholeCartToPercent extends Action
$report['item_id'] = $item->id;
$report['product_id'] = $item->product_id;
$report['discount'] = $discountPerItem;
$report['formatted_discount'] = core()->currency(0);
$report['discount'] = round($discountPerItem, 4);
$report['formatted_discount'] = core()->currency(round($discountPerItem, 4));
$impact->push($report);
@ -67,15 +66,15 @@ class WholeCartToPercent extends Action
}
}
} else {
$discountPerItem = $report->discount / $cart->items_qty;
$discountPerItem = $impact->discount / $cart->items_qty;
foreach ($items as $item) {
$report = array();
$report['item_id'] = $item->id;
$report['product_id'] = $item->product_id;
$report['discount'] = $discountPerItem;
$report['formatted_discount'] = core()->currency(0);
$report['discount'] = round($discountPerItem, 4);
$report['formatted_discount'] = core()->currency(round($discountPerItem, 4));
$impact->push($report);

View File

@ -3,16 +3,16 @@
return [
'cart' => [
'percent_of_product' => 'Webkul\Discount\Actions\Cart\PercentOfProduct',
'fixed_amount' => 'Webkul\Discount\Actions\Cart\FixedAmount',
// 'whole_cart_to_fixed' => 'Webkul\Discount\Actions\Cart\WholeCartToFixed',
'percent_of_product' => 'Webkul\Discount\Actions\Cart\PercentOfProduct',
// 'whole_cart_to_fixed' => 'aWebkul\Discount\Actions\Cart\WholeCartToFixed',
'whole_cart_to_percent' => 'Webkul\Discount\Actions\Cart\WholeCartToPercent'
],
'catalog' => [
'percent_of_original' => 'Webkul\Discount\Actions\Catalog\PercentOfOriginal',
'fixed_amount' => 'Webkul\Discount\Actions\Catalog\FixedAmount',
'final_price_to_percent' => 'Webkul\Discount\Actions\Catalog\AdjustToPercent',
'percent_of_original' => 'Webkul\Discount\Actions\Catalog\PercentOfOriginal',
'to_discount_value' => 'Webkul\Discount\Actions\Catalog\AdjustToDiscountValue'
]
];

View File

@ -6,32 +6,10 @@ return [
'any_is_true' => 'Any condition is true',
],
'conditions' => [
'numeric' => [
0 => 'Equals',
1 => 'Equals or greater',
2 => 'Equals or lesser',
3 => 'Greater than',
4 => 'Lesser than'
],
'text' => [
0 => 'is',
1 => 'is not',
2 => 'contains',
3 => 'does not contains'
],
'boolean' => [
0 => 'True/Yes',
1 => 'False/No',
]
],
'cart' => [
'actions' => [
'percent_of_product' => 'Percentage of product',
'fixed_amount' => 'Apply as fixed amount',
'percent_of_product' => 'Percentage of product',
// 'whole_cart_to_fixed' => 'Adjust whole cart to fixed amount',
'whole_cart_to_percent' => 'Adjust whole cart to percent'
],
@ -39,8 +17,8 @@ return [
'validation' => [
0 => 'percent_of_product',
1 => 'fixed_amount',
2 => 'adjust_to_percent',
3 => 'fixed_amount_cart'
2 => 'whole_cart_to_percent',
3 => 'whole_cart_to_fixed'
],
'conditions' => [
@ -49,7 +27,7 @@ return [
'>=' => 'Greater or equals',
'<=' => 'Lesser or equals',
'>' => 'Greater than',
'<' => 'Lesser than',
'<' => 'Lesser than'
],
'string' => [
@ -74,7 +52,7 @@ return [
'>' => 'greater_than',
'<' => 'lesser_than',
'{}' => 'contains',
'={}' => 'is_one_f',
'={}' => 'is_one_of',
'!={}' => 'is_not_one_of',
'!{}' => 'does_not_contains'
]
@ -175,7 +153,7 @@ return [
'>' => 'greater_than',
'<' => 'lesser_than',
'{}' => 'contains',
'={}' => 'is_one_f',
'={}' => 'is_one_of',
'!={}' => 'is_not_one_of',
'!{}' => 'does_not_contains'
]

View File

@ -61,6 +61,7 @@ abstract class Discount
// time based constraints
foreach ($rules as $rule) {
if ($this->checkApplicability($rule)) {
if ($rule->starts_from != null && $rule->ends_till == null) {
if (Carbon::parse($rule->starts_from) < now()) {
$rule->impact = $this->calculateImpact($rule);
@ -85,10 +86,136 @@ abstract class Discount
$filteredRules->push($rule);
}
}
}
dd($filteredRules, 'called by this');
if (count($filteredRules) && count($filteredRules) > 1) {
$filteredRule = $this->breakTie($filteredRules);
return $filteredRules;
return $filteredRule;
} else {
$filteredRule = $filteredRules->first();
return $filteredRule;
}
}
/**
* To find that one rule that is going to be applied on the current cart
*
* @param Collection $rules
*
* @return Object
*/
public function breakTie($rules)
{
// priority criteria
$prioritySorted = array();
$leastPriority = 999999999999;
foreach ($applicableRules as $applicableRule) {
if ($applicableRule['rule']->priority <= $leastPriority) {
$leastPriority = $applicableRule['rule']->priority;
array_push($prioritySorted, $applicableRule);
}
}
// end rule criteria with end rule
$endRules = array();
if (count($prioritySorted) > 1) {
foreach ($prioritySorted as $prioritySortedRule) {
if ($prioritySortedRule['rule']->end_other_rules) {
array_push($endRules, $prioritySortedRule);
}
}
} else {
$this->save(array_first($prioritySorted)['rule']);
return $prioritySorted;
}
// max impact criteria with end rule
$maxImpacts = array();
if (count($endRules)) {
$this->endRuleActive = true;
if (count($endRules) == 1) {
$this->save(array_first($endRules)['rule']);
return array_first($endRules)['impact'];
}
$maxImpact = 0;
foreach ($endRules as $endRule) {
if ($endRule['impact']->discount >= $maxImpact) {
$maxImpact = $endRule['impact']->discount;
array_push($maxImpacts, $endRule);
}
}
// oldest and max impact criteria
$leastId = 999999999999;
$leastIdImpactIndex = 0;
if (count($maxImpacts) > 1) {
foreach ($maxImpacts as $index => $maxImpactRule) {
if ($maxImpactRule['rule']->id < $leastId) {
$leastId = $maxImpactRule['rule']->id;
$leastIdImpactIndex = $index;
}
}
$this->save($maxImpacts[$leastIdImpactIndex]['rule']);
return $maxImpacts[$leastIdImpactIndex];
} else {
$this->save(array_first($maxImpacts)['rule']);
return $maxImpacts;
}
}
if (count($prioritySorted) > 1) {
$maxImpact = 0;
foreach ($prioritySorted as $prioritySortedRule) {
if ($prioritySortedRule['impact']->discount >= $maxImpact) {
$maxImpact = $prioritySortedRule['impact']->discount;
array_push($maxImpacts, $prioritySortedRule);
}
}
// oldest and max impact criteria
$leastId = 999999999999;
$leastIdImpactIndex = 0;
if (count($maxImpacts) > 1) {
foreach ($maxImpacts as $index => $maxImpactRule) {
if ($maxImpactRule['rule']->id < $leastId) {
$leastId = $maxImpactRule['rule']->id;
$leastIdImpactIndex = $index;
}
}
$this->save($maxImpacts[$leastIdImpactIndex]['rule']);
return $maxImpacts[$leastIdImpactIndex];
} else {
$this->save(array_first($maxImpacts)['rule']);
return array_first($applicableRules)['impact'];
}
} else {
$this->save(array_first($prioritySorted)['rule']);
return $prioritySorted;
}
}
/**

View File

@ -128,7 +128,7 @@ class CartRuleController extends Controller
'action_type' => 'required|string',
'disc_amount' => 'required|numeric',
'disc_quantity' => 'numeric',
'disc_threshold' => 'numeric',
// 'disc_threshold' => 'numeric',
'free_shipping' => 'required|boolean',
'apply_to_shipping' => 'required|boolean',
'code' => 'string|required_if:auto_generation,0',
@ -361,7 +361,7 @@ class CartRuleController extends Controller
'action_type' => 'required|string',
'disc_amount' => 'required|numeric',
'disc_quantity' => 'required|numeric',
'disc_threshold' => 'required|numeric',
// 'disc_threshold' => 'required|numeric',
'free_shipping' => 'required|boolean',
'apply_to_shipping' => 'required|boolean',
'code' => 'string|required_if:user_coupon,1',
@ -416,7 +416,6 @@ class CartRuleController extends Controller
$data['actions'] = [
'action_type' => $data['action_type'],
'disc_amount' => $data['disc_amount'],
'disc_threshold' => $data['disc_threshold']
];
$data['disc_quantity'] = $data['disc_amount'];