add header show SMSpanel
This commit is contained in:
@@ -37,6 +37,7 @@ class SmsPanelController extends Controller
|
|||||||
'alert_days_sent' => (int) $wallet->alert_days_sent,
|
'alert_days_sent' => (int) $wallet->alert_days_sent,
|
||||||
'last_alert_date' => $wallet->last_alert_date?->toDateString(),
|
'last_alert_date' => $wallet->last_alert_date?->toDateString(),
|
||||||
],
|
],
|
||||||
|
'deposit' => SmsWalletService::getDepositInfo(),
|
||||||
'stats' => [
|
'stats' => [
|
||||||
'today' => [
|
'today' => [
|
||||||
'parts' => (int) ($todayStats->total_parts ?? 0),
|
'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)
|
public function charge(Request $request)
|
||||||
{
|
{
|
||||||
$data = $request->validate([
|
$data = $request->validate([
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ class SmsAlertService
|
|||||||
|
|
||||||
public function maybeSendLowBalanceAlerts(SmsWallet $wallet): void
|
public function maybeSendLowBalanceAlerts(SmsWallet $wallet): void
|
||||||
{
|
{
|
||||||
if (! SmsWalletService::isBillingEnabled()) {
|
if (! SmsWalletService::isBillingOperational()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -35,9 +35,9 @@ class SmsGatewayService
|
|||||||
bool $isAlert = false
|
bool $isAlert = false
|
||||||
): SmsSendResult {
|
): SmsSendResult {
|
||||||
$config = $this->buildProviderConfig();
|
$config = $this->buildProviderConfig();
|
||||||
$billingEnabled = SmsWalletService::isBillingEnabled();
|
$billingOperational = SmsWalletService::isBillingOperational();
|
||||||
|
|
||||||
if ($billingEnabled && $this->walletService->isBlocked()) {
|
if ($billingOperational && $this->walletService->isBlocked()) {
|
||||||
return SmsSendResult::blocked();
|
return SmsSendResult::blocked();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,7 +76,7 @@ class SmsGatewayService
|
|||||||
|
|
||||||
$providerName = $this->providerLabel($provider);
|
$providerName = $this->providerLabel($provider);
|
||||||
|
|
||||||
if ($billingEnabled) {
|
if ($billingOperational) {
|
||||||
$debit = $this->walletService->debitSuccessfulSms(
|
$debit = $this->walletService->debitSuccessfulSms(
|
||||||
$to,
|
$to,
|
||||||
$text,
|
$text,
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ use App\Models\SmsLedger;
|
|||||||
use App\Models\SmsSendLog;
|
use App\Models\SmsSendLog;
|
||||||
use App\Models\SmsWallet;
|
use App\Models\SmsWallet;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
class SmsWalletService
|
class SmsWalletService
|
||||||
{
|
{
|
||||||
@@ -16,6 +17,22 @@ class SmsWalletService
|
|||||||
public const TYPE_DEBIT = 'debit';
|
public const TYPE_DEBIT = 'debit';
|
||||||
public const TYPE_ALERT_DEBIT = 'alert_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 باشد. */
|
/** Billing/panel فعال است مگر sms_panel صریحاً false باشد. */
|
||||||
public static function isBillingEnabled(): bool
|
public static function isBillingEnabled(): bool
|
||||||
{
|
{
|
||||||
@@ -30,6 +47,22 @@ class SmsWalletService
|
|||||||
return ! in_array($normalized, ['false', '0', 'no', 'off'], true);
|
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
|
public function getWallet(): SmsWallet
|
||||||
{
|
{
|
||||||
return SmsWallet::query()->firstOrCreate([], [
|
return SmsWallet::query()->firstOrCreate([], [
|
||||||
@@ -42,7 +75,7 @@ class SmsWalletService
|
|||||||
|
|
||||||
public function isBlocked(): bool
|
public function isBlocked(): bool
|
||||||
{
|
{
|
||||||
if (! self::isBillingEnabled()) {
|
if (! self::isBillingOperational()) {
|
||||||
return false;
|
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<string, string|null> $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
|
public static function isSmsPanelSuperAdmin(?object $user): bool
|
||||||
{
|
{
|
||||||
if (! $user) {
|
if (! $user) {
|
||||||
|
|||||||
@@ -207,11 +207,15 @@ Route::middleware('auth:user')->group(function (){
|
|||||||
Route::put('categories/{id}', [CategoryController::class, 'update']);
|
Route::put('categories/{id}', [CategoryController::class, 'update']);
|
||||||
Route::get('categories/{id}/active/{active}', [CategoryController::class, 'changeActive']);
|
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::middleware('sms.panel.super')->prefix('sms-panel')->group(function () {
|
||||||
Route::get('overview', [SmsPanelController::class, 'overview']);
|
Route::get('overview', [SmsPanelController::class, 'overview']);
|
||||||
Route::post('charge', [SmsPanelController::class, 'charge']);
|
Route::post('charge', [SmsPanelController::class, 'charge']);
|
||||||
Route::put('price', [SmsPanelController::class, 'updatePrice']);
|
Route::put('price', [SmsPanelController::class, 'updatePrice']);
|
||||||
Route::put('block', [SmsPanelController::class, 'updateBlock']);
|
Route::put('block', [SmsPanelController::class, 'updateBlock']);
|
||||||
|
Route::put('deposit-info', [SmsPanelController::class, 'updateDepositInfo']);
|
||||||
Route::post('logs/table', [SmsPanelController::class, 'logsTable']);
|
Route::post('logs/table', [SmsPanelController::class, 'logsTable']);
|
||||||
Route::post('ledger/table', [SmsPanelController::class, 'ledgerTable']);
|
Route::post('ledger/table', [SmsPanelController::class, 'ledgerTable']);
|
||||||
Route::get('report', [SmsPanelController::class, 'report']);
|
Route::get('report', [SmsPanelController::class, 'report']);
|
||||||
|
|||||||
Reference in New Issue
Block a user