428 lines
12 KiB
Python
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,
|
|
)
|