130 lines
4.0 KiB
Python
130 lines
4.0 KiB
Python
from fastapi import APIRouter, Depends, HTTPException, UploadFile, File
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
from sqlalchemy import select, func, delete
|
|
|
|
from app.core.database import get_db
|
|
from app.core.deps import get_approved_user
|
|
from app.models.user import User
|
|
from app.models.collection import CollectionCard
|
|
from app.schemas.collection import CollectionCardOut, CollectionStatsOut, PaginatedCollection
|
|
from app.services.imports import archidekt, manabox
|
|
from app.services.imports.enrichment import enrich_and_upsert
|
|
|
|
router = APIRouter()
|
|
|
|
|
|
@router.post("/import/archidekt", status_code=201)
|
|
async def import_archidekt(
|
|
file: UploadFile = File(...),
|
|
replace: bool = False,
|
|
user: User = Depends(get_approved_user),
|
|
db: AsyncSession = Depends(get_db),
|
|
):
|
|
raw = await file.read()
|
|
rows = archidekt.parse(raw)
|
|
if replace:
|
|
await db.execute(delete(CollectionCard).where(CollectionCard.owner_id == user.id))
|
|
await db.commit()
|
|
imported = await enrich_and_upsert(rows, user.id, db)
|
|
return {"imported": imported}
|
|
|
|
|
|
@router.post("/import/manabox", status_code=201)
|
|
async def import_manabox(
|
|
file: UploadFile = File(...),
|
|
replace: bool = False,
|
|
user: User = Depends(get_approved_user),
|
|
db: AsyncSession = Depends(get_db),
|
|
):
|
|
raw = await file.read()
|
|
rows = manabox.parse(raw)
|
|
if replace:
|
|
await db.execute(delete(CollectionCard).where(CollectionCard.owner_id == user.id))
|
|
await db.commit()
|
|
imported = await enrich_and_upsert(rows, user.id, db)
|
|
return {"imported": imported}
|
|
|
|
|
|
@router.get("/", response_model=PaginatedCollection)
|
|
async def list_collection(
|
|
search: str = "",
|
|
page: int = 1,
|
|
page_size: int = 50,
|
|
user: User = Depends(get_approved_user),
|
|
db: AsyncSession = Depends(get_db),
|
|
):
|
|
query = select(CollectionCard).where(CollectionCard.owner_id == user.id)
|
|
if search:
|
|
query = query.where(CollectionCard.card_name.ilike(f"%{search}%"))
|
|
|
|
total_result = await db.execute(
|
|
select(func.count()).select_from(query.subquery())
|
|
)
|
|
total = total_result.scalar_one()
|
|
|
|
result = await db.execute(
|
|
query.order_by(CollectionCard.card_name)
|
|
.offset((page - 1) * page_size)
|
|
.limit(page_size)
|
|
)
|
|
items = result.scalars().all()
|
|
|
|
return PaginatedCollection(
|
|
items=items, total=total, page=page, page_size=page_size,
|
|
pages=max(1, -(-total // page_size)),
|
|
)
|
|
|
|
|
|
@router.get("/stats", response_model=CollectionStatsOut)
|
|
async def collection_stats(
|
|
user: User = Depends(get_approved_user),
|
|
db: AsyncSession = Depends(get_db),
|
|
):
|
|
result = await db.execute(
|
|
select(CollectionCard).where(CollectionCard.owner_id == user.id)
|
|
)
|
|
cards = result.scalars().all()
|
|
|
|
total = sum(c.quantity + c.foil_quantity for c in cards)
|
|
unique = len(cards)
|
|
foil = sum(c.foil_quantity for c in cards)
|
|
|
|
value = None
|
|
prices = []
|
|
for c in cards:
|
|
if c.scryfall_data:
|
|
p = c.scryfall_data.get("prices", {}).get("usd")
|
|
if p:
|
|
prices.append(float(p) * (c.quantity + c.foil_quantity))
|
|
if prices:
|
|
value = sum(prices)
|
|
|
|
return CollectionStatsOut(
|
|
total_cards=total, unique_cards=unique, foil_cards=foil, estimated_value=value
|
|
)
|
|
|
|
|
|
@router.delete("/", status_code=204)
|
|
async def clear_collection(
|
|
user: User = Depends(get_approved_user),
|
|
db: AsyncSession = Depends(get_db),
|
|
):
|
|
await db.execute(delete(CollectionCard).where(CollectionCard.owner_id == user.id))
|
|
await db.commit()
|
|
|
|
|
|
@router.delete("/{card_id}", status_code=204)
|
|
async def delete_card(
|
|
card_id: int,
|
|
user: User = Depends(get_approved_user),
|
|
db: AsyncSession = Depends(get_db),
|
|
):
|
|
result = await db.execute(
|
|
select(CollectionCard).where(CollectionCard.id == card_id, CollectionCard.owner_id == user.id)
|
|
)
|
|
card = result.scalar_one_or_none()
|
|
if not card:
|
|
raise HTTPException(status_code=404, detail="Card not found")
|
|
await db.delete(card)
|
|
await db.commit()
|