47c7f17c90
— RPU v2: бюджет удачи, потолок (ceiling), комбек после проигрышей, hot/cold анализ, интеграция с promo-фазами — Bank API: mock-банк для карты (депозит/вывод с балансом 1000₽) — Promo-сервис: автогенерация промокодов каждый час, типы (card_to_site, luck_boost, ceiling_boost, free_case, reset_streak) — Promo-фазы: LUCKY/NEUTRAL/UNLUCKY, переключение каждые 1-6ч — Admin: история транзакций (user_history), управление промокодами, управление promo-фазами, API фильтров/коллекций, RPU info — Database: WAL mode, новые поля RPU v2, TransactionLog, карточный баланс, статистики (streaks, ceiling, budget) — Frontend: /deposit, /promo/activate, /withdraw, /card-balance, /online-count, /rpu-info, lifespan вместо startup event — UI: user_history.html, улучшения профиля, кейсов, навигации — Cases: обновление cases.json (1892 строки новых данных) — Achievements: кэш коллекций, оптимизация is_custom проверок — Sounds: дополнительные звуковые эффекты — Upgrade: интеграция с RPU (множители, streaks) — .gitignore: исключены .db, .bak, __pycache__
108 lines
3.7 KiB
Python
108 lines
3.7 KiB
Python
"""
|
|
BankAPI — внешний сервис для управления "картой" пользователя.
|
|
Сейчас заглушка (mock), архитектура под настоящий REST.
|
|
"""
|
|
|
|
import random
|
|
from datetime import datetime, timedelta
|
|
from typing import Optional
|
|
|
|
|
|
class BankAPIClient:
|
|
"""
|
|
Клиент для взаимодействия с Bank API.
|
|
В будущем — HTTP-клиент к внешнему сервису.
|
|
Сейчас — in-memory заглушка.
|
|
"""
|
|
|
|
def __init__(self, base_url: str = "http://bank-api:8000"):
|
|
self.base_url = base_url
|
|
# mock: user_id -> {balance, transactions}
|
|
self._mock_balances: dict[int, float] = {}
|
|
self._mock_txns: dict[int, list] = {}
|
|
self._initial_balance = 1000.0
|
|
|
|
def _ensure_user(self, user_id: int):
|
|
if user_id not in self._mock_balances:
|
|
self._mock_balances[user_id] = self._initial_balance
|
|
self._mock_txns[user_id] = []
|
|
|
|
async def get_balance(self, user_id: int) -> float:
|
|
"""Сколько денег на карте пользователя"""
|
|
self._ensure_user(user_id)
|
|
return self._mock_balances[user_id]
|
|
|
|
async def transfer_to_site(self, user_id: int, amount: float,
|
|
promo_code: Optional[str] = None) -> dict:
|
|
"""
|
|
Перевод с карты на баланс сайта.
|
|
Возвращает: {success, amount, new_card_balance, promo_effect}
|
|
"""
|
|
self._ensure_user(user_id)
|
|
if self._mock_balances[user_id] < amount:
|
|
return {"success": False, "error": "Недостаточно средств на карте"}
|
|
|
|
self._mock_balances[user_id] -= amount
|
|
self._mock_txns[user_id].append({
|
|
"type": "card_to_site",
|
|
"amount": amount,
|
|
"promo": promo_code,
|
|
"timestamp": datetime.utcnow().isoformat()
|
|
})
|
|
|
|
return {
|
|
"success": True,
|
|
"amount": amount,
|
|
"new_card_balance": self._mock_balances[user_id],
|
|
"promo_effect": None
|
|
}
|
|
|
|
async def withdraw_to_card(self, user_id: int, amount: float) -> dict:
|
|
"""
|
|
Вывод с баланса сайта на карту.
|
|
Возвращает: {success, amount, new_card_balance, fee}
|
|
"""
|
|
self._ensure_user(user_id)
|
|
fee = round(amount * 0.10, 2) # 10% комиссия
|
|
net = round(amount - fee, 2)
|
|
|
|
self._mock_balances[user_id] += net
|
|
self._mock_txns[user_id].append({
|
|
"type": "site_to_card",
|
|
"gross": amount,
|
|
"fee": fee,
|
|
"net": net,
|
|
"timestamp": datetime.utcnow().isoformat()
|
|
})
|
|
|
|
return {
|
|
"success": True,
|
|
"amount": amount,
|
|
"fee": fee,
|
|
"net": net,
|
|
"new_card_balance": self._mock_balances[user_id]
|
|
}
|
|
|
|
async def validate_promo(self, user_id: int, promo_code: str) -> dict:
|
|
"""
|
|
Проверяет промокод. Возвращает его эффект для перевода card->site.
|
|
"""
|
|
# Заглушка — реальная логика будет в PromoCode сервисе
|
|
return {
|
|
"valid": True,
|
|
"promo_type": "card_to_site",
|
|
"amount": 0,
|
|
"luck_boost": 0,
|
|
"ceiling_boost": 0
|
|
}
|
|
|
|
async def get_transaction_history(self, user_id: int,
|
|
limit: int = 50) -> list:
|
|
"""История транзакций по карте"""
|
|
self._ensure_user(user_id)
|
|
return self._mock_txns[user_id][-limit:]
|
|
|
|
|
|
# Singleton
|
|
bank_client = BankAPIClient()
|