126 lines
4.7 KiB
Python
126 lines
4.7 KiB
Python
"""This module handles CRUD operations for todo-items in the database, based on pydanctic schemas."""
|
|
|
|
from datetime import datetime
|
|
|
|
from sqlalchemy.orm import Session
|
|
|
|
from todo.models import todos as todomodel
|
|
from todo.models import users as usermodel
|
|
from todo.schemas import todos as todoschema
|
|
from todo.schemas.users import User
|
|
from todo.utils.exceptions import NotFoundException, InvalidFilterParameterException
|
|
from todo.dependencies.common import SortOrder
|
|
from todo.dependencies.todos import SortableTodoItemField
|
|
|
|
|
|
def create_todo(db: Session, todo: todoschema.TodoItemCreate, user_id: int) -> todoschema.TodoItem:
|
|
"""Creates the specified todo-item for the user with the specified id in the database."""
|
|
|
|
db_user = db.query(usermodel.User).filter(usermodel.User.id == user_id).first()
|
|
if not db_user:
|
|
raise NotFoundException(f"User with id '{user_id}' not found.")
|
|
|
|
db_todo = todomodel.TodoItem(
|
|
user_id=user_id,
|
|
title=todo.title,
|
|
description=todo.description
|
|
)
|
|
|
|
db.add(db_todo)
|
|
db.commit()
|
|
db.refresh(db_todo)
|
|
return todoschema.TodoItem.from_orm(db_todo)
|
|
|
|
|
|
def read_todo(db: Session, todo_id: int) -> todoschema.TodoItem:
|
|
"""Queries the db for a todo-item with the specified id and returns it."""
|
|
|
|
db_todo = db.query(todomodel.TodoItem).filter(todomodel.TodoItem.id == todo_id).first()
|
|
if not db_todo:
|
|
raise NotFoundException(f"Todo item with id '{todo_id}' not found.")
|
|
|
|
return todoschema.TodoItem.from_orm(db_todo)
|
|
|
|
|
|
def read_todos_for_user(
|
|
db: Session,
|
|
user_id: int,
|
|
skip: int = 0, limit: int = 100,
|
|
sortby: SortableTodoItemField = SortableTodoItemField('updated'),
|
|
sortorder: SortOrder = SortOrder['desc'],
|
|
) -> list[todoschema.TodoItem]:
|
|
"""Returns a range of todo-items of the user with the specified user_id from the database."""
|
|
|
|
for parameter in [skip, limit]:
|
|
if not isinstance(parameter, int):
|
|
raise InvalidFilterParameterException(f"Parameter '{parameter}' must be an integer.")
|
|
if parameter < 0:
|
|
raise InvalidFilterParameterException(f"Parameter '{parameter}' cannot be smaller than zero.")
|
|
|
|
db_user = db.query(usermodel.User).filter(usermodel.User.id == user_id).first()
|
|
if not db_user:
|
|
raise NotFoundException(f"User with id '{user_id}' not found.")
|
|
|
|
db_todos = db.query(todomodel.TodoItem).filter(todomodel.TodoItem.user_id == user_id).order_by(sortorder.call(sortby.field)).offset(skip).limit(limit).all()
|
|
|
|
return [todoschema.TodoItem.from_orm(db_todo) for db_todo in db_todos]
|
|
|
|
|
|
def read_user_for_todo(
|
|
db: Session,
|
|
todo_id: int,
|
|
) -> User:
|
|
"""Returns the user who owns the todo-item with the specified ID."""
|
|
|
|
db_todo = db.query(todomodel.TodoItem).filter(todomodel.TodoItem.id == todo_id).first()
|
|
if not db_todo:
|
|
raise NotFoundException(f"Todo item with id '{todo_id}' not found.")
|
|
|
|
return User.from_orm(db_todo.user)
|
|
|
|
|
|
def read_todos_count_for_user(db: Session, user_id: int) -> int:
|
|
"""Returns the total number of todo-items of the user with the specified user_id."""
|
|
|
|
db_user = db.query(usermodel.User).filter(usermodel.User.id == user_id).first()
|
|
if not db_user:
|
|
raise NotFoundException(f"User with id '{user_id}' not found.")
|
|
|
|
return db.query(todomodel.TodoItem).filter(todomodel.TodoItem.user_id == user_id).count()
|
|
|
|
|
|
def update_todo(db: Session, todo: todoschema.TodoItemUpdate, todo_id: int) -> todoschema.TodoItem:
|
|
"""Updates the todo-item with the provided id with all non-None fields from the input todo-item."""
|
|
|
|
db_todo = db.query(todomodel.TodoItem).filter(todomodel.TodoItem.id == todo_id).first()
|
|
if not db_todo:
|
|
raise NotFoundException(f"Todo item with id '{todo_id}' not found.")
|
|
db_todo_orm_obj = todoschema.TodoItem.from_orm(db_todo)
|
|
|
|
for key in ['title', 'description', 'done']:
|
|
value = getattr(todo, key)
|
|
if value is not None:
|
|
setattr(db_todo, key, value)
|
|
# If we just newly finished a TODO, record the time it was finished
|
|
if todo.done and not db_todo_orm_obj.done:
|
|
setattr(db_todo, "finished", datetime.now(db_todo_orm_obj.updated.tzinfo))
|
|
|
|
db.commit()
|
|
db.refresh(db_todo)
|
|
return todoschema.TodoItem.from_orm(db_todo)
|
|
|
|
|
|
def delete_todo(db: Session, todo_id: int) -> todoschema.TodoItem:
|
|
"""Deletes the todo-item with the provided id from the db."""
|
|
|
|
db_todo = db.query(todomodel.TodoItem).filter(todomodel.TodoItem.id == todo_id).first()
|
|
if not db_todo:
|
|
raise NotFoundException(f"Todo item with id '{todo_id}' not found.")
|
|
todo_copy = todoschema.TodoItem.from_orm(db_todo)
|
|
|
|
db.delete(db_todo)
|
|
db.commit()
|
|
|
|
todo_copy.updated = datetime.now(todo_copy.updated.tzinfo)
|
|
return todo_copy
|