diff --git a/app/database/crud/subscription_conversion.py b/app/database/crud/subscription_conversion.py index 6ca85af2..f8764451 100644 --- a/app/database/crud/subscription_conversion.py +++ b/app/database/crud/subscription_conversion.py @@ -54,37 +54,33 @@ async def get_conversion_by_user_id( async def get_conversion_statistics(db: AsyncSession) -> dict: from app.database.models import Subscription - # Подсчитываем уникальных пользователей, у которых когда-либо был триал - users_with_trial_result = await db.execute( - select(func.count(func.distinct(Subscription.user_id))) - .where(Subscription.is_trial == True) - ) - users_with_trial = users_with_trial_result.scalar() or 0 - - # Подсчитываем пользователей, которые конвертировались из триала в платные - # Это пользователи, у которых был триал И has_had_paid_subscription = True - converted_users_result = await db.execute( - select(func.count(func.distinct(User.id))) - .join(Subscription, Subscription.user_id == User.id) - .where( - Subscription.is_trial == True, - User.has_had_paid_subscription == True - ) - ) - converted_users = converted_users_result.scalar() or 0 - - # Расчёт конверсии: (конвертировавшиеся из триала) / (всего использовавших триал) * 100 - if users_with_trial > 0: - conversion_rate = round((converted_users / users_with_trial) * 100, 1) - else: - conversion_rate = 0.0 - - # Общее количество записей о конверсиях + # Получаем количество записей о конверсиях в таблице total_conversions_result = await db.execute( select(func.count(SubscriptionConversion.id)) ) total_conversions = total_conversions_result.scalar() or 0 + # Подсчитываем пользователей с платными подписками + users_with_paid_result = await db.execute( + select(func.count(User.id)) + .where(User.has_had_paid_subscription == True) + ) + users_with_paid = users_with_paid_result.scalar() or 0 + + # Подсчитываем всех пользователей с подписками (использовавших триал) + # Считаем что все новые пользователи начинают с триала + total_users_with_subscriptions_result = await db.execute( + select(func.count(func.distinct(Subscription.user_id))) + ) + total_users_with_subscriptions = total_users_with_subscriptions_result.scalar() or 0 + + # Расчёт конверсии: (оплатившие) / (всего с подписками) * 100 + # Это показывает какой % пользователей, получивших подписку, в итоге оплатили + if total_users_with_subscriptions > 0: + conversion_rate = round((users_with_paid / total_users_with_subscriptions) * 100, 1) + else: + conversion_rate = 0.0 + avg_trial_duration_result = await db.execute( select(func.avg(SubscriptionConversion.trial_duration_days)) ) @@ -103,15 +99,15 @@ async def get_conversion_statistics(db: AsyncSession) -> dict: month_conversions = month_conversions_result.scalar() or 0 logger.info(f"📊 Статистика конверсий:") - logger.info(f" Пользователей с триалом: {users_with_trial}") - logger.info(f" Конвертировалось в платные: {converted_users}") + logger.info(f" Всего пользователей с подписками: {total_users_with_subscriptions}") + logger.info(f" Оплативших подписку: {users_with_paid}") logger.info(f" Рассчитанная конверсия: {conversion_rate}%") return { "total_conversions": total_conversions, "conversion_rate": conversion_rate, - "users_with_trial": users_with_trial, - "converted_users": converted_users, + "users_with_trial": total_users_with_subscriptions, + "converted_users": users_with_paid, "avg_trial_duration_days": round(avg_trial_duration, 1), "avg_first_payment_rubles": round((avg_first_payment or 0) / 100, 2), "month_conversions": month_conversions