From 279e4bc881ab5bef81c38e8125b201aacf461fd0 Mon Sep 17 00:00:00 2001 From: adonis Date: Mon, 10 Aug 2026 16:48:53 +0330 Subject: [PATCH] Enable gated multi-level referral profit and harden chat/SMS notify paths. Honor enable_customer_level_profit for order referral payouts, and tighten support-chat webhook/SMS plus SuperAdmin SMS panel sync settings. Co-authored-by: Cursor --- .../Controllers/Admin/GiftCardController.php | 4 + .../Controllers/Admin/SmsPanelController.php | 49 +++-- .../Chat/SupportChatNotifyController.php | 14 +- .../Single/SingleOrderController.php | 168 ++++++++++++------ .../Controllers/Site/RequestsController.php | 3 +- app/Models/Customer.php | 3 +- app/Services/ChatWebhookService.php | 108 ++++++++--- database/sql/deploy_settings_const.sql | 38 +++- 8 files changed, 277 insertions(+), 110 deletions(-) diff --git a/app/Http/Controllers/Admin/GiftCardController.php b/app/Http/Controllers/Admin/GiftCardController.php index 8f670e2..44dba0e 100644 --- a/app/Http/Controllers/Admin/GiftCardController.php +++ b/app/Http/Controllers/Admin/GiftCardController.php @@ -82,6 +82,10 @@ class GiftCardController extends Controller throw new UnprocessableEntityHttpException('auth failed!'); } + if (!app(ConfigService::class)->getBool('has_page_gift_card', false)) { + throw new UnprocessableEntityHttpException('قابلیت کارت هدیه غیرفعال است.'); + } + $redeem = $request->code; $giftcode = GiftCardCodes::where('code', $redeem)->first(); $gift = GiftCard::find($giftcode->giftcard_id); diff --git a/app/Http/Controllers/Admin/SmsPanelController.php b/app/Http/Controllers/Admin/SmsPanelController.php index 17d0640..02ccb8e 100644 --- a/app/Http/Controllers/Admin/SmsPanelController.php +++ b/app/Http/Controllers/Admin/SmsPanelController.php @@ -144,6 +144,7 @@ class SmsPanelController extends Controller /** * خلاصه سبک کیف پول برای نمایش «اعتبار پیامک» در هدر؛ برای همه ادمین‌ها. + * اگر سوپرادمین قطع باشد، روی آینهٔ محلی برمی‌گردیم — نه 502 (ویجت هدر نباید بترکد). */ public function walletSummary() { @@ -159,24 +160,39 @@ class SmsPanelController extends Controller if ($this->useSuperAdmin()) { $balanceData = $this->sa()->balance(); $charge = $this->sa()->chargeInfo(); - if ($balanceData === null || $charge === null) { - $this->abortSaUnavailable(); + + if ($balanceData !== null) { + $deposit = is_array($charge) + ? $this->depositFromChargeInfo($charge) + : SmsWalletService::getDepositInfo(); + + $this->mirrorLocalFromSa(array_merge($balanceData, [ + 'charge_info' => is_array($charge) ? $charge : [], + 'deposit' => $deposit, + ])); + + return response()->json([ + 'enabled' => true, + 'balance' => (int) ($balanceData['balance'] ?? 0), + 'is_blocked' => (bool) ($balanceData['is_blocked'] ?? false), + 'deposit' => $deposit, + 'source' => 'superadmin', + 'sa_partial' => $charge === null, + ]); } - $this->mirrorLocalFromSa(array_merge($balanceData, [ - 'charge_info' => $charge, - 'deposit' => $this->depositFromChargeInfo($charge), - ])); - - return response()->json([ - 'enabled' => true, - 'balance' => (int) ($balanceData['balance'] ?? 0), - 'is_blocked' => (bool) ($balanceData['is_blocked'] ?? false), - 'deposit' => $this->depositFromChargeInfo($charge), - 'source' => 'superadmin', - ]); + // SA فعال است ولی balance نرسید — آخرین آینهٔ محلی + return response()->json($this->localWalletSummaryPayload('local_fallback')); } + return response()->json($this->localWalletSummaryPayload('local')); + } + + /** + * @return array{enabled: bool, balance: int, is_blocked: bool, deposit: array, source: string} + */ + private function localWalletSummaryPayload(string $source): array + { $balance = 0; $isBlocked = false; @@ -186,12 +202,13 @@ class SmsPanelController extends Controller $isBlocked = (bool) $wallet->is_blocked; } - return response()->json([ + return [ 'enabled' => true, 'balance' => $balance, 'is_blocked' => $isBlocked, 'deposit' => SmsWalletService::getDepositInfo(), - ]); + 'source' => $source, + ]; } /** diff --git a/app/Http/Controllers/Chat/SupportChatNotifyController.php b/app/Http/Controllers/Chat/SupportChatNotifyController.php index d3f981f..661286b 100644 --- a/app/Http/Controllers/Chat/SupportChatNotifyController.php +++ b/app/Http/Controllers/Chat/SupportChatNotifyController.php @@ -134,16 +134,18 @@ class SupportChatNotifyController extends Controller /** * ثبت/تازه‌سازی وب‌هوک روی ah_chat (از پنل ادمین). + * همیشه HTTP 200 — شکست ثبت best-effort است و نباید toast خطای 422 بسازد. */ public function ensureWebhook() { - $service = app(ChatWebhookService::class); - $ok = $service->ensureRegistered(); + $result = app(ChatWebhookService::class)->ensureRegisteredDetailed(); return response()->json([ - 'ok' => $ok, - 'webhook_url' => $service->webhookUrl(), - 'message' => $ok ? 'webhook registered' : 'webhook register skipped or failed', - ], $ok ? 200 : 422); + 'ok' => (bool) ($result['ok'] ?? false), + 'webhook_url' => (string) ($result['webhook_url'] ?? ''), + 'reason' => (string) ($result['reason'] ?? ''), + 'message' => (string) ($result['message'] ?? ''), + 'attempts' => (int) ($result['attempts'] ?? 0), + ]); } } diff --git a/app/Http/Controllers/Single/SingleOrderController.php b/app/Http/Controllers/Single/SingleOrderController.php index 8656128..2e8418d 100644 --- a/app/Http/Controllers/Single/SingleOrderController.php +++ b/app/Http/Controllers/Single/SingleOrderController.php @@ -259,7 +259,7 @@ class SingleOrderController extends Controller report($e); } } -// $response['reward'] = $this->give_order_reward($data, $wallet, $wallet_interface); + $response['reward'] = $this->give_order_reward($data, $wallet, $wallet_interface); if ((int) $data['direction'] === 1 && $customer) { $referrer = Customer::where('referral_id', $customer->referral_to_id)->first(); if (!empty($referrer) && $referrer->first_buy_order == 1 && $customer->first_buy_order !== 1) { @@ -810,64 +810,97 @@ class SingleOrderController extends Controller private function give_order_reward(&$data, $wallet, $wallet_interface) { + if (!app(\App\Services\ConfigService::class)->getBool('enable_customer_level_profit', false)) { + return $data; + } + + $serviceCharge = (float) ($data['order']['service_charge'] ?? 0); + if ($serviceCharge <= 0) { + return $data; + } + $data['aCustomers'] = []; $i = 0; $data['aCustomers'][$i] = Customer::findOrFail($data['customer_id']); while ($data['aCustomers'][$i + 1] = Customer::where('referral_id', $data['aCustomers'][$i]->referral_to_id)->first()) { - if ($data['aCustomers'][$i + 1]->profit_amount_by_lvl) { - $levels = json_decode(str_replace(['{', '}'], ['[', ']'], $data['aCustomers'][$i + 1]->profit_amount_by_lvl), true); - foreach ($levels as $level) { - if ($level[0] == $i + 1) { -// [$level[1],$data['aCustomers'][$i+1]]; - - if ($this->Config('has_page_earn_money') == true) { - $gift_for_invite = ($data['order']['service_charge'] * $level[1]) / 100; - $profit_receiver = $data['aCustomers'][$i + 1]->id; - $profit_sender = $data['aCustomers'][0]->id; - $Withdraw = Withdraw::create([ - 'user_id' => $profit_sender, - 'customer_id' => $profit_receiver, - "cash" => 0, - "gold" => $gift_for_invite, - 'sts' => 9, - ]); - $wallet_interface = new WalletInterface($profit_receiver, 2); - new TransactionInterface($wallet_interface, $_inp = [ - "cash" => 0, - "gold" => $gift_for_invite, - 'expire_at' => now(), - 'active' => true, - 'withdraw_id' => $Withdraw->id, - 'start_at' => now(), - ], 9, true, false); - $transaction = Transaction::where('customer_id', $profit_receiver)->latest()->first(); - TransactionsAdmin::create([ - 'customer_id' => $profit_sender, - 'customer_to_id' => $profit_receiver, - 'user_id' => $profit_sender, - 'order_id' => $data['order']['id'], - 'wallet' => null, // یا مقدار مناسب دیگری - 'transaction_id' => $transaction->id, - 'cash' => 0, - 'note' => ' سود بابت سفارش', - 'type' => 1, // یا مقدار مناسب دیگری - 'gold' => $gift_for_invite, - 'balance_cash' => 0, // یا مقدار مناسب دیگری - 'balance_gold' => $gift_for_invite, // مقدار صحیح برای `balance_gold` - 'withdraw_id' => $Withdraw->id, - ]); - } - } + $levels = $this->parseProfitAmountByLevel($data['aCustomers'][$i + 1]->profit_amount_by_lvl); + foreach ($levels as $levelRow) { + $levelNo = (int) ($levelRow['level'] ?? $levelRow[0] ?? 0); + $percent = (float) ($levelRow['present'] ?? $levelRow[1] ?? 0); + if ($levelNo !== ($i + 1) || $percent <= 0) { + continue; } + + $gift_for_invite = ($serviceCharge * $percent) / 100; + if ($gift_for_invite <= 0) { + continue; + } + + $profit_receiver = $data['aCustomers'][$i + 1]->id; + $profit_sender = $data['aCustomers'][0]->id; + $Withdraw = Withdraw::create([ + 'user_id' => $profit_sender, + 'customer_id' => $profit_receiver, + 'cash' => 0, + 'gold' => $gift_for_invite, + 'sts' => 9, + ]); + $wallet_interface = new WalletInterface($profit_receiver, 2); + new TransactionInterface($wallet_interface, [ + 'cash' => 0, + 'gold' => $gift_for_invite, + 'expire_at' => now(), + 'active' => true, + 'withdraw_id' => $Withdraw->id, + 'start_at' => now(), + ], 9, true, false); + $transaction = Transaction::where('customer_id', $profit_receiver)->latest()->first(); + TransactionsAdmin::create([ + 'customer_id' => $profit_sender, + 'customer_to_id' => $profit_receiver, + 'user_id' => $profit_sender, + 'order_id' => $data['order']['id'], + 'wallet' => null, + 'transaction_id' => $transaction->id, + 'cash' => 0, + 'note' => ' سود بابت سفارش', + 'type' => 1, + 'gold' => $gift_for_invite, + 'balance_cash' => 0, + 'balance_gold' => $gift_for_invite, + 'withdraw_id' => $Withdraw->id, + ]); } - if ($i == 100) break; - $i++; // برای جلوگیری از حلقه بی‌نهایت + if ($i == 100) { + break; + } + $i++; } - return $data; } + /** @return list */ + private function parseProfitAmountByLevel(mixed $raw): array + { + if (is_array($raw)) { + return $raw; + } + if (!is_string($raw) || trim($raw) === '') { + return []; + } + + $decoded = json_decode($raw, true); + if (is_array($decoded)) { + return $decoded; + } + + // فرمت قدیمی: رشته شبیه {1,5},{2,2} + $legacy = json_decode(str_replace(['{', '}'], ['[', ']'], $raw), true); + + return is_array($legacy) ? $legacy : []; + } + private function sendTransactionNotifications(array $data, string $transactionType) { $customer = Customer::findOrFail($data['customer_id']); @@ -880,8 +913,9 @@ class SingleOrderController extends Controller $totalPrice = $data['total_price'] ?? ($data['payment_amount'] ?? 0); $subjectTitle = $this->transactionSubjectTitle($data); + $amountLabel = self::formatSmsGoldWeight($amount); $message = "کاربر {$customer->name} با شماره موبایل {$customer->mobile} اقدام به $transactionType {$subjectTitle} به مقدار " . - "{$amount} گرم به مبلغ " . number_format($totalPrice) . + "{$amountLabel} گرم به مبلغ " . number_format($totalPrice) . " ریال کرد. با تشکر، $companyName"; if (self::isSmsNotifEnabled('sms_notif_order_admin')) { User::where('send_sms', 1)->get()->each(function ($admin) use ($message) { @@ -895,9 +929,10 @@ class SingleOrderController extends Controller $balanceLabel = self::metalTypeLabel(); $goldBalance = $wallet ? ($wallet->gold ?? 0) : 0; $cashBalance = $wallet ? ($wallet->cash ?? 0) : 0; - $customerMessage = "$companyName\n$transactionType {$subjectTitle}\nگرم: {$amount}\n" . + $goldBalanceLabel = self::formatSmsGoldWeight($goldBalance); + $customerMessage = "$companyName\n$transactionType {$subjectTitle}\nگرم: {$amountLabel}\n" . "مبلغ کل: " . number_format($totalPrice) . "\n\n" . - "موجودی {$balanceLabel}: {$goldBalance}\n" . + "موجودی {$balanceLabel}: {$goldBalanceLabel}\n" . "مانده ریالی: " . number_format($cashBalance) . "\n" . self::publicSiteUrl(request()); @@ -1036,7 +1071,7 @@ class SingleOrderController extends Controller $userMobile = $customer->mobile; // User's mobile number $userName = $customer->name; // User's name $chargedAmount = $data['total_price']; // Total price in Rial - $chargedAmountGold = $data['amount']; // Amount of gold + $chargedAmountGold = self::formatSmsGoldWeight($data['amount']); // Amount of gold // Company name $companyName = $this->Config('name_fa'); // Company name from configuration @@ -1055,15 +1090,16 @@ class SingleOrderController extends Controller ->main() ->first(); $companyurl = self::publicSiteUrl(request()); - $weight = $data['amount']; + $weight = (float) $data['amount']; + $weightLabel = self::formatSmsGoldWeight($weight); $totalAmount = $data['total_price']; $pricePerGram = $weight > 0 ? $totalAmount / $weight : 0; - $goldBalance = $mainWallet->gold ?? 0; + $goldBalance = self::formatSmsGoldWeight($mainWallet->gold ?? 0); $remainingBalance = $mainWallet->cash ?? 0; $message = "$companyName\n"; $message .= "خرید آبشده\n"; - $message .= "گرم: $weight\n"; + $message .= "گرم: $weightLabel\n"; $message .= "قیمت گرم: " . number_format($pricePerGram) . "\n"; $message .= "مبلغ کل: " . number_format($totalAmount) . "\n\n"; $message .= "موجودی طلایی: $goldBalance\n"; @@ -1110,6 +1146,28 @@ class SingleOrderController extends Controller return null; } + /** + * مقدار ضرب‌شونده در قیمت واحد برای مبلغ سفارش. + * قیمت فرمولی = قیمت هر عدد (وزن داخل فرمول است) → فقط تعداد. + * بقیه = تعداد × وزن واحد محصول. + */ + private function resolveProductOrderPricingAmount(Product|array|null $product, float $number): float + { + if ($product instanceof Product && FormulaPriceService::isEnabled($product)) { + return $number; + } + + if (is_array($product) && ! empty($product['price_formula_enabled'])) { + return $number; + } + + $unitAmount = $product instanceof Product + ? (float) ($product->amount ?? 0) + : (float) (is_array($product) ? ($product['amount'] ?? 0) : 0); + + return $number * $unitAmount; + } + private function assertMinimumSellCash(array $data): void { $minSell = Setting::where('key', 'minimum_sell')->where('is_active', 1)->first(); diff --git a/app/Http/Controllers/Site/RequestsController.php b/app/Http/Controllers/Site/RequestsController.php index 9075ea3..6687aa8 100644 --- a/app/Http/Controllers/Site/RequestsController.php +++ b/app/Http/Controllers/Site/RequestsController.php @@ -158,8 +158,9 @@ class RequestsController extends Controller $message = "کاربر {$customer->name} با شماره موبایل {$customer->mobile} اقدام به برداشت موجودی از طرف $montifyCompanyName به مقدار " . "{$data['amount']} ریال " . " کرد. با تشکر، $companyName"; }elseif ($data['method'] == 'gold') { + $amountLabel = self::formatSmsGoldWeight($data['amount']); $message = "کاربر {$customer->name} با شماره موبایل {$customer->mobile} اقدام به $transactionType طلا به مقدار " . - "{$data['amount']} گرم به مبلغ " . number_format($data['total_price']) . + "{$amountLabel} گرم به مبلغ " . number_format($data['total_price']) . " ریال کرد. با تشکر، $companyName"; } User::where('send_sms', 1)->get()->each(function ($admin) use ($message, $data, $transactionType, $companyName) { diff --git a/app/Models/Customer.php b/app/Models/Customer.php index 2fe1908..866c354 100644 --- a/app/Models/Customer.php +++ b/app/Models/Customer.php @@ -52,7 +52,7 @@ class Customer extends Authenticatable implements JWTSubject 'credential_id', 'moshtari_code', 'pargar_account_id', - + 'profit_amount_by_lvl', ]; /** * The attributes that should be hidden for arrays. @@ -75,6 +75,7 @@ class Customer extends Authenticatable implements JWTSubject "finger_print" => "boolean", "conditional_order_active" => "boolean", "conditional_order_limit" => "integer", + "profit_amount_by_lvl" => "array", ]; static $TYPE = [ 1=>'همکار', diff --git a/app/Services/ChatWebhookService.php b/app/Services/ChatWebhookService.php index e1d1e17..5f77a65 100644 --- a/app/Services/ChatWebhookService.php +++ b/app/Services/ChatWebhookService.php @@ -12,62 +12,114 @@ class ChatWebhookService { public function ensureRegistered(): bool { + return (bool) ($this->ensureRegisteredDetailed()['ok'] ?? false); + } + + /** + * @return array{ok: bool, reason: string, message: string, webhook_url: string, attempts?: int} + */ + public function ensureRegisteredDetailed(int $maxAttempts = 3): array + { + $webhookUrl = $this->webhookUrl(); $chatApi = Controller::Config('chat_api'); $chatApiKey = Controller::Config('chat_api_key'); - if (!$chatApi || !$chatApiKey) { - return false; + if (! $chatApi || ! $chatApiKey) { + return [ + 'ok' => false, + 'reason' => 'missing_chat_config', + 'message' => 'تنظیمات chat_api یا chat_api_key خالی است', + 'webhook_url' => $webhookUrl, + ]; } $host = preg_replace('#^https?://#', '', rtrim((string) $chatApi, '/')); $secret = $this->ensureSecret(); if ($host === '' || $secret === '') { - return false; + return [ + 'ok' => false, + 'reason' => 'invalid_host_or_secret', + 'message' => 'آدرس چت یا رمز وب‌هوک نامعتبر است', + 'webhook_url' => $webhookUrl, + ]; } - $webhookUrl = $this->webhookUrl(); if ($this->isUnreachableWebhookUrl($webhookUrl)) { Log::warning('chat webhook register refused: unreachable/local URL', [ 'webhook_url' => $webhookUrl, 'hint' => 'Set chat_webhook_base_url to public Laravel URL (e.g. https://niazitala.ir/server) or fix APP_URL', ]); - return false; + return [ + 'ok' => false, + 'reason' => 'unreachable_webhook_url', + 'message' => 'آدرس وب‌هوک محلی/غیرقابل‌دسترس است؛ chat_webhook_base_url را روی آدرس عمومی سرور بگذارید', + 'webhook_url' => $webhookUrl, + ]; } - try { - $response = Http::timeout(8)->post('https://'.$host.'/api/projects/set-webhook', [ - 'api_key' => $chatApiKey, - 'webhook_url' => $webhookUrl, - 'webhook_secret' => $secret, - ]); + $attempts = max(1, $maxAttempts); + $lastReason = 'unknown'; + $lastMessage = 'ثبت وب‌هوک ناموفق بود'; - if (! $response->successful()) { + for ($i = 1; $i <= $attempts; $i++) { + try { + $response = Http::timeout(8) + ->retry(0) + ->post('https://'.$host.'/api/projects/set-webhook', [ + 'api_key' => $chatApiKey, + 'webhook_url' => $webhookUrl, + 'webhook_secret' => $secret, + ]); + + if ($response->successful()) { + Log::info('chat webhook registered', [ + 'host' => $host, + 'webhook_url' => $webhookUrl, + 'attempt' => $i, + ]); + + return [ + 'ok' => true, + 'reason' => 'registered', + 'message' => 'webhook registered', + 'webhook_url' => $webhookUrl, + 'attempts' => $i, + ]; + } + + $lastReason = 'chat_api_http_'.$response->status(); + $lastMessage = 'سرور چت ثبت وب‌هوک را رد کرد (HTTP '.$response->status().')'; Log::warning('chat webhook register non-2xx', [ 'host' => $host, 'webhook_url' => $webhookUrl, 'status' => $response->status(), 'body' => mb_substr($response->body(), 0, 300), + 'attempt' => $i, + ]); + } catch (\Throwable $e) { + $lastReason = 'chat_api_exception'; + $lastMessage = 'ارتباط با سرور چت برای ثبت وب‌هوک برقرار نشد'; + Log::warning('chat webhook register failed', [ + 'host' => $host, + 'webhook_url' => $webhookUrl, + 'error' => $e->getMessage(), + 'attempt' => $i, ]); - - return false; } - Log::info('chat webhook registered', [ - 'host' => $host, - 'webhook_url' => $webhookUrl, - ]); - - return true; - } catch (\Throwable $e) { - Log::warning('chat webhook register failed', [ - 'host' => $host, - 'webhook_url' => $webhookUrl, - 'error' => $e->getMessage(), - ]); - - return false; + if ($i < $attempts) { + usleep(250000 * $i); + } } + + return [ + 'ok' => false, + 'reason' => $lastReason, + 'message' => $lastMessage, + 'webhook_url' => $webhookUrl, + 'attempts' => $attempts, + ]; } /** diff --git a/database/sql/deploy_settings_const.sql b/database/sql/deploy_settings_const.sql index 3088c02..406ee2d 100644 --- a/database/sql/deploy_settings_const.sql +++ b/database/sql/deploy_settings_const.sql @@ -405,6 +405,18 @@ SELECT 'enable_product_funds', 'false', 'قلک محصول', 0, 1, 'switch' WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'enable_product_funds' LIMIT 1); +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) +SELECT 'has_page_gift_card', 'false', 'کارت هدیه', 0, 1, + 'روشن: منوی «ثبت کارت هدیه» و صفحه ثبت کد در اپ کاربر فعال است. خاموش: منو و صفحه مخفی است و API استفاده از کد هدیه در دسترس نیست. فقط از دیپلوی قابل تغییر است.', + 'switch' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'has_page_gift_card' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) +SELECT 'enable_customer_level_profit', 'false', 'سود چندسطحی معرف', 0, 1, + 'روشن: در لیست مشتریان آیکون تنظیم درصد سود هر سطح زیرمجموعه فعال است و پس از سفارش، سهم کارمزد طبق درصدهای هر معرف به کیف طلا واریز می‌شود. خاموش: آیکون و واریز سود چندسطحی غیرفعال است. فقط از دیپلوی قابل تغییر است.', + 'switch' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'enable_customer_level_profit' LIMIT 1); + INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) SELECT 'has_page_price_trigger', 'true', 'هشدار قیمت', 0, 1, 'روشن: منوی هشدار قیمت در اپ کاربر نمایش داده می‌شود. خاموش: منو و صفحه مخفی است. فقط از دیپلوی قابل تغییر است.', @@ -773,6 +785,11 @@ SELECT 'deposit_card_number', '', 'شماره کارت واریز', 1, 1, 'شماره کارت واریز — در متن‌ها با ٪کارت یا %کارت جایگزین می‌شود.', 'text' WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'deposit_card_number' LIMIT 1); +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) +SELECT 'deposit_account_number', '', 'شماره حساب واریز', 1, 1, + 'شماره حساب بانکی واریز — در مودال راهنمای شارژ کنار کارت و شبا نمایش داده می‌شود. در متن‌ها با ٪حساب یا %حساب جایگزین می‌شود.', 'text' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'deposit_account_number' LIMIT 1); + INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) SELECT 'deposit_sheba', '', 'شبا واریز', 1, 1, 'شماره شبا واریز — در متن‌ها با ٪شبا یا %شبا جایگزین می‌شود.', 'text' @@ -1110,7 +1127,8 @@ UPDATE `settings` SET `type` = 'switch' WHERE `key` IN ( 'fee_deduct_from_gold', 'require_zero_main_gold_before_other_buy', 'profit_gold_api_enabled', 'payping_round_toman', 'payping_strict_failed_withdraw', - 'has_page_earn_money', 'has_page_price_trigger', 'has_page_notification', 'charge_notif', 'group_sms', 'sms_panel', 'customer_direct_sms', + 'has_page_earn_money', 'has_page_price_trigger', 'has_page_notification', 'has_page_gift_card', + 'enable_customer_level_profit', 'charge_notif', 'group_sms', 'sms_panel', 'customer_direct_sms', 'enable_conditional_order', 'enable_product_funds', 'sms_notif_order_admin', 'sms_notif_order_customer', 'sms_notif_withdraw_admin', 'sms_notif_withdraw_otp', 'sms_notif_login_otp', @@ -1358,6 +1376,13 @@ UPDATE `settings` SET `description` = 'شماره کارت واریز — در متن‌ها با ٪کارت یا %کارت جایگزین می‌شود.' WHERE `key` = 'deposit_card_number'; +UPDATE `settings` SET + `title_fa` = 'شماره حساب واریز', + `type` = 'text', + `can_edit` = 1, + `description` = 'شماره حساب بانکی واریز — در مودال راهنمای شارژ کنار کارت و شبا نمایش داده می‌شود. در متن‌ها با ٪حساب یا %حساب جایگزین می‌شود.' +WHERE `key` = 'deposit_account_number'; + UPDATE `settings` SET `title_fa` = 'شبا واریز', `type` = 'text', @@ -1603,6 +1628,10 @@ UPDATE `settings` SET `title_fa` = 'احراز هویت جیبیت' WHERE `key` UPDATE `settings` SET `title_fa` = 'سفارش شرطی' WHERE `key` = 'enable_conditional_order'; UPDATE `settings` SET `title_fa` = 'قلک محصول' WHERE `key` = 'enable_product_funds'; UPDATE `settings` SET `description` = 'روشن: ساخت و مدیریت قلک per-product در اپ مشتری فعال است (یک محصول در هر قلک؛ انتقال بدون سند حسابداری). خاموش: منو و API ساخت قلک جدید در دسترس نیست. فقط از دیپلوی قابل تغییر است.' WHERE `key` = 'enable_product_funds'; +UPDATE `settings` SET `title_fa` = 'کارت هدیه' WHERE `key` = 'has_page_gift_card'; +UPDATE `settings` SET `description` = 'روشن: منوی «ثبت کارت هدیه» و صفحه ثبت کد در اپ کاربر فعال است. خاموش: منو و صفحه مخفی است و API استفاده از کد هدیه در دسترس نیست. فقط از دیپلوی قابل تغییر است.' WHERE `key` = 'has_page_gift_card'; +UPDATE `settings` SET `title_fa` = 'سود چندسطحی معرف' WHERE `key` = 'enable_customer_level_profit'; +UPDATE `settings` SET `description` = 'روشن: در لیست مشتریان آیکون تنظیم درصد سود هر سطح زیرمجموعه فعال است و پس از سفارش، سهم کارمزد طبق درصدهای هر معرف به کیف طلا واریز می‌شود. خاموش: آیکون و واریز سود چندسطحی غیرفعال است. فقط از دیپلوی قابل تغییر است.' WHERE `key` = 'enable_customer_level_profit'; UPDATE `settings` SET `description` = 'روشن: امکان ارسال پیامک گروهی از پنل ادمین فعال است.' WHERE `key` = 'group_sms'; UPDATE `settings` SET `description` = 'روشن: پنل پیامک و کیف پول billing فعال است. خاموش: پیامک‌ها مثل قبل ارسال می‌شوند بدون billing.' WHERE `key` = 'sms_panel'; @@ -1817,6 +1846,7 @@ UPDATE `settings` SET `title_fa` = 'متن راهنمای واریز' WHERE `key UPDATE `settings` SET `title_fa` = 'متن پیام به پشتیبانی (واریز)' WHERE `key` = 'deposit_support_message_text'; UPDATE `settings` SET `title_fa` = 'نام صاحب حساب واریز' WHERE `key` = 'deposit_account_holder'; UPDATE `settings` SET `title_fa` = 'شماره کارت واریز' WHERE `key` = 'deposit_card_number'; +UPDATE `settings` SET `title_fa` = 'شماره حساب واریز' WHERE `key` = 'deposit_account_number'; UPDATE `settings` SET `title_fa` = 'شبا واریز' WHERE `key` = 'deposit_sheba'; UPDATE `settings` SET `title_fa` = 'حساب بانکی ته‌حساب' WHERE `key` = 'tahesab_bank_account'; UPDATE `settings` SET `title_fa` = 'نام دیتابیس ته‌حساب' WHERE `key` = 'tahesab_db'; @@ -1863,6 +1893,8 @@ UPDATE `settings` SET `can_edit` = 0 WHERE `key` IN ( 'enable_product_funds', 'has_page_price_trigger', 'has_page_notification', + 'has_page_gift_card', + 'enable_customer_level_profit', 'jibit_enabled', 'has_page_earn_money', 'is_store', @@ -1906,7 +1938,7 @@ UPDATE `settings` SET `can_edit` = 1 WHERE `key` IN ( 'sms_notif_fund_withdraw_admin', 'sms_notif_fund_withdraw_customer', 'sms_notif_price_trigger', 'sms_notif_wallet_alert', 'sms_notif_support_admin', 'deposit_sms_support_number', 'deposit_support_message_text', - 'deposit_account_holder', 'deposit_card_number', 'deposit_sheba', + 'deposit_account_holder', 'deposit_card_number', 'deposit_account_number', 'deposit_sheba', 'endDay', 'fee_free', 'fee_service_charge_percentage', 'gift_for_referral', 'gift_for_referrer', @@ -1925,7 +1957,7 @@ UPDATE `settings` SET `can_edit` = 1 WHERE `key` IN ( 'startDay', 'support_messenger', 'support_messenger_id', 'support_messenger_text', 'support_messengers', 'has_chat', - 'deposit_support_message_text', 'deposit_account_holder', 'deposit_card_number', 'deposit_sheba', + 'deposit_support_message_text', 'deposit_account_holder', 'deposit_card_number', 'deposit_account_number', 'deposit_sheba', 'text_about', 'text_rule', 'price_channel_enabled', 'price_channel_messengers', 'price_channel_diff', 'price_channel_min_seconds', 'price_channel_message_text',