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

151 lines
6.2 KiB
Python

from sqlalchemy.orm import Session
from db.utils import db_transaction
from db.models import Product, File, CardManabox, Card, StagedFileProduct, CardTCGPlayer
from io import StringIO
import pandas as pd
from services.file import FileService
from services.tcgplayer import TCGPlayerService
from uuid import uuid4 as uuid
import logging
logger = logging.getLogger(__name__)
class ManaboxRow:
def __init__(self, row: pd.Series):
self.name = row['name']
self.set_code = row['set_code']
self.set_name = row['set_name']
self.collector_number = row['collector_number']
self.foil = row['foil']
self.rarity = row['rarity']
self.manabox_id = row['manabox_id']
self.scryfall_id = row['scryfall_id']
self.condition = row['condition']
self.language = row['language']
self.quantity = row['quantity']
class ProductService:
def __init__(self, db: Session, file_service: FileService, tcgplayer_service: TCGPlayerService):
self.db = db
self.file_service = file_service
self.tcgplayer_service = tcgplayer_service
def _format_manabox_df(self, df: pd.DataFrame) -> pd.DataFrame:
# format columns
df.columns = df.columns.str.lower()
df.columns = df.columns.str.replace(' ', '_')
return df
def _manabox_file_to_df(self, file: File) -> pd.DataFrame:
with open(file.filepath, 'rb') as f:
content = f.read()
content = content.decode('utf-8')
df = pd.read_csv(StringIO(content))
df = self._format_manabox_df(df)
return df
def create_staged_product(self, file: File, card_manabox:CardManabox, row: ManaboxRow) -> StagedFileProduct:
staged_product = StagedFileProduct(
id = str(uuid()),
file_id = file.id,
product_id = card_manabox.product_id,
quantity = row.quantity
)
with db_transaction(self.db):
self.db.add(staged_product)
return staged_product
def create_card_manabox(self, manabox_row: ManaboxRow) -> CardManabox:
card_manabox = CardManabox(
product_id = str(uuid()),
name = manabox_row.name,
set_code = manabox_row.set_code,
set_name = manabox_row.set_name,
collector_number = manabox_row.collector_number,
foil = manabox_row.foil,
rarity = manabox_row.rarity,
manabox_id = manabox_row.manabox_id,
scryfall_id = manabox_row.scryfall_id,
condition = manabox_row.condition,
language = manabox_row.language
)
return card_manabox
def create_product(self, card_manabox: CardManabox) -> Product:
product = Product(
id = card_manabox.product_id,
name = card_manabox.name,
set_code = card_manabox.set_code,
set_name = card_manabox.set_name,
type = 'card',
product_line = 'mtg'
)
return product
def get_tcgplayer_card(self, card_manabox: CardManabox) -> CardTCGPlayer:
# check if tcgplayer_id exists for product_id in CardTCGPlayer
tcgplayer_card = self.db.query(CardTCGPlayer).filter(CardTCGPlayer.product_id == card_manabox.product_id).first()
if tcgplayer_card:
return tcgplayer_card
# if not, get tcgplayer_id from tcgplayer_service
tcgplayer_card = self.tcgplayer_service.get_tcgplayer_card(card_manabox)
return tcgplayer_card
def create_card(self, card_manabox: CardManabox) -> Card:
tcgplayer_card = self.get_tcgplayer_card(card_manabox)
card = Card(
product_id = tcgplayer_card.product_id if tcgplayer_card else card_manabox.product_id,
number = card_manabox.collector_number,
foil = card_manabox.foil,
rarity = card_manabox.rarity,
condition = card_manabox.condition,
language = card_manabox.language,
scryfall_id = card_manabox.scryfall_id,
manabox_id = card_manabox.manabox_id,
tcgplayer_id = tcgplayer_card.tcgplayer_id if tcgplayer_card else None
)
return card
def card_manabox_lookup_create_if_not_exist(self, manabox_row: ManaboxRow) -> CardManabox:
# query based on all fields in manabox_row
card_manabox = self.db.query(CardManabox).filter(
CardManabox.name == manabox_row.name,
CardManabox.set_code == manabox_row.set_code,
CardManabox.set_name == manabox_row.set_name,
CardManabox.collector_number == manabox_row.collector_number,
CardManabox.foil == manabox_row.foil,
CardManabox.rarity == manabox_row.rarity,
CardManabox.manabox_id == manabox_row.manabox_id,
CardManabox.scryfall_id == manabox_row.scryfall_id,
CardManabox.condition == manabox_row.condition,
CardManabox.language == manabox_row.language
).first()
if not card_manabox:
# create new card_manabox, card, and product
with db_transaction(self.db):
card_manabox = self.create_card_manabox(manabox_row)
product = self.create_product(card_manabox)
card = self.create_card(card_manabox)
card_manabox.product_id = card.product_id
product.id = card.product_id
self.db.add(card_manabox)
self.db.add(product)
self.db.add(card)
return card_manabox
def bg_process_manabox_file(self, file_id: str):
try:
file = self.file_service.get_file(file_id)
df = self._manabox_file_to_df(file)
for index, row in df.iterrows():
manabox_row = ManaboxRow(row)
card_manabox = self.card_manabox_lookup_create_if_not_exist(manabox_row)
staged_product = self.create_staged_product(file, card_manabox, row)
# update file status
with db_transaction(self.db):
file.status = 'completed'
except Exception as e:
with db_transaction(self.db):
file.status = 'error'
raise e