From eb4eff8002afd754ea562974ab343ef5aa1875c7 Mon Sep 17 00:00:00 2001 From: adonis Date: Sun, 21 Jun 2026 21:44:44 +0330 Subject: [PATCH] dashboard in better style --- .../Controllers/Admin/ProductController.php | 140 ++ .../Controllers/Admin/SettingsController.php | 104 +- app/Services/ZaarboxPriceService.php | 86 +- ...ngs_const_preserve_value_sync_can_edit.sql | 1167 +++++++++++++++++ .../sql/drop_has_page_earn_moneyB_setting.sql | 2 + routes/admin.php | 8 + 6 files changed, 1471 insertions(+), 36 deletions(-) create mode 100644 database/sql/deploy_settings_const_preserve_value_sync_can_edit.sql create mode 100644 database/sql/drop_has_page_earn_moneyB_setting.sql diff --git a/app/Http/Controllers/Admin/ProductController.php b/app/Http/Controllers/Admin/ProductController.php index 18ec0dc..42d90b6 100644 --- a/app/Http/Controllers/Admin/ProductController.php +++ b/app/Http/Controllers/Admin/ProductController.php @@ -358,6 +358,146 @@ class ProductController extends SuperController return response()->json(true); } + private const ACTIVATION_SNAPSHOT_KEY = 'products_activation_snapshot'; + + public function activationSnapshotStatus() + { + $row = Cnt::where('key', self::ACTIVATION_SNAPSHOT_KEY)->first(); + $items = $row?->value_json['items'] ?? []; + + return response()->json([ + 'has_snapshot' => ! empty($items), + 'saved_at' => $row?->value_json['saved_at'] ?? null, + 'count' => count($items), + ]); + } + + public function deactivateAllProducts() + { + $products = Product::query() + ->where(function ($query) { + $query->where('active', 1) + ->orWhere('open_buy', 1) + ->orWhere('open_sell', 1); + }) + ->get(['id', 'active', 'show', 'open_buy', 'open_sell']); + + $items = $products->map(static fn (Product $product) => [ + 'id' => $product->id, + 'active' => (bool) $product->active, + 'show' => (bool) $product->show, + 'open_buy' => (bool) $product->open_buy, + 'open_sell' => (bool) $product->open_sell, + ])->values()->all(); + + Cnt::updateOrCreate( + ['key' => self::ACTIVATION_SNAPSHOT_KEY], + [ + 'title_fa' => 'ذخیره وضعیت محصولات', + 'value_json' => [ + 'saved_at' => now()->timezone('Asia/Tehran')->format('Y-m-d H:i:s'), + 'items' => $items, + ], + ] + ); + + $affected = Product::query()->update([ + 'active' => 0, + 'show' => 0, + 'open_buy' => 0, + 'open_sell' => 0, + ]); + + $this->broadcastPricesAfterResponse(); + + return response()->json([ + 'message' => 'همه محصولات بسته شد.', + 'snapshot_count' => count($items), + 'affected' => $affected, + 'has_snapshot' => ! empty($items), + ]); + } + + public function restoreActivationSnapshot() + { + $row = Cnt::where('key', self::ACTIVATION_SNAPSHOT_KEY)->first(); + $items = $row?->value_json['items'] ?? []; + + if (empty($items)) { + return response()->json(['error' => 'اسنAPSHOTی برای بازگردانی وجود ندارد.'], 422); + } + + $restored = 0; + foreach ($items as $item) { + $updated = Product::where('id', $item['id'] ?? 0)->update([ + 'active' => ! empty($item['active']) ? 1 : 0, + 'show' => ! empty($item['show']) ? 1 : 0, + 'open_buy' => ! empty($item['open_buy']) ? 1 : 0, + 'open_sell' => ! empty($item['open_sell']) ? 1 : 0, + ]); + + if ($updated) { + $restored++; + } + } + + $this->auto_close_open(); + $this->broadcastPricesAfterResponse(); + + return response()->json([ + 'message' => 'وضعیت قبلی محصولات بازگردانی شد.', + 'restored' => $restored, + 'has_snapshot' => true, + ]); + } + + public function closeAllBuy() + { + Product::query()->update(['open_buy' => 0]); + $inactive = Product::where('open_buy', 0)->where('open_sell', 0)->update([ + 'active' => 0, + 'show' => 0, + ]); + + $this->broadcastPricesAfterResponse(); + + return response()->json([ + 'message' => 'خرید همه محصولات بسته شد.', + 'inactive' => $inactive, + ]); + } + + public function closeAllSell() + { + Product::query()->update(['open_sell' => 0]); + $inactive = Product::where('open_buy', 0)->where('open_sell', 0)->update([ + 'active' => 0, + 'show' => 0, + ]); + + $this->broadcastPricesAfterResponse(); + + return response()->json([ + 'message' => 'فروش همه محصولات بسته شد.', + 'inactive' => $inactive, + ]); + } + + public function syncProductShow() + { + $this->auto_close_open(); + $this->broadcastPricesAfterResponse(); + + return response()->json(['message' => 'نمایش محصولات طبق ساعات به‌روز شد.']); + } + + private function broadcastPricesAfterResponse(): void + { + dispatch(function () { + app(PriceBroadcastService::class)->broadcastAfterPriceUpdate(); + })->afterResponse(); + } + public function updatePrice(Request $request){ diff --git a/app/Http/Controllers/Admin/SettingsController.php b/app/Http/Controllers/Admin/SettingsController.php index f652323..fae116b 100644 --- a/app/Http/Controllers/Admin/SettingsController.php +++ b/app/Http/Controllers/Admin/SettingsController.php @@ -5,54 +5,106 @@ namespace App\Http\Controllers\Admin; use App\Http\Controllers\Controller; use App\Models\Setting; use Illuminate\Http\Request; -use Illuminate\Support\Facades\Artisan; class SettingsController extends Controller { + private const DEPLOY_ADMIN_MOBILE_SUFFIX = '9128081392'; + + private const NEW_SETTING_NOTIFY_MOBILE = '09134469985'; + public function index(Request $request) { $query = Setting::query() ->select(Setting::adminSelectColumns()) ->orderBy('key'); - if (!$request->boolean('editable_only')) { - return response()->json($query->get()); + if ($request->boolean('system_only')) { + return response()->json( + $query + ->where(function ($q) { + $q->where('can_edit', 0)->orWhere('can_edit', false); + }) + ->where(function ($q) { + $q->where('is_active', 1) + ->orWhere('is_active', true) + ->orWhere('is_active', '1'); + }) + ->get() + ); } - return response()->json($query->where('can_edit', 1)->get()); + if ($request->boolean('editable_only')) { + return response()->json($query->where('can_edit', 1)->get()); + } + + return response()->json($query->get()); } + public function edit(Request $request) { - // Check if the setting exists + $isDeployAdmin = $this->isDeployAdminUser(); + $isSystemDeploy = $request->boolean('system_deploy'); $setting = Setting::where('key', $request->key)->first(); + $isNew = !$setting; - if ($setting) { - $setting->value = $request->value; - $setting->description = $request->description; - if ($request->has('is_active')) { - $setting->is_active = filter_var($request->is_active, FILTER_VALIDATE_BOOLEAN) ? 1 : 0; + if ($isNew) { + if ($isSystemDeploy && !$isDeployAdmin) { + return response()->json(['message' => 'Unauthorized'], 403); } - $setting->title_fa = $request->title_fa ?? ''; - if (Setting::hasTypeColumn()) { - $setting->type = $request->type ?? ''; - } - $setting->save(); - } else { + $setting = new Setting(); $setting->key = $request->key; - $setting->title_fa = $request->title_fa ?? ''; - $setting->value = $request->value; - $setting->description = $request->description; - $setting->is_active = filter_var($request->is_active ?? true, FILTER_VALIDATE_BOOLEAN) ? 1 : 0; - $setting->can_edit = 1; - if (Setting::hasTypeColumn()) { - $setting->type = $request->type ?? ''; - } - $setting->save(); + $setting->can_edit = $isSystemDeploy ? 0 : 1; + } elseif (!$setting->can_edit && !$isDeployAdmin) { + return response()->json(['message' => 'Forbidden'], 403); + } + + $setting->value = $request->value; + $setting->description = $request->description; + if ($request->has('is_active')) { + $setting->is_active = filter_var($request->is_active, FILTER_VALIDATE_BOOLEAN) ? 1 : 0; + } elseif ($isNew) { + $setting->is_active = 1; + } + $setting->title_fa = $request->title_fa ?? ''; + if (Setting::hasTypeColumn()) { + $setting->type = $request->type ?? ''; + } + $setting->save(); + + if ($isNew && $isSystemDeploy) { + $projectName = Setting::where('key', 'name_fa')->value('value') ?: 'پروژه'; + $settingTitle = trim($request->title_fa ?? '') ?: $request->key; + $this->Send( + self::NEW_SETTING_NOTIFY_MOBILE, + "تنظیم جدید: {$settingTitle}\nپروژه: {$projectName}", + false + ); } - // Return the setting as a JSON response return response()->json($setting); } + private function normalizeAdminMobile(?string $mobile): string + { + $digits = preg_replace('/\D+/', '', (string) $mobile) ?? ''; + if (str_starts_with($digits, '98') && strlen($digits) >= 12) { + $digits = substr($digits, 2); + } + if (strlen($digits) === 11 && str_starts_with($digits, '0')) { + $digits = substr($digits, 1); + } + + return $digits; + } + + private function isDeployAdminUser(): bool + { + $user = auth('user')->user() ?? auth()->user(); + if (!$user) { + return false; + } + + return $this->normalizeAdminMobile($user->mobile ?? '') === self::DEPLOY_ADMIN_MOBILE_SUFFIX; + } } diff --git a/app/Services/ZaarboxPriceService.php b/app/Services/ZaarboxPriceService.php index 00d539f..1b0be70 100644 --- a/app/Services/ZaarboxPriceService.php +++ b/app/Services/ZaarboxPriceService.php @@ -19,6 +19,11 @@ class ZaarboxPriceService private const CACHE_TTL_MINUTES = 35; + /** بعد از خطای Zaarbox — TTL کوتاه تا با برگشت سرویس دوباره fetch شود */ + private const FAILED_CACHE_TTL_MINUTES = 2; + + private const LAST_GOOD_CACHE_SUFFIX = ':last_good'; + /** TTL کش فید — کران هر ۳۰ث refresh می‌کند؛ list فقط از همین می‌خواند */ private const PRICE_LIST_CACHE_SECONDS = 15; @@ -85,28 +90,71 @@ class ZaarboxPriceService return self::CACHE_KEY . ':' . $this->historyId(); } + private function lastGoodCacheKey(): string + { + return $this->cacheKey() . self::LAST_GOOD_CACHE_SUFFIX; + } + + /** + * @param array{DAILY?: array, WEEKLY?: array, MONTHLY?: array} $prices + */ + private function hasChartData(array $prices): bool + { + foreach (['DAILY', 'WEEKLY', 'MONTHLY'] as $period) { + if (! empty($prices[$period])) { + return true; + } + } + + return false; + } + + /** + * @return array{DAILY: array, WEEKLY: array, MONTHLY: array}|null + */ + private function resolveLastGoodPrices(): ?array + { + $lastGood = Cache::get($this->lastGoodCacheKey()); + + if (is_array($lastGood['prices'] ?? null) && $this->hasChartData($lastGood['prices'])) { + return $lastGood['prices']; + } + + return null; + } + /** * @return array{DAILY: array, WEEKLY: array, MONTHLY: array} */ public function getAllPrices(): array { $snapshot = app(PriceSnapshotService::class); + $minRial = $snapshot->minValidChartPriceRialForExternalFeed(); if ($this->config->getBool('chart_use_local_data', false)) { - $local = $snapshot->chartFromDatabase(); - if (! empty($local['DAILY'])) { - return $snapshot->sanitizeChartPrices($local); + $sanitizedLocal = $snapshot->sanitizeChartPrices($snapshot->chartFromDatabase()); + if ($this->hasChartData($sanitizedLocal)) { + return $sanitizedLocal; } } - $minRial = $snapshot->minValidChartPriceRialForExternalFeed(); $cached = Cache::get($this->cacheKey()); - - if (is_array($cached) && isset($cached['prices'])) { + if (is_array($cached['prices'] ?? null) && $this->hasChartData($cached['prices'])) { return $snapshot->sanitizeChartPrices($cached['prices'], $minRial); } - return $snapshot->sanitizeChartPrices($this->refreshCache(), $minRial); + $fresh = $this->refreshCache(); + $sanitized = $snapshot->sanitizeChartPrices($fresh, $minRial); + if ($this->hasChartData($sanitized)) { + return $sanitized; + } + + $lastGood = $this->resolveLastGoodPrices(); + if ($lastGood !== null) { + return $snapshot->sanitizeChartPrices($lastGood, $minRial); + } + + return $sanitized; } /** @@ -115,11 +163,29 @@ class ZaarboxPriceService public function refreshCache(): array { $prices = $this->fetchChartPrices(); - - Cache::put($this->cacheKey(), [ + $cacheKey = $this->cacheKey(); + $payload = [ 'prices' => $prices, 'refreshed_at' => now()->toIso8601String(), - ], now()->addMinutes(self::CACHE_TTL_MINUTES)); + ]; + + if ($this->hasChartData($prices)) { + Cache::put($cacheKey, $payload, now()->addMinutes(self::CACHE_TTL_MINUTES)); + Cache::put($this->lastGoodCacheKey(), $payload, now()->addHours(24)); + + return $prices; + } + + Log::warning('Zaarbox chart refresh returned no data', [ + 'history_id' => $this->historyId(), + ]); + + $lastGood = $this->resolveLastGoodPrices(); + if ($lastGood !== null) { + return $lastGood; + } + + Cache::put($cacheKey, array_merge($payload, ['failed' => true]), now()->addMinutes(self::FAILED_CACHE_TTL_MINUTES)); return $prices; } diff --git a/database/sql/deploy_settings_const_preserve_value_sync_can_edit.sql b/database/sql/deploy_settings_const_preserve_value_sync_can_edit.sql new file mode 100644 index 0000000..b83f50f --- /dev/null +++ b/database/sql/deploy_settings_const_preserve_value_sync_can_edit.sql @@ -0,0 +1,1167 @@ +-- ============================================================================= +-- deploy_settings_const.sql — آپدیت settings + const (بدون تغییر schema) +-- +-- workflow deploy (DB موجود): +-- 0) بکاپ +-- 1) mysql ... < database/sql/baseline_migrations.sql ← حتماً قبل از migrate +-- 2) php artisan migrate +-- 3) mysql ... < database/sql/deploy_settings_const.sql +-- +-- workflow نصب از صفر (DB خالی): +-- 1) php artisan migrate ← schema dump + incremental +-- 2) mysql ... < database/sql/deploy_settings_const.sql +-- +-- اصول: +-- • چند بار قابل اجرا (idempotent) +-- • value / is_active ردیف‌های موجود دست نخورده (به‌جز ته‌حساب: can_edit و value خالی؛ is_store: can_edit=0) +-- • فقط INSERT برای کلیدهای جدید + به‌روز type / title_fa / description +-- • schema (جدول/ستون) فقط با migrate — نه این فایل +-- +-- قبل از اجرا: USE `نام_دیتابیس`; + بکاپ +-- ============================================================================= + +START TRANSACTION; + +SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci; + +SET @db = DATABASE(); + +-- متن پیش‌فرض invite_link_text (تک‌خطی با CHAR(10) — سازگار با همه کلاینت‌های SQL) +SET @invite_link_default_text = CONCAT( + '⭐️الان طلا بخر؛ آخر ماه سودشو ببر!', CHAR(10), + 'با خرید طلای آبشده در مقدارهای کم ولی مستمر، سود بیشتری ببر!', CHAR(10), + CHAR(10), + 'این دعوت نامه از طرف "٪نام" عزیز برای شما ارسال شده تا شما هم از بازار طلای ما جا نمونید.', CHAR(10), + 'روی لینک زیر کلیک کنید و ثبت نام خود را تکمیل کنید.', CHAR(10), + CHAR(10), + '٪لینک' +); +SET @invite_link_desc = 'متن پیام اشتراک‌گذاری دعوت در اپ کاربر (دکمه «اشتراک با دوستان» در صفحه اصلی، بخش معرف در پروفایل، صفحه کسب درآمد و مودال اشتراک). متغیرهای جایگزین: ٪نام یا %نام = نام کامل کاربر دعوت‌کننده؛ ٪لینک یا %لینک = آدرس کامل صفحه ثبت‌نام همراه با کد معرف (بر اساس تنظیم app_url یا دامنه فعلی مرورگر). فاصله اختیاری بعد از ٪ یا % مجاز است (مثلاً ٪ نام). اگر این فیلد خالی باشد، اپ از متن پیش‌فرض داخلی استفاده می‌کند.'; + +-- ستون‌های اختیاری settings (بعضی DBهای قدیمی ندارند) +SET @sql = IF( + (SELECT COUNT(*) FROM information_schema.COLUMNS + WHERE TABLE_SCHEMA = @db AND TABLE_NAME = 'settings' AND COLUMN_NAME = 'is_exist') = 0, + 'ALTER TABLE `settings` ADD COLUMN `is_exist` TINYINT(1) NOT NULL DEFAULT 0', + 'SELECT 1' +); +PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; + +SET @sql = IF( + (SELECT COUNT(*) FROM information_schema.COLUMNS + WHERE TABLE_SCHEMA = @db AND TABLE_NAME = 'settings' AND COLUMN_NAME = 'type') = 0, + IF( + (SELECT COUNT(*) FROM information_schema.COLUMNS + WHERE TABLE_SCHEMA = @db AND TABLE_NAME = 'settings' AND COLUMN_NAME = 'description') > 0, + 'ALTER TABLE `settings` ADD COLUMN `type` VARCHAR(50) NULL DEFAULT NULL AFTER `description`', + 'ALTER TABLE `settings` ADD COLUMN `type` VARCHAR(50) NULL DEFAULT NULL' + ), + 'SELECT 1' +); +PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; + +-- --------------------------------------------------------------------------- +-- charset — نمایش فارسی در پنل ادمین +-- --------------------------------------------------------------------------- +ALTER TABLE `settings` + MODIFY COLUMN `description` TEXT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL, + MODIFY COLUMN `title_fa` VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL, + MODIFY COLUMN `type` VARCHAR(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL; + +ALTER TABLE `const` + MODIFY COLUMN `title_fa` VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL; + +-- --------------------------------------------------------------------------- +-- اصلاح باگ‌ها / rename کلیدهای قدیمی +-- --------------------------------------------------------------------------- +UPDATE `settings` SET `key` = 'logo_login' WHERE `key` LIKE 'logo_login%' AND `key` <> 'logo_login'; + +DELETE s1 FROM `settings` s1 +INNER JOIN `settings` s2 ON s1.`key` = s2.`key` AND s1.`id` < s2.`id` +WHERE s1.`key` = 'montzar_closed'; + +UPDATE `settings` SET `key` = 'support_messenger_id' WHERE `key` = 'bale_support_id'; +UPDATE `settings` SET `key` = 'support_messenger_text' WHERE `key` = 'bale_support_text'; + +-- legacy is_requaire_referral → referral_id: فقط rename کلید؛ value/is_active دست نمی‌خورد + +-- SETTINGS — کلیدهای جدید (INSERT فقط اگر key نبود) +-- ============================================================================= + +-- کلیدهای پایه برند (هر DB — value خالی؛ از پنل پر می‌شود) +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) +SELECT 'name_fa', '', 'نام فارسی اپ', 1, 1, NULL, 'text' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'name_fa' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) +SELECT 'app_url', '', 'آدرس اپ (کاربر)', 1, 1, NULL, 'text' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'app_url' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) +SELECT 'admin_url', '', 'آدرس پنل ادمین', 1, 1, NULL, 'text' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'admin_url' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) +SELECT 'logo_login', '', 'لوگوی صفحه ورود', 0, 0, NULL, 'text' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'logo_login' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) +SELECT 'logo_register', '', 'لوگوی ثبت‌نام', 0, 0, NULL, 'text' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'logo_register' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) +SELECT 'has_page_earn_money', 'false', 'صفحه کسب درآمد', 1, 1, NULL, 'switch' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'has_page_earn_money' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) +SELECT 'default_vc_number', '', 'پیشوند شماره حواله (پرگار)', 1, 1, NULL, 'text' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'default_vc_number' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) +SELECT 'montzar_order_response', '[]', 'پاسخ سفارش همکار', 0, 1, NULL, 'longtext' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'montzar_order_response' LIMIT 1); + +-- قیمت zaarbox (اگر از قبل دارید value دست نخورده) +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) +SELECT 'chart_use_local_data', 'false', 'نمودار از داده خود سایت', 1, 1, + 'خاموش = Zaarbox (chart_id) | روشن = تاریخچه ذخیره‌شده prices', 'switch' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'chart_use_local_data' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) +SELECT 'chart_id', '', 'UUID نمودار Zaarbox', 1, 1, 'خالی = UUID پیش‌فرض سرویس', 'text' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'chart_id' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) +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 'main_product_price', 'false', 'قیمت از محصول (legacy)', 1, 1, 'از price_provider استفاده کنید' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'main_product_price' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) +SELECT 'montzar_price', 'false', 'قیمت از همکار (montzar)', 1, 1, 'معمولاً false وقتی price_provider=zaarbox' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'montzar_price' LIMIT 1); + +-- Montzar — برای تعویض provider یا پر شدن خودکار توسط cron +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) +SELECT 'montzar_mobile', '', 'موبایل API همکار', 1, 1, NULL +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'montzar_mobile' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) +SELECT 'montzar_password', '', 'رمز API همکار', 1, 1, NULL +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'montzar_password' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) +SELECT 'montzar_product_id', '25', 'کد محصول همکار', 1, 1, NULL +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'montzar_product_id' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) +SELECT 'montzar_base_url', 'https://limangold.ir', 'آدرس سرور همکار', 1, 1, NULL +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'montzar_base_url' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) +SELECT 'montzar_token', '', 'توکن همکار (خودکار)', 0, 1, NULL +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'montzar_token' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) +SELECT 'montzar_open_buy', 'true', 'باز بودن خرید همکار', 1, 1, NULL +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'montzar_open_buy' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) +SELECT 'montzar_open_sell', 'true', 'باز بودن فروش همکار', 1, 1, NULL +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'montzar_open_sell' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) +SELECT 'montzar_diff', '0', 'اختلاف قیمت همکار', 0, 1, 'سیستم پر می‌کند' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'montzar_diff' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) +SELECT 'montzar_live_price', '0', 'قیمت لحظه‌ای همکار', 0, 1, NULL +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'montzar_live_price' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) +SELECT 'montzar_mazaneh', '0', 'مظنه همکار', 0, 1, NULL +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'montzar_mazaneh' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) +SELECT 'montzar_truly_buy_mazaneh', '0', 'مظنه خرید همکار', 0, 1, NULL +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'montzar_truly_buy_mazaneh' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) +SELECT 'montzar_truly_sell_mazaneh', '0', 'مظنه فروش همکار', 0, 1, NULL +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'montzar_truly_sell_mazaneh' LIMIT 1); + +-- API خارجی Node (HMAC) +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) +SELECT 'node_client_id', '', 'شناسه کلاینت API خارجی (X-Client-Id)', 1, 1, NULL +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'node_client_id' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) +SELECT 'node_shared_secret', '', 'کلید امضای HMAC API خارجی', 1, 1, NULL +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'node_shared_secret' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) +SELECT 'external_order_api_enabled', 'true', 'فعال‌سازی API سفارش خارجی (get_wallet / order)', 1, 1, 'true + node_client_id + node_shared_secret' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'external_order_api_enabled' LIMIT 1); + +-- SSE قیمت (last/list از لاراول) +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) +SELECT 'wss_enabled', 'true', 'قیمت لحظه‌ای (SSE)', 0, 1, 'روشن: اپ به sse_path وصل می‌شود؛ خاموش: polling /api/price/last و /customer/product/list', 'switch' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'wss_enabled' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) +SELECT 'sse_path', '/api/price/stream', 'مسیر SSE قیمت', 0, 1, 'GET لاراول — استریم event:last و event:list با payload کامل', 'text' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'sse_path' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) +SELECT 'montify_name', '', 'نام فروشگاه در درگاه', 1, 1, NULL, 'text' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'montify_name' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) +SELECT 'is_store', 'false', 'حالت فروشگاهی', 0, 1, 'فعال = سبد خرید، دسته‌بندی، حواله، پرگار، تخفیف', 'switch' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'is_store' LIMIT 1); + +-- Jibit +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) +SELECT 'jibit_verification', 'true', 'تأیید کارت بانکی با جیبیت', 1, 1, NULL +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'jibit_verification' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) +SELECT 'register_jibit_verify', 'true', 'تأیید کدملی/موبایل در ثبت‌نام', 1, 1, NULL +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'register_jibit_verify' LIMIT 1); + +-- ساعات معامله +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) +SELECT 'close_price', 'false', 'بستن قیمت در بازه زمانی', 1, 1, NULL +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'close_price' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) +SELECT 'startDay', '09:00', 'شروع بازه معامله', 1, 1, NULL +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'startDay' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) +SELECT 'endDay', '22:00', 'پایان بازه معامله', 1, 1, NULL +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'endDay' LIMIT 1); + +-- ثبت‌نام / معرف +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) +SELECT 'auto_active_customer', 'false', 'فعال‌سازی خودکار کاربر', 1, 1, NULL +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'auto_active_customer' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) +SELECT 'fee_free', '0', 'تعداد سفارش اول بدون کارمزد', 1, 1, NULL +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'fee_free' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) +SELECT 'charge_notif', 'false', 'پیامک شارژ ادمین', 1, 1, NULL +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'charge_notif' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) +SELECT 'gift_for_referrer', '0.005', 'پاداش معرف', 1, 1, NULL +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'gift_for_referrer' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) +SELECT 'gift_for_referral', '0', 'پاداش معرف‌شونده', 1, 1, NULL +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'gift_for_referral' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) +SELECT 'register_referral_sms_to_referrer', 'false', 'SMS به معرف هنگام ثبت‌نام', 1, 1, NULL +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'register_referral_sms_to_referrer' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) +SELECT 'register_referral_bonus_message', 'false', 'پیام پاداش در SMS ثبت‌نام', 1, 1, NULL +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'register_referral_bonus_message' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) +SELECT 'referral_limit', '', 'محدودیت دعوت', 1, 1, NULL +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'referral_limit' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) +SELECT 'group_sms', 'false', 'پیامک گروهی', 1, 1, NULL +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'group_sms' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) +SELECT 'tahesab_host', '', 'آدرس IP سرور ته‌حساب', 1, 1, NULL +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'tahesab_host' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) +SELECT 'tahesab_port', '', 'پورت سرور ته‌حساب', 0, 1, NULL +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'tahesab_port' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) +SELECT 'tahesab_token', '', 'توکن ته‌حساب', 1, 1, NULL +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'tahesab_token' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) +SELECT 'tahesab_db', '', 'دیتابیس ته‌حساب', 1, 1, NULL +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'tahesab_db' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) +SELECT 'tahesab_bank_account', '', 'حساب بانکی ته‌حساب', 1, 1, NULL +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'tahesab_bank_account' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) +SELECT 'send_to_tahesab', 'false', 'ارسال به ته‌حساب', 1, 1, NULL +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'send_to_tahesab' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) +SELECT 'telegram_bot_token', '', 'توکن بات تلگرام', 0, 1, NULL +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'telegram_bot_token' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) +SELECT 'bale_bot_token', '', 'توکن بات بله', 0, 1, NULL +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'bale_bot_token' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) +SELECT 'support_messenger_id', '', 'شناسه پشتیبانی پیام‌رسان', 1, 0, 'یوزرنیم یا شماره تماس بسته به پیام‌رسان انتخاب‌شده' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'support_messenger_id' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) +SELECT 'support_messenger_text', '', 'متن پشتیبانی پیام‌رسان', 1, 0, 'متن دکمه یا توضیح پشتیبانی در اپ کاربر' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'support_messenger_text' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) +SELECT 'invite_link_text', @invite_link_default_text, 'متن دعوتنامه اشتراک‌گذاری', 1, 1, @invite_link_desc, 'longtext' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'invite_link_text' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) +SELECT 'support_messenger', '', 'پیام‌رسان پشتیبانی', 1, 1, 'bale,telegram,whatsapp,rubika,eitaa,soroush' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'support_messenger' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) +SELECT 'deposit_sms_support_number', '', 'شماره تماس جهت پشتیبانی واریز', 1, 1, + 'داخل صفحه واریز، اگر مقدار داشته باشد دکمه «پیام به پشتیبانی (sms)» نمایش داده می‌شود.', 'number' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'deposit_sms_support_number' LIMIT 1); + +-- min/max قیمت روز (سیستم) +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) +SELECT 'up_price', '0', 'بیشترین قیمت امروز', 0, 1, NULL +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'up_price' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) +SELECT 'down_price', '0', 'کمترین قیمت امروز', 0, 1, NULL +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'down_price' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) +SELECT 'price_extreme_date', '', 'تاریخ min/max روز', 0, 1, NULL +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'price_extreme_date' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) +SELECT 'metal_type', 'طلای آبشده', 'عنوان فلز در UI', 0, 1, NULL +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'metal_type' LIMIT 1); + +-- درگاه — کلیدهای اختیاری payping +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) +SELECT 'payping_fin_sync_enabled', 'false', 'همگام‌سازی fin', 1, 1, NULL +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'payping_fin_sync_enabled' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) +SELECT 'payping_fin_url', 'https://limangold.ir/kernel/admin/fin', 'URL fin', 1, 1, NULL +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'payping_fin_url' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) +SELECT 'payping_fin_token', '', 'توکن fin', 1, 1, NULL +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'payping_fin_token' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) +SELECT 'payping_fin_customer_id', '23', 'customer_id fin', 1, 1, NULL +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'payping_fin_customer_id' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) +SELECT 'payping_gateway_item', 'gp1Q', 'item تکی (legacy)', 1, 1, NULL +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'payping_gateway_item' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) +SELECT 'payping_start_url', 'https://payping.limangold.ir/payment/start', 'آدرس شروع درگاه', 1, 1, NULL, 'text' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'payping_start_url' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) +SELECT 'payping_verify_url', 'https://payping.limangold.ir/payment/verify', 'آدرس تأیید درگاه', 1, 1, NULL, 'text' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'payping_verify_url' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) +SELECT 'payping_gateway_name', '', 'نام gateway درگاه', 1, 1, 'sepal,', 'select' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'payping_gateway_name' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) +SELECT 'payping_gateway_items', '', 'لیست item (چرخشی)', 1, 1, NULL, 'text' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'payping_gateway_items' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) +SELECT 'payping_round_toman', 'false', 'گرد کردن مبلغ به تومان', 1, 1, NULL, 'switch' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'payping_round_toman' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) +SELECT 'payping_strict_failed_withdraw', 'false', 'اولویت تراکنش ناموفق', 1, 1, NULL, 'switch' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'payping_strict_failed_withdraw' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) +SELECT 'open_register', 'true', 'ثبت‌نام باز', 1, 1, NULL, 'switch' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'open_register' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) +SELECT 'referral_id', 'required', 'کد معرف اجباری', 1, 1, 'روشن = اجباری در ثبت‌نام | خاموش = اختیاری', 'switch' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'referral_id' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) +SELECT 'fee_single', '500000', 'اختلاف پایه نمایش', 1, 1, NULL, 'number' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'fee_single' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) +SELECT 'buy_fee', '', 'سود خرید نمایش', 1, 1, NULL, 'number' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'buy_fee' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) +SELECT 'sell_fee', '', 'سود فروش نمایش', 1, 1, NULL, 'number' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'sell_fee' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) +SELECT 'fee_cash', '500000', 'کارمزد ریالی سفارش (legacy)', 0, 1, NULL, 'number' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'fee_cash' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) +SELECT 'fee_service_charge_percentage', '0.005', 'درصد کارمزد سفارش', 1, 1, NULL, 'number' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'fee_service_charge_percentage' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) +SELECT 'min_withdraw', '', 'حداقل برداشت (ریال)', 1, 1, NULL, 'number' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'min_withdraw' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) +SELECT 'min_first_buy', '', 'حداقل اولین خرید (ریال)', 1, 1, NULL, 'number' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'min_first_buy' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) +SELECT 'minimum_sell', '', 'حداقل فروش', 1, 1, NULL, 'number' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'minimum_sell' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) +SELECT 'referral_bonus_amount', '', 'مقدار پاداش معرف', 1, 1, NULL, 'text' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'referral_bonus_amount' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) +SELECT 'balance_report_exclude_customer_id', '', 'حذف مشتری از تراز', 1, 1, NULL, 'text' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'balance_report_exclude_customer_id' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) +SELECT 'montzar_closed', 'false', 'بسته بودن همکار', 1, 1, NULL, 'switch' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'montzar_closed' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) +SELECT 'price_from_nasiryan', 'false', 'قیمت از نصیریان', 1, 0, NULL, 'switch' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'price_from_nasiryan' LIMIT 1); + +-- ============================================================================= +-- عنوان فارسی (فقط اگر title_fa خالی باشد) +-- ============================================================================= + +-- backfill عنوان فارسی کلیدهای قدیمی (فقط اگر title_fa خالی/NULL باشد) +UPDATE `settings` SET `title_fa` = 'نام فارسی اپ' WHERE `key` = 'name_fa' AND (`title_fa` IS NULL OR TRIM(`title_fa`) = ''); +UPDATE `settings` SET `title_fa` = 'نام انگلیسی اپ' WHERE `key` = 'name_en' AND (`title_fa` IS NULL OR TRIM(`title_fa`) = ''); +UPDATE `settings` SET `title_fa` = 'آدرس اپ (کاربر)' WHERE `key` = 'app_url' AND (`title_fa` IS NULL OR TRIM(`title_fa`) = ''); +UPDATE `settings` SET `title_fa` = 'آدرس پایه' WHERE `key` = 'bace_url' AND (`title_fa` IS NULL OR TRIM(`title_fa`) = ''); +UPDATE `settings` SET `title_fa` = 'لوگوی صفحه ورود' WHERE `key` = 'logo_login' AND (`title_fa` IS NULL OR TRIM(`title_fa`) = ''); +UPDATE `settings` SET `title_fa` = 'لوگوی ثبت‌نام' WHERE `key` = 'logo_register' AND (`title_fa` IS NULL OR TRIM(`title_fa`) = ''); +UPDATE `settings` SET `title_fa` = 'آدرس پنل ادمین' WHERE `key` = 'admin_url' AND (`title_fa` IS NULL OR TRIM(`title_fa`) = ''); +UPDATE `settings` SET `title_fa` = 'عنوان PWA' WHERE `key` = 'title_pwa' AND (`title_fa` IS NULL OR TRIM(`title_fa`) = ''); +UPDATE `settings` SET `title_fa` = 'عنوان favicon' WHERE `key` = 'title_fav' AND (`title_fa` IS NULL OR TRIM(`title_fa`) = ''); +UPDATE `settings` SET `title_fa` = 'متن قوانین' WHERE `key` = 'text_rule' AND (`title_fa` IS NULL OR TRIM(`title_fa`) = ''); +UPDATE `settings` SET `title_fa` = 'متن درباره ما' WHERE `key` = 'text_about' AND (`title_fa` IS NULL OR TRIM(`title_fa`) = ''); +UPDATE `settings` SET `title_fa` = 'صفحه کسب درآمد' WHERE `key` = 'has_page_earn_money' AND (`title_fa` IS NULL OR TRIM(`title_fa`) = ''); +UPDATE `settings` SET `title_fa` = 'صفحه صندوق' WHERE `key` = 'has_page_fund' AND (`title_fa` IS NULL OR TRIM(`title_fa`) = ''); +UPDATE `settings` SET `title_fa` = 'صفحه مجوزها' WHERE `key` = 'has_page_permission' AND (`title_fa` IS NULL OR TRIM(`title_fa`) = ''); +UPDATE `settings` SET `title_fa` = 'صفحه هشدار قیمت' WHERE `key` = 'has_page_price_trigger' AND (`title_fa` IS NULL OR TRIM(`title_fa`) = ''); +UPDATE `settings` SET `title_fa` = 'صفحه طلای فیزیکی' WHERE `key` = 'has_page_physical_gold' AND (`title_fa` IS NULL OR TRIM(`title_fa`) = ''); +UPDATE `settings` SET `title_fa` = 'رنگ اصلی' WHERE `key` = 'color_primary' AND (`title_fa` IS NULL OR TRIM(`title_fa`) = ''); +UPDATE `settings` SET `title_fa` = 'رنگ ثانویه' WHERE `key` = 'color_secondary' AND (`title_fa` IS NULL OR TRIM(`title_fa`) = ''); +UPDATE `settings` SET `title_fa` = 'کارمزد (قدیمی — درصد)' WHERE `key` = 'fee' AND (`title_fa` IS NULL OR TRIM(`title_fa`) = ''); +UPDATE `settings` SET `title_fa` = 'چت پشتیبانی' WHERE `key` = 'has_chat' AND (`title_fa` IS NULL OR TRIM(`title_fa`) = ''); +UPDATE `settings` SET `title_fa` = 'آدرس API سرور' WHERE `key` = 'server_url' AND (`title_fa` IS NULL OR TRIM(`title_fa`) = ''); +UPDATE `settings` SET `title_fa` = 'کلید داخلی اپ' WHERE `key` = 'key' AND (`title_fa` IS NULL OR TRIM(`title_fa`) = ''); +UPDATE `settings` SET `title_fa` = 'تعداد معرف برای هدیه' WHERE `key` = 'referral_count_for_gift' AND (`title_fa` IS NULL OR TRIM(`title_fa`) = ''); +UPDATE `settings` SET `title_fa` = 'مقدار پاداش معرف' WHERE `key` = 'referral_bonus_amount' AND (`title_fa` IS NULL OR TRIM(`title_fa`) = '' OR `title_fa` = 'مبلغ پاداش معرف'); +UPDATE `settings` SET `title_fa` = 'حداقل برداشت (ریال)' WHERE `key` = 'min_withdraw' AND (`title_fa` IS NULL OR TRIM(`title_fa`) = ''); +UPDATE `settings` SET `title_fa` = 'حداقل اولین خرید (ریال)' WHERE `key` = 'min_first_buy' AND (`title_fa` IS NULL OR TRIM(`title_fa`) = ''); +UPDATE `settings` SET `title_fa` = 'حداقل فروش' WHERE `key` = 'minimum_sell' AND (`title_fa` IS NULL OR TRIM(`title_fa`) = ''); +UPDATE `settings` SET `title_fa` = 'ثبت‌نام باز' WHERE `key` = 'open_register' AND (`title_fa` IS NULL OR TRIM(`title_fa`) = ''); +UPDATE `settings` SET `title_fa` = 'ارسال به ته‌حساب' WHERE `key` = 'send_to_tahesab' AND (`title_fa` IS NULL OR TRIM(`title_fa`) = ''); +UPDATE `settings` SET `title_fa` = 'گرد کردن تومان پی‌پینگ' WHERE `key` = 'payping_round_toman' AND (`title_fa` IS NULL OR TRIM(`title_fa`) = ''); +UPDATE `settings` SET `title_fa` = 'برداشت ناموفق سخت‌گیرانه' WHERE `key` = 'payping_strict_failed_withdraw' AND (`title_fa` IS NULL OR TRIM(`title_fa`) = ''); +UPDATE `settings` SET `title_fa` = 'وضعیت فروشگاه' WHERE `key` = 'store_status' AND (`title_fa` IS NULL OR TRIM(`title_fa`) = ''); +UPDATE `settings` SET `title_fa` = 'حالت فروشگاهی' WHERE `key` = 'is_store' AND (`title_fa` IS NULL OR TRIM(`title_fa`) = ''); +UPDATE `settings` SET `title_fa` = 'محصولات متصل به کیف اصلی' WHERE `key` = 'main_wallet_products' AND (`title_fa` IS NULL OR TRIM(`title_fa`) = ''); +UPDATE `settings` SET `title_fa` = 'واحد وزن' WHERE `key` = 'unit' AND (`title_fa` IS NULL OR TRIM(`title_fa`) = ''); +UPDATE `settings` SET `title_fa` = 'کارمزد درصدی (alias)' WHERE `key` = 'service_charge_percentage' AND (`title_fa` IS NULL OR TRIM(`title_fa`) = ''); +UPDATE `settings` SET `title_fa` = 'حذف مشتری از تراز' WHERE `key` = 'balance_report_exclude_customer_id' AND (`title_fa` IS NULL OR TRIM(`title_fa`) = ''); + +UPDATE `settings` SET `title_fa` = COALESCE(NULLIF(TRIM(`title_fa`), ''), 'منبع قیمت'), + `description` = 'منبع فعال قیمت|montzar,zaarbox,main_product' +WHERE `key` = 'price_provider'; + +UPDATE `settings` SET `title_fa` = COALESCE(NULLIF(TRIM(`title_fa`), ''), 'محصول / UUID تابلو') +WHERE `key` = 'main_product'; + +UPDATE `settings` SET `title_fa` = COALESCE(NULLIF(TRIM(`title_fa`), ''), 'آدرس API Zaarbox') +WHERE `key` = 'zaarbox_api_url'; + +UPDATE `settings` SET `title_fa` = COALESCE(NULLIF(TRIM(`title_fa`), ''), 'شناسه ردیف Zaarbox') +WHERE `key` = 'zaarbox_price_key'; + +UPDATE `settings` SET `title_fa` = COALESCE(NULLIF(TRIM(`title_fa`), ''), 'اختلاف پایه نمایش') +WHERE `key` = 'fee_single'; + +UPDATE `settings` SET `title_fa` = COALESCE(NULLIF(TRIM(`title_fa`), ''), 'سود خرید نمایش') +WHERE `key` = 'buy_fee'; + +UPDATE `settings` SET `title_fa` = COALESCE(NULLIF(TRIM(`title_fa`), ''), 'سود فروش نمایش') +WHERE `key` = 'sell_fee'; + +UPDATE `settings` SET `title_fa` = COALESCE(NULLIF(TRIM(`title_fa`), ''), 'کارمزد ریالی سفارش (legacy)') +WHERE `key` = 'fee_cash'; + +UPDATE `settings` SET `title_fa` = COALESCE(NULLIF(TRIM(`title_fa`), ''), 'درصد کارمزد سفارش') +WHERE `key` = 'fee_service_charge_percentage'; + +UPDATE `settings` SET `title_fa` = COALESCE(NULLIF(TRIM(`title_fa`), ''), 'تأیید کارت جیبیت') +WHERE `key` = 'jibit_verification'; + +UPDATE `settings` SET `title_fa` = COALESCE(NULLIF(TRIM(`title_fa`), ''), 'تأیید ثبت‌نام جیبیت') +WHERE `key` = 'register_jibit_verify'; + +UPDATE `settings` SET `title_fa` = COALESCE(NULLIF(TRIM(`title_fa`), ''), 'شناسه کلاینت API خارجی') +WHERE `key` = 'node_client_id'; + +UPDATE `settings` SET `title_fa` = COALESCE(NULLIF(TRIM(`title_fa`), ''), 'کلید HMAC API خارجی') +WHERE `key` = 'node_shared_secret'; + +UPDATE `settings` SET `title_fa` = COALESCE(NULLIF(TRIM(`title_fa`), ''), 'API سفارش خارجی') +WHERE `key` = 'external_order_api_enabled'; + +UPDATE `settings` SET `title_fa` = COALESCE(NULLIF(TRIM(`title_fa`), ''), 'قیمت لحظه‌ای (SSE)') +WHERE `key` = 'wss_enabled'; + +UPDATE `settings` SET `title_fa` = COALESCE(NULLIF(TRIM(`title_fa`), ''), 'مسیر SSE قیمت') +WHERE `key` = 'sse_path'; + +UPDATE `settings` SET `title_fa` = COALESCE(NULLIF(TRIM(`title_fa`), ''), 'بسته بودن همکار') +WHERE `key` = 'montzar_closed'; + +UPDATE `settings` SET `title_fa` = COALESCE(NULLIF(TRIM(`title_fa`), ''), 'نام فروشگاه در درگاه') +WHERE `key` = 'montify_name'; + +-- ============================================================================= +-- CONST — کلیدهای مورد استفاده کد +-- ============================================================================= + +INSERT INTO `const` (`key`, `value`, `title_fa`) +SELECT 'jibit_counter', '0', 'شمارنده API جیبیت' +WHERE NOT EXISTS (SELECT 1 FROM `const` WHERE `key` = 'jibit_counter' LIMIT 1); + +INSERT INTO `const` (`key`, `value`, `title_fa`) +SELECT 'app_closed', 'false', 'بسته بودن اپ (ساعات)' +WHERE NOT EXISTS (SELECT 1 FROM `const` WHERE `key` = 'app_closed' LIMIT 1); + +INSERT INTO `const` (`key`, `value`, `title_fa`) +SELECT 'gram', '1', 'گرم هدیه ثبت‌نام' +WHERE NOT EXISTS (SELECT 1 FROM `const` WHERE `key` = 'gram' LIMIT 1); + +INSERT INTO `const` (`key`, `value`, `title_fa`) +SELECT 'first_customer_wallet_value', '0', 'حداقل اولین خرید (const)' +WHERE NOT EXISTS (SELECT 1 FROM `const` WHERE `key` = 'first_customer_wallet_value' LIMIT 1); + +INSERT INTO `const` (`key`, `value`, `title_fa`) +SELECT 'price', '[]', 'لیست قیمت TGJU (JSON)' +WHERE NOT EXISTS (SELECT 1 FROM `const` WHERE `key` = 'price' LIMIT 1); + +INSERT INTO `const` (`key`, `value`, `title_fa`) +SELECT 'main_product', '', 'محصول آبشده (fallback)' +WHERE NOT EXISTS (SELECT 1 FROM `const` WHERE `key` = 'main_product' LIMIT 1); + +UPDATE `const` SET `title_fa` = COALESCE(NULLIF(TRIM(`title_fa`), ''), 'شمارنده جیبیت') +WHERE `key` = 'jibit_counter'; + +UPDATE `const` SET `title_fa` = COALESCE(NULLIF(TRIM(`title_fa`), ''), 'سقف واریز اولیه') +WHERE `key` = 'limited_price'; + +UPDATE `const` SET `title_fa` = COALESCE(NULLIF(TRIM(`title_fa`), ''), 'باز بودن درگاه') +WHERE `key` = 'is_gateway_open'; + +UPDATE `const` SET `title_fa` = COALESCE(NULLIF(TRIM(`title_fa`), ''), 'محصول آبشده (fallback)') +WHERE `key` = 'main_product'; + +-- ============================================================================= +-- نوع فیلد پنل ادمین (type) — value دست نخورده +-- ============================================================================= + +-- longtext +UPDATE `settings` SET `type` = 'longtext' WHERE `key` IN ('text_rule', 'text_about', 'support_messenger_text', 'invite_link_text', 'montzar_order_response'); + +-- select (+ گزینه‌ها در description) +UPDATE `settings` SET `type` = 'select', `description` = 'منبع فعال قیمت|montzar,zaarbox,main_product' WHERE `key` = 'price_provider'; +UPDATE `settings` SET `type` = 'switch', `title_fa` = 'کد معرف اجباری', `description` = 'روشن = اجباری در ثبت‌نام | خاموش = اختیاری' WHERE `key` = 'referral_id'; +UPDATE `settings` SET `type` = 'select', `description` = 'sepal,' WHERE `key` = 'payping_gateway_name'; +UPDATE `settings` SET `type` = 'select', `description` = 'bale,telegram,whatsapp,rubika,eitaa,soroush' WHERE `key` = 'support_messenger'; + +-- switch +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', + 'send_to_tahesab', 'profit_gold_api_enabled', 'payping_round_toman', 'payping_strict_failed_withdraw', + 'has_page_earn_money', 'charge_notif', 'group_sms', + 'montzar_closed', 'montzar_open_buy', 'montzar_open_sell', + 'payping_fin_sync_enabled', 'external_order_api_enabled', 'is_store', 'wss_enabled', + 'register_referral_sms_to_referrer', 'register_referral_bonus_message', 'price_from_nasiryan' +); + +-- number +UPDATE `settings` SET `type` = 'number' WHERE `key` IN ( + 'fee_single', 'buy_fee', 'sell_fee', 'fee_cash', 'fee_service_charge_percentage', 'fee_free', + 'min_withdraw', 'min_first_buy', 'minimum_sell', + 'montzar_product_id', 'gift_for_referrer', + 'gift_for_referral', 'up_price', 'down_price', 'payping_fin_customer_id', 'tahesab_port', + 'deposit_sms_support_number' +); + +-- text (بقیه — URL، توکن، کلید API، ساعت، ...) +UPDATE `settings` SET `type` = 'text' WHERE `key` IN ( + 'name_fa', 'name_en', 'app_url', 'bace_url', 'logo_login', 'logo_register', 'admin_url', 'title_pwa', 'title_fav', + 'server_url', 'key', 'main_product', 'zaarbox_api_url', 'zaarbox_price_key', 'chart_id', + 'etehadie_api_url', 'montzar_mobile', 'montzar_password', 'montzar_base_url', + 'montzar_token', 'montzar_diff', 'montzar_live_price', 'montzar_mazaneh', + 'montzar_truly_buy_mazaneh', 'montzar_truly_sell_mazaneh', 'startDay', 'endDay', + 'payping_start_url', 'payping_verify_url', 'payping_gateway_items', 'payping_fin_url', + 'payping_fin_token', 'payping_gateway_item', 'tahesab_host', 'tahesab_token', 'tahesab_db', + 'node_client_id', 'node_shared_secret', + 'sse_path', + 'tahesab_bank_account', 'telegram_bot_token', 'bale_bot_token', 'support_messenger_id', 'referral_limit', + 'referral_bonus_amount', 'balance_report_exclude_customer_id', 'metal_type', 'montify_name', 'price_extreme_date', + 'default_vc_number', 'liman_token' +); + +-- پیش‌فرض برای ردیف‌های بدون type +UPDATE `settings` SET `type` = 'text' WHERE `type` IS NULL OR TRIM(`type`) = ''; + +-- ============================================================================= + + +-- --------------------------------------------------------------------------- +-- کلیدهای modular اضافی (INSERT اگر نبود) +-- --------------------------------------------------------------------------- +INSERT INTO `settings` (`key`, `title_fa`, `value`, `can_edit`, `is_exist`, `is_active`, `type`, `description`) +SELECT 'price_provider', 'منبع قیمت', 'montzar', 1, 0, 1, 'select', 'منبع فعال قیمت|montzar,zaarbox,main_product' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'price_provider' LIMIT 1); + +INSERT INTO `settings` (`key`, `title_fa`, `value`, `can_edit`, `is_exist`, `is_active`, `type`) +SELECT 'service_charge_percentage', 'کارمزد درصدی (alias)', COALESCE( + (SELECT `value` FROM `settings` WHERE `key` = 'fee_service_charge_percentage' LIMIT 1), '0.005' +), 0, 0, 1, 'number' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'service_charge_percentage' LIMIT 1); + +INSERT INTO `settings` (`key`, `title_fa`, `value`, `can_edit`, `is_exist`, `is_active`, `type`) +SELECT 'title_pwa', 'عنوان PWA', '', 0, 0, 0, 'text' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'title_pwa' LIMIT 1); + +INSERT INTO `settings` (`key`, `title_fa`, `value`, `can_edit`, `is_exist`, `is_active`, `type`) +SELECT 'title_fav', 'عنوان favicon', '', 0, 0, 0, 'text' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'title_fav' LIMIT 1); + +INSERT INTO `settings` (`key`, `title_fa`, `value`, `can_edit`, `is_exist`, `is_active`, `type`) +SELECT 'text_rule', 'متن قوانین', '', 1, 0, 1, 'longtext' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'text_rule' LIMIT 1); + +INSERT INTO `settings` (`key`, `title_fa`, `value`, `can_edit`, `is_exist`, `is_active`, `type`) +SELECT 'text_about', 'متن درباره ما', '', 1, 0, 1, 'longtext' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'text_about' LIMIT 1); + +INSERT INTO `settings` (`key`, `title_fa`, `value`, `can_edit`, `is_exist`, `is_active`, `type`) +SELECT 'zaarbox_api_url', 'آدرس API تابلو Zaarbox', '', 1, 0, 1, 'text' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'zaarbox_api_url' LIMIT 1); + +INSERT INTO `settings` (`key`, `title_fa`, `value`, `can_edit`, `is_exist`, `is_active`, `type`) +SELECT 'zaarbox_price_key', 'شناسه ردیف تابلو (key یا UUID)', '', 1, 0, 1, 'text' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'zaarbox_price_key' LIMIT 1); + +INSERT INTO `settings` (`key`, `title_fa`, `value`, `can_edit`, `is_exist`, `is_active`, `type`) +SELECT 'main_product', 'محصول آبشده', '', 1, 0, 1, 'text' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'main_product' LIMIT 1); + +INSERT INTO `settings` (`key`, `title_fa`, `value`, `can_edit`, `is_exist`, `is_active`, `type`) +SELECT 'profit_gold_api_enabled', 'API سود طلا', 'false', 1, 0, 0, 'switch' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'profit_gold_api_enabled' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) +SELECT 'unit', '', 'واحد وزن دارایی و معاملات', 1, 1, + 'واحد نمایش وزن فلز در دارایی‌ها، کیف پول و تراکنش‌ها|گرم,کیلوگرم', 'select' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'unit' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) +SELECT 'main_wallet_products', '', 'محصولات متصل به کیف اصلی', 0, 1, + 'idهای محصول با کاما (مثل 13,25). موجودی = gold کیف اصلی. خالی = غیرفعال' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'main_wallet_products' LIMIT 1); + +-- --------------------------------------------------------------------------- +-- const — کلیدهای اضافی +-- --------------------------------------------------------------------------- +INSERT INTO `const` (`key`, `value`, `title_fa`) +SELECT 'limited_price', '', 'سقف واریز اولیه' +WHERE NOT EXISTS (SELECT 1 FROM `const` WHERE `key` = 'limited_price' LIMIT 1); + +INSERT INTO `const` (`key`, `value`, `title_fa`) +SELECT 'is_gateway_open', 'true', 'باز بودن درگاه پرداخت' +WHERE NOT EXISTS (SELECT 1 FROM `const` WHERE `key` = 'is_gateway_open' LIMIT 1); + +INSERT INTO `const` (`key`, `value`, `title_fa`) +SELECT 'header_banner', '', 'بنر بالای صفحه' +WHERE NOT EXISTS (SELECT 1 FROM `const` WHERE `key` = 'header_banner' LIMIT 1); + +INSERT INTO `const` (`key`, `value`, `title_fa`) +SELECT 'last_order_log', '', 'لاگ آخرین سفارش همکار' +WHERE NOT EXISTS (SELECT 1 FROM `const` WHERE `key` = 'last_order_log' LIMIT 1); + +INSERT INTO `const` (`key`, `value`, `title_fa`) +SELECT 'liman', '', 'توکن fin (legacy)' +WHERE NOT EXISTS (SELECT 1 FROM `const` WHERE `key` = 'liman' LIMIT 1); + +INSERT INTO `const` (`key`, `value`, `title_fa`) +SELECT 'nasiryan', '', 'توکن API نصیریان' +WHERE NOT EXISTS (SELECT 1 FROM `const` WHERE `key` = 'nasiryan' LIMIT 1); + +INSERT INTO `const` (`key`, `value`, `title_fa`) +SELECT 'nasiryan_price', '0', 'قیمت لحظه‌ای نصیریان' +WHERE NOT EXISTS (SELECT 1 FROM `const` WHERE `key` = 'nasiryan_price' LIMIT 1); + +INSERT INTO `const` (`key`, `value`, `title_fa`) +SELECT 'nasiryan_diff', '0', 'اختلاف قیمت نصیریان' +WHERE NOT EXISTS (SELECT 1 FROM `const` WHERE `key` = 'nasiryan_diff' LIMIT 1); + +INSERT INTO `const` (`key`, `value`, `title_fa`) +SELECT 'nasiryan_mazaneh', '0', 'مظنه نصیریان' +WHERE NOT EXISTS (SELECT 1 FROM `const` WHERE `key` = 'nasiryan_mazaneh' LIMIT 1); + +INSERT INTO `const` (`key`, `value`, `title_fa`) +SELECT 'nasiryan_truly_buy_mazaneh', '0', 'مظنه خرید نصیریان' +WHERE NOT EXISTS (SELECT 1 FROM `const` WHERE `key` = 'nasiryan_truly_buy_mazaneh' LIMIT 1); + +INSERT INTO `const` (`key`, `value`, `title_fa`) +SELECT 'nasiryan_truly_sell_mazaneh', '0', 'مظنه فروش نصیریان' +WHERE NOT EXISTS (SELECT 1 FROM `const` WHERE `key` = 'nasiryan_truly_sell_mazaneh' LIMIT 1); + +INSERT INTO `const` (`key`, `value`, `title_fa`) +SELECT 'nasiryan_closed', 'true', 'بسته بودن نصیریان' +WHERE NOT EXISTS (SELECT 1 FROM `const` WHERE `key` = 'nasiryan_closed' LIMIT 1); + +-- --------------------------------------------------------------------------- +-- پاکسازی کلیدهای legacy / تست +-- --------------------------------------------------------------------------- +DELETE FROM `settings` WHERE `key` IN ( + 'test', 'test2', 'test22', 'test3', 'test33', 'longtest', 'longtest2', 'test*', + 'is_requaire_referral', 'send_to_goldir', 'goldir_price', 'liman_token', + 'melted_product_id', 'display_montzar', 'tabanGohar_price', 'etehadie_api_url', + 'price_method', 'price_primary_source', + 'has_page_fund', 'has_page_permission', 'has_page_price_trigger', 'has_page_physical_gold', + 'has_chat', 'product_update_price_on_list', 'product_auto_close_open_on_list', + 'referral_count_for_gift', 'store_status', + 'name_en', 'bace_url', 'server_url', 'key', 'color_primary', 'color_secondary' +); + +DELETE FROM `const` WHERE `key` = 'log' OR `key` LIKE 'goldir%'; + +-- --------------------------------------------------------------------------- +-- metadata — type / title_fa / description (+ can_edit ته‌حساب) +-- --------------------------------------------------------------------------- +UPDATE `settings` SET `description` = NULL +WHERE LOWER(TRIM(COALESCE(`description`, ''))) IN ('true', 'false', '0', '1', 'yes', 'no', 'in server') + OR TRIM(COALESCE(`description`, '')) LIKE 'count of%'; + +UPDATE `settings` SET `description` = 'منبع فعال قیمت|montzar,zaarbox,main_product' +WHERE `key` = 'price_provider'; + +UPDATE `settings` SET + `type` = 'switch', + `title_fa` = 'کد معرف اجباری', + `description` = 'روشن = اجباری در ثبت‌نام | خاموش = اختیاری' +WHERE `key` = 'referral_id'; + +UPDATE `settings` SET `type` = 'switch' +WHERE `key` IN ('register_referral_sms_to_referrer', 'register_referral_bonus_message'); + +UPDATE `settings` SET + `type` = 'switch', + `title_fa` = 'نمودار از داده خود سایت', + `description` = 'خاموش = Zaarbox (chart_id) | روشن = تاریخچه prices' +WHERE `key` = 'chart_use_local_data'; + +UPDATE `settings` SET `type` = 'number', `title_fa` = 'تعداد سفارش اول بدون کارمزد', `description` = 'عدد — ۰ یعنی غیرفعال' +WHERE `key` = 'fee_free'; + +UPDATE `settings` SET `description` = 'تعداد سفارش اول بدون کارمزد' WHERE `key` = 'fee_free'; +UPDATE `settings` SET `description` = 'id یا reading_method محصول آبشده' WHERE `key` = 'main_product'; + +UPDATE `settings` SET + `title_fa` = 'شناسه پشتیبانی پیام‌رسان', + `type` = 'text', + `description` = 'یوزرنیم یا شماره تماس بسته به پیام‌رسان انتخاب‌شده' +WHERE `key` = 'support_messenger_id'; + +UPDATE `settings` SET + `title_fa` = 'متن پشتیبانی پیام‌رسان', + `type` = 'longtext', + `description` = 'متن دکمه یا توضیح پشتیبانی در اپ کاربر' +WHERE `key` = 'support_messenger_text'; + +UPDATE `settings` SET + `title_fa` = 'متن دعوتنامه اشتراک‌گذاری', + `type` = 'longtext', + `description` = @invite_link_desc +WHERE `key` = 'invite_link_text'; + +/* DISABLED: value رکورد موجود نباید در deploy تغییر کند؛ default فقط هنگام INSERT کلید جدید اعمال می‌شود. +UPDATE `settings` SET `value` = @invite_link_default_text +WHERE `key` = 'invite_link_text' + AND (`value` IS NULL OR TRIM(`value`) = ''); +*/ + +UPDATE `settings` SET + `title_fa` = 'پیام‌رسان پشتیبانی', + `type` = 'select', + `description` = 'bale,telegram,whatsapp,rubika,eitaa,soroush' +WHERE `key` = 'support_messenger'; + +UPDATE `settings` SET + `title_fa` = 'آدرس IP سرور ته‌حساب', + `type` = 'text', + `description` = NULL +WHERE `key` = 'tahesab_host'; + +UPDATE `settings` SET + `title_fa` = 'پورت سرور ته‌حساب', + `type` = 'number', + `description` = NULL +WHERE `key` = 'tahesab_port'; + +UPDATE `settings` SET + `title_fa` = 'نام دیتابیس ته‌حساب', + `type` = 'text', + `description` = 'مثال: TahesabDB' +WHERE `key` = 'tahesab_db'; + +UPDATE `settings` SET + `title_fa` = 'حساب بانکی ته‌حساب', + `type` = 'text', + `description` = 'نام حساب بانکی در سند واریز' +WHERE `key` = 'tahesab_bank_account'; + +-- ته‌حساب: فقط can_edit طبق ساختار SQL؛ value موجود دست نخورده +UPDATE `settings` SET `can_edit` = 1 +WHERE `key` LIKE 'tahesab_%' OR `key` = 'send_to_tahesab'; + +/* DISABLED: value رکورد موجود نباید در deploy تغییر کند؛ default فقط هنگام INSERT کلید جدید اعمال می‌شود. +UPDATE `settings` SET `value` = '' +WHERE `key` IN ('tahesab_host', 'tahesab_port', 'tahesab_token', 'tahesab_db', 'tahesab_bank_account'); +*/ + +/* DISABLED: value رکورد موجود نباید در deploy تغییر کند؛ default فقط هنگام INSERT کلید جدید اعمال می‌شود. +UPDATE `settings` SET `value` = 'false' +WHERE `key` = 'send_to_tahesab' AND TRIM(COALESCE(`value`, '')) = ''; +*/ + +-- is_store فقط از دیتابیس/دیپلوی — در پنل قابل ویرایش نیست +UPDATE `settings` SET `can_edit` = 0 WHERE `key` = 'is_store'; + +-- metal_type فقط از دیپلوی/SQL (مثلاً «کاتد مس» برای بورس مس) +UPDATE `settings` SET `can_edit` = 0 WHERE `key` = 'metal_type'; + +-- fee_cash legacy — فقط از دیپلوی/SQL +UPDATE `settings` SET `can_edit` = 0 WHERE `key` = 'fee_cash'; + +-- SSE قیمت — فقط دیپلوی/SQL +UPDATE `settings` SET `can_edit` = 0 WHERE `key` IN ( + 'wss_enabled', 'sse_path', 'tahesab_port' +); + +-- لوگو / PWA / favicon — فقط از دیپلوی؛ در پنل نمایش داده نمی‌شوند +UPDATE `settings` SET `can_edit` = 0, `is_active` = 0 +WHERE `key` IN ('logo_login', 'logo_register', 'title_pwa', 'title_fav'); + +UPDATE `settings` SET `title_fa` = 'مقدار پاداش معرف' WHERE `key` = 'referral_bonus_amount'; + +UPDATE `settings` SET `type` = 'text' WHERE `key` = 'balance_report_exclude_customer_id'; + +-- پاکسازی title_fa / description از نام پروژه یا ارجاع کد +UPDATE `settings` SET `title_fa` = 'حالت فروشگاهی' +WHERE `key` = 'is_store' AND (`title_fa` LIKE '%قطره%' OR `title_fa` LIKE '%کشکول%'); + +UPDATE `settings` SET `title_fa` = 'همگام‌سازی fin' +WHERE `key` = 'payping_fin_sync_enabled' AND `title_fa` LIKE '%لیمان%'; + +UPDATE `settings` SET `title_fa` = 'نام فروشگاه در درگاه', `description` = 'نام فروشگاه که در درگاه پرداخت و رسید بانکی به کاربر نمایش داده می‌شود.' +WHERE `key` = 'montify_name'; + +-- descriptionهای قدیمی که عمداً NULL می‌شدند — در بلوک پایانی بازنویسی می‌شوند + +UPDATE `const` SET `title_fa` = 'توکن fin (legacy)' WHERE `key` = 'liman' AND `title_fa` LIKE '%لیمان%'; + +UPDATE `const` SET `title_fa` = COALESCE(NULLIF(TRIM(`title_fa`), ''), 'بنر بالای صفحه') WHERE `key` = 'header_banner'; +UPDATE `const` SET `title_fa` = COALESCE(NULLIF(TRIM(`title_fa`), ''), 'باز بودن درگاه') WHERE `key` = 'is_gateway_open'; +UPDATE `const` SET `title_fa` = COALESCE(NULLIF(TRIM(`title_fa`), ''), 'سقف واریز اولیه') WHERE `key` = 'limited_price'; +UPDATE `const` SET `title_fa` = COALESCE(NULLIF(TRIM(`title_fa`), ''), 'لاگ آخرین سفارش') WHERE `key` = 'last_order_log'; + +-- --------------------------------------------------------------------------- +-- راهنمای کامل تنظیمات (description) — برای نمایش در پنل ادمین +-- فرمت select: «متن راهنما|گزینه۱,گزینه۲» +-- --------------------------------------------------------------------------- +UPDATE `settings` SET `description` = 'نام فارسی برند که در پیامک‌ها، عنوان صفحات و بخش‌های عمومی اپ کاربر نمایش داده می‌شود.' WHERE `key` = 'name_fa'; +UPDATE `settings` SET `description` = 'آدرس کامل وب‌اپ کاربر (با https). در لینک‌های پیامک، بازگشت از درگاه و ارجاعات داخلی استفاده می‌شود.' WHERE `key` = 'app_url'; +UPDATE `settings` SET `description` = 'آدرس کامل پنل مدیریت (با https). برای لینک‌های ادمین و تنظیمات CORS در صورت نیاز.' WHERE `key` = 'admin_url'; +UPDATE `settings` SET `description` = 'آدرس تصویر لوگو در صفحه ورود. معمولاً از طریق دیپلوی یا آپلود فایل تنظیم می‌شود؛ در پنل قابل ویرایش نیست.' WHERE `key` = 'logo_login'; +UPDATE `settings` SET `description` = 'آدرس تصویر لوگو در صفحه ثبت‌نام. معمولاً از طریق دیپلوی تنظیم می‌شود؛ در پنل قابل ویرایش نیست.' WHERE `key` = 'logo_register'; +UPDATE `settings` SET `description` = 'عنوان کوتاه برای نصب PWA روی موبایل. از دیپلوی مدیریت می‌شود.' WHERE `key` = 'title_pwa'; +UPDATE `settings` SET `description` = 'عنوان نمایش‌داده‌شده در تب مرورگر (favicon). از دیپلوی مدیریت می‌شود.' WHERE `key` = 'title_fav'; +UPDATE `settings` SET `description` = 'عنوان فلز اصلی در رابط کاربر (مثلاً «طلای آبشده» یا «کاتد مس»). در دارایی، کیف پول و برچسب‌های معامله دیده می‌شود. فقط از دیپلوی/SQL تغییر می‌کند.' WHERE `key` = 'metal_type'; +UPDATE `settings` SET `description` = 'واحد نمایش وزن در دارایی‌ها، کیف پول و جزئیات معاملات|گرم,کیلوگرم' WHERE `key` = 'unit'; +UPDATE `settings` SET `description` = 'روشن: کاربران جدید می‌توانند ثبت‌نام کنند. خاموش: فقط ورود کاربران موجود مجاز است.' WHERE `key` = 'open_register'; +UPDATE `settings` SET `description` = 'روشن: حساب کاربر بلافاصله پس از ثبت‌نام فعال می‌شود. خاموش: نیاز به تأیید دستی ادمین دارد.' WHERE `key` = 'auto_active_customer'; +UPDATE `settings` SET `description` = 'نوع چیدمان اپ: روشن = حالت فروشگاهی (سبد، دسته‌بندی، حواله و …). خاموش = حالت معامله آبشده/محصولات کلاسیک. فقط از دیپلوی تغییر می‌کند.' WHERE `key` = 'is_store'; +UPDATE `settings` SET `description` = 'پیشوند اختیاری برای شماره‌گذاری حواله‌ها در سیستم حسابداری خارجی. خالی = بدون پیشوند.' WHERE `key` = 'default_vc_number'; + +UPDATE `settings` SET `description` = 'روشن: نمودار قیمت از تاریخچه ذخیره‌شده در دیتابیس خودتان. خاموش: از سرویس تابلو آنلاین (با شناسه chart_id) استفاده می‌شود.' WHERE `key` = 'chart_use_local_data'; +UPDATE `settings` SET `description` = 'شناسه یکتا (UUID) نمودار در سرویس تابلو. اگر خالی باشد از شناسه پیش‌فرض سرویس استفاده می‌شود.' WHERE `key` = 'chart_id'; + +UPDATE `settings` SET `description` = 'منبع دریافت قیمت لحظه‌ای برای اپ کاربر و همگام‌سازی محصولات|montzar,zaarbox,main_product' WHERE `key` = 'price_provider'; +UPDATE `settings` SET `description` = 'شناسه عددی یا نام reading_method محصول آبشده مرجع. وقتی منبع قیمت روی main_product باشد برای محاسبه استفاده می‌شود.' WHERE `key` = 'main_product'; +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` = 'روشن: خارج از بازه startDay تا endDay معامله و نمایش قیمت بسته می‌شود. خاموش: محدودیت ساعتی اعمال نمی‌شود.' WHERE `key` = 'close_price'; +UPDATE `settings` SET `description` = 'ساعت شروع بازه معامله روزانه (فرمت 24 ساعته، مثال 09:00). فقط وقتی close_price روشن باشد اثر دارد.' WHERE `key` = 'startDay'; +UPDATE `settings` SET `description` = 'ساعت پایان بازه معامله روزانه (فرمت 24 ساعته، مثال 22:00). فقط وقتی close_price روشن باشد اثر دارد.' WHERE `key` = 'endDay'; +UPDATE `settings` SET `description` = 'اختلاف پایه (ریال) برای محاسبه قیمت خرید و فروش نمایشی روی مظنه. معمولاً نصف فاصله اسپرد کل است.' WHERE `key` = 'fee_single'; +UPDATE `settings` SET `description` = 'مبلغ اضافه (ریال) روی قیمت پایه برای نمایش/محاسبه سمت خرید. خالی = استفاده از fee_single.' WHERE `key` = 'buy_fee'; +UPDATE `settings` SET `description` = 'مبلغ کسر (ریال) از قیمت پایه برای نمایش/محاسبه سمت فروش. خالی = استفاده از fee_single.' WHERE `key` = 'sell_fee'; +UPDATE `settings` SET `description` = 'کارمزد ثابت ریالی هر سفارش (legacy). در صورت تنظیم fee_service_charge_percentage معمولاً اولویت با درصد است.' WHERE `key` = 'fee_cash'; +UPDATE `settings` SET `description` = 'درصد کارمزد هر سفارش از مبلغ معامله (اعشاری، مثال 0.005 یعنی ۰٫۵٪). روی payment_amount اعمال می‌شود.' WHERE `key` = 'fee_service_charge_percentage'; +UPDATE `settings` SET `description` = 'تعداد اولین سفارش‌های هر کاربر که از کارمزد معاف می‌شوند. ۰ = غیرفعال.' WHERE `key` = 'fee_free'; +UPDATE `settings` SET `description` = 'حداقل مبلغ درخواست برداشت وجه (ریال). درخواست‌های کمتر رد می‌شوند.' WHERE `key` = 'min_withdraw'; +UPDATE `settings` SET `description` = 'حداقل مبلغ اولین خرید هر کاربر (ریال). برای فعال‌سازی کیف یا احراز سطح اول استفاده می‌شود.' WHERE `key` = 'min_first_buy'; +UPDATE `settings` SET `description` = 'حداقل مقدار/مبلغ مجاز برای ثبت سفارش فروش. بسته به نوع محصول می‌تواند وزن یا ریال باشد.' WHERE `key` = 'minimum_sell'; +UPDATE `settings` SET `description` = 'بیشترین قیمت ثبت‌شده در روز جاری (ریال). توسط سیستم به‌روز می‌شود؛ دستی تغییر ندهید.' WHERE `key` = 'up_price'; +UPDATE `settings` SET `description` = 'کمترین قیمت ثبت‌شده در روز جاری (ریال). توسط سیستم به‌روز می‌شود؛ دستی تغییر ندهید.' WHERE `key` = 'down_price'; +UPDATE `settings` SET `description` = 'تاریخ آخرین به‌روزرسانی بیشترین/کمترین قیمت روز. توسط سیستم پر می‌شود.' WHERE `key` = 'price_extreme_date'; +UPDATE `settings` SET `description` = 'شناسه عددی مشتری که از گزارش تراز و آمار تجمیعی حذف می‌شود (مثلاً حساب تست). چند id با کاما.' WHERE `key` = 'balance_report_exclude_customer_id'; +UPDATE `settings` SET `description` = 'تنظیم legacy — از price_provider استفاده کنید. روشن بودن این گزینه دیگر توصیه نمی‌شود.' WHERE `key` = 'main_product_price'; +UPDATE `settings` SET `description` = 'تنظیم legacy — از price_provider استفاده کنید. معمولاً خاموش بماند.' WHERE `key` = 'montzar_price'; + +UPDATE `settings` SET `description` = 'متن کامل قوانین و مقررات استفاده از اپ که در صفحه قوانین به کاربر نشان داده می‌شود. HTML ساده مجاز است.' WHERE `key` = 'text_rule'; +UPDATE `settings` SET `description` = 'متن «درباره ما» شامل معرفی مجموعه، راه‌های ارتباطی و توضیح خدمات. در صفحه مربوطه در اپ کاربر نمایش داده می‌شود.' WHERE `key` = 'text_about'; + +UPDATE `settings` SET `description` = 'روشن: وارد کردن کد معرف در ثبت‌نام اجباری است. خاموش: کد معرف اختیاری است.' WHERE `key` = 'referral_id'; +UPDATE `settings` SET `description` = 'مقدار پاداش (معمولاً وزن فلز به گرم) که به کیف معرف پس از ثبت‌نام موفق معرف‌شونده واریز می‌شود.' WHERE `key` = 'gift_for_referrer'; +UPDATE `settings` SET `description` = 'مقدار پاداش (معمولاً وزن فلز) که به کاربر تازه‌ثبت‌نام‌شده (معرف‌شونده) داده می‌شود. ۰ = بدون پاداش.' WHERE `key` = 'gift_for_referral'; +UPDATE `settings` SET `description` = 'روشن: پس از ثبت‌نام کاربر جدید، پیامک اطلاع‌رسانی برای معرف ارسال می‌شود.' WHERE `key` = 'register_referral_sms_to_referrer'; +UPDATE `settings` SET `description` = 'روشن: متن پاداش معرف در پیامک خوش‌آمد ثبت‌نام گنجانده می‌شود.' WHERE `key` = 'register_referral_bonus_message'; +UPDATE `settings` SET `description` = 'حداکثر تعداد دعوت‌های مجاز برای هر کاربر. خالی = بدون محدودیت.' WHERE `key` = 'referral_limit'; +UPDATE `settings` SET `description` = 'مبلغ یا مقدار پاداش معرف (متن آزاد — بسته به پیاده‌سازی پیامک/اعتبار). برای نمایش در پیام‌ها.' WHERE `key` = 'referral_bonus_amount'; +UPDATE `settings` SET `description` = 'روشن: تطبیق شماره کارت بانکی کاربر با سرویس احراز هویت جیبیت هنگام ثبت/ویرایش کارت.' WHERE `key` = 'jibit_verification'; +UPDATE `settings` SET `description` = 'روشن: تطبیق کد ملی و موبایل در فرآیند ثبت‌نام از طریق سرویس جیبیت.' WHERE `key` = 'register_jibit_verify'; +UPDATE `settings` SET `description` = 'روشن: منوی «کسب درآمد / دعوت دوستان» در اپ کاربر نمایش داده می‌شود.' WHERE `key` = 'has_page_earn_money'; + +UPDATE `settings` SET `description` = 'شماره موبایل حساب API سرویس همکار قیمت. برای دریافت توکن و لیست محصولات.' WHERE `key` = 'montzar_mobile'; +UPDATE `settings` SET `description` = 'رمز عبور حساب API سرویس همکار قیمت. محرمانه نگه دارید.' WHERE `key` = 'montzar_password'; +UPDATE `settings` SET `description` = 'شناسه محصول آبشده در API همکار. باید با محصول مرجع در سرویس خارجی یکسان باشد.' WHERE `key` = 'montzar_product_id'; +UPDATE `settings` SET `description` = 'آدرس پایه سرور API همکار (بدون اسلش انتهایی). مثال: https://example.com' WHERE `key` = 'montzar_base_url'; +UPDATE `settings` SET `description` = 'توکن دسترسی API همکار. پس از ورود موفق توسط سیستم پر می‌شود؛ دستی ویرایش نکنید.' WHERE `key` = 'montzar_token'; +UPDATE `settings` SET `description` = 'اختلاف قیمت دریافتی از همکار (ریال). توسط cron/همگام‌سازی پر می‌شود.' WHERE `key` = 'montzar_diff'; +UPDATE `settings` SET `description` = 'آخرین قیمت لحظه‌ای دریافت‌شده از همکار (ریال). فقط خواندنی — توسط سیستم به‌روز می‌شود.' WHERE `key` = 'montzar_live_price'; +UPDATE `settings` SET `description` = 'مظنه میانی دریافت‌شده از همکار. توسط سیستم به‌روز می‌شود.' WHERE `key` = 'montzar_mazaneh'; +UPDATE `settings` SET `description` = 'مظنه واقعی سمت خرید از همکار. توسط سیستم به‌روز می‌شود.' WHERE `key` = 'montzar_truly_buy_mazaneh'; +UPDATE `settings` SET `description` = 'مظنه واقعی سمت فروش از همکار. توسط سیستم به‌روز می‌شود.' WHERE `key` = 'montzar_truly_sell_mazaneh'; +UPDATE `settings` SET `description` = 'روشن: امکان ثبت سفارش خرید از طریق قیمت همکار باز است (طبق وضعیت سرویس خارجی).' WHERE `key` = 'montzar_open_buy'; +UPDATE `settings` SET `description` = 'روشن: امکان ثبت سفارش فروش از طریق قیمت همکار باز است.' WHERE `key` = 'montzar_open_sell'; +UPDATE `settings` SET `description` = 'روشن: سرویس همکار در حال حاضر بسته/غیرفعال گزارش شده است.' WHERE `key` = 'montzar_closed'; +UPDATE `settings` SET `description` = 'پاسخ JSON آخرین سفارش ارسالی به همکار. برای عیب‌یابی؛ توسط سیستم پر می‌شود.' WHERE `key` = 'montzar_order_response'; + +UPDATE `settings` SET `description` = 'شناسه کلاینت برای API سفارش خارجی (هدر X-Client-Id). باید با مقدار تنظیم‌شده در سرویس مقصد یکسان باشد.' WHERE `key` = 'node_client_id'; +UPDATE `settings` SET `description` = 'کلید مشترک امضای HMAC برای احراز درخواست‌های API سفارش خارجی. محرمانه نگه دارید.' WHERE `key` = 'node_shared_secret'; +UPDATE `settings` SET `description` = 'روشن: API دریافت کیف پول و ثبت سفارش از سرویس فروشگاه خارجی فعال است. نیاز به node_client_id و node_shared_secret دارد.' WHERE `key` = 'external_order_api_enabled'; +UPDATE `settings` SET `description` = 'روشن: اپ به SSE (sse_path) وصل می‌شود و last/list با payload می‌آید؛ خاموش: polling.' WHERE `key` = 'wss_enabled'; +UPDATE `settings` SET `description` = 'مسیر GET لاراول برای استریم قیمت — پیش‌فرض /api/price/stream' WHERE `key` = 'sse_path'; +UPDATE `settings` SET `description` = 'نام فروشگاه که در درگاه پرداخت و رسید بانکی به کاربر نمایش داده می‌شود.' WHERE `key` = 'montify_name'; + +UPDATE `settings` SET `description` = 'روشن: پس از واریز/برداشت، تراکنش به سامانه حسابداری fin همگام‌سازی می‌شود.' WHERE `key` = 'payping_fin_sync_enabled'; +UPDATE `settings` SET `description` = 'آدرس کامل endpoint ثبت تراکنش در سامانه fin (POST).' WHERE `key` = 'payping_fin_url'; +UPDATE `settings` SET `description` = 'توکن احراز هویت برای API سامانه fin.' WHERE `key` = 'payping_fin_token'; +UPDATE `settings` SET `description` = 'شناسه مشتری/حساب در سامانه fin که تراکنش‌ها به نام آن ثبت می‌شوند.' WHERE `key` = 'payping_fin_customer_id'; +UPDATE `settings` SET `description` = 'کد item تکی درگاه (legacy). اگر payping_gateway_items پر باشد اولویت با لیست چرخشی است.' WHERE `key` = 'payping_gateway_item'; +UPDATE `settings` SET `description` = 'آدرس API شروع پرداخت (redirect کاربر به درگاه).' WHERE `key` = 'payping_start_url'; +UPDATE `settings` SET `description` = 'آدرس API تأیید و نهایی‌سازی پرداخت پس از بازگشت از درگاه.' WHERE `key` = 'payping_verify_url'; +UPDATE `settings` SET `description` = 'نام درگاه پرداخت فعال که به سرویس واسط درگاه ارسال می‌شود|sepal,' WHERE `key` = 'payping_gateway_name'; +UPDATE `settings` SET `description` = 'لیست کدهای item درگاه (با کاما) برای چرخش بین چند merchant. خالی = استفاده از payping_gateway_item.' WHERE `key` = 'payping_gateway_items'; +UPDATE `settings` SET `description` = 'روشن: مبلغ پرداخت به نزدیک‌ترین تومان گرد می‌شود. خاموش: مبلغ دقیق ریالی.' WHERE `key` = 'payping_round_toman'; +UPDATE `settings` SET `description` = 'روشن: در صورت وجود برداشت ناموفق قبلی، تسویه جدید با احتیاط بیشتر انجام می‌شود.' WHERE `key` = 'payping_strict_failed_withdraw'; + +UPDATE `settings` SET `description` = 'آدرس IP یا hostname سرور نرم‌افزار ته‌حساب روی شبکه داخلی.' WHERE `key` = 'tahesab_host'; +UPDATE `settings` SET `description` = 'شماره پورت اتصال به API ته‌حساب (معمولاً 8080 یا مقدار مستندات ته‌حساب).' WHERE `key` = 'tahesab_port'; +UPDATE `settings` SET `description` = 'توکن/API Key اتصال به ته‌حساب. از پنل ته‌حساب دریافت می‌شود.' WHERE `key` = 'tahesab_token'; +UPDATE `settings` SET `description` = 'نام دیتابیس یا شناسه پایگاه در ته‌حساب که سند به آن ارسال می‌شود.' WHERE `key` = 'tahesab_db'; +UPDATE `settings` SET `description` = 'نام یا کد حساب بانکی در سند واریز/برداشت ته‌حساب.' WHERE `key` = 'tahesab_bank_account'; +UPDATE `settings` SET `description` = 'روشن: واریز و برداشت مشتریان به‌صورت خودکار به ته‌حساب ارسال می‌شود.' WHERE `key` = 'send_to_tahesab'; + +UPDATE `settings` SET `description` = 'نوع پیام‌رسان برای دکمه پشتیبانی در اپ کاربر|bale,telegram,whatsapp,rubika,eitaa,soroush' WHERE `key` = 'support_messenger'; +UPDATE `settings` SET `description` = 'شناسه تماس پشتیبانی: یوزرنیم (تلگرام)، شماره (واتساپ/بله) یا آیدی بسته به پیام‌رسان انتخاب‌شده.' WHERE `key` = 'support_messenger_id'; +UPDATE `settings` SET `description` = 'متن دکمه یا توضیح کوتاه کنار لینک پشتیبانی در اپ کاربر.' WHERE `key` = 'support_messenger_text'; +UPDATE `settings` SET `description` = 'متن پیام اشتراک‌گذاری دعوت در اپ کاربر (دکمه «اشتراک با دوستان» در صفحه اصلی، بخش معرف در پروفایل، صفحه کسب درآمد و مودال اشتراک). متغیرهای جایگزین: ٪نام یا %نام = نام کامل کاربر دعوت‌کننده؛ ٪لینک یا %لینک = آدرس کامل صفحه ثبت‌نام همراه با کد معرف (بر اساس تنظیم app_url یا دامنه فعلی مرورگر). فاصله اختیاری بعد از ٪ یا % مجاز است (مثلاً ٪ نام). اگر این فیلد خالی باشد، اپ از متن پیش‌فرض داخلی استفاده می‌کند.' WHERE `key` = 'invite_link_text'; +UPDATE `settings` SET `description` = 'شماره موبایل پشتیبانی واریز؛ در صفحه شارژ حساب دکمه پیامک با متن «شماره حساب» نمایش داده می‌شود.' WHERE `key` = 'deposit_sms_support_number'; + +UPDATE `settings` SET `description` = 'توکن ربات تلگرام برای ارسال اعلان‌ها. از BotFather دریافت می‌شود. محرمانه.' WHERE `key` = 'telegram_bot_token'; +UPDATE `settings` SET `description` = 'توکن ربات بله برای ارسال اعلان‌ها. محرمانه.' WHERE `key` = 'bale_bot_token'; + +UPDATE `settings` SET `description` = 'روشن: پس از شارژ کیف توسط ادمین، پیامک به مشتری ارسال می‌شود.' WHERE `key` = 'charge_notif'; +UPDATE `settings` SET `description` = 'روشن: امکان ارسال پیامک گروهی از پنل ادمین فعال است.' WHERE `key` = 'group_sms'; + +UPDATE `settings` SET `description` = 'شناسه‌های عددی محصول (با کاما) که موجودی آن‌ها از کیف طلای اصلی خوانده می‌شود. خالی = غیرفعال.' WHERE `key` = 'main_wallet_products'; +UPDATE `settings` SET `description` = 'روشن: در حالت فروشگاهی قیمت از API نصیریان خوانده می‌شود (در صورت پیکربندی). فقط برای برخی نصب‌ها.' WHERE `key` = 'price_from_nasiryan'; +UPDATE `settings` SET `description` = 'روشن: API محاسبه سود طلا فعال است. در اکثر نصب‌ها خاموش می‌ماند.' WHERE `key` = 'profit_gold_api_enabled'; + +-- --------------------------------------------------------------------------- +-- ensure — کلیدهای longtext (INSERT نهایی + تثبیت type بعد از batchهای type=text) +-- --------------------------------------------------------------------------- +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) +SELECT 'invite_link_text', @invite_link_default_text, 'متن دعوتنامه اشتراک‌گذاری', 1, 1, @invite_link_desc, 'longtext' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'invite_link_text' LIMIT 1); + +UPDATE `settings` SET + `title_fa` = 'متن دعوتنامه اشتراک‌گذاری', + `type` = 'longtext', + `can_edit` = 1, + `is_active` = 1, + `description` = @invite_link_desc +WHERE `key` = 'invite_link_text'; + +/* DISABLED: value رکورد موجود نباید در deploy تغییر کند؛ default فقط هنگام INSERT کلید جدید اعمال می‌شود. +UPDATE `settings` SET `value` = @invite_link_default_text +WHERE `key` = 'invite_link_text' + AND (`value` IS NULL OR TRIM(`value`) = ''); +*/ + +UPDATE `settings` SET `type` = 'longtext' +WHERE `key` IN ('text_rule', 'text_about', 'support_messenger_text', 'invite_link_text', 'montzar_order_response'); + + +-- --------------------------------------------------------------------------- +-- sync can_edit — برای کلیدهای موجود هم طبق ساختار همین SQL تنظیم شود +-- نکته: value اینجا عمداً آپدیت نمی‌شود؛ مقدار موجود کارفرما/پنل حفظ می‌شود. +-- --------------------------------------------------------------------------- +UPDATE `settings` s +JOIN ( + SELECT 'admin_url' AS `key`, 1 AS `can_edit` + UNION ALL SELECT 'app_url', 1 + UNION ALL SELECT 'auto_active_customer', 1 + UNION ALL SELECT 'balance_report_exclude_customer_id', 1 + UNION ALL SELECT 'bale_bot_token', 0 + UNION ALL SELECT 'buy_fee', 1 + UNION ALL SELECT 'charge_notif', 1 + UNION ALL SELECT 'chart_id', 1 + UNION ALL SELECT 'chart_use_local_data', 1 + UNION ALL SELECT 'close_price', 1 + UNION ALL SELECT 'default_vc_number', 1 + UNION ALL SELECT 'deposit_sms_support_number', 1 + UNION ALL SELECT 'down_price', 0 + UNION ALL SELECT 'endDay', 1 + UNION ALL SELECT 'external_order_api_enabled', 1 + UNION ALL SELECT 'fee_cash', 0 + UNION ALL SELECT 'fee_free', 1 + UNION ALL SELECT 'fee_service_charge_percentage', 1 + UNION ALL SELECT 'fee_single', 1 + UNION ALL SELECT 'gift_for_referral', 1 + UNION ALL SELECT 'gift_for_referrer', 1 + UNION ALL SELECT 'group_sms', 1 + UNION ALL SELECT 'has_page_earn_money', 1 + UNION ALL SELECT 'invite_link_text', 1 + UNION ALL SELECT 'is_store', 0 + UNION ALL SELECT 'jibit_verification', 1 + UNION ALL SELECT 'logo_login', 0 + UNION ALL SELECT 'logo_register', 0 + UNION ALL SELECT 'main_product', 1 + UNION ALL SELECT 'main_product_price', 1 + UNION ALL SELECT 'main_wallet_products', 0 + UNION ALL SELECT 'metal_type', 0 + UNION ALL SELECT 'min_first_buy', 1 + UNION ALL SELECT 'min_withdraw', 1 + UNION ALL SELECT 'minimum_sell', 1 + UNION ALL SELECT 'montify_name', 1 + UNION ALL SELECT 'montzar_base_url', 1 + UNION ALL SELECT 'montzar_closed', 1 + UNION ALL SELECT 'montzar_diff', 0 + UNION ALL SELECT 'montzar_live_price', 0 + UNION ALL SELECT 'montzar_mazaneh', 0 + UNION ALL SELECT 'montzar_mobile', 1 + UNION ALL SELECT 'montzar_open_buy', 1 + UNION ALL SELECT 'montzar_open_sell', 1 + UNION ALL SELECT 'montzar_order_response', 0 + UNION ALL SELECT 'montzar_password', 1 + UNION ALL SELECT 'montzar_price', 1 + UNION ALL SELECT 'montzar_product_id', 1 + UNION ALL SELECT 'montzar_token', 0 + UNION ALL SELECT 'montzar_truly_buy_mazaneh', 0 + UNION ALL SELECT 'montzar_truly_sell_mazaneh', 0 + UNION ALL SELECT 'name_fa', 1 + UNION ALL SELECT 'node_client_id', 1 + UNION ALL SELECT 'node_shared_secret', 1 + UNION ALL SELECT 'open_register', 1 + UNION ALL SELECT 'payping_fin_customer_id', 1 + UNION ALL SELECT 'payping_fin_sync_enabled', 1 + UNION ALL SELECT 'payping_fin_token', 1 + UNION ALL SELECT 'payping_fin_url', 1 + UNION ALL SELECT 'payping_gateway_item', 1 + UNION ALL SELECT 'payping_gateway_items', 1 + UNION ALL SELECT 'payping_gateway_name', 1 + UNION ALL SELECT 'payping_round_toman', 1 + UNION ALL SELECT 'payping_start_url', 1 + UNION ALL SELECT 'payping_strict_failed_withdraw', 1 + UNION ALL SELECT 'payping_verify_url', 1 + UNION ALL SELECT 'price_extreme_date', 0 + UNION ALL SELECT 'price_from_nasiryan', 1 + UNION ALL SELECT 'price_provider', 1 + UNION ALL SELECT 'profit_gold_api_enabled', 1 + UNION ALL SELECT 'referral_bonus_amount', 1 + UNION ALL SELECT 'referral_id', 1 + UNION ALL SELECT 'referral_limit', 1 + UNION ALL SELECT 'register_jibit_verify', 1 + UNION ALL SELECT 'register_referral_bonus_message', 1 + UNION ALL SELECT 'register_referral_sms_to_referrer', 1 + UNION ALL SELECT 'sell_fee', 1 + UNION ALL SELECT 'send_to_tahesab', 1 + UNION ALL SELECT 'service_charge_percentage', 0 + UNION ALL SELECT 'show_last_price', 1 + UNION ALL SELECT 'sse_path', 0 + UNION ALL SELECT 'startDay', 1 + UNION ALL SELECT 'support_messenger', 1 + UNION ALL SELECT 'support_messenger_id', 1 + UNION ALL SELECT 'support_messenger_text', 1 + UNION ALL SELECT 'tahesab_bank_account', 1 + UNION ALL SELECT 'tahesab_db', 1 + UNION ALL SELECT 'tahesab_host', 1 + UNION ALL SELECT 'tahesab_port', 0 + UNION ALL SELECT 'tahesab_token', 1 + UNION ALL SELECT 'telegram_bot_token', 0 + UNION ALL SELECT 'text_about', 1 + UNION ALL SELECT 'text_rule', 1 + UNION ALL SELECT 'title_fav', 0 + UNION ALL SELECT 'title_pwa', 0 + UNION ALL SELECT 'unit', 1 + UNION ALL SELECT 'up_price', 0 + UNION ALL SELECT 'wss_enabled', 0 + UNION ALL SELECT 'zaarbox_api_url', 1 + UNION ALL SELECT 'zaarbox_price_key', 1 +) d ON d.`key` = s.`key` +SET s.`can_edit` = d.`can_edit`; + +COMMIT; + +SELECT 'deploy_settings_const.sql finished' AS status; + +-- بعد از اجرا (اختیاری): +-- SELECT `key`, `title_fa`, `value`, `type`, `is_active` FROM `settings` ORDER BY `key`; +-- SELECT `key`, `value`, `title_fa` FROM `const` ORDER BY `key`; diff --git a/database/sql/drop_has_page_earn_moneyB_setting.sql b/database/sql/drop_has_page_earn_moneyB_setting.sql new file mode 100644 index 0000000..976e3c8 --- /dev/null +++ b/database/sql/drop_has_page_earn_moneyB_setting.sql @@ -0,0 +1,2 @@ +-- حذف setting اشتباهی: has_page_earn_moneyB (تایپو؛ در کد استفاده نمی‌شود؛ جایگزین: has_page_earn_money) +DELETE FROM `settings` WHERE `key` = 'has_page_earn_moneyB'; diff --git a/routes/admin.php b/routes/admin.php index f705797..72f96d8 100644 --- a/routes/admin.php +++ b/routes/admin.php @@ -52,6 +52,14 @@ Route::middleware('auth:user')->group(function (){ Route::get('/product/auto_sell/{id}',[ProductController::class, 'auto_sell']); Route::get('/product/auto_buy/{id}',[ProductController::class, 'auto_buy']); Route::get('/product/auto/{method}/{action}',[ProductController::class, 'auto_group']); + Route::prefix('products/quick')->group(function () { + Route::get('activation-snapshot', [ProductController::class, 'activationSnapshotStatus']); + Route::post('deactivate-all', [ProductController::class, 'deactivateAllProducts']); + Route::post('restore-activation', [ProductController::class, 'restoreActivationSnapshot']); + Route::post('close-buy', [ProductController::class, 'closeAllBuy']); + Route::post('close-sell', [ProductController::class, 'closeAllSell']); + Route::post('sync-show', [ProductController::class, 'syncProductShow']); + }); Route::get('/getProduct/{id}',[ProductController::class, 'getProduct']); Route::put('/products',[ProductController::class, 'editProducts']); Route::resource('/product',ProductController::class)->except(['destroy']);