完善税费
This commit is contained in:
parent
c279cede8b
commit
bf3a1bedfa
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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']);
|
||||
}
|
||||
|
||||
|
|
@ -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',
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
];
|
||||
|
|
|
|||
|
|
@ -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
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue