diff --git a/src/Calculation/DefaultCalculator.php b/src/Calculation/DefaultCalculator.php new file mode 100644 index 0000000..e554fb5 --- /dev/null +++ b/src/Calculation/DefaultCalculator.php @@ -0,0 +1,34 @@ +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; + } + } +} \ No newline at end of file diff --git a/src/Calculation/GrossPrice.php b/src/Calculation/GrossPrice.php new file mode 100644 index 0000000..d622e12 --- /dev/null +++ b/src/Calculation/GrossPrice.php @@ -0,0 +1,36 @@ +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; + } + } +} \ No newline at end of file diff --git a/src/CartItem.php b/src/CartItem.php index 675371b..b73d203 100644 --- a/src/CartItem.php +++ b/src/CartItem.php @@ -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; + } +} \ No newline at end of file diff --git a/src/Config/cart.php b/src/Config/cart.php index 739265e..42f667a 100644 --- a/src/Config/cart.php +++ b/src/Config/cart.php @@ -12,7 +12,7 @@ return [ | */ - 'gross_price' => false, + 'calculator' => \Gloudemans\Shoppingcart\Calculation\DefaultCalculator::class, /* |-------------------------------------------------------------------------- diff --git a/tests/CartTest.php b/tests/CartTest.php index 09e3526..0e45315 100644 --- a/tests/CartTest.php +++ b/tests/CartTest.php @@ -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);