Merge pull request #3463 from Haendlerbund/performance-cart-rules-checks

Improve performance when checking cart-rules
This commit is contained in:
Jitendra Singh 2020-07-14 19:38:48 +05:30 committed by GitHub
commit fca88e16ac
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 109 additions and 43 deletions

View File

@ -3,6 +3,7 @@
namespace Webkul\CartRule\Helpers;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Builder;
use Webkul\CartRule\Repositories\CartRuleRepository;
use Webkul\CartRule\Repositories\CartRuleCouponRepository;
use Webkul\CartRule\Repositories\CartRuleCouponUsageRepository;
@ -144,7 +145,7 @@ class CartRule
if ($staticCartRules::$cartID === cart()->getCart()->id && $staticCartRules::$cartRules) {
return $staticCartRules::$cartRules;
}
$staticCartRules::$cartID = cart()->getCart()->id;
$customerGroupId = null;
@ -157,21 +158,7 @@ class CartRule
}
}
$cartRules = $this->cartRuleRepository->scopeQuery(function ($query) use ($customerGroupId) {
return $query->leftJoin('cart_rule_customer_groups', 'cart_rules.id', '=', 'cart_rule_customer_groups.cart_rule_id')
->leftJoin('cart_rule_channels', 'cart_rules.id', '=', 'cart_rule_channels.cart_rule_id')
->where('cart_rule_customer_groups.customer_group_id', $customerGroupId)
->where('cart_rule_channels.channel_id', core()->getCurrentChannel()->id)
->where(function ($query1) {
$query1->where('cart_rules.starts_from', '<=', Carbon::now()->format('Y-m-d'))
->orWhereNull('cart_rules.starts_from');
})
->where(function ($query2) {
$query2->where('cart_rules.ends_till', '>=', Carbon::now()->format('Y-m-d'))
->orWhereNull('cart_rules.ends_till');
})
->orderBy('sort_order', 'asc');
})->findWhere(['status' => 1]);
$cartRules = $this->getCartRuleQuery($customerGroupId, core()->getCurrentChannel()->id);
$staticCartRules::$cartRules = $cartRules;
return $cartRules;
@ -180,21 +167,22 @@ class CartRule
/**
* Check if cart rule can be applied
*
* @param \Webkul\CartRule\Contracts\CartRule $rule
* @param $cart
* @param \Webkul\CartRule\Contracts\CartRule $rule
*
* @return bool
*/
public function canProcessRule($rule): bool
public function canProcessRule($cart, $rule): bool
{
$cart = Cart::getCart();
if ($rule->coupon_type) {
if (strlen($cart->coupon_code)) {
$coupon = $this->cartRuleCouponRepository->findOneWhere([
'cart_rule_id' => $rule->id,
'code' => $cart->coupon_code,
]);
/** @var \Webkul\CartRule\Models\CartRule $rule */
if ($coupon) {
// Laravel relation is used instead of repository for performance
// reasons (cart_rule_coupon-relation is pre-loaded by self::getCartRuleQuery())
$coupon = $rule->cart_rule_coupon;
if ($coupon && $coupon->code === $cart->coupon_code) {
if ($coupon->usage_limit && $coupon->times_used >= $coupon->usage_limit) {
return false;
}
@ -245,8 +233,10 @@ class CartRule
$appliedRuleIds = [];
foreach ($this->getCartRules() as $rule) {
if (! $this->canProcessRule($rule)) {
$cart = Cart::getCart();
foreach ($rules = $this->getCartRules() as $rule) {
if (! $this->canProcessRule($cart, $rule)) {
continue;
}
@ -368,8 +358,10 @@ class CartRule
$appliedRuleIds = [];
$cart = Cart::getCart();
foreach ($this->getCartRules() as $rule) {
if (! $this->canProcessRule($rule)) {
if (! $this->canProcessRule($cart, $rule)) {
continue;
}
@ -450,8 +442,10 @@ class CartRule
$appliedRuleIds = [];
$cart = Cart::getCart();
foreach ($this->getCartRules() as $rule) {
if (! $this->canProcessRule($rule)) {
if (! $this->canProcessRule($cart, $rule)) {
continue;
}
@ -495,12 +489,14 @@ class CartRule
*/
public function calculateCartItemTotals($items)
{
$cart = Cart::getCart();
foreach ($this->getCartRules() as $rule) {
if ($rule->action_type == 'cart_fixed') {
$totalPrice = $totalBasePrice = $validCount = 0;
foreach ($items as $item) {
if (! $this->canProcessRule($rule, $item)) {
if (! $this->canProcessRule($cart, $rule)) {
continue;
}
@ -564,4 +560,38 @@ class CartRule
}
}
}
}
/**
* @param $customerGroupId
* @param $channelId
*
* @return \Illuminate\Database\Eloquent\Collection
*/
public function getCartRuleQuery($customerGroupId, $channelId): \Illuminate\Database\Eloquent\Collection
{
return $this->cartRuleRepository->scopeQuery(function ($query) use ($customerGroupId) {
/** @var Builder $query */
return $query->leftJoin('cart_rule_customer_groups', 'cart_rules.id', '=',
'cart_rule_customer_groups.cart_rule_id')
->leftJoin('cart_rule_channels', 'cart_rules.id', '=', 'cart_rule_channels.cart_rule_id')
->where('cart_rule_customer_groups.customer_group_id', $customerGroupId)
->where('cart_rule_channels.channel_id', core()->getCurrentChannel()->id)
->where(function ($query1) {
/** @var Builder $query1 */
$query1->where('cart_rules.starts_from', '<=', Carbon::now()->format('Y-m-d'))
->orWhereNull('cart_rules.starts_from');
})
->where(function ($query2) {
/** @var Builder $query2 */
$query2->where('cart_rules.ends_till', '>=', Carbon::now()->format('Y-m-d'))
->orWhereNull('cart_rules.ends_till');
})
->with([
'cart_rule_customer_groups',
'cart_rule_channels',
'cart_rule_coupon'
])
->orderBy('sort_order', 'asc');
})->findWhere(['status' => 1]);
}
}

View File

@ -2,13 +2,11 @@
namespace Webkul\CartRule\Models;
// use Webkul\Core\Eloquent\TranslatableModel;
use Illuminate\Database\Eloquent\Model;
use Webkul\CartRule\Contracts\CartRule as CartRuleContract;
use Webkul\Core\Models\ChannelProxy;
use Webkul\Customer\Models\CustomerGroupProxy;
// class CartRule extends TranslatableModel implements CartRuleContract
class CartRule extends Model implements CartRuleContract
{
protected $fillable = [
@ -40,42 +38,80 @@ class CartRule extends Model implements CartRuleContract
'conditions' => 'array',
];
// public $translatedAttributes = ['name'];
/**
* Get the channels that owns the cart rule.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function channels()
public function cart_rule_channels(): \Illuminate\Database\Eloquent\Relations\BelongsToMany
{
return $this->belongsToMany(ChannelProxy::modelClass(), 'cart_rule_channels');
}
/**
* Get the customer groups that owns the cart rule.
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*
* @deprecated laravel standard should be used
*/
public function customer_groups()
public function channels(): \Illuminate\Database\Eloquent\Relations\BelongsToMany
{
return $this->cart_rule_channels();
}
/**
* Get the customer groups that owns the cart rule.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function cart_rule_customer_groups(): \Illuminate\Database\Eloquent\Relations\BelongsToMany
{
return $this->belongsToMany(CustomerGroupProxy::modelClass(), 'cart_rule_customer_groups');
}
/**
* Get the coupons that owns the cart rule.
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*
* @deprecated laravel standard should be used
*/
public function coupons()
public function customer_groups(): \Illuminate\Database\Eloquent\Relations\BelongsToMany
{
return $this->cart_rule_customer_groups();
}
/**
* Get the coupons that owns the cart rule.
*
* @return \Illuminate\Database\Eloquent\Relations\HasOne
*/
public function cart_rule_coupon(): \Illuminate\Database\Eloquent\Relations\HasOne
{
return $this->hasOne(CartRuleCouponProxy::modelClass());
}
/**
* Get primary coupon code for cart rule.
* @return \Illuminate\Database\Eloquent\Relations\HasOne
*
* @deprecated laravel standard should be used
*/
public function coupon_code()
public function coupons(): \Illuminate\Database\Eloquent\Relations\HasOne
{
return $this->coupons()->where('is_primary', 1);
return $this->cart_rule_coupon();
}
/**
* Get primary coupon code for cart rule.
*
* @return \Illuminate\Database\Eloquent\Relations\HasOne
*/
public function coupon_code(): \Illuminate\Database\Eloquent\Relations\HasOne
{
return $this->cart_rule_coupon()->where('is_primary', 1);
}
/**
* Get primary coupon code for cart rule.
*
* @return string|void
*/
public function getCouponCodeAttribute()
{