from fastapi import APIRouter, HTTPException, status, Depends from typing import List from datetime import datetime from .Model import Subscription from App.Users.Model import User from App.Plans.Model import Plan from .Schema import ( CreateSubscriptionRequest, SubscriptionResponse, BaseResponse, UpdateUsageRequest, CreateCustomSubscriptionRequest, SubscriptionListResponse, ) subscription_router = APIRouter(tags=["Subscriptions"]) @subscription_router.post("/subscription/create", response_model=BaseResponse) async def create_subscription(request: CreateSubscriptionRequest): # Check if user exists user = await User.get_or_none(id=request.user_id) if not user: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="User not found" ) # Check if plan exists plan = await Plan.get_or_none(id=request.plan_id) if not plan: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Plan not found" ) # Create new subscription based on plan details expiration_time = datetime.datetime.now() + datetime.timedelta(hours=plan.duration) subscription = await Subscription.create( user=user, plan=plan, duration=plan.duration, download_mb=plan.download_speed * 1024, # Converting Mbps to MB upload_mb=plan.upload_speed * 1024, # Converting Mbps to MB expiration_time=expiration_time, active=True, ) await subscription.save() return BaseResponse( code=200, message="Subscription created successfully", payload={"subscription_id": str(subscription.id)}, ) @subscription_router.get( "/subscription/{subscription_id}", response_model=SubscriptionResponse ) async def get_subscription(subscription_id: str): subscription = await Subscription.get_or_none(id=subscription_id) if not subscription: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Subscription not found" ) remaining_hours = await subscription.time_remaining() return SubscriptionResponse( id=str(subscription.id), user_id=subscription.user_id, plan_id=subscription.plan_id, active=subscription.active, duration=subscription.duration, download_mb=subscription.download_mb, upload_mb=subscription.upload_mb, remaining_hours=remaining_hours, created_time=subscription.created_time, expiration_time=subscription.expiration_time, ) @subscription_router.get( "/subscription/user/{user_id}", response_model=List[SubscriptionResponse] ) async def get_user_subscriptions(user_id: str): user = await User.get_or_none(id=user_id) if not user: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="User not found" ) subscriptions = await Subscription.filter(user_id=user_id) result = [] for subscription in subscriptions: remaining_hours = await subscription.time_remaining() if subscription.active: result.append( SubscriptionResponse( id=str(subscription.id), user_id=subscription.user_id, plan_id=subscription.plan_id, active=subscription.active, duration=subscription.duration, download_mb=subscription.download_mb, upload_mb=subscription.upload_mb, remaining_hours=remaining_hours, created_time=subscription.created_time, expiration_time=subscription.expiration_time, ) ) return result @subscription_router.put( "/subscription/{subscription_id}/update-usage", response_model=BaseResponse ) async def update_usage(subscription_id: str, request: UpdateUsageRequest): subscription = await Subscription.get_or_none(id=subscription_id) if not subscription: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Subscription not found" ) if not await subscription.is_valid(): raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail="Subscription is not active or has expired", ) subscription.download_mb += request.download_mb subscription.upload_mb += request.upload_mb await subscription.save() return BaseResponse( code=200, message="Usage updated successfully", payload={ "total_download_mb": subscription.download_mb, "total_upload_mb": subscription.upload_mb, }, ) @subscription_router.post( "/subscription/{subscription_id}/deactivate", response_model=BaseResponse ) async def deactivate_subscription(subscription_id: str): # Fetch the subscription by ID subscription = await Subscription.get_or_none(id=subscription_id) if not subscription: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Subscription not found" ) # Fetch the associated user user = await subscription.user plan = await subscription.plan if not user: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="User not found for subscription", ) # Deactivate the subscription subscription.active = False await subscription.save() # Deactivate the user associated with this subscription await user.deactivate_user() await user.send_subcription_expired_message(plan=plan) return BaseResponse( code=200, message="Subscription and user deactivated successfully" ) from datetime import datetime, time from datetime import datetime @subscription_router.post("/subscription/custom", response_model=BaseResponse) async def create_subscription(request: CreateCustomSubscriptionRequest): # Find user by user_id or phone_number user = None if request.user_id: # Check if user_id is provided user = await User.get_or_none(id=request.user_id) elif request.phone_number: # Check if phone_number is provided user = await User.get_or_none(phoneNumber=request.phone_number) if not user: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="User not found" ) # Check if plan exists plan = await Plan.get_or_none(id=request.plan_id) if not plan: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Plan not found" ) # Parse expiration_time try: # Expecting expiration_time in "day/month" format (e.g., "12/1" for 12th January) day, month = map(int, request.expiration_time.split("/")) today = datetime.now() expiration_date = datetime( year=today.year, # Always use the current year month=month, day=day, hour=12, # Fixed time at 12 PM minute=0, second=0, ) except (ValueError, IndexError): raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail="Invalid expiration_time format. Use 'day/month' (e.g., '12/1').", ) # Validate expiration_date is not in the past if expiration_date < datetime.now(): raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail="Expiration time cannot be in the past", ) # Create new subscription based on plan details subscription = await Subscription.create( user=user, plan=plan, duration=plan.duration, download_mb=plan.download_speed * 1024, # Converting Mbps to MB upload_mb=plan.upload_speed * 1024, # Converting Mbps to MB expiration_time=expiration_date, active=True, ) await subscription.save() return BaseResponse( code=200, message="Subscription created successfully", payload={"subscription_id": str(subscription.id)}, )