完善税费

This commit is contained in:
Edward Yang 2022-07-29 15:12:14 +08:00
parent c279cede8b
commit bf3a1bedfa
13 changed files with 177 additions and 42 deletions

View File

@ -45,4 +45,10 @@ class TaxRateRepo
$taxRate = TaxRate::query()->findOrFail($id);
$taxRate->delete();
}
public static function getNameByRateId($taxRateId)
{
$taxRate = TaxRate::query()->findOrFail($taxRateId);
return $taxRate->name;
}
}

View File

@ -9,23 +9,23 @@
* @modified 2022-07-21 16:29:54
*/
namespace Beike\Services;
namespace Beike\Libraries;
use Beike\Models\Address;
use Beike\Models\TaxRate;
use Beike\Models\TaxRule;
class TaxService
class Tax
{
private $taxRates = array();
private static $taxRules;
private array $taxRates = [];
private static array $taxRules = [];
const AVAILABLE_TYPES = ['shipping', 'payment', 'store'];
public function __construct($data = array())
{
$countryId = system_setting('base.config_country_id');
$zoneId = system_setting('base.config_zone_id');
$countryId = (int)system_setting('base.country_id');
$zoneId = (int)system_setting('base.zone_id');
$shippingAddress = $data['shipping_address'] ?? null;
$paymentAddress = $data['payment_address'] ?? null;
@ -68,21 +68,19 @@ class TaxService
return self::$taxRules["$type-$countryId-$zoneId"];
}
$customerGroupId = (int)system_setting('base.config_customer_group_id');
$sqlBuilder = TaxRule::query()
->leftJoin('tax_rate', 'tax_rule.tax_rate_id', '=', 'tax_rate.tax_rate_id')
->join('tax_rate_to_customer_group', 'tax_rate.tax_rate_id', '=', 'tax_rate_to_customer_group.tax_rate_id')
->leftJoin('zone_to_geo_zone', 'tax_rate.geo_zone_id', '=', 'zone_to_geo_zone.geo_zone_id')
->leftJoin('geo_zone', 'tax_rate.geo_zone_id', '=', 'geo_zone.geo_zone_id')
->select('tax_rule.*', 'tax_rate.*')
->where('tax_rule.based', $type)
->where('tax_rate_to_customer_group.customer_group_id', $customerGroupId)
->where('zone_to_geo_zone.country_id', $countryId)
->from('tax_rules as rule')
->select('rule.*', 'rate.*')
->leftJoin('tax_rates as rate', 'rule.tax_rate_id', '=', 'rate.id')
->leftJoin('region_zones as rz', 'rate.region_id', '=', 'rz.region_id')
->leftJoin('regions as region', 'rate.region_id', '=', 'region.id')
->where('rule.based', $type)
->where('rz.country_id', $countryId)
->where(function ($query) use ($zoneId) {
$query->where('zone_to_geo_zone.zone_id', '=', 0)
->orWhere('zone_to_geo_zone.zone_id', '=', (int)$zoneId);
$query->where('rz.zone_id', '=', 0)
->orWhere('rz.zone_id', '=', (int)$zoneId);
})
->orderBy('tax_rule.priority');
->orderBy('rule.priority');
$data = $sqlBuilder->get();
self::$taxRules["$type-$countryId-$zoneId"] = $data;
return $data;
@ -187,9 +185,9 @@ class TaxService
$amount = 0;
}
if ($taxRate['type'] == 'F') {
if ($taxRate['type'] == 'flat') {
$amount += $taxRate['rate'];
} elseif ($taxRate['type'] == 'P') {
} elseif ($taxRate['type'] == 'percent') {
$amount += ($value / 100 * $taxRate['rate']);
}

View File

@ -29,7 +29,16 @@ class SystemSettingRepo
['value' => '2', 'label' => '美国']
],
'value' => old('country_id', system_setting('base.country_id', '1')),
'description' => '默认语言设置',
'description' => '默认国家设置',
],
[
'name' => 'zone_id',
'label' => '默认省份',
'type' => 'select',
'required' => true,
'options' => ZoneRepo::getZoneOptions(1),
'value' => old('zone_id', system_setting('base.zone_id', '1')),
'description' => '默认省份设置',
],
[
'name' => 'locale',

View File

@ -18,7 +18,7 @@ class ZoneRepo
/**
* 创建一个zone记录
* @param $data
* @return int
* @return mixed
*/
public static function create($data)
{
@ -29,7 +29,8 @@ class ZoneRepo
/**
* @param $id
* @param $data
* @return bool|int
* @return mixed
* @throws \Exception
*/
public static function update($id, $data)
{
@ -43,7 +44,7 @@ class ZoneRepo
/**
* @param $id
* @return \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Eloquent\Builder[]|\Illuminate\Database\Eloquent\Collection|\Illuminate\Database\Eloquent\Model|null
* @return mixed
*/
public static function find($id)
{
@ -97,4 +98,24 @@ class ZoneRepo
return $country->zones;
}
}
/**
* 通过国家ID获取省份拉下选项
*
* @param $countryId
* @return array
*/
public static function getZoneOptions($countryId): array
{
$zones = self::listByCountry($countryId);
$items = [];
foreach ($zones as $zone) {
$items[] = [
'value' => $zone->id,
'label' => $zone->name
];
}
return $items;
}
}

View File

@ -13,12 +13,14 @@ class CartList extends JsonResource
*
* @param Request $request
* @return array|Arrayable|\JsonSerializable
* @throws \Exception
*/
public function toArray($request)
{
$sku = $this->sku;
$product = $sku->product;
$price = $sku->price;
$description = $sku->product->description;
$description = $product->description;
$subTotal = $price * $this->quantity;
return [
'cart_id' => $this->id,
@ -30,6 +32,7 @@ class CartList extends JsonResource
'selected' => $this->selected,
'price' => $price,
'price_format' => currency_format($price),
'tax_class_id' => $product->tax_class_id,
'subtotal' => $subTotal,
'subtotal_format' => currency_format($subTotal),
];

View File

@ -2,18 +2,32 @@
namespace Beike\Shop\Providers;
use Beike\Libraries\Tax;
use Beike\Models\Customer;
use Illuminate\Support\Str;
use Illuminate\View\FileViewFinder;
use TorMorten\Eventy\Facades\Eventy;
use Beike\Repositories\CategoryRepo;
use Illuminate\Support\Facades\View;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\ServiceProvider;
use Beike\Shop\View\Components\AccountSidebar;
use Illuminate\View\FileViewFinder;
use TorMorten\Eventy\Facades\Eventy;
class ShopServiceProvider extends ServiceProvider
{
/**
* Register the application services.
*
* @return void
*/
public function register()
{
$this->app->singleton('tax', function () {
return new Tax();
});
}
/**
* @throws \Exception
*/

View File

@ -11,6 +11,7 @@
namespace Beike\Shop\Services;
use Beike\Libraries\Tax;
use Illuminate\Support\Str;
class TotalService
@ -23,6 +24,7 @@ class TotalService
];
public array $carts;
public array $taxes = [];
public array $totals;
public float $amount = 0;
public string $shippingMethod = '';
@ -30,6 +32,7 @@ class TotalService
public function __construct($carts)
{
$this->carts = $carts;
$this->getTaxes();
}
@ -43,6 +46,33 @@ class TotalService
}
/**
* 获取税费数据
*
* @return array
*/
public function getTaxes(): array
{
$taxLib = Tax::getInstance();
foreach ($this->carts as $product) {
if (empty($product['tax_class_id'])) {
continue;
}
$taxRates = $taxLib->getRates($product['price'], $product['tax_class_id']);
foreach ($taxRates as $taxRate) {
if (!isset($this->taxes[$taxRate['tax_rate_id']])) {
$this->taxes[$taxRate['tax_rate_id']] = ($taxRate['amount'] * $product['quantity']);
} else {
$this->taxes[$taxRate['tax_rate_id']] += ($taxRate['amount'] * $product['quantity']);
}
}
}
return $this->taxes;
}
/**
* @return array
*/
@ -54,11 +84,7 @@ class TotalService
if (!class_exists($service) || !method_exists($service, 'getTotal')) {
continue;
}
$totalData = $service::getTotal($this);
if ($totalData) {
$this->amount += $totalData['amount'];
$this->totals[] = $totalData;
}
$service::getTotal($this);
}
return $this->totals;

View File

@ -18,11 +18,16 @@ class OrderTotalService
public static function getTotal(TotalService $totalService)
{
$amount = $totalService->amount;
return [
$totalData = [
'code' => 'order_total',
'title' => '应付总金额',
'amount' => $amount,
'amount_format' => currency_format($amount)
];
$totalService->amount += $totalData['amount'];
$totalService->totals[] = $totalData;
return $totalData;
}
}

View File

@ -31,11 +31,16 @@ class ShippingService
throw new \Exception("请在插件 {$className} 实现方法 getShippingFee");
}
$amount = (float)(new $className)->getShippingFee($totalService);
return [
$totalData = [
'code' => 'shipping',
'title' => '运费',
'amount' => $amount,
'amount_format' => currency_format($amount)
];
$totalService->amount += $totalData['amount'];
$totalService->totals[] = $totalData;
return $totalData;
}
}

View File

@ -20,11 +20,16 @@ class SubtotalService
{
$carts = $totalService->carts;
$amount = collect($carts)->sum('subtotal');
return [
$totalData = [
'code' => 'sub_total',
'title' => '商品总额',
'amount' => $amount,
'amount_format' => currency_format($amount)
];
$totalService->amount += $totalData['amount'];
$totalService->totals[] = $totalData;
return $totalData;
}
}

View File

@ -12,18 +12,30 @@
namespace Beike\Shop\Services\TotalServices;
use Beike\Admin\Repositories\TaxRateRepo;
use Beike\Shop\Services\TotalService;
class TaxService
{
public static function getTotal(TotalService $totalService)
{
$amount = $totalService->amount * 0.02;
return [
'code' => 'tax',
'title' => '税费',
'amount' => $amount,
'amount_format' => currency_format($amount)
];
$taxes = $totalService->taxes;
$totalItems = [];
foreach ($taxes as $taxRateId => $value) {
if ($value <= 0) {
continue;
}
$totalItems[] = array(
'code' => 'tax',
'title' => TaxRateRepo::getNameByRateId($taxRateId),
'amount' => $value,
'amount_format' => currency_format($value)
);
$totalService->amount += $value;
}
$totalService->totals = array_merge($totalService->totals, $totalItems);
return $totalItems;
}
}

View File

@ -52,6 +52,7 @@ class CreateTax extends Migration
$table->integer('tax_class_id');
$table->integer('tax_rate_id');
$table->enum('based', ['store', 'payment', 'shipping']);
$table->integer('priority');
$table->timestamps();
});
}

View File

@ -0,0 +1,30 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddProductTaxClassId extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('products', function (Blueprint $table) {
$table->integer('tax_class_id')->after('variables');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
//
}
}