Catalog rules tie break in progress, squased a line of dead code in CartRuleController

This commit is contained in:
Prashant Singh 2019-08-19 12:36:43 +05:30
parent aca7b4c6c7
commit 8a9198e5d9
11 changed files with 420 additions and 130 deletions

View File

@ -188,13 +188,15 @@ return [
'route' => 'admin.cart-rule.index',
'sort' => 1,
'icon-class' => '',
], [
'key' => 'promotions.catalog-rule',
'name' => 'admin::app.promotion.catalog-rule',
'route' => 'admin.catalog-rule.index',
'sort' => 1,
'icon-class' => '',
], [
],
// [
// 'key' => 'promotions.catalog-rule',
// 'name' => 'admin::app.promotion.catalog-rule',
// 'route' => 'admin.catalog-rule.index',
// 'sort' => 1,
// 'icon-class' => '',
// ],
[
'key' => 'cms',
'name' => 'admin::app.layouts.cms',
'route' => 'admin.cms.index',

View File

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

View File

@ -0,0 +1,22 @@
<?php
namespace Webkul\Discount\Actions\Catalog;
use Webkul\Discount\Actions\Catalog\Action;
class AdjustToDiscountValue extends Action
{
public function calculate($rule, $product)
{
$discountAmount = $rule->discount_amount;
$price = $product->price;
if ($discountAmount <= $price) {
$discount = $price - $discountAmount;
return $discount;
} else {
return $price;
}
}
}

View File

@ -0,0 +1,19 @@
<?php
namespace Webkul\Discount\Actions\Catalog;
use Webkul\Discount\Actions\Catalog\Action;
class AdjustToPerenct extends Action
{
public function calculate($rule, $product)
{
$discountAmount = $rule->discount_amount;
$price = $product->price;
$discount = ($discountAmount / 100) * $price;
return $discount;
}
}

View File

@ -0,0 +1,20 @@
<?php
namespace Webkul\Discount\Actions\Catalog;
use Webkul\Discount\Actions\Catalog\Action;
class FixedAmount extends Action
{
public function calculate($rule, $product)
{
$discountAmount = $rule->discount_amount;
$price = $product->price;
if ($discountAmount <= $price) {
return $discountAmount;
} else {
return $price;
}
}
}

View File

@ -0,0 +1,19 @@
<?php
namespace Webkul\Discount\Actions\Catalog;
use Webkul\Discount\Actions\Catalog\Action;
class PercentOfOriginal extends Action
{
public function calculate($rule, $product)
{
$discountAmount = $rule->discount_amount;
$price = $product->price;
$discount = ($discountAmount / 100) * $price;
return $discount;
}
}

View File

@ -109,10 +109,10 @@ return [
'catalog' => [
'actions' => [
'percent_of_product' => 'Percentage of product',
'percent_of_original' => 'Percentage of product',
'fixed_amount' => 'Apply as fixed amount',
'adjust_to_percent' => 'Adjust price to percentage',
'adjust_to_fixed_amount' => 'Adjust price to given amount'
'final_price_to_percent' => 'Adjust price to percentage',
'to_discount_value' => 'Adjust price to given amount'
],
'validation' => [

View File

@ -100,16 +100,19 @@ class Apply extends Sale
if ($this->active->count()) {
$productIDs = array();
$temp = collect();
foreach ($this->activeRules as $rule) {
array_push($productIDs, $this->getProductIds($rule));
$productIDs = $this->getProductIds($rule);
$productIDs = $this->expandProducts($productIDs);
$result = $this->setSale($rule, $productIDs);
}
dd(array_flatten($productIDs));
$this->setSale($rule, $productIDs);
dd($result, 'processing done');
} else {
// handle the deceased rules here
dd($this->deceased);
}
}
@ -126,9 +129,11 @@ class Apply extends Sale
if (is_array($productIDs)) {
// apply on selected products
foreach ($productIDs as $productID) {
$this->createOrUpdate($rule, $productID);
// catalog rule product resource is updated here
$this->catalogRuleProduct->createOrUpdate($rule, $productID);
// $this->catalogRuleProductPrice->createOrUpdate($rule, $productID);
// catalog rule product price resource is updated here
$this->catalogRuleProductPrice->createOrUpdate($rule, $productID);
}
} else if ($productIDs == '*') {
$this->catalogRuleProduct->createOrUpdate($rule, $productIDs);
@ -138,127 +143,36 @@ class Apply extends Sale
}
/**
* Create or update catalog rule product resource
* To expand the productIDs of configurable products
*
* @param CatalogRule $rule
* @param Integer $productID
* @param Array $productIDs
*
* @return Void
* @return Array
*/
public function createOrUpdate($rule, $productID)
protected function expandProducts($productIDs)
{
$channels = $rule->channels;
$customerGroups = $rule->customer_groups;
$products = app('Webkul\Product\Repositories\ProductRepository');
$channelsGroupsCross = $channels->crossJoin($customerGroups);
$newProductIDs = collect();
if ($productID == '*') {
$products = $this->product->all('id');
foreach ($productIDs as $productID) {
$product = $products->find($productID);
foreach ($channelsGroupsCross as $channelGroup) {
$channelId = $channelGroup[0]->channel_id;
$groupId = $channelGroup[1]->customer_group_id;
if ($product->type == 'configurable') {
$variants = $product->variants;
$model = new $this->model();
foreach ($products as $product) {
$productID = $product->id;
$catalogRuleProduct = $this->catalogRuleProduct->findWhere([
'channel_id' => $channelId,
'customer_group_id' => $groupId,
'product_id' => $productID
]);
if ($catalogRuleProduct->count()) {
// check for tie breaker rules and then update
$previousRuleID = $catalogRuleProduct->first()->catalog_rule_id;
$newRuleID = $rule->id;
$winnerRuleId = $this->breakTie($previousRuleID, $newRuleID);
$data = [
'catalog_rule_id' => $rule->id,
'starts_from' => $rule->starts_from,
'ends_till' => $rule->ends_till,
'customer_group_id' => $groupId,
'channel_id' => $channelId,
'product_id' => $productID,
'action_code' => $rule->action_code,
'action_amount' => $rule->discount_amount
];
if ($rule->id == $winnerRuleId) {
$this->catalogRuleProduct->create($data);
} else {
$this->catalogRuleProduct->update($data, $catalogRuleProduct->first()->id);
}
} else {
$data = [
'catalog_rule_id' => $rule->id,
'starts_from' => $rule->starts_from,
'ends_till' => $rule->ends_till,
'customer_group_id' => $groupId,
'channel_id' => $channelId,
'product_id' => $productID,
'action_code' => $rule->action_code,
'action_amount' => $rule->discount_amount
];
$this->catalogRuleProduct->create($data);
}
foreach($variants as $variant) {
$newProductIDs->push($variant->id);
}
} else {
$newProductIDs->push($productID);
}
}
if ($newProductIDs->count()) {
return $newProductIDs->toArray();
} else {
foreach ($channelsGroupsCross as $channelGroup) {
$channelId = $channelGroup[0]->channel_id;
$groupId = $channelGroup[1]->customer_group_id;
$catalogRuleProduct = $this->catalogRuleProduct->findWhere([
'channel_id' => $channelId,
'customer_group_id' => $groupId,
'product_id' => $productID
]);
if ($catalogRuleProduct->count() && $catalogRuleProduct->first()->catalog_rule_id != $rule->id) {
// check for tie breaker rules and then update
$previousRuleID = $catalogRuleProduct->first()->catalog_rule_id;
$newRuleID = $rule->id;
$winnerRuleId = $this->breakTie($previousRuleID, $newRuleID);
// update
$catalogRuleProduct->first()->update([
'catalog_rule_id' => $rule->id,
'starts_from' => $rule->starts_from,
'ends_till' => $rule->ends_till,
'customer_group_id' => $groupId,
'channel_id' => $channelId,
'product_id' => $productID,
'action_code' => $rule->action_code,
'action_amount' => $rule->discount_amount
]);
} else if ($catalogRuleProduct->count() == 0) {
// create
$data = [
'catalog_rule_id' => $rule->id,
'starts_from' => $rule->starts_from,
'ends_till' => $rule->ends_till,
'customer_group_id' => $groupId,
'channel_id' => $channelId,
'product_id' => $productID,
'action_code' => $rule->action_code,
'action_amount' => $rule->discount_amount
];
$this->catalogRuleProduct->create($data);
} else {
// do the reassessment updation if the cart rule action changes the new action and its amount needs to be updated
}
}
return [];
}
}

View File

@ -349,7 +349,6 @@ class CartRuleController extends Controller
*/
public function update($id)
{
dd(request()->all());
$this->validate(request(), [
'name' => 'required|string|unique:cart_rules,name,'.$id,
'description' => 'string',

View File

@ -4,6 +4,7 @@ namespace Webkul\Discount\Repositories;
use Webkul\Core\Eloquent\Repository;
use Webkul\Product\Repositories\ProductRepository as Product;
use Webkul\Discount\Repositories\CatalogRuleProductsRepository as CatalogRuleProduct;
use Illuminate\Container\Container as App;
/**
@ -15,17 +16,26 @@ use Illuminate\Container\Container as App;
class CatalogRuleProductsPriceRepository extends Repository
{
/**
* ProductRepository instance
* To hold ProductRepository instance
*/
protected $product;
/**
* To hold CatalogRuleProductRepository instance
*
*/
protected $catalogRuleProduct;
/**
* @param Product $product
*/
public function __construct(Product $product, App $app)
public function __construct(Product $product, CatalogRuleProduct $catalogRuleProduct,App $app)
{
$this->product = $product;
$this->catalogRuleProduct = $catalogRuleProduct;
parent::__construct($app);
}
@ -38,4 +48,136 @@ class CatalogRuleProductsPriceRepository extends Repository
{
return 'Webkul\Discount\Contracts\CatalogRuleProductsPrice';
}
/**
* Create or update catalog rule product resource
*
* @param CatalogRule $rule
* @param Integer $productID
*
* @return Void
*/
public function createOrUpdate($rule, $productID)
{
$channels = $rule->channels;
$customerGroups = $rule->customer_groups;
$channelsGroupsCross = $channels->crossJoin($customerGroups);
if ($productID == '*') {
$products = $this->product->all('id');
foreach ($channelsGroupsCross as $channelGroup) {
$channelId = $channelGroup[0]->channel_id;
$groupId = $channelGroup[1]->customer_group_id;
foreach ($products as $product) {
$productID = $product->id;
$catalogRuleProductPrice = $this->findWhere([
'channel_id' => $channelId,
'customer_group_id' => $groupId,
'product_id' => $productID
]);
if ($catalogRuleProductPrice->count()) {
// check for tie breaker rules and then update
$data = [
'catalog_rule_id' => $rule->id,
'starts_from' => $rule->starts_from,
'ends_till' => $rule->ends_till,
'customer_group_id' => $groupId,
'channel_id' => $channelId,
'product_id' => $productID,
'action_code' => $rule->action_code,
'action_amount' => $rule->discount_amount
];
$this->update($data, $catalogRuleProductPrice->first()->id);
} else {
$data = [
'catalog_rule_id' => $rule->id,
'starts_from' => $rule->starts_from,
'ends_till' => $rule->ends_till,
'customer_group_id' => $groupId,
'channel_id' => $channelId,
'product_id' => $productID,
'action_code' => $rule->action_code,
'action_amount' => $rule->discount_amount
];
$this->create($data);
}
}
}
} else {
foreach ($channelsGroupsCross as $channelGroup) {
$channelId = $channelGroup[0]->channel_id;
$groupId = $channelGroup[1]->customer_group_id;
$catalogRuleProduct = $this->catalogRuleProduct->findWhere([
'channel_id' => $channelId,
'customer_group_id' => $groupId,
'product_id' => $productID
]);
$catalogRuleProductPrice = $this->findWhere([
'channel_id' => $channelId,
'customer_group_id' => $groupId,
'product_id' => $productID
]);
if ($catalogRuleProductPrice->count() && $catalogRuleProductPrice->first()->catalog_rule_id != $rule->id) {
$catalogRuleProduct = $catalogRuleProduct->first();
$discountAmount = $rule->discount_amount;
$product = $this->product->find($productID);
$productPrice = $product->price - $catalogRuleProduct->action_amount;
$data = [
'catalog_rule_id' => $rule->id,
'starts_from' => $rule->starts_from,
'ends_till' => $rule->ends_till,
'customer_group_id' => $groupId,
'channel_id' => $channelId,
'product_id' => $productID,
'rule_price' => $productPrice
];
// update
$catalogRuleProductPrice->first()->update($data);
} else if ($catalogRuleProductPrice->count() == 0) {
$catalogRuleProduct = $catalogRuleProduct->first();
$discountAmount = $rule->discount_amount;
$product = $this->product->find($productID);
$productPrice = $product->price - $catalogRuleProduct->action_amount;
if ($productPrice <= $discountAmount) {
$product->price = $productPrice - $discountAmount;
} else {
$product->price = 0;
}
$data = [
'catalog_rule_id' => $rule->id,
'starts_from' => $rule->starts_from,
'ends_till' => $rule->ends_till,
'customer_group_id' => $groupId,
'channel_id' => $channelId,
'product_id' => $productID,
'rule_price' => $productPrice
];
$this->create($data);
} else {
// do the reassessment updation if the cart rule action changes the new action and its amount needs to be updated
}
}
}
}
}

View File

@ -36,6 +36,18 @@ class CatalogRuleProductsRepository extends Repository
parent::__construct($app);
}
public function getDiscountAmount($product, $rule)
{
$actionClass = config('discount-rules.catalog')[$rule->action_code];
$actionInstance = new $actionClass();
$discountAmount = $actionInstance->calculate($rule, $product);
return $discountAmount;
}
/**
* Specify Model class name
*
@ -45,4 +57,137 @@ class CatalogRuleProductsRepository extends Repository
{
return 'Webkul\Discount\Contracts\CatalogRuleProducts';
}
/**
* Create or update catalog rule product resource
*
* @param CatalogRule $rule
* @param Integer $productID
*
* @return Void
*/
public function createOrUpdate($rule, $productID)
{
$channels = $rule->channels;
$customerGroups = $rule->customer_groups;
$channelsGroupsCross = $channels->crossJoin($customerGroups);
if ($productID == '*') {
$products = $this->product->all('id');
foreach ($channelsGroupsCross as $channelGroup) {
$channelId = $channelGroup[0]->channel_id;
$groupId = $channelGroup[1]->customer_group_id;
$model = new $this->model();
foreach ($products as $product) {
$productID = $product->id;
$catalogRuleProduct = $this->findWhere([
'channel_id' => $channelId,
'customer_group_id' => $groupId,
'product_id' => $productID
]);
if ($catalogRuleProduct->count()) {
// check for tie breaker rules and then update
$previousRuleID = $catalogRuleProduct->first()->catalog_rule_id;
$newRuleID = $rule->id;
$winnerRuleId = $this->breakTie($previousRuleID, $newRuleID);
$data = [
'catalog_rule_id' => $rule->id,
'starts_from' => $rule->starts_from,
'ends_till' => $rule->ends_till,
'customer_group_id' => $groupId,
'channel_id' => $channelId,
'product_id' => $productID,
'action_code' => $rule->action_code,
'action_amount' => $rule->discount_amount
];
if ($rule->id == $winnerRuleId) {
$this->catalogRuleProduct->create($data);
} else {
$this->catalogRuleProduct->update($data, $catalogRuleProduct->first()->id);
}
} else {
$data = [
'catalog_rule_id' => $rule->id,
'starts_from' => $rule->starts_from,
'ends_till' => $rule->ends_till,
'customer_group_id' => $groupId,
'channel_id' => $channelId,
'product_id' => $productID,
'action_code' => $rule->action_code,
'action_amount' => $rule->discount_amount
];
$this->catalogRuleProduct->create($data);
}
}
}
} else {
foreach ($channelsGroupsCross as $channelGroup) {
$channelId = $channelGroup[0]->channel_id;
$groupId = $channelGroup[1]->customer_group_id;
$catalogRuleProduct = $this->findWhere([
'channel_id' => $channelId,
'customer_group_id' => $groupId,
'product_id' => $productID
]);
if ($catalogRuleProduct->count() && $catalogRuleProduct->first()->catalog_rule_id != $rule->id) {
$product = $this->product->find($productID);
$productPrice = $product->price;
$discountAmount = $this->getDiscountAmount($product, $rule);
// check for tie breaker rules and then update
$previousRuleID = $catalogRuleProduct->first()->catalog_rule_id;
$newRuleID = $rule->id;
$winnerRuleId = $this->breakTie($previousRuleID, $newRuleID);
// update
$catalogRuleProduct->first()->update([
'catalog_rule_id' => $rule->id,
'starts_from' => $rule->starts_from,
'ends_till' => $rule->ends_till,
'customer_group_id' => $groupId,
'channel_id' => $channelId,
'product_id' => $productID,
'action_code' => $rule->action_code,
'action_amount' => $discountAmount
]);
} else if ($catalogRuleProduct->count() == 0) {
$product = $this->product->find($productID);
$productPrice = $product->price;
$discountAmount = $this->getDiscountAmount($product, $rule);
$data = [
'catalog_rule_id' => $rule->id,
'starts_from' => $rule->starts_from,
'ends_till' => $rule->ends_till,
'customer_group_id' => $groupId,
'channel_id' => $channelId,
'product_id' => $productID,
'action_code' => $rule->action_code,
'action_amount' => $discountAmount
];
$this->create($data);
} else {
// do the reassessment updation if the cart rule action changes the new action and its amount needs to be updated
}
}
}
}
}