Commit 3ac51f09 authored by Thomas Bilk's avatar Thomas Bilk

modified cart total method to also apply new price conditions

parent 00167799
......@@ -318,7 +318,7 @@ class Cart implements Jsonable, \JsonSerializable, Arrayable{
// set target to cart if not set
$condition->setTarget($condition->getTarget() ?: Condition::TARGET_CART);
if ($condition->getTarget() !== Condition::TARGET_CART)
if (!in_array($condition->getTarget(), [Condition::TARGET_CART, Condition::TARGET_PRICE], true))
throw new InvalidConditionException('target have to be cart for cart conditions');
$conditions = $this->getConditions();
......@@ -339,11 +339,9 @@ class Cart implements Jsonable, \JsonSerializable, Arrayable{
public function getConditions($withItemConditions = false) {
$conditions = new Conditions($this->session->get($this->sessionKeyCartConditions));
if ($withItemConditions) {
$this->items()->each(function (Item $item) use (&$conditions) {
$item->conditions->each(function (Condition $condition) use (&$conditions) {
$conditions->push($condition);
});
});
return $conditions->concat($this->items()->flatMap(function (Item $item) {
return $item->conditions;
}));
}
return $conditions;
}
......@@ -431,7 +429,7 @@ class Cart implements Jsonable, \JsonSerializable, Arrayable{
}
if ($this->itemHasConditions($item))
return $item->conditions->offsetUnset($conditionName);
$item->conditions->offsetUnset($conditionName);
return true;
}
......@@ -482,7 +480,7 @@ class Cart implements Jsonable, \JsonSerializable, Arrayable{
* @return int
*/
public function subTotal($only_with_condition_type = null) {
$sum = $this->items()->sum(function (Item $item) use($only_with_condition_type) {
$sum = $this->items()->sum(function (Item $item) use ($only_with_condition_type) {
return $item->priceSumWithConditions($only_with_condition_type);
});
......@@ -500,14 +498,24 @@ class Cart implements Jsonable, \JsonSerializable, Arrayable{
if ($this->getConditions($only_with_condition_type)->isEmpty())
return $subTotal;
$condTotal = $this->getConditions($only_with_condition_type)->sum(function ($cond) use ($subTotal) {
/** @var Condition $cond */
return $cond->getTarget() === Condition::TARGET_CART
? $cond->applyCondition($subTotal)
: 0;
});
/* all cart conditions like fees or discounts are applied */
$condTotal = $this->getConditions($only_with_condition_type)
->filter(function (Condition $cond) {
return $cond->getTarget() === Condition::TARGET_CART;
})
->sum(function (Condition $cond) use ($subTotal) {
return $cond->applyCondition($subTotal);
});
/* all conditions affecting the price are applied */
$grand_total = $this->getConditions()
->filter(function (Condition $condition) {
return $condition->getTarget() === Condition::TARGET_PRICE;
})->reduce(function ($acc, Condition $cond) {
return $acc + $cond->applyCondition($acc);
}, $subTotal + $condTotal);
return $subTotal + $condTotal;
return $grand_total < 0 ? 0 : $grand_total;
}
......
......@@ -14,7 +14,7 @@ class Condition extends Collection {
const TARGET_CART = 'cart';
const TARGET_ITEM = 'item';
const TARGET_price = 'price';
const TARGET_PRICE = 'price';
/**
* List of validation rules for the condition
......@@ -23,7 +23,7 @@ class Condition extends Collection {
protected $rules = [
'name' => 'required',
'type' => 'required|string',
'target' => 'sometimes|required|in:item,cart',
'target' => 'sometimes|required|in:item,cart,price',
'value' => 'required|string',
];
......
......@@ -531,7 +531,7 @@ class CartConditionTest extends PHPUnit_Framework_TestCase {
$this->assertEquals(2, count($this->cart->get(456)['conditions']), 'Item should have two conditions');
// now let's remove a condition on that item using the condition name
$this->cart->removeItemCondition(456, 'SALE 5%');
$this->assertTrue($this->cart->removeItemCondition(456, 'SALE 5%'));
// now we should have only 1 condition left on that item
$this->assertEquals(1, count($this->cart->get(456)['conditions']), 'Item should have one condition left');
......@@ -562,7 +562,7 @@ class CartConditionTest extends PHPUnit_Framework_TestCase {
$this->assertNotEmpty($this->cart->get(456)['conditions'], 'Item should have one condition in it.');
// now let's remove a condition on that item using the condition name
$this->cart->removeItemCondition(456, 'SALE 5%');
$this->assertTrue($this->cart->removeItemCondition(456, 'SALE 5%'));
// now we should have only 1 condition left on that item
$this->assertEmpty($this->cart->get(456)->conditions, 'Item should have no condition now');
......@@ -952,4 +952,174 @@ class CartConditionTest extends PHPUnit_Framework_TestCase {
$this->assertEquals(31000, $this->cart->total(), 'match total');
}
/**
* @throws \Bnet\Cart\Exceptions\InvalidConditionException
* @throws \Bnet\Cart\Exceptions\InvalidItemException
*/
public function test_single_coupon() {
$this->cart->add([
'id' => 456,
'name' => 'Sample Item 1',
'price' => 10000,
'quantity' => 3,
]);
$coupon = new Condition([
'name' => 'Coupon',
'type' => 'coupon',
'target' => Condition::TARGET_PRICE,
'value' => '-500',
]);
$this->cart->condition($coupon);
$this->assertEquals(30000, $this->cart->subTotal());
$this->assertEquals(29500, $this->cart->total());
}
/**
* @throws \Bnet\Cart\Exceptions\InvalidConditionException
* @throws \Bnet\Cart\Exceptions\InvalidItemException
*/
public function test_two_coupons() {
$this->cart->add([
'id' => 456,
'name' => 'Sample Item 1',
'price' => 10000,
'quantity' => 3,
]);
$coupon1 = new Condition([
'name' => 'Coupon 1',
'type' => 'coupon',
'target' => Condition::TARGET_PRICE,
'value' => '-500',
]);
$coupon2 = new Condition([
'name' => 'Coupon 2',
'type' => 'coupon',
'target' => Condition::TARGET_PRICE,
'value' => '-1500',
]);
$this->cart->condition([$coupon1, $coupon2]);
$this->assertEquals(30000, $this->cart->subTotal());
$this->assertEquals(28000, $this->cart->total());
}
/**
* @throws \Bnet\Cart\Exceptions\InvalidConditionException
* @throws \Bnet\Cart\Exceptions\InvalidItemException
*/
public function test_larger_coupons_than_items() {
$this->cart->add([
'id' => 456,
'name' => 'Sample Item 1',
'price' => 2500,
'quantity' => 3,
]);
$coupon1 = new Condition([
'name' => 'Coupon 1',
'type' => 'coupon',
'target' => Condition::TARGET_PRICE,
'value' => '-5000',
]);
$coupon2 = new Condition([
'name' => 'Coupon 2',
'type' => 'coupon',
'target' => Condition::TARGET_PRICE,
'value' => '-3000',
]);
$this->cart->condition([$coupon1, $coupon2]);
$this->assertEquals(7500, $this->cart->subTotal());
$this->assertEquals(0, $this->cart->total());
}
/**
* @throws \Bnet\Cart\Exceptions\InvalidConditionException
* @throws \Bnet\Cart\Exceptions\InvalidItemException
*/
public function test_coupon_removal() {
$this->cart->add([
'id' => 456,
'name' => 'Sample Item 1',
'price' => 2500,
'quantity' => 3,
]);
$coupon1 = new Condition([
'name' => 'Coupon 1',
'type' => 'coupon',
'target' => Condition::TARGET_PRICE,
'value' => '-5000',
]);
$coupon2 = new Condition([
'name' => 'Coupon 2',
'type' => 'coupon',
'target' => Condition::TARGET_PRICE,
'value' => '-3000',
]);
$this->cart->condition([$coupon1, $coupon2]);
$this->assertEquals(7500, $this->cart->subTotal());
$this->assertEquals(0, $this->cart->total());
/* remove an item from the cart */
$this->cart->update(456, ['quantity' => -1]);
$this->assertEquals(5000, $this->cart->subTotal());
$this->assertEquals(0, $this->cart->total());
/* remove a coupon */
$this->cart->removeCartCondition('Coupon 1');
$this->assertEquals(5000, $this->cart->subTotal());
$this->assertEquals(2000, $this->cart->total());
}
/**
* @throws \Bnet\Cart\Exceptions\InvalidConditionException
* @throws \Bnet\Cart\Exceptions\InvalidItemException
*/
public function test_coupon_and_other_cart_condition() {
$this->cart->add([
'id' => 456,
'name' => 'Sample Item 1',
'price' => 2500,
'quantity' => 3,
]);
$coupon1 = new Condition([
'name' => 'Coupon 1',
'type' => 'coupon',
'target' => Condition::TARGET_PRICE,
'value' => '-5000',
]);
$cartCondition1 = new Condition([
'name' => 'SALE 5%',
'type' => 'sale',
'target' => Condition::TARGET_CART,
'value' => '-5%',
'attributes' => [
'description' => 'october fest promo sale',
'sale_start_date' => '2015-01-20',
'sale_end_date' => '2015-01-30',
]
]);
$this->cart->condition([$coupon1, $cartCondition1]);
$this->assertEquals(7500, $this->cart->subTotal());
$this->assertEquals(2125, $this->cart->total());
}
}
......@@ -554,7 +554,7 @@ class CurrencyCartConditionTest extends PHPUnit_Framework_TestCase {
$this->assertEquals(2, count($this->cart->get(456)['conditions']), 'Item should have two conditions');
// now let's remove a condition on that item using the condition name
$this->cart->removeItemCondition(456, 'SALE 5%');
$this->assertTrue($this->cart->removeItemCondition(456, 'SALE 5%'));
// now we should have only 1 condition left on that item
$this->assertEquals(1, count($this->cart->get(456)['conditions']), 'Item should have one condition left');
......@@ -585,7 +585,7 @@ class CurrencyCartConditionTest extends PHPUnit_Framework_TestCase {
$this->assertNotEmpty($this->cart->get(456)['conditions'], 'Item should have one condition in it.');
// now let's remove a condition on that item using the condition name
$this->cart->removeItemCondition(456, 'SALE 5%');
$this->assertTrue($this->cart->removeItemCondition(456, 'SALE 5%'));
// now we should have only 1 condition left on that item
$this->assertEmpty($this->cart->get(456)['conditions'], 'Item should have no condition now');
......
......@@ -28,7 +28,7 @@ class SessionMock implements SessionInterface{
}
public function put($key, $value) {
$this->session[$key] = $value;
$this->set($key, $value);
}
/**
......@@ -129,7 +129,7 @@ class SessionMock implements SessionInterface{
* @param mixed $value
*/
public function set($name, $value) {
// TODO: Implement set() method.
$this->session[$name] = $value;
}
/**
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment