from app.services.base_service import BaseService from sqlalchemy.orm import Session from app.db.database import transaction from app.schemas.file import FileInDB from app.models.mtgjson_card import MTGJSONCard from app.models.mtgjson_sku import MTGJSONSKU from app.models.tcgplayer_inventory import TCGPlayerInventory from app.models.tcgplayer_product import TCGPlayerProduct from app.models.tcgplayer_category import TCGPlayerCategory from app.models.tcgplayer_group import TCGPlayerGroup from typing import Dict, Any import csv import logging from datetime import datetime logger = logging.getLogger(__name__) class ManaboxService(BaseService): def __init__(self): super().__init__(None) async def process_manabox_csv(self, db: Session, bytes: bytes) -> bool: # save file file = await self.file_service.save_file( db=db, file_data=bytes, filename=f"manabox_{datetime.now().strftime('%Y%m%d%H%M%S')}.csv", subdir="manabox", file_type="manabox", content_type="text/csv" ) # Read the CSV file with open(file.path, 'r') as file: reader = csv.DictReader(file) # validate headers if reader.fieldnames != ['Name', 'Set code', 'Set name', 'Collector number', 'Foil', 'Rarity', 'Quantity', 'ManaBox ID', 'Scryfall ID', 'Purchase price', 'Misprint', 'Altered', 'Condition', 'Language', 'Purchase price currency']: logger.error("Invalid headers") return False # skip header row next(reader) for row in reader: # match scryfall id to mtgjson scryfall id, make sure only one distinct tcgplayer id mtg_json = db.query(MTGJSONCard).filter(MTGJSONCard.scryfall_id == row['Scryfall ID']).all() # count distinct tcgplayer ids cd_tcgplayer_ids = db.query(MTGJSONCard.tcgplayer_product_id).filter(MTGJSONCard.scryfall_id == row['Scryfall ID']).distinct().count() if cd_tcgplayer_ids != 1: logger.error(f"Error: {cd_tcgplayer_ids} TCGplayer IDs found for {row['Scryfall ID']}") return False else: mtg_json = mtg_json[0] # get tcgplayer sku id from mtgjson skus language = 'ENGLISH' if row['Language'] == 'en' else 'JAPANESE' if row['Language'] == 'ja' else None if row['Foil'].lower() == 'etched': printing = 'FOIL' tcgplayer_sku = db.query(MTGJSONSKU.sku_id).filter(MTGJSONSKU.product_id == mtg_json.tcgplayer_etched_product_id).filter(MTGJSONSKU.condition == row['Condition'].replace('_', ' ').upper()).filter(MTGJSONSKU.printing == printing).filter(MTGJSONSKU.language == language).all().distinct() else: printing = 'FOIL' if row['Foil'].lower() == 'foil' else 'NON FOIL' tcgplayer_sku = db.query(MTGJSONSKU.sku_id).filter(MTGJSONSKU.product_id == mtg_json.tcgplayer_product_id).filter(MTGJSONSKU.condition == row['Condition'].replace('_', ' ').upper()).filter(MTGJSONSKU.printing == printing).filter(MTGJSONSKU.language == language).all().distinct() # count distinct tcgplayer skus if len(tcgplayer_sku) == 0: logger.error(f"Error: No TCGplayer SKU found for {mtg_json.name} {row['Condition']}") logger.debug(row) logger.debug(language) logger.debug(row['Condition'].replace('_', ' ').upper()) logger.debug(mtg_json.tcgplayer_product_id) logger.debug(printing) return False elif len(tcgplayer_sku) > 1: logger.error(f"Error: {len(tcgplayer_sku)} TCGplayer SKUs found for {mtg_json.name} {row['Condition']}") return False else: tcgplayer_sku = tcgplayer_sku[0] # look up tcgplayer product data for sku tcgplayer_product = db.query(TCGPlayerProduct).filter(TCGPlayerProduct.product_id == tcgplayer_sku.product_id).first() # temp just dump into tcgplayer inventory condition = f'{tcgplayer_sku.condition.title()} Foil' if 'Foil' in tcgplayer_product.sub_type_name else f'{tcgplayer_sku.condition.title()}' # join tcgplaeyer product on tcgplayer category on category_id and get name product_line = db.query(TCGPlayerCategory).filter(TCGPlayerCategory.category_id == tcgplayer_product.category_id).first().name # join tcgplaeyer product on tcgplayer group on group_id and get name set_name = db.query(TCGPlayerGroup).filter(TCGPlayerGroup.group_id == tcgplayer_product.group_id).first().name with transaction(db): tcgplayer_inventory = TCGPlayerInventory( tcgplayer_id=tcgplayer_sku.sku_id, product_line=product_line, set_name=set_name, product_name=tcgplayer_product.name, title=None, number=tcgplayer_product.ext_number, rarity=tcgplayer_product.ext_rarity, condition=condition, tcg_market_price=tcgplayer_product.market_price, tcg_direct_low=tcgplayer_product.direct_low_price, tcg_low_price_with_shipping=tcgplayer_product.low_price, tcg_low_price=tcgplayer_product.low_price, total_quantity=row['Quantity'], add_to_quantity=row['Quantity'] ) db.add(tcgplayer_inventory) return True # Name,Set code,Set name,Collector number,Foil,Rarity,Quantity,ManaBox ID,Scryfall ID,Purchase price,Misprint,Altered,Condition,Language,Purchase price currency