Merge pull request #2112 from BEDOLAGA-DEV/dev5

Dev5
This commit is contained in:
Egor
2025-12-06 17:31:03 +03:00
committed by GitHub

View File

@@ -2,6 +2,11 @@ from __future__ import annotations
from datetime import datetime
from app.database.crud.referral import get_referral_statistics
from app.database.crud.subscription import get_subscriptions_statistics, get_trial_statistics
from app.database.crud.transaction import get_transactions_statistics
from app.database.crud.user import get_users_statistics
from fastapi import APIRouter, Depends, Security
from sqlalchemy import func, select
from sqlalchemy.ext.asyncio import AsyncSession
@@ -22,43 +27,11 @@ from ..dependencies import get_db_session, require_api_token
router = APIRouter()
@router.get(
"/overview",
summary="Общая статистика",
response_description="Агрегированные показатели пользователей, подписок, саппорта и платежей",
responses={
200: {
"content": {
"application/json": {
"example": {
"users": {
"total": 12345,
"active": 9876,
"blocked": 321,
"balance_kopeks": 1234567,
"balance_rubles": 12345.67,
},
"subscriptions": {
"active": 4321,
"expired": 210,
},
"support": {
"open_tickets": 42,
},
"payments": {
"today_kopeks": 654321,
"today_rubles": 6543.21,
},
}
}
}
}
},
)
async def stats_overview(
_: object = Security(require_api_token),
db: AsyncSession = Depends(get_db_session),
) -> dict[str, object]:
def _kopeks_to_rubles(value: int | float | None) -> float:
return round((value or 0) / 100, 2)
async def _get_overview(db: AsyncSession) -> dict[str, object]:
total_users = await db.scalar(select(func.count()).select_from(User)) or 0
active_users = await db.scalar(
select(func.count()).select_from(User).where(User.status == UserStatus.ACTIVE.value)
@@ -103,7 +76,7 @@ async def stats_overview(
"active": active_users,
"blocked": blocked_users,
"balance_kopeks": int(total_balance_kopeks),
"balance_rubles": round(total_balance_kopeks / 100, 2),
"balance_rubles": _kopeks_to_rubles(total_balance_kopeks),
},
"subscriptions": {
"active": active_subscriptions,
@@ -114,6 +87,208 @@ async def stats_overview(
},
"payments": {
"today_kopeks": int(today_transactions),
"today_rubles": round(today_transactions / 100, 2),
"today_rubles": _kopeks_to_rubles(today_transactions),
},
}
@router.get(
"/overview",
summary="Общая статистика",
response_description="Агрегированные показатели пользователей, подписок, саппорта и платежей",
responses={
200: {
"content": {
"application/json": {
"example": {
"users": {
"total": 12345,
"active": 9876,
"blocked": 321,
"balance_kopeks": 1234567,
"balance_rubles": 12345.67,
},
"subscriptions": {
"active": 4321,
"expired": 210,
},
"support": {
"open_tickets": 42,
},
"payments": {
"today_kopeks": 654321,
"today_rubles": 6543.21,
},
}
}
}
}
},
)
async def stats_overview(
_: object = Security(require_api_token),
db: AsyncSession = Depends(get_db_session),
) -> dict[str, object]:
return await _get_overview(db)
@router.get(
"/full",
summary="Полная статистика",
response_description="Расширенные показатели пользователей, подписок, платежей и рефералов",
responses={
200: {
"content": {
"application/json": {
"example": {
"overview": {
"users": {
"total": 12345,
"active": 9876,
"blocked": 321,
"balance_kopeks": 1234567,
"balance_rubles": 12345.67,
},
"subscriptions": {
"active": 4321,
"expired": 210,
},
"support": {
"open_tickets": 42,
},
"payments": {
"today_kopeks": 654321,
"today_rubles": 6543.21,
},
},
"users": {
"total_users": 12345,
"active_users": 9876,
"blocked_users": 321,
"new_today": 12,
"new_week": 345,
"new_month": 1234,
},
"subscriptions": {
"total_subscriptions": 9876,
"active_subscriptions": 8765,
"trial_subscriptions": 321,
"paid_subscriptions": 8444,
"purchased_today": 12,
"purchased_week": 210,
"purchased_month": 765,
"trial_to_paid_conversion": 42.5,
"renewals_count": 123,
"trial_statistics": {
"used_trials": 555,
"active_trials": 210,
"resettable_trials": 42,
},
},
"transactions": {
"period": {
"start_date": "2024-06-01T00:00:00Z",
"end_date": "2024-06-30T23:59:59Z",
},
"totals": {
"income_kopeks": 1234567,
"income_rubles": 12345.67,
"expenses_kopeks": 21000,
"expenses_rubles": 210,
"profit_kopeks": 1213567,
"profit_rubles": 12135.67,
"subscription_income_kopeks": 987654,
"subscription_income_rubles": 9876.54,
},
"today": {
"transactions_count": 42,
"income_kopeks": 654321,
"income_rubles": 6543.21,
},
"by_type": {
"deposit": {"count": 123, "amount": 1234567},
"withdrawal": {"count": 10, "amount": 21000},
},
"by_payment_method": {
"card": {"count": 100, "amount": 1000000}
},
},
"referrals": {
"users_with_referrals": 4321,
"active_referrers": 123,
"total_paid_kopeks": 765432,
"total_paid_rubles": 7654.32,
"today_earnings_kopeks": 12345,
"today_earnings_rubles": 123.45,
"week_earnings_kopeks": 23456,
"week_earnings_rubles": 234.56,
"month_earnings_kopeks": 34567,
"month_earnings_rubles": 345.67,
"top_referrers": [
{
"user_id": 123456789,
"display_name": "@testuser",
"username": "testuser",
"telegram_id": 123456789,
"total_earned_kopeks": 54321,
"referrals_count": 42,
}
],
},
}
}
}
}
},
)
async def stats_full(
_: object = Security(require_api_token),
db: AsyncSession = Depends(get_db_session),
) -> dict[str, object]:
overview = await _get_overview(db)
users_stats = await get_users_statistics(db)
subscriptions_stats = await get_subscriptions_statistics(db)
trial_stats = await get_trial_statistics(db)
transactions_stats = await get_transactions_statistics(db)
referral_stats = await get_referral_statistics(db)
transactions_totals = transactions_stats.get("totals", {})
transactions_today = transactions_stats.get("today", {})
transactions_totals = {
**transactions_totals,
"income_rubles": _kopeks_to_rubles(transactions_totals.get("income_kopeks")),
"expenses_rubles": _kopeks_to_rubles(transactions_totals.get("expenses_kopeks")),
"profit_rubles": _kopeks_to_rubles(transactions_totals.get("profit_kopeks")),
"subscription_income_rubles": _kopeks_to_rubles(
transactions_totals.get("subscription_income_kopeks")
),
}
transactions_today = {
**transactions_today,
"income_rubles": _kopeks_to_rubles(transactions_today.get("income_kopeks")),
}
referral_stats = {
**referral_stats,
"total_paid_rubles": _kopeks_to_rubles(referral_stats.get("total_paid_kopeks")),
"today_earnings_rubles": _kopeks_to_rubles(
referral_stats.get("today_earnings_kopeks")
),
"week_earnings_rubles": _kopeks_to_rubles(referral_stats.get("week_earnings_kopeks")),
"month_earnings_rubles": _kopeks_to_rubles(referral_stats.get("month_earnings_kopeks")),
}
return {
"overview": overview,
"users": users_stats,
"subscriptions": {**subscriptions_stats, "trial_statistics": trial_stats},
"transactions": {
**transactions_stats,
"totals": transactions_totals,
"today": transactions_today,
},
"referrals": referral_stats,
}