From 771080d68c40b244aa8d1b092b8aa64b8066923d Mon Sep 17 00:00:00 2001 From: adonis Date: Wed, 8 Jul 2026 13:15:29 +0330 Subject: [PATCH] fix some handling 4 --- app/Console/Commands/PriceChannelTest.php | 1 + .../Controllers/Admin/SettingsController.php | 12 ++++ app/Services/PriceChannelBroadcastService.php | 69 ++++++++++++++++--- 3 files changed, 74 insertions(+), 8 deletions(-) diff --git a/app/Console/Commands/PriceChannelTest.php b/app/Console/Commands/PriceChannelTest.php index 1f0bce6..5b32b80 100644 --- a/app/Console/Commands/PriceChannelTest.php +++ b/app/Console/Commands/PriceChannelTest.php @@ -21,6 +21,7 @@ class PriceChannelTest extends Command $this->line('پیام‌رسان‌های انتخاب‌شده: ' . (implode(', ', $info['selected_messengers']) ?: '— (خالی)')); $this->line('حداقل فاصله ارسال (ثانیه): ' . $info['min_seconds']); $this->line('فاصله cooldown گذشته؟ ' . ($info['cooldown_elapsed'] ? 'بله' : 'خیر (هنوز زوده)')); + $this->line('منبع قالب: ' . ($info['template_source'] === 'db' ? 'تنظیمات ادمین' : 'پیش‌فرض داخلی')); $this->line('تعداد محصولات واجد شرایط: ' . $info['eligible_products']); $this->line('مقصدهای فعال (آماده ارسال): ' . (implode(', ', $info['active_targets']) ?: '— (هیچ)')); diff --git a/app/Http/Controllers/Admin/SettingsController.php b/app/Http/Controllers/Admin/SettingsController.php index fae116b..a5573a5 100644 --- a/app/Http/Controllers/Admin/SettingsController.php +++ b/app/Http/Controllers/Admin/SettingsController.php @@ -4,6 +4,7 @@ namespace App\Http\Controllers\Admin; use App\Http\Controllers\Controller; use App\Models\Setting; +use App\Services\PriceChannelBroadcastService; use Illuminate\Http\Request; class SettingsController extends Controller @@ -59,6 +60,8 @@ class SettingsController extends Controller return response()->json(['message' => 'Forbidden'], 403); } + $previousValue = $setting->exists ? (string) ($setting->value ?? '') : null; + $setting->value = $request->value; $setting->description = $request->description; if ($request->has('is_active')) { @@ -72,6 +75,15 @@ class SettingsController extends Controller } $setting->save(); + if ( + $request->key === 'price_channel_message_text' + && $previousValue !== (string) ($request->value ?? '') + ) { + dispatch(function () { + app(PriceChannelBroadcastService::class)->broadcastAfterTemplateChange(); + })->afterResponse(); + } + if ($isNew && $isSystemDeploy) { $projectName = Setting::where('key', 'name_fa')->value('value') ?: 'پروژه'; $settingTitle = trim($request->title_fa ?? '') ?: $request->key; diff --git a/app/Services/PriceChannelBroadcastService.php b/app/Services/PriceChannelBroadcastService.php index b51ce08..d3b5e9a 100644 --- a/app/Services/PriceChannelBroadcastService.php +++ b/app/Services/PriceChannelBroadcastService.php @@ -89,8 +89,8 @@ TXT; return; } - // شرط ۲: قیمت تابلو نسبت به آخرین ارسال واقعاً تغییر کرده باشد - $signature = $this->priceSignature($boardProduct); + // شرط ۲: قیمت تابلو یا قالب پیام نسبت به آخرین ارسال واقعاً تغییر کرده باشد + $signature = $this->broadcastSignature($boardProduct); if ($signature === Cache::get(self::SIGNATURE_CACHE_KEY)) { return; } @@ -123,12 +123,9 @@ TXT; } /** - * امضای قیمت — روی «بدنهٔ نمایشیِ» پیام (بدون هدر/ساعت) گرفته می‌شود تا دقیقاً همان چیزی - * که کاربر می‌بیند مبنای تشخیص تغییر باشد؛ اختلاف چند ریالیِ زیرِ آستانهٔ نمایش پیام تکراری نمی‌سازد. - * - * @param array $products + * امضای ارسال — قیمت تابلو + قالب پیام؛ تغییر هر کدام باید ارسال بعدی را مجاز کند. */ - private function priceSignature(Product $boardProduct): string + private function broadcastSignature(Product $boardProduct): string { $prices = $this->computeDisplayPrices($boardProduct); @@ -137,9 +134,63 @@ TXT; $prices['gram_sell'], $prices['mesghal_buy'], $prices['mesghal_sell'], + $this->messageTemplate(), ])); } + /** + * پس از ذخیرهٔ قالب در ادمین — یک بار فوری ارسال (بدون cooldown و بدون چک امضا). + */ + public function broadcastAfterTemplateChange(): void + { + try { + if (! $this->config->getBool('price_channel_enabled', false)) { + return; + } + + $targets = $this->resolveActiveTargets(); + if ($targets === []) { + return; + } + + $lock = Cache::lock(self::SEND_LOCK_KEY, 30); + if (! $lock->get()) { + return; + } + + try { + $products = $this->eligibleProducts(); + $boardProduct = $this->resolveBoardProduct($products); + if ($boardProduct === null || (int) ($boardProduct->price ?? 0) <= 0) { + return; + } + + $message = $this->buildMessage($products, $boardProduct); + if ($message === '') { + return; + } + + $results = []; + foreach ($targets as $messenger => $target) { + $results[$messenger] = $this->dispatchToMessenger($messenger, $target['token'], $target['chat_ids'], $message); + } + + $signature = $this->broadcastSignature($boardProduct); + $this->markSent(); + Cache::put(self::SIGNATURE_CACHE_KEY, $signature, now()->addDay()); + + Log::info('PriceChannel: قالب پیام تغییر کرد — ارسال فوری به کانال', [ + 'targets' => array_keys($targets), + 'results' => $results, + ]); + } finally { + $lock->release(); + } + } catch (\Throwable $e) { + Log::warning('PriceChannel template broadcast failed', ['message' => $e->getMessage()]); + } + } + /** * ارسال دستی (عیب‌یابی) — cooldown و شرط تغییر قیمت را نادیده می‌گیرد. * وضعیت روشن/خاموش، انتخاب پیام‌رسان، توکن و مقصد همچنان لازم است. @@ -163,7 +214,7 @@ TXT; $products = $this->eligibleProducts(); $boardProduct = $this->resolveBoardProduct($products); if ($boardProduct !== null) { - Cache::put(self::SIGNATURE_CACHE_KEY, $this->priceSignature($boardProduct), now()->addDay()); + Cache::put(self::SIGNATURE_CACHE_KEY, $this->broadcastSignature($boardProduct), now()->addDay()); } } @@ -197,6 +248,7 @@ TXT; } $message = $this->buildMessage(); + $fromConfig = trim((string) $this->config->getString('price_channel_message_text', '')); return [ 'enabled' => $this->config->getBool('price_channel_enabled', false), @@ -206,6 +258,7 @@ TXT; 'eligible_products' => count($this->eligibleProducts()), 'messengers' => $messengers, 'active_targets' => array_keys($this->resolveActiveTargets()), + 'template_source' => $fromConfig !== '' ? 'db' : 'default', 'message_preview' => $message, ]; }