Commit 5cf9cc5b authored by Thomas Bilk's avatar Thomas Bilk

added `taxonly` function to cart and cart item

parent 8403909c
......@@ -13,7 +13,8 @@
"php": ">=5.4.0",
"illuminate/support": "5.0.x|5.1.x|5.2.x|5.3.x",
"illuminate/validation": "5.0.x|5.1.x|5.2.x|5.3.x",
"bnet/money-datatype": "^0.1.3"
"illuminate/translation": "5.3.*",
"bnet/money-datatype": "^0.1"
},
"require-dev": {
"mockery/mockery": "~0.9",
......
......@@ -182,7 +182,7 @@ class Condition extends Collection {
* @param $value
* @return bool
*/
protected function valueIsPercentage($value) {
public function valueIsPercentage($value) {
return (preg_match('/%/', $value) == 1);
}
......@@ -192,7 +192,7 @@ class Condition extends Collection {
* @param $value
* @return bool
*/
protected function valueIsToBeSubtracted($value) {
public function valueIsToBeSubtracted($value) {
return (preg_match('/\-/', $value) == 1);
}
......@@ -202,7 +202,7 @@ class Condition extends Collection {
* @param $value
* @return bool
*/
protected function valueIsToBeAdded($value) {
public function valueIsToBeAdded($value) {
return (preg_match('/\+/', $value) == 1);
}
......
......@@ -68,6 +68,12 @@ class CurrencyCart extends Cart {
return new Money((int)($subTotal + $condTotal), $this->currency);
}
public function totalTaxAmount() {
return $this->items()->sum(function(CurrencyItem $item) {
return $item->taxAmountWithConditions();
});
}
/**
* get the cart
*
......
......@@ -10,6 +10,7 @@ namespace Bnet\Cart;
use Bnet\Money\Currency;
use Bnet\Money\Money;
use Bnet\Money\TaxedMoney;
/**
* Class CurrencyItem
......@@ -81,5 +82,55 @@ class CurrencyItem extends Item {
$newPrice = $this->returnPriceAboveZero($condition_price + ($this->quantity * $originalPrice));
return new Money((int)$newPrice, $this->currency);
}
/**
* @return int
*/
public function taxAmountWithConditions() {
$tax = 0;
$item_price = $this->price->amount();
/* get the tax for the item */
if ($this->price->hasTax()) {
$taxed_price = $this->price;
$tax = $taxed_price->taxAmountOnly();
$item_price = $taxed_price->amountWithoutTax();
}
/* summarize all taxes of item conditions that need to be applied as
* percent onto the item price */
$percent_condition_tax_amount = $this->conditions
->filter(function (CurrencyCondition $cond) {
return $cond->valueIsPercentage($cond->getValue());
})
->sum(function (CurrencyCondition $cond) use ($item_price) {
if ($this->price->hasTax()) {
$cond_price = (int)$cond->applyConditionWithQuantity($item_price, $this->quantity);
return (new TaxedMoney($cond_price, $this->currency, $this->price->tax))->taxAmountOnly();
}
return 0;
});
/* summarize all taxes of item conditions that have absolute values */
$absolute_condition_tax_amount = $this->conditions
->filter(function (CurrencyCondition $cond) {
return $cond->getValue() instanceof TaxedMoney;
})
->sum(function (CurrencyCondition $cond) use ($item_price) {
if ($cond->getValue() instanceof TaxedMoney) {
/* @var TaxedMoney $value */
$value = $cond->getValue();
$cond_price = $value->amountWithoutTax() * ($cond->getQuantityIndependent() ? 1 : $this->quantity);
return (new TaxedMoney($cond_price, $value->currency(), $value->tax))->taxAmountOnly();
}
return 0;
});
/* add everything up */
return $this->returnPriceAboveZero(
$this->quantity * $tax
+ $percent_condition_tax_amount
+ $absolute_condition_tax_amount);
}
}
\ No newline at end of file
<?php namespace Bnet\Cart\Validators;
use Symfony\Component\Translation\Translator;
use Illuminate\Filesystem\Filesystem;
use Illuminate\Translation\FileLoader;
use Illuminate\Translation\Translator;
use Illuminate\Validation\Factory;
/**
......@@ -15,8 +17,9 @@ abstract class Validator {
public static function instance() {
if (!static::$factory) {
$loader = new FileLoader(new Filesystem(),'/tmp');
$locale = class_exists('\Config') ? \Config::get('app.locale') : 'en';
$translator = new Translator($locale);
$translator = new Translator($loader, $locale);
static::$factory = new Factory($translator);
}
......
......@@ -479,4 +479,38 @@ class CurrencyCartTest extends PHPUnit_Framework_TestCase {
$this->assertInternalType("int", $this->cart->totalQuantity(), 'Return type should be INT');
$this->assertEquals(4, $this->cart->totalQuantity(), 'Cart\'s quantity should be 4.');
}
}
\ No newline at end of file
public function test_cart_tax_only() {
$items = [
[
'id' => 123,
'name' => 'Item A',
'price' => \Bnet\Money\TaxedMoney::fromNet(2500, 20),
'quantity' => 2
],
[
'id' => 456,
'name' => 'Item B',
'price' => \Bnet\Money\TaxedMoney::fromNet(3500, 20),
'quantity' => 1
],
[
'id' => 789,
'name' => 'Item C',
'price' => new Money(4500),
'quantity' => 1,
'conditions' => [
new \Bnet\Cart\CurrencyCondition([
'name' => 'Absolute Tax Plus',
'type' => 'misc2',
'target' => 'item',
'value' => new \Bnet\Money\TaxedMoney(500, 'EUR', 20),
])
]
]
];
$this->cart->add($items);
$this->assertEquals(1800, $this->cart->totalTaxAmount());
}
}
......@@ -33,4 +33,176 @@ class CurrencyItemTest extends PHPUnit_Framework_TestCase {
// undefined param
$this->assertEquals('x0', $item->blub);
}
public function testTaxOnlyOnItem() {
$money_with_tax = \Bnet\Money\MoneyGross::fromNet(1000, 20);
$money_no_tax = new \Bnet\Money\Money(1000);
$single_item_with_tax = new \Bnet\Cart\CurrencyItem([
'id' => 999,
'name' => 'Item x',
'price' => $money_with_tax,
'quantity' => 1,
], 'EUR');
$multi_item_with_tax = new \Bnet\Cart\CurrencyItem([
'id' => 999,
'name' => 'Item x',
'price' => $money_with_tax,
'quantity' => 3,
], 'EUR');
$single_item_no_tax = new \Bnet\Cart\CurrencyItem([
'id' => 999,
'name' => 'Item x',
'price' => $money_no_tax,
'quantity' => 1,
], 'EUR');
$this->assertEquals(200, $single_item_with_tax->taxAmountWithConditions());
$this->assertEquals(3*200, $multi_item_with_tax->taxAmountWithConditions());
$this->assertEquals(0, $single_item_no_tax->taxAmountWithConditions());
}
public function testTaxOnlyOnItemAttribute() {
$money_with_tax = \Bnet\Money\MoneyGross::fromNet(1000, 20);
$money_no_tax = new \Bnet\Money\Money(1000);
$condition_percent_plus = new \Bnet\Cart\CurrencyCondition([
'name' => 'Percent Plus',
'type' => 'misc2',
'target' => 'item',
'value' => '+10%',
]);
$condition_percent_minus = new \Bnet\Cart\CurrencyCondition([
'name' => 'Percent Minus',
'type' => 'misc2',
'target' => 'item',
'value' => '-10%',
]);
$condition_with_tax_plus = new \Bnet\Cart\CurrencyCondition([
'name' => 'Absolute Tax Plus',
'type' => 'misc2',
'target' => 'item',
'value' => new \Bnet\Money\TaxedMoney(500, 'EUR', 20),
]);
$condition_with_tax_minus = new \Bnet\Cart\CurrencyCondition([
'name' => 'Absolute Tax Minus',
'type' => 'misc2',
'target' => 'item',
'value' => new \Bnet\Money\TaxedMoney(-500, 'EUR', 20),
]);
$condition_no_tax_plus = new \Bnet\Cart\CurrencyCondition([
'name' => 'Absolute Plus',
'type' => 'misc2',
'target' => 'item',
'value' => new \Bnet\Money\Money(500, 'EUR'),
]);
$condition_no_tax_minus = new \Bnet\Cart\CurrencyCondition([
'name' => 'Absolute Minus',
'type' => 'misc2',
'target' => 'item',
'value' => new \Bnet\Money\Money(-500, 'EUR'),
]);
/* here come the tests */
$single_item_with_tax_percent_plus = new \Bnet\Cart\CurrencyItem([
'id' => 999,
'name' => 'Item x',
'price' => $money_with_tax,
'quantity' => 1,
'conditions' => [$condition_percent_plus],
], 'EUR');
$this->assertEquals(220, $single_item_with_tax_percent_plus->taxAmountWithConditions());
$single_item_with_tax_percent_minus = new \Bnet\Cart\CurrencyItem([
'id' => 999,
'name' => 'Item x',
'price' => $money_with_tax,
'quantity' => 1,
'conditions' => [$condition_percent_minus],
], 'EUR');
$this->assertEquals(180, $single_item_with_tax_percent_minus->taxAmountWithConditions());
$single_item_no_tax_percent_plus = new \Bnet\Cart\CurrencyItem([
'id' => 999,
'name' => 'Item x',
'price' => $money_no_tax,
'quantity' => 1,
'conditions' => [$condition_percent_plus],
], 'EUR');
$this->assertEquals(0, $single_item_no_tax_percent_plus->taxAmountWithConditions());
$single_item_with_tax_plus_tax = new \Bnet\Cart\CurrencyItem([
'id' => 999,
'name' => 'Item x',
'price' => $money_with_tax,
'quantity' => 1,
'conditions' => [$condition_with_tax_plus],
], 'EUR');
$this->assertEquals(300, $single_item_with_tax_plus_tax->taxAmountWithConditions());
$single_item_with_tax_minus_tax = new \Bnet\Cart\CurrencyItem([
'id' => 999,
'name' => 'Item x',
'price' => $money_with_tax,
'quantity' => 1,
'conditions' => [$condition_with_tax_minus],
], 'EUR');
$this->assertEquals(100, $single_item_with_tax_minus_tax->taxAmountWithConditions());
$single_item_with_tax_plus_no_tax = new \Bnet\Cart\CurrencyItem([
'id' => 999,
'name' => 'Item x',
'price' => $money_with_tax,
'quantity' => 1,
'conditions' => [$condition_no_tax_plus],
], 'EUR');
$this->assertEquals(200, $single_item_with_tax_plus_no_tax->taxAmountWithConditions());
$single_item_with_tax_minus_no_tax = new \Bnet\Cart\CurrencyItem([
'id' => 999,
'name' => 'Item x',
'price' => $money_with_tax,
'quantity' => 1,
'conditions' => [$condition_no_tax_minus],
], 'EUR');
$this->assertEquals(200, $single_item_with_tax_minus_no_tax->taxAmountWithConditions());
$single_item_no_tax_plus_tax = new \Bnet\Cart\CurrencyItem([
'id' => 999,
'name' => 'Item x',
'price' => $money_no_tax,
'quantity' => 1,
'conditions' => [$condition_with_tax_plus],
], 'EUR');
$this->assertEquals(100, $single_item_no_tax_plus_tax->taxAmountWithConditions());
$single_item_no_tax_minus_tax = new \Bnet\Cart\CurrencyItem([
'id' => 999,
'name' => 'Item x',
'price' => $money_no_tax,
'quantity' => 1,
'conditions' => [$condition_with_tax_minus],
], 'EUR');
$this->assertEquals(0, $single_item_no_tax_minus_tax->taxAmountWithConditions());
$single_item_no_tax_plus_no_tax = new \Bnet\Cart\CurrencyItem([
'id' => 999,
'name' => 'Item x',
'price' => $money_no_tax,
'quantity' => 1,
'conditions' => [$condition_no_tax_plus],
], 'EUR');
$this->assertEquals(0, $single_item_no_tax_plus_no_tax->taxAmountWithConditions());
$single_item_no_tax_minus_no_tax = new \Bnet\Cart\CurrencyItem([
'id' => 999,
'name' => 'Item x',
'price' => $money_no_tax,
'quantity' => 1,
'conditions' => [$condition_no_tax_minus],
], 'EUR');
$this->assertEquals(0, $single_item_no_tax_minus_no_tax->taxAmountWithConditions());
}
}
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