from fastapi import APIRouter, HTTPException, Depends, Query, UploadFile, File from typing import List from datetime import datetime from enum import Enum from app.schemas.tcgplayer import TCGPlayerAPIOrderSummary, TCGPlayerAPIOrder from app.schemas.generate import GenerateAddressLabelsRequest, GeneratePackingSlipsRequest, GeneratePullSheetsRequest, GenerateResponse, GenerateReturnLabelsRequest from app.schemas.file import FileUpload from app.services.service_manager import ServiceManager from app.services.file_service import FileService from sqlalchemy.orm import Session from app.db.database import get_db import os import tempfile import logging logger = logging.getLogger(__name__) class SearchRange(str, Enum): LAST_WEEK = "LastWeek" LAST_MONTH = "LastMonth" LAST_THREE_MONTHS = "LastThreeMonths" LAST_FOUR_MONTHS = "LastFourMonths" LAST_TWO_YEARS = "LastTwoYears" class LabelType(str, Enum): DK1201 = "dk1201" DK1241 = "dk1241" # Initialize service manager service_manager = ServiceManager() # Initialize router router = APIRouter(prefix="/orders") @router.get("/", response_model=List[TCGPlayerAPIOrderSummary]) async def get_orders( search_range: SearchRange = SearchRange.LAST_THREE_MONTHS, open_only: bool = False ) -> List[TCGPlayerAPIOrderSummary]: """ Retrieve orders from TCGPlayer based on search criteria. Args: search_range: Time range to search for orders open_only: Whether to only return open orders Returns: List of orders matching the search criteria """ try: order_management = service_manager.get_service('order_management') orders = await order_management.get_orders(search_range, open_only) return orders except Exception as e: raise HTTPException(status_code=500, detail=f"Failed to fetch orders: {str(e)}") @router.get("/{order_id}", response_model=TCGPlayerAPIOrder) async def get_order(order_id: str) -> TCGPlayerAPIOrder: """ Retrieve a specific order by ID. Args: order_id: The TCGPlayer order number Returns: The requested order details """ try: order_management = service_manager.get_service('order_management') order = await order_management.get_order(order_id) if not order: raise HTTPException(status_code=404, detail=f"Order {order_id} not found") return order except HTTPException: raise except Exception as e: raise HTTPException(status_code=500, detail=f"Failed to fetch order: {str(e)}") @router.post("/generate-pull-sheets", response_model=GenerateResponse) async def generate_pull_sheets( request: GeneratePullSheetsRequest, db: Session = Depends(get_db) ) -> GenerateResponse: """ Generate and print pull sheets for the specified orders. Args: request: Dictionary containing: - order_ids: List of TCGPlayer order numbers Returns: Success status of the operation """ try: pull_sheet_service = service_manager.get_service('pull_sheet') order_ids = request.order_ids pull_sheet = await pull_sheet_service.get_or_create_rendered_pull_sheet(db, order_ids) regular_printer = service_manager.get_service('regular_printer') success = await regular_printer.print_file(pull_sheet.path) # TODO: change to accept file instead of path return {"success": success, "message": "Pull sheets generated and printed successfully"} except Exception as e: raise HTTPException(status_code=500, detail=f"Failed to generate pull sheet: {str(e)}") @router.post("/generate-packing-slips", response_model=GenerateResponse) async def generate_packing_slips( request: GeneratePackingSlipsRequest, db: Session = Depends(get_db) ) -> GenerateResponse: """ Generate and print packing slips for the specified orders. Args: request: Dictionary containing: - order_ids: List of TCGPlayer order numbers """ try: order_management = service_manager.get_service('order_management') # get or create packing slips packing_slips = await order_management.get_or_create_packing_slip(db, request.order_ids) if packing_slips: # print packing slips label_printer = service_manager.get_service('label_printer') success = await label_printer.print_file(packing_slips.path, label_size="dk1241", label_type="packing_slip") return {"success": success, "message": "Packing slips generated and printed successfully"} return {"success": False, "message": "Packing slips not found"} except Exception as e: raise HTTPException(status_code=500, detail=f"Failed to generate packing slips: {str(e)}") @router.post("/generate-address-labels") async def generate_address_labels( request: GenerateAddressLabelsRequest, db: Session = Depends(get_db) ) -> GenerateResponse: """ Generate and print address labels for the specified orders. Args: request: Dictionary containing: - order_ids: List of TCGPlayer order numbers - label_type: Type of label to generate (dk1201 or dk1241) Returns: Success status of the operation """ try: address_label_service = service_manager.get_service('address_label') address_labels = await address_label_service.get_or_create_address_labels(db, request.order_ids, request.label_type) if address_labels: # print address labels label_printer = service_manager.get_service('label_printer') for address_label in address_labels: success = await label_printer.print_file(address_label.path, label_size=request.label_type, label_type="address_label") if not success: return {"success": False, "message": "Address labels not found"} return {"success": True, "message": "Address labels generated and printed successfully"} return {"success": False, "message": "Address labels not found"} except Exception as e: raise HTTPException(status_code=500, detail=f"Failed to generate address labels: {str(e)}") @router.post("/generate-return-labels") async def generate_return_labels( request: GenerateReturnLabelsRequest, db: Session = Depends(get_db) ) -> GenerateResponse: """ Generate and print return labels for the specified number of labels. Args: request: Dictionary containing: - number_of_labels: Number of return labels to generate """ try: label_printer = service_manager.get_service('label_printer') success = await label_printer.print_file("app/data/assets/images/ccrcardsaddress.png", label_size="dk1201", label_type="return_label", copies=request.number_of_labels) return {"success": success, "message": "Return labels generated and printed successfully"} except Exception as e: raise HTTPException(status_code=500, detail=f"Failed to generate return labels: {str(e)}") @router.post("/print-pirate-ship-label") async def print_pirate_ship_label( file: UploadFile = File(...), db: Session = Depends(get_db) ) -> GenerateResponse: """ Print a PDF file uploaded via the API. Args: file: The PDF file to print Returns: Success status of the operation """ try: # Read the file content content = await file.read() # Store the file using FileService file_service = service_manager.get_service('file') stored_file = await file_service.save_file( db=db, file_data=content, filename=file.filename, subdir="pirate_ship_labels", file_type="pdf", content_type=file.content_type, metadata={"filename": file.filename} ) try: # Use the label printer service to print the file label_printer = service_manager.get_service('label_printer') success = await label_printer.print_file(stored_file, label_size="dk1241", label_type="pirate_ship_label") return {"success": success, "message": "Pirate Ship label printed successfully"} except Exception as e: # If printing fails, we'll keep the file in storage for potential retry logger.error(f"Failed to print file: {str(e)}") raise e except Exception as e: raise HTTPException(status_code=500, detail=f"Failed to print Pirate Ship label: {str(e)}")