161 lines
5.4 KiB
Python
161 lines
5.4 KiB
Python
from calendar import monthrange
|
|
from datetime import UTC, date, datetime
|
|
|
|
from fastapi import APIRouter, Depends, HTTPException, Query
|
|
from sqlalchemy import select
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
|
from app.database import get_db
|
|
from app.models.goal import Goal
|
|
from app.models.reminder import Reminder
|
|
from app.models.task import Task, TaskPriority
|
|
from app.models.todo import DailyTodo
|
|
from app.models.user import User
|
|
from app.routers.auth import get_current_user
|
|
from app.schemas.schedule_center import (
|
|
ScheduleCenterDateOut,
|
|
ScheduleCenterDaySummary,
|
|
ScheduleCenterMonthOut,
|
|
)
|
|
|
|
router = APIRouter(prefix="/api/schedule-center", tags=["调度中心"])
|
|
|
|
|
|
def _build_summary(
|
|
target_date: str,
|
|
todos: list[DailyTodo],
|
|
tasks: list[Task],
|
|
reminders: list[Reminder],
|
|
goals: list[Goal],
|
|
) -> ScheduleCenterDaySummary:
|
|
return ScheduleCenterDaySummary(
|
|
date=target_date,
|
|
todo_total=len(todos),
|
|
todo_completed=sum(1 for item in todos if item.is_completed),
|
|
task_due_total=len(tasks),
|
|
high_priority_total=sum(1 for item in tasks if item.priority in {TaskPriority.HIGH, TaskPriority.URGENT}),
|
|
reminder_total=len(reminders),
|
|
goal_total=len(goals),
|
|
)
|
|
|
|
|
|
@router.get("/month", response_model=ScheduleCenterMonthOut)
|
|
async def get_month_schedule(
|
|
year: int = Query(..., ge=2000, le=2100),
|
|
month: int = Query(..., ge=1, le=12),
|
|
current_user: User = Depends(get_current_user),
|
|
db: AsyncSession = Depends(get_db),
|
|
):
|
|
month_start = date(year, month, 1)
|
|
days_in_month = monthrange(month_start.year, month_start.month)[1]
|
|
start_key = month_start.isoformat()
|
|
end_key = month_start.replace(day=days_in_month).isoformat()
|
|
start_dt = datetime.combine(month_start, datetime.min.time())
|
|
end_dt = datetime.combine(month_start.replace(day=days_in_month), datetime.max.time())
|
|
|
|
todos = (await db.execute(
|
|
select(DailyTodo).where(DailyTodo.user_id == current_user.id, DailyTodo.todo_date >= start_key, DailyTodo.todo_date <= end_key)
|
|
)).scalars().all()
|
|
tasks = (await db.execute(
|
|
select(Task).where(
|
|
Task.user_id == current_user.id,
|
|
Task.due_date.is_not(None),
|
|
Task.due_date >= start_dt,
|
|
Task.due_date <= end_dt,
|
|
)
|
|
)).scalars().all()
|
|
reminders = (await db.execute(
|
|
select(Reminder).where(
|
|
Reminder.user_id == current_user.id,
|
|
Reminder.reminder_at >= start_dt,
|
|
Reminder.reminder_at <= end_dt,
|
|
)
|
|
)).scalars().all()
|
|
goals = (await db.execute(
|
|
select(Goal).where(Goal.user_id == current_user.id, Goal.goal_date >= start_key, Goal.goal_date <= end_key)
|
|
)).scalars().all()
|
|
|
|
todo_map: dict[str, list[DailyTodo]] = {}
|
|
for item in todos:
|
|
todo_map.setdefault(item.todo_date, []).append(item)
|
|
|
|
task_map: dict[str, list[Task]] = {}
|
|
for item in tasks:
|
|
key = item.due_date.date().isoformat()
|
|
task_map.setdefault(key, []).append(item)
|
|
|
|
reminder_map: dict[str, list[Reminder]] = {}
|
|
for item in reminders:
|
|
key = item.reminder_at.date().isoformat()
|
|
reminder_map.setdefault(key, []).append(item)
|
|
|
|
goal_map: dict[str, list[Goal]] = {}
|
|
for item in goals:
|
|
goal_map.setdefault(item.goal_date, []).append(item)
|
|
|
|
days = []
|
|
for day in range(1, days_in_month + 1):
|
|
date_key = month_start.replace(day=day).isoformat()
|
|
days.append(_build_summary(
|
|
date_key,
|
|
todo_map.get(date_key, []),
|
|
task_map.get(date_key, []),
|
|
reminder_map.get(date_key, []),
|
|
goal_map.get(date_key, []),
|
|
))
|
|
|
|
return ScheduleCenterMonthOut(month=f"{year:04d}-{month:02d}", days=days)
|
|
|
|
|
|
@router.get("/date", response_model=ScheduleCenterDateOut)
|
|
async def get_date_schedule(
|
|
date_str: date = Query(...),
|
|
current_user: User = Depends(get_current_user),
|
|
db: AsyncSession = Depends(get_db),
|
|
):
|
|
target_date = date_str
|
|
start_dt = datetime.combine(target_date, datetime.min.time())
|
|
end_dt = datetime.combine(target_date, datetime.max.time())
|
|
date_key = target_date.isoformat()
|
|
|
|
todos = (await db.execute(
|
|
select(DailyTodo)
|
|
.where(DailyTodo.user_id == current_user.id, DailyTodo.todo_date == date_key)
|
|
.order_by(DailyTodo.created_at.desc())
|
|
)).scalars().all()
|
|
tasks = (await db.execute(
|
|
select(Task)
|
|
.where(
|
|
Task.user_id == current_user.id,
|
|
Task.due_date.is_not(None),
|
|
Task.due_date >= start_dt,
|
|
Task.due_date <= end_dt,
|
|
)
|
|
.order_by(Task.created_at.desc())
|
|
)).scalars().all()
|
|
reminders = (await db.execute(
|
|
select(Reminder)
|
|
.where(
|
|
Reminder.user_id == current_user.id,
|
|
Reminder.reminder_at >= start_dt,
|
|
Reminder.reminder_at <= end_dt,
|
|
)
|
|
.order_by(Reminder.reminder_at.asc(), Reminder.created_at.asc())
|
|
)).scalars().all()
|
|
goals = (await db.execute(
|
|
select(Goal)
|
|
.where(Goal.user_id == current_user.id, Goal.goal_date == date_key)
|
|
.order_by(Goal.created_at.desc())
|
|
)).scalars().all()
|
|
|
|
summary = _build_summary(date_key, todos, tasks, reminders, goals)
|
|
return ScheduleCenterDateOut(
|
|
date=date_key,
|
|
todos=todos,
|
|
tasks=tasks,
|
|
reminders=reminders,
|
|
goals=goals,
|
|
summary=summary,
|
|
generated_at=datetime.now(UTC),
|
|
)
|