Automated Action b8143c43e4 Implement ecommerce authentication and inventory API
- Set up project structure and FastAPI application
- Create database models for users, products, and inventory
- Configure SQLAlchemy and Alembic for database management
- Implement JWT authentication
- Create API endpoints for user, product, and inventory management
- Add admin-only routes and authorization middleware
- Add health check endpoint
- Update README with documentation
- Lint and fix code issues
2025-06-08 21:40:55 +00:00

266 lines
8.0 KiB
Python

from typing import Any, List, Optional
from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.orm import Session
from app import crud, models, schemas
from app.api import deps
router = APIRouter()
# Category endpoints
@router.get("/categories/", response_model=List[schemas.Category])
def read_categories(
db: Session = Depends(deps.get_db),
skip: int = 0,
limit: int = 100,
current_user: models.User = Depends(deps.get_current_active_user),
) -> Any:
"""
Retrieve categories.
"""
categories = crud.product.get_all_categories(db, skip=skip, limit=limit)
return categories
@router.post("/categories/", response_model=schemas.Category)
def create_category(
*,
db: Session = Depends(deps.get_db),
category_in: schemas.CategoryCreate,
current_user: models.User = Depends(deps.get_current_admin_user),
) -> Any:
"""
Create new category. Admin only.
"""
category = crud.product.get_category_by_name(db, name=category_in.name)
if category:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Category with this name already exists",
)
category = crud.product.create_category(db, obj_in=category_in)
return category
@router.get("/categories/{category_id}", response_model=schemas.Category)
def read_category(
*,
db: Session = Depends(deps.get_db),
category_id: str,
current_user: models.User = Depends(deps.get_current_active_user),
) -> Any:
"""
Get category by ID.
"""
category = crud.product.get_category_by_id(db, category_id=category_id)
if not category:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Category not found",
)
return category
@router.put("/categories/{category_id}", response_model=schemas.Category)
def update_category(
*,
db: Session = Depends(deps.get_db),
category_id: str,
category_in: schemas.CategoryUpdate,
current_user: models.User = Depends(deps.get_current_admin_user),
) -> Any:
"""
Update a category. Admin only.
"""
category = crud.product.get_category_by_id(db, category_id=category_id)
if not category:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Category not found",
)
# Check if updated name already exists
if category_in.name and category_in.name != category.name:
existing_category = crud.product.get_category_by_name(db, name=category_in.name)
if existing_category:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Category with this name already exists",
)
category = crud.product.update_category(db, db_obj=category, obj_in=category_in)
return category
@router.delete("/categories/{category_id}", response_model=schemas.Category)
def delete_category(
*,
db: Session = Depends(deps.get_db),
category_id: str,
current_user: models.User = Depends(deps.get_current_admin_user),
) -> Any:
"""
Delete a category. Admin only.
"""
category = crud.product.get_category_by_id(db, category_id=category_id)
if not category:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Category not found",
)
# Check if category has products
products = crud.product.get_all_products(db, category_id=category_id)
if products:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Cannot delete category with associated products",
)
category = crud.product.delete_category(db, category_id=category_id)
return category
# Product endpoints
@router.get("/", response_model=List[schemas.Product])
def read_products(
db: Session = Depends(deps.get_db),
skip: int = 0,
limit: int = 100,
category_id: Optional[str] = None,
active_only: bool = False,
current_user: models.User = Depends(deps.get_current_active_user),
) -> Any:
"""
Retrieve products with optional filtering.
"""
products = crud.product.get_all_products(
db,
skip=skip,
limit=limit,
category_id=category_id,
active_only=active_only
)
return products
@router.post("/", response_model=schemas.Product)
def create_product(
*,
db: Session = Depends(deps.get_db),
product_in: schemas.ProductCreate,
current_user: models.User = Depends(deps.get_current_admin_user),
) -> Any:
"""
Create new product. Admin only.
"""
# Check if SKU exists
product = crud.product.get_product_by_sku(db, sku=product_in.sku)
if product:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Product with this SKU already exists",
)
# Check if category exists if provided
if product_in.category_id:
category = crud.product.get_category_by_id(db, category_id=product_in.category_id)
if not category:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Category not found",
)
product = crud.product.create_product(db, obj_in=product_in)
return product
@router.get("/{product_id}", response_model=schemas.ProductWithCategory)
def read_product(
*,
db: Session = Depends(deps.get_db),
product_id: str,
current_user: models.User = Depends(deps.get_current_active_user),
) -> Any:
"""
Get product by ID.
"""
product = crud.product.get_product_by_id(db, product_id=product_id)
if not product:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Product not found",
)
return product
@router.put("/{product_id}", response_model=schemas.Product)
def update_product(
*,
db: Session = Depends(deps.get_db),
product_id: str,
product_in: schemas.ProductUpdate,
current_user: models.User = Depends(deps.get_current_admin_user),
) -> Any:
"""
Update a product. Admin only.
"""
product = crud.product.get_product_by_id(db, product_id=product_id)
if not product:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Product not found",
)
# Check if updated SKU already exists
if product_in.sku and product_in.sku != product.sku:
existing_product = crud.product.get_product_by_sku(db, sku=product_in.sku)
if existing_product:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Product with this SKU already exists",
)
# Check if category exists if provided
if product_in.category_id:
category = crud.product.get_category_by_id(db, category_id=product_in.category_id)
if not category:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Category not found",
)
product = crud.product.update_product(db, db_obj=product, obj_in=product_in)
return product
@router.delete("/{product_id}", response_model=schemas.Product)
def delete_product(
*,
db: Session = Depends(deps.get_db),
product_id: str,
current_user: models.User = Depends(deps.get_current_admin_user),
) -> Any:
"""
Delete a product. Admin only.
"""
product = crud.product.get_product_by_id(db, product_id=product_id)
if not product:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Product not found",
)
# Check if product has inventory items
inventory_item = crud.inventory.get_inventory_item_by_product_id(db, product_id=product_id)
if inventory_item:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Cannot delete product with associated inventory items",
)
product = crud.product.delete_product(db, product_id=product_id)
return product