Automated Action b78ac1f072 Create comprehensive gym membership management system
Features:
- User registration and authentication with JWT tokens
- Multi-level admin access (Admin and Super Admin)
- Gym management with membership plans
- Subscription management with payment integration
- Stripe and Paystack payment gateway support
- Role-based access control
- SQLite database with Alembic migrations
- Comprehensive API endpoints with FastAPI
- Database models for users, gyms, memberships, subscriptions, and transactions
- Admin endpoints for user management and financial reporting
- Health check and documentation endpoints

Core Components:
- FastAPI application with CORS support
- SQLAlchemy ORM with relationship mapping
- JWT-based authentication with bcrypt password hashing
- Payment service abstraction for multiple gateways
- Pydantic schemas for request/response validation
- Alembic database migration system
- Admin dashboard functionality
- Environment variable configuration
2025-06-20 09:08:21 +00:00

149 lines
4.3 KiB
Python

from typing import List
from datetime import datetime, timedelta
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from app.db.session import get_db
from app.core.deps import get_current_active_user, get_current_admin_user
from app.models.subscription import Subscription, SubscriptionStatus
from app.models.membership import MembershipPlan
from app.models.user import User
from app.schemas.subscription import (
Subscription as SubscriptionSchema,
SubscriptionCreate,
SubscriptionUpdate,
)
router = APIRouter()
@router.get("/", response_model=List[SubscriptionSchema])
def read_subscriptions(
skip: int = 0,
limit: int = 100,
db: Session = Depends(get_db),
current_user: User = Depends(get_current_active_user),
):
subscriptions = (
db.query(Subscription)
.filter(Subscription.user_id == current_user.id)
.offset(skip)
.limit(limit)
.all()
)
return subscriptions
@router.get("/{subscription_id}", response_model=SubscriptionSchema)
def read_subscription(
subscription_id: int,
db: Session = Depends(get_db),
current_user: User = Depends(get_current_active_user),
):
subscription = (
db.query(Subscription)
.filter(
Subscription.id == subscription_id, Subscription.user_id == current_user.id
)
.first()
)
if not subscription:
raise HTTPException(status_code=404, detail="Subscription not found")
return subscription
@router.post("/", response_model=SubscriptionSchema)
def create_subscription(
subscription_data: SubscriptionCreate,
db: Session = Depends(get_db),
current_user: User = Depends(get_current_active_user),
):
plan = (
db.query(MembershipPlan)
.filter(
MembershipPlan.id == subscription_data.membership_plan_id,
MembershipPlan.is_active,
)
.first()
)
if not plan:
raise HTTPException(status_code=404, detail="Membership plan not found")
existing_active_subscription = (
db.query(Subscription)
.filter(
Subscription.user_id == current_user.id,
Subscription.membership_plan_id == subscription_data.membership_plan_id,
Subscription.status == SubscriptionStatus.ACTIVE,
)
.first()
)
if existing_active_subscription:
raise HTTPException(
status_code=400, detail="Active subscription already exists for this plan"
)
start_date = datetime.utcnow()
end_date = start_date + timedelta(days=plan.duration_days)
subscription = Subscription(
user_id=current_user.id,
membership_plan_id=subscription_data.membership_plan_id,
start_date=start_date,
end_date=end_date,
amount_paid=plan.price,
status=SubscriptionStatus.PENDING,
)
db.add(subscription)
db.commit()
db.refresh(subscription)
return subscription
@router.put("/{subscription_id}", response_model=SubscriptionSchema)
def update_subscription(
subscription_id: int,
subscription_update: SubscriptionUpdate,
db: Session = Depends(get_db),
current_user=Depends(get_current_admin_user),
):
subscription = (
db.query(Subscription).filter(Subscription.id == subscription_id).first()
)
if not subscription:
raise HTTPException(status_code=404, detail="Subscription not found")
update_data = subscription_update.dict(exclude_unset=True)
for field, value in update_data.items():
setattr(subscription, field, value)
db.commit()
db.refresh(subscription)
return subscription
@router.post("/{subscription_id}/cancel")
def cancel_subscription(
subscription_id: int,
db: Session = Depends(get_db),
current_user: User = Depends(get_current_active_user),
):
subscription = (
db.query(Subscription)
.filter(
Subscription.id == subscription_id, Subscription.user_id == current_user.id
)
.first()
)
if not subscription:
raise HTTPException(status_code=404, detail="Subscription not found")
if subscription.status == SubscriptionStatus.CANCELLED:
raise HTTPException(status_code=400, detail="Subscription already cancelled")
subscription.status = SubscriptionStatus.CANCELLED
db.commit()
return {"message": "Subscription cancelled successfully"}