store/app/Services/System/Setting/MarketplaceService.php
Yoga Pangestu ee9bff3043
Some checks are pending
linter / quality (push) Waiting to run
tests / ci (8.3) (push) Waiting to run
tests / ci (8.4) (push) Waiting to run
tests / ci (8.5) (push) Waiting to run
feat: replace OwnerVerificationService with PushNotificationService and update notification logic in SettingController and MarketplaceService
2026-07-20 23:02:28 +07:00

219 lines
8.8 KiB
PHP

<?php
namespace App\Services\System\Setting;
use App\Enums\OrderChannel;
use App\Enums\Permission;
use App\Models\OwnerVerificationRequest;
use App\Models\User;
use App\Services\Concerns\CachesQuery;
use App\Services\Concerns\RunsInTransaction;
use App\Services\System\PushNotificationService;
use App\Settings\MarketplaceSettings;
use App\Support\Marketplace\MarketplaceFeeCalculator;
use App\Support\Marketplace\MarketplaceFeeRule;
class MarketplaceService
{
use CachesQuery, RunsInTransaction;
public function __construct(
private readonly PushNotificationService $pushNotificationService,
) {}
private function tiktokFeeKeys(): array
{
return [
'tiktok_shop_platform_commission',
'tiktok_shop_logistics_service_fee',
'tiktok_shop_dynamic_commission',
'tiktok_shop_order_processing_fee',
'tiktok_shop_affiliate',
'tiktok_shop_pre_order_service_fee',
];
}
private function shopeeFeeKeys(): array
{
return [
'shopee_admin_fee',
'shopee_program_fee',
'shopee_shipping_savings',
'shopee_premium',
'shopee_service_fee',
'shopee_order_processing_fee',
'shopee_ams_commission_fee',
'shopee_pre_order',
'shopee_live_extra',
];
}
public function marketplaceData(): array
{
return $this->cacheRemember('system:marketplace', 86400, function () {
$settings = app(MarketplaceSettings::class);
return [
'tiktok_shop_platform_commission' => $this->presentFeeRule($settings->tiktok_shop_platform_commission),
'tiktok_shop_logistics_service_fee' => $this->presentFeeRule($settings->tiktok_shop_logistics_service_fee),
'tiktok_shop_dynamic_commission' => $this->presentFeeRule($settings->tiktok_shop_dynamic_commission),
'tiktok_shop_order_processing_fee' => $this->presentFeeRule($settings->tiktok_shop_order_processing_fee),
'tiktok_shop_affiliate' => $this->presentFeeRule($settings->tiktok_shop_affiliate),
'tiktok_shop_pre_order_service_fee' => $this->presentFeeRule($settings->tiktok_shop_pre_order_service_fee),
'shopee_admin_fee' => $this->presentFeeRule($settings->shopee_admin_fee),
'shopee_program_fee' => $this->presentFeeRule($settings->shopee_program_fee),
'shopee_shipping_savings' => $this->presentFeeRule($settings->shopee_shipping_savings),
'shopee_premium' => $this->presentFeeRule($settings->shopee_premium),
'shopee_service_fee' => $this->presentFeeRule($settings->shopee_service_fee),
'shopee_order_processing_fee' => $this->presentFeeRule($settings->shopee_order_processing_fee),
'shopee_ams_commission_fee' => $this->presentFeeRule($settings->shopee_ams_commission_fee),
'shopee_pre_order' => $this->presentFeeRule($settings->shopee_pre_order),
'shopee_live_extra' => $this->presentFeeRule($settings->shopee_live_extra),
];
});
}
public function updateMarketplace(array $validated, User $user): void
{
$this->runInTransaction(
function () use ($validated, $user): void {
$this->saveSettings($validated);
if (! $user->can(Permission::OWNER_VERIFICATIONS_VERIFY->value)) {
$this->pushNotificationService->sendToRoles(
'⚙️ Pengaturan Marketplace Diubah',
"Pengaturan marketplace telah diubah oleh '{$user->username}'.",
['owner', 'developer'],
route('admin.system.settings.index'),
);
}
},
'Gagal memperbarui pengaturan marketplace',
);
}
public function saveSettings(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();
$this->cacheForget('system:marketplace');
}
public function applyVerificationRequest(OwnerVerificationRequest $request): void
{
$this->runInTransaction(
function () use ($request): void {
$newPayload = $request->payload['new'] ?? [];
$this->saveSettings($newPayload);
$this->cacheForget('system:marketplace');
},
'Gagal menerapkan pengajuan verifikasi owner',
);
}
public function buildOrderSnapshot(OrderChannel $channel, int $totalAmount, array $lineItems, bool $isAffiliate = false): ?array
{
$feeSnapshot = $this->feeRulesForChannel($channel);
if ($feeSnapshot === null) {
return null;
}
if (! $isAffiliate) {
$feeSnapshot['fees'] = $this->excludeAffiliateFee($feeSnapshot['fees'], $channel);
}
$calculation = app(MarketplaceFeeCalculator::class)->calculate(
$feeSnapshot['fees'],
$totalAmount,
$lineItems,
);
return [
'platform' => $feeSnapshot['platform'],
'is_affiliate' => $isAffiliate,
'fees' => $feeSnapshot['fees'],
'base_amount' => $totalAmount,
'base_amount_formatted' => 'Rp '.number_format($totalAmount, 0, ',', '.'),
'results' => $calculation['results'],
'total_fee_amount' => $calculation['total_fee_amount'],
'total_fee_amount_formatted' => 'Rp '.number_format($calculation['total_fee_amount'], 0, ',', '.'),
'net_amount' => $calculation['net_amount'],
'net_amount_formatted' => 'Rp '.number_format($calculation['net_amount'], 0, ',', '.'),
];
}
private function excludeAffiliateFee(array $fees, OrderChannel $channel): array
{
$affiliateKey = match ($channel) {
OrderChannel::TIKTOK => 'tiktok_shop_affiliate',
OrderChannel::SHOPEE => 'ams_commission_fee',
default => null,
};
if ($affiliateKey !== null && isset($fees[$affiliateKey])) {
$fees[$affiliateKey] = [
'scope' => $fees[$affiliateKey]['scope'],
'value_type' => $fees[$affiliateKey]['value_type'],
'value' => 0,
];
}
return $fees;
}
private function feeRulesForChannel(OrderChannel $channel): ?array
{
$settings = app(MarketplaceSettings::class);
return match ($channel) {
OrderChannel::TIKTOK => [
'platform' => 'tiktok',
'fees' => [
'platform_commission' => $this->presentFeeRule($settings->tiktok_shop_platform_commission),
'logistics_service_fee' => $this->presentFeeRule($settings->tiktok_shop_logistics_service_fee),
'dynamic_commission' => $this->presentFeeRule($settings->tiktok_shop_dynamic_commission),
'order_processing_fee' => $this->presentFeeRule($settings->tiktok_shop_order_processing_fee),
'affiliate' => $this->presentFeeRule($settings->tiktok_shop_affiliate),
'pre_order_service_fee' => $this->presentFeeRule($settings->tiktok_shop_pre_order_service_fee),
],
],
OrderChannel::SHOPEE => [
'platform' => 'shopee',
'fees' => [
'admin_fee' => $this->presentFeeRule($settings->shopee_admin_fee),
'program_fee' => $this->presentFeeRule($settings->shopee_program_fee),
'shipping_savings' => $this->presentFeeRule($settings->shopee_shipping_savings),
'premium' => $this->presentFeeRule($settings->shopee_premium),
'service_fee' => $this->presentFeeRule($settings->shopee_service_fee),
'order_processing_fee' => $this->presentFeeRule($settings->shopee_order_processing_fee),
'ams_commission_fee' => $this->presentFeeRule($settings->shopee_ams_commission_fee),
'pre_order' => $this->presentFeeRule($settings->shopee_pre_order),
'live_extra' => $this->presentFeeRule($settings->shopee_live_extra),
],
],
OrderChannel::STORE => null,
};
}
private function presentFeeRule(array $data): array
{
return MarketplaceFeeRule::fromArray($data)->toArray();
}
private function normalizeFeeRule(array $data): array
{
return MarketplaceFeeRule::fromArray($data)->toArray();
}
}