from typing import List, Dict, Optional, Union, Any from sqlalchemy.orm import Session from sqlalchemy import and_, or_ from models.book import Book from schemas.book import BookCreate, BookUpdate def validate_isbn(isbn: str) -> bool: """ Validate ISBN format. Args: isbn: ISBN string to validate Returns: bool: True if ISBN format is valid, False otherwise """ # Remove any hyphens or spaces isbn = isbn.replace('-', '').replace(' ', '') if len(isbn) == 13: # ISBN-13 return isbn.isdigit() elif len(isbn) == 10: # ISBN-10 return isbn[:-1].isdigit() and (isbn[-1].isdigit() or isbn[-1].lower() == 'x') return False def get_available_books(db: Session, skip: int = 0, limit: int = 100) -> List[Book]: """ Get list of available books with pagination. Args: db: Database session skip: Number of records to skip limit: Maximum number of records to return Returns: List of available Book objects """ return db.query(Book)\ .filter(Book.is_available == True)\ .filter(Book.quantity > 0)\ .offset(skip)\ .limit(limit)\ .all() def search_books( db: Session, search_term: str, include_unavailable: bool = False ) -> List[Book]: """ Search books by title, author or ISBN. Args: db: Database session search_term: Search string include_unavailable: Whether to include unavailable books Returns: List of matching Book objects """ query = db.query(Book) # Create search conditions search_conditions = or_( Book.title.ilike(f"%{search_term}%"), Book.author.ilike(f"%{search_term}%"), Book.isbn == search_term ) if not include_unavailable: query = query.filter(Book.is_available == True) return query.filter(search_conditions).all() def update_book_availability(db: Session, book_id: int) -> Optional[Book]: """ Update book availability based on quantity. Args: db: Database session book_id: ID of book to update Returns: Updated Book object if found, None otherwise """ book = db.query(Book).filter(Book.id == book_id).first() if book: book.is_available = book.quantity > 0 db.commit() db.refresh(book) return book return None def validate_book_data(book_data: Union[BookCreate, BookUpdate]) -> Dict[str, str]: """ Validate book data before creation/update. Args: book_data: Book data to validate Returns: Dict containing any validation errors """ errors = {} if hasattr(book_data, 'isbn') and book_data.isbn: if not validate_isbn(book_data.isbn): errors['isbn'] = "Invalid ISBN format" if hasattr(book_data, 'price') and book_data.price: if book_data.price < 0: errors['price'] = "Price cannot be negative" if hasattr(book_data, 'quantity') and book_data.quantity: if book_data.quantity < 0: errors['quantity'] = "Quantity cannot be negative" return errors