diff --git a/app/Http/Controllers/Admin/SmsPanelController.php b/app/Http/Controllers/Admin/SmsPanelController.php index bd0828d..87863d0 100644 --- a/app/Http/Controllers/Admin/SmsPanelController.php +++ b/app/Http/Controllers/Admin/SmsPanelController.php @@ -37,6 +37,7 @@ class SmsPanelController extends Controller 'alert_days_sent' => (int) $wallet->alert_days_sent, 'last_alert_date' => $wallet->last_alert_date?->toDateString(), ], + 'deposit' => SmsWalletService::getDepositInfo(), 'stats' => [ 'today' => [ 'parts' => (int) ($todayStats->total_parts ?? 0), @@ -52,6 +53,57 @@ class SmsPanelController extends Controller ]); } + /** + * خلاصه سبک کیف پول برای نمایش «اعتبار پیامک» در هدر؛ برای همه ادمین‌ها. + */ + public function walletSummary() + { + if (! SmsWalletService::isBillingEnabled()) { + return response()->json([ + 'enabled' => false, + 'balance' => 0, + 'is_blocked' => false, + 'deposit' => SmsWalletService::getDepositInfo(), + ]); + } + + $balance = 0; + $isBlocked = false; + + if (SmsWalletService::isBillingOperational()) { + $wallet = app(SmsWalletService::class)->getWallet(); + $balance = (int) $wallet->balance; + $isBlocked = (bool) $wallet->is_blocked; + } + + return response()->json([ + 'enabled' => true, + 'balance' => $balance, + 'is_blocked' => $isBlocked, + 'deposit' => SmsWalletService::getDepositInfo(), + ]); + } + + /** + * ویرایش اطلاعات واریز (کارت/شبا/نام/متن) — فقط سوپرادمین پنل پیامک. + */ + public function updateDepositInfo(Request $request) + { + $data = $request->validate([ + 'card_number' => 'nullable|string|max:50', + 'sheba' => 'nullable|string|max:50', + 'account_holder' => 'nullable|string|max:191', + 'note' => 'nullable|string|max:2000', + ]); + + $deposit = SmsWalletService::setDepositInfo($data); + + return response()->json([ + 'message' => 'اطلاعات واریز به‌روزرسانی شد.', + 'deposit' => $deposit, + ]); + } + public function charge(Request $request) { $data = $request->validate([ diff --git a/app/Services/SmsBilling/SmsAlertService.php b/app/Services/SmsBilling/SmsAlertService.php index db52858..218e528 100644 --- a/app/Services/SmsBilling/SmsAlertService.php +++ b/app/Services/SmsBilling/SmsAlertService.php @@ -17,7 +17,7 @@ class SmsAlertService public function maybeSendLowBalanceAlerts(SmsWallet $wallet): void { - if (! SmsWalletService::isBillingEnabled()) { + if (! SmsWalletService::isBillingOperational()) { return; } diff --git a/app/Services/SmsBilling/SmsGatewayService.php b/app/Services/SmsBilling/SmsGatewayService.php index 2674a0f..16ae92f 100644 --- a/app/Services/SmsBilling/SmsGatewayService.php +++ b/app/Services/SmsBilling/SmsGatewayService.php @@ -35,9 +35,9 @@ class SmsGatewayService bool $isAlert = false ): SmsSendResult { $config = $this->buildProviderConfig(); - $billingEnabled = SmsWalletService::isBillingEnabled(); + $billingOperational = SmsWalletService::isBillingOperational(); - if ($billingEnabled && $this->walletService->isBlocked()) { + if ($billingOperational && $this->walletService->isBlocked()) { return SmsSendResult::blocked(); } @@ -76,7 +76,7 @@ class SmsGatewayService $providerName = $this->providerLabel($provider); - if ($billingEnabled) { + if ($billingOperational) { $debit = $this->walletService->debitSuccessfulSms( $to, $text, diff --git a/app/Services/SmsBilling/SmsWalletService.php b/app/Services/SmsBilling/SmsWalletService.php index 81a54f7..03f1c66 100644 --- a/app/Services/SmsBilling/SmsWalletService.php +++ b/app/Services/SmsBilling/SmsWalletService.php @@ -7,6 +7,7 @@ use App\Models\SmsLedger; use App\Models\SmsSendLog; use App\Models\SmsWallet; use Illuminate\Support\Facades\DB; +use Illuminate\Support\Facades\Schema; class SmsWalletService { @@ -16,6 +17,22 @@ class SmsWalletService public const TYPE_DEBIT = 'debit'; public const TYPE_ALERT_DEBIT = 'alert_debit'; + /** کلیدهای تنظیمات اطلاعات واریز برای شارژ سامانه پیامکی (یکسان برای همه). */ + public const DEPOSIT_SETTING_KEYS = [ + 'card_number' => 'sms_charge_card_number', + 'sheba' => 'sms_charge_sheba', + 'account_holder' => 'sms_charge_account_holder', + 'note' => 'sms_charge_note', + ]; + + /** مقادیر پیش‌فرض اطلاعات واریز. */ + public const DEPOSIT_DEFAULTS = [ + 'card_number' => '6219861961033817', + 'sheba' => 'IR080560611828005603604401', + 'account_holder' => 'حسین منتظر', + 'note' => 'لطفا مبلغ مورد نظر خود جهت شارژ سامانه پیامکی را به شماره کارت یا حساب زیر واریز نمایید و تصویر فیش پرداختی را برای پشتیبانی بفرستید.', + ]; + /** Billing/panel فعال است مگر sms_panel صریحاً false باشد. */ public static function isBillingEnabled(): bool { @@ -30,6 +47,22 @@ class SmsWalletService return ! in_array($normalized, ['false', '0', 'no', 'off'], true); } + /** billing فعال است و جداول migration هم وجود دارند. */ + public static function isBillingOperational(): bool + { + if (! self::isBillingEnabled()) { + return false; + } + + try { + return Schema::hasTable('sms_wallets') + && Schema::hasTable('sms_send_logs') + && Schema::hasTable('sms_ledger'); + } catch (\Throwable) { + return false; + } + } + public function getWallet(): SmsWallet { return SmsWallet::query()->firstOrCreate([], [ @@ -42,7 +75,7 @@ class SmsWalletService public function isBlocked(): bool { - if (! self::isBillingEnabled()) { + if (! self::isBillingOperational()) { return false; } @@ -155,6 +188,75 @@ class SmsWalletService }); } + /** + * اطلاعات واریز جهت شارژ سامانه پیامکی؛ اگر تنظیمی ذخیره نشده باشد، مقدار پیش‌فرض برمی‌گردد. + * + * @return array{card_number: string, sheba: string, account_holder: string, note: string} + */ + public static function getDepositInfo(): array + { + $values = []; + + try { + $values = Setting::whereIn('key', array_values(self::DEPOSIT_SETTING_KEYS)) + ->pluck('value', 'key') + ->toArray(); + } catch (\Throwable) { + $values = []; + } + + $info = []; + foreach (self::DEPOSIT_SETTING_KEYS as $field => $key) { + $stored = $values[$key] ?? null; + $info[$field] = ($stored === null || trim((string) $stored) === '') + ? self::DEPOSIT_DEFAULTS[$field] + : (string) $stored; + } + + return $info; + } + + /** + * ذخیره اطلاعات واریز در تنظیمات. فقط فیلدهای ارسال‌شده به‌روزرسانی می‌شوند. + * + * @param array $data + * @return array{card_number: string, sheba: string, account_holder: string, note: string} + */ + public static function setDepositInfo(array $data): array + { + foreach (self::DEPOSIT_SETTING_KEYS as $field => $key) { + if (! array_key_exists($field, $data)) { + continue; + } + + $setting = Setting::firstOrNew(['key' => $key]); + $setting->value = (string) ($data[$field] ?? ''); + + if ($setting->title_fa === null || $setting->title_fa === '') { + $setting->title_fa = self::depositFieldTitle($field); + } + if (! $setting->exists) { + $setting->is_active = 1; + $setting->can_edit = 0; + } + + $setting->save(); + } + + return self::getDepositInfo(); + } + + private static function depositFieldTitle(string $field): string + { + return match ($field) { + 'card_number' => 'شماره کارت شارژ پیامک', + 'sheba' => 'شماره شبا شارژ پیامک', + 'account_holder' => 'نام صاحب حساب شارژ پیامک', + 'note' => 'متن راهنمای شارژ پیامک', + default => $field, + }; + } + public static function isSmsPanelSuperAdmin(?object $user): bool { if (! $user) { diff --git a/routes/admin.php b/routes/admin.php index bd37b05..3f9006c 100644 --- a/routes/admin.php +++ b/routes/admin.php @@ -207,11 +207,15 @@ Route::middleware('auth:user')->group(function (){ Route::put('categories/{id}', [CategoryController::class, 'update']); Route::get('categories/{id}/active/{active}', [CategoryController::class, 'changeActive']); + // خلاصه کیف پول پیامک برای همه ادمین‌ها (نمایش «اعتبار پیامک» در هدر) + Route::get('sms-wallet/summary', [SmsPanelController::class, 'walletSummary']); + Route::middleware('sms.panel.super')->prefix('sms-panel')->group(function () { Route::get('overview', [SmsPanelController::class, 'overview']); Route::post('charge', [SmsPanelController::class, 'charge']); Route::put('price', [SmsPanelController::class, 'updatePrice']); Route::put('block', [SmsPanelController::class, 'updateBlock']); + Route::put('deposit-info', [SmsPanelController::class, 'updateDepositInfo']); Route::post('logs/table', [SmsPanelController::class, 'logsTable']); Route::post('ledger/table', [SmsPanelController::class, 'ledgerTable']); Route::get('report', [SmsPanelController::class, 'report']);