bounty board feature buyers to see bounty boards seller profile page (like have theme chooser) Have the game and set name be filters. Add cards to vault manually update card inventory add to have the autocomplete for the card - store analytics, clicks, views, link to store (url/QR code) bulk item inventory creation -- Make the banner feature flag driven so I can have a beta site setup like the primary site don't use primary key values in urls - update to use uuid4 values site analytics. tianji is being sent item potent on the mtg and lorcana populate scripts Card item images for specific listings check that when you buy a card it is in the vault Buys should be able to search on store inventories More pie charts for the seller! post bounty board is slow to load seller reviews/ratings - show a historgram - need a way for someone to rate Report a seller feature for buyer to report Make sure the stlying is consistent based on the theme choosen smart minimum order quantity and shipping amounts (defined by the store itself) put virtual packs behind a feature flag like bounty board proxy service feature flag Terms of Service new description for TCGKof store SSN, ITIN, and EIN optomize for SEO
140 lines
5.9 KiB
Python
140 lines
5.9 KiB
Python
import random
|
|
import requests
|
|
from django.core.management.base import BaseCommand
|
|
from django.utils.text import slugify
|
|
from django.contrib.auth import get_user_model
|
|
from store.models import Game, Set, Card, CardListing
|
|
from faker import Faker
|
|
|
|
User = get_user_model()
|
|
fake = Faker()
|
|
|
|
class Command(BaseCommand):
|
|
help = 'Populate database with MTG data from Scryfall and fake data for other games'
|
|
|
|
def handle(self, *args, **options):
|
|
self.stdout.write('Starting database population...')
|
|
|
|
# Create Games
|
|
mtg, _ = Game.objects.get_or_create(name='Magic: The Gathering', slug='mtg')
|
|
pokemon, _ = Game.objects.get_or_create(name='Pokemon TCG', slug='pokemon')
|
|
lorcana, _ = Game.objects.get_or_create(name='Disney Lorcana', slug='lorcana')
|
|
|
|
# Populate MTG (Real Data)
|
|
self.populate_mtg(mtg)
|
|
|
|
# Populate Pokemon (Fake Data)
|
|
self.populate_fake_game(pokemon, 'Pokemon')
|
|
|
|
# Populate Lorcana (Fake Data)
|
|
self.populate_fake_game(lorcana, 'Lorcana')
|
|
|
|
# Create Superuser
|
|
if not User.objects.filter(username='admin').exists():
|
|
User.objects.create_superuser('admin', 'admin@example.com', 'admin')
|
|
self.stdout.write(self.style.SUCCESS('Created superuser: admin/admin'))
|
|
|
|
# Create Demo Users
|
|
self.create_demo_users()
|
|
|
|
self.stdout.write(self.style.SUCCESS('Database populated successfully!'))
|
|
|
|
def populate_mtg(self, game):
|
|
self.stdout.write('Fetching MTG data from Scryfall...')
|
|
# Get a few sets
|
|
sets_api = "https://api.scryfall.com/sets"
|
|
try:
|
|
resp = requests.get(sets_api).json()
|
|
# Pick top 3 recent expansion sets
|
|
target_sets = [s for s in resp['data'] if s['set_type'] == 'expansion'][:3]
|
|
|
|
for s_data in target_sets:
|
|
set_obj, created = Set.objects.get_or_create(
|
|
game=game,
|
|
name=s_data['name'],
|
|
code=s_data['code'],
|
|
defaults={'release_date': s_data.get('released_at')}
|
|
)
|
|
|
|
if created:
|
|
self.stdout.write(f"Created set: {set_obj.name}")
|
|
# Fetch cards for this set
|
|
cards_url = s_data['search_uri']
|
|
cards_resp = requests.get(cards_url).json()
|
|
|
|
for card_data in cards_resp.get('data', [])[:20]: # Limit to 20 cards per set to be fast
|
|
if 'image_uris' in card_data:
|
|
image = card_data['image_uris'].get('normal')
|
|
elif 'card_faces' in card_data and 'image_uris' in card_data['card_faces'][0]:
|
|
image = card_data['card_faces'][0]['image_uris'].get('normal')
|
|
else:
|
|
continue
|
|
|
|
card, _ = Card.objects.get_or_create(
|
|
set=set_obj,
|
|
name=card_data['name'],
|
|
collector_number=card_data['collector_number'],
|
|
defaults={
|
|
'rarity': card_data['rarity'].capitalize(),
|
|
'image_url': image,
|
|
'scryfall_id': card_data['id'],
|
|
'tcgplayer_id': card_data.get('tcgplayer_id'),
|
|
}
|
|
)
|
|
|
|
# Create Listings
|
|
self.create_listings_for_card(card)
|
|
|
|
except Exception as e:
|
|
self.stdout.write(self.style.ERROR(f"Failed to fetch MTG data: {e}"))
|
|
|
|
def populate_fake_game(self, game, prefix):
|
|
self.stdout.write(f'Generating data for {game.name}...')
|
|
for i in range(3): # 3 Sets
|
|
set_name = f"{prefix} Set {i+1}"
|
|
set_obj, _ = Set.objects.get_or_create(
|
|
game=game,
|
|
name=set_name,
|
|
code=f"{prefix[:3].upper()}{i+1}",
|
|
defaults={'release_date': fake.date_between(start_date='-2y', end_date='today')}
|
|
)
|
|
|
|
for j in range(15): # 15 Cards per set
|
|
card, _ = Card.objects.get_or_create(
|
|
set=set_obj,
|
|
name=f"{prefix} Monster {fake.word().capitalize()}",
|
|
defaults={
|
|
'rarity': random.choice(['Common', 'Uncommon', 'Rare', 'Ultra Rare']),
|
|
'image_url': f"https://placehold.co/400x600?text={prefix}+{j}",
|
|
'collector_number': str(j+1)
|
|
}
|
|
)
|
|
self.create_listings_for_card(card)
|
|
|
|
def create_listings_for_card(self, card):
|
|
# Create 1-5 listings per card with different conditions
|
|
for _ in range(random.randint(1, 4)):
|
|
condition = random.choice(['NM', 'LP', 'MP', 'HP'])
|
|
price = round(random.uniform(0.50, 100.00), 2)
|
|
CardListing.objects.create(
|
|
card=card,
|
|
condition=condition,
|
|
price=price,
|
|
quantity=random.randint(1, 20),
|
|
market_price=price, # Simplified
|
|
is_foil=random.choice([True, False])
|
|
)
|
|
|
|
def create_demo_users(self):
|
|
# Create a Pro user
|
|
if not User.objects.filter(username='prouser').exists():
|
|
u = User.objects.create_user('prouser', 'pro@example.com', 'password')
|
|
u.profile.is_pro = True
|
|
u.profile.save()
|
|
self.stdout.write("Created prouser/password")
|
|
|
|
# Create a Basic user
|
|
if not User.objects.filter(username='basicuser').exists():
|
|
User.objects.create_user('basicuser', 'basic@example.com', 'password')
|
|
self.stdout.write("Created basicuser/password")
|