160 lines
6.2 KiB
PHP
160 lines
6.2 KiB
PHP
<?php
|
|
|
|
namespace App\Services\System\Setting;
|
|
|
|
use App\Enums\OrderChannel;
|
|
use App\Settings\MarketplaceSettings;
|
|
use App\Support\Marketplace\MarketplaceFeeCalculator;
|
|
use App\Support\Marketplace\MarketplaceFeeRule;
|
|
|
|
class MarketplaceService
|
|
{
|
|
/**
|
|
* @return list<string>
|
|
*/
|
|
private function tiktokFeeKeys(): array
|
|
{
|
|
return [
|
|
'tiktok_shop_admin_fee',
|
|
'tiktok_shop_transaction_fee',
|
|
'tiktok_shop_payment_fee',
|
|
'tiktok_shop_affiliate_commission',
|
|
'tiktok_shop_shipping_subsidy',
|
|
'tiktok_shop_vat_rate',
|
|
];
|
|
}
|
|
|
|
/**
|
|
* @return list<string>
|
|
*/
|
|
private function shopeeFeeKeys(): array
|
|
{
|
|
return [
|
|
'shopee_commission_fee',
|
|
'shopee_transaction_fee',
|
|
'shopee_service_fee',
|
|
'shopee_payment_fee',
|
|
'shopee_affiliate_commission',
|
|
'shopee_shipping_subsidy',
|
|
'shopee_voucher_fee',
|
|
];
|
|
}
|
|
|
|
public function marketplaceData(): array
|
|
{
|
|
$settings = app(MarketplaceSettings::class);
|
|
|
|
return [
|
|
'tiktok_shop_admin_fee' => $this->presentFeeRule($settings->tiktok_shop_admin_fee),
|
|
'tiktok_shop_transaction_fee' => $this->presentFeeRule($settings->tiktok_shop_transaction_fee),
|
|
'tiktok_shop_payment_fee' => $this->presentFeeRule($settings->tiktok_shop_payment_fee),
|
|
'tiktok_shop_affiliate_commission' => $this->presentFeeRule($settings->tiktok_shop_affiliate_commission),
|
|
'tiktok_shop_shipping_subsidy' => $this->presentFeeRule($settings->tiktok_shop_shipping_subsidy),
|
|
'tiktok_shop_vat_rate' => $this->presentFeeRule($settings->tiktok_shop_vat_rate),
|
|
'shopee_commission_fee' => $this->presentFeeRule($settings->shopee_commission_fee),
|
|
'shopee_transaction_fee' => $this->presentFeeRule($settings->shopee_transaction_fee),
|
|
'shopee_service_fee' => $this->presentFeeRule($settings->shopee_service_fee),
|
|
'shopee_payment_fee' => $this->presentFeeRule($settings->shopee_payment_fee),
|
|
'shopee_affiliate_commission' => $this->presentFeeRule($settings->shopee_affiliate_commission),
|
|
'shopee_shipping_subsidy' => $this->presentFeeRule($settings->shopee_shipping_subsidy),
|
|
'shopee_voucher_fee' => $this->presentFeeRule($settings->shopee_voucher_fee),
|
|
];
|
|
}
|
|
|
|
public function updateMarketplace(array $validated): void
|
|
{
|
|
$settings = app(MarketplaceSettings::class);
|
|
|
|
foreach ($this->tiktokFeeKeys() as $key) {
|
|
$settings->{$key} = $this->normalizeFeeRule($validated[$key]);
|
|
}
|
|
|
|
foreach ($this->shopeeFeeKeys() as $key) {
|
|
$settings->{$key} = $this->normalizeFeeRule($validated[$key]);
|
|
}
|
|
|
|
$settings->save();
|
|
}
|
|
|
|
/**
|
|
* @param list<array{quantity: int, subtotal: int}> $lineItems
|
|
* @return array<string, mixed>|null
|
|
*/
|
|
public function buildOrderSnapshot(OrderChannel $channel, int $totalAmount, array $lineItems): ?array
|
|
{
|
|
$feeSnapshot = $this->feeRulesForChannel($channel);
|
|
|
|
if ($feeSnapshot === null) {
|
|
return null;
|
|
}
|
|
|
|
$calculation = app(MarketplaceFeeCalculator::class)->calculate(
|
|
$feeSnapshot['fees'],
|
|
$totalAmount,
|
|
$lineItems,
|
|
);
|
|
|
|
return [
|
|
'platform' => $feeSnapshot['platform'],
|
|
'fees' => $feeSnapshot['fees'],
|
|
'base_amount' => $totalAmount,
|
|
'results' => $calculation['results'],
|
|
'total_fee_amount' => $calculation['total_fee_amount'],
|
|
'net_amount' => $calculation['net_amount'],
|
|
];
|
|
}
|
|
|
|
/**
|
|
* @return array{platform: string, fees: array<string, array{scope: string, value_type: string, value: float}>}|null
|
|
*/
|
|
private function feeRulesForChannel(OrderChannel $channel): ?array
|
|
{
|
|
$settings = app(MarketplaceSettings::class);
|
|
|
|
return match ($channel) {
|
|
OrderChannel::SHOPEE => [
|
|
'platform' => 'shopee',
|
|
'fees' => [
|
|
'commission_fee' => $this->presentFeeRule($settings->shopee_commission_fee),
|
|
'transaction_fee' => $this->presentFeeRule($settings->shopee_transaction_fee),
|
|
'service_fee' => $this->presentFeeRule($settings->shopee_service_fee),
|
|
'payment_fee' => $this->presentFeeRule($settings->shopee_payment_fee),
|
|
'affiliate_commission' => $this->presentFeeRule($settings->shopee_affiliate_commission),
|
|
'shipping_subsidy' => $this->presentFeeRule($settings->shopee_shipping_subsidy),
|
|
'voucher_fee' => $this->presentFeeRule($settings->shopee_voucher_fee),
|
|
],
|
|
],
|
|
OrderChannel::TIKTOK => [
|
|
'platform' => 'tiktok',
|
|
'fees' => [
|
|
'admin_fee' => $this->presentFeeRule($settings->tiktok_shop_admin_fee),
|
|
'transaction_fee' => $this->presentFeeRule($settings->tiktok_shop_transaction_fee),
|
|
'payment_fee' => $this->presentFeeRule($settings->tiktok_shop_payment_fee),
|
|
'affiliate_commission' => $this->presentFeeRule($settings->tiktok_shop_affiliate_commission),
|
|
'shipping_subsidy' => $this->presentFeeRule($settings->tiktok_shop_shipping_subsidy),
|
|
'vat_rate' => $this->presentFeeRule($settings->tiktok_shop_vat_rate),
|
|
],
|
|
],
|
|
OrderChannel::STORE => null,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* @param array{scope: string, value_type: string, value: float|int|string} $data
|
|
* @return array{scope: string, value_type: string, value: float}
|
|
*/
|
|
private function presentFeeRule(array $data): array
|
|
{
|
|
return MarketplaceFeeRule::fromArray($data)->toArray();
|
|
}
|
|
|
|
/**
|
|
* @param array{scope: string, value_type: string, value: float|int|string} $data
|
|
* @return array{scope: string, value_type: string, value: float}
|
|
*/
|
|
private function normalizeFeeRule(array $data): array
|
|
{
|
|
return MarketplaceFeeRule::fromArray($data)->toArray();
|
|
}
|
|
}
|