from datetime import datetime, timezone from fastapi import APIRouter, Depends, HTTPException, status from sqlalchemy.orm import Session from typing import List from database import get_db from models.notes import SiteNote, SiteTodo from models.user import User from schemas.notes import NoteCreate, NoteUpdate, NoteOut, TodoCreate, TodoUpdate, TodoOut from routers.deps import require_manager router = APIRouter() def _utcnow(): return datetime.now(timezone.utc) def _note_out(n: SiteNote) -> dict: name = None if n.created_by: name = n.created_by.full_name or n.created_by.username return { "id": n.id, "body": n.body, "is_pinned": n.is_pinned, "created_by_id": n.created_by_id, "created_by_name": name, "created_at": n.created_at, "updated_at": n.updated_at, } def _todo_out(t: SiteTodo) -> dict: creator_name = None if t.created_by: creator_name = t.created_by.full_name or t.created_by.username done_name = None if t.done_by: done_name = t.done_by.full_name or t.done_by.username return { "id": t.id, "body": t.body, "is_done": t.is_done, "done_at": t.done_at, "done_by_id": t.done_by_id, "done_by_name": done_name, "created_by_id": t.created_by_id, "created_by_name": creator_name, "created_at": t.created_at, "priority": t.priority, } # ── Notes ───────────────────────────────────────────────────────────────────── @router.get("/", response_model=List[NoteOut]) def list_notes(db: Session = Depends(get_db), user: User = Depends(require_manager)): notes = db.query(SiteNote).order_by( SiteNote.is_pinned.desc(), SiteNote.updated_at.desc() ).all() return [_note_out(n) for n in notes] @router.post("/", response_model=NoteOut, status_code=status.HTTP_201_CREATED) def create_note(body: NoteCreate, db: Session = Depends(get_db), user: User = Depends(require_manager)): note = SiteNote(body=body.body, is_pinned=body.is_pinned, created_by_id=user.id) db.add(note) db.commit() db.refresh(note) return _note_out(note) @router.put("/{note_id}", response_model=NoteOut) def update_note(note_id: int, body: NoteUpdate, db: Session = Depends(get_db), user: User = Depends(require_manager)): note = db.query(SiteNote).filter(SiteNote.id == note_id).first() if not note: raise HTTPException(status_code=404, detail="Note not found") if body.body is not None: note.body = body.body if body.is_pinned is not None: note.is_pinned = body.is_pinned note.updated_at = _utcnow() db.commit() db.refresh(note) return _note_out(note) @router.delete("/{note_id}", status_code=status.HTTP_204_NO_CONTENT) def delete_note(note_id: int, db: Session = Depends(get_db), user: User = Depends(require_manager)): note = db.query(SiteNote).filter(SiteNote.id == note_id).first() if not note: raise HTTPException(status_code=404, detail="Note not found") db.delete(note) db.commit() # ── Todos ───────────────────────────────────────────────────────────────────── @router.get("/todos", response_model=List[TodoOut]) def list_todos(done: bool = None, db: Session = Depends(get_db), user: User = Depends(require_manager)): q = db.query(SiteTodo) if done is not None: q = q.filter(SiteTodo.is_done == done) # undone high-priority first, then undone normal, then done (by created_at desc) todos = q.order_by( SiteTodo.is_done.asc(), SiteTodo.priority.desc(), SiteTodo.created_at.desc(), ).all() return [_todo_out(t) for t in todos] @router.post("/todos", response_model=TodoOut, status_code=status.HTTP_201_CREATED) def create_todo(body: TodoCreate, db: Session = Depends(get_db), user: User = Depends(require_manager)): todo = SiteTodo(body=body.body, priority=body.priority, created_by_id=user.id) db.add(todo) db.commit() db.refresh(todo) return _todo_out(todo) @router.put("/todos/{todo_id}", response_model=TodoOut) def update_todo(todo_id: int, body: TodoUpdate, db: Session = Depends(get_db), user: User = Depends(require_manager)): todo = db.query(SiteTodo).filter(SiteTodo.id == todo_id).first() if not todo: raise HTTPException(status_code=404, detail="Todo not found") if body.body is not None: todo.body = body.body if body.priority is not None: todo.priority = body.priority if body.is_done is not None: todo.is_done = body.is_done if body.is_done and not todo.done_at: todo.done_at = _utcnow() todo.done_by_id = user.id elif not body.is_done: todo.done_at = None todo.done_by_id = None db.commit() db.refresh(todo) return _todo_out(todo) @router.delete("/todos/{todo_id}", status_code=status.HTTP_204_NO_CONTENT) def delete_todo(todo_id: int, db: Session = Depends(get_db), user: User = Depends(require_manager)): todo = db.query(SiteTodo).filter(SiteTodo.id == todo_id).first() if not todo: raise HTTPException(status_code=404, detail="Todo not found") db.delete(todo) db.commit()