From bf3a1bedfaa02f8d52190477124b13dc0c8997a7 Mon Sep 17 00:00:00 2001 From: Edward Yang Date: Fri, 29 Jul 2022 15:12:14 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E5=96=84=E7=A8=8E=E8=B4=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- beike/Admin/Repositories/TaxRateRepo.php | 6 +++ .../TaxService.php => Libraries/Tax.php} | 38 +++++++++---------- beike/Repositories/SystemSettingRepo.php | 11 +++++- beike/Repositories/ZoneRepo.php | 27 +++++++++++-- beike/Shop/Http/Resources/CartList.php | 5 ++- beike/Shop/Providers/ShopServiceProvider.php | 18 ++++++++- beike/Shop/Services/TotalService.php | 36 +++++++++++++++--- .../TotalServices/OrderTotalService.php | 7 +++- .../TotalServices/ShippingService.php | 7 +++- .../TotalServices/SubtotalService.php | 7 +++- .../Services/TotalServices/TaxService.php | 26 +++++++++---- .../2022_07_21_073835_create_tax.php | 1 + ..._07_29_063112_add_product_tax_class_id.php | 30 +++++++++++++++ 13 files changed, 177 insertions(+), 42 deletions(-) rename beike/{Services/TaxService.php => Libraries/Tax.php} (82%) create mode 100644 database/migrations/2022_07_29_063112_add_product_tax_class_id.php diff --git a/beike/Admin/Repositories/TaxRateRepo.php b/beike/Admin/Repositories/TaxRateRepo.php index e7ca2b38..621feae0 100644 --- a/beike/Admin/Repositories/TaxRateRepo.php +++ b/beike/Admin/Repositories/TaxRateRepo.php @@ -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; + } } diff --git a/beike/Services/TaxService.php b/beike/Libraries/Tax.php similarity index 82% rename from beike/Services/TaxService.php rename to beike/Libraries/Tax.php index 76cb072d..6007b706 100644 --- a/beike/Services/TaxService.php +++ b/beike/Libraries/Tax.php @@ -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']); } diff --git a/beike/Repositories/SystemSettingRepo.php b/beike/Repositories/SystemSettingRepo.php index c8330e5e..2b6487ee 100644 --- a/beike/Repositories/SystemSettingRepo.php +++ b/beike/Repositories/SystemSettingRepo.php @@ -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', diff --git a/beike/Repositories/ZoneRepo.php b/beike/Repositories/ZoneRepo.php index 3a8ab766..d90cfc29 100644 --- a/beike/Repositories/ZoneRepo.php +++ b/beike/Repositories/ZoneRepo.php @@ -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; + } } diff --git a/beike/Shop/Http/Resources/CartList.php b/beike/Shop/Http/Resources/CartList.php index f19d8640..87b0b277 100644 --- a/beike/Shop/Http/Resources/CartList.php +++ b/beike/Shop/Http/Resources/CartList.php @@ -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), ]; diff --git a/beike/Shop/Providers/ShopServiceProvider.php b/beike/Shop/Providers/ShopServiceProvider.php index d0e5727e..db7de2d2 100644 --- a/beike/Shop/Providers/ShopServiceProvider.php +++ b/beike/Shop/Providers/ShopServiceProvider.php @@ -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 */ diff --git a/beike/Shop/Services/TotalService.php b/beike/Shop/Services/TotalService.php index 9ddcd193..9292a28f 100644 --- a/beike/Shop/Services/TotalService.php +++ b/beike/Shop/Services/TotalService.php @@ -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; diff --git a/beike/Shop/Services/TotalServices/OrderTotalService.php b/beike/Shop/Services/TotalServices/OrderTotalService.php index 0454dced..480b57eb 100644 --- a/beike/Shop/Services/TotalServices/OrderTotalService.php +++ b/beike/Shop/Services/TotalServices/OrderTotalService.php @@ -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; } } diff --git a/beike/Shop/Services/TotalServices/ShippingService.php b/beike/Shop/Services/TotalServices/ShippingService.php index 659559c4..ca585dca 100644 --- a/beike/Shop/Services/TotalServices/ShippingService.php +++ b/beike/Shop/Services/TotalServices/ShippingService.php @@ -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; } } diff --git a/beike/Shop/Services/TotalServices/SubtotalService.php b/beike/Shop/Services/TotalServices/SubtotalService.php index ef079d5b..2e788440 100644 --- a/beike/Shop/Services/TotalServices/SubtotalService.php +++ b/beike/Shop/Services/TotalServices/SubtotalService.php @@ -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; } } diff --git a/beike/Shop/Services/TotalServices/TaxService.php b/beike/Shop/Services/TotalServices/TaxService.php index b3134c36..199ab44c 100644 --- a/beike/Shop/Services/TotalServices/TaxService.php +++ b/beike/Shop/Services/TotalServices/TaxService.php @@ -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; } } diff --git a/database/migrations/2022_07_21_073835_create_tax.php b/database/migrations/2022_07_21_073835_create_tax.php index b481d241..95555465 100644 --- a/database/migrations/2022_07_21_073835_create_tax.php +++ b/database/migrations/2022_07_21_073835_create_tax.php @@ -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(); }); } diff --git a/database/migrations/2022_07_29_063112_add_product_tax_class_id.php b/database/migrations/2022_07_29_063112_add_product_tax_class_id.php new file mode 100644 index 00000000..dec3149c --- /dev/null +++ b/database/migrations/2022_07_29_063112_add_product_tax_class_id.php @@ -0,0 +1,30 @@ +integer('tax_class_id')->after('variables'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + // + } +}