Files
sasa-membership/backend/app/api/v1/payments.py
James Pattinson 3751ee0076 First commit
2025-11-10 13:57:46 +00:00

182 lines
5.5 KiB
Python

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