Add helper functions for Exception

This commit is contained in:
Backend IM Bot 2025-03-29 22:41:04 +00:00
parent 12b83331c6
commit a9e30e13fb

View File

@ -1,117 +1,156 @@
from typing import Dict, Optional, Union, Any from typing import Dict, Optional, Union, Any
from decimal import Decimal
from sqlalchemy.orm import Session
from fastapi import HTTPException from fastapi import HTTPException
from pydantic import BaseModel, ValidationError
from decimal import Decimal
import logging
from datetime import datetime
from sqlalchemy.orm import Session
from models.product import Product from models.product import Product
from schemas.product import ProductCreate
def validate_product_data(product_data: ProductCreate) -> bool: def validate_product_data(
name: str,
price: Decimal,
stock: int
) -> Dict[str, Any]:
""" """
Validate product data before creation. Validates product data before creation.
Args: Args:
product_data: Product data to validate name: Product name
price: Product price
stock: Stock quantity
Returns: Returns:
bool: True if data is valid, False otherwise Dict with validation results
Raises:
ValidationError: If validation fails
""" """
if not product_data.name or len(product_data.name.strip()) == 0: errors = {}
return False
if not product_data.price or product_data.price <= Decimal('0.00'): if not name or len(name) < 3:
return False errors["name"] = "Product name must be at least 3 characters"
if product_data.quantity and product_data.quantity < 0: if price <= Decimal(0):
return False errors["price"] = "Price must be greater than 0"
return True if stock < 0:
errors["stock"] = "Stock cannot be negative"
return {"is_valid": len(errors) == 0, "errors": errors}
def check_duplicate_product(db: Session, name: str) -> bool: def handle_product_exception(
exception: Exception,
operation: str
) -> HTTPException:
""" """
Check if a product with the same name already exists. Handles product related exceptions and returns appropriate HTTP exceptions.
Args:
exception: The exception that occurred
operation: The operation being performed
Returns:
HTTPException with appropriate status code and detail
"""
error_map = {
ValidationError: (400, "Invalid product data"),
ValueError: (400, "Invalid value provided"),
Exception: (500, "Internal server error")
}
status_code, detail = error_map.get(
type(exception),
(500, "Internal server error")
)
logging.error(
f"Error during {operation}: {str(exception)}"
)
return HTTPException(
status_code=status_code,
detail=detail
)
def check_duplicate_product(
db: Session,
name: str,
sku: Optional[str] = None
) -> bool:
"""
Check if product with same name or SKU already exists.
Args: Args:
db: Database session db: Database session
name: Product name to check name: Product name
sku: Product SKU
Returns: Returns:
bool: True if duplicate exists, False otherwise bool indicating if duplicate exists
""" """
existing_product = db.query(Product).filter(Product.name == name).first() query = db.query(Product)
return bool(existing_product) if query.filter(Product.name == name).first():
return True
if sku and query.filter(Product.sku == sku).first():
return True
return False
def create_product_safely(db: Session, product_data: ProductCreate) -> Union[Product, Dict[str, str]]: def format_product_response(
product: Product,
include_timestamps: bool = False
) -> Dict[str, Any]:
""" """
Create a new product with validation and error handling. Formats product data for API response.
Args: Args:
db: Database session product: Product model instance
product_data: Product data for creation include_timestamps: Whether to include timestamps
Returns: Returns:
Product object if created successfully, error dict otherwise Formatted product dictionary
""" """
if not validate_product_data(product_data): response = {
raise HTTPException(status_code=400, detail="Invalid product data")
if check_duplicate_product(db, product_data.name):
raise HTTPException(status_code=400, detail="Product with this name already exists")
try:
db_product = Product(
name=product_data.name,
description=product_data.description,
price=product_data.price,
quantity=product_data.quantity,
category_id=product_data.category_id
)
db.add(db_product)
db.commit()
db.refresh(db_product)
return db_product
except Exception as e:
db.rollback()
raise HTTPException(status_code=500, detail=f"Failed to create product: {str(e)}")
def format_product_response(product: Product) -> Dict[str, Any]:
"""
Format product data for API response.
Args:
product: Product object to format
Returns:
Dict containing formatted product data
"""
return {
"id": product.id, "id": product.id,
"name": product.name, "name": product.name,
"description": product.description,
"price": str(product.price), "price": str(product.price),
"quantity": product.quantity, "stock": product.stock,
"category_id": product.category_id, "sku": product.sku
"created_at": product.created_at.isoformat() if product.created_at else None
} }
if include_timestamps:
response.update({
"created_at": product.created_at.isoformat(),
"updated_at": product.updated_at.isoformat() if product.updated_at else None
})
return response
def validate_product_update(product_data: Dict[str, Any]) -> bool: def log_product_operation(
operation: str,
product_id: int,
user_id: Optional[int] = None,
details: Optional[Dict] = None
) -> None:
""" """
Validate product data for updates. Logs product operations for auditing.
Args: Args:
product_data: Product update data to validate operation: Type of operation performed
product_id: ID of the product
Returns: user_id: ID of user performing operation
bool: True if update data is valid, False otherwise details: Additional operation details
""" """
if "price" in product_data and product_data["price"] <= Decimal('0.00'): log_entry = {
return False "timestamp": datetime.utcnow().isoformat(),
"operation": operation,
if "quantity" in product_data and product_data["quantity"] < 0: "product_id": product_id,
return False "user_id": user_id,
"details": details or {}
if "name" in product_data and len(product_data["name"].strip()) == 0: }
return False
logging.info(
return True f"Product Operation: {log_entry}"
)