diff --git a/backend/src/routes/projects.py b/backend/src/routes/projects.py index a97c773..f6baa43 100644 --- a/backend/src/routes/projects.py +++ b/backend/src/routes/projects.py @@ -1,66 +1,96 @@ import logging from datetime import datetime, timedelta -from fastapi import APIRouter, status, Path -from src.models.project import ProjectCreate, ProjectRead +import sqlalchemy.exc +from fastapi import APIRouter, status, Path, Depends, HTTPException +from sqlmodel import Session, select + +from src import database +from src.models.project import ProjectCreate, ProjectRead, Project router = APIRouter(prefix='/projects', tags=["Projects"]) @router.get("/", response_model=list[ProjectRead], summary="Get a list of all projects") -async def all_projects() -> list[ProjectRead]: +async def all_projects( + *, + session: Session = Depends(database.get_session) +) -> list[Project]: """Returns a list of all projects""" - return [ - ProjectRead( - name="Learning", - start_date=datetime.now(), - duration=timedelta(days=3, hours=5, minutes=47), - records=42 - ), - ProjectRead( - name="Sports", - start_date=datetime.now(), - duration=timedelta(hours=14, minutes=10), - records=10 - ), - ProjectRead( - name="Gaming", - start_date=datetime.now(), - duration=timedelta(hours=3, minutes=2), - records=5 - ) - ] + projects = session.exec(select(Project)).all() + return projects -@router.post("/", status_code=status.HTTP_201_CREATED, summary="Add a project") -async def add_project(project: ProjectCreate): +@router.post("/", status_code=status.HTTP_201_CREATED, summary="Add a project", response_model=ProjectRead) +async def add_project( + *, + project: ProjectCreate, + session: Session = Depends(database.get_session) +): """Add a project.""" - print('adding project', project) + db_project = Project.from_orm(project) + session.add(db_project) + session.commit() + session.refresh(db_project) + return db_project @router.get("/{name}", response_model=ProjectRead, summary="Get a project by name") -async def get_project(name: str = Path(..., title="Name of the module")) -> ProjectRead: +async def get_project( + *, + name: str = Path(..., title="Name of the module"), + session: Session = Depends(database.get_session) +) -> Project: """Fetch a project by name.""" - return ProjectRead( - name=name, - start_date=datetime.now(), - duration=timedelta(hours=3, minutes=2), - records=5 - ) + try: + project = session.exec(select(Project).where(Project.name == name)).one() + return project + except sqlalchemy.exc.NoResultFound: + raise HTTPException(status_code=status.HTTP_404_NOT_FOUND) @router.delete("/{name}", status_code=status.HTTP_204_NO_CONTENT, summary="Delete a project by name") -async def delete_project(name: str = Path(..., title="Name of the module")): +async def delete_project( + *, + name: str = Path(..., title="Name of the module"), + session: Session = Depends(database.get_session) +): """Delete a module specified by name.""" - logging.debug(f"Deleting module {name}") + project = session.exec(select(Project).where(Project.name == name)).one() + session.delete(project) + session.commit() + # TODO: This method implicitly returns None, which will be converted to null by FastAPI, which triggers a + # warning, because the method returns with header HTTP_204_NO_CONTENT, but has content -@router.patch("/{name}", summary="Apply partial updates to a project by name") -async def patch_project(project: ProjectCreate, name: str = Path(..., title="Name of the module")): +@router.patch( + "/{name}", + status_code=status.HTTP_200_OK, + response_model=ProjectRead, + summary="Apply partial updates to a project by name" +) +async def patch_project( + *, + project: ProjectCreate, + name: str = Path(..., title="Name of the module"), + session: Session = Depends(database.get_session) +) -> Project: """Apply partial updates to a project.""" - logging.debug(f"Patching project {name} with {project}") + try: + db_project = session.exec(select(Project).where(Project.name == name)).one() + except sqlalchemy.exc.NoResultFound: + raise HTTPException(status_code=status.HTTP_404_NOT_FOUND) + + # Set all provided arguments in the database project + for key, value in project.dict(exclude_unset=True).items(): + setattr(db_project, key, value) + + session.add(db_project) + session.commit() + session.refresh(db_project) + return db_project