Refactor gross price / default into calculators,

Remove gross_price from config replaced with calculator
This commit is contained in:
Patrick Henninger
2020-08-29 16:18:05 +02:00
parent ae0a976785
commit 238d8cf7d9
5 changed files with 90 additions and 55 deletions

View File

@@ -0,0 +1,34 @@
<?php
namespace Gloudemans\Shoppingcart\Calculation;
use Gloudemans\Shoppingcart\CartItem;
class DefaultCalculator {
static function getAttribute(string $attribute, CartItem $cartItem) {
$decimals = config('cart.format.decimals', 2);
switch ($attribute) {
case 'discount':
return $cartItem->price * ($cartItem->getDiscountRate() / 100);
case 'tax':
return round($cartItem->priceTarget * ($cartItem->taxRate / 100), $decimals);
case 'priceTax':
return round($cartItem->priceTarget + $cartItem->tax, $decimals);
case 'discountTotal':
return round($cartItem->discount * $cartItem->qty, $decimals);
case 'priceTotal':
return round($cartItem->price * $cartItem->qty, $decimals);
case 'subtotal':
return max(round($cartItem->priceTotal - $cartItem->discountTotal, $decimals), 0);
case 'priceTarget':
return round(($cartItem->priceTotal - $cartItem->discountTotal) / $cartItem->qty, $decimals);
case 'taxTotal':
return round($cartItem->subtotal * ($cartItem->taxRate / 100), $decimals);
case 'total':
return round($cartItem->subtotal + $cartItem->taxTotal, $decimals);
default:
return;
}
}
}

View File

@@ -0,0 +1,36 @@
<?php
namespace Gloudemans\Shoppingcart\Calculation;
use Gloudemans\Shoppingcart\CartItem;
class GrossPrice {
static function getAttribute(string $attribute, CartItem $cartItem) {
$decimals = config('cart.format.decimals', 2);
switch ($attribute) {
case 'priceNet':
return round($cartItem->price / (1 + ($cartItem->taxRate / 100)), $decimals);
case 'discount':
return $cartItem->priceNet * ($cartItem->getDiscountRate() / 100);
case 'tax':
return round($cartItem->priceTarget * ($cartItem->taxRate / 100), $decimals);
case 'priceTax':
return round($cartItem->priceTarget + $cartItem->tax, $decimals);
case 'discountTotal':
return round($cartItem->discount * $cartItem->qty, $decimals);
case 'priceTotal':
return round($cartItem->priceNet * $cartItem->qty, $decimals);
case 'subtotal':
return max(round($cartItem->priceTotal - $cartItem->discountTotal, $decimals), 0);
case 'priceTarget':
return round(($cartItem->priceTotal - $cartItem->discountTotal) / $cartItem->qty, $decimals);
case 'taxTotal':
return round($cartItem->subtotal * ($cartItem->taxRate / 100), $decimals);
case 'total':
return round($cartItem->subtotal + $cartItem->taxTotal, $decimals);
default:
return;
}
}
}

View File

@@ -2,6 +2,7 @@
namespace Gloudemans\Shoppingcart;
use Gloudemans\Shoppingcart\Calculation\DefaultCalculator;
use Gloudemans\Shoppingcart\Contracts\Buyable;
use Illuminate\Contracts\Support\Arrayable;
use Illuminate\Contracts\Support\Jsonable;
@@ -89,7 +90,7 @@ class CartItem implements Arrayable, Jsonable
*
* @var float
*/
private $discountRate = 0;
private float $discountRate = 0;
/**
* CartItem constructor.
@@ -396,56 +397,8 @@ class CartItem implements Arrayable, Jsonable
case 'weightTotal':
return round($this->weight * $this->qty, $decimals);
}
if (config('cart.gross_price')) {
switch ($attribute) {
case 'priceNet':
return round($this->price / (1 + ($this->taxRate / 100)), $decimals);
case 'discount':
return $this->priceNet * ($this->discountRate / 100);
case 'tax':
return round($this->priceTarget * ($this->taxRate / 100), $decimals);
case 'priceTax':
return round($this->priceTarget + $this->tax, $decimals);
case 'discountTotal':
return round($this->discount * $this->qty, $decimals);
case 'priceTotal':
return round($this->priceNet * $this->qty, $decimals);
case 'subtotal':
return max(round($this->priceTotal - $this->discountTotal, $decimals), 0);
case 'priceTarget':
return round(($this->priceTotal - $this->discountTotal) / $this->qty, $decimals);
case 'taxTotal':
return round($this->subtotal * ($this->taxRate / 100), $decimals);
case 'total':
return round($this->subtotal + $this->taxTotal, $decimals);
default:
return;
}
} else {
switch ($attribute) {
case 'discount':
return $this->price * ($this->discountRate / 100);
case 'tax':
return round($this->priceTarget * ($this->taxRate / 100), $decimals);
case 'priceTax':
return round($this->priceTarget + $this->tax, $decimals);
case 'discountTotal':
return round($this->discount * $this->qty, $decimals);
case 'priceTotal':
return round($this->price * $this->qty, $decimals);
case 'subtotal':
return max(round($this->priceTotal - $this->discountTotal, $decimals), 0);
case 'priceTarget':
return round(($this->priceTotal - $this->discountTotal) / $this->qty, $decimals);
case 'taxTotal':
return round($this->subtotal * ($this->taxRate / 100), $decimals);
case 'total':
return round($this->subtotal + $this->taxTotal, $decimals);
default:
return;
}
}
return call_user_func(config('cart.calculator', DefaultCalculator::class) . '::getAttribute', $attribute, $this);
}
/**
@@ -564,4 +517,15 @@ class CartItem implements Arrayable, Jsonable
return number_format($value, $decimals, $decimalPoint, $thousandSeperator);
}
}
/**
* Getter for the raw internal discount rate.
* Should be used in calculators.
*
* @return float
*/
public function getDiscountRate()
{
return $this->discountRate;
}
}

View File

@@ -12,7 +12,7 @@ return [
|
*/
'gross_price' => false,
'calculator' => \Gloudemans\Shoppingcart\Calculation\DefaultCalculator::class,
/*
|--------------------------------------------------------------------------

View File

@@ -3,6 +3,7 @@
namespace Gloudemans\Tests\Shoppingcart;
use Carbon\Carbon;
use Gloudemans\Shoppingcart\Calculation\GrossPrice;
use Gloudemans\Shoppingcart\Cart;
use Gloudemans\Shoppingcart\CartItem;
use Gloudemans\Shoppingcart\ShoppingcartServiceProvider;
@@ -1378,7 +1379,7 @@ class CartTest extends TestCase
public function it_use_gross_price_as_base_price()
{
$cart = $this->getCartDiscount(0);
config(['cart.gross_price' => true]);
config(['cart.calculator' => GrossPrice::class]);
$cartItem = $cart->add(new BuyableProduct(1, 'First item', 100), 2);
@@ -1392,7 +1393,7 @@ class CartTest extends TestCase
public function it_use_gross_price_and_it_use_correctly_rounded_values_for_totals_and_cart_summary()
{
$this->setConfigFormat(2, ',', '');
config(['cart.gross_price' => true]);
config(['cart.calculator' => GrossPrice::class]);
$cart = $this->getCartDiscount(6);