PRICING
This commit is contained in:
@ -12,6 +12,7 @@ from app.schemas.transaction import PurchaseTransactionCreate, PurchaseItem
|
||||
from app.contexts.inventory_item import InventoryItemContextFactory
|
||||
from app.models.tcgplayer_products import MTGJSONSKU, MTGJSONCard
|
||||
from app.models.tcgplayer_products import TCGPlayerPriceHistory
|
||||
from app.models.critical_error_log import CriticalErrorLog
|
||||
import csv
|
||||
import io
|
||||
import logging
|
||||
@ -349,7 +350,7 @@ class DataInitializationService(BaseService):
|
||||
for price_data in archived_prices_data.get("results", []):
|
||||
try:
|
||||
# Get the subtype name from the price data
|
||||
sub_type_name = price_data.get("subTypeName", "other")
|
||||
sub_type_name = price_data.get("subTypeName", "None")
|
||||
|
||||
# First try to find product with the requested subtype
|
||||
product = db.query(TCGPlayerProduct).filter(
|
||||
@ -521,120 +522,178 @@ class DataInitializationService(BaseService):
|
||||
}
|
||||
|
||||
async def sync_mtgjson_identifiers(self, db: Session, identifiers_data: List[dict]) -> int:
|
||||
"""Sync MTGJSON identifiers data to the database"""
|
||||
|
||||
|
||||
count = 0
|
||||
with db_transaction(db):
|
||||
# Load all existing UUIDs once
|
||||
existing_cards = {
|
||||
card.mtgjson_uuid: card
|
||||
for card in db.query(MTGJSONCard).all()
|
||||
}
|
||||
|
||||
new_cards = []
|
||||
|
||||
for card_data in identifiers_data:
|
||||
if not isinstance(card_data, dict):
|
||||
logger.debug(f"Skipping non-dict item: {card_data}")
|
||||
continue
|
||||
|
||||
existing_card = db.query(MTGJSONCard).filter(MTGJSONCard.mtgjson_uuid == card_data.get("uuid")).first()
|
||||
if existing_card:
|
||||
# Update existing card
|
||||
for key, value in {
|
||||
|
||||
uuid = card_data.get("uuid")
|
||||
identifiers = card_data.get("identifiers", {})
|
||||
|
||||
if uuid in existing_cards:
|
||||
card = existing_cards[uuid]
|
||||
updates = {
|
||||
"name": card_data.get("name"),
|
||||
"set_code": card_data.get("setCode"),
|
||||
"abu_id": card_data.get("identifiers", {}).get("abuId"),
|
||||
"card_kingdom_etched_id": card_data.get("identifiers", {}).get("cardKingdomEtchedId"),
|
||||
"card_kingdom_foil_id": card_data.get("identifiers", {}).get("cardKingdomFoilId"),
|
||||
"card_kingdom_id": card_data.get("identifiers", {}).get("cardKingdomId"),
|
||||
"cardsphere_id": card_data.get("identifiers", {}).get("cardsphereId"),
|
||||
"cardsphere_foil_id": card_data.get("identifiers", {}).get("cardsphereFoilId"),
|
||||
"cardtrader_id": card_data.get("identifiers", {}).get("cardtraderId"),
|
||||
"csi_id": card_data.get("identifiers", {}).get("csiId"),
|
||||
"mcm_id": card_data.get("identifiers", {}).get("mcmId"),
|
||||
"mcm_meta_id": card_data.get("identifiers", {}).get("mcmMetaId"),
|
||||
"miniaturemarket_id": card_data.get("identifiers", {}).get("miniaturemarketId"),
|
||||
"mtg_arena_id": card_data.get("identifiers", {}).get("mtgArenaId"),
|
||||
"mtgjson_foil_version_id": card_data.get("identifiers", {}).get("mtgjsonFoilVersionId"),
|
||||
"mtgjson_non_foil_version_id": card_data.get("identifiers", {}).get("mtgjsonNonFoilVersionId"),
|
||||
"mtgjson_v4_id": card_data.get("identifiers", {}).get("mtgjsonV4Id"),
|
||||
"mtgo_foil_id": card_data.get("identifiers", {}).get("mtgoFoilId"),
|
||||
"mtgo_id": card_data.get("identifiers", {}).get("mtgoId"),
|
||||
"multiverse_id": card_data.get("identifiers", {}).get("multiverseId"),
|
||||
"scg_id": card_data.get("identifiers", {}).get("scgId"),
|
||||
"scryfall_id": card_data.get("identifiers", {}).get("scryfallId"),
|
||||
"scryfall_card_back_id": card_data.get("identifiers", {}).get("scryfallCardBackId"),
|
||||
"scryfall_oracle_id": card_data.get("identifiers", {}).get("scryfallOracleId"),
|
||||
"scryfall_illustration_id": card_data.get("identifiers", {}).get("scryfallIllustrationId"),
|
||||
"tcgplayer_product_id": card_data.get("identifiers", {}).get("tcgplayerProductId"),
|
||||
"tcgplayer_etched_product_id": card_data.get("identifiers", {}).get("tcgplayerEtchedProductId"),
|
||||
"tnt_id": card_data.get("identifiers", {}).get("tntId")
|
||||
}.items():
|
||||
setattr(existing_card, key, value)
|
||||
"abu_id": identifiers.get("abuId"),
|
||||
"card_kingdom_etched_id": identifiers.get("cardKingdomEtchedId"),
|
||||
"card_kingdom_foil_id": identifiers.get("cardKingdomFoilId"),
|
||||
"card_kingdom_id": identifiers.get("cardKingdomId"),
|
||||
"cardsphere_id": identifiers.get("cardsphereId"),
|
||||
"cardsphere_foil_id": identifiers.get("cardsphereFoilId"),
|
||||
"cardtrader_id": identifiers.get("cardtraderId"),
|
||||
"csi_id": identifiers.get("csiId"),
|
||||
"mcm_id": identifiers.get("mcmId"),
|
||||
"mcm_meta_id": identifiers.get("mcmMetaId"),
|
||||
"miniaturemarket_id": identifiers.get("miniaturemarketId"),
|
||||
"mtg_arena_id": identifiers.get("mtgArenaId"),
|
||||
"mtgjson_foil_version_id": identifiers.get("mtgjsonFoilVersionId"),
|
||||
"mtgjson_non_foil_version_id": identifiers.get("mtgjsonNonFoilVersionId"),
|
||||
"mtgjson_v4_id": identifiers.get("mtgjsonV4Id"),
|
||||
"mtgo_foil_id": identifiers.get("mtgoFoilId"),
|
||||
"mtgo_id": identifiers.get("mtgoId"),
|
||||
"multiverse_id": identifiers.get("multiverseId"),
|
||||
"scg_id": identifiers.get("scgId"),
|
||||
"scryfall_id": identifiers.get("scryfallId"),
|
||||
"scryfall_card_back_id": identifiers.get("scryfallCardBackId"),
|
||||
"scryfall_oracle_id": identifiers.get("scryfallOracleId"),
|
||||
"scryfall_illustration_id": identifiers.get("scryfallIllustrationId"),
|
||||
"tcgplayer_product_id": identifiers.get("tcgplayerProductId"),
|
||||
"tcgplayer_etched_product_id": identifiers.get("tcgplayerEtchedProductId"),
|
||||
"tnt_id": identifiers.get("tntId")
|
||||
}
|
||||
|
||||
for k, v in updates.items():
|
||||
if getattr(card, k) != v:
|
||||
setattr(card, k, v)
|
||||
|
||||
else:
|
||||
new_card = MTGJSONCard(
|
||||
mtgjson_uuid=card_data.get("uuid"),
|
||||
new_cards.append(MTGJSONCard(
|
||||
mtgjson_uuid=uuid,
|
||||
name=card_data.get("name"),
|
||||
set_code=card_data.get("setCode"),
|
||||
abu_id=card_data.get("identifiers", {}).get("abuId"),
|
||||
card_kingdom_etched_id=card_data.get("identifiers", {}).get("cardKingdomEtchedId"),
|
||||
card_kingdom_foil_id=card_data.get("identifiers", {}).get("cardKingdomFoilId"),
|
||||
card_kingdom_id=card_data.get("identifiers", {}).get("cardKingdomId"),
|
||||
cardsphere_id=card_data.get("identifiers", {}).get("cardsphereId"),
|
||||
cardsphere_foil_id=card_data.get("identifiers", {}).get("cardsphereFoilId"),
|
||||
cardtrader_id=card_data.get("identifiers", {}).get("cardtraderId"),
|
||||
csi_id=card_data.get("identifiers", {}).get("csiId"),
|
||||
mcm_id=card_data.get("identifiers", {}).get("mcmId"),
|
||||
mcm_meta_id=card_data.get("identifiers", {}).get("mcmMetaId"),
|
||||
miniaturemarket_id=card_data.get("identifiers", {}).get("miniaturemarketId"),
|
||||
mtg_arena_id=card_data.get("identifiers", {}).get("mtgArenaId"),
|
||||
mtgjson_foil_version_id=card_data.get("identifiers", {}).get("mtgjsonFoilVersionId"),
|
||||
mtgjson_non_foil_version_id=card_data.get("identifiers", {}).get("mtgjsonNonFoilVersionId"),
|
||||
mtgjson_v4_id=card_data.get("identifiers", {}).get("mtgjsonV4Id"),
|
||||
mtgo_foil_id=card_data.get("identifiers", {}).get("mtgoFoilId"),
|
||||
mtgo_id=card_data.get("identifiers", {}).get("mtgoId"),
|
||||
multiverse_id=card_data.get("identifiers", {}).get("multiverseId"),
|
||||
scg_id=card_data.get("identifiers", {}).get("scgId"),
|
||||
scryfall_id=card_data.get("identifiers", {}).get("scryfallId"),
|
||||
scryfall_card_back_id=card_data.get("identifiers", {}).get("scryfallCardBackId"),
|
||||
scryfall_oracle_id=card_data.get("identifiers", {}).get("scryfallOracleId"),
|
||||
scryfall_illustration_id=card_data.get("identifiers", {}).get("scryfallIllustrationId"),
|
||||
tcgplayer_product_id=card_data.get("identifiers", {}).get("tcgplayerProductId"),
|
||||
tcgplayer_etched_product_id=card_data.get("identifiers", {}).get("tcgplayerEtchedProductId"),
|
||||
tnt_id=card_data.get("identifiers", {}).get("tntId")
|
||||
)
|
||||
db.add(new_card)
|
||||
count += 1
|
||||
abu_id=identifiers.get("abuId"),
|
||||
card_kingdom_etched_id=identifiers.get("cardKingdomEtchedId"),
|
||||
card_kingdom_foil_id=identifiers.get("cardKingdomFoilId"),
|
||||
card_kingdom_id=identifiers.get("cardKingdomId"),
|
||||
cardsphere_id=identifiers.get("cardsphereId"),
|
||||
cardsphere_foil_id=identifiers.get("cardsphereFoilId"),
|
||||
cardtrader_id=identifiers.get("cardtraderId"),
|
||||
csi_id=identifiers.get("csiId"),
|
||||
mcm_id=identifiers.get("mcmId"),
|
||||
mcm_meta_id=identifiers.get("mcmMetaId"),
|
||||
miniaturemarket_id=identifiers.get("miniaturemarketId"),
|
||||
mtg_arena_id=identifiers.get("mtgArenaId"),
|
||||
mtgjson_foil_version_id=identifiers.get("mtgjsonFoilVersionId"),
|
||||
mtgjson_non_foil_version_id=identifiers.get("mtgjsonNonFoilVersionId"),
|
||||
mtgjson_v4_id=identifiers.get("mtgjsonV4Id"),
|
||||
mtgo_foil_id=identifiers.get("mtgoFoilId"),
|
||||
mtgo_id=identifiers.get("mtgoId"),
|
||||
multiverse_id=identifiers.get("multiverseId"),
|
||||
scg_id=identifiers.get("scgId"),
|
||||
scryfall_id=identifiers.get("scryfallId"),
|
||||
scryfall_card_back_id=identifiers.get("scryfallCardBackId"),
|
||||
scryfall_oracle_id=identifiers.get("scryfallOracleId"),
|
||||
scryfall_illustration_id=identifiers.get("scryfallIllustrationId"),
|
||||
tcgplayer_product_id=identifiers.get("tcgplayerProductId"),
|
||||
tcgplayer_etched_product_id=identifiers.get("tcgplayerEtchedProductId"),
|
||||
tnt_id=identifiers.get("tntId")
|
||||
))
|
||||
|
||||
return count
|
||||
count += 1
|
||||
|
||||
if new_cards:
|
||||
db.bulk_save_objects(new_cards)
|
||||
|
||||
return count
|
||||
|
||||
async def sync_mtgjson_skus(self, db: Session, skus_data: dict) -> int:
|
||||
"""Sync MTGJSON SKUs data to the database"""
|
||||
|
||||
count = 0
|
||||
with db_transaction(db):
|
||||
for mtgjson_uuid, product_data in skus_data['data'].items():
|
||||
for sku_data in product_data:
|
||||
existing_record = db.query(MTGJSONSKU).filter(MTGJSONSKU.mtgjson_uuid == mtgjson_uuid).filter(MTGJSONSKU.tcgplayer_sku_id == sku_data.get("skuId")).first()
|
||||
if existing_record:
|
||||
# Update existing SKU
|
||||
for key, value in {
|
||||
"tcgplayer_product_id": sku_data.get("productId"),
|
||||
"condition": sku_data.get("condition"),
|
||||
"finish": sku_data.get("finish"),
|
||||
"language": sku_data.get("language"),
|
||||
"printing": sku_data.get("printing"),
|
||||
"normalized_printing": sku_data.get("printing").lower().replace(" ", "_") if sku_data.get("printing") else None
|
||||
}.items():
|
||||
setattr(existing_record, key, value)
|
||||
else:
|
||||
new_sku = MTGJSONSKU(
|
||||
mtgjson_uuid=mtgjson_uuid,
|
||||
tcgplayer_sku_id=sku_data.get("skuId"),
|
||||
tcgplayer_product_id=sku_data.get("productId"),
|
||||
condition=sku_data.get("condition"),
|
||||
finish=sku_data.get("finish"),
|
||||
language=sku_data.get("language"),
|
||||
printing=sku_data.get("printing"),
|
||||
normalized_printing=sku_data.get("printing").lower().replace(" ", "_") if sku_data.get("printing") else None
|
||||
)
|
||||
db.add(new_sku)
|
||||
count += 1
|
||||
sku_details_by_key = {}
|
||||
|
||||
for mtgjson_uuid, product_data in skus_data["data"].items():
|
||||
for sku_data in product_data:
|
||||
sku_id = sku_data.get("skuId")
|
||||
if sku_id is None or sku_id in sku_details_by_key:
|
||||
continue # Skip if missing or already added
|
||||
|
||||
sku_details_by_key[sku_id] = {
|
||||
"mtgjson_uuid": mtgjson_uuid,
|
||||
"tcgplayer_sku_id": sku_id,
|
||||
"tcgplayer_product_id": sku_data.get("productId"),
|
||||
"printing": sku_data.get("printing"),
|
||||
"normalized_printing": sku_data.get("printing", "").lower().replace(" ", "_").replace("non_foil", "normal") if sku_data.get("printing") else None,
|
||||
"condition": sku_data.get("condition"),
|
||||
"finish": sku_data.get("finish"),
|
||||
"language": sku_data.get("language"),
|
||||
}
|
||||
|
||||
with db_transaction(db):
|
||||
db.flush()
|
||||
|
||||
valid_uuids = {uuid for (uuid,) in db.query(MTGJSONCard.mtgjson_uuid).all()}
|
||||
valid_product_keys = {
|
||||
(product.tcgplayer_product_id, product.normalized_sub_type_name)
|
||||
for product in db.query(TCGPlayerProduct.tcgplayer_product_id, TCGPlayerProduct.normalized_sub_type_name)
|
||||
}
|
||||
|
||||
existing_sku_ids = {
|
||||
sku.tcgplayer_sku_id
|
||||
for sku in db.query(MTGJSONSKU.tcgplayer_sku_id).all()
|
||||
}
|
||||
|
||||
existing = {
|
||||
(sku.mtgjson_uuid, sku.tcgplayer_sku_id): sku
|
||||
for sku in db.query(MTGJSONSKU).all()
|
||||
}
|
||||
|
||||
new_skus = []
|
||||
|
||||
for data in sku_details_by_key.values():
|
||||
sku_id = data["tcgplayer_sku_id"]
|
||||
|
||||
if sku_id in existing_sku_ids:
|
||||
continue
|
||||
|
||||
mtgjson_uuid = data["mtgjson_uuid"]
|
||||
product_id = data["tcgplayer_product_id"]
|
||||
normalized_printing = data["normalized_printing"]
|
||||
|
||||
if mtgjson_uuid not in valid_uuids:
|
||||
continue
|
||||
|
||||
if (product_id, normalized_printing) not in valid_product_keys:
|
||||
continue
|
||||
|
||||
key = (mtgjson_uuid, sku_id)
|
||||
|
||||
if key in existing:
|
||||
record = existing[key]
|
||||
for field, value in data.items():
|
||||
if field not in ("mtgjson_uuid", "tcgplayer_sku_id") and getattr(record, field) != value:
|
||||
setattr(record, field, value)
|
||||
else:
|
||||
new_skus.append(MTGJSONSKU(**data))
|
||||
count += 1
|
||||
|
||||
if new_skus:
|
||||
db.bulk_save_objects(new_skus)
|
||||
|
||||
return count
|
||||
|
||||
|
||||
|
||||
return count
|
||||
|
||||
async def initialize_data(
|
||||
self,
|
||||
@ -693,19 +752,17 @@ class DataInitializationService(BaseService):
|
||||
with db_transaction(db):
|
||||
logger.info("Initializing inventory data...")
|
||||
# set expected value
|
||||
product_id1 = db.query(TCGPlayerProduct).filter(TCGPlayerProduct.tcgplayer_sku == "562118").first().id
|
||||
expected_value_box = SealedExpectedValue(
|
||||
product_id=product_id1,
|
||||
expected_value=120.69
|
||||
tcgplayer_product_id=619645,
|
||||
expected_value=136.42
|
||||
)
|
||||
db.add(expected_value_box)
|
||||
db.flush()
|
||||
product_id2 = db.query(TCGPlayerProduct).filter(TCGPlayerProduct.tcgplayer_sku == "562119").first().id
|
||||
expected_value_case = SealedExpectedValue(
|
||||
product_id=product_id2,
|
||||
expected_value=820.69
|
||||
)
|
||||
db.add(expected_value_case)
|
||||
#db.flush()
|
||||
#expected_value_case = SealedExpectedValue(
|
||||
# tcgplayer_product_id=562119,
|
||||
# expected_value=820.69
|
||||
#)
|
||||
#db.add(expected_value_case)
|
||||
db.flush()
|
||||
|
||||
inventory_service = self.get_service("inventory")
|
||||
@ -715,32 +772,38 @@ class DataInitializationService(BaseService):
|
||||
transaction = await inventory_service.create_purchase_transaction(db, PurchaseTransactionCreate(
|
||||
vendor_id=vendor.id,
|
||||
transaction_date=datetime.now(),
|
||||
items=[PurchaseItem(product_id=product_id1, unit_price=100.69, quantity=1, is_case=False),
|
||||
PurchaseItem(product_id=product_id2, unit_price=800.01, quantity=2, is_case=True, num_boxes=6)],
|
||||
transaction_notes="Test Transaction: 1 case and 2 boxes of foundations"
|
||||
items=[PurchaseItem(product_id=619645, unit_price=100, quantity=1, is_case=False)],
|
||||
transaction_notes="tdm real box test"
|
||||
#PurchaseItem(product_id=562119, unit_price=800.01, quantity=2, is_case=True, num_boxes=6)],
|
||||
#transaction_notes="Test Transaction: 1 case and 2 boxes of foundations"
|
||||
))
|
||||
logger.info(f"Transaction created: {transaction}")
|
||||
case_num = 0
|
||||
for item in transaction.transaction_items:
|
||||
item = InventoryItemContextFactory(db).get_context(item.physical_item.inventory_item)
|
||||
logger.info(f"Item: {item}")
|
||||
if item.physical_item.item_type == "sealed_box":
|
||||
if item.inventory_item.physical_item.item_type == "box":
|
||||
manabox_service = self.get_service("manabox")
|
||||
file_path = 'app/data/test_data/manabox_test_file.csv'
|
||||
#file_path = 'app/data/test_data/manabox_test_file.csv'
|
||||
file_path = 'app/data/test_data/tdmtest.csv'
|
||||
file_bytes = open(file_path, 'rb').read()
|
||||
manabox_file = await manabox_service.process_manabox_csv(db, file_bytes, {"source": "test", "description": "test"}, wait=True)
|
||||
# Ensure manabox_file is a list before passing it
|
||||
if not isinstance(manabox_file, list):
|
||||
manabox_file = [manabox_file]
|
||||
sealed_box_service = self.get_service("sealed_box")
|
||||
sealed_box = sealed_box_service.get(db, item.physical_item.inventory_item.id)
|
||||
success = await inventory_service.process_manabox_import_staging(db, manabox_file, sealed_box)
|
||||
logger.info(f"sealed box opening success: {success}")
|
||||
elif item.physical_item.item_type == "sealed_case":
|
||||
box_service = self.get_service("box")
|
||||
open_event = await box_service.open_box(db, item.inventory_item.physical_item, manabox_file)
|
||||
# get all cards from box
|
||||
cards = open_event.resulting_items if open_event.resulting_items else []
|
||||
marketplace_listing_service = self.get_service("marketplace_listing")
|
||||
for card in cards:
|
||||
logger.info(f"card: {card}")
|
||||
# create marketplace listing
|
||||
await marketplace_listing_service.create_marketplace_listing(db, card.inventory_item, marketplace)
|
||||
elif item.inventory_item.physical_item.item_type == "case":
|
||||
if case_num == 0:
|
||||
logger.info(f"sealed case {case_num} opening...")
|
||||
sealed_case_service = self.get_service("sealed_case")
|
||||
success = await sealed_case_service.open_sealed_case(db, item.physical_item)
|
||||
case_service = self.get_service("case")
|
||||
success = await case_service.open_case(db, item.inventory_item.physical_item, 562119)
|
||||
logger.info(f"sealed case {case_num} opening success: {success}")
|
||||
case_num += 1
|
||||
|
||||
|
Reference in New Issue
Block a user