Commit fe2d6778 authored by Thorsten Buss's avatar Thorsten Buss

change CurrencyCondition to work with MoneyObj and Currency with optional tax

parent fd94eafa
......@@ -247,7 +247,7 @@ class Cart implements Jsonable, \JsonSerializable, Arrayable{
*
* @param int|string $productId
* @param Condition $itemCondition
* @return $this
* @return Cart
*/
public function addItemCondition($productId, Condition $itemCondition) {
if ($product = $this->get($productId)) {
......@@ -532,18 +532,24 @@ class Cart implements Jsonable, \JsonSerializable, Arrayable{
* @return int
*/
public function totalOnlyConditions($type = null) {
$subTotal = $this->totalItemsOnlyConditions($type);
if ($this->getConditions($type)->isEmpty())
return $subTotal;
$subTotal = $this->subTotal();
$condTotal = $this->getConditions($type)->sum(function ($cond) use ($subTotal) {
$cond = $type
? $this->getConditionsByType($type)
: $this->getConditions()
;
$itemConditionTotal = $this->totalItemsOnlyConditions($type);
if ($cond->isEmpty())
return $itemConditionTotal;
$condTotal = $cond->sum(function ($cond) use ($subTotal) {
/** @var Condition $cond */
return $cond->getTarget() === 'cart'
? $cond->applyCondition($subTotal)
: 0;
});
return $subTotal + $condTotal;
return $itemConditionTotal + $condTotal;
}
/**
......
......@@ -64,9 +64,12 @@ class CurrencyCart extends Cart {
$condTotal = $this->getConditions($only_with_condition_type)->sum(function ($cond) use ($subTotal) {
/** @var Condition $cond */
return $cond->getTarget() === 'cart'
$price =$cond->getTarget() === 'cart'
? $cond->applyCondition($subTotal)
: 0;
return $price instanceof Money
? $price->amount()
: $price;
});
return new Money((int)($subTotal + $condTotal), $this->currency);
......@@ -93,20 +96,26 @@ class CurrencyCart extends Cart {
* @return Money
*/
public function totalOnlyConditions($type = null) {
$subTotal = $this->totalItemsOnlyConditions($type);
if ($this->getConditions($type)->isEmpty())
return $subTotal;
$subTotal = $this->subTotal();
$subTotal = $subTotal->amount();
$cond = $type
? $this->getConditionsByType($type)
: $this->getConditions();
$itemConditionTotal = $this->totalItemsOnlyConditions($type);
if ($cond->isEmpty())
return $itemConditionTotal;
$condTotal = $this->getConditions($type)->sum(function ($cond) use ($subTotal) {
$condTotal = $cond->sum(function ($cond) use ($subTotal) {
/** @var Condition $cond */
return $cond->getTarget() === 'cart'
? $cond->applyCondition($subTotal)
$price = $cond->getTarget() === 'cart'
? $cond->applyCondition($subTotal->amount())
: 0;
return $price instanceof Money
? $price->amount()
: $price;
});
return new Money((int)($subTotal + $condTotal), $this->currency);
return new Money((int)($itemConditionTotal->value() + $condTotal), $this->currency);
}
/**
......@@ -206,5 +215,18 @@ class CurrencyCart extends Cart {
return $item;
}
/**
* add condition on an existing item on the cart
*
* @param int|string $productId
* @param Condition $itemCondition
* @return CurrencyCart
*/
public function addItemCondition($productId, Condition $itemCondition) {
// add the cart currency to the condition
if ($itemCondition instanceof CurrencyCondition)
$itemCondition->setCurrency($this->currency);
return parent::addItemCondition($productId, $itemCondition);
}
}
\ No newline at end of file
......@@ -8,16 +8,31 @@
namespace Bnet\Cart;
use Bnet\Cart\Helpers\Helpers;
use Bnet\Money\Currency;
use Bnet\Money\Money;
use Bnet\Money\TaxedMoney;
class CurrencyCondition extends Condition {
/**
* @var Currency
*/
protected $currency;
/**
* @var int tax percentage
*/
protected $tax;
/**
* CurrencyCondition constructor.
* @param array $args
*/
public function __construct(array $args) {
if (isset($args['tax'])) {
$this->tax = $args['tax'];
unset($args['tax']);
}
// remove the "string" validator from the value field
$this->rules['value'] = 'required';
parent::__construct($args);
......@@ -32,9 +47,7 @@ class CurrencyCondition extends Condition {
*/
protected function apply($totalOrSubTotalOrPrice, $conditionValue) {
if ($conditionValue instanceof Money) {
$this->parsedRawValue = $conditionValue->amount();
return Helpers::intval($this->parsedRawValue);
$conditionValue = $conditionValue->amount();
}
return parent::apply($totalOrSubTotalOrPrice, $conditionValue);
}
......@@ -52,4 +65,57 @@ class CurrencyCondition extends Condition {
: $this->apply($totalOrSubTotalOrPrice, $conditionValue) * $quantity;
}
/**
* apply condition to total or subtotal
*
* @param $totalOrSubTotalOrPrice
* @return Money
*/
public function applyCondition($totalOrSubTotalOrPrice) {
$price = (int)parent::applyCondition($totalOrSubTotalOrPrice);
return $this->tax
? new TaxedMoney($price, $this->currency, $this->tax)
: new Money($price, $this->currency);
}
/**
* apply condition to total or subtotal
*
* @param $totalOrSubTotalOrPrice
* @param int $quantity
* @return Money
*/
public function applyConditionWithQuantity($totalOrSubTotalOrPrice, $quantity) {
$price = (int)parent::applyConditionWithQuantity($totalOrSubTotalOrPrice, $quantity);
return $this->tax
? new TaxedMoney($price, $this->currency, $this->tax)
: new Money($price, $this->currency);
}
/**
* get the calculated value of this condition supplied by the subtotal|price
*
* @param $totalOrSubTotalOrPrice
* @return mixed
*/
public function getCalculatedValue($totalOrSubTotalOrPrice) {
$price = (int)parent::getCalculatedValue($totalOrSubTotalOrPrice);
return $this->tax
? new TaxedMoney($price, $this->currency, $this->tax)
: new Money($price, $this->currency);
}
/**
* @param Currency $currency
*/
public function setCurrency(Currency $currency) {
$this->currency = $currency;
}
/**
* @param int $tax tax percentage
*/
public function setTax($tax) {
$this->tax = $tax;
}
}
\ No newline at end of file
......@@ -65,10 +65,13 @@ class CurrencyItem extends Item {
$condition_price = $this->conditions->sum(function ($condition) use ($originalPrice, $type) {
/** @var Condition $condition */
return ($condition && $condition->getTarget() === 'item'
$price = ($condition && $condition->getTarget() === 'item'
&& (is_null($type) || $type == $condition->getType()))
? $condition->applyCondition($originalPrice)
: 0;
return $price instanceof Money
? $price->amount()
: $price;
});
$newPrice = $this->returnPriceAboveZero($condition_price + $originalPrice);
return new Money((int)$newPrice, $this->currency);
......@@ -85,10 +88,13 @@ class CurrencyItem extends Item {
$condition_price = $this->conditions->sum(function ($condition) use ($originalPrice, $type) {
/** @var Condition $condition */
return ($condition && $condition->getTarget() === 'item'
$price = ($condition && $condition->getTarget() === 'item'
&& (is_null($type) || $type == $condition->getType()))
? $condition->applyConditionWithQuantity($originalPrice, $this->quantity)
: 0;
return $price instanceof Money
? $price->amount()
: $price;
});
$newPrice = $this->returnPriceAboveZero($condition_price + ($this->quantity * $originalPrice));
return new Money((int)$newPrice, $this->currency);
......@@ -136,7 +142,7 @@ class CurrencyItem extends Item {
})
->sum(function (CurrencyCondition $cond) use ($item_price) {
if ($this->price->hasTax()) {
$cond_price = (int)$cond->applyConditionWithQuantity($item_price, $this->quantity);
$cond_price = (int)$cond->applyConditionWithQuantity($item_price, $this->quantity)->amount();
return (new TaxedMoney($cond_price, $this->currency, $this->price->tax))->taxAmountOnly();
}
return 0;
......
......@@ -97,6 +97,8 @@ class CurrencyCartConditionTest extends PHPUnit_Framework_TestCase {
// total should be changed
$this->assertEquals(21093, $this->cart->total()->amount(), 'Cart should have a total of 21093');
$this->assertEquals(2344, $this->cart->totalOnlyConditions()->amount());
}
public function test_total_with_multiple_conditions_added_scenario_one() {
......@@ -933,25 +935,25 @@ class CurrencyCartConditionTest extends PHPUnit_Framework_TestCase {
$this->cart->add($item);
# Fix quantity independent
$this->assertEquals(500, $itemCondition->applyCondition(0), 'condition');
$this->assertEquals(500, $itemCondition->applyConditionWithQuantity(0, 3), 'Quantitycondition');
$this->assertEquals(500, $itemCondition->applyConditionWithQuantity(1000, 3), 'Quantitycondition +itemAmount');
$this->assertEquals(500, $itemCondition->applyCondition(0)->amount(), 'condition');
$this->assertEquals(500, $itemCondition->applyConditionWithQuantity(0, 3)->amount(), 'Quantitycondition');
$this->assertEquals(500, $itemCondition->applyConditionWithQuantity(1000, 3)->amount(), 'Quantitycondition +itemAmount');
# % quantity independent
$this->assertEquals(0, $itemCondition1->applyCondition(0), 'condition');
$this->assertEquals(10, $itemCondition1->applyCondition(100), 'condition');
$this->assertEquals(10, $itemCondition1->applyConditionWithQuantity(100, 3), 'Quantitycondition +itemAmount');
$this->assertEquals(0, $itemCondition1->applyCondition(0)->amount(), 'condition');
$this->assertEquals(10, $itemCondition1->applyCondition(100)->amount(), 'condition');
$this->assertEquals(10, $itemCondition1->applyConditionWithQuantity(100, 3)->amount(), 'Quantitycondition +itemAmount');
# % with quantity
$this->assertEquals(0, $itemCondition2->applyCondition(0), 'condition');
$this->assertEquals(10, $itemCondition2->applyCondition(100), 'condition');
$this->assertEquals(300, $itemCondition2->applyConditionWithQuantity(1000, 3), 'Quantitycondition +itemAmount');
$this->assertEquals(0, $itemCondition2->applyCondition(0)->amount(), 'condition');
$this->assertEquals(10, $itemCondition2->applyCondition(100)->amount(), 'condition');
$this->assertEquals(300, $itemCondition2->applyConditionWithQuantity(1000, 3)->amount(), 'Quantitycondition +itemAmount');
# Fixed with quantity
$this->assertEquals(250, $itemCondition3->applyCondition(0), 'condition');
$this->assertEquals(750, $itemCondition3->applyConditionWithQuantity(0, 3), 'Quantitycondition');
$this->assertEquals(750, $itemCondition3->applyConditionWithQuantity(1000, 3), 'Quantitycondition +itemAmount');
$this->assertEquals(250, $itemCondition3->applyCondition(0)->amount(), 'condition');
$this->assertEquals(750, $itemCondition3->applyConditionWithQuantity(0, 3)->amount(), 'Quantitycondition');
$this->assertEquals(750, $itemCondition3->applyConditionWithQuantity(1000, 3)->amount(), 'Quantitycondition +itemAmount');
$this->assertEquals(35250, $this->cart->total()->amount(), 'match total');
}
......@@ -965,7 +967,8 @@ class CurrencyCartConditionTest extends PHPUnit_Framework_TestCase {
'value' => new Money(500)
));
$itemCondition1 = new CurrencyCondition(array(
'name' => 'Test1',
'name' => 'Test1 With Tax',
'tax' => 19,
'type' => 'sale',
'target' => 'item',
'quantity_independent' => true,
......@@ -986,14 +989,14 @@ class CurrencyCartConditionTest extends PHPUnit_Framework_TestCase {
$this->cart->add($item);
$this->assertEquals(500, $itemCondition->applyCondition(0), 'condition');
$this->assertEquals(500, $itemCondition->applyConditionWithQuantity(0, 3), 'Quantitycondition');
$this->assertEquals(500, $itemCondition->applyConditionWithQuantity(1000, 3), 'Quantitycondition +itemAmount');
$this->assertEquals(500, $itemCondition->applyCondition(0)->amount(), 'condition');
$this->assertEquals(500, $itemCondition->applyConditionWithQuantity(0, 3)->amount(), 'Quantitycondition');
$this->assertEquals(500, $itemCondition->applyConditionWithQuantity(1000, 3)->amount(), 'Quantitycondition +itemAmount');
$this->assertEquals(500, $itemCondition1->applyCondition(0), 'condition');
$this->assertEquals(500, $itemCondition1->applyConditionWithQuantity(0, 3), 'Quantitycondition');
$this->assertEquals(500, $itemCondition1->applyConditionWithQuantity(1000, 3), 'Quantitycondition +itemAmount');
$this->assertEquals(595, $itemCondition1->applyCondition(0)->amount(), 'condition');
$this->assertEquals(595, $itemCondition1->applyConditionWithQuantity(0, 3)->amount(), 'Quantitycondition');
$this->assertEquals(595, $itemCondition1->applyConditionWithQuantity(1000, 3)->amount(), 'Quantitycondition +itemAmount');
$this->assertEquals(31000, $this->cart->total()->amount(), 'match total');
$this->assertEquals(31095, $this->cart->total()->amount(), 'match total');
}
}
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