From 9cdacf901ccd43ce0c1ed51c8e7a0bbab49e7933 Mon Sep 17 00:00:00 2001 From: sartoric <> Date: Tue, 14 Jan 2020 22:33:12 +0100 Subject: [PATCH 1/3] changed the strategy for cart values calculation (taxes per row), test, some fixes --- src/Cart.php | 10 +++++----- src/CartItem.php | 41 +++++++++++++++++++++++++++++------------ tests/CartTest.php | 27 ++++++++++++++++++++++++--- 3 files changed, 58 insertions(+), 20 deletions(-) diff --git a/src/Cart.php b/src/Cart.php index 0ead1f59..7a0333ea 100644 --- a/src/Cart.php +++ b/src/Cart.php @@ -375,7 +375,7 @@ public function subtotal($decimals = null, $decimalPoint = null, $thousandSepera } /** - * Get the subtotal (total - tax) of the items in the cart. + * Get the discount of the items in the cart. * * @return float */ @@ -387,7 +387,7 @@ public function discountFloat() } /** - * Get the subtotal (total - tax) of the items in the cart as formatted string. + * Get the discount of the items in the cart as formatted string. * * @param int $decimals * @param string $decimalPoint @@ -401,11 +401,11 @@ public function discount($decimals = null, $decimalPoint = null, $thousandSepera } /** - * Get the subtotal (total - tax) of the items in the cart. + * Get the price of the items in the cart. * * @return float */ - public function initialFloat() + public function initialFloat() // TODO: rename and use priceTotal { return $this->getContent()->reduce(function ($initial, CartItem $cartItem) { return $initial + ($cartItem->qty * $cartItem->price); @@ -413,7 +413,7 @@ public function initialFloat() } /** - * Get the subtotal (total - tax) of the items in the cart as formatted string. + * Get the price of the items in the cart as formatted string. * * @param int $decimals * @param string $decimalPoint diff --git a/src/CartItem.php b/src/CartItem.php index 6ba3f5f4..a7387cc1 100644 --- a/src/CartItem.php +++ b/src/CartItem.php @@ -253,6 +253,20 @@ public function discountTotal($decimals = null, $decimalPoint = null, $thousandS return $this->numberFormat($this->discountTotal, $decimals, $decimalPoint, $thousandSeperator); } + /** + * Returns the formatted total price for this cart item. + * + * @param int $decimals + * @param string $decimalPoint + * @param string $thousandSeperator + * + * @return string + */ + public function priceTotal($decimals = null, $decimalPoint = null, $thousandSeperator = null) + { + return $this->numberFormat($this->priceTotal, $decimals, $decimalPoint, $thousandSeperator); + } + /** * Set the quantity for this cart item. * @@ -354,26 +368,29 @@ public function __get($attribute) if (property_exists($this, $attribute)) { return $this->{$attribute}; } + $decimals = config('cart.format.decimals', 2); switch ($attribute) { case 'discount': return $this->price * ($this->discountRate / 100); - case 'priceTarget': - return $this->price - $this->discount; - case 'subtotal': - return $this->priceTarget * $this->qty; case 'tax': - return $this->priceTarget * ($this->taxRate / 100); + return round($this->priceTarget * ($this->taxRate / 100), $decimals); case 'priceTax': - return $this->priceTarget + $this->tax; - case 'total': - return $this->priceTax * $this->qty; - case 'taxTotal': - return $this->tax * $this->qty; + return round($this->priceTarget + $this->tax, $decimals); case 'discountTotal': - return $this->discount * $this->qty; + return round ($this->discount * $this->qty, $decimals); case 'weightTotal': - return $this->weight * $this->qty; + return round($this->weight * $this->qty, $decimals); + case 'priceTotal': + return round($this->price * $this->qty, $decimals); + case 'subtotal': + return round($this->priceTotal - $this->discountTotal, $decimals); + 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); case 'model': if (isset($this->associatedModel)) { diff --git a/tests/CartTest.php b/tests/CartTest.php index e48d5b67..7d499dac 100644 --- a/tests/CartTest.php +++ b/tests/CartTest.php @@ -1049,7 +1049,7 @@ public function can_change_discount_globally() } /** @test */ - public function cart_hast_no_rounding_errors() + public function cart_has_no_rounding_errors() { $cart = $this->getCart(); @@ -1309,6 +1309,26 @@ public function it_can_merge_dispatching_add_events() }); } + /** @test */ + public function it_use_correctly_rounded_values_for_totals_and_cart_summary() { + + $this->setConfigFormat(2, ',', ''); + + $cart = $this->getCartDiscount(6); + + $cartItem = $cart->add(new BuyableProduct(1, 'First item', 0.18929), 1000); + $cart->add(new BuyableProduct(2, 'Second item', 4.41632), 5); + $cart->add(new BuyableProduct(3, 'Third item', 0.37995), 25); + + $cart->setGlobalTax(22); + + // check total + $this->assertEquals('253,29', $cart->total()); + + // check that the sum of cart subvalues matches the total (in order to avoid cart summary to looks wrong) + $this->assertEquals($cart->totalFloat(), $cart->subtotalFloat() + $cart->taxFloat()); + } + /** * Get an instance of the cart. * @@ -1325,12 +1345,13 @@ private function getCart() /** * Get an instance of the cart with discount. * + * @param int $discount * @return \Gloudemans\Shoppingcart\Cart */ - private function getCartDiscount($discount = 0) + private function getCartDiscount($discount = 50) { $cart = $this->getCart(); - $cart->setGlobalDiscount(50); + $cart->setGlobalDiscount($discount); return $cart; } From 1a34bda8ab37403f054f56994cb5057765306b3d Mon Sep 17 00:00:00 2001 From: sartoric <> Date: Wed, 15 Jan 2020 12:44:58 +0100 Subject: [PATCH 2/3] added CartItem::priceTotal for rounded total (from internal calculation) --- src/Cart.php | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/src/Cart.php b/src/Cart.php index 7a0333ea..53bedbd4 100644 --- a/src/Cart.php +++ b/src/Cart.php @@ -401,11 +401,11 @@ public function discount($decimals = null, $decimalPoint = null, $thousandSepera } /** - * Get the price of the items in the cart. + * Get the price of the items in the cart (not rounded). * * @return float */ - public function initialFloat() // TODO: rename and use priceTotal + public function initialFloat() { return $this->getContent()->reduce(function ($initial, CartItem $cartItem) { return $initial + ($cartItem->qty * $cartItem->price); @@ -426,6 +426,32 @@ public function initial($decimals = null, $decimalPoint = null, $thousandSeperat return $this->numberFormat($this->initialFloat(), $decimals, $decimalPoint, $thousandSeperator); } + /** + * Get the price of the items in the cart (previously rounded). + * + * @return float + */ + public function priceTotalFloat() + { + return $this->getContent()->reduce(function ($initial, CartItem $cartItem) { + return $initial + $cartItem->priceTotal; + }, 0); + } + + /** + * Get the price of the items in the cart as formatted string. + * + * @param int $decimals + * @param string $decimalPoint + * @param string $thousandSeperator + * + * @return string + */ + public function priceTotal($decimals = null, $decimalPoint = null, $thousandSeperator = null) + { + return $this->numberFormat($this->priceTotalFloat(), $decimals, $decimalPoint, $thousandSeperator); + } + /** * Get the total weight of the items in the cart. * From 7b29fe376d9c68f5484850277fc62a6d05c5038b Mon Sep 17 00:00:00 2001 From: Patrick Henninger Date: Sat, 18 Jan 2020 17:29:06 +0100 Subject: [PATCH 3/3] StyleCI --- src/CartItem.php | 4 ++-- tests/CartTest.php | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/CartItem.php b/src/CartItem.php index a7387cc1..c2d97247 100644 --- a/src/CartItem.php +++ b/src/CartItem.php @@ -378,7 +378,7 @@ public function __get($attribute) case 'priceTax': return round($this->priceTarget + $this->tax, $decimals); case 'discountTotal': - return round ($this->discount * $this->qty, $decimals); + return round($this->discount * $this->qty, $decimals); case 'weightTotal': return round($this->weight * $this->qty, $decimals); case 'priceTotal': @@ -388,7 +388,7 @@ public function __get($attribute) case 'priceTarget': return round(($this->priceTotal - $this->discountTotal) / $this->qty, $decimals); case 'taxTotal': - return round($this->subtotal * ($this->taxRate / 100) , $decimals); + return round($this->subtotal * ($this->taxRate / 100), $decimals); case 'total': return round($this->subtotal + $this->taxTotal, $decimals); diff --git a/tests/CartTest.php b/tests/CartTest.php index 7d499dac..e5624dca 100644 --- a/tests/CartTest.php +++ b/tests/CartTest.php @@ -1310,8 +1310,8 @@ public function it_can_merge_dispatching_add_events() } /** @test */ - public function it_use_correctly_rounded_values_for_totals_and_cart_summary() { - + public function it_use_correctly_rounded_values_for_totals_and_cart_summary() + { $this->setConfigFormat(2, ',', ''); $cart = $this->getCartDiscount(6); @@ -1346,6 +1346,7 @@ private function getCart() * Get an instance of the cart with discount. * * @param int $discount + * * @return \Gloudemans\Shoppingcart\Cart */ private function getCartDiscount($discount = 50)