Skip to content

Commit

Permalink
Merge pull request #36 from ral-facilities/endpoint-for-reading-catal…
Browse files Browse the repository at this point in the history
…ogue-categories-#33

Implement API Endpoint for Reading Catalogue Categories
  • Loading branch information
VKTB committed Jul 5, 2023
2 parents 0ed9d58 + fc60e2d commit 970aaa9
Show file tree
Hide file tree
Showing 6 changed files with 514 additions and 2 deletions.
18 changes: 18 additions & 0 deletions inventory_management_system_api/repositories/catalogue_category.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,24 @@ def get(self, catalogue_category_id: str) -> Optional[CatalogueCategoryOut]:
return CatalogueCategoryOut(**catalogue_category)
return None

def list(self, path: Optional[str], parent_path: Optional[str]) -> list[CatalogueCategoryOut]:
"""
Retrieve catalogue categories from a MongoDB based on the provided filters.
:param path: The path to filter catalogue categories by.
:param parent_path: The parent path to filter catalogue categories by.
:return: A list of catalogue categories, or an empty list if no catalogue categories are returned by the
database.
"""
query = {}
if path:
query["path"] = path
if parent_path:
query["parent_path"] = parent_path

catalogue_categories = self._collection.find(query)
return [CatalogueCategoryOut(**catalogue_category) for catalogue_category in catalogue_categories]

def _is_duplicate_catalogue_category(self, parent_id: Optional[str], code: str) -> bool:
"""
Check if a catalogue category with the same code already exists within the parent category.
Expand Down
14 changes: 13 additions & 1 deletion inventory_management_system_api/routers/v1/catalogue_category.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
`CatalogueCategoryService` service.
"""
import logging
from typing import Optional, Annotated

from fastapi import APIRouter, status, Depends, HTTPException, Path
from fastapi import APIRouter, status, Depends, HTTPException, Path, Query

from inventory_management_system_api.core.exceptions import (
MissingRecordError,
Expand All @@ -23,6 +24,17 @@
router = APIRouter(prefix="/v1/catalogue-categories", tags=["catalogue categories"])


@router.get(path="/", summary="Get catalogue categories", response_description="List of catalogue categories")
def get_catalogue_categories(
path: Annotated[Optional[str], Query(description="Filter catalogue categories by path")] = None,
parent_path: Annotated[Optional[str], Query(description="Filter catalogue categories by parent path")] = None,
catalogue_category_service: CatalogueCategoryService = Depends(),
) -> list[CatalogueCategorySchema]:
# pylint: disable=missing-function-docstring
catalogue_categories = catalogue_category_service.list(path, parent_path)
return [CatalogueCategorySchema(**catalogue_category.dict()) for catalogue_category in catalogue_categories]


@router.get(
path="/{catalogue_category_id}",
summary="Get a catalogue category by ID",
Expand Down
10 changes: 10 additions & 0 deletions inventory_management_system_api/services/catalogue_category.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,16 @@ def get(self, catalogue_category_id: str) -> Optional[CatalogueCategoryOut]:
"""
return self._catalogue_category_repository.get(catalogue_category_id)

def list(self, path: Optional[str], parent_path: Optional[str]) -> list[CatalogueCategoryOut]:
"""
Retrieve catalogue categories based on the provided filters.
:param path: The path to filter catalogue categories by.
:param parent_path: The parent path to filter catalogue categories by.
:return: A list of catalogue categories, or an empty list if no catalogue categories are retrieved.
"""
return self._catalogue_category_repository.list(path, parent_path)

def _generate_code(self, name: str) -> str:
"""
Generate a code for a catalogue category based on its name. This is used to maintain uniqueness and prevent
Expand Down
111 changes: 111 additions & 0 deletions test/e2e/test_catalogue_category.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,3 +179,114 @@ def test_get_catalogue_category_with_nonexistent_id(test_client):

assert response.status_code == 404
assert response.json()["detail"] == "The requested catalogue category was not found"


def test_get_catalogue_categories(test_client):
"""
Test getting catalogue categories.
"""
catalogue_category_post = CatalogueCategoryPostRequestSchema(name="Category A", is_leaf=False)
test_client.post("/v1/catalogue-categories", json=catalogue_category_post.dict())
catalogue_category_post = CatalogueCategoryPostRequestSchema(name="Category B", is_leaf=False)
response = test_client.post("/v1/catalogue-categories", json=catalogue_category_post.dict())
catalogue_category = CatalogueCategorySchema(**response.json())

parent_id = catalogue_category.id
catalogue_category_post = CatalogueCategoryPostRequestSchema(name="Category C", is_leaf=True, parent_id=parent_id)
test_client.post("/v1/catalogue-categories", json=catalogue_category_post.dict())

response = test_client.get("/v1/catalogue-categories")

assert response.status_code == 200

catalogue_categories = [CatalogueCategorySchema(**r) for r in response.json()]

assert len(catalogue_categories) == 3
assert catalogue_categories[0].path == "/category-a"
assert catalogue_categories[0].parent_path == "/"
assert catalogue_categories[1].path == "/category-b"
assert catalogue_categories[1].parent_path == "/"
assert catalogue_categories[2].path == "/category-b/category-c"
assert catalogue_categories[2].parent_path == "/category-b"


def test_list_with_path_filter(test_client):
"""
Test getting catalogue categories based on the provided parent path filter.
"""
catalogue_category_post = CatalogueCategoryPostRequestSchema(name="Category A", is_leaf=False)
test_client.post("/v1/catalogue-categories", json=catalogue_category_post.dict())
catalogue_category_post = CatalogueCategoryPostRequestSchema(name="Category B", is_leaf=False)
test_client.post("/v1/catalogue-categories", json=catalogue_category_post.dict())

response = test_client.get("/v1/catalogue-categories", params={"path": "/category-a"})

assert response.status_code == 200

catalogue_categories = [CatalogueCategorySchema(**r) for r in response.json()]

assert len(catalogue_categories) == 1
assert catalogue_categories[0].path == "/category-a"
assert catalogue_categories[0].parent_path == "/"


def test_list_with_parent_path_filter(test_client):
"""
Test getting catalogue categories based on the provided parent path filter.
"""
catalogue_category_post = CatalogueCategoryPostRequestSchema(name="Category B", is_leaf=False)
response = test_client.post("/v1/catalogue-categories", json=catalogue_category_post.dict())
catalogue_category = CatalogueCategorySchema(**response.json())

parent_id = catalogue_category.id
catalogue_category_post = CatalogueCategoryPostRequestSchema(name="Category C", is_leaf=True, parent_id=parent_id)
test_client.post("/v1/catalogue-categories", json=catalogue_category_post.dict())

response = test_client.get("/v1/catalogue-categories", params={"parent_path": "/"})

assert response.status_code == 200

catalogue_categories = [CatalogueCategorySchema(**r) for r in response.json()]

assert len(catalogue_categories) == 1
assert catalogue_categories[0].path == "/category-b"
assert catalogue_categories[0].parent_path == "/"


def test_list_with_path_and_parent_path_filters(test_client):
"""
Test getting catalogue categories based on the provided path and parent path filters.
"""
catalogue_category_post = CatalogueCategoryPostRequestSchema(name="Category A", is_leaf=False)
test_client.post("/v1/catalogue-categories", json=catalogue_category_post.dict())
catalogue_category_post = CatalogueCategoryPostRequestSchema(name="Category B", is_leaf=False)
test_client.post("/v1/catalogue-categories", json=catalogue_category_post.dict())

response = test_client.get("/v1/catalogue-categories", params={"path": "/category-b", "parent_path": "/"})

assert response.status_code == 200

catalogue_categories = [CatalogueCategorySchema(**r) for r in response.json()]

assert len(catalogue_categories) == 1
assert catalogue_categories[0].path == "/category-b"
assert catalogue_categories[0].parent_path == "/"


def test_list_with_path_and_parent_path_filters_no_matching_results(test_client):
"""
Test getting catalogue categories based on the provided path and parent path filters when there is no matching
results in the database.
"""
catalogue_category_post = CatalogueCategoryPostRequestSchema(name="Category A", is_leaf=False)
test_client.post("/v1/catalogue-categories", json=catalogue_category_post.dict())
catalogue_category_post = CatalogueCategoryPostRequestSchema(name="Category B", is_leaf=False)
test_client.post("/v1/catalogue-categories", json=catalogue_category_post.dict())

response = test_client.get("/v1/catalogue-categories", params={"path": "/category-c", "parent_path": "/"})

assert response.status_code == 200

catalogue_categories = [CatalogueCategorySchema(**r) for r in response.json()]

assert len(catalogue_categories) == 0
Loading

0 comments on commit 970aaa9

Please sign in to comment.