store/app/Services/System/Setting/MarketplaceService.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();
}
}