from fastapi import APIRouter, Depends, HTTPException, status from sqlalchemy.orm import Session from typing import List from datetime import datetime from ...core.database import get_db from ...models.models import Payment, PaymentStatus, User, Membership from ...schemas import ( PaymentCreate, PaymentUpdate, PaymentResponse, MessageResponse ) from ...api.dependencies import get_current_active_user, get_admin_user router = APIRouter() @router.get("/my-payments", response_model=List[PaymentResponse]) async def get_my_payments( current_user: User = Depends(get_current_active_user), db: Session = Depends(get_db) ): """Get current user's payment history""" payments = db.query(Payment).filter( Payment.user_id == current_user.id ).order_by(Payment.created_at.desc()).all() return payments @router.post("/", response_model=PaymentResponse, status_code=status.HTTP_201_CREATED) async def create_payment( payment_data: PaymentCreate, current_user: User = Depends(get_current_active_user), db: Session = Depends(get_db) ): """Create a new payment""" # Verify membership exists if provided if payment_data.membership_id: membership = db.query(Membership).filter( Membership.id == payment_data.membership_id, Membership.user_id == current_user.id ).first() if not membership: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Membership not found or does not belong to user" ) payment = Payment( user_id=current_user.id, membership_id=payment_data.membership_id, amount=payment_data.amount, payment_method=payment_data.payment_method, notes=payment_data.notes, status=PaymentStatus.PENDING ) db.add(payment) db.commit() db.refresh(payment) return payment @router.get("/{payment_id}", response_model=PaymentResponse) async def get_payment( payment_id: int, current_user: User = Depends(get_current_active_user), db: Session = Depends(get_db) ): """Get payment by ID""" payment = db.query(Payment).filter(Payment.id == payment_id).first() if not payment: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Payment not found" ) # Check if user has permission to view this payment if payment.user_id != current_user.id and current_user.role.value not in ["admin", "super_admin"]: raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail="Not authorized to view this payment" ) return payment @router.put("/{payment_id}", response_model=PaymentResponse) async def update_payment( payment_id: int, payment_update: PaymentUpdate, current_user = Depends(get_admin_user), db: Session = Depends(get_db) ): """Update payment (admin only)""" payment = db.query(Payment).filter(Payment.id == payment_id).first() if not payment: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Payment not found" ) update_data = payment_update.model_dump(exclude_unset=True) # If marking as completed, set payment_date if not already set if update_data.get("status") == PaymentStatus.COMPLETED and not payment.payment_date: update_data["payment_date"] = datetime.utcnow() for field, value in update_data.items(): setattr(payment, field, value) db.commit() db.refresh(payment) return payment @router.get("/", response_model=List[PaymentResponse]) async def list_payments( skip: int = 0, limit: int = 100, status: PaymentStatus | None = None, current_user = Depends(get_admin_user), db: Session = Depends(get_db) ): """List all payments (admin only)""" query = db.query(Payment) if status: query = query.filter(Payment.status == status) payments = query.order_by(Payment.created_at.desc()).offset(skip).limit(limit).all() return payments @router.post("/manual-payment", response_model=PaymentResponse, status_code=status.HTTP_201_CREATED) async def record_manual_payment( user_id: int, payment_data: PaymentCreate, current_user = Depends(get_admin_user), db: Session = Depends(get_db) ): """Record a manual payment (cash/check) for a user (admin only)""" # Verify user exists user = db.query(User).filter(User.id == user_id).first() if not user: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="User not found" ) # Verify membership if provided if payment_data.membership_id: membership = db.query(Membership).filter( Membership.id == payment_data.membership_id, Membership.user_id == user_id ).first() if not membership: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Membership not found or does not belong to user" ) payment = Payment( user_id=user_id, membership_id=payment_data.membership_id, amount=payment_data.amount, payment_method=payment_data.payment_method, notes=payment_data.notes, status=PaymentStatus.COMPLETED, payment_date=datetime.utcnow() ) db.add(payment) db.commit() db.refresh(payment) return payment