diff --git a/app/Http/Controllers/Site/ReportController.php b/app/Http/Controllers/Site/ReportController.php index 715a55a..65de76f 100644 --- a/app/Http/Controllers/Site/ReportController.php +++ b/app/Http/Controllers/Site/ReportController.php @@ -139,6 +139,7 @@ class ReportController extends Controller $payload['up'] = $this->buildUpDownPrices(); $payload['last_historical'] = app(ProductDisplayPriceService::class)->resolveHistoricalBasePrice(); + $payload['gold_ounce'] = $this->resolveGoldOuncePayload(); app(ProductDisplayPriceService::class)->cacheLivePricePayload($payload); $isFreshPrice = $saveFullCache || request()->boolean('force_refresh'); @@ -164,6 +165,29 @@ class ReportController extends Controller return $payload; } + protected function resolveGoldOuncePayload(): ?array + { + $config = app(ConfigService::class); + if (! $config->getBool('show_gold_ounce_price', false)) { + return null; + } + + $zaarbox = app(ZaarboxPriceService::class); + if (! $zaarbox->hasApiUrlConfigured()) { + return null; + } + + $ounce = $zaarbox->fetchOuncePrice(); + if (($ounce['price'] ?? 0) <= 0) { + return null; + } + + return [ + 'price' => (int) $ounce['price'], + 'label' => trim((string) ($ounce['name'] ?? 'انس طلا')) ?: 'انس طلا', + ]; + } + public function lastPrice(Request $request) { $config = app(ConfigService::class); diff --git a/app/Services/ZaarboxPriceService.php b/app/Services/ZaarboxPriceService.php index c048b80..364d5c7 100644 --- a/app/Services/ZaarboxPriceService.php +++ b/app/Services/ZaarboxPriceService.php @@ -54,6 +54,11 @@ class ZaarboxPriceService return $url !== '' ? $url : 'https://price.zaarbox.ir/api/free'; } + public function hasApiUrlConfigured(): bool + { + return trim($this->config->getString('zaarbox_api_url', '')) !== ''; + } + /** کلید یا id ردیف در JSON تابلو (settings: zaarbox_price_key) */ public function priceIdentifier(): string { @@ -190,6 +195,67 @@ class ZaarboxPriceService return $prices; } + /** + * @param array> $prices + * @return array|null + */ + public function findOunceFeedRow(array $prices): ?array + { + $row = collect($prices) + ->map(fn ($item) => is_array($item) ? $item : (array) $item) + ->filter(function (array $item) { + $name = trim((string) ($item['name'] ?? '')); + + return $name !== '' && mb_strpos($name, 'انس') !== false; + }) + ->sortBy([ + fn (array $item) => (bool) ($item['active'] ?? false) ? 0 : 1, + fn (array $item) => str_contains(trim((string) ($item['name'] ?? '')), 'انس طلا') ? 0 : 1, + fn (array $item) => mb_strlen(trim((string) ($item['name'] ?? ''))), + ]) + ->first(); + + return is_array($row) ? $row : null; + } + + /** + * @return array{price: int, name: string, raw: array|null} + */ + public function fetchOuncePrice(): array + { + $empty = ['price' => 0, 'name' => '', 'raw' => null]; + if (! $this->hasApiUrlConfigured()) { + return $empty; + } + + try { + $prices = $this->cachedPriceList(false) ?? $this->fetchPriceList(); + if (! is_array($prices)) { + return $empty; + } + + $row = $this->findOunceFeedRow($prices); + if ($row === null) { + return $empty; + } + + $price = $this->resolveReferenceProviderTotal($row); + if ($price <= 0) { + return $empty; + } + + return [ + 'price' => $price, + 'name' => trim((string) ($row['name'] ?? 'انس طلا')), + 'raw' => $row, + ]; + } catch (\Throwable $e) { + Log::warning('Zaarbox ounce price fetch failed', ['message' => $e->getMessage()]); + + return $empty; + } + } + /** * @return array{price: int, order_price: int, raw: array|null} */ diff --git a/database/sql/deploy_settings_const.sql b/database/sql/deploy_settings_const.sql index 33abb23..1b338ad 100644 --- a/database/sql/deploy_settings_const.sql +++ b/database/sql/deploy_settings_const.sql @@ -209,6 +209,10 @@ INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `de SELECT 'show_last_price', 'true', 'نمایش آخرین قیمت DB اگر API قطع شد', 1, 1, NULL WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'show_last_price' LIMIT 1); +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) +SELECT 'show_gold_ounce_price', 'false', 'نمایش قیمت انس طلا', 1, 1, NULL +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'show_gold_ounce_price' LIMIT 1); + INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) SELECT 'main_product_price', 'false', 'قیمت از محصول (legacy)', 1, 1, 'از price_provider استفاده کنید' WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'main_product_price' LIMIT 1); @@ -795,7 +799,7 @@ UPDATE `settings` SET `type` = 'select', `description` = 'bale,telegram,whatsapp UPDATE `settings` SET `type` = 'switch' WHERE `key` IN ( 'chart_use_local_data', 'jibit_verification', 'register_jibit_verify', 'open_register', 'auto_active_customer', - 'close_price', 'show_last_price', + 'close_price', 'show_last_price', 'show_gold_ounce_price', 'fee_deduct_from_gold', 'profit_gold_api_enabled', 'payping_round_toman', 'payping_strict_failed_withdraw', 'has_page_earn_money', 'charge_notif', 'group_sms', 'sms_panel', @@ -1115,6 +1119,7 @@ UPDATE `settings` SET `description` = 'شناسه عددی یا نام reading_m UPDATE `settings` SET `description` = 'آدرس پایه API سرویس تابلو آنلاین (بدون مسیر انتهایی). مثال: https://example.com/api' WHERE `key` = 'zaarbox_api_url'; UPDATE `settings` SET `description` = 'کلید یا UUID ردیف قیمت در پاسخ API تابلو. باید با محصول/ردیف موردنظر در سرویس خارجی یکسان باشد.' WHERE `key` = 'zaarbox_price_key'; UPDATE `settings` SET `description` = 'روشن: اگر API قیمت در دسترس نباشد، آخرین قیمت ذخیره‌شده در دیتابیس به کاربر نشان داده می‌شود. خاموش: در قطعی API ممکن است قیمت صفر نمایش داده شود.' WHERE `key` = 'show_last_price'; +UPDATE `settings` SET `description` = 'روشن: اگر آدرس API تابلو (zaarbox_api_url) تنظیم شده باشد، قیمت انس طلا در اپ مشتری نمایش داده می‌شود. خاموش: نمایش داده نمی‌شود.' WHERE `key` = 'show_gold_ounce_price'; UPDATE `settings` SET `description` = 'روشن: خارج از بازه «ساعت شروع» تا «ساعت پایان» معامله و نمایش قیمت بسته می‌شود. خاموش: محدودیت ساعتی سراسری اعمال نمی‌شود.' WHERE `key` = 'close_price'; UPDATE `settings` SET `description` = 'ساعت شروع فعالیت روزانه. فقط وقتی «بستن خودکار خارج از ساعت کاری» روشن باشد اعمال می‌شود (مثلاً ۰۹:۰۰).' WHERE `key` = 'startDay'; UPDATE `settings` SET `description` = 'ساعت پایان فعالیت روزانه. فقط وقتی «بستن خودکار خارج از ساعت کاری» روشن باشد اعمال می‌شود (مثلاً ۲۲:۰۰).' WHERE `key` = 'endDay'; @@ -1365,6 +1370,7 @@ UPDATE `settings` SET `title_fa` = 'ارسال به ته‌حساب' WHERE `key` UPDATE `settings` SET `title_fa` = 'آدرس API سرور' WHERE `key` = 'server_url'; UPDATE `settings` SET `title_fa` = 'کارمزد درصدی (alias)' WHERE `key` = 'service_charge_percentage'; UPDATE `settings` SET `title_fa` = 'نمایش آخرین قیمت ذخیره‌شده' WHERE `key` = 'show_last_price'; +UPDATE `settings` SET `title_fa` = 'نمایش قیمت انس طلا' WHERE `key` = 'show_gold_ounce_price'; UPDATE `settings` SET `title_fa` = 'مسیر SSE قیمت' WHERE `key` = 'sse_path'; UPDATE `settings` SET `title_fa` = 'ساعت شروع' WHERE `key` = 'startDay'; UPDATE `settings` SET `title_fa` = 'وضعیت فروشگاه' WHERE `key` = 'store_status'; @@ -1448,7 +1454,7 @@ UPDATE `settings` SET `can_edit` = 1 WHERE `key` IN ( 'open_register', 'referral_bonus_amount', 'referral_id', 'referral_limit', 'referral_gift_on_first_order', 'register_jibit_verify', 'register_referral_bonus_message', 'register_referral_sms_to_referrer', - 'sell_fee', 'show_last_price', 'startDay', + 'sell_fee', 'show_last_price', 'show_gold_ounce_price', 'startDay', 'support_messenger', 'support_messenger_id', 'support_messenger_text', 'deposit_support_message_text', 'deposit_account_holder', 'deposit_card_number', 'deposit_sheba', 'text_about', 'text_rule', diff --git a/database/sql/show_gold_ounce_price_patch.sql b/database/sql/show_gold_ounce_price_patch.sql new file mode 100644 index 0000000..72d85d6 --- /dev/null +++ b/database/sql/show_gold_ounce_price_patch.sql @@ -0,0 +1,25 @@ +-- سوییچ «نمایش قیمت انس طلا» — برای نصب‌های موجود +-- idempotent: چند بار قابل اجرا +-- • اولین بار: INSERT با value='false' (پیش‌فرض خاموش) +-- • اجرای مجدد: value و is_active دست نمی‌خورند — title_fa / description / type / can_edit همیشه override می‌شوند + +START TRANSACTION; + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) +SELECT 'show_gold_ounce_price', 'false', 'نمایش قیمت انس طلا', 1, 1, + 'روشن: اگر آدرس API تابلو (zaarbox_api_url) تنظیم شده باشد، قیمت انس طلا در اپ مشتری نمایش داده می‌شود. خاموش: نمایش داده نمی‌شود.', + 'switch' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'show_gold_ounce_price' LIMIT 1); + +UPDATE `settings` +SET `title_fa` = 'نمایش قیمت انس طلا', + `description` = 'روشن: اگر آدرس API تابلو (zaarbox_api_url) تنظیم شده باشد، قیمت انس طلا در اپ مشتری نمایش داده می‌شود. خاموش: نمایش داده نمی‌شود.', + `type` = 'switch', + `can_edit` = 1 +WHERE `key` = 'show_gold_ounce_price'; + +COMMIT; + +SELECT `key`, `title_fa`, LEFT(`description`, 60) AS desc_preview, `can_edit`, `type` +FROM `settings` +WHERE `key` = 'show_gold_ounce_price';