- Migrated all schemas to Pydantic v2 syntax (model_config, ConfigDict) - Fixed mutable default in ProtoMessageBase using Field(default_factory=datetime.now) - Consolidated CardCollection and Wishlist schemas in user_card_collection.py - Created game_schemas.py with GameCreate, GameResponse, GameJoinRequest, etc. - Created mtg_card_schemas.py with MtgCardResponse, MtgCardSearchRequest, etc. - Added CardImportBatchCreate, CardImportBatchResponse, UserCardImportCreate/Response schemas - Fixed duplicate UserCardImportRecord class between card_import_batch.py and user_card_import_record.py - Updated __init__.py with comprehensive schema exports - Created verify_schemas.py for schema-model matching verification
130 lines
3.2 KiB
Python
130 lines
3.2 KiB
Python
"""
|
|
Pydantic schemas for card import feature.
|
|
|
|
Provides request/response models for importing card collections
|
|
and using them for deckbuilding.
|
|
"""
|
|
from pydantic import BaseModel, Field, ConfigDict
|
|
from typing import List, Optional, Dict, Any
|
|
from datetime import datetime
|
|
|
|
|
|
class CardImportRequest(BaseModel):
|
|
"""Request body for importing card collection."""
|
|
card_names: List[str] = Field(
|
|
...,
|
|
min_length=1,
|
|
max_length=10000,
|
|
description="List of card names to import",
|
|
examples=[["Lightning Bolt", "Shock", "Thoughtseize"]]
|
|
)
|
|
|
|
|
|
class CardImportResponse(BaseModel):
|
|
"""Response after successful card import."""
|
|
message: str
|
|
card_count: int
|
|
card_names: List[str]
|
|
imported_at: datetime
|
|
|
|
|
|
class CardImportStatusResponse(BaseModel):
|
|
"""Response showing current import status."""
|
|
has_import: bool
|
|
card_count: Optional[int] = None
|
|
card_names: Optional[List[str]] = None
|
|
last_imported: Optional[datetime] = None
|
|
|
|
|
|
class CardMatchResult(BaseModel):
|
|
"""Result of matching imported card name to database card."""
|
|
card_id: Optional[int] = None
|
|
card_name: str
|
|
matched_name: str
|
|
match_type: str # 'exact', 'fuzzy', 'partial'
|
|
confidence: float # 0.0 to 1.0
|
|
|
|
|
|
class CardImportSummary(BaseModel):
|
|
"""Summary of card import with match results."""
|
|
total_cards: int
|
|
matched_cards: List[CardMatchResult]
|
|
unmatched_cards: List[str]
|
|
import_id: Optional[int] = None
|
|
|
|
|
|
# ===== Card Import Batch Schemas =====
|
|
|
|
class CardImportBatchCreate(BaseModel):
|
|
"""Card import batch creation request."""
|
|
user_id: int
|
|
card_names: List[str] = Field(..., min_length=1, max_length=10000)
|
|
source: Optional[str] = None # 'manual', 'mtgjson', 'deck_text'
|
|
|
|
|
|
class CardImportBatchResponse(BaseModel):
|
|
"""Card import batch response."""
|
|
id: int
|
|
user_id: int
|
|
card_names: List[str]
|
|
source: Optional[str]
|
|
status: str # 'pending', 'processing', 'completed', 'failed'
|
|
total_cards: int
|
|
matched_cards: int
|
|
unmatched_cards: int
|
|
created_at: datetime
|
|
updated_at: datetime
|
|
|
|
model_config = ConfigDict(from_attributes=True)
|
|
|
|
|
|
class UserCardImportCreate(BaseModel):
|
|
"""User card import request."""
|
|
batch_id: int
|
|
card_id: int
|
|
quantity: int = Field(1, ge=1)
|
|
match_confidence: Optional[float] = None
|
|
|
|
|
|
class UserCardImportResponse(BaseModel):
|
|
"""User card import response."""
|
|
id: int
|
|
user_id: int
|
|
batch_id: int
|
|
card_id: int
|
|
quantity: int
|
|
match_confidence: Optional[float]
|
|
created_at: datetime
|
|
|
|
model_config = ConfigDict(from_attributes=True)
|
|
|
|
|
|
class UserCardImportRecordResponse(BaseModel):
|
|
"""User card import record response."""
|
|
id: int
|
|
user_id: int
|
|
card_id: int
|
|
batch_id: int
|
|
quantity: int
|
|
source: Optional[str]
|
|
created_at: datetime
|
|
|
|
model_config = ConfigDict(from_attributes=True)
|
|
|
|
|
|
# Generic response models
|
|
class MessageResponse(BaseModel):
|
|
"""Generic message response."""
|
|
message: str
|
|
|
|
|
|
class CountResponse(BaseModel):
|
|
"""Generic count response."""
|
|
count: int
|
|
|
|
|
|
class ErrorResponse(BaseModel):
|
|
"""Error response with details."""
|
|
detail: str
|
|
error_code: Optional[str] = None
|