77 lines
2.8 KiB
Python
77 lines
2.8 KiB
Python
from __future__ import annotations
|
|
|
|
from typing import TYPE_CHECKING
|
|
|
|
from config import (
|
|
CASHBACK as DEFAULT_CASHBACK,
|
|
REFERRAL_BONUS_PERCENTAGES,
|
|
)
|
|
from core.bootstrap import MONEY_CONFIG
|
|
from database import add_payment
|
|
from database.access.resolution import resolve_user_optional
|
|
from database.referrals import get_referral_by_referred_id
|
|
from database.users import update_balance
|
|
from logger import logger
|
|
|
|
|
|
if TYPE_CHECKING:
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
|
|
|
async def process_referrals(session: AsyncSession, user_id: int, amount: float) -> dict[int, float]:
|
|
"""Начисляет реферальные бонусы по цепочке.
|
|
|
|
Returns: dict {referrer_id: bonus_amount} — для логирования/уведомлений.
|
|
"""
|
|
u = await resolve_user_optional(session, user_id)
|
|
if u is None:
|
|
return {}
|
|
|
|
max_levels = len(REFERRAL_BONUS_PERCENTAGES)
|
|
current_id = u.id
|
|
bonus_by_chain: dict[int, tuple[float, int]] = {}
|
|
|
|
for level in range(1, max_levels + 1):
|
|
referral = await get_referral_by_referred_id(session, current_id)
|
|
if not referral:
|
|
break
|
|
referrer_id = int(referral["referrer_user_id"])
|
|
percent = REFERRAL_BONUS_PERCENTAGES.get(level)
|
|
if not percent:
|
|
continue
|
|
bonus = amount * percent if isinstance(percent, float) else percent
|
|
bonus_by_chain[referrer_id] = (bonus, level)
|
|
current_id = referrer_id
|
|
|
|
result_map: dict[int, float] = {}
|
|
for referrer_id, (bonus, lvl) in bonus_by_chain.items():
|
|
await update_balance(session, referrer_id, float(bonus))
|
|
await add_payment(session, tg_id=referrer_id, amount=bonus, payment_system="referral")
|
|
logger.info(f"Начислен бонус {bonus}₽ пользователю {referrer_id} за уровень {lvl}")
|
|
result_map[referrer_id] = bonus
|
|
|
|
return result_map
|
|
|
|
|
|
async def process_cashback(session: AsyncSession, user_id: int, amount: float) -> float:
|
|
"""Начисляет кэшбэк на баланс пользователя.
|
|
|
|
Returns: сумма кэшбэка (0 если отключён).
|
|
"""
|
|
cashback_config = MONEY_CONFIG.get("CASHBACK", DEFAULT_CASHBACK)
|
|
try:
|
|
cashback_percent = float(cashback_config) if cashback_config not in (None, False) else 0.0
|
|
except (TypeError, ValueError):
|
|
cashback_percent = 0.0
|
|
|
|
if cashback_percent <= 0:
|
|
return 0.0
|
|
|
|
cashback_amount = round(amount * (cashback_percent / 100))
|
|
if cashback_amount > 0:
|
|
await update_balance(session, user_id, cashback_amount)
|
|
await add_payment(session, tg_id=user_id, amount=cashback_amount, payment_system="cashback")
|
|
logger.info(f"Начислен кешбэк {cashback_amount}₽ пользователю {user_id}")
|
|
|
|
return float(cashback_amount)
|