Exception handling enhancement

This commit is contained in:
2025-09-23 22:42:26 +02:00
parent b1a76cdb57
commit 98285aa8aa
35 changed files with 3283 additions and 1743 deletions

View File

@@ -1,16 +1,17 @@
# app/api/v1/product.py
"""Summary description ....
"""
Product endpoints - simplified with service-level exception handling.
This module provides classes and functions for:
- ....
- ....
- ....
- Product CRUD operations with marketplace support
- Advanced product filtering and search
- Product export functionality
"""
import logging
from typing import Optional
from fastapi import APIRouter, Depends, HTTPException, Query
from fastapi import APIRouter, Depends, Query
from fastapi.responses import StreamingResponse
from sqlalchemy.orm import Session
@@ -26,183 +27,115 @@ router = APIRouter()
logger = logging.getLogger(__name__)
# Enhanced Product Routes with Marketplace Support
@router.get("/product", response_model=ProductListResponse)
def get_products(
skip: int = Query(0, ge=0),
limit: int = Query(100, ge=1, le=1000),
brand: Optional[str] = Query(None),
category: Optional[str] = Query(None),
availability: Optional[str] = Query(None),
marketplace: Optional[str] = Query(None, description="Filter by marketplace"),
shop_name: Optional[str] = Query(None, description="Filter by shop name"),
search: Optional[str] = Query(None),
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user),
skip: int = Query(0, ge=0),
limit: int = Query(100, ge=1, le=1000),
brand: Optional[str] = Query(None),
category: Optional[str] = Query(None),
availability: Optional[str] = Query(None),
marketplace: Optional[str] = Query(None, description="Filter by marketplace"),
shop_name: Optional[str] = Query(None, description="Filter by shop name"),
search: Optional[str] = Query(None),
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user),
):
"""Get products with advanced filtering including marketplace and shop (Protected)."""
try:
products, total = product_service.get_products_with_filters(
db=db,
skip=skip,
limit=limit,
brand=brand,
category=category,
availability=availability,
marketplace=marketplace,
shop_name=shop_name,
search=search,
)
products, total = product_service.get_products_with_filters(
db=db,
skip=skip,
limit=limit,
brand=brand,
category=category,
availability=availability,
marketplace=marketplace,
shop_name=shop_name,
search=search,
)
return ProductListResponse(
products=products, total=total, skip=skip, limit=limit
)
except Exception as e:
logger.error(f"Error getting products: {str(e)}")
raise HTTPException(status_code=500, detail="Internal server error")
return ProductListResponse(
products=products, total=total, skip=skip, limit=limit
)
@router.post("/product", response_model=ProductResponse)
def create_product(
product: ProductCreate,
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user),
product: ProductCreate,
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user),
):
"""Create a new product with validation and marketplace support (Protected)."""
try:
logger.info(f"Starting product creation for ID: {product.product_id}")
logger.info(f"Starting product creation for ID: {product.product_id}")
# Check if product_id already exists
logger.info("Checking for existing product...")
existing = product_service.get_product_by_id(db, product.product_id)
logger.info(f"Existing product found: {existing is not None}")
db_product = product_service.create_product(db, product)
logger.info("Product created successfully")
if existing:
logger.info("Product already exists, raising 400 error")
raise HTTPException(
status_code=400, detail="Product with this ID already exists"
)
logger.info("No existing product found, proceeding to create...")
db_product = product_service.create_product(db, product)
logger.info("Product created successfully")
return db_product
except HTTPException as he:
logger.info(f"HTTPException raised: {he.status_code} - {he.detail}")
raise # Re-raise HTTP exceptions
except ValueError as e:
logger.error(f"ValueError: {str(e)}")
raise HTTPException(status_code=400, detail=str(e))
except Exception as e:
logger.error(f"Unexpected error: {str(e)}", exc_info=True)
raise HTTPException(status_code=500, detail="Internal server error")
return db_product
@router.get("/product/{product_id}", response_model=ProductDetailResponse)
def get_product(
product_id: str,
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user),
product_id: str,
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user),
):
"""Get product with stock information (Protected)."""
try:
product = product_service.get_product_by_id(db, product_id)
if not product:
raise HTTPException(status_code=404, detail="Product not found")
product = product_service.get_product_by_id_or_raise(db, product_id)
# Get stock information if GTIN exists
stock_info = None
if product.gtin:
stock_info = product_service.get_stock_info(db, product.gtin)
# Get stock information if GTIN exists
stock_info = None
if product.gtin:
stock_info = product_service.get_stock_info(db, product.gtin)
return ProductDetailResponse(product=product, stock_info=stock_info)
except HTTPException:
raise
except Exception as e:
logger.error(f"Error getting product {product_id}: {str(e)}")
raise HTTPException(status_code=500, detail="Internal server error")
return ProductDetailResponse(product=product, stock_info=stock_info)
@router.put("/product/{product_id}", response_model=ProductResponse)
def update_product(
product_id: str,
product_update: ProductUpdate,
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user),
product_id: str,
product_update: ProductUpdate,
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user),
):
"""Update product with validation and marketplace support (Protected)."""
try:
product = product_service.get_product_by_id(db, product_id)
if not product:
raise HTTPException(status_code=404, detail="Product not found")
updated_product = product_service.update_product(db, product_id, product_update)
return updated_product
except HTTPException:
raise
except ValueError as e:
raise HTTPException(status_code=400, detail=str(e))
except Exception as e:
logger.error(f"Error updating product {product_id}: {str(e)}")
raise HTTPException(status_code=500, detail="Internal server error")
updated_product = product_service.update_product(db, product_id, product_update)
return updated_product
@router.delete("/product/{product_id}")
def delete_product(
product_id: str,
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user),
product_id: str,
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user),
):
"""Delete product and associated stock (Protected)."""
try:
product = product_service.get_product_by_id(db, product_id)
if not product:
raise HTTPException(status_code=404, detail="Product not found")
product_service.delete_product(db, product_id)
return {"message": "Product and associated stock deleted successfully"}
except HTTPException:
raise
except Exception as e:
logger.error(f"Error deleting product {product_id}: {str(e)}")
raise HTTPException(status_code=500, detail="Internal server error")
product_service.delete_product(db, product_id)
return {"message": "Product and associated stock deleted successfully"}
# Export with streaming for large datasets (Protected)
@router.get("/export-csv")
async def export_csv(
marketplace: Optional[str] = Query(None, description="Filter by marketplace"),
shop_name: Optional[str] = Query(None, description="Filter by shop name"),
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user),
marketplace: Optional[str] = Query(None, description="Filter by marketplace"),
shop_name: Optional[str] = Query(None, description="Filter by shop name"),
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user),
):
"""Export products as CSV with streaming and marketplace filtering (Protected)."""
try:
def generate_csv():
return product_service.generate_csv_export(
db=db, marketplace=marketplace, shop_name=shop_name
)
filename = "products_export"
if marketplace:
filename += f"_{marketplace}"
if shop_name:
filename += f"_{shop_name}"
filename += ".csv"
return StreamingResponse(
generate_csv(),
media_type="text/csv",
headers={"Content-Disposition": f"attachment; filename={filename}"},
def generate_csv():
return product_service.generate_csv_export(
db=db, marketplace=marketplace, shop_name=shop_name
)
except Exception as e:
logger.error(f"Error exporting CSV: {str(e)}")
raise HTTPException(status_code=500, detail="Internal server error")
filename = "products_export"
if marketplace:
filename += f"_{marketplace}"
if shop_name:
filename += f"_{shop_name}"
filename += ".csv"
return StreamingResponse(
generate_csv(),
media_type="text/csv",
headers={"Content-Disposition": f"attachment; filename={filename}"},
)