initial commit - LeDiscord plateforme des copains
This commit is contained in:
257
backend/api/routers/events.py
Normal file
257
backend/api/routers/events.py
Normal file
@@ -0,0 +1,257 @@
|
||||
from fastapi import APIRouter, Depends, HTTPException, status
|
||||
from sqlalchemy.orm import Session
|
||||
from typing import List
|
||||
from datetime import datetime
|
||||
from config.database import get_db
|
||||
from models.event import Event, EventParticipation, ParticipationStatus
|
||||
from models.user import User
|
||||
from models.notification import Notification, NotificationType
|
||||
from schemas.event import EventCreate, EventUpdate, EventResponse, ParticipationUpdate
|
||||
from utils.security import get_current_active_user
|
||||
from utils.email import send_event_notification
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
@router.post("/", response_model=EventResponse)
|
||||
async def create_event(
|
||||
event_data: EventCreate,
|
||||
db: Session = Depends(get_db),
|
||||
current_user: User = Depends(get_current_active_user)
|
||||
):
|
||||
"""Create a new event."""
|
||||
event = Event(
|
||||
**event_data.dict(),
|
||||
creator_id=current_user.id
|
||||
)
|
||||
db.add(event)
|
||||
db.commit()
|
||||
db.refresh(event)
|
||||
|
||||
# Create participations for all active users
|
||||
users = db.query(User).filter(User.is_active == True).all()
|
||||
for user in users:
|
||||
participation = EventParticipation(
|
||||
event_id=event.id,
|
||||
user_id=user.id,
|
||||
status=ParticipationStatus.PENDING
|
||||
)
|
||||
db.add(participation)
|
||||
|
||||
# Create notification
|
||||
if user.id != current_user.id:
|
||||
notification = Notification(
|
||||
user_id=user.id,
|
||||
type=NotificationType.EVENT_INVITATION,
|
||||
title=f"Nouvel événement: {event.title}",
|
||||
message=f"{current_user.full_name} a créé un nouvel événement",
|
||||
link=f"/events/{event.id}"
|
||||
)
|
||||
db.add(notification)
|
||||
|
||||
# Send email notification (async task would be better)
|
||||
try:
|
||||
send_event_notification(user.email, event)
|
||||
except:
|
||||
pass # Don't fail if email sending fails
|
||||
|
||||
db.commit()
|
||||
return format_event_response(event, db)
|
||||
|
||||
@router.get("/", response_model=List[EventResponse])
|
||||
async def get_events(
|
||||
db: Session = Depends(get_db),
|
||||
current_user: User = Depends(get_current_active_user),
|
||||
upcoming: bool = None
|
||||
):
|
||||
"""Get all events, optionally filtered by upcoming status."""
|
||||
query = db.query(Event)
|
||||
|
||||
if upcoming is True:
|
||||
# Only upcoming events
|
||||
query = query.filter(Event.date >= datetime.utcnow())
|
||||
elif upcoming is False:
|
||||
# Only past events
|
||||
query = query.filter(Event.date < datetime.utcnow())
|
||||
# If upcoming is None, return all events
|
||||
|
||||
events = query.order_by(Event.date.desc()).all()
|
||||
return [format_event_response(event, db) for event in events]
|
||||
|
||||
@router.get("/upcoming", response_model=List[EventResponse])
|
||||
async def get_upcoming_events(
|
||||
db: Session = Depends(get_db),
|
||||
current_user: User = Depends(get_current_active_user)
|
||||
):
|
||||
"""Get only upcoming events."""
|
||||
events = db.query(Event).filter(
|
||||
Event.date >= datetime.utcnow()
|
||||
).order_by(Event.date).all()
|
||||
return [format_event_response(event, db) for event in events]
|
||||
|
||||
@router.get("/past", response_model=List[EventResponse])
|
||||
async def get_past_events(
|
||||
db: Session = Depends(get_db),
|
||||
current_user: User = Depends(get_current_active_user)
|
||||
):
|
||||
"""Get only past events."""
|
||||
events = db.query(Event).filter(
|
||||
Event.date < datetime.utcnow()
|
||||
).order_by(Event.date.desc()).all()
|
||||
return [format_event_response(event, db) for event in events]
|
||||
|
||||
@router.get("/{event_id}", response_model=EventResponse)
|
||||
async def get_event(
|
||||
event_id: int,
|
||||
db: Session = Depends(get_db),
|
||||
current_user: User = Depends(get_current_active_user)
|
||||
):
|
||||
"""Get a specific event."""
|
||||
event = db.query(Event).filter(Event.id == event_id).first()
|
||||
if not event:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
detail="Event not found"
|
||||
)
|
||||
return format_event_response(event, db)
|
||||
|
||||
@router.put("/{event_id}", response_model=EventResponse)
|
||||
async def update_event(
|
||||
event_id: int,
|
||||
event_update: EventUpdate,
|
||||
db: Session = Depends(get_db),
|
||||
current_user: User = Depends(get_current_active_user)
|
||||
):
|
||||
"""Update an event."""
|
||||
event = db.query(Event).filter(Event.id == event_id).first()
|
||||
if not event:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
detail="Event not found"
|
||||
)
|
||||
|
||||
if event.creator_id != current_user.id and not current_user.is_admin:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_403_FORBIDDEN,
|
||||
detail="Not authorized to update this event"
|
||||
)
|
||||
|
||||
for field, value in event_update.dict(exclude_unset=True).items():
|
||||
setattr(event, field, value)
|
||||
|
||||
db.commit()
|
||||
db.refresh(event)
|
||||
return format_event_response(event, db)
|
||||
|
||||
@router.delete("/{event_id}")
|
||||
async def delete_event(
|
||||
event_id: int,
|
||||
db: Session = Depends(get_db),
|
||||
current_user: User = Depends(get_current_active_user)
|
||||
):
|
||||
"""Delete an event."""
|
||||
event = db.query(Event).filter(Event.id == event_id).first()
|
||||
if not event:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
detail="Event not found"
|
||||
)
|
||||
|
||||
if event.creator_id != current_user.id and not current_user.is_admin:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_403_FORBIDDEN,
|
||||
detail="Not authorized to delete this event"
|
||||
)
|
||||
|
||||
db.delete(event)
|
||||
db.commit()
|
||||
return {"message": "Event deleted successfully"}
|
||||
|
||||
@router.put("/{event_id}/participation", response_model=EventResponse)
|
||||
async def update_participation(
|
||||
event_id: int,
|
||||
participation_update: ParticipationUpdate,
|
||||
db: Session = Depends(get_db),
|
||||
current_user: User = Depends(get_current_active_user)
|
||||
):
|
||||
"""Update user participation status for an event."""
|
||||
participation = db.query(EventParticipation).filter(
|
||||
EventParticipation.event_id == event_id,
|
||||
EventParticipation.user_id == current_user.id
|
||||
).first()
|
||||
|
||||
if not participation:
|
||||
# Create new participation if it doesn't exist
|
||||
participation = EventParticipation(
|
||||
event_id=event_id,
|
||||
user_id=current_user.id,
|
||||
status=participation_update.status
|
||||
)
|
||||
db.add(participation)
|
||||
else:
|
||||
participation.status = participation_update.status
|
||||
participation.response_date = datetime.utcnow()
|
||||
|
||||
db.commit()
|
||||
|
||||
# Update user attendance rate
|
||||
update_user_attendance_rate(current_user, db)
|
||||
|
||||
event = db.query(Event).filter(Event.id == event_id).first()
|
||||
return format_event_response(event, db)
|
||||
|
||||
def format_event_response(event: Event, db: Session) -> dict:
|
||||
"""Format event response with participation counts."""
|
||||
participations = []
|
||||
present_count = absent_count = maybe_count = pending_count = 0
|
||||
|
||||
for p in event.participations:
|
||||
user = db.query(User).filter(User.id == p.user_id).first()
|
||||
participations.append({
|
||||
"user_id": user.id,
|
||||
"username": user.username,
|
||||
"full_name": user.full_name,
|
||||
"avatar_url": user.avatar_url,
|
||||
"status": p.status,
|
||||
"response_date": p.response_date
|
||||
})
|
||||
|
||||
if p.status == ParticipationStatus.PRESENT:
|
||||
present_count += 1
|
||||
elif p.status == ParticipationStatus.ABSENT:
|
||||
absent_count += 1
|
||||
elif p.status == ParticipationStatus.MAYBE:
|
||||
maybe_count += 1
|
||||
else:
|
||||
pending_count += 1
|
||||
|
||||
return {
|
||||
"id": event.id,
|
||||
"title": event.title,
|
||||
"description": event.description,
|
||||
"location": event.location,
|
||||
"date": event.date,
|
||||
"end_date": event.end_date,
|
||||
"creator_id": event.creator_id,
|
||||
"cover_image": event.cover_image,
|
||||
"created_at": event.created_at,
|
||||
"updated_at": event.updated_at,
|
||||
"creator_name": event.creator.full_name,
|
||||
"participations": participations,
|
||||
"present_count": present_count,
|
||||
"absent_count": absent_count,
|
||||
"maybe_count": maybe_count,
|
||||
"pending_count": pending_count
|
||||
}
|
||||
|
||||
def update_user_attendance_rate(user: User, db: Session):
|
||||
"""Update user attendance rate based on past events."""
|
||||
past_participations = db.query(EventParticipation).join(Event).filter(
|
||||
EventParticipation.user_id == user.id,
|
||||
Event.date < datetime.utcnow(),
|
||||
EventParticipation.status.in_([ParticipationStatus.PRESENT, ParticipationStatus.ABSENT])
|
||||
).all()
|
||||
|
||||
if past_participations:
|
||||
present_count = sum(1 for p in past_participations if p.status == ParticipationStatus.PRESENT)
|
||||
user.attendance_rate = (present_count / len(past_participations)) * 100
|
||||
db.commit()
|
||||
Reference in New Issue
Block a user