315 lines
12 KiB
Python
315 lines
12 KiB
Python
from fastapi import APIRouter, Depends
|
|
from sqlalchemy.orm import Session
|
|
from sqlalchemy import func
|
|
from datetime import datetime, timedelta
|
|
from config.database import get_db
|
|
from models.user import User
|
|
from models.event import Event, EventParticipation, ParticipationStatus
|
|
from models.album import Album, Media
|
|
from models.post import Post
|
|
from models.vlog import Vlog
|
|
from utils.security import get_current_active_user
|
|
|
|
router = APIRouter()
|
|
|
|
@router.get("/overview")
|
|
async def get_overview_stats(
|
|
db: Session = Depends(get_db),
|
|
current_user: User = Depends(get_current_active_user)
|
|
):
|
|
"""Get general overview statistics."""
|
|
total_users = db.query(User).filter(User.is_active == True).count()
|
|
total_events = db.query(Event).count()
|
|
total_albums = db.query(Album).count()
|
|
total_posts = db.query(Post).count()
|
|
total_vlogs = db.query(Vlog).count()
|
|
total_media = db.query(Media).count()
|
|
|
|
# Recent activity (last 30 days)
|
|
thirty_days_ago = datetime.utcnow() - timedelta(days=30)
|
|
recent_events = db.query(Event).filter(Event.created_at >= thirty_days_ago).count()
|
|
recent_posts = db.query(Post).filter(Post.created_at >= thirty_days_ago).count()
|
|
recent_vlogs = db.query(Vlog).filter(Vlog.created_at >= thirty_days_ago).count()
|
|
|
|
return {
|
|
"total_users": total_users,
|
|
"total_events": total_events,
|
|
"total_albums": total_albums,
|
|
"total_posts": total_posts,
|
|
"total_vlogs": total_vlogs,
|
|
"total_media": total_media,
|
|
"recent_events": recent_events,
|
|
"recent_posts": recent_posts,
|
|
"recent_vlogs": recent_vlogs
|
|
}
|
|
|
|
@router.get("/attendance")
|
|
async def get_attendance_stats(
|
|
db: Session = Depends(get_db),
|
|
current_user: User = Depends(get_current_active_user)
|
|
):
|
|
"""Get attendance statistics for all users."""
|
|
users = db.query(User).filter(User.is_active == True).all()
|
|
|
|
attendance_stats = []
|
|
for user in users:
|
|
# Get past events participation
|
|
past_participations = db.query(EventParticipation).join(Event).filter(
|
|
EventParticipation.user_id == user.id,
|
|
Event.date < datetime.utcnow()
|
|
).all()
|
|
|
|
total_past_events = len(past_participations)
|
|
present_count = sum(1 for p in past_participations if p.status == ParticipationStatus.PRESENT)
|
|
absent_count = sum(1 for p in past_participations if p.status == ParticipationStatus.ABSENT)
|
|
|
|
# Get upcoming events participation
|
|
upcoming_participations = db.query(EventParticipation).join(Event).filter(
|
|
EventParticipation.user_id == user.id,
|
|
Event.date >= datetime.utcnow()
|
|
).all()
|
|
|
|
upcoming_present = sum(1 for p in upcoming_participations if p.status == ParticipationStatus.PRESENT)
|
|
upcoming_maybe = sum(1 for p in upcoming_participations if p.status == ParticipationStatus.MAYBE)
|
|
upcoming_pending = sum(1 for p in upcoming_participations if p.status == ParticipationStatus.PENDING)
|
|
|
|
attendance_stats.append({
|
|
"user_id": user.id,
|
|
"username": user.username,
|
|
"full_name": user.full_name,
|
|
"avatar_url": user.avatar_url,
|
|
"attendance_rate": user.attendance_rate,
|
|
"total_past_events": total_past_events,
|
|
"present_count": present_count,
|
|
"absent_count": absent_count,
|
|
"upcoming_present": upcoming_present,
|
|
"upcoming_maybe": upcoming_maybe,
|
|
"upcoming_pending": upcoming_pending
|
|
})
|
|
|
|
# Sort by attendance rate
|
|
attendance_stats.sort(key=lambda x: x["attendance_rate"], reverse=True)
|
|
|
|
return {
|
|
"attendance_stats": attendance_stats,
|
|
"best_attendee": attendance_stats[0] if attendance_stats else None,
|
|
"worst_attendee": attendance_stats[-1] if attendance_stats else None
|
|
}
|
|
|
|
@router.get("/fun")
|
|
async def get_fun_stats(
|
|
db: Session = Depends(get_db),
|
|
current_user: User = Depends(get_current_active_user)
|
|
):
|
|
"""Get fun statistics about the group."""
|
|
# Most active poster
|
|
post_counts = db.query(
|
|
User.id,
|
|
User.username,
|
|
User.full_name,
|
|
func.count(Post.id).label("post_count")
|
|
).join(Post).group_by(User.id).order_by(func.count(Post.id).desc()).first()
|
|
|
|
# Most mentioned user
|
|
mention_counts = db.query(
|
|
User.id,
|
|
User.username,
|
|
User.full_name,
|
|
func.count().label("mention_count")
|
|
).join(Post.mentions).group_by(User.id).order_by(func.count().desc()).first()
|
|
|
|
# Biggest vlogger
|
|
vlog_counts = db.query(
|
|
User.id,
|
|
User.username,
|
|
User.full_name,
|
|
func.count(Vlog.id).label("vlog_count")
|
|
).join(Vlog).group_by(User.id).order_by(func.count(Vlog.id).desc()).first()
|
|
|
|
# Photo addict (most albums created)
|
|
album_counts = db.query(
|
|
User.id,
|
|
User.username,
|
|
User.full_name,
|
|
func.count(Album.id).label("album_count")
|
|
).join(Album).group_by(User.id).order_by(func.count(Album.id).desc()).first()
|
|
|
|
# Event organizer (most events created)
|
|
event_counts = db.query(
|
|
User.id,
|
|
User.username,
|
|
User.full_name,
|
|
func.count(Event.id).label("event_count")
|
|
).join(Event, Event.creator_id == User.id).group_by(User.id).order_by(func.count(Event.id).desc()).first()
|
|
|
|
# Most viewed vlog
|
|
most_viewed_vlog = db.query(Vlog).order_by(Vlog.views_count.desc()).first()
|
|
|
|
# Longest event streak (consecutive events attended)
|
|
# This would require more complex logic to calculate
|
|
|
|
return {
|
|
"most_active_poster": {
|
|
"user_id": post_counts[0] if post_counts else None,
|
|
"username": post_counts[1] if post_counts else None,
|
|
"full_name": post_counts[2] if post_counts else None,
|
|
"post_count": post_counts[3] if post_counts else 0
|
|
} if post_counts else None,
|
|
"most_mentioned": {
|
|
"user_id": mention_counts[0] if mention_counts else None,
|
|
"username": mention_counts[1] if mention_counts else None,
|
|
"full_name": mention_counts[2] if mention_counts else None,
|
|
"mention_count": mention_counts[3] if mention_counts else 0
|
|
} if mention_counts else None,
|
|
"biggest_vlogger": {
|
|
"user_id": vlog_counts[0] if vlog_counts else None,
|
|
"username": vlog_counts[1] if vlog_counts else None,
|
|
"full_name": vlog_counts[2] if vlog_counts else None,
|
|
"vlog_count": vlog_counts[3] if vlog_counts else 0
|
|
} if vlog_counts else None,
|
|
"photo_addict": {
|
|
"user_id": album_counts[0] if album_counts else None,
|
|
"username": album_counts[1] if album_counts else None,
|
|
"full_name": album_counts[2] if album_counts else None,
|
|
"album_count": album_counts[3] if album_counts else 0
|
|
} if album_counts else None,
|
|
"event_organizer": {
|
|
"user_id": event_counts[0] if event_counts else None,
|
|
"username": event_counts[1] if event_counts else None,
|
|
"full_name": event_counts[2] if event_counts else None,
|
|
"event_count": event_counts[3] if event_counts else 0
|
|
} if event_counts else None,
|
|
"most_viewed_vlog": {
|
|
"id": most_viewed_vlog.id,
|
|
"title": most_viewed_vlog.title,
|
|
"author_name": most_viewed_vlog.author.full_name,
|
|
"views_count": most_viewed_vlog.views_count
|
|
} if most_viewed_vlog else None
|
|
}
|
|
|
|
@router.get("/user/{user_id}")
|
|
async def get_user_stats(
|
|
user_id: int,
|
|
db: Session = Depends(get_db),
|
|
current_user: User = Depends(get_current_active_user)
|
|
):
|
|
"""Get statistics for a specific user."""
|
|
user = db.query(User).filter(User.id == user_id).first()
|
|
if not user:
|
|
return {"error": "User not found"}
|
|
|
|
posts_count = db.query(Post).filter(Post.author_id == user_id).count()
|
|
vlogs_count = db.query(Vlog).filter(Vlog.author_id == user_id).count()
|
|
albums_count = db.query(Album).filter(Album.creator_id == user_id).count()
|
|
events_created = db.query(Event).filter(Event.creator_id == user_id).count()
|
|
|
|
# Get participation stats
|
|
participations = db.query(EventParticipation).filter(EventParticipation.user_id == user_id).all()
|
|
present_count = sum(1 for p in participations if p.status == ParticipationStatus.PRESENT)
|
|
absent_count = sum(1 for p in participations if p.status == ParticipationStatus.ABSENT)
|
|
maybe_count = sum(1 for p in participations if p.status == ParticipationStatus.MAYBE)
|
|
|
|
# Total views on vlogs
|
|
total_vlog_views = db.query(func.sum(Vlog.views_count)).filter(Vlog.author_id == user_id).scalar() or 0
|
|
|
|
return {
|
|
"user": {
|
|
"id": user.id,
|
|
"username": user.username,
|
|
"full_name": user.full_name,
|
|
"avatar_url": user.avatar_url,
|
|
"attendance_rate": user.attendance_rate,
|
|
"member_since": user.created_at
|
|
},
|
|
"content_stats": {
|
|
"posts_count": posts_count,
|
|
"vlogs_count": vlogs_count,
|
|
"albums_count": albums_count,
|
|
"events_created": events_created,
|
|
"total_vlog_views": total_vlog_views
|
|
},
|
|
"participation_stats": {
|
|
"total_events": len(participations),
|
|
"present_count": present_count,
|
|
"absent_count": absent_count,
|
|
"maybe_count": maybe_count
|
|
}
|
|
}
|
|
|
|
@router.get("/activity/user/{user_id}")
|
|
async def get_user_activity(
|
|
user_id: int,
|
|
db: Session = Depends(get_db),
|
|
current_user: User = Depends(get_current_active_user)
|
|
):
|
|
"""Get recent activity for a specific user."""
|
|
user = db.query(User).filter(User.id == user_id).first()
|
|
if not user:
|
|
return {"error": "User not found"}
|
|
|
|
# Get recent posts
|
|
recent_posts = db.query(Post).filter(
|
|
Post.author_id == user_id
|
|
).order_by(Post.created_at.desc()).limit(5).all()
|
|
|
|
# Get recent vlogs
|
|
recent_vlogs = db.query(Vlog).filter(
|
|
Vlog.author_id == user_id
|
|
).order_by(Vlog.created_at.desc()).limit(5).all()
|
|
|
|
# Get recent albums
|
|
recent_albums = db.query(Album).filter(
|
|
Album.creator_id == user_id
|
|
).order_by(Album.created_at.desc()).limit(5).all()
|
|
|
|
# Get recent events created
|
|
recent_events = db.query(Event).filter(
|
|
Event.creator_id == user_id
|
|
).order_by(Event.created_at.desc()).limit(5).all()
|
|
|
|
# Combine and sort by date
|
|
activities = []
|
|
|
|
for post in recent_posts:
|
|
activities.append({
|
|
"id": post.id,
|
|
"type": "post",
|
|
"description": f"A publié : {post.content[:50]}...",
|
|
"created_at": post.created_at,
|
|
"link": f"/posts/{post.id}"
|
|
})
|
|
|
|
for vlog in recent_vlogs:
|
|
activities.append({
|
|
"id": vlog.id,
|
|
"type": "vlog",
|
|
"description": f"A publié un vlog : {vlog.title}",
|
|
"created_at": vlog.created_at,
|
|
"link": f"/vlogs/{vlog.id}"
|
|
})
|
|
|
|
for album in recent_albums:
|
|
activities.append({
|
|
"id": album.id,
|
|
"type": "album",
|
|
"description": f"A créé un album : {album.title}",
|
|
"created_at": album.created_at,
|
|
"link": f"/albums/{album.id}"
|
|
})
|
|
|
|
for event in recent_events:
|
|
activities.append({
|
|
"id": event.id,
|
|
"type": "event",
|
|
"description": f"A créé un événement : {event.title}",
|
|
"created_at": event.created_at,
|
|
"link": f"/events/{event.id}"
|
|
})
|
|
|
|
# Sort by creation date (most recent first)
|
|
activities.sort(key=lambda x: x["created_at"], reverse=True)
|
|
|
|
return {
|
|
"activity": activities[:10] # Return top 10 most recent activities
|
|
}
|