149 lines
7.1 KiB
Python
149 lines
7.1 KiB
Python
from sqlalchemy.orm import Session
|
|
import logging
|
|
from fastapi import BackgroundTasks
|
|
from db.models import TCGPlayerGroups, SetCodeGroupIdMapping, ManaboxExportData, TCGPlayerProduct, ManaboxTCGPlayerMapping, UnmatchedManaboxData, TCGPlayerInventory
|
|
from db.utils import db_transaction
|
|
import uuid
|
|
from services.tcgplayer import TCGPlayerService
|
|
from sqlalchemy.sql import exists
|
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
class DataService:
|
|
def __init__(self, db: Session, tcgplayer_service: TCGPlayerService):
|
|
self.db = db
|
|
self.tcgplayer_service = tcgplayer_service
|
|
|
|
def _normalize_rarity(self, rarity: str) -> str:
|
|
if rarity.lower() == "rare":
|
|
return "R"
|
|
elif rarity.lower() == "mythic":
|
|
return "M"
|
|
elif rarity.lower() == "uncommon":
|
|
return "U"
|
|
elif rarity.lower() == "common":
|
|
return "C"
|
|
elif rarity.lower() in ["R", "M", "U", "C"]:
|
|
return rarity.upper()
|
|
else:
|
|
raise ValueError(f"Invalid rarity: {rarity}")
|
|
|
|
def _normalize_condition(self, condition: str, foil: str) -> str:
|
|
if condition.lower() == "near_mint":
|
|
condition1 = "Near Mint"
|
|
else:
|
|
raise ValueError(f"Invalid condition: {condition}")
|
|
if foil.lower() == "foil":
|
|
condition2 = " Foil"
|
|
elif foil.lower() == "normal":
|
|
condition2 = ""
|
|
else:
|
|
raise ValueError(f"Invalid foil: {foil}")
|
|
return condition1 + condition2
|
|
|
|
def _normalize_number(self, number: str) -> str:
|
|
return str(number.split(".")[0])
|
|
|
|
def _convert_set_code_to_group_id(self, set_code: str) -> str:
|
|
group = self.db.query(TCGPlayerGroups).filter(TCGPlayerGroups.abbreviation == set_code).first()
|
|
return group.group_id
|
|
|
|
def _add_set_group_mapping(self, set_code: str, group_id: str) -> None:
|
|
with db_transaction(self.db):
|
|
self.db.add(SetCodeGroupIdMapping(id=str(uuid.uuid4()), set_code=set_code, group_id=group_id))
|
|
|
|
def _get_set_codes(self, **filters) -> list:
|
|
query = self.db.query(ManaboxExportData.set_code).distinct()
|
|
for field, value in filters.items():
|
|
if value is not None:
|
|
query = query.filter(getattr(ManaboxExportData, field) == value)
|
|
return [code[0] for code in query.all()]
|
|
|
|
async def bg_set_manabox_tcg_relationship(self, box_id: str = None, upload_id: str = None) -> None:
|
|
if not bool(box_id) ^ bool(upload_id):
|
|
raise ValueError("Must provide exactly one of box_id or upload_id")
|
|
|
|
filters = {"box_id": box_id} if box_id else {"upload_id": upload_id}
|
|
set_codes = self._get_set_codes(**filters)
|
|
|
|
for set_code in set_codes:
|
|
try:
|
|
group_id = self._convert_set_code_to_group_id(set_code)
|
|
except AttributeError:
|
|
logger.warning(f"No group found for set code {set_code}")
|
|
continue
|
|
self._add_set_group_mapping(set_code, group_id)
|
|
# update pricing for groups
|
|
if self.db.query(TCGPlayerProduct).filter(TCGPlayerProduct.group_id == group_id).count() == 0:
|
|
self.tcgplayer_service.update_pricing(set_name_ids={"set_name_ids":[group_id]})
|
|
|
|
# match manabox data to tcgplayer pricing data
|
|
# match on manabox - set_code (through group_id), collector_number, foil, rarity, condition
|
|
# match on tcgplayer - group_id, number, rarity, condition (condition + foil)
|
|
# use normalizing functions
|
|
matched_records = self.db.query(ManaboxExportData).filter(ManaboxExportData.set_code.in_(set_codes)).all()
|
|
for record in matched_records:
|
|
rarity = self._normalize_rarity(record.rarity)
|
|
condition = self._normalize_condition(record.condition, record.foil)
|
|
number = self._normalize_number(record.collector_number)
|
|
group_id = self._convert_set_code_to_group_id(record.set_code)
|
|
tcg_record = self.db.query(TCGPlayerProduct).filter(
|
|
TCGPlayerProduct.group_id == group_id,
|
|
TCGPlayerProduct.number == number,
|
|
TCGPlayerProduct.rarity == rarity,
|
|
TCGPlayerProduct.condition == condition
|
|
).all()
|
|
if len(tcg_record) == 0:
|
|
logger.warning(f"No match found for {record.name}")
|
|
if self.db.query(UnmatchedManaboxData).filter(UnmatchedManaboxData.manabox_id == record.id).count() == 0:
|
|
with db_transaction(self.db):
|
|
self.db.add(UnmatchedManaboxData(id=str(uuid.uuid4()), manabox_id=record.id, reason="No match found"))
|
|
elif len(tcg_record) > 1:
|
|
logger.warning(f"Multiple matches found for {record.name}")
|
|
if self.db.query(UnmatchedManaboxData).filter(UnmatchedManaboxData.manabox_id == record.id).count() == 0:
|
|
with db_transaction(self.db):
|
|
self.db.add(UnmatchedManaboxData(id=str(uuid.uuid4()), manabox_id=record.id, reason="Multiple matches found"))
|
|
else:
|
|
with db_transaction(self.db):
|
|
self.db.add(ManaboxTCGPlayerMapping(id=str(uuid.uuid4()), manabox_id=record.id, tcgplayer_id=tcg_record[0].id))
|
|
|
|
async def bg_set_tcg_inventory_product_relationship(self, export_id: str) -> None:
|
|
inventory_without_product = (
|
|
self.db.query(TCGPlayerInventory.tcgplayer_id, TCGPlayerInventory.set_name)
|
|
.filter(TCGPlayerInventory.total_quantity > 0)
|
|
.filter(TCGPlayerInventory.product_line == "Magic")
|
|
.filter(TCGPlayerInventory.export_id == export_id)
|
|
.filter(TCGPlayerInventory.tcgplayer_product_id.is_(None))
|
|
.filter(~exists().where(
|
|
TCGPlayerProduct.id == TCGPlayerInventory.tcgplayer_product_id
|
|
))
|
|
.all()
|
|
)
|
|
|
|
set_names = list(set(inv.set_name for inv in inventory_without_product
|
|
if inv.set_name is not None and isinstance(inv.set_name, str)))
|
|
|
|
group_ids = self.db.query(TCGPlayerGroups.group_id).filter(
|
|
TCGPlayerGroups.name.in_(set_names)
|
|
).all()
|
|
|
|
group_ids = [str(group_id[0]) for group_id in group_ids]
|
|
|
|
self.tcgplayer_service.update_pricing(set_name_ids={"set_name_ids": group_ids})
|
|
|
|
for inventory in inventory_without_product:
|
|
product = self.db.query(TCGPlayerProduct).filter(
|
|
TCGPlayerProduct.tcgplayer_id == inventory.tcgplayer_id
|
|
).first()
|
|
|
|
if product:
|
|
with db_transaction(self.db):
|
|
inventory_record = self.db.query(TCGPlayerInventory).filter(
|
|
TCGPlayerInventory.tcgplayer_id == inventory.tcgplayer_id,
|
|
TCGPlayerInventory.export_id == export_id
|
|
).first()
|
|
|
|
if inventory_record:
|
|
inventory_record.tcgplayer_product_id = product.id
|
|
self.db.add(inventory_record) |