giga_tcg/routes/routes.py
2025-02-04 22:30:33 -05:00

360 lines
12 KiB
Python

from fastapi import APIRouter, Depends, HTTPException, UploadFile, File, Request, BackgroundTasks
from fastapi.responses import StreamingResponse
from sqlalchemy.orm import Session
from typing import Dict, Any, List, Optional
from db.database import get_db
from services.upload import UploadService
from services.box import BoxService
from services.tcgplayer import TCGPlayerService
from services.data import DataService
from services.file import FileService
from services.product import ProductService
from services.task import TaskService
from schemas.file import FileSchema, CreateFileRequest, CreateFileResponse, GetFileResponse, DeleteFileResponse, GetFileQueryParams
from schemas.box import CreateBoxResponse, CreateBoxRequestData
from dependencies import get_data_service, get_upload_service, get_tcgplayer_service, get_box_service, get_create_file_metadata, get_file_service, get_product_service, get_task_service
import logging
logger = logging.getLogger(__name__)
router = APIRouter(prefix="/api", tags=["cards"])
MAX_FILE_SIZE = 1024 * 1024 * 100 # 100 MB
## GIGA FOR REAL
## FILE
## CREATE
@router.post(
"/files",
response_model=CreateFileResponse,
status_code=201
)
@router.post(
"/files",
response_model=CreateFileResponse,
status_code=201
)
async def create_file(
background_tasks: BackgroundTasks,
file: UploadFile = File(...),
metadata: CreateFileRequest = Depends(get_create_file_metadata),
file_service: FileService = Depends(get_file_service),
task_service: TaskService = Depends(get_task_service)
):
try:
# Validate file size before reading
if not file.filename:
raise HTTPException(status_code=400, detail="No filename provided")
# File size check
content = await file.read()
if len(content) > MAX_FILE_SIZE:
raise HTTPException(status_code=413, detail="File too large")
logger.debug(f"File received: {file.filename}")
logger.debug(f"Metadata: {metadata}")
# ADD FILENAME TO METADATA
if not metadata.filename:
metadata.filename = file.filename
# VALIDATE FILE
if not file_service.validate_file(content, metadata):
raise HTTPException(status_code=400, detail="Invalid file content")
# STORE FILE
created_file = file_service.create_file(content, metadata)
# Close file after processing
await file.close()
# handle manabox file background task
if metadata.source == 'manabox':
background_tasks.add_task(task_service.process_manabox_file, created_file)
return CreateFileResponse(
status_code=201,
success=True,
files=[FileSchema.from_orm(created_file)] # Changed to return list
)
except HTTPException as http_ex:
await file.close()
raise http_ex
except Exception as e:
await file.close()
logger.error(f"File upload failed: {str(e)}")
raise HTTPException(
status_code=500,
detail="Internal server error occurred during file upload"
)
## FILE
## GET
@router.get("/files/{file_id:path}", response_model=GetFileResponse)
@router.get("/files", response_model=GetFileResponse)
async def get_file(
file_id: Optional[str] = None,
query: GetFileQueryParams = Depends(),
file_service: FileService = Depends(get_file_service)
):
"""
Get file(s) by optional ID and/or status.
If file_id is provided, returns that specific file.
If status is provided, returns all files with that status.
If neither is provided, returns all files.
"""
try:
if file_id:
# Get specific file by ID
file = file_service.get_file(file_id)
return GetFileResponse(
status_code=200,
success=True,
files=[FileSchema.from_orm(file)]
)
else:
# Get multiple files with optional status filter
files = file_service.get_files(status=query.status)
return GetFileResponse(
status_code=200,
success=True,
files=[FileSchema.from_orm(f) for f in files]
)
except Exception as e:
logger.error(f"Get file(s) failed: {str(e)}")
raise HTTPException(status_code=400, detail=str(e))
## DELETE
@router.delete("/files/{file_id}", response_model=DeleteFileResponse)
async def delete_file(
file_id: str,
file_service: FileService = Depends(get_file_service)
):
try:
file = file_service.delete_file(file_id)
return DeleteFileResponse(
status_code=200,
success=True,
files=[FileSchema.from_orm(file)]
)
except Exception as e:
logger.error(f"Delete file failed: {str(e)}")
raise HTTPException(status_code=400, detail=str(e))
# FILE
"""
@router.post("/file/uploadManabox", response_model=FileUploadResponse)
async def upload_file(
background_tasks: BackgroundTasks,
file: UploadFile = File(...),
file_service: FileService = Depends(get_file_service),
product_service: ProductService = Depends(get_product_service),
metadata: FileMetadata = Depends(get_file_metadata)) -> FileUploadResponse:
try:
content = await file.read()
metadata.service = 'product'
result = file_service.upload_file(content, file.filename, metadata)
background_tasks.add_task(product_service.bg_process_manabox_file, result.id)
return result
except Exception as e:
logger.error(f"File upload failed: {str(e)}")
raise HTTPException(status_code=400, detail=str(e))
@router.get("/file/getPreparedFiles", response_model=GetPreparedFilesResponse)
async def get_prepared_files(file_service: FileService = Depends(get_file_service)) -> GetPreparedFilesResponse:
try:
response = file_service.get_prepared_files()
return response
except Exception as e:
logger.error(f"Get prepared files failed: {str(e)}")
raise HTTPException(status_code=400, detail=str(e))
@router.post("/file/deleteFile", response_model=FileDeleteResponse)
async def delete_file(file_id: str, file_service: FileService = Depends(get_file_service)) -> FileDeleteResponse:
try:
response = file_service.delete_file(file_id)
return response
except Exception as e:
logger.error(f"Delete file failed: {str(e)}")
raise HTTPException(status_code=400, detail=str(e))
@router.post("/box/createBox", response_model=CreateBoxResponse)
async def create_box(file_ids: list[str], create_box_data: CreateBoxRequestData, box_service: BoxService = Depends(get_box_service)) -> CreateBoxResponse:
try:
create_box_data = create_box_data.dict()
response = box_service.create_box(create_box_data, file_ids)
return response
except Exception as e:
logger.error(f"Create box failed: {str(e)}")
raise HTTPException(status_code=400, detail=str(e))
"""
## all old below
@router.post("/upload/manabox", response_model=dict)
async def upload_manabox(
background_tasks: BackgroundTasks,
upload_service: UploadService = Depends(get_upload_service),
data_service: DataService = Depends(get_data_service),
file: UploadFile = File(...)
) -> dict:
"""
Upload endpoint for Manabox CSV files
"""
try:
logger.info(f"file received: {file.filename}")
# Read the file content
content = await file.read()
filename = file.filename
file_size = len(content)
file_size_kb = file_size / 1024
if not content:
logger.error("Empty file content")
raise HTTPException(status_code=400, detail="Empty file content")
# You might want to validate it's a CSV file
if not file.filename.endswith('.csv'):
logger.error("File must be a CSV")
raise HTTPException(status_code=400, detail="File must be a CSV")
result = upload_service.process_manabox_upload(content, filename, file_size_kb)
background_tasks.add_task(data_service.bg_set_manabox_tcg_relationship, upload_id=result[1])
return result[0]
except Exception as e:
logger.error(f"Manabox upload failed: {str(e)}")
raise HTTPException(status_code=400, detail=str(e))
@router.post("/createBox", response_model=dict)
async def create_box(
upload_id: str,
box_service: BoxService = Depends(get_box_service)
) -> dict:
try:
result = box_service.convert_upload_to_boxes(upload_id)
except Exception as e:
logger.error(f"Box creation failed: {str(e)}")
raise HTTPException(status_code=400, detail=str(e))
return result
@router.post("/deleteBox", response_model=dict)
async def delete_box(
box_id: str,
box_service: BoxService = Depends(get_box_service)
) -> dict:
try:
result = box_service.delete_box(box_id)
except Exception as e:
logger.error(f"Box deletion failed: {str(e)}")
raise HTTPException(status_code=400, detail=str(e))
return result
@router.post("/tcgplayer/add/box/{box_id}", response_model=dict)
async def add_box(box_id: str = None, tcgplayer_service: TCGPlayerService = Depends(get_tcgplayer_service)):
try:
csv_content = tcgplayer_service.add_to_tcgplayer(box_id)
return StreamingResponse(
iter([csv_content]),
media_type="text/csv",
headers={"Content-Disposition": "attachment; filename=add_to_tcgplayer.csv"}
)
except Exception as e:
logger.error(f"Box add failed: {str(e)}")
raise HTTPException(status_code=400, detail=str(e))
@router.post("/tcgplayer/update/box/{box_id}", response_model=dict)
async def update_box(box_id: int = None):
"""asdf"""
pass
@router.post("/tcgplayer/updateInventory", response_model=dict)
async def update_inventory(
background_tasks: BackgroundTasks,
tcgplayer_service: TCGPlayerService = Depends(get_tcgplayer_service),
data_service: DataService = Depends(get_data_service)):
try:
result = tcgplayer_service.update_inventory('live')
export_id = result['export_id']
background_tasks.add_task(data_service.bg_set_tcg_inventory_product_relationship, export_id)
return result
except Exception as e:
logger.error(f"Inventory update failed: {str(e)}")
raise HTTPException(status_code=400, detail=str(e))
@router.post("/tcgplayer/updatePricing", response_model=dict)
async def update_inventory(
tcgplayer_service: TCGPlayerService = Depends(get_tcgplayer_service),
group_ids: Dict = None):
try:
result = tcgplayer_service.update_pricing(group_ids)
return result
except Exception as e:
logger.error(f"Pricing update failed: {str(e)}")
raise HTTPException(status_code=400, detail=str(e))
@router.post("/tcgplayer/updatePricingAll", response_model=dict)
async def update_inventory(tcgplayer_service: TCGPlayerService = Depends(get_tcgplayer_service)):
try:
result = tcgplayer_service.update_pricing_all()
return result
except Exception as e:
logger.error(f"Pricing update failed: {str(e)}")
raise HTTPException(status_code=400, detail=str(e))
@router.get("/tcgplayer/createLiveInventoryPricingUpdateFile")
async def create_inventory_import(
tcgplayer_service: TCGPlayerService = Depends(get_tcgplayer_service)
):
try:
csv_content = tcgplayer_service.get_live_inventory_pricing_update_csv()
return StreamingResponse(
iter([csv_content]),
media_type="text/csv",
headers={"Content-Disposition": "attachment; filename=inventory_pricing_update.csv"}
)
except Exception as e:
logger.error(f"Inventory import creation failed: {str(e)}")
raise HTTPException(status_code=400, detail=str(e))