From 330d1cb6fe2eee81a3e8f841de75d41e8b4cde40 Mon Sep 17 00:00:00 2001 From: Fringg Date: Sun, 8 Mar 2026 12:47:25 +0300 Subject: [PATCH] fix: gift purchase notification and activation flow - Refresh purchase.user relationship after setting user_id to fix stale None value that prevented Telegram gift notifications - Route gift purchases with expired subscriptions through PENDING_ACTIVATION instead of auto-activating - Hide subscription URL from gift buyer in API response --- app/cabinet/routes/landing.py | 2 +- app/services/guest_purchase_service.py | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/cabinet/routes/landing.py b/app/cabinet/routes/landing.py index 353aa655..85316129 100644 --- a/app/cabinet/routes/landing.py +++ b/app/cabinet/routes/landing.py @@ -182,7 +182,7 @@ def _build_purchase_status_response(purchase: GuestPurchase) -> PurchaseStatusRe within_ttl = False subscription_url = None subscription_crypto_link = None - if purchase.delivered_at and purchase.subscription_url: + if purchase.delivered_at and purchase.subscription_url and not purchase.is_gift: age = datetime.now(UTC) - purchase.delivered_at if age < timedelta(hours=_SUBSCRIPTION_URL_EXPIRY_HOURS): within_ttl = True diff --git a/app/services/guest_purchase_service.py b/app/services/guest_purchase_service.py index 2604feaa..4aaf3984 100644 --- a/app/services/guest_purchase_service.py +++ b/app/services/guest_purchase_service.py @@ -219,14 +219,14 @@ async def fulfill_purchase(db: AsyncSession, purchase_token: str) -> GuestPurcha # Check if user already has a subscription existing_subscription = await get_subscription_by_user_id(db, user.id) - if existing_subscription is not None and existing_subscription.is_active: - # Active subscription — hold for manual activation + if existing_subscription is not None and (existing_subscription.is_active or purchase.is_gift): + # Active subscription or gift with any existing subscription — hold for manual activation purchase.status = GuestPurchaseStatus.PENDING_ACTIVATION.value purchase.user_id = user.id if recipient_type == 'email' and not purchase.is_gift: purchase.auto_login_token = create_auto_login_token(user.id) await db.commit() - await db.refresh(purchase, attribute_names=['landing']) + await db.refresh(purchase, attribute_names=['landing', 'user']) try: await send_guest_notification( @@ -295,7 +295,7 @@ async def fulfill_purchase(db: AsyncSession, purchase_token: str) -> GuestPurcha purchase.auto_login_token = create_auto_login_token(user.id) await db.commit() - await db.refresh(purchase, attribute_names=['landing']) + await db.refresh(purchase, attribute_names=['landing', 'user']) try: await send_guest_notification( @@ -832,7 +832,7 @@ async def activate_purchase(db: AsyncSession, purchase_token: str, *, skip_notif if user.auth_type == 'email' and not purchase.is_gift: purchase.auto_login_token = create_auto_login_token(user.id) await db.commit() - await db.refresh(purchase, attribute_names=['landing']) + await db.refresh(purchase, attribute_names=['landing', 'user']) if not skip_notification: try: