feat: implement subscription management and billing enhancements
This commit is contained in:
@@ -1,15 +1,12 @@
|
||||
import datetime
|
||||
import logging
|
||||
import math
|
||||
|
||||
from aiogram.types import Message, User as TelegramUser
|
||||
from remnawave import RemnawaveSDK
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from bot.texts import (
|
||||
NO_SUBSCRIPTION,
|
||||
NOTHING_PLACEHOLDER,
|
||||
SUBSCRIPTION_INFORMATION,
|
||||
)
|
||||
from bot.texts import NO_SUBSCRIPTION, NOTHING_PLACEHOLDER, SUBSCRIPTION_INFORMATION
|
||||
from db.models.users import User
|
||||
from misc import utils
|
||||
from repositories import UserRepository
|
||||
@@ -33,8 +30,7 @@ class UserService:
|
||||
|
||||
@staticmethod
|
||||
def format_subscription_message(
|
||||
rw_user: rw.RWUserInfo | None,
|
||||
link: str | None = None,
|
||||
rw_user: rw.RWUserInfo | None, link: str | None = None, autorenew: bool = False
|
||||
):
|
||||
if rw_user is None:
|
||||
# Пользователь не найден в Remnawave
|
||||
@@ -46,6 +42,7 @@ class UserService:
|
||||
used_traffic = utils.format_traffic(rw_user.used_traffic_bytes, rw_user.traffic_limit_bytes)
|
||||
hwid_limit = utils.format_hwid_limit(rw_user.hwid_device_limit)
|
||||
link = link or NOTHING_PLACEHOLDER
|
||||
autorenew_text = "🟢" if autorenew else "🔴"
|
||||
|
||||
return SUBSCRIPTION_INFORMATION.format(
|
||||
status_icon=status_icon,
|
||||
@@ -55,6 +52,7 @@ class UserService:
|
||||
used_traffic=used_traffic,
|
||||
hwid_limit=hwid_limit,
|
||||
link=link,
|
||||
autorenew=autorenew_text,
|
||||
)
|
||||
|
||||
async def add_user(
|
||||
@@ -147,7 +145,13 @@ class UserService:
|
||||
duration_days=duration.days,
|
||||
)
|
||||
|
||||
await rw.add_days(rw_sdk, rw_user.uuid, duration.days)
|
||||
if not utils.is_same_plan(rw_user, subscription):
|
||||
new_expire = datetime.datetime.now(datetime.UTC) + duration
|
||||
delta_days = (new_expire - rw_user.expire_at).days
|
||||
await rw.add_days(rw_sdk, rw_user.uuid, delta_days)
|
||||
else:
|
||||
await rw.add_days(rw_sdk, rw_user.uuid, duration.days)
|
||||
|
||||
await rw.update_squads(rw_sdk, rw_user.uuid, squads)
|
||||
await rw.set_hwid_limit(rw_sdk, rw_user.uuid, subscription.devices)
|
||||
|
||||
@@ -198,3 +202,25 @@ class UserService:
|
||||
await self.update_user_link(session, user.id, rw_sdk)
|
||||
|
||||
return db_subscription
|
||||
|
||||
async def calculate_plan_credit(
|
||||
self,
|
||||
session: AsyncSession,
|
||||
user_id: int,
|
||||
new_plan: SubscriptionPlan,
|
||||
rw_sdk: RemnawaveSDK,
|
||||
) -> int:
|
||||
rw_user = await rw.get_user_by_telegram_id(rw_sdk, user_id)
|
||||
|
||||
if not rw_user or rw_user.expire_at <= datetime.datetime.now(datetime.UTC):
|
||||
return 0
|
||||
|
||||
if utils.is_same_plan(rw_user, new_plan):
|
||||
return 0
|
||||
|
||||
db_sub = await self.subscription_repository.get_subscription_by_user_id(session, user_id)
|
||||
if not db_sub or not db_sub.plan_price_paid or not db_sub.duration_days:
|
||||
return 0
|
||||
|
||||
remaining_days = max(0, (rw_user.expire_at - datetime.datetime.now(datetime.UTC)).days)
|
||||
return math.floor(db_sub.plan_price_paid * remaining_days / db_sub.duration_days)
|
||||
|
||||
Reference in New Issue
Block a user