Refactoring cart rules

This commit is contained in:
Prashant Singh 2019-08-03 19:54:02 +05:30
parent 9ca97aa594
commit e4a5e84fb6
8 changed files with 227 additions and 77 deletions

View File

@ -269,7 +269,7 @@ body {
.control-container {
display: flex;
flex-direction: row;
align-items: center;
align-items: flex-start;
width: 750px;
.control {

View File

@ -9,4 +9,4 @@ use Illuminate\Foundation\Validation\ValidatesRequests;
class Controller extends BaseController
{
use DispatchesJobs, ValidatesRequests;
}
}

View File

@ -4,7 +4,7 @@ namespace Webkul\Discount\Actions;
abstract class Action
{
abstract public function calculate($rule, $item, $cart);
abstract public function calculate($rule);
abstract public function calculateOnShipping($cart);
abstract public function calculateOnShipping();
}

View File

@ -6,60 +6,132 @@ use Webkul\Discount\Actions\Action;
class PercentOfProduct extends Action
{
public function calculate($rule, $items, $cart)
public function calculate($rule)
{
$report = collect();
$cart = \Cart::getCart();
$items = $cart->items;
$impact = collect();
$totalDiscount = 0;
foreach ($items as $item) {
$amountDiscounted = 0;
$itemReport = array();
if ($rule->uses_attribute_conditions) {
$productIds = $rule->product_ids;
$disc_threshold = $rule->disc_threshold;
$disc_amount = $rule->disc_amount;
$disc_quantity = $rule->disc_quantity;
$productIds = explode(',', $productIds);
$realQty = $item['quantity'];
foreach ($items as $item) {
$product = $item->product;
if ($cart->items_qty >= $disc_threshold) {
$amountDiscounted = $item['base_price'] * ($disc_amount / 100);
if ($realQty > $disc_quantity) {
$amountDiscounted = $amountDiscounted * $disc_quantity;
} else {
$amountDiscounted = $amountDiscounted * $realQty;
if ($product->type == 'configurable') {
$product = $item->child->product;
}
if ($amountDiscounted > $item['base_price'] && $realQty == 1) {
$amountDiscounted = $item['base_price'];
foreach ($productIds as $productId) {
$disc_threshold = $rule->disc_threshold;
$disc_amount = $rule->disc_amount;
$disc_quantity = $rule->disc_quantity;
$amountDiscounted = 0;
$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);
$impact->push($report);
unset($report);
}
}
}
} else {
$productIds = null;
$totalDiscount = $totalDiscount + $amountDiscounted;
foreach ($items as $item) {
$product = $item->product;
$itemReport['item_id'] = $item->id;
$itemReport['product_id'] = $item->product_id;
$itemReport['discount'] = $amountDiscounted;
$itemReport['formatted_discount'] = core()->currency($amountDiscounted);
if ($product->type == 'configurable') {
$product = $item->child->product;
}
$report->push($itemReport);
$disc_threshold = $rule->disc_threshold;
$disc_amount = $rule->disc_amount;
$disc_quantity = $rule->disc_quantity;
$amountDiscounted = 0;
$report = array();
unset($itemReport);
$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);
$impact->push($report);
unset($report);
}
}
}
$report->discount = $totalDiscount;
$report->formatted_discount = core()->currency($totalDiscount);
// 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;
// }
return $report;
$impact->discount = $totalDiscount;
$impact->formatted_discount = core()->currency($totalDiscount);
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();
$shippingRate = $cart->selected_shipping_rate;
$percentOfDiscount = ($cart->base_discount_amount * 100) / $cart->base_grand_total;
return $percentOfDiscount;

View File

@ -15,19 +15,21 @@ class WholeCartToPercent extends Action
*
* @return boolean
*/
public function calculate($rule, $items, $cart)
public function calculate($rule)
{
$report = collect();
$cart = \Cart::getCart();
$items = $cart->items;
$impact = collect();
$totalDiscount = 0;
if ($rule->discount_amount >= 100) {
$report->discount = $cart->base_grand_total;
$impact->discount = $cart->base_grand_total;
} else {
$report->discount = ($rule->disc_amount / 100) * $cart->base_grand_total;
$impact->discount = ($rule->disc_amount / 100) * $cart->base_grand_total;
}
$report->formatted_discount = core()->currency($report->discount);
$impact->formatted_discount = core()->currency($impact->discount);
if ($rule->uses_attribute_conditions) {
$productIDs = $rule->product_ids;
@ -45,22 +47,22 @@ class WholeCartToPercent extends Action
}
if ($matchCount > 0) {
$discountPerItem = $report->discount / $matchCount;
$discountPerItem = $impact->discount / $matchCount;
}
foreach ($productIDs as $productID) {
foreach ($items as $item) {
if ($item->product_id == $productID) {
$itemReport = array();
$report = array();
$itemReport['item_id'] = $item->id;
$itemReport['product_id'] = $item->product_id;
$itemReport['discount'] = $discountPerItem;
$itemReport['formatted_discount'] = core()->currency(0);
$report['item_id'] = $item->id;
$report['product_id'] = $item->product_id;
$report['discount'] = $discountPerItem;
$report['formatted_discount'] = core()->currency(0);
$report->push($itemReport);
$impact->push($report);
unset($itemReport);
unset($report);
}
}
}
@ -68,26 +70,26 @@ class WholeCartToPercent extends Action
$discountPerItem = $report->discount / $cart->items_qty;
foreach ($items as $item) {
$itemReport = array();
$report = array();
$itemReport['item_id'] = $item->id;
$itemReport['product_id'] = $item->product_id;
$itemReport['discount'] = $discountPerItem;
$itemReport['formatted_discount'] = core()->currency(0);
$report['item_id'] = $item->id;
$report['product_id'] = $item->product_id;
$report['discount'] = $discountPerItem;
$report['formatted_discount'] = core()->currency(0);
$report->push($itemReport);
$impact->push($report);
unset($itemReport);
unset($report);
}
}
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()
{
$percentOfDiscount = ($cart->base_discount_amount * 100) / $cart->base_grand_total;

View File

@ -43,6 +43,81 @@ abstract class Discount
*/
abstract public function apply($code);
/**
* To find all the suitable rules that can be applied on the current cart
*
* @return collection $rules
*/
public function getApplicableRules($usecoupon = false)
{
$channel = core()->getCurrentChannel()->id;
$rules = $this->cartRule->findWhere([
'use_coupon' => 0,
'status' => 1
]);
$filteredRules = collect();
// time based constraints
foreach ($rules as $rule) {
if ($rule->starts_from != null && $rule->ends_till == null) {
if (Carbon::parse($rule->starts_from) < now()) {
$rule->impact = $this->calculateImpact($rule);
$filteredRules->push($rule);
}
} else if ($rule->starts_from == null && $rule->ends_till != null) {
if (Carbon::parse($rule->ends_till) > now()) {
$rule->impact = $this->calculateImpact($rule);
$filteredRules->push($rule);
}
} else if ($rule->starts_from != null && $rule->ends_till != null) {
if (Carbon::parse($rule->starts_from) < now() && now() < Carbon::parse($rule->ends_till)) {
$rule->impact = $this->calculateImpact($rule);
$filteredRules->push($rule);
}
} else {
$rule->impact = $this->calculateImpact($rule);
$filteredRules->push($rule);
}
}
dd($filteredRules, 'called by this');
return $filteredRules;
}
/**
* To calculate the impact of the rule
*
* @return collection
*/
public function calculateImpact($rule)
{
$impact = $this->getActionInstance($rule);
return $impact;
}
/**
* Return the instance of the related rule's action type
*
* @return object
*/
public function getActionInstance($rule)
{
$actionType = new $this->rules['cart'][$rule->action_type];
$outcome = $actionType->calculate($rule);
return $outcome;
}
/**
* Checks whether coupon is getting applied on current cart instance or not
*
@ -54,22 +129,22 @@ abstract class Discount
$timeBased = 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 {
$timeBased = true;
}
// // 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 {
// $timeBased = true;
// }
$channelBased = false;
@ -130,7 +205,7 @@ abstract class Discount
}
}
if ($timeBased && $channelBased && $customerGroupBased && $conditionsBased) {
if ($channelBased && $customerGroupBased && $conditionsBased) {
if ($rule->uses_attribute_conditions == 1 && $partialMatch) {
return true;
} else if ($rule->uses_attribute_conditions == 0) {

View File

@ -51,7 +51,7 @@ class NonCouponAbleRule extends Discount
}
// time based filter
foreach($rules as $rule) {
foreach ($rules as $rule) {
$applicability = $this->checkApplicability($rule);
if ($applicability) {

View File

@ -89,7 +89,8 @@ class OnepageController extends Controller
if (Cart::hasError())
return redirect()->route('shop.checkout.cart.index');
$this->nonCoupon->apply();
// $this->nonCoupon->apply();
$this->nonCoupon->getApplicableRules();
Cart::collectTotals();
@ -126,7 +127,7 @@ class OnepageController extends Controller
if (Cart::hasError() || !Cart::saveCustomerAddress($data) || ! $rates = Shipping::collectRates())
return response()->json(['redirect_url' => route('shop.checkout.cart.index')], 403);
$this->nonCoupon->apply();
$this->nonCoupon->getApplicableRules();
Cart::collectTotals();
@ -145,7 +146,7 @@ class OnepageController extends Controller
if (Cart::hasError() || !$shippingMethod || !Cart::saveShippingMethod($shippingMethod))
return response()->json(['redirect_url' => route('shop.checkout.cart.index')], 403);
$this->nonCoupon->apply();
$this->nonCoupon->getApplicableRules();
Cart::collectTotals();
@ -164,7 +165,7 @@ class OnepageController extends Controller
if (Cart::hasError() || !$payment || !Cart::savePaymentMethod($payment))
return response()->json(['redirect_url' => route('shop.checkout.cart.index')], 403);
$this->nonCoupon->apply();
$this->nonCoupon->getApplicableRules();
$this->nonCoupon->checkOnShipping(Cart::getCart());