2025-07-01 12:54:48 +00:00

428 lines
12 KiB
Python

from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from sqlalchemy import or_, and_
from typing import List, Optional
from datetime import datetime
from app.db.base import get_db
from app.models.user import User, Connection
from app.models.ministry import MinistryMember
from app.models.prayer import (
PrayerRequest,
Prayer,
PrayerPrivacyLevel,
PrayerStatus,
PrayerCategory,
)
from app.schemas.prayer import (
PrayerRequestCreate,
PrayerRequestUpdate,
PrayerRequestResponse,
PrayerCreate,
PrayerResponse,
PrayerStats,
)
from app.api.auth import get_current_user
router = APIRouter()
def can_view_prayer_request(
prayer_request: PrayerRequest, current_user: User, db: Session
) -> bool:
"""Check if user can view a prayer request based on privacy level"""
if prayer_request.requester_id == current_user.id:
return True
if prayer_request.privacy_level == PrayerPrivacyLevel.PUBLIC:
return True
if prayer_request.privacy_level == PrayerPrivacyLevel.PRIVATE:
return False
if prayer_request.privacy_level == PrayerPrivacyLevel.CONNECTIONS_ONLY:
# Check if users are connected
connection = (
db.query(Connection)
.filter(
or_(
and_(
Connection.sender_id == current_user.id,
Connection.receiver_id == prayer_request.requester_id,
),
and_(
Connection.sender_id == prayer_request.requester_id,
Connection.receiver_id == current_user.id,
),
),
Connection.status == "accepted",
)
.first()
)
return connection is not None
if (
prayer_request.privacy_level == PrayerPrivacyLevel.MINISTRY_ONLY
and prayer_request.ministry_id
):
# Check if user is in the same ministry
membership = (
db.query(MinistryMember)
.filter(
MinistryMember.ministry_id == prayer_request.ministry_id,
MinistryMember.user_id == current_user.id,
MinistryMember.is_active,
)
.first()
)
return membership is not None
return False
@router.post("/", response_model=PrayerRequestResponse)
def create_prayer_request(
prayer_request: PrayerRequestCreate,
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user),
):
"""Create a new prayer request"""
# Validate ministry access if ministry_only privacy
if (
prayer_request.privacy_level == PrayerPrivacyLevel.MINISTRY_ONLY
and prayer_request.ministry_id
):
membership = (
db.query(MinistryMember)
.filter(
MinistryMember.ministry_id == prayer_request.ministry_id,
MinistryMember.user_id == current_user.id,
MinistryMember.is_active,
)
.first()
)
if not membership:
raise HTTPException(
status_code=403,
detail="Must be a ministry member to create ministry-only requests",
)
db_request = PrayerRequest(**prayer_request.dict(), requester_id=current_user.id)
db.add(db_request)
db.commit()
db.refresh(db_request)
# Add response metadata
db_request.requester_name = (
f"{current_user.first_name} {current_user.last_name}"
if not db_request.is_anonymous
else "Anonymous"
)
db_request.prayer_count = 0
db_request.has_prayed = False
if db_request.ministry_id:
db_request.ministry_name = db_request.ministry.name
return db_request
@router.get("/", response_model=List[PrayerRequestResponse])
def get_prayer_requests(
skip: int = 0,
limit: int = 100,
category: Optional[PrayerCategory] = None,
status: Optional[PrayerStatus] = None,
privacy_level: Optional[PrayerPrivacyLevel] = None,
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user),
):
"""Get prayer requests based on user's access level"""
query = db.query(PrayerRequest)
# Apply filters
if category:
query = query.filter(PrayerRequest.category == category)
if status:
query = query.filter(PrayerRequest.status == status)
if privacy_level:
query = query.filter(PrayerRequest.privacy_level == privacy_level)
prayer_requests = (
query.order_by(PrayerRequest.created_at.desc()).offset(skip).limit(limit).all()
)
# Filter based on privacy and add metadata
accessible_requests = []
for request in prayer_requests:
if can_view_prayer_request(request, current_user, db):
# Add metadata
request.requester_name = (
f"{request.requester.first_name} {request.requester.last_name}"
if not request.is_anonymous
else "Anonymous"
)
request.prayer_count = (
db.query(Prayer).filter(Prayer.prayer_request_id == request.id).count()
)
request.has_prayed = (
db.query(Prayer)
.filter(
Prayer.prayer_request_id == request.id,
Prayer.prayer_warrior_id == current_user.id,
)
.first()
is not None
)
if request.ministry_id:
request.ministry_name = request.ministry.name
accessible_requests.append(request)
return accessible_requests
@router.get("/my-requests", response_model=List[PrayerRequestResponse])
def get_my_prayer_requests(
db: Session = Depends(get_db), current_user: User = Depends(get_current_user)
):
"""Get current user's prayer requests"""
requests = (
db.query(PrayerRequest)
.filter(PrayerRequest.requester_id == current_user.id)
.order_by(PrayerRequest.created_at.desc())
.all()
)
for request in requests:
request.requester_name = f"{current_user.first_name} {current_user.last_name}"
request.prayer_count = (
db.query(Prayer).filter(Prayer.prayer_request_id == request.id).count()
)
request.has_prayed = False # Can't pray for own request
if request.ministry_id:
request.ministry_name = request.ministry.name
return requests
@router.get("/{request_id}", response_model=PrayerRequestResponse)
def get_prayer_request(
request_id: int,
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user),
):
"""Get specific prayer request"""
prayer_request = (
db.query(PrayerRequest).filter(PrayerRequest.id == request_id).first()
)
if not prayer_request:
raise HTTPException(status_code=404, detail="Prayer request not found")
if not can_view_prayer_request(prayer_request, current_user, db):
raise HTTPException(
status_code=403, detail="Access denied to this prayer request"
)
# Add metadata
prayer_request.requester_name = (
f"{prayer_request.requester.first_name} {prayer_request.requester.last_name}"
if not prayer_request.is_anonymous
else "Anonymous"
)
prayer_request.prayer_count = (
db.query(Prayer).filter(Prayer.prayer_request_id == prayer_request.id).count()
)
prayer_request.has_prayed = (
db.query(Prayer)
.filter(
Prayer.prayer_request_id == prayer_request.id,
Prayer.prayer_warrior_id == current_user.id,
)
.first()
is not None
)
if prayer_request.ministry_id:
prayer_request.ministry_name = prayer_request.ministry.name
return prayer_request
@router.put("/{request_id}", response_model=PrayerRequestResponse)
def update_prayer_request(
request_id: int,
prayer_update: PrayerRequestUpdate,
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user),
):
"""Update prayer request (owner only)"""
prayer_request = (
db.query(PrayerRequest).filter(PrayerRequest.id == request_id).first()
)
if not prayer_request:
raise HTTPException(status_code=404, detail="Prayer request not found")
if prayer_request.requester_id != current_user.id:
raise HTTPException(
status_code=403, detail="Can only update own prayer requests"
)
# Handle status changes
update_data = prayer_update.dict(exclude_unset=True)
if "status" in update_data and update_data["status"] == PrayerStatus.ANSWERED:
if not update_data.get("answer_description"):
raise HTTPException(
status_code=400,
detail="Answer description required when marking as answered",
)
update_data["answered_at"] = datetime.utcnow()
# Update fields
for field, value in update_data.items():
setattr(prayer_request, field, value)
db.commit()
db.refresh(prayer_request)
return prayer_request
@router.post("/{request_id}/pray", response_model=PrayerResponse)
def pray_for_request(
request_id: int,
prayer: PrayerCreate,
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user),
):
"""Pray for a prayer request"""
prayer_request = (
db.query(PrayerRequest).filter(PrayerRequest.id == request_id).first()
)
if not prayer_request:
raise HTTPException(status_code=404, detail="Prayer request not found")
if not can_view_prayer_request(prayer_request, current_user, db):
raise HTTPException(
status_code=403, detail="Access denied to this prayer request"
)
if prayer_request.requester_id == current_user.id:
raise HTTPException(status_code=400, detail="Cannot pray for your own request")
# Check if already prayed
existing_prayer = (
db.query(Prayer)
.filter(
Prayer.prayer_request_id == request_id,
Prayer.prayer_warrior_id == current_user.id,
)
.first()
)
if existing_prayer:
raise HTTPException(status_code=400, detail="Already prayed for this request")
db_prayer = Prayer(
prayer_request_id=request_id,
prayer_warrior_id=current_user.id,
message=prayer.message,
)
db.add(db_prayer)
db.commit()
db.refresh(db_prayer)
db_prayer.prayer_warrior_name = (
f"{current_user.first_name} {current_user.last_name}"
)
return db_prayer
@router.get("/{request_id}/prayers", response_model=List[PrayerResponse])
def get_prayers_for_request(
request_id: int,
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user),
):
"""Get prayers for a specific request"""
prayer_request = (
db.query(PrayerRequest).filter(PrayerRequest.id == request_id).first()
)
if not prayer_request:
raise HTTPException(status_code=404, detail="Prayer request not found")
if not can_view_prayer_request(prayer_request, current_user, db):
raise HTTPException(
status_code=403, detail="Access denied to this prayer request"
)
prayers = (
db.query(Prayer)
.filter(Prayer.prayer_request_id == request_id)
.order_by(Prayer.prayed_at.desc())
.all()
)
for prayer in prayers:
prayer.prayer_warrior_name = (
f"{prayer.prayer_warrior.first_name} {prayer.prayer_warrior.last_name}"
)
return prayers
@router.get("/stats/personal", response_model=PrayerStats)
def get_personal_prayer_stats(
db: Session = Depends(get_db), current_user: User = Depends(get_current_user)
):
"""Get personal prayer statistics"""
total_requests = db.query(PrayerRequest).count()
active_requests = (
db.query(PrayerRequest)
.filter(PrayerRequest.status == PrayerStatus.ACTIVE)
.count()
)
answered_requests = (
db.query(PrayerRequest)
.filter(PrayerRequest.status == PrayerStatus.ANSWERED)
.count()
)
prayers_offered = (
db.query(Prayer).filter(Prayer.prayer_warrior_id == current_user.id).count()
)
requests_created = (
db.query(PrayerRequest)
.filter(PrayerRequest.requester_id == current_user.id)
.count()
)
return PrayerStats(
total_requests=total_requests,
active_requests=active_requests,
answered_requests=answered_requests,
prayers_offered=prayers_offered,
requests_created=requests_created,
)