chore: run lint and prettifier

This commit is contained in:
3252a8
2026-05-12 21:54:12 +03:00
parent f31540afdb
commit 11187487b4
174 changed files with 12383 additions and 6688 deletions
+91 -81
View File
@@ -1,18 +1,18 @@
import logging
from typing import Optional, List, Dict, Any
from datetime import datetime, timedelta, timezone
from typing import Any, Dict, List, Optional
from sqlalchemy import delete, func, or_, update
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.future import select
from sqlalchemy import update, delete, func, and_, or_
from sqlalchemy.orm import selectinload
from datetime import datetime, timezone, timedelta
from db.models import Subscription, User
from db.models import Subscription
async def get_active_subscription_by_user_id(
session: AsyncSession,
user_id: int,
panel_user_uuid: Optional[str] = None) -> Optional[Subscription]:
session: AsyncSession, user_id: int, panel_user_uuid: Optional[str] = None
) -> Optional[Subscription]:
stmt = select(Subscription).where(
Subscription.user_id == user_id,
Subscription.is_active == True,
@@ -26,26 +26,29 @@ async def get_active_subscription_by_user_id(
async def get_subscription_by_panel_subscription_uuid(
session: AsyncSession, panel_sub_uuid: str) -> Optional[Subscription]:
stmt = select(Subscription).where(
Subscription.panel_subscription_uuid == panel_sub_uuid)
session: AsyncSession, panel_sub_uuid: str
) -> Optional[Subscription]:
stmt = select(Subscription).where(Subscription.panel_subscription_uuid == panel_sub_uuid)
result = await session.execute(stmt)
return result.scalar_one_or_none()
async def get_active_subscriptions_for_user(session: AsyncSession, user_id: int) -> List[Subscription]:
async def get_active_subscriptions_for_user(
session: AsyncSession, user_id: int
) -> List[Subscription]:
"""Get all active subscriptions for a user."""
stmt = select(Subscription).where(
Subscription.user_id == user_id,
Subscription.is_active == True
).order_by(Subscription.end_date.desc())
stmt = (
select(Subscription)
.where(Subscription.user_id == user_id, Subscription.is_active == True)
.order_by(Subscription.end_date.desc())
)
result = await session.execute(stmt)
return result.scalars().all()
async def update_subscription(
session: AsyncSession, subscription_id: int,
update_data: Dict[str, Any]) -> Optional[Subscription]:
session: AsyncSession, subscription_id: int, update_data: Dict[str, Any]
) -> Optional[Subscription]:
sub = await session.get(Subscription, subscription_id)
if sub:
for key, value in update_data.items():
@@ -55,20 +58,24 @@ async def update_subscription(
return sub
async def set_auto_renew(session: AsyncSession, subscription_id: int, enabled: bool) -> Optional[Subscription]:
async def set_auto_renew(
session: AsyncSession, subscription_id: int, enabled: bool
) -> Optional[Subscription]:
"""Toggle auto_renew_enabled for a subscription."""
return await update_subscription(session, subscription_id, {"auto_renew_enabled": enabled})
async def set_user_subscriptions_cancelled_with_grace(
session: AsyncSession, user_id: int, grace_days: int = 1) -> int:
session: AsyncSession, user_id: int, grace_days: int = 1
) -> int:
"""Mark all active user subscriptions as cancelled with a short grace period.
Sets end_date to now + grace_days, status_from_panel to 'CANCELLED', and
skip future notifications to reduce noise after cancellation.
Returns number of updated rows.
"""
from datetime import datetime, timezone, timedelta
from datetime import datetime, timedelta, timezone
grace_end = datetime.now(timezone.utc) + timedelta(days=grace_days)
stmt = (
update(Subscription)
@@ -83,14 +90,12 @@ async def set_user_subscriptions_cancelled_with_grace(
return result.rowcount or 0
async def upsert_subscription(session: AsyncSession,
sub_payload: Dict[str, Any]) -> Subscription:
async def upsert_subscription(session: AsyncSession, sub_payload: Dict[str, Any]) -> Subscription:
panel_sub_uuid = sub_payload.get("panel_subscription_uuid")
if not panel_sub_uuid:
raise ValueError("panel_subscription_uuid is required for upsert.")
existing_sub = await get_subscription_by_panel_subscription_uuid(
session, panel_sub_uuid)
existing_sub = await get_subscription_by_panel_subscription_uuid(session, panel_sub_uuid)
if existing_sub:
logging.info(
@@ -103,18 +108,15 @@ async def upsert_subscription(session: AsyncSession,
await session.refresh(existing_sub)
return existing_sub
else:
logging.info(
f"Creating new subscription with panel_sub_uuid {panel_sub_uuid}")
logging.info(f"Creating new subscription with panel_sub_uuid {panel_sub_uuid}")
if sub_payload.get(
"user_id") is None and "panel_user_uuid" not in sub_payload:
raise ValueError(
"For a new subscription without user_id, panel_user_uuid is required."
)
if sub_payload.get("user_id") is None and "panel_user_uuid" not in sub_payload:
raise ValueError("For a new subscription without user_id, panel_user_uuid is required.")
if "end_date" not in sub_payload:
raise ValueError("Missing 'end_date' for new subscription.")
if sub_payload.get("user_id") is not None:
from .user_dal import get_user_by_id
user = await get_user_by_id(session, sub_payload["user_id"])
if not user:
raise ValueError(
@@ -129,15 +131,18 @@ async def upsert_subscription(session: AsyncSession,
async def deactivate_other_active_subscriptions(
session: AsyncSession, panel_user_uuid: str,
current_panel_subscription_uuid: Optional[str]) -> None:
stmt = (update(Subscription).where(
Subscription.panel_user_uuid == panel_user_uuid,
Subscription.is_active == True,
).values(is_active=False, status_from_panel="INACTIVE_BY_BOT_SYNC"))
session: AsyncSession, panel_user_uuid: str, current_panel_subscription_uuid: Optional[str]
) -> None:
stmt = (
update(Subscription)
.where(
Subscription.panel_user_uuid == panel_user_uuid,
Subscription.is_active == True,
)
.values(is_active=False, status_from_panel="INACTIVE_BY_BOT_SYNC")
)
if current_panel_subscription_uuid:
stmt = stmt.where(Subscription.panel_subscription_uuid !=
current_panel_subscription_uuid)
stmt = stmt.where(Subscription.panel_subscription_uuid != current_panel_subscription_uuid)
result = await session.execute(stmt)
if result.rowcount > 0:
@@ -146,8 +151,7 @@ async def deactivate_other_active_subscriptions(
)
async def deactivate_all_user_subscriptions(
session: AsyncSession, user_id: int) -> int:
async def deactivate_all_user_subscriptions(session: AsyncSession, user_id: int) -> int:
stmt = (
update(Subscription)
.where(Subscription.user_id == user_id, Subscription.is_active == True)
@@ -161,8 +165,7 @@ async def deactivate_all_user_subscriptions(
return result.rowcount
async def delete_all_user_subscriptions(
session: AsyncSession, user_id: int) -> int:
async def delete_all_user_subscriptions(session: AsyncSession, user_id: int) -> int:
"""Completely delete all user subscriptions (for trial reset)"""
stmt = delete(Subscription).where(Subscription.user_id == user_id)
result = await session.execute(stmt)
@@ -174,70 +177,77 @@ async def delete_all_user_subscriptions(
async def update_subscription_end_date(
session: AsyncSession, subscription_id: int,
new_end_date: datetime) -> Optional[Subscription]:
session: AsyncSession, subscription_id: int, new_end_date: datetime
) -> Optional[Subscription]:
return await update_subscription(
session, subscription_id, {
session,
subscription_id,
{
"end_date": new_end_date,
"last_notification_sent": None,
"is_active": True,
"status_from_panel": "ACTIVE_EXTENDED_BY_BOT"
})
"status_from_panel": "ACTIVE_EXTENDED_BY_BOT",
},
)
async def has_any_subscription_for_user(session: AsyncSession,
user_id: int) -> bool:
stmt = select(Subscription.subscription_id).where(
Subscription.user_id == user_id).limit(1)
async def has_any_subscription_for_user(session: AsyncSession, user_id: int) -> bool:
stmt = select(Subscription.subscription_id).where(Subscription.user_id == user_id).limit(1)
result = await session.execute(stmt)
return result.scalar_one_or_none() is not None
async def get_subscriptions_near_expiration(
session: AsyncSession, days_threshold: int) -> List[Subscription]:
session: AsyncSession, days_threshold: int
) -> List[Subscription]:
now_utc = datetime.now(timezone.utc)
threshold_date = now_utc + timedelta(days=days_threshold)
stmt = (select(Subscription).join(Subscription.user).where(
Subscription.is_active == True,
Subscription.skip_notifications == False,
Subscription.end_date > now_utc,
Subscription.end_date <= threshold_date,
or_(
Subscription.last_notification_sent == None,
func.date(Subscription.last_notification_sent)
< func.date(now_utc))).order_by(
Subscription.end_date.asc()).options(
selectinload(Subscription.user)))
stmt = (
select(Subscription)
.join(Subscription.user)
.where(
Subscription.is_active == True,
Subscription.skip_notifications == False,
Subscription.end_date > now_utc,
Subscription.end_date <= threshold_date,
or_(
Subscription.last_notification_sent == None,
func.date(Subscription.last_notification_sent) < func.date(now_utc),
),
)
.order_by(Subscription.end_date.asc())
.options(selectinload(Subscription.user))
)
result = await session.execute(stmt)
return result.scalars().all()
async def update_subscription_notification_time(
session: AsyncSession, subscription_id: int,
notification_time: datetime) -> Optional[Subscription]:
session: AsyncSession, subscription_id: int, notification_time: datetime
) -> Optional[Subscription]:
return await update_subscription(
session, subscription_id,
{"last_notification_sent": notification_time})
session, subscription_id, {"last_notification_sent": notification_time}
)
async def find_subscription_for_notification_update(
session: AsyncSession, user_id: int,
subscription_end_date_to_match: datetime) -> Optional[Subscription]:
session: AsyncSession, user_id: int, subscription_end_date_to_match: datetime
) -> Optional[Subscription]:
if subscription_end_date_to_match.tzinfo is None:
subscription_end_date_to_match = subscription_end_date_to_match.replace(
tzinfo=timezone.utc)
subscription_end_date_to_match = subscription_end_date_to_match.replace(tzinfo=timezone.utc)
stmt = select(Subscription).where(
Subscription.user_id == user_id, Subscription.is_active == True,
Subscription.end_date
>= subscription_end_date_to_match - timedelta(seconds=1),
Subscription.end_date
<= subscription_end_date_to_match + timedelta(seconds=1)).limit(1)
stmt = (
select(Subscription)
.where(
Subscription.user_id == user_id,
Subscription.is_active == True,
Subscription.end_date >= subscription_end_date_to_match - timedelta(seconds=1),
Subscription.end_date <= subscription_end_date_to_match + timedelta(seconds=1),
)
.limit(1)
)
result = await session.execute(stmt)
return result.scalar_one_or_none()