Merge pull request #1047 from prashant-webkul/development

Development
This commit is contained in:
Jitendra Singh 2019-06-17 14:23:31 +05:30 committed by GitHub
commit 106cd039db
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 1050 additions and 753 deletions

View File

@ -0,0 +1,7 @@
<?php
return [
];
?>

View File

@ -96,7 +96,7 @@ return [
'key' => 'configuration',
'name' => 'admin::app.layouts.configure',
'route' => 'admin.configuration.index',
'sort' => 5,
'sort' => 7,
'icon-class' => 'configuration-icon',
], [
'key' => 'settings',
@ -177,23 +177,16 @@ return [
'sort' => 2,
'icon-class' => '',
], [
'key' => 'promotion',
'key' => 'promotions',
'name' => 'admin::app.layouts.promotion',
'route' => 'admin.cart-rule.index',
'sort' => 7,
'sort' => 5,
'icon-class' => 'promotion-icon',
], [
'key' => 'promotion.cart-rule',
'key' => 'promotions.cart-rule',
'name' => 'admin::app.promotion.cart-rule',
'route' => 'admin.cart-rule.index',
'sort' => 1,
'icon-class' => '',
]
// , [
// 'key' => 'promotion.catalog-rule',
// 'name' => 'admin::app.promotion.catalog-rule',
// 'route' => 'admin.catalog-rule.index',
// 'sort' => 1,
// 'icon-class' => '',
// ]
];

View File

@ -649,27 +649,27 @@ Route::group(['middleware' => ['web']], function () {
// Route::post('fetch/options', 'Webkul\Discount\Http\Controllers\CatalogRuleController@fetchAttributeOptions')->name('admin.catalog-rule.options');
Route::get('/cart-rules', 'Webkul\Discount\Http\Controllers\CartRuleController@index')->defaults('_config', [
Route::get('cart-rules', 'Webkul\Discount\Http\Controllers\CartRuleController@index')->defaults('_config', [
'view' => 'admin::promotions.cart-rule.index'
])->name('admin.cart-rule.index');
Route::get('/cart-rule/create', 'Webkul\Discount\Http\Controllers\CartRuleController@create')->defaults('_config', [
Route::get('cart-rules/create', 'Webkul\Discount\Http\Controllers\CartRuleController@create')->defaults('_config', [
'view' => 'admin::promotions.cart-rule.create'
])->name('admin.cart-rule.create');
Route::post('/cart-rule/store', 'Webkul\Discount\Http\Controllers\CartRuleController@store')->defaults('_config', [
Route::post('cart-rules/store', 'Webkul\Discount\Http\Controllers\CartRuleController@store')->defaults('_config', [
'redirect' => 'admin.cart-rule.index'
])->name('admin.cart-rule.store');
Route::get('/cart-rule/edit/{id}', 'Webkul\Discount\Http\Controllers\CartRuleController@edit')->defaults('_config', [
Route::get('cart-rules/edit/{id}', 'Webkul\Discount\Http\Controllers\CartRuleController@edit')->defaults('_config', [
'view' => 'admin::promotions.cart-rule.edit'
])->name('admin.cart-rule.edit');
Route::post('/cart-rule/update/{id}', 'Webkul\Discount\Http\Controllers\CartRuleController@update')->defaults('_config', [
Route::post('cart-rules/update/{id}', 'Webkul\Discount\Http\Controllers\CartRuleController@update')->defaults('_config', [
'redirect' => 'admin.cart-rule.index'
])->name('admin.cart-rule.update');
Route::post('/cart-rule/delete/{id}', 'Webkul\Discount\Http\Controllers\CartRuleController@destroy')->name('admin.cart-rule.delete');
Route::post('cart-rules/delete/{id}', 'Webkul\Discount\Http\Controllers\CartRuleController@destroy')->name('admin.cart-rule.delete');
});
});
});

View File

@ -31,7 +31,7 @@
@endif
</ul>
{{-- <div class="close-nav-aside">
<!-- <div class="close-nav-aside">
<i class="icon angle-left-icon close-icon"></i>
</div> --}}
</div> -->
</div>

View File

@ -213,7 +213,7 @@
<div v-if='conditions_list[index].type == "string"'>
<select class="control" name="cart_attributes[]" v-model="conditions_list[index].condition" style="margin-right: 15px;">
<option v-for="(condition, index) in conditions.numeric" :value="index" :key="index">@{{ condition }}</option>
<option v-for="(condition, index) in conditions.string" :value="index" :key="index">@{{ condition }}</option>
</select>
<div v-if='conditions_list[index].attribute == "shipping_state"'>
@ -459,15 +459,13 @@
}
},
mounted () {
},
methods: {
addCondition () {
if (this.criteria == 'product_subselection' || this.criteria == 'cart') {
this.condition_on = this.criteria;
} else {
alert('please try again');
alert('Please select type of condition');
return false;
}
@ -476,7 +474,6 @@
this.conditions_list.push(this.cart_object);
this.cart_object = {
criteria: null,
attribute: null,
condition: null,
value: []
@ -503,7 +500,6 @@
for (i in this.cart_input) {
if (i == selectedIndex) {
this.conditions_list[index].type = this.cart_input[i].type;
console.log(this.conditions_list[index]);
}
}
},
@ -526,10 +522,10 @@
onSubmit: function (e) {
if (this.conditions_list.length != 0) {
this.conditions_list.test_mode = this.match_criteria;
}
this.conditions_list.push({'criteria': this.match_criteria});
this.all_conditions = JSON.stringify(this.conditions_list);
this.all_conditions = JSON.stringify(this.conditions_list);
}
this.$validator.validateAll().then(result => {
if (result) {

View File

@ -76,7 +76,7 @@
</div>
</datetime>
{{-- <div class="control-group" :class="[errors.has('customer_groups[]') ? 'has-error' : '']">
<div class="control-group" :class="[errors.has('customer_groups[]') ? 'has-error' : '']">
<label for="customer_groups" class="required">{{ __('admin::app.promotion.general-info.cust-groups') }}</label>
<select type="text" class="control" name="customer_groups[]" v-model="customer_groups" v-validate="'required'" value="{{ old('customer_groups[]') }}" data-vv-as="&quot;{{ __('admin::app.promotion.general-info.cust-groups') }}&quot;" multiple="multiple">
@ -86,8 +86,8 @@
@endforeach
</select>
<span class="control-error" v-if="errors.has('customer_groups')">@{{ errors.first('customer_groups') }}</span>
</div> --}}
<span class="control-error" v-if="errors.has('customer_groups[]')">@{{ errors.first('customer_groups[]') }}</span>
</div>
<div class="control-group" :class="[errors.has('channels[]') ? 'has-error' : '']">
<label for="channels" class="required">{{ __('admin::app.promotion.general-info.channels') }}</label>
@ -187,7 +187,7 @@
<div class="control-group">
{{ __('admin::app.promotion.general-info.test-mode') }}
<select class="control" v-model="match_criteria" style="margin-right: 15px;">
<select class="control" v-model="match_criteria" name="match_criteria" style="margin-right: 15px;">
{{ $i = 0 }}
@foreach(config('pricerules.test_mode') as $key => $value)
<option value="{{ $key }}">{{ $value }}</option>
@ -213,7 +213,7 @@
<div v-if='conditions_list[index].type == "string"'>
<select class="control" name="cart_attributes[]" v-model="conditions_list[index].condition" style="margin-right: 15px;">
<option v-for="(condition, index) in conditions.numeric" :value="index" :key="index">@{{ condition }}</option>
<option v-for="(condition, index) in conditions.string" :value="index" :key="index">@{{ condition }}</option>
</select>
<div v-if='conditions_list[index].attribute == "shipping_state"'>
@ -501,6 +501,7 @@
if (data.conditions != null) {
this.conditions_list = JSON.parse(JSON.parse(data.conditions));
this.match_criteria = this.conditions_list.pop().criteria;
}
criteria = null;
@ -511,7 +512,7 @@
if (this.criteria == 'product_subselection' || this.criteria == 'cart') {
this.condition_on = this.criteria;
} else {
alert('please try again');
alert('please select type of condition');
return false;
}
@ -567,14 +568,11 @@
},
onSubmit: function (e) {
if (this.conditions_list.length != 0) {
this.conditions_list.push({'criteria': this.match_criteria});
// if (this.conditions_list.length != 0) {
// this.conditions_list.push(this.match_criteria);
// }
console.log(JSON.stringify(this.conditions_list));
this.all_conditions = JSON.stringify(this.conditions_list);
this.all_conditions = JSON.stringify(this.conditions_list);
}
this.$validator.validateAll().then(result => {
if (result) {

View File

@ -12,8 +12,6 @@ use Webkul\Tax\Repositories\TaxCategoryRepository;
use Webkul\Checkout\Models\CartPayment;
use Webkul\Customer\Repositories\WishlistRepository;
use Webkul\Customer\Repositories\CustomerAddressRepository;
use Webkul\Discount\Repositories\CartRuleRepository as CartRule;
use Webkul\Discount\Helpers\Discount;
use Webkul\Product\Helpers\Price;
/**
@ -81,16 +79,6 @@ class Cart {
*/
protected $customerAddress;
/**
* CartRule Repository instance
*/
protected $cartRule;
/**
* Discount helper instance
*/
protected $discount;
/**
* Suppress the session flash messages
*/
@ -125,8 +113,6 @@ class Cart {
TaxCategoryRepository $taxCategory,
WishlistRepository $wishlist,
CustomerAddressRepository $customerAddress,
CartRule $cartRule,
Discount $discount,
Price $price
)
{
@ -146,10 +132,6 @@ class Cart {
$this->customerAddress = $customerAddress;
$this->cartRule = $cartRule;
$this->discount = $discount;
$this->price = $price;
$this->suppressFlash = false;
@ -1235,95 +1217,4 @@ class Cart {
}
}
}
public function applyCoupon($code)
{
$result = $this->discount->applyCouponAbleRule($code);
return $result;
}
public function applyNonCoupon()
{
$result = $this->discount->applyNonCouponAbleRule();
return $result;
}
/**
* Removes discount from the cart and calls collect totals
*
* @return void
*/
public function clearDiscount()
{
$cartItems = $this->getCart()->items;
foreach($cartItems as $item) {
$item->update([
'coupon_code' => NULL,
'discount_percent' => 0,
'discount_amount' => 0,
'base_discount_amount' => 0
]);
}
$this->getCart()->update([
'coupon_code' => NULL,
'discount_amount' => 0,
'base_discount_amount' => 0
]);
return true;
}
public function removeCoupon()
{
$result = $this->discount->removeCoupon();
return $result;
}
public function leastWorthItem()
{
$cart = $this->getCart();
$leastValue = 999999999999;
$leastSubTotal = [];
foreach ($cart->items as $item) {
if ($item->price < $leastValue) {
$leastValue = $item->price;
$leastSubTotal = [
'id' => $item->id,
'total' => $item->total,
'base_total' => $leastValue,
'quantity' => $item->quantity,
'price' => $item->price
];
}
}
return $leastSubTotal;
}
public function maxWorthItem()
{
$cart = $this->getCart();
$maxValue = 0;
$maxSubTotal = [];
foreach ($cart->items as $item) {
if ($item->base_total > $maxValue) {
$maxValue = $item->total;
$maxSubTotal = [
'id' => $item->id,
'total' => $item->total,
'base_total' => $maxValue,
'quantity' => $item->quantity
];
}
}
return $maxSubTotal;
}
}

View File

@ -69,17 +69,17 @@ class Tree {
/**
* Add a Config item to the item stack
*
* @param string $item Dot seperated heirarchy
* @param string $item Dot seperated heirarchy
*/
public function add($item, $type = '')
{
$item['children'] = [];
if ($type == 'menu') {
$item['url'] = route($item['route']);
$item['url'] = route($item['route']);
if (strpos($this->current, $item['url']) !== false) {
$this->currentKey = $item['key'];
$this->currentKey = $item['key'];
}
} else if ($type == 'acl') {
$item['name'] = trans($item['name']);

View File

@ -0,0 +1,8 @@
<?php
namespace Webkul\Discount\Actions;
abstract class Action
{
abstract public function calculate($rule, $item, $cart);
}

View File

@ -0,0 +1,38 @@
<?php
namespace Webkul\Discount\Actions;
use Webkul\Discount\Actions\Action;
class BuyAGetB extends Action
{
public function calculate($rule, $item, $cart)
{
//calculate discount amount
$action_type = $rule->action_type; // action type used
$disc_threshold = $rule->disc_threshold; // atleast quantity by default 1
$disc_amount = $rule->disc_amount; // value of discount
$disc_quantity = $rule->disc_quantity; //max quantity allowed to be discounted
$amountDiscounted = 0;
$realQty = $item['quantity'];
if ($cart->items_qty >= $disc_threshold) {
$amountDiscounted = $disc_amount;
if ($realQty > $disc_quantity) {
$amountDiscounted = $amountDiscounted * $disc_quantity;
}
if ($amountDiscounted > $item['price']) {
$amountDiscounted = $item['price'];
}
}
$report['discount'] = $amountDiscounted;
$report['formatted_discount'] = core()->formatPrice($amountDiscounted, $cart->cart_currency_code);
return $report;
}
}

View File

@ -0,0 +1,38 @@
<?php
namespace Webkul\Discount\Actions;
use Webkul\Discount\Actions\Action;
class FixedAmount extends Action
{
public function calculate($rule, $item, $cart)
{
//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
$amountDiscounted = 0;
$realQty = $item['quantity'];
if ($cart >= $disc_threshold) {
$amountDiscounted = $disc_amount;
if ($realQty > $disc_quantity) {
$amountDiscounted = $amountDiscounted * $disc_quantity;
}
if ($amountDiscounted > $item['price']) {
$amountDiscounted = $item['price'];
}
}
$report['discount'] = $amountDiscounted;
$report['formatted_discount'] = core()->formatPrice($amountDiscounted, $cart->cart_currency_code);
return $report;
}
}

View File

@ -0,0 +1,35 @@
<?php
namespace Webkul\Discount\Actions;
use Webkul\Discount\Actions\Action;
class PercentOfProduct extends Action
{
public function calculate($rule, $item, $cart)
{
$amountDiscounted = 0;
$disc_threshold = $rule->disc_threshold;
$disc_amount = $rule->disc_amount;
$disc_quantity = $rule->disc_quantity;
$realQty = $item['quantity'];
if ($cart >= $disc_threshold) {
$amountDiscounted = $item['price'] * ($disc_amount / 100);
if ($realQty > $disc_quantity) {
$amountDiscounted = $amountDiscounted * $disc_quantity;
}
if ($amountDiscounted > $item['price']) {
$amountDiscounted = $item['price'];
}
}
$report['discount'] = $amountDiscounted;
$report['formatted_discount'] = core()->formatPrice($amountDiscounted, $cart->cart_currency_code);
return $report;
}
}

View File

@ -0,0 +1,7 @@
<?php
return [
'percent_of_product' => 'Webkul\Discount\Actions\PercentOfProduct',
'fixed_amount' => 'Webkul\Discount\Actions\FixedAmount',
'buy_a_get_b' => 'Webkul\Discount\Actions\BuyAGetB'
];

View File

@ -1,6 +1,13 @@
<?php
return [
'test_mode' => [
'all_are_true' => 'All conditions are true',
// 'all_are_false' => 'All conditions are false',
'any_is_true' => 'Any condition is true',
// 'any_is_false' => 'Any condition is false'
],
'conditions' => [
'numeric' => [
0 => 'Equals',
@ -23,52 +30,12 @@ return [
]
],
'catalog' => [
'actions' => [
0 => 'admin::app.promotion.catalog.apply-percent',
1 => 'admin::app.promotion.catalog.apply-fixed',
2 => 'admin::app.promotion.catalog.adjust-to-percent',
// 3 => 'admin::app.promotion.catalog.adjust-to-value'
],
'attributes' => [
0 => [
'name' => 'Sub-total',
'type' => 'numeric'
],
1 => [
'name' => 'Total Items Quantity',
'type' => 'numeric'
],
2 => [
'name' => 'Total Weight',
'type' => 'numeric'
],
3 => [
'name' => 'Payment Method',
'type' => 'string'
],
4 => [
'name' => 'Shipping Postcode',
'type' => 'string'
],
5 => [
'name' => 'Shipping State',
'type' => 'string'
],
6 => [
'name' => 'Shipping Country',
'type' => 'string'
]
]
],
'cart' => [
'actions' => [
'percent_of_product' => 'Percentage of product',
'fixed_amount' => 'Apply as fixed amount',
'buy_a_get_b' => 'Get B amount back',
// 'fixed_amount_cart' => 'Fixed amount for whole cart'
'fixed_amount_cart' => 'Whole cart gets discounted'
],
'validation' => [
@ -87,22 +54,12 @@ return [
'<' => 'Lesser than',
],
'text' => [
'=' => 'Equals',
'>=' => 'Greater or equals',
'<=' => 'Lesser or equals',
'>' => 'Greater than',
'<' => 'Lesser than',
'{}' => 'Contains',
'!{}' => 'Does not contains'
],
'string' => [
'=' => 'Equals',
'>=' => 'Greater or equals',
'<=' => 'Lesser or equals',
'>' => 'Greater than',
'<' => 'Lesser than',
// '>=' => 'Greater or equals',
// '<=' => 'Lesser or equals',
// '>' => 'Greater than',
// '<' => 'Lesser than',
'{}' => 'Contains',
'!{}' => 'Does not contains'
],
@ -162,10 +119,43 @@ return [
]
],
'test_mode' => [
'all_are_true' => 'All conditions are true',
'all_are_false' => 'All conditions are false',
'any_is_true' => 'Any condition is true',
'any_is_false' => 'Any condition is false'
]
'catalog' => [
'actions' => [
0 => 'admin::app.promotion.catalog.apply-percent',
1 => 'admin::app.promotion.catalog.apply-fixed',
2 => 'admin::app.promotion.catalog.adjust-to-percent',
// 3 => 'admin::app.promotion.catalog.adjust-to-value'
],
'attributes' => [
0 => [
'name' => 'Sub-total',
'type' => 'numeric'
],
1 => [
'name' => 'Total Items Quantity',
'type' => 'numeric'
],
2 => [
'name' => 'Total Weight',
'type' => 'numeric'
],
3 => [
'name' => 'Payment Method',
'type' => 'string'
],
4 => [
'name' => 'Shipping Postcode',
'type' => 'string'
],
5 => [
'name' => 'Shipping State',
'type' => 'string'
],
6 => [
'name' => 'Shipping Country',
'type' => 'string'
]
]
],
];

View File

@ -0,0 +1,156 @@
<?php
namespace Webkul\Discount\Helpers;
use Webkul\Discount\Helpers\Discount;
use Carbon\Carbon;
use Cart;
class CouponAbleRule extends Discount
{
/**
* Applies the couponable rule on the current cart instance
*
* @return mixed
*/
public function apply($code)
{
$cart = Cart::getCart();
if (auth()->guard('customer')->check()) {
$rules = $this->cartRule->findWhere([
'use_coupon' => 1,
'status' => 1
]);
} else {
$rules = $this->cartRule->findWhere([
'use_coupon' => 1,
'is_guest' => 1,
'status' => 1
]);
}
$applicableRule = null;
foreach($rules as $rule) {
if ($rule->use_coupon && ($rule->coupons->code == $code)) {
$applicableRule = $rule;
break;
}
}
$applicability = $this->checkApplicability($applicableRule);
if ($applicability) {
$item = $this->leastWorthItem();
$actionInstance = new $this->rules[$applicableRule->action_type];
$impact = $actionInstance->calculate($applicableRule, $item, $cart);
$ifAlreadyApplied = $this->cartRuleCart->findWhere([
'cart_id' => $cart->id,
'cart_rule_id' => $applicableRule->id
]);
if ($ifAlreadyApplied->count() == 1) {
return false;
}
$ifAlreadyApplied = $this->cartRuleCart->findWhere([
'cart_id' => $cart->id,
]);
if ($ifAlreadyApplied->count() == 0) {
$this->save($applicableRule);
return $impact;
}
$alreadyAppliedRule = $ifAlreadyApplied->first()->cart_rule;
if ($alreadyAppliedRule->priority < $rule->priority) {
return false;
} else if ($alreadyAppliedRule->priority == $applicableRule->priority) {
// tie breaker case
// end other rules
if ($alreadyAppliedRule->end_other_rules) {
return false;
}
$actionInstance = new $this->rules[$alreadyAppliedRule->action_type];
$alreadyAppliedRuleImpact = $actionInstance->calculate($alreadyAppliedRule, $item, $cart);
if ($alreadyAppliedRule['discount'] > $impact['discount']) {
return false;
} else if ($alreadyAppliedRule['discount'] < $impact['discount']) {
$this->save($applicableRule);
return $impact;
} else {
// least id case
if ($applicableRule->id < $alreadyAppliedRule->id) {
$this->save($applicableRule);
return $impact;
}
}
} else {
$this->save($applicableRule);
return $impact;
}
} else {
return false;
}
}
/**
* Removes the already applied coupon on the current cart instance
*
* @return boolean
*/
public function remove()
{
$cart = Cart::getCart();
$existingRule = $this->cartRuleCart->findWhere([
'cart_id' => $cart->id
]);
if ($existingRule->count()) {
if ($existingRule->first()->cart_rule->use_coupon) {
$existingRule->first()->delete();
foreach ($cart->items as $item) {
if ($item->discount_amount > 0) {
$item->update([
'discount_amount' => 0,
'base_discount_amount' => 0,
'discount_percent' => 0,
'coupon_code' => NULL
]);
}
}
$cart->update([
'coupon_code' => NULL,
'discount_amount' => 0,
'base_discount_amount' => 0
]);
Cart::collectTotals();
return true;
} else {
return false;
}
} else {
return false;
}
}
}

View File

@ -5,9 +5,9 @@ namespace Webkul\Discount\Helpers;
use Webkul\Discount\Repositories\CartRuleRepository as CartRule;
use Webkul\Discount\Repositories\CartRuleCartRepository as CartRuleCart;
use Carbon\Carbon;
use Arr;
use Cart;
class Discount
abstract class Discount
{
/**
* To hold the cart rule repository instance
@ -24,6 +24,11 @@ class Discount
*/
protected $endRuleActive = false;
/**
* To hold the rule classes
*/
protected $rules;
/**
* disable coupon
*/
@ -32,400 +37,95 @@ class Discount
public function __construct(CartRule $cartRule, CartRuleCart $cartRuleCart)
{
$this->cartRule = $cartRule;
$this->endRuleActive = false;
$this->cartRuleCart = $cartRuleCart;
$this->rules = config('discount-rules');
}
/**
* Applies the non couponable rule on the current cart
*
* @return mixed
* Abstract method apply
*/
public function applyNonCouponAbleRule()
abstract public function apply($code);
/**
* Checks whether coupon is getting applied on current cart instance or not
*
* @return boolean
*/
public function checkApplicability($rule)
{
$cart = \Cart::getCart();
$previousRule = $this->cartRuleCart->findWhere([
'cart_id' => $cart->id
]);
$timeBased = false;
if ($previousRule->count()) {
$previousRule = $previousRule->first()->cart_rule;
if ($previousRule->use_coupon) {
return 'false';
// time based constraints
if ($rule->starts_from != null && $rule->ends_till == null) {
if (Carbon::parse($rule->starts_from) < now()) {
$timeBased = true;
}
} else if ($rule->starts_from == null && $rule->ends_till != null) {
if (Carbon::parse($rule->ends_till) > now()) {
$timeBased = true;
}
} else if ($rule->starts_from != null && $rule->ends_till != null) {
if (Carbon::parse($rule->starts_from) < now() && now() < Carbon::parse($rule->ends_till)) {
$timeBased = true;
}
} else {
\Cart::clearDiscount();
$timeBased = true;
}
$channelBased = false;
// channel based constraints
foreach ($rule->channels as $channel) {
if ($channel->channel_id == core()->getCurrentChannel()->id) {
$channelBased = true;
}
}
$customerGroupBased = false;
// customer groups based constraints
if (auth()->guard('customer')->check()) {
$nonCouponAbleRules = $this->cartRule->findWhere([
'use_coupon' => 0,
'status' => 1
]);
foreach ($rule->customer_groups as $customer_group) {
if ($customer_group->customer_group_id == auth()->guard('customer')->user()->group->id) {
$customerGroupBased = true;
}
}
} else {
$nonCouponAbleRules = $this->cartRule->findWhere([
'use_coupon' => 0,
'is_guest' => 1,
'status' => 1
]);
}
$canBeApplied = array();
// time based filter
foreach($nonCouponAbleRules as $rule) {
$report = $this->checkApplicability($rule);
$report['rule'] = $rule;
$passed = 0;
if ($rule->starts_from != null && $rule->ends_till == null) {
if (Carbon::parse($rule->starts_from) < now()) {
$passed = 1;
}
} else if ($rule->starts_from == null && $rule->ends_till != null) {
if (Carbon::parse($rule->ends_till) > now()) {
$passed = 1;
}
} else if ($rule->starts_from != null && $rule->ends_till != null) {
if (Carbon::parse($rule->starts_from) < now() && now() < Carbon::parse($rule->ends_till)) {
$passed = 1;
}
} else {
$passed = 1;
}
if ($passed) {
$report['used_coupon'] = false;
array_push($canBeApplied, $report);
if ($rule->is_guest) {
$customerGroupBased = true;
}
}
//min priority
$minPriority = collect($canBeApplied)->min('priority');
$canBeApplied = collect($canBeApplied)->where('priority', $minPriority);
if (count($canBeApplied) > 1) {
$maxDiscount = collect($canBeApplied)->max('discount');
$canBeApplied = collect($canBeApplied)->where('discount', $maxDiscount);
$leastId = 999999999999;
if (count($canBeApplied) > 1) {
foreach($canBeApplied as $rule) {
if ($rule['rule']->id < $leastId) {
$leastId = $rule['rule']->id;
}
}
// fighting the edge case for non couponable discount rule
foreach($canBeApplied as $rule) {
if ($rule['rule']->id == $leastId) {
$rule['used_coupon'] = false;
foreach (\Cart::getCart()->items as $item) {
if ($item->id == $itemId['item_id']) {
$item->update([
'discount_amount' => array_first($canBeApplied)['discount'],
'base_discount_amount' => array_first($canBeApplied)['discount']
]);
break;
}
}
$this->save($rule['rule']);
return $rule;
}
}
}
}
if ($canBeApplied->count()) {
$itemId = array_first($canBeApplied);
foreach (\Cart::getCart()->items as $item) {
if ($item->id == $itemId['item_id']) {
$item->update([
'discount_amount' => array_first($canBeApplied)['discount'],
'base_discount_amount' => array_first($canBeApplied)['discount']
]);
break;
}
}
$this->save(array_first($canBeApplied)['rule']);
return array_first($canBeApplied);
} else {
return 'false';
}
}
/**
* Applies the couponable rule on the current cart
*
* @return mixed
*/
public function applyCouponAbleRule($code)
{
$cart = \Cart::getCart();
if (auth()->guard('customer')->check()) {
$couponAbleRules = $this->cartRule->findWhere([
'use_coupon' => 1,
'status' => 1
]);
} else {
$couponAbleRules = $this->cartRule->findWhere([
'use_coupon' => 1,
'is_guest' => 1,
'status' => 1
]);
}
foreach ($couponAbleRules as $couponAbleRule) {
if ($couponAbleRule->coupons->code == $code) {
$rule = $couponAbleRule;
}
}
$useCouponable = false;
if (isset($rule)) {
$canBeApplied = array();
// time based filter
$report = $this->checkApplicability($rule);
$report['rule'] = $rule;
$passed = 0;
if ($rule->starts_from != null && $rule->ends_till == null) {
if (Carbon::parse($rule->starts_from) < now()) {
$passed = 1;
}
} else if ($rule->starts_from == null && $rule->ends_till != null) {
if (Carbon::parse($rule->ends_till) > now()) {
$passed = 1;
}
} else if ($rule->starts_from != null && $rule->ends_till != null) {
if (Carbon::parse($rule->starts_from) < now() && now() < Carbon::parse($rule->ends_till)) {
$passed = 1;
}
} else {
$passed = 1;
}
if ($passed) {
array_push($canBeApplied, $report);
$useCouponable = true;
$alreadyAppliedRule = $this->cartRuleCart->findWhere([
'cart_id' => \Cart::getCart()->id
]);
if ($alreadyAppliedRule->count() && ! ($alreadyAppliedRule->first()->cart_rule->priority < $canBeApplied[0]['rule']->priority)) {
unset($report);
$alreadyAppliedRule = $alreadyAppliedRule->first()->cart_rule;
// analyze impact
if ($alreadyAppliedRule->id != $rule->id) {
$report = $this->checkApplicability($alreadyAppliedRule);
$report['rule'] = $alreadyAppliedRule;
array_push($canBeApplied, $report);
//min priority
$minPriority = collect($canBeApplied)->min('priority');
//min priority rule
$canBeApplied = collect($canBeApplied)->where('priority', $minPriority);
if (count($canBeApplied) > 1) {
$maxDiscount = collect($canBeApplied)->max('discount');
$canBeApplied = collect($canBeApplied)->where('discount', $maxDiscount);
$leastId = 999999999999;
if (count($canBeApplied) > 1) {
foreach($canBeApplied as $rule) {
if ($rule['rule']->id < $leastId) {
$leastId = $rule['rule']->id;
}
}
// fighting the edge case for couponable discount rule
foreach($canBeApplied as $rule) {
if ($rule['rule']->id == $leastId) {
if($rule['rule']->use_coupon) {
$useCouponable = true;
}
}
}
} else {
if (array_first($canBeApplied)['rule']->use_coupon) {
$useCouponable = true;
}
}
} else if (count($canBeApplied)) {
if (array_first($canBeApplied)['rule']->use_coupon) {
$useCouponable = true;
}
}
if ($alreadyAppliedRule->end_other_rules) {
$useCouponable = false;
}
} else {
$report = $this->checkApplicability($rule);
array_push($canBeApplied, $report);
}
}
}
}
if ($useCouponable) {
$report = $this->checkApplicability($rule);
$report['rule'] = $rule;
$report['used_coupon'] = $useCouponable;
$itemId = array_first($canBeApplied);
foreach ($cart->items as $item) {
if ($item->id == $itemId['item_id']) {
$item->update([
'discount_amount' => array_first($canBeApplied)['discount'],
'base_discount_amount' => array_first($canBeApplied)['discount'],
'coupon_code' => $rule->coupons->code
]);
$cart->update([
'coupon_code' => $rule->coupons->code
]);
\Cart::collectTotals();
$report['grand_total'] = core()->currency(\Cart::getCart()->grand_total);
break;
}
}
// saves the rule in cart rule cart
$this->save($rule);
return $report;
} else {
return null;
}
}
/**
* This function checks whether the rule is getting applied on the current cart or not
*
* @return mixed
*/
public function checkApplicability($rule = null)
{
$cart = \Cart::getCart();
$report = array();
$result = 0;
$conditionsBased = true;
//check conditions
if ($rule->conditions != null) {
$conditions = json_decode(json_decode($rule->conditions));
$test_mode = config('pricerules.test_mode.0');
if ($test_mode == config('pricerules.test_mode.0')) {
$result = $this->testIfAllConditionAreTrue($conditions, $cart);
} else if ($test_mode == config('pricerules.test_mode.1')) {
$result = $this->testIfAllConditionAreFalse($conditions, $cart);
} else if ($test_mode == config('pricerules.test_mode.2')) {
$result = $this->testIfAnyConditionIsTrue($conditions, $cart);
} else if ($test_mode == config('pricerules.test_mode.3')) {
$result = $this->testIfAnyConditionIsFalse($conditions, $cart);
$test_mode = array_last($conditions);
if ($test_mode->criteria == 'any_is_true') {
$conditionsBased = $this->testIfAnyConditionIsTrue($conditions, $cart);
}
if ($test_mode->criteria == 'all_are_true') {
$conditionsBased = $this->testIfAllConditionAreTrue($conditions, $cart);
}
}
if ($result) {
$report['conditions'] = true;
if ($timeBased && $channelBased && $customerGroupBased && $conditionsBased) {
return true;
} else {
if ($rule->conditions == null)
$report['conditions'] = true;
else
$report['conditions'] = false;
return false;
}
//check endrule
if ($rule->end_other_rules) {
$report['end_other_rules'] = true;
} else {
$report['end_other_rules'] = false;
}
//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
$amountDiscounted = 0;
$leastWorthItem = \Cart::leastWorthItem();
$realQty = $leastWorthItem['quantity'];
if ($cart->items_qty >= $disc_threshold) {
if ($action_type == config('pricerules.cart.validation.0')) {
$amountDiscounted = $leastWorthItem['price'] * ($disc_amount / 100);
if ($realQty > $disc_quantity) {
$amountDiscounted = $amountDiscounted * $disc_quantity;
}
if ($amountDiscounted > $leastWorthItem['price']) {
$amountDiscounted = $leastWorthItem['price'];
}
} else if ($action_type == config('pricerules.cart.validation.1')) {
$amountDiscounted = $disc_amount;
if ($realQty > $disc_quantity) {
$amountDiscounted = $amountDiscounted * $disc_quantity;
}
if ($amountDiscounted > $leastWorthItem['price']) {
$amountDiscounted = $leastWorthItem['price'];
}
} else if ($action_type == config('pricerules.cart.validation.2')) {
$amountDiscounted = $disc_amount;
if ($realQty > $disc_quantity) {
$amountDiscounted = $amountDiscounted * $disc_quantity;
}
if ($amountDiscounted > $leastWorthItem['price']) {
$amountDiscounted = $leastWorthItem['price'];
}
}
}
$report['item_id'] = $leastWorthItem['id'];
$report['item_price'] = $leastWorthItem['total'];
$report['discount'] = $amountDiscounted;
$report['action'] = $action_type;
$report['formatted_discount'] = core()->formatPrice($amountDiscounted, $cart->cart_currency_code);
$report['grand_total'] = $cart->grand_total - $amountDiscounted;
$report['formatted_grand_total'] = core()->formatPrice($cart->grand_total - $amountDiscounted, $cart->cart_currency_code);
$report['priority'] = $rule->priority;
return $report;
}
/**
* Save the rule in the cart rule cart
* Save the rule in the CartRule for current cart instance
*
* @return boolean
*/
@ -439,19 +139,27 @@ class Discount
]);
if (count($existingRule)) {
// $this->clearDiscount();
if ($existingRule->first()->cart_rule_id != $rule->id) {
$existingRule->first()->update([
'cart_rule_id' => $rule->id
]);
$this->updateCartItemAndCart($rule);
return true;
}
} else {
// $this->clearDiscount();
$this->cartRuleCart->create([
'cart_id' => $cart->id,
'cart_rule_id' => $rule->id
]);
$this->updateCartItemAndCart($rule);
return true;
}
@ -459,49 +167,148 @@ class Discount
}
/**
* Removes the couponable rule from the current cart and cart rule cart
* Removes any cart rule from the current cart instance
*
* @return void
*/
public function clearDiscount()
{
$cart = Cart::getCart();
$cartItems = $cart->items;
foreach($cartItems as $item) {
$item->update([
'coupon_code' => NULL,
'discount_percent' => 0,
'discount_amount' => 0,
'base_discount_amount' => 0
]);
}
$cart->update([
'coupon_code' => NULL,
'discount_amount' => 0,
'base_discount_amount' => 0
]);
return true;
}
/**
* To find the least worth item in current cart instance
*
* @return array
*/
public function leastWorthItem()
{
$cart = Cart::getCart();
$leastValue = 999999999999;
$leastWorthItem = [];
foreach ($cart->items as $item) {
if ($item->price < $leastValue) {
$leastValue = $item->price;
$leastWorthItem = [
'id' => $item->id,
'price' => $item->price,
'base_price' => $item->base_price,
'quantity' => $item->quantity
];
}
}
return $leastWorthItem;
}
/**
* Update discount for least worth item
*/
public function updateCartItemAndCart($rule)
{
$cart = Cart::getCart();
$leastWorthItem = $this->leastWorthItem();
$actionInstance = new $this->rules[$rule->action_type];
$impact = $actionInstance->calculate($rule, $leastWorthItem, $cart);
foreach ($cart->items as $item) {
if ($item->id == $leastWorthItem['id']) {
if ($rule->action_type == 'percent_of_product') {
$item->update([
'discount_percent' => $rule->discount_amount,
'discount_amount' => $impact['discount'],
'base_discount_amount' => $impact['discount']
]);
} else {
$item->update([
'discount_amount' => $impact['discount'],
'base_discount_amount' => $impact['discount']
]);
}
// save coupon if rule has it
if ($rule->use_coupon) {
$coupon = $rule->coupons->code;
$item->update([
'coupon_code' => $coupon
]);
$cart->update([
'coupon_code' => $coupon
]);
}
break;
}
}
Cart::collectTotals();
return true;
}
/**
* To find the max worth item in current cart instance
*
* @return Array
*/
public function maxWorthItem()
{
$cart = Cart::getCart();
$maxValue = 0;
$maxWorthItem = [];
foreach ($cart->items as $item) {
if ($item->base_total > $maxValue) {
$maxValue = $item->total;
$maxWorthItem = [
'id' => $item->id,
'price' => $item->price,
'base_price' => $item->base_price,
'quantity' => $item->quantity
];
}
}
return $maxWorthItem;
}
/**
* Checks the rule against the current cart instance whether rule conditions are applicable
* or not
*
* @return boolean
*/
public function removeCoupon()
protected function testIfAllConditionAreTrue($conditions, $cart)
{
$cart = \Cart::getCart();
array_pop($conditions);
$existingRule = $this->cartRuleCart->findWhere([
'cart_id' => $cart->id
]);
if ($existingRule->count()) {
if ($existingRule->first()->delete()) {
foreach ($cart->items as $item) {
if ($item->discount_amount > 0) {
$item->update([
'discount_amount' => 0,
'base_discount_amount' => 0,
'discount_percent' => 0,
'coupon_code' => NULL
]);
}
}
$cart->update([
'coupon_code' => NULL,
'discount_amount' => 0,
'base_discount_amount' => 0
]);
\Cart::collectTotals();
return true;
} else {
return false;
}
} else {
return false;
}
}
protected function testIfAllConditionAreTrue($conditions, $cart) {
$shipping_address = $cart->getShippingAddressAttribute() ?? '';
$shipping_method = $cart->shipping_method ?? '';
@ -520,10 +327,8 @@ class Discount
$total_weight = $total_weight + $item->base_total_weight;
}
$test_mode = config('pricerules.test_mode.0');
$test_conditions = config('pricerules.cart.conditions');
$result = true;
$result = 1;
foreach ($conditions as $condition) {
$actual_value = ${$condition->attribute};
$test_value = $condition->value;
@ -532,43 +337,127 @@ class Discount
if ($condition->type == 'numeric' || $condition->type == 'string' || $condition->type == 'text') {
if ($test_condition == '=') {
if ($actual_value != $test_value) {
$result = 0;
$result = false;
break;
}
} else if ($test_condition == '>=') {
if (! ($actual_value >= $test_value)) {
$result = 0;
$result = false;
break;
}
} else if ($test_condition == '<=') {
if (! ($actual_value <= $test_value)) {
$result = 0;
$result = false;
break;
}
} else if ($test_condition == '>') {
if (! ($actual_value > $test_value)) {
$result = 0;
$result = false;
break;
}
} else if ($test_condition == '<') {
if (! ($actual_value < $test_value)) {
$result = 0;
$result = false;
break;
}
} else if ($test_condition == '{}') {
if (! str_contains($actual_value, $test_value)) {
$result = 0;
$result = false;
break;
}
} else if ($test_condition == '!{}') {
if (str_contains($actual_value, $test_value)) {
$result = 0;
$result = false;
break;
}
}
}
}
return $result;
}
/**
* Checks the rule against the current cart instance whether rule conditions are applicable
* or not
*
* @return boolean
*/
protected function testIfAnyConditionIsTrue($conditions, $cart) {
array_pop($conditions);
$result = false;
$shipping_address = $cart->getShippingAddressAttribute() ?? '';
$shipping_method = $cart->shipping_method ?? '';
$shipping_country = $shipping_address->country ?? '';
$shipping_state = $shipping_address->state ?? '';
$shipping_postcode = $shipping_address->postcode ?? '';
$shipping_city = $shipping_address->city ?? '';
$payment_method = $cart->payment->method ?? '';
$sub_total = $cart->base_sub_total;
$total_items = $cart->items_qty;
$total_weight = 0;
foreach($cart->items as $item) {
$total_weight = $total_weight + $item->base_total_weight;
}
foreach ($conditions as $condition) {
$actual_value = ${$condition->attribute};
$test_value = $condition->value;
$test_condition = $condition->condition;
if ($condition->type == 'numeric' || $condition->type == 'string' || $condition->type == 'text') {
if ($test_condition == '=') {
if ($actual_value == $test_value) {
$result = true;
break;
}
} else if ($test_condition == '>=') {
if ($actual_value >= $test_value) {
$result = true;
break;
}
} else if ($test_condition == '<=') {
if ($actual_value <= $test_value) {
$result = true;
break;
}
} else if ($test_condition == '>') {
if ($actual_value > $test_value) {
$result = true;
break;
}
} else if ($test_condition == '<') {
if ($actual_value < $test_value) {
$result = true;
break;
}
} else if ($test_condition == '{}') {
if (str_contains($actual_value, $test_value)) {
$result = true;
break;
}
} else if ($test_condition == '!{}') {
if (str_contains($actual_value, $test_value)) {
$result = true;
break;
}

View File

@ -0,0 +1,185 @@
<?php
namespace Webkul\Discount\Helpers;
use Webkul\Discount\Helpers\Discount;
use Cart;
class NonCouponAbleRule extends Discount
{
/**
* Applies the non couponable rule on the current cart instance
*
* @return mixed
*/
public function apply($code = null)
{
$cart = Cart::getCart();
$applicableRules = array();
if (auth()->guard('customer')->check()) {
$rules = $this->cartRule->findWhere([
'use_coupon' => 0,
'status' => 1
]);
} else {
$rules = $this->cartRule->findWhere([
'use_coupon' => 0,
'is_guest' => 1,
'status' => 1
]);
}
$alreadyAppliedRule = $this->cartRuleCart->findWhere([
'cart_id' => $cart->id,
]);
if (count($alreadyAppliedRule)) {
$alreadyAppliedRule = $alreadyAppliedRule->first()->cart_rule;
if ($alreadyAppliedRule->use_coupon) {
return null;
}
}
// time based filter
foreach($rules as $rule) {
$applicability = $this->checkApplicability($rule);
if ($applicability) {
$item = $this->leastWorthItem();
$actionInstance = new $this->rules[$rule->action_type];
$impact = $actionInstance->calculate($rule, $item, $cart);
array_push($applicableRules, [
'rule' => $rule,
'impact' => $impact
]);
}
}
if (count($applicableRules) > 1) {
// 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 $endRules;
}
$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 $maxImpacts;
}
} else {
$this->save(array_first($prioritySorted)['rule']);
return $prioritySorted;
}
} else if (count($applicableRules) == 1) {
$rule = array_first($applicableRules)['rule'];
$this->save($applicableRules);
return array_first($applicableRules)['impact'];
} else {
return null;
}
}
}

View File

@ -79,7 +79,7 @@ class CartRuleController extends Controller
}
/**
* @return Redirect
* @return redirect
*/
public function store()
{
@ -114,9 +114,13 @@ class CartRuleController extends Controller
// set per customer usage limit
$data['per_customer'] = 0;
// check starts from and ends till
if ($data['starts_from'] == "" || $data['ends_till'] == "") {
// check if starts_from is null
if ($data['starts_from'] == "") {
$data['starts_from'] = null;
}
// check if end_till is null
if ($data['ends_till'] == "") {
$data['ends_till'] = null;
}
@ -162,7 +166,7 @@ class CartRuleController extends Controller
$data['actions'] = json_encode($data['actions']);
// check if all
if (! isset($data['all_conditions']) || $data['all_conditions'] == "[]") {
if (! isset($data['all_conditions']) || $data['all_conditions'] == "[]" || $data['all_conditions'] == "") {
$data['conditions'] = null;
} else {
$data['conditions'] = json_encode($data['all_conditions']);
@ -282,12 +286,10 @@ class CartRuleController extends Controller
*/
public function update($id)
{
$types = config('price_rules.cart.validations');
$this->validate(request(), [
'name' => 'required|string',
'description' => 'string',
// 'customer_groups' => 'required|array',
'customer_groups' => 'required|array',
'channels' => 'required|array',
'status' => 'required|boolean',
'use_coupon' => 'boolean|required',
@ -304,35 +306,52 @@ class CartRuleController extends Controller
'label' => 'array|nullable'
]);
$data['usage_limit'] = 0;
$data['per_customer'] = 0;
// collecting request in $data
$data = request()->all();
if ($data['starts_from'] == "" || $data['ends_till'] == "") {
// unset request token from $data
unset($data['_token']);
// set rule uasge limit
$data['usage_limit'] = 0;
// set rule usage per customer
$data['per_customer'] = 0;
// check if starts_from is null
if ($data['starts_from'] == "") {
$data['starts_from'] = null;
}
// check if end_till is null
if ($data['ends_till'] == "") {
$data['ends_till'] = null;
}
unset($data['_token']);
// set channels
$channels = $data['channels'];
// unset the channels from $data
unset($data['channels']);
// $customer_groups = $data['customer_groups'];
// unset($data['customer_groups']);
// unset($data['criteria']);
// set customer_groups
$customer_groups = $data['customer_groups'];
// unset customer groups
unset($data['customer_groups']);
// set labels and unset them from $data
if (isset($data['label'])) {
$labels = $data['label'];
unset($data['label']);
}
// unset cart_attributes and attributes from $data
unset($data['cart_attributes']);
unset($data['attributes']);
// prepare actions from data for json action
if (isset($data['disc_amount']) && $data['action_type'] == config('pricerules.cart.validations.2')) {
$data['actions'] = [
'action_type' => $data['action_type'],
@ -349,16 +368,22 @@ class CartRuleController extends Controller
];
}
// encode php array to json for actions
$data['actions'] = json_encode($data['actions']);
if (! isset($data['all_conditions']) || $data['all_conditions'] == "[]") {
// Prepares conditions from all conditions
if (! isset($data['all_conditions']) || $data['all_conditions'] == "[]" || $data['all_conditions'] == "") {
$data['conditions'] = null;
} else {
$data['conditions'] = json_encode($data['all_conditions']);
}
unset($data['match_criteria']);
// unset all_conditions from conditions
unset($data['all_conditions']);
// set coupons from $data
if ($data['use_coupon']) {
// if (isset($data['auto_generation']) && $data['auto_generation']) {
$data['auto_generation'] = 0;
@ -386,13 +411,19 @@ class CartRuleController extends Controller
// $coupons['limit'] = $data['usage_limit'];
// }
// update cart rule
$ruleUpdated = $this->cartRule->update($data, $id);
// $ruleGroupUpdated = $this->cartRule->CustomerGroupSync($customer_groups, $ruleUpdated);
// update customer groups for cart rule
$ruleGroupUpdated = $this->cartRule->CustomerGroupSync($customer_groups, $ruleUpdated);
// update customer groups for cart rule
$ruleChannelUpdated = $this->cartRule->ChannelSync($channels, $ruleUpdated);
// update labels
$labelsUpdated = $this->cartRule->LabelSync($labels, $ruleUpdated);
// check coupons set conditions
if (isset($coupons)) {
$coupons['cart_rule_id'] = $ruleUpdated->id;
// $coupons['usage_per_customer'] = $data['per_customer']; //0 is for unlimited usage
@ -400,7 +431,7 @@ class CartRuleController extends Controller
$couponUpdated = $ruleUpdated->coupons->update($coupons);
}
if ($ruleUpdated && $ruleChannelUpdated) {
if ($ruleUpdated && $ruleGroupUpdated && $ruleChannelUpdated) {
if (isset($couponUpdated) && $couponUpdated) {
session()->flash('info', trans('admin::app.promotion.status.success-coupon'));
}
@ -415,6 +446,11 @@ class CartRuleController extends Controller
return redirect()->route($this->_config['redirect']);
}
/**
* Deletes the cart rule
*
* @return JSON
*/
public function destroy($id)
{
$cartRule = $this->cartRule->findOrFail($id);
@ -430,6 +466,11 @@ class CartRuleController extends Controller
}
}
/**
* Get Countries and states list from core helpers
*
* @return Array
*/
public function getStatesAndCountries()
{
$countries = core()->countries()->toArray();

View File

@ -35,5 +35,9 @@ class DiscountServiceProvider extends ServiceProvider
$this->mergeConfigFrom(
dirname(__DIR__) . '/Config/rule-conditions.php', 'pricerules'
);
$this->mergeConfigFrom(
dirname(__DIR__) . '/Config/discount-rules.php', 'discount-rules'
);
}
}

View File

@ -9,7 +9,6 @@ use Webkul\Checkout\Repositories\CartItemRepository;
use Webkul\Product\Repositories\ProductRepository;
use Webkul\Customer\Repositories\CustomerRepository;
use Webkul\Customer\Repositories\WishlistRepository;
use Webkul\Discount\Repositories\CartRuleCartRepository as CartRuleCart;
use Illuminate\Support\Facades\Event;
use Cart;
@ -34,11 +33,15 @@ class CartController extends Controller
* @param $productView
*/
protected $_config;
protected $cart;
protected $cartItem;
protected $customer;
protected $product;
protected $cartRuleCart;
protected $suppressFlash = false;
/**
@ -53,8 +56,7 @@ class CartController extends Controller
CartItemRepository $cartItem,
CustomerRepository $customer,
ProductRepository $product,
WishlistRepository $wishlist,
CartRuleCart $cartRuleCart
WishlistRepository $wishlist
)
{
@ -70,8 +72,6 @@ class CartController extends Controller
$this->wishlist = $wishlist;
$this->cartRuleCart = $cartRuleCart;
$this->_config = request('_config');
}
@ -252,70 +252,4 @@ class CartController extends Controller
return redirect()->back();
}
}
/**
* To apply coupon rules
*/
public function applyCoupon()
{
$this->validate(request(), [
'code' => 'string|required'
]);
$code = request()->input('code');
$result = Cart::applyCoupon($code);
if ($result != null) {
return response()->json([
'success' => true,
'message' => trans('shop::app.checkout.onepage.total.coupon-applied'),
'result' => $result
]);
} else {
return response()->json([
'success' => false,
'message' => trans('shop::app.checkout.onepage.total.cannot-apply-coupon'),
'result' => null
]);
}
return $result;
}
/**
* Fetch the non couponable rule
*/
public function getNonCouponAbleRule()
{
$cart = Cart::getCart();
$nonCouponAbleRules = Cart::applyNonCoupon();
return $nonCouponAbleRules;
}
/**
* To remove the currently active
* couponable rule
*/
public function removeCoupon()
{
$result = Cart::removeCoupon();
if ($result) {
return response()->json([
'success' => true,
'message' => trans('admin::app.promotion.status.coupon-removed'),
'data' => [
'grand_total' => core()->currency(Cart::getCart()->grand_total)
]
]);
} else {
return response()->json([
'success' => false,
'message' => trans('admin::app.promotion.status.coupon-remove-failed'),
'data' => null
]);
}
}
}

View File

@ -3,20 +3,22 @@
namespace Webkul\Shop\Http\Controllers;
use Webkul\Shop\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Auth;
use Webkul\Checkout\Facades\Cart;
use Webkul\Shipping\Facades\Shipping;
use Webkul\Payment\Facades\Payment;
use Webkul\Discount\Repositories\CartRuleCartRepository as CartRuleCart;
use Webkul\Checkout\Http\Requests\CustomerAddressForm;
use Webkul\Sales\Repositories\OrderRepository;
use Webkul\Discount\Helpers\CouponAbleRule as Coupon;
use Webkul\Discount\Helpers\NonCouponAbleRule as NonCoupon;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Auth;
/**
* Chekout controller for the customer and guest for placing order
*
* @author Jitendra Singh <jitendra@webkul.com>
* @author Jitendra Singh <jitendra@webkul.com> @jitendra-webkul
* @author Prashant Singh <prashant.singh852@webkul.com> @prashant-webkul
* @copyright 2018 Webkul Software Pvt Ltd (http://www.webkul.com)
*/
class OnepageController extends Controller
@ -28,13 +30,6 @@ class OnepageController extends Controller
*/
protected $orderRepository;
/**
* CartRuleCartRepository object
*
* @var array
*/
protected $cartRuleCart;
/**
* Contains route related configuration
*
@ -42,17 +37,31 @@ class OnepageController extends Controller
*/
protected $_config;
/**
*
* CouponAbleRule instance
*/
protected $coupon;
/**
*
* NoncouponAbleRule instance
*/
protected $nonCoupon;
/**
* Create a new controller instance.
*
* @param \Webkul\Attribute\Repositories\OrderRepository $orderRepository
* @return void
*/
public function __construct(OrderRepository $orderRepository, CartRuleCart $cartRuleCart)
public function __construct(OrderRepository $orderRepository, Coupon $coupon, NonCoupon $nonCoupon)
{
$this->orderRepository = $orderRepository;
$this->coupon = $coupon;
$this->cartRuleCart = $cartRuleCart;
$this->nonCoupon = $nonCoupon;
$this->orderRepository = $orderRepository;
$this->_config = request('_config');
}
@ -67,7 +76,9 @@ class OnepageController extends Controller
if (Cart::hasError())
return redirect()->route('shop.checkout.cart.index');
Cart::applyNonCoupon();
$this->nonCoupon->apply();
Cart::collectTotals();
return view($this->_config['view'])->with('cart', Cart::getCart());
}
@ -99,13 +110,13 @@ class OnepageController extends Controller
$data['billing']['address1'] = implode(PHP_EOL, array_filter($data['billing']['address1']));
$data['shipping']['address1'] = implode(PHP_EOL, array_filter($data['shipping']['address1']));
if (Cart::hasError() || !Cart::saveCustomerAddress($data) || ! $rates = Shipping::collectRates())
return response()->json(['redirect_url' => route('shop.checkout.cart.index')], 403);
Cart::applyNonCoupon();
$this->nonCoupon->apply();
Cart::collectTotals();
if (Cart::hasError() || !Cart::saveCustomerAddress($data) || ! $rates = Shipping::collectRates())
return response()->json(['redirect_url' => route('shop.checkout.cart.index')], 403);
return response()->json($rates);
}
@ -118,13 +129,13 @@ class OnepageController extends Controller
{
$shippingMethod = request()->get('shipping_method');
if (Cart::hasError() || !$shippingMethod || !Cart::saveShippingMethod($shippingMethod))
return response()->json(['redirect_url' => route('shop.checkout.cart.index')], 403);
Cart::applyNonCoupon();
$this->nonCoupon->apply();
Cart::collectTotals();
if (Cart::hasError() || !$shippingMethod || !Cart::saveShippingMethod($shippingMethod))
return response()->json(['redirect_url' => route('shop.checkout.cart.index')], 403);
return response()->json(Payment::getSupportedPaymentMethods());
}
@ -137,15 +148,15 @@ class OnepageController extends Controller
{
$payment = request()->get('payment');
$this->nonCoupon->apply();
Cart::collectTotals();
if (Cart::hasError() || !$payment || !Cart::savePaymentMethod($payment))
return response()->json(['redirect_url' => route('shop.checkout.cart.index')], 403);
$cart = Cart::getCart();
Cart::applyNonCoupon();
Cart::collectTotals();
return response()->json([
'jump_to_section' => 'review',
'html' => view('shop::checkout.onepage.review', compact('cart', 'rule'))->render()
@ -208,6 +219,9 @@ class OnepageController extends Controller
{
$cart = Cart::getCart();
// extra validation check if some the conditions is changed for the coupons but not using it now
// $this->nonCoupon->apply();
if (! $cart->shipping_address) {
throw new \Exception(trans('Please check shipping address.'));
}
@ -224,4 +238,79 @@ class OnepageController extends Controller
throw new \Exception(trans('Please specify payment method.'));
}
}
/**
* To apply couponable rule requested
*
* @return JSON
*/
public function applyCoupon()
{
$this->validate(request(), [
'code' => 'string|required'
]);
$code = request()->input('code');
$result = $this->coupon->apply($code);
if ($result) {
Cart::collectTotals();
return response()->json([
'success' => true,
'message' => trans('shop::app.checkout.onepage.total.coupon-applied'),
'result' => $result
], 200);
} else {
return response()->json([
'success' => false,
'message' => trans('shop::app.checkout.onepage.total.cannot-apply-coupon'),
'result' => null
], 422);
}
return $result;
}
/**
* Applies non couponable rule if present
*
* @return Void
*/
public function applyNonCouponAbleRule()
{
$cart = Cart::getCart();
$nonCouponAbleRules = Cart::applyNonCoupon();
return $nonCouponAbleRules;
}
/**
* Initiates the removal of couponable cart rule
*
* @return Void
*/
public function removeCoupon()
{
$result = $this->coupon->remove();
if ($result) {
Cart::collectTotals();
return response()->json([
'success' => true,
'message' => trans('admin::app.promotion.status.coupon-removed'),
'data' => [
'grand_total' => core()->currency(Cart::getCart()->grand_total)
]
], 200);
} else {
return response()->json([
'success' => false,
'message' => trans('admin::app.promotion.status.coupon-remove-failed'),
'data' => null
], 422);
}
}
}

View File

@ -39,9 +39,9 @@ Route::group(['middleware' => ['web', 'locale', 'theme', 'currency']], function
'view' => 'shop::checkout.cart.index'
])->name('shop.checkout.cart.index');
Route::post('checkout/check/coupons', 'Webkul\Shop\Http\Controllers\CartController@applyCoupon')->name('shop.checkout.check.coupons');
Route::post('checkout/check/coupons', 'Webkul\Shop\Http\Controllers\OnepageController@applyCoupon')->name('shop.checkout.check.coupons');
Route::post('checkout/remove/coupon', 'Webkul\Shop\Http\Controllers\CartController@removeCoupon')->name('shop.checkout.remove.coupon');
Route::post('checkout/remove/coupon', 'Webkul\Shop\Http\Controllers\OnepageController@removeCoupon')->name('shop.checkout.remove.coupon');
//Cart Items Add
Route::post('checkout/cart/add/{id}', 'Webkul\Shop\Http\Controllers\CartController@add')->defaults('_config', [

View File

@ -24,7 +24,6 @@
</div>
@endif
<div class="item-detail" id="discount-detail" @if ($cart->discount_amount && $cart->discount_amount > 0) style="display: block;" @else style="display: none;" @endif>
<label>
<b>{{ __('shop::app.checkout.total.disc-amount') }}</b>
@ -36,7 +35,6 @@
</label>
</div>
<div class="payable-amount" id="grand-total-detail">
<label>{{ __('shop::app.checkout.total.grand-total') }}</label>
<label class="right" id="grand-total-amount-detail">

View File

@ -241,7 +241,7 @@ abstract class DataGrid
$this->operators[$condition],
'%'.$filter_value.'%'
);
} else if($this->enableFilterMap && !isset($this->filterMap[$columnName])) {
} else if ($this->enableFilterMap && ! isset($this->filterMap[$columnName])) {
$collection->where(
$columnName,
$this->operators[$condition],
@ -264,7 +264,7 @@ abstract class DataGrid
$this->operators[$condition],
$filter_value
);
} else if($this->enableFilterMap && !isset($this->filterMap[$columnName])) {
} else if ($this->enableFilterMap && ! isset($this->filterMap[$columnName])) {
$collection->whereDate(
$columnName,
$this->operators[$condition],

View File

@ -45,7 +45,7 @@
computed: {
iconClass() {
return {
'accordian-down-icon': !this.isActive,
'accordian-down-icon': ! this.isActive,
'accordian-up-icon': this.isActive,
};
}