feat(rw): remnawave integration
This commit is contained in:
@@ -6,16 +6,21 @@ from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from db.models import Subscription, SubscriptionAddon, User
|
||||
from db.models.orders import Order, OrderStatus
|
||||
from db.models.transactions import BalanceTransaction, BalanceTxType
|
||||
from external.rw import sync_subscription_by_telegram_id
|
||||
from schemas.enums import SubscriptionStatus
|
||||
from schemas.plans import PricingPlans
|
||||
|
||||
|
||||
def calculate_plan_monthly_price(pricing: PricingPlans, devices: int, addon_ids: list[str]) -> float:
|
||||
def calculate_plan_monthly_price(
|
||||
pricing: PricingPlans, devices: int, addon_ids: list[str]
|
||||
) -> float:
|
||||
addon_prices = {addon.id: addon.price for addon in pricing.addons}
|
||||
return devices * pricing.device_price + sum(addon_prices[addon_id] for addon_id in addon_ids)
|
||||
|
||||
|
||||
def calculate_order_total(pricing: PricingPlans, devices: int, addon_ids: list[str], duration_days: int) -> float:
|
||||
def calculate_order_total(
|
||||
pricing: PricingPlans, devices: int, addon_ids: list[str], duration_days: int
|
||||
) -> float:
|
||||
monthly_price = calculate_plan_monthly_price(pricing, devices, addon_ids)
|
||||
return monthly_price * duration_days / 30
|
||||
|
||||
@@ -29,10 +34,10 @@ def get_subscription_addon_ids(subscription: Subscription | None) -> list[str]:
|
||||
|
||||
def should_apply_immediately(
|
||||
*,
|
||||
subscription: Subscription | None,
|
||||
order: Order,
|
||||
pricing: PricingPlans,
|
||||
now: datetime,
|
||||
subscription: Subscription | None = None,
|
||||
) -> bool:
|
||||
if subscription is None or subscription.expires_at <= now:
|
||||
return True
|
||||
@@ -66,7 +71,9 @@ async def replace_subscription_addons(
|
||||
session.add(SubscriptionAddon(subscription_id=subscription_id, addon_id=addon_id))
|
||||
|
||||
|
||||
async def ensure_subscription(user: User, session: AsyncSession, starts_at: datetime) -> Subscription:
|
||||
async def ensure_subscription(
|
||||
user: User, session: AsyncSession, starts_at: datetime
|
||||
) -> Subscription:
|
||||
subscription = user.subscription
|
||||
if subscription is not None:
|
||||
return subscription
|
||||
@@ -113,7 +120,7 @@ async def apply_order_now(
|
||||
order: Order,
|
||||
pricing: PricingPlans,
|
||||
now: datetime,
|
||||
) -> None:
|
||||
) -> Subscription:
|
||||
subscription = await ensure_subscription(user, session, now)
|
||||
addon_ids = [addon.addon_id for addon in order.addons]
|
||||
current_addons = [] if subscription.devices == 0 else get_subscription_addon_ids(subscription)
|
||||
@@ -142,11 +149,10 @@ async def apply_order_now(
|
||||
await replace_subscription_addons(session, subscription.id, addon_ids)
|
||||
order.applies_at = now
|
||||
order.applied_at = now
|
||||
return subscription
|
||||
|
||||
|
||||
async def queue_order_for_later(
|
||||
*, order: Order, subscription: Subscription, now: datetime
|
||||
) -> None:
|
||||
async def queue_order_for_later(*, order: Order, subscription: Subscription, now: datetime) -> None:
|
||||
order.applies_at = max(subscription.expires_at, now)
|
||||
|
||||
|
||||
@@ -157,6 +163,7 @@ async def sync_user_subscription(
|
||||
) -> None:
|
||||
now = datetime.now(UTC)
|
||||
subscription = user.subscription
|
||||
applied_due_orders = False
|
||||
|
||||
if subscription is not None and subscription.expires_at <= now:
|
||||
due_orders = [
|
||||
@@ -181,5 +188,14 @@ async def sync_user_subscription(
|
||||
[addon.addon_id for addon in order.addons],
|
||||
)
|
||||
order.applied_at = now
|
||||
applied_due_orders = True
|
||||
else:
|
||||
subscription.status = SubscriptionStatus.EXPIRED
|
||||
|
||||
if applied_due_orders:
|
||||
await sync_subscription_by_telegram_id(
|
||||
expires_at=subscription.expires_at,
|
||||
devices=subscription.devices,
|
||||
telegram_id=user.telegram_id,
|
||||
username=user.username,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user