fix tax handling, add functional cest for cart

This commit is contained in:
Steffen Mahler 2020-02-04 08:50:37 +01:00
parent 8abce3302a
commit cb5e3a47f6
17 changed files with 217 additions and 21 deletions

View File

@ -344,12 +344,12 @@
</tr>
@endif
@php ($taxRates = Webkul\Checkout\Helpers\Tax::getTaxRatesWithAmount($order, true))
@php ($taxRates = Webkul\Tax\Helpers\Tax::getTaxRatesWithAmount($order, true))
@foreach ($taxRates as $taxRate => $baseTaxAmount)
<tr {{ $loop->last ? 'class=border' : ''}}>
<td id="taxrate-{{ $taxRate }}">{{ __('admin::app.sales.orders.tax') }} {{ $taxRate }} %</td>
<td>-</td>
<td id="taxamount-{{ $taxRate }}">{{ core()->formatBasePrice($baseTaxAmount) }}</td>
<td id="basetaxamount-{{ $taxRate }}">{{ core()->formatBasePrice($baseTaxAmount) }}</td>
</tr>
@endforeach

View File

@ -7,6 +7,7 @@ use Webkul\Checkout\Repositories\CartItemRepository;
use Webkul\Checkout\Repositories\CartAddressRepository;
use Webkul\Customer\Models\CustomerAddress;
use Webkul\Product\Repositories\ProductRepository;
use Webkul\Tax\Helpers\Tax;
use Webkul\Tax\Repositories\TaxCategoryRepository;
use Webkul\Checkout\Models\CartItem;
use Webkul\Checkout\Models\CartPayment;
@ -675,16 +676,16 @@ class Cart
$cart->discount_amount += $item->discount_amount;
$cart->base_discount_amount += $item->base_discount_amount;
$cart->grand_total = (float)$cart->grand_total + $item->total + $item->tax_amount - $item->discount_amount;
$cart->base_grand_total = (float)$cart->base_grand_total + $item->base_total + $item->base_tax_amount - $item->base_discount_amount;
$cart->sub_total = (float)$cart->sub_total + $item->total;
$cart->base_sub_total = (float)$cart->base_sub_total + $item->base_total;
$cart->tax_total = (float)$cart->tax_total + $item->tax_amount;
$cart->base_tax_total = (float)$cart->base_tax_total + $item->base_tax_amount;
}
$cart->tax_total = Tax::getTaxTotal($cart, false);
$cart->base_tax_total = Tax::getTaxTotal($cart, true);
$cart->grand_total = $cart->sub_total + $cart->tax_total + $cart->discount_amount;
$cart->base_grand_total = $cart->base_sub_total + $cart->base_tax_total - $cart->base_discount_amount;
if ($shipping = $cart->selected_shipping_rate) {
$cart->grand_total = (float)$cart->grand_total + $shipping->price - $shipping->discount_amount;
$cart->base_grand_total = (float)$cart->base_grand_total + $shipping->base_price - $shipping->base_discount_amount;

View File

@ -68,7 +68,7 @@ class Laravel5Helper extends Laravel5
): Product {
$I = $this;
/** @var Product $product */
$product = factory(Product::class)->states($productStates)->create($configs['productAttributes'] ?? []);;
$product = factory(Product::class)->states($productStates)->create($configs['productAttributes'] ?? []);
$I->createAttributeValues($product->id,$configs['attributeValues'] ?? []);
$I->have(ProductInventory::class, array_merge($configs['productInventory'] ?? [], [
'product_id' => $product->id,

View File

@ -42,7 +42,7 @@ $factory->defineAs(ProductAttributeValue::class, 'tax_category_id', function (Fa
return factory(Product::class)->create()->id;
},
'channel' => 'default',
'integer_value' => null, // ToDo
'integer_value' => null,
'attribute_id' => 4,
];
});

View File

@ -18,10 +18,10 @@
@endif
@if ($cart->base_tax_total)
@foreach (Webkul\Checkout\Helpers\Tax::getTaxRatesWithAmount($cart, false) as $taxRate => $taxAmount )
@foreach (Webkul\Tax\Helpers\Tax::getTaxRatesWithAmount($cart, true) as $taxRate => $baseTaxAmount )
<div class="item-detail">
<label id="taxrate-{{ $taxRate }}">{{ __('shop::app.checkout.total.tax') }} {{ $taxRate }} %</label>
<label class="right" id="taxamount-{{ $taxRate }}">{{ core()->currency($taxAmount) }}</label>
<label class="right" id="basetaxamount-{{ $taxRate }}">{{ core()->currency($baseTaxAmount) }}</label>
</div>
@endforeach
@endif

View File

@ -161,7 +161,7 @@
</span>
</div>
@foreach (Webkul\Checkout\Helpers\Tax::getTaxRatesWithAmount($order, true) as $taxRate => $baseTaxAmount )
@foreach (Webkul\Tax\Helpers\Tax::getTaxRatesWithAmount($order, true) as $taxRate => $baseTaxAmount )
<div>
<span id="taxrate-{{ $taxRate }}">{{ __('shop::app.mail.order.tax') }} {{ $taxRate }} %</span>
<span id="basetaxamount-{{ $taxRate }}" style="float: right;">

View File

@ -156,7 +156,7 @@
</div>
@endif
@foreach ($order->getTaxRatesWithAmount(false) as $taxRate => $taxAmount)
@foreach (Webkul\Tax\Helpers\Tax::getTaxRatesWithAmount($refund, false) as $taxRate => $taxAmount)
<div>
<span id="taxrate-{{ $taxRate }}">{{ __('shop::app.mail.order.tax') }} {{ $taxRate }} %</span>
<span id="taxamount-{{ $taxRate }}" style="float: right;">

View File

@ -156,7 +156,7 @@
</div>
@endif
@foreach (Webkul\Checkout\Helpers\Tax::getTaxRatesWithAmount($order, false) as $taxRate => $taxAmount )
@foreach (Webkul\Tax\Helpers\Tax::getTaxRatesWithAmount($order, false) as $taxRate => $taxAmount )
<div>
<span id="taxrate-{{ $taxRate }}">{{ __('shop::app.mail.order.tax') }} {{ $taxRate }} %</span>
<span id="taxamount-{{ $taxRate }}" style="float: right;">

View File

@ -158,14 +158,16 @@
</span>
</div>
@endif
@php(//ToDo: taxes)
@if ($refund->tax_amount > 0)
@foreach (Webkul\Tax\Helpers\Tax::getTaxRatesWithAmount($refund, false) as $taxRate => $taxAmount)
<div>
<span>{{ __('shop::app.mail.order.tax') }}</span>
<span style="float: right;">
{{ core()->formatPrice($refund->tax_amount, $refund->order_currency_code) }}
</span>
</div>
@endforeach
@endif
@if ($refund->discount_amount > 0)

View File

@ -157,7 +157,7 @@
</span>
</div>
@foreach (Webkul\Checkout\Helpers\Tax::getTaxRatesWithAmount($order, false) as $taxRate => $taxAmount )
@foreach (Webkul\Tax\Helpers\Tax::getTaxRatesWithAmount($order, false) as $taxRate => $taxAmount )
<div>
<span id="taxrate-{{ $taxRate }}">{{ __('shop::app.mail.order.cancel.tax') }} {{ $taxRate }} %</span>
<span id="taxamount-{{ $taxRate }}" style="float: right;">

View File

@ -0,0 +1,17 @@
<?php
/** @var \Illuminate\Database\Eloquent\Factory $factory */
use Faker\Generator as Faker;
use Webkul\Tax\Models\TaxCategory;
$factory->define(TaxCategory::class, function (Faker $faker) {
return [
'channel_id' => function () {
return core()->getCurrentChannel()->id;
},
'code' => $faker->uuid,
'name' => $faker->words(2, true),
'description' => $faker->sentence(10),
];
});

View File

@ -0,0 +1,19 @@
<?php
/** @var \Illuminate\Database\Eloquent\Factory $factory */
use Faker\Generator as Faker;
use Webkul\Tax\Models\TaxMap;
use Webkul\Tax\Models\TaxRate;
use Webkul\Tax\Models\TaxCategory;
$factory->define(TaxMap::class, function (Faker $faker) {
return [
'tax_category_id' => function () {
return factory(TaxCategory::class)->create()->id;
},
'tax_rate_id' => function () {
return factory(TaxRate::class)->create()->id;
},
];
});

View File

@ -0,0 +1,19 @@
<?php
/** @var \Illuminate\Database\Eloquent\Factory $factory */
use Faker\Generator as Faker;
use Webkul\Tax\Models\TaxRate;
$factory->define(TaxRate::class, function (Faker $faker) {
return [
'identifier' => $faker->uuid,
'is_zip' => 0,
'zip_code' => '*',
'zip_from' => null,
'zip_to' => null,
'state' => '',
'country' => $faker->countryCode,
'tax_rate' => $faker->randomFloat(2, 3, 25),
];
});

View File

@ -1,19 +1,19 @@
<?php
namespace Webkul\Checkout\Helpers;
namespace Webkul\Tax\Helpers;
class Tax
{
private const TAX_PRECISION = 4;
/**
* Returns an array with tax rates and tax amounts
* Returns an array with tax rates and tax amount
* @param object $that
* @param bool $asBase
*
* @return array
*/
public static function getTaxRatesWithAmount(object $that, bool $asBase): array
public static function getTaxRatesWithAmount(object $that, bool $asBase = false): array
{
$taxes = [];
foreach ($that->items as $item) {
@ -28,4 +28,15 @@ class Tax
return $taxes;
}
public static function getTaxTotal(object $that, bool $asBase = false): float
{
$taxes = self::getTaxRatesWithAmount($that, $asBase);
$result = 0;
foreach ($taxes as $taxRate => $taxAmount) {
$result += round($taxAmount, 2);
}
return $result;
}
}

View File

@ -2,6 +2,7 @@
namespace Webkul\Tax\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Database\Eloquent\Factory as EloquentFactory;
class TaxServiceProvider extends ServiceProvider
{
@ -22,5 +23,17 @@ class TaxServiceProvider extends ServiceProvider
*/
public function register()
{
$this->registerEloquentFactoriesFrom(__DIR__ . '/../Database/Factories');
}
/**
* Register factories.
*
* @param string $path
* @return void
*/
protected function registerEloquentFactoriesFrom($path): void
{
$this->app->make(EloquentFactory::class)->load($path);
}
}

View File

@ -0,0 +1,114 @@
<?php
namespace Tests\Functional\Cart;
use FunctionalTester;
use Faker\Factory;
use Webkul\Tax\Models\TaxMap;
use Webkul\Tax\Models\TaxRate;
use Webkul\Tax\Models\TaxCategory;
use Webkul\Checkout\Models\Cart as CartModel;
use Cart;
class CartCest
{
private $country;
private $faker;
private $product1, $product2;
private $tax1, $tax2;
function _before(FunctionalTester $I)
{
$this->faker = Factory::create();
$this->country = 'DE'; //$this->faker->countryCode;
$this->tax1 = $I->have(TaxRate::class, ['tax_rate' => 7.00, 'country' => $this->country]);
$taxCategorie1 = $I->have(TaxCategory::class, []);
$I->have(TaxMap::class, ['tax_rate_id' => $this->tax1->id, 'tax_category_id' => $taxCategorie1->id]);
$this->tax2 = $I->have(TaxRate::class, ['tax_rate' => 19.00, 'country' => $this->country]);
$taxCategorie2 = $I->have(TaxCategory::class, []);
$I->have(TaxMap::class, ['tax_rate_id' => $this->tax2->id, 'tax_category_id' => $taxCategorie2->id]);
$config1 = [
'productInventory' => ['qty' => 100],
'attributeValues' => [
'status' => true,
'new' => 1,
'tax_category_id' => $taxCategorie1->id,
],
];
$this->product1 = $I->haveProduct($config1, ['simple']);
$config2 = [
'productInventory' => ['qty' => 100],
'attributeValues' => [
'status' => true,
'new' => 1,
'tax_category_id' => $taxCategorie2->id,
],
];
$this->product2 = $I->haveProduct($config2, ['simple']);
}
public function checkCartWithMultipleTaxRates(FunctionalTester $I)
{
$I->setConfigData(['default_country' => $this->country]);
$prod1Quantity = $this->faker->numberBetween(9, 30);
if ($prod1Quantity % 2 !== 0) {
$prod1Quantity -= 1;
}
$prod2Quantity = $this->faker->numberBetween(9, 30);
if ($prod2Quantity % 2 == 0) {
$prod2Quantity -= 1;
}
Cart::addProduct($this->product1->id, [
'_token' => session('_token'),
'product_id' => $this->product1->id,
'quantity' => 1,
]);
$I->amOnPage('/checkout/cart');
$I->see('Tax ' . $this->tax1->tax_rate . ' %', '#taxrate-' . $this->tax1->tax_rate);
$I->see(round($this->product1->price * $this->tax1->tax_rate / 100, 2),
'#basetaxamount-' . $this->tax1->tax_rate);
Cart::addProduct($this->product1->id, [
'_token' => session('_token'),
'product_id' => $this->product1->id,
'quantity' => $prod1Quantity,
]);
$I->amOnPage('/checkout/cart');
$I->see('Tax ' . $this->tax1->tax_rate . ' %', '#taxrate-' . $this->tax1->tax_rate);
$I->see(round(($prod1Quantity + 1) * $this->product1->price * $this->tax1->tax_rate / 100, 2),
'#basetaxamount-' . $this->tax1->tax_rate);
Cart::addProduct($this->product2->id, [
'_token' => session('_token'),
'product_id' => $this->product2->id,
'quantity' => $prod2Quantity,
]);
$I->amOnPage('/checkout/cart');
$I->see('Tax ' . $this->tax1->tax_rate . ' %', '#taxrate-' . $this->tax1->tax_rate);
$taxAmount1 = round(($prod1Quantity + 1) * $this->product1->price * $this->tax1->tax_rate / 100, 2);
$I->see(core()->currency($taxAmount1),'#basetaxamount-' . $this->tax1->tax_rate);
$I->see('Tax ' . $this->tax2->tax_rate . ' %', '#taxrate-' . $this->tax2->tax_rate);
$taxAmount2 = round($prod2Quantity * $this->product2->price * $this->tax2->tax_rate / 100, 2);
$I->see(core()->currency($taxAmount2),'#basetaxamount-' . $this->tax2->tax_rate);
$cart = Cart::getCart();
$I->assertEquals(2, $cart->items_count);
$I->assertEquals((float)($prod1Quantity + 1 + $prod2Quantity), $cart->items_qty);
$I->assertEquals($taxAmount1 + $taxAmount2, $cart->tax_total);
}
}

View File

@ -1,6 +1,6 @@
<?php
namespace Tests\Webkul\Unit\Shop;
namespace Tests\Functional\Shop;
use Codeception\Example;
use FunctionalTester;