def update_category(public_id: int, data: dict):
    """
    HTTP `PUT`/`PATCH` route for update a single category resource.

    Args:
        public_id (int): Public ID of the updatable category
        data (CategoryModel.SCHEMA): New category data to update

    Raises:
        ManagerGetError: When the category with the `public_id` was not found.
        ManagerUpdateError: When something went wrong during the update.

    Returns:
        UpdateSingleResponse: With update result of the new updated category.
    """
    category_manager: CategoryManager = CategoryManager(
        database_manager=current_app.database_manager)
    try:
        category = CategoryModel.from_data(data=data)
        category_manager.update(public_id=PublicID(public_id),
                                category=CategoryModel.to_json(category))
        api_response = UpdateSingleResponse(result=data,
                                            url=request.url,
                                            model=CategoryModel.MODEL)
    except ManagerGetError as err:
        return abort(404, err.message)
    except ManagerUpdateError as err:
        return abort(400, err.message)

    return api_response.make_response()
 def update_category(self, category: CategoryModel):
     """Update a existing category into the database"""
     try:
         return self._update(collection=CategoryModel.COLLECTION,
                             public_id=category.get_public_id(),
                             data=CategoryModel.to_json(category))
     except Exception as err:
         raise ObjectManagerUpdateError(err=err)
def delete_category(public_id: int):
    """
    HTTP `DELETE` route for delete a single category resource.

    Args:
        public_id (int): Public ID of the deletable category

    Raises:
        ManagerGetError: When the category with the `public_id` was not found.
        ManagerDeleteError: When something went wrong during the deletion.

    Returns:
        DeleteSingleResponse: Delete result with the deleted category as data.
    """
    category_manager: CategoryManager = CategoryManager(
        database_manager=current_app.database_manager)
    try:
        deleted_category = category_manager.delete(
            public_id=PublicID(public_id))
        api_response = DeleteSingleResponse(
            raw=CategoryModel.to_json(deleted_category),
            model=CategoryModel.MODEL)
    except ManagerGetError as err:
        return abort(404, err.message)
    except ManagerDeleteError as err:
        return abort(404, err.message)
    return api_response.make_response()
def insert_category(data: dict):
    """
    HTTP `POST` route for insert a single category resource.

    Args:
        data (CategoryModel.SCHEMA): Insert data of a new category.

    Raises:
        ManagerGetError: If the inserted resource could not be found after inserting.
        ManagerInsertError: If something went wrong during insertion.

    Returns:
        InsertSingleResponse: Insert response with the new category and its public_id.
    """
    category_manager: CategoryManager = CategoryManager(
        database_manager=current_app.database_manager)
    data.setdefault('creation_time', datetime.utcnow())
    try:
        result_id: PublicID = category_manager.insert(data)
        raw_doc = category_manager.get(public_id=result_id)
    except ManagerGetError as err:
        return abort(404, err.message)
    except ManagerInsertError as err:
        return abort(400, err.message)
    api_response = InsertSingleResponse(result_id,
                                        raw=CategoryModel.to_json(raw_doc),
                                        url=request.url,
                                        model=CategoryModel.MODEL)
    return api_response.make_response(prefix='categories')
def get_category(public_id: int):
    """
    HTTP `GET`/`HEAD` route for a single category resource.

    Args:
        public_id (int): Public ID of the category.

    Raises:
        ManagerGetError: When the selected category does not exists.

    Returns:
        GetSingleResponse: Which includes the json data of a CategoryModel.
    """
    category_manager: CategoryManager = CategoryManager(
        database_manager=current_app.database_manager)
    body = True if not request.method != 'HEAD' else False

    try:
        category_instance = category_manager.get(public_id)
    except ManagerGetError as err:
        return abort(404, err.message)
    api_response = GetSingleResponse(CategoryModel.to_json(category_instance),
                                     url=request.url,
                                     model=CategoryModel.MODEL,
                                     body=body)
    return api_response.make_response()
 def insert_category(self, category: CategoryModel):
     """Add a new category into the database or add the children list an existing category"""
     try:
         return self._insert(collection=CategoryModel.COLLECTION,
                             data=CategoryModel.to_json(category))
     except Exception as err:
         raise ObjectManagerInsertError(err=err)
 def get_category(self, public_id: int) -> CategoryModel:
     """Get a category from the database"""
     try:
         raw_category: dict = self._get(collection=CategoryModel.COLLECTION,
                                        public_id=public_id)
         return CategoryModel.from_data(raw_category)
     except Exception as err:
         raise ObjectManagerGetError(err=err)
def get_categories(params: CollectionParameters):
    """
    HTTP `GET`/`HEAD` route for getting a iterable collection of resources.

    Args:
        params (CollectionParameters): Passed parameters over the http query string + optional `view` parameter.

    Returns:
        GetMultiResponse: Which includes a IterationResult of the CategoryModel.
        If the view parameter with tree was set the route returns a GetMultiResponse<CategoryTree>.

    Example:
        You can pass any parameter based on the CollectionParameters.
        Optional parameters are passed over the function declaration.
        The `view` parameter is optional and default `list`, but can be `tree` for the category tree view.

    Raises:
        FrameworkIterationError: If the collection could not be iterated.
        ManagerGetError: If the collection could not be found.

    """
    category_manager: CategoryManager = CategoryManager(
        database_manager=current_app.database_manager)
    body = True if not request.method != 'HEAD' else False

    try:
        if params.optional['view'] == 'tree':
            tree: CategoryTree = category_manager.tree
            api_response = GetMultiResponse(CategoryTree.to_json(tree),
                                            total=len(tree),
                                            params=params,
                                            url=request.url,
                                            model=CategoryTree.MODEL,
                                            body=body)
            return api_response.make_response(pagination=False)
        else:
            iteration_result: IterationResult[
                CategoryModel] = category_manager.iterate(filter=params.filter,
                                                          limit=params.limit,
                                                          skip=params.skip,
                                                          sort=params.sort,
                                                          order=params.order)
            category_list = [
                CategoryModel.to_json(category)
                for category in iteration_result.results
            ]
            api_response = GetMultiResponse(category_list,
                                            total=iteration_result.total,
                                            params=params,
                                            url=request.url,
                                            model=CategoryModel.MODEL,
                                            body=body)
    except FrameworkIterationError as err:
        return abort(400, err.message)
    except ManagerGetError as err:
        return abort(404, err.message)
    return api_response.make_response()
 def get_categories_by(self, sort='public_id', **requirements: dict) -> List[CategoryModel]:
     """Get a list of categories by special requirements"""
     try:
         raw_categories = self._get_many(collection=CategoryModel.COLLECTION, sort=sort, **requirements)
     except Exception as err:
         raise ObjectManagerGetError(err)
     try:
         return [CategoryModel.from_data(category) for category in raw_categories]
     except Exception as err:
         raise ObjectManagerInitError(err)
 def get_categories(self) -> List[CategoryModel]:
     """Get all categories as nested list"""
     try:
         raw_categories = self._get_many(collection=CategoryModel.COLLECTION, sort='public_id')
     except Exception as err:
         raise ObjectManagerGetError(err)
     try:
         return [CategoryModel.from_data(category) for category in raw_categories]
     except Exception as err:
         raise ObjectManagerInitError(err)
    def get_category_by(self, **requirements) -> CategoryModel:
        """Get a single category by requirements
        Notes:
            Even if multiple categories match the requirements only the first matched will be returned
        """
        try:
            raw_category = self._get_by(collection=CategoryModel.COLLECTION, **requirements)
        except Exception as err:
            raise ObjectManagerGetError(err)

        try:
            return CategoryModel.from_data(raw_category)
        except Exception as err:
            raise ObjectManagerInitError(err)