from fastapi import APIRouter, Depends, HTTPException, status from sqlmodel import Session, select from app.core.db import get_session from app.core.auth import require_any_access, require_write_access, require_admin from app.schemas.models import Payment, Transaction from app.schemas.schemas import ( PaymentCreate, PaymentUpdate, PaymentResponse, UserResponse ) from typing import List router = APIRouter(prefix="/payments", tags=["payments"]) # Create Payment @router.post("/", response_model=PaymentResponse, status_code=status.HTTP_201_CREATED) def create_payment( payment: PaymentCreate, session: Session = Depends(get_session), current_user: UserResponse = Depends(require_write_access) ): """Create new payment (requires write access).""" # Validate transaction exists transaction = session.get(Transaction, payment.transaction_id) if not transaction: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail="Transaction not found" ) # Create payment with audit fields payment_data = payment.model_dump() payment_data["created_by"] = current_user.id payment_data["updated_by"] = current_user.id db_payment = Payment(**payment_data) session.add(db_payment) session.commit() session.refresh(db_payment) return db_payment # Read all Payments @router.get("/", response_model=List[PaymentResponse]) def read_payments( skip: int = 0, limit: int = 100, session: Session = Depends(get_session), current_user: UserResponse = Depends(require_any_access) ): """Get all payments (requires authentication).""" payments = session.exec( select(Payment).offset(skip).limit(limit) ).all() return payments # Read Payments by transaction @router.get("/transaction/{transaction_id}", response_model=List[PaymentResponse]) def read_payments_by_transaction( transaction_id: int, skip: int = 0, limit: int = 100, session: Session = Depends(get_session), current_user: UserResponse = Depends(require_any_access) ): """Get payments for a specific transaction (requires authentication).""" # Validate transaction exists transaction = session.get(Transaction, transaction_id) if not transaction: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Transaction not found" ) statement = select(Payment).where( Payment.transaction_id == transaction_id ).offset(skip).limit(limit) payments = session.exec(statement).all() return payments # Read single Payment by ID @router.get("/{payment_id}", response_model=PaymentResponse) def read_payment_by_id( payment_id: int, session: Session = Depends(get_session), current_user: UserResponse = Depends(require_any_access) ): """Get specific payment by ID (requires authentication).""" payment = session.get(Payment, payment_id) if not payment: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Payment not found" ) return payment # Update Payment @router.put("/{payment_id}", response_model=PaymentResponse) def update_payment( payment_id: int, payment: PaymentUpdate, session: Session = Depends(get_session), current_user: UserResponse = Depends(require_write_access) ): """Update specific payment (requires write access).""" db_payment = session.get(Payment, payment_id) if not db_payment: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Payment not found" ) update_data = payment.model_dump(exclude_unset=True) # Validate transaction if being updated if "transaction_id" in update_data: transaction = session.get(Transaction, update_data["transaction_id"]) if not transaction: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail="Transaction not found" ) # Track who updated update_data["updated_by"] = current_user.id # Update payment for key, value in update_data.items(): setattr(db_payment, key, value) session.add(db_payment) session.commit() session.refresh(db_payment) return db_payment # Delete Payment @router.delete("/{payment_id}", status_code=status.HTTP_204_NO_CONTENT) def delete_payment( payment_id: int, session: Session = Depends(get_session), current_user: UserResponse = Depends(require_admin) ): """Delete specific payment (admin only).""" payment = session.get(Payment, payment_id) if not payment: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Payment not found" ) session.delete(payment) session.commit() return None