annotation/annotation/categories/resources.py (152 lines of code) (raw):

from typing import List, Union from fastapi import APIRouter, Depends, HTTPException, Path, Response, status from filter_lib import Page from sqlalchemy.orm import Session from sqlalchemy_filters.exceptions import BadFilterFormat from annotation.database import get_db from annotation.errors import NoSuchCategoryError from annotation.filters import CategoryFilter from annotation.microservice_communication.search import ( X_CURRENT_TENANT_HEADER, ) from annotation.schemas import ( BadRequestErrorSchema, CategoryBaseSchema, CategoryInputSchema, CategoryResponseSchema, ConnectionErrorSchema, NotFoundErrorSchema, SubCategoriesOutSchema, ) from annotation.tags import CATEGORIES_TAG from .services import ( add_category_db, delete_category_db, fetch_category_db, filter_category_db, insert_category_tree, recursive_subcategory_search, response_object_from_db, update_category_db, ) router = APIRouter( prefix="/categories", tags=[CATEGORIES_TAG], responses={500: {"model": ConnectionErrorSchema}}, ) @router.post( "", status_code=status.HTTP_201_CREATED, response_model=CategoryResponseSchema, responses={ 400: {"model": BadRequestErrorSchema}, }, summary="Save new category and return saved one.", ) def save_category( category: CategoryInputSchema, db: Session = Depends(get_db), x_current_tenant: str = X_CURRENT_TENANT_HEADER, ) -> CategoryResponseSchema: category_db = add_category_db(db, category, x_current_tenant) return response_object_from_db(category_db) # Get by category id, requires children/parents @router.get( "/{category_id}", status_code=status.HTTP_200_OK, response_model=CategoryResponseSchema, responses={ 404: {"model": NotFoundErrorSchema}, }, summary="Get category by id.", ) def fetch_category( category_id: str = Path(..., example="1"), db: Session = Depends(get_db), x_current_tenant: str = X_CURRENT_TENANT_HEADER, ) -> CategoryResponseSchema: category_db = fetch_category_db(db, category_id, x_current_tenant) category_response = insert_category_tree( db, category_db, tenant=x_current_tenant ) return category_response @router.get( "/{category_id}/child", status_code=status.HTTP_200_OK, response_model=List[SubCategoriesOutSchema], responses={ 404: {"model": NotFoundErrorSchema}, }, summary="Get list of child categories ids for category with category_id.", ) def get_child_categories( category_id: str = Path(..., example="Table"), db: Session = Depends(get_db), x_current_tenant: str = X_CURRENT_TENANT_HEADER, ) -> List[SubCategoriesOutSchema]: fetch_category_db(db, category_id, x_current_tenant) root_category = category_id child_categories = recursive_subcategory_search( db, category_id, root_category, set() ) response = [ SubCategoriesOutSchema.parse_obj({"id": child_id}) for child_id in sorted(child_categories) ] return response # Search with params, return paginate obj, each entity # requires children/parents @router.post( "/search", status_code=status.HTTP_200_OK, response_model=Page[Union[CategoryResponseSchema, str, dict]], summary="Search categories.", response_model_exclude_none=True, ) def search_categories( request: CategoryFilter, db: Session = Depends(get_db), x_current_tenant: str = X_CURRENT_TENANT_HEADER, ) -> Page[Union[CategoryResponseSchema, str, dict]]: """ Searches and returns categories data according to search request parameters filters. Supports pagination and ordering. """ try: task_response = filter_category_db(db, request, x_current_tenant) except BadFilterFormat as error: raise HTTPException( status_code=400, detail=f"{error}", ) return task_response @router.put( "/{category_id}", status_code=status.HTTP_200_OK, response_model=CategoryResponseSchema, responses={ 400: {"model": BadRequestErrorSchema}, 404: {"model": NotFoundErrorSchema}, }, summary="Update category.", ) def update_category( query: CategoryBaseSchema, category_id: str = Path(..., example="1"), db: Session = Depends(get_db), x_current_tenant: str = X_CURRENT_TENANT_HEADER, ) -> CategoryResponseSchema: """ Updates category by id and returns updated category. """ category_db = update_category_db( db, category_id, query.dict(), x_current_tenant ) if not category_db: raise NoSuchCategoryError("Cannot update category parameters") return response_object_from_db(category_db) @router.delete( "/{category_id}", status_code=status.HTTP_204_NO_CONTENT, responses={ 404: {"model": NotFoundErrorSchema}, }, summary="Delete category by id.", ) def delete_category( category_id: str = Path(..., example="1"), db: Session = Depends(get_db), x_current_tenant: str = X_CURRENT_TENANT_HEADER, ) -> Response: delete_category_db(db, category_id, x_current_tenant) return Response(status_code=status.HTTP_204_NO_CONTENT)