add inventory sorting to the api
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
@@ -75,10 +75,35 @@ def _find(db: DbSession, user: User, class_name: str) -> InventoryEntry | None:
|
|||||||
).scalar_one_or_none()
|
).scalar_one_or_none()
|
||||||
|
|
||||||
|
|
||||||
|
def _sort_key_name(item):
|
||||||
|
return (item["name"].lower(), item["class_name"])
|
||||||
|
|
||||||
|
|
||||||
|
def _sort_key_category(item):
|
||||||
|
return ((item["category"] or "").lower(), item["name"].lower(), item["class_name"])
|
||||||
|
|
||||||
|
|
||||||
|
def _sort_key_quantity(item):
|
||||||
|
return (-item["quantity"], item["name"].lower(), item["class_name"])
|
||||||
|
|
||||||
|
|
||||||
|
def _sort_key_updated(item):
|
||||||
|
return (-item["updated_at"].timestamp(), item["name"].lower())
|
||||||
|
|
||||||
|
|
||||||
|
_SORT_KEYS = {
|
||||||
|
"name": _sort_key_name,
|
||||||
|
"category": _sort_key_category,
|
||||||
|
"quantity": _sort_key_quantity,
|
||||||
|
"updated": _sort_key_updated,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@router.get("", response_model=InventoryPage)
|
@router.get("", response_model=InventoryPage)
|
||||||
def list_inventory(
|
def list_inventory(
|
||||||
category: str | None = None,
|
category: str | None = None,
|
||||||
search: str | None = None,
|
search: str | None = None,
|
||||||
|
sort: str = Query(default="name", pattern="^(name|category|quantity|updated)$"),
|
||||||
page: int = Query(default=1, ge=1),
|
page: int = Query(default=1, ge=1),
|
||||||
page_size: int = Query(default=25, ge=1),
|
page_size: int = Query(default=25, ge=1),
|
||||||
user: User = Depends(get_current_user),
|
user: User = Depends(get_current_user),
|
||||||
@@ -102,7 +127,7 @@ def list_inventory(
|
|||||||
if needle in i["name"].lower() or needle in i["class_name"].lower()
|
if needle in i["name"].lower() or needle in i["class_name"].lower()
|
||||||
]
|
]
|
||||||
|
|
||||||
items.sort(key=lambda i: (i["name"].lower(), i["class_name"]))
|
items.sort(key=_SORT_KEYS[sort])
|
||||||
total = len(items)
|
total = len(items)
|
||||||
total_pages = max(1, math.ceil(total / page_size))
|
total_pages = max(1, math.ceil(total / page_size))
|
||||||
start = (page - 1) * page_size
|
start = (page - 1) * page_size
|
||||||
|
|||||||
@@ -189,3 +189,27 @@ def test_catalog_is_not_mutated_by_inventory_operations():
|
|||||||
carrack = client.get(f"/api/v1/items/{CARROCK}").json()
|
carrack = client.get(f"/api/v1/items/{CARROCK}").json()
|
||||||
assert "quantity" not in carrack
|
assert "quantity" not in carrack
|
||||||
assert "notes" not in carrack
|
assert "notes" not in carrack
|
||||||
|
|
||||||
|
|
||||||
|
def test_sort_by_category_groups_categories():
|
||||||
|
client = authed_client()
|
||||||
|
add(client, CARROCK)
|
||||||
|
add(client, RIFLE)
|
||||||
|
items = client.get("/api/v1/me/inventory?sort=category").json()["items"]
|
||||||
|
assert [i["class_name"] for i in items] == [RIFLE, CARROCK]
|
||||||
|
|
||||||
|
|
||||||
|
def test_sort_by_quantity_is_descending():
|
||||||
|
client = authed_client()
|
||||||
|
add(client, CARROCK, quantity=5)
|
||||||
|
add(client, RIFLE, quantity=1)
|
||||||
|
items = client.get("/api/v1/me/inventory?sort=quantity").json()["items"]
|
||||||
|
assert [i["class_name"] for i in items] == [CARROCK, RIFLE]
|
||||||
|
|
||||||
|
|
||||||
|
def test_sort_defaults_to_name_and_rejects_unknown_values():
|
||||||
|
client = authed_client()
|
||||||
|
add(client, CARROCK)
|
||||||
|
listing = client.get("/api/v1/me/inventory").json()
|
||||||
|
assert [i["class_name"] for i in listing["items"]] == [CARROCK]
|
||||||
|
assert client.get("/api/v1/me/inventory?sort=bogus").status_code == 422
|
||||||
|
|||||||
Reference in New Issue
Block a user