getWallet(); $monthStart = Carbon::now()->startOfMonth(); $monthStats = SmsSendLog::query() ->where('created_at', '>=', $monthStart) ->selectRaw('COALESCE(SUM(parts), 0) as total_parts, COALESCE(SUM(total_amount), 0) as total_amount, COUNT(*) as total_messages') ->first(); $todayStats = SmsSendLog::query() ->whereDate('created_at', Carbon::today()) ->selectRaw('COALESCE(SUM(parts), 0) as total_parts, COALESCE(SUM(total_amount), 0) as total_amount, COUNT(*) as total_messages') ->first(); return response()->json([ 'wallet' => [ 'balance' => (int) $wallet->balance, 'price_per_part' => (int) $wallet->price_per_part, 'is_blocked' => (bool) $wallet->is_blocked, '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), 'amount' => (int) ($todayStats->total_amount ?? 0), 'messages' => (int) ($todayStats->total_messages ?? 0), ], 'month' => [ 'parts' => (int) ($monthStats->total_parts ?? 0), 'amount' => (int) ($monthStats->total_amount ?? 0), 'messages' => (int) ($monthStats->total_messages ?? 0), ], ], ]); } /** * خلاصه سبک کیف پول برای نمایش «اعتبار پیامک» در هدر؛ برای همه ادمین‌ها. */ 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([ 'amount' => 'required|integer|min:1', 'note' => 'nullable|string|max:500', ]); $wallet = app(SmsWalletService::class)->charge( (int) $data['amount'], auth()->id(), $data['note'] ?? null ); return response()->json([ 'message' => 'کیف پول با موفقیت شارژ شد.', 'balance' => (int) $wallet->balance, ]); } public function updatePrice(Request $request) { $data = $request->validate([ 'price_per_part' => 'required|integer|min:0', ]); $wallet = app(SmsWalletService::class)->updatePricePerPart((int) $data['price_per_part']); return response()->json([ 'message' => 'قیمت هر پارت به‌روزرسانی شد.', 'price_per_part' => (int) $wallet->price_per_part, ]); } public function updateBlock(Request $request) { $data = $request->validate([ 'is_blocked' => 'required|boolean', ]); $wallet = app(SmsWalletService::class)->setBlocked((bool) $data['is_blocked']); return response()->json([ 'message' => $wallet->is_blocked ? 'ارسال پیامک مسدود شد.' : 'ارسال پیامک فعال شد.', 'is_blocked' => (bool) $wallet->is_blocked, ]); } public function logsTable(Request $request) { $records = SmsSendLog::query()->orderByDesc('id'); if ($request->filled('from_date')) { $records->whereDate('created_at', '>=', $request->input('from_date')); } if ($request->filled('to_date')) { $records->whereDate('created_at', '<=', $request->input('to_date')); } $table = TableEngine::create($records, $request->all()) ->initSearch(['receiver', 'body', 'provider', 'source']) ->select([ 'id', 'receiver', 'body', 'parts', 'price_per_part', 'total_amount', 'provider', 'source', 'is_alert', 'created_at', ]); return response()->json($table->export()); } public function ledgerTable(Request $request) { $records = SmsLedger::query()->orderByDesc('id'); if ($request->filled('from_date')) { $records->whereDate('created_at', '>=', $request->input('from_date')); } if ($request->filled('to_date')) { $records->whereDate('created_at', '<=', $request->input('to_date')); } $table = TableEngine::create($records, $request->all()) ->initSearch(['type', 'note']) ->select([ 'id', 'type', 'amount', 'balance_after', 'price_per_part', 'parts', 'note', 'created_by', 'created_at', ]); return response()->json($table->export()); } public function report(Request $request) { $from = $request->input('from_date', Carbon::now()->startOfMonth()->toDateString()); $to = $request->input('to_date', Carbon::now()->toDateString()); $summary = SmsSendLog::query() ->whereDate('created_at', '>=', $from) ->whereDate('created_at', '<=', $to) ->selectRaw('COALESCE(SUM(parts), 0) as total_parts, COALESCE(SUM(total_amount), 0) as total_amount, COUNT(*) as total_messages') ->first(); $byProvider = SmsSendLog::query() ->whereDate('created_at', '>=', $from) ->whereDate('created_at', '<=', $to) ->select('provider', DB::raw('COUNT(*) as messages'), DB::raw('SUM(parts) as parts'), DB::raw('SUM(total_amount) as amount')) ->groupBy('provider') ->get(); $wallet = app(SmsWalletService::class)->getWallet(); return response()->json([ 'from_date' => $from, 'to_date' => $to, 'balance' => (int) $wallet->balance, 'summary' => [ 'parts' => (int) ($summary->total_parts ?? 0), 'amount' => (int) ($summary->total_amount ?? 0), 'messages' => (int) ($summary->total_messages ?? 0), ], 'by_provider' => $byProvider, ]); } public function chargeReport(Request $request) { $request->validate([ 'from_date' => 'nullable|date', 'to_date' => 'nullable|date', ]); $baseQuery = SmsLedger::query()->where('type', SmsWalletService::TYPE_CHARGE); if ($request->filled('from_date')) { $baseQuery->whereDate('created_at', '>=', $request->input('from_date')); } if ($request->filled('to_date')) { $baseQuery->whereDate('created_at', '<=', $request->input('to_date')); } $summary = (clone $baseQuery) ->selectRaw('COUNT(*) as total_charges, COALESCE(SUM(amount), 0) as total_amount') ->first(); $items = (clone $baseQuery) ->orderByDesc('created_at') ->select([ 'id', 'amount', 'balance_after', 'note', 'created_by', 'created_at', ]) ->get(); return response()->json([ 'from_date' => $request->input('from_date'), 'to_date' => $request->input('to_date'), 'summary' => [ 'charges' => (int) ($summary->total_charges ?? 0), 'amount' => (int) ($summary->total_amount ?? 0), ], 'items' => $items, ]); } }