diff --git a/backend/app/alembic/versions/add_category_to_items.py b/backend/app/alembic/versions/add_category_to_items.py new file mode 100644 index 0000000000..e9728a59fd --- /dev/null +++ b/backend/app/alembic/versions/add_category_to_items.py @@ -0,0 +1,31 @@ +"""Add category to items + +Revision ID: add_category_to_items +Revises: d98dd8ec85a3 +Create Date: 2023-11-30 10:00:00.000000 + +""" +import sqlalchemy as sa +import sqlmodel.sql.sqltypes +from alembic import op + +# revision identifiers, used by Alembic. +revision = "add_category_to_items" +down_revision = "d98dd8ec85a3" +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.add_column( + "item", + sa.Column("category", sqlmodel.sql.sqltypes.AutoString(length=100), nullable=True) + ) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_column("item", "category") + # ### end Alembic commands ### \ No newline at end of file diff --git a/backend/app/api/routes/items.py b/backend/app/api/routes/items.py index 177dc1e476..7140f1c1ca 100644 --- a/backend/app/api/routes/items.py +++ b/backend/app/api/routes/items.py @@ -12,35 +12,58 @@ @router.get("/", response_model=ItemsPublic) def read_items( - session: SessionDep, current_user: CurrentUser, skip: int = 0, limit: int = 100 + session: SessionDep, + current_user: CurrentUser, + skip: int = 0, + limit: int = 100, + category: str | None = None ) -> Any: """ Retrieve items. """ - + + # Base query if current_user.is_superuser: - count_statement = select(func.count()).select_from(Item) - count = session.exec(count_statement).one() - statement = select(Item).offset(skip).limit(limit) - items = session.exec(statement).all() + query = select(Item) + count_query = select(func.count()).select_from(Item) else: - count_statement = ( - select(func.count()) - .select_from(Item) - .where(Item.owner_id == current_user.id) - ) - count = session.exec(count_statement).one() - statement = ( - select(Item) - .where(Item.owner_id == current_user.id) - .offset(skip) - .limit(limit) - ) - items = session.exec(statement).all() + query = select(Item).where(Item.owner_id == current_user.id) + count_query = select(func.count()).select_from(Item).where(Item.owner_id == current_user.id) + + # Apply category filter if provided + if category: + query = query.where(Item.category == category) + count_query = count_query.where(Item.category == category) + + # Apply pagination + query = query.offset(skip).limit(limit) + + # Execute queries + count = session.exec(count_query).one() + items = session.exec(query).all() return ItemsPublic(data=items, count=count) +@router.get("/categories", response_model=list[str]) +def get_item_categories( + session: SessionDep, current_user: CurrentUser +) -> Any: + """ + Get all unique item categories. + """ + if current_user.is_superuser: + statement = select(Item.category).distinct() + else: + statement = select(Item.category).where( + Item.owner_id == current_user.id + ).distinct() + + categories = session.exec(statement).all() + # Filter out None values and return unique non-empty categories + return [cat for cat in categories if cat] + + @router.get("/{id}", response_model=ItemPublic) def read_item(session: SessionDep, current_user: CurrentUser, id: uuid.UUID) -> Any: """ diff --git a/backend/app/models.py b/backend/app/models.py index 2389b4a532..57a6c62c92 100644 --- a/backend/app/models.py +++ b/backend/app/models.py @@ -60,6 +60,7 @@ class UsersPublic(SQLModel): class ItemBase(SQLModel): title: str = Field(min_length=1, max_length=255) description: str | None = Field(default=None, max_length=255) + category: str | None = Field(default=None, max_length=100) # Properties to receive on item creation