project-cqhzqd/helpers/book_helpers.py
2025-03-28 01:27:20 +00:00

127 lines
3.5 KiB
Python

from typing import List, Dict, Optional, Union, Any
from datetime import datetime
import re
from sqlalchemy.orm import Session
from pydantic import ValidationError
def validate_isbn(isbn: str) -> bool:
"""
Validate ISBN format (supports both ISBN-10 and ISBN-13).
Args:
isbn: ISBN string to validate
Returns:
bool: True if ISBN format is valid, False otherwise
"""
# Remove hyphens and spaces
isbn = isbn.replace('-', '').replace(' ', '')
if len(isbn) == 10:
# ISBN-10 validation
if not isbn[:-1].isdigit():
return False
check_digit = 'X' if isbn[-1].upper() == 'X' else isbn[-1]
if not (check_digit.isdigit() or check_digit == 'X'):
return False
return True
elif len(isbn) == 13:
# ISBN-13 validation
if not isbn.isdigit():
return False
return isbn.startswith('978') or isbn.startswith('979')
return False
def format_book_price(price: int) -> str:
"""
Format book price from cents to currency string.
Args:
price: Price in cents
Returns:
str: Formatted price string
"""
return f"${price/100:.2f}"
def get_books_by_author(db: Session, author: str) -> List[Any]:
"""
Get all books by a specific author.
Args:
db: Database session
author: Author name to search for
Returns:
List of Book objects by the author
"""
return db.query(Book).filter(Book.author == author).all()
def search_books(
db: Session,
search_term: str,
include_unavailable: bool = False
) -> List[Any]:
"""
Search books by title, author, or ISBN.
Args:
db: Database session
search_term: Term to search for
include_unavailable: Whether to include unavailable books
Returns:
List of matching Book objects
"""
query = db.query(Book).filter(
(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.all()
def validate_publication_year(year: int) -> bool:
"""
Validate if publication year is within acceptable range.
Args:
year: Publication year to validate
Returns:
bool: True if year is valid, False otherwise
"""
current_year = datetime.now().year
return 1800 <= year <= current_year + 1
def process_book_data(book_data: Dict[str, Any]) -> Dict[str, Any]:
"""
Process and validate book data before creation/update.
Args:
book_data: Dictionary containing book data
Returns:
Dict with processed and validated data
"""
processed_data = book_data.copy()
# Validate ISBN
if 'isbn' in processed_data and not validate_isbn(processed_data['isbn']):
raise ValidationError("Invalid ISBN format")
# Validate publication year
if 'publication_year' in processed_data:
if not validate_publication_year(processed_data['publication_year']):
raise ValidationError("Invalid publication year")
# Ensure title and author are stripped of whitespace
if 'title' in processed_data:
processed_data['title'] = processed_data['title'].strip()
if 'author' in processed_data:
processed_data['author'] = processed_data['author'].strip()
return processed_data