Cart rules refactored

This commit is contained in:
Prashant Singh 2019-08-08 05:53:28 +05:30
parent fbedc8a161
commit bb12e07212
13 changed files with 160 additions and 197 deletions

View File

@ -1,8 +0,0 @@
Discount Condition:
Attribute Family is all the attributes
Cart Attribute such as
base_total,
grand_total,
shipping_free,
shipping_not_free,

View File

@ -78,7 +78,7 @@ class FixedAmount extends Action
{
$cart = \Cart::getCart();
$percentOfDiscount = ($cart->base_discount_amount * 100) / $cart->base_grand_total;
$percentOfDiscount = ($cart->base_discount_amount * 100) / $cart->base_sub_total;
return $percentOfDiscount;
}

View File

@ -16,7 +16,7 @@ class PercentOfProduct extends Action
$totalDiscount = 0;
if ($rule->discount_amount >= 100) {
$impact->discount = $cart->base_grand_total;
$impact->discount = $cart->base_sub_total;
$impact->formatted_discount = core()->currency($impact->discount);
} else {
@ -106,7 +106,7 @@ class PercentOfProduct extends Action
$shippingRate = $cart->selected_shipping_rate;
$percentOfDiscount = ($cart->base_discount_amount * 100) / $cart->base_grand_total;
$percentOfDiscount = ($cart->base_discount_amount * 100) / $cart->base_sub_total;
return $percentOfDiscount;
}

View File

@ -90,7 +90,7 @@ class WholeCartToFixed extends Action
*/
public function calculateOnShipping($cart)
{
$percentOfDiscount = ($cart->base_discount_amount * 100) / $cart->base_grand_total;
$percentOfDiscount = ($cart->base_discount_amount * 100) / $cart->base_sub_total;
$discountOnShipping = ($percentOfDiscount / 100) * $cart->selected_shipping_rate->base_price;

View File

@ -23,9 +23,9 @@ class WholeCartToPercent extends Action
$impact = collect();
if ($rule->discount_amount >= 100) {
$impact->discount = $cart->base_grand_total;
$impact->discount = $cart->base_sub_total;
} else {
$impact->discount = ($rule->disc_amount / 100) * $cart->base_grand_total;
$impact->discount = ($rule->disc_amount / 100) * $cart->base_sub_total;
}
$impact->formatted_discount = core()->currency($impact->discount);
@ -90,7 +90,7 @@ class WholeCartToPercent extends Action
*/
public function calculateOnShipping()
{
$percentOfDiscount = ($cart->base_discount_amount * 100) / $cart->base_grand_total;
$percentOfDiscount = ($cart->base_discount_amount * 100) / $cart->base_sub_total;
$discountOnShipping = ($percentOfDiscount / 100) * $cart->selected_shipping_rate->base_price;

View File

@ -10,114 +10,35 @@ use Cart;
class CouponAbleRule extends Discount
{
/**
* Applies the couponable rule on the current cart instance
* Applies the non couponable rule on the current cart instance
*
* @param String $code
*
* @return mixed
*/
public function apply($code)
{
$cart = Cart::getCart();
$this->validateIfAlreadyApplied();
$rules = $this->cartRule->findWhere([
'use_coupon' => 1,
'status' => 1
]);
$rules = $this->getApplicableRules($code);
$applicableRule = null;
if ($rules->count() == 1) {
$rule = $rules->first();
foreach ($rules as $rule) {
if ($rule->use_coupon && ($rule->coupons->code == $code)) {
$applicableRule = $rule;
$canApply = $this->canApply($rule);
break;
}
}
if ($canApply) {
$this->save($rule);
if (! isset($applicableRule)) {
return false;
}
$this->updateCartItemAndCart($rule);
$applicability = $this->checkApplicability($applicableRule);
if ($applicability) {
$item = $cart->items;
$actionInstance = new $this->rules['cart'][$applicableRule->action_type];
$impact = $actionInstance->calculate($applicableRule, $item, $cart);
if ($impact->discount == 0) {
return false;
}
// avoid applying the same rule
$ifAlreadyApplied = $this->cartRuleCart->findWhere([
'cart_id' => $cart->id,
'cart_rule_id' => $applicableRule->id
]);
if ($ifAlreadyApplied->count() == 1) {
// can give a message that coupon is already applied
return false;
}
// if the rule ain't same
$ifAlreadyApplied = $this->cartRuleCart->findWhere([
'cart_id' => $cart->id,
]);
if ($ifAlreadyApplied->count() == 0) {
$this->save($applicableRule);
return $impact;
}
// the only case where a non couponable rule defeats couponable rule
if ($ifAlreadyApplied->first()->cart_rule->use_coupon == 0 && $ifAlreadyApplied->first()->cart_rule->end_other_rules == 1) {
return false;
}
if ($ifAlreadyApplied->first()->cart_rule->use_coupon == 1 && $ifAlreadyApplied->first()->cart_rule->end_other_rules == 1) {
return false;
}
if ($ifAlreadyApplied->first()->cart_rule->use_coupon == 1) {
$alreadyAppliedRule = $ifAlreadyApplied->first()->cart_rule;
if ($alreadyAppliedRule->priority < $applicableRule->priority) {
return false;
} else if ($alreadyAppliedRule->priority == $applicableRule->priority) {
$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 {
$this->save($applicableRule);
return $impact;
return true;
}
} else {
return false;
}
return false;
}
/**
@ -133,33 +54,8 @@ class CouponAbleRule extends Discount
'cart_id' => $cart->id
]);
if ($existingRule->count()) {
$existingRule->first()->delete();
$this->clearDiscount();
$this->resetShipping($cart);
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;
}
return true;
}
}

View File

@ -56,12 +56,19 @@ abstract class Discount
*
* @return collection $rules
*/
public function getApplicableRules($usecoupon = false)
public function getApplicableRules($code = null)
{
$rules = $this->cartRule->findWhere([
'use_coupon' => 0,
'status' => 1
]);
if ($code != null) {
$rules = $this->cartRule->findWhere([
'use_coupon' => 1,
'status' => 1
]);
} else {
$rules = $this->cartRule->findWhere([
'use_coupon' => 0,
'status' => 1
]);
}
$filteredRules = collect();
@ -185,19 +192,64 @@ abstract class Discount
{
$cart = \Cart::getCart();
$alreadyAppliedRule = $this->cartRuleCart->findWhere([
'cart_id' => $cart->id,
'cart_rule_id' => $rule->id
$alreadyApplied = $this->cartRuleCart->findWhere([
'cart_id' => $cart->id
]);
if ($alreadyAppliedRule->count()) {
if ($this->validateRule($alreadyAppliedRule->first()->cart_rule)) {
if ($alreadyApplied->count() && $alreadyApplied->first()->cart_rule->id == $rule->id) {
if ($this->validateRule($alreadyApplied->first()->cart_rule)) {
return false;
} else {
$this->clearDiscount();
return true;
}
} else if ($alreadyApplied->count() && $alreadyApplied->first()->cart_rule->id != $rule->id && ! $alreadyApplied->first()->cart_rule->end_other_rules) {
if ($rule->use_coupon) {
if ($alreadyApplied->first()->cart_rule->use_coupon) {
$rules = collect();
$alreadyAppliedRule = $alreadyApplied->first()->cart_rule;
$alreadyAppliedRule->impact = $this->calculateImpact($alreadyAppliedRule);
$rule->impact = $this->calculateImpact($alreadyAppliedRule);
$rules->push($alreadyAppliedRule);
$rules->push($rule);
$result = $this->breakTie($rules);
if ($result->id == $rule->id) {
return true;
} else {
return false;
}
} else {
return true;
}
} else {
// this case will work when non couponable rule is applied and another non couponable rule is created
// again break tie
$rules = collect();
$alreadyAppliedRule = $alreadyApplied->first()->cart_rule;
$alreadyAppliedRule->impact = $this->calculateImpact($alreadyAppliedRule);
$rule->impact = $this->calculateImpact($alreadyAppliedRule);
$rules->push($alreadyAppliedRule);
$rules->push($rule);
$result = $this->breakTie($rules);
if ($result) {
if ($result->id != $rule->id) {
return true;
} else {
return false;
}
}
}
} else {
return true;
}
@ -380,8 +432,7 @@ abstract class Discount
$cart = \Cart::getCart();
$alreadyApplied = $this->cartRuleCart->findWhere([
'cart_id' => $cart->id,
'cart_rule_id' => $rule->id
'cart_id' => $cart->id
]);
if ($alreadyApplied->count()) {
@ -443,7 +494,9 @@ abstract class Discount
/**
* Resets the shipping for the current items in the cart
*
* @return void
* @param Cart $cart
*
* @return Void
*/
public function resetShipping($cart)
{
@ -479,7 +532,9 @@ abstract class Discount
/**
* Update discount for least worth item
*
* @return boolean
* @param CartRule $rule
*
* @return Boolean
*/
public function updateCartItemAndCart($rule)
{
@ -516,9 +571,9 @@ abstract class Discount
]);
}
if ($rule->free_shipping || $rule->apply_on_shipping) {
$this->applyOnShipping($rule);
}
// if ($rule->free_shipping || $rule->apply_on_shipping) {
// $this->applyOnShipping($rule);
// }
Cart::collectTotals();
@ -528,7 +583,7 @@ abstract class Discount
/**
* Removes any cart rule from the current cart instance
*
* @return void
* @return Boolean
*/
public function clearDiscount()
{
@ -536,6 +591,7 @@ abstract class Discount
$cartItems = $cart->items;
// remove all the discount properties from items
foreach ($cartItems as $item) {
$item->update([
'coupon_code' => NULL,
@ -545,39 +601,68 @@ abstract class Discount
]);
}
// remove all the discount properties from cart
$cart->update([
'coupon_code' => NULL,
'discount_amount' => 0,
'base_discount_amount' => 0
]);
// find & remove cart rule from cart rule cart resource
$cartRuleCart = $this->cartRuleCart->findWhere([
'cart_id' => $cart->id
]);
$cartRuleCart->first()->delete();
return true;
}
/**
* Validate the currently applied cart rule
*
* @return boolean
* @param CartRule $rule
*
* @return Boolean
*/
public function validateRule($rule)
{
$applicability = $this->checkApplicability($rule);
if ($applicability) {
if ($rule->status) {
return true;
} else {
return false;
}
if ($applicability && $rule->status) {
return true;
} else {
return false;
}
}
/**
* Will validate already applied rule
*
* @return Void
*/
public function validateIfAlreadyApplied()
{
$cart = \Cart::getCart();
$alreadyAppliedRule = $this->cartRuleCart->findWhere([
'cart_id' => $cart->id
]);
if ($alreadyAppliedRule->count()) {
$alreadyAppliedRule = $alreadyAppliedRule->first()->cart_rule;
$result = $this->validateRule($alreadyAppliedRule);
if (! $result)
$this->clearDiscount();
}
}
/**
* Retreives all the payment methods from application config
*
* @return array
* @return Array
*/
public function getPaymentMethods()
{
@ -602,7 +687,11 @@ abstract class Discount
* Checks the rule against the current cart instance whether rule conditions are applicable
* or not
*
* @return boolean
* @param Array $conditions
*
* @param Cart $cart
*
* @return Boolean
*/
protected function testIfAllConditionAreTrue($conditions, $cart)
{
@ -702,14 +791,14 @@ abstract class Discount
break;
}
} else if ($test_condition == '{}') {
if (str_contains($test_value, $actual_value)) {
$result = true;
if (! str_contains($test_value, $actual_value)) {
$result = false;
break;
}
} else if ($test_condition == '!{}') {
if (! str_contains($test_value, $actual_value)) {
$result = true;
if (str_contains($test_value, $actual_value)) {
$result = false;
break;
}
@ -724,7 +813,11 @@ abstract class Discount
* Checks the rule against the current cart instance whether rule conditions are applicable
* or not
*
* @return boolean
* @param Array $conditions
*
* @param Cart $cart
*
* @return Boolean
*/
protected function testIfAnyConditionIsTrue($conditions, $cart)
{

View File

@ -3,7 +3,7 @@
namespace Webkul\Discount\Helpers;
use Webkul\Discount\Helpers\Discount;
use Webkul\Discount\Repositories\CartRuleCartRepository as CartRuleCart;
use Cart;
class NonCouponAbleRule extends Discount
@ -11,10 +11,14 @@ class NonCouponAbleRule extends Discount
/**
* Applies the non couponable rule on the current cart instance
*
* @param String $code
*
* @return mixed
*/
public function apply($code = null)
{
$this->validateIfAlreadyApplied();
$rules = $this->getApplicableRules();
if ($rules->count() == 1) {

View File

@ -24,7 +24,7 @@ class ValidatesDiscount extends Discount
public function apply($code)
{
return ;
return null;
}
/**
@ -34,27 +34,9 @@ class ValidatesDiscount extends Discount
*
* @return mixed
*/
public function validate($cart)
public function validate()
{
$appliedRule = $this->cartRuleCart->findWhere([
'cart_id' => $cart->id
]);
if ($appliedRule->count()) {
$appliedRule = $appliedRule->first()->cart_rule;
if ($appliedRule->status == 1) {
$applicability = $this->checkApplicability($appliedRule);
if (! $applicability) {
return $this->remove();
}
} else {
return $this->remove();
}
}
return false;
$this->validateIfAlreadyApplied();
}
/**

View File

@ -167,8 +167,6 @@ class OnepageController extends Controller
$this->nonCoupon->apply();
$this->nonCoupon->checkOnShipping(Cart::getCart());
Cart::collectTotals();
$cart = Cart::getCart();
@ -235,7 +233,7 @@ class OnepageController extends Controller
{
$cart = Cart::getCart();
$this->validatesDiscount->validate($cart);
$this->validatesDiscount->validate();
if (! $cart->shipping_address) {
throw new \Exception(trans('Please check shipping address.'));

View File

@ -11,7 +11,7 @@ use Webkul\Product\Repositories\SearchRepository as Search;
/**
* Search controller
*
* @author Prashant Singh <prashant.singh852@webkul.com> @prashant-webkul
* @author Prashant Singh <prashant.singh852@webkul.com> @prashant-webkul
* @copyright 2018 Webkul Software Pvt Ltd (http://www.webkul.com)
*/

View File

@ -54,6 +54,8 @@ class SubscriptionController extends Controller
/**
* Subscribes email to the email subscription list
*
* @return Redirect
*/
public function subscribe()
{

View File

@ -289,9 +289,5 @@ Route::group(['middleware' => ['web', 'locale', 'theme', 'currency']], function
Route::get('pages/{slug}', 'Webkul\CMS\Http\Controllers\Shop\PagePresenterController@presenter')->name('shop.cms.page');
Route::view('onecol', 'shop::cms.onecol');
Route::view('twocol', 'shop::cms.twocol');
Route::view('threecol', 'shop::cms.threecol');
Route::fallback('Webkul\Shop\Http\Controllers\HomeController@notFound');
});