prep for pricing service work
This commit is contained in:
367
routes/routes.py
367
routes/routes.py
@@ -1,99 +1,102 @@
|
||||
from fastapi import APIRouter, Depends, HTTPException, UploadFile, File, Request, BackgroundTasks
|
||||
from fastapi import APIRouter, Depends, HTTPException, UploadFile, File, 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, CreateBoxRequest, BoxSchema, UpdateBoxRequest, CreateOpenBoxRequest, CreateOpenBoxResponse, OpenBoxSchema
|
||||
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, get_box_data, get_box_update_data, get_open_box_data
|
||||
|
||||
|
||||
from typing import Optional
|
||||
import logging
|
||||
|
||||
from schemas.file import (
|
||||
FileSchema,
|
||||
CreateFileRequest,
|
||||
CreateFileResponse,
|
||||
GetFileResponse,
|
||||
DeleteFileResponse,
|
||||
GetFileQueryParams
|
||||
)
|
||||
from schemas.box import (
|
||||
CreateBoxResponse,
|
||||
CreateBoxRequest,
|
||||
BoxSchema,
|
||||
UpdateBoxRequest,
|
||||
CreateOpenBoxRequest,
|
||||
CreateOpenBoxResponse,
|
||||
OpenBoxSchema
|
||||
)
|
||||
from services.file import FileService
|
||||
from services.box import BoxService
|
||||
from services.task import TaskService
|
||||
from dependencies import (
|
||||
get_file_service,
|
||||
get_box_service,
|
||||
get_task_service,
|
||||
get_create_file_metadata,
|
||||
get_box_data,
|
||||
get_box_update_data,
|
||||
get_open_box_data
|
||||
)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
router = APIRouter(prefix="/api", tags=["cards"])
|
||||
MAX_FILE_SIZE = 1024 * 1024 * 100 # 100 MB
|
||||
MAX_FILE_SIZE = 100 * 1024 * 1024 # 100 MB
|
||||
|
||||
async def validate_file_upload(file: UploadFile) -> bytes:
|
||||
"""Validate uploaded file and return its contents."""
|
||||
if not file.filename:
|
||||
raise HTTPException(status_code=400, detail="No filename provided")
|
||||
|
||||
content = await file.read()
|
||||
if len(content) > MAX_FILE_SIZE:
|
||||
raise HTTPException(status_code=413, detail="File too large")
|
||||
|
||||
return content
|
||||
|
||||
|
||||
## 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)
|
||||
):
|
||||
) -> CreateFileResponse:
|
||||
"""Create a new file entry with the uploaded file."""
|
||||
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")
|
||||
|
||||
content = await validate_file_upload(file)
|
||||
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
|
||||
|
||||
metadata.filename = metadata.filename or file.filename
|
||||
|
||||
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
|
||||
created_file = file_service.create_file(content, metadata)
|
||||
|
||||
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
|
||||
files=[FileSchema.from_orm(created_file)]
|
||||
)
|
||||
|
||||
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"
|
||||
)
|
||||
finally:
|
||||
await file.close()
|
||||
|
||||
## 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)
|
||||
):
|
||||
) -> GetFileResponse:
|
||||
"""
|
||||
Get file(s) by optional ID and/or status.
|
||||
If file_id is provided, returns that specific file.
|
||||
@@ -102,31 +105,26 @@ async def get_file(
|
||||
"""
|
||||
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)]
|
||||
)
|
||||
files = [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]
|
||||
)
|
||||
|
||||
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)
|
||||
):
|
||||
) -> DeleteFileResponse:
|
||||
"""Delete a file by ID."""
|
||||
try:
|
||||
file = file_service.delete_file(file_id)
|
||||
return DeleteFileResponse(
|
||||
@@ -138,14 +136,12 @@ async def delete_file(
|
||||
logger.error(f"Delete file failed: {str(e)}")
|
||||
raise HTTPException(status_code=400, detail=str(e))
|
||||
|
||||
|
||||
## BOX
|
||||
## CREATE
|
||||
@router.post("/boxes", response_model=CreateBoxResponse, status_code=201)
|
||||
async def create_box(
|
||||
box_data: CreateBoxRequest = Depends(get_box_data),
|
||||
box_service: BoxService = Depends(get_box_service)
|
||||
):
|
||||
) -> CreateBoxResponse:
|
||||
"""Create a new box."""
|
||||
try:
|
||||
result = box_service.create_box(box_data)
|
||||
return CreateBoxResponse(
|
||||
@@ -157,13 +153,13 @@ async def create_box(
|
||||
logger.error(f"Create box failed: {str(e)}")
|
||||
raise HTTPException(status_code=400, detail=str(e))
|
||||
|
||||
## UPDATE
|
||||
@router.put("/boxes/{box_id}", response_model=CreateBoxResponse)
|
||||
async def update_box(
|
||||
box_id: str,
|
||||
box_data: UpdateBoxRequest = Depends(get_box_update_data),
|
||||
box_service: BoxService = Depends(get_box_service)
|
||||
):
|
||||
) -> CreateBoxResponse:
|
||||
"""Update an existing box."""
|
||||
try:
|
||||
result = box_service.update_box(box_id, box_data)
|
||||
return CreateBoxResponse(
|
||||
@@ -175,12 +171,12 @@ async def update_box(
|
||||
logger.error(f"Update box failed: {str(e)}")
|
||||
raise HTTPException(status_code=400, detail=str(e))
|
||||
|
||||
## DELETE
|
||||
@router.delete("/boxes/{box_id}", response_model=CreateBoxResponse)
|
||||
async def delete_box(
|
||||
box_id: str,
|
||||
box_service: BoxService = Depends(get_box_service)
|
||||
):
|
||||
) -> CreateBoxResponse:
|
||||
"""Delete a box by ID."""
|
||||
try:
|
||||
result = box_service.delete_box(box_id)
|
||||
return CreateBoxResponse(
|
||||
@@ -192,13 +188,13 @@ async def delete_box(
|
||||
logger.error(f"Delete box failed: {str(e)}")
|
||||
raise HTTPException(status_code=400, detail=str(e))
|
||||
|
||||
# BOX OPEN
|
||||
@router.post("/boxes/{box_id}/open", response_model=CreateOpenBoxResponse, status_code=201)
|
||||
async def open_box(
|
||||
box_id: str,
|
||||
box_data: CreateOpenBoxRequest = Depends(get_open_box_data),
|
||||
box_service: BoxService = Depends(get_box_service)
|
||||
):
|
||||
) -> CreateOpenBoxResponse:
|
||||
"""Open a box by ID."""
|
||||
try:
|
||||
result = box_service.open_box(box_id, box_data)
|
||||
return CreateOpenBoxResponse(
|
||||
@@ -208,215 +204,4 @@ async def open_box(
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error(f"Open box 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))
|
Reference in New Issue
Block a user