inital checkin
This commit is contained in:
133
store/utils.py
Normal file
133
store/utils.py
Normal file
@@ -0,0 +1,133 @@
|
||||
import re
|
||||
from .models import Card, CardListing, Order, OrderItem, VaultItem
|
||||
from django.db.models import Min
|
||||
|
||||
def add_to_vault(user, card, quantity=1):
|
||||
"""
|
||||
Adds a card to the user's vault.
|
||||
"""
|
||||
vault_item, created = VaultItem.objects.get_or_create(user=user, card=card)
|
||||
if not created:
|
||||
vault_item.quantity += quantity
|
||||
else:
|
||||
vault_item.quantity = quantity
|
||||
vault_item.save()
|
||||
|
||||
def parse_deck_list(deck_text):
|
||||
"""
|
||||
Parses a deck list string and returns a list of dictionaries with 'quantity' and 'name'.
|
||||
Format expected: "4 Lightning Bolt" or "1x Lightning Bolt"
|
||||
"""
|
||||
lines = deck_text.strip().split('\n')
|
||||
parsed_cards = []
|
||||
|
||||
for line in lines:
|
||||
line = line.strip()
|
||||
if not line:
|
||||
continue
|
||||
|
||||
match = re.match(r'^(\d+)[xX]?\s+(.+)$', line)
|
||||
if match:
|
||||
quantity = int(match.group(1))
|
||||
name = match.group(2).strip()
|
||||
parsed_cards.append({'quantity': quantity, 'name': name})
|
||||
else:
|
||||
# Maybe just name? assume 1
|
||||
parsed_cards.append({'quantity': 1, 'name': line})
|
||||
|
||||
return parsed_cards
|
||||
|
||||
def find_best_listings_for_deck(parsed_cards):
|
||||
"""
|
||||
Finds cheapest listings for the parsed cards.
|
||||
Returns:
|
||||
- found_items: list of {listing, quantity_needed, total_cost, card_name}
|
||||
- missing_items: list of {name, quantity}
|
||||
"""
|
||||
found_items = []
|
||||
missing_items = []
|
||||
|
||||
for item in parsed_cards:
|
||||
name = item['name']
|
||||
qty_needed = item['quantity']
|
||||
|
||||
# Find card (simple name match)
|
||||
cards = Card.objects.filter(name__iexact=name)
|
||||
if not cards.exists():
|
||||
# Try contains
|
||||
cards = Card.objects.filter(name__icontains=name)
|
||||
|
||||
if not cards.exists():
|
||||
missing_items.append(item)
|
||||
continue
|
||||
|
||||
# Find cheapest listing with stock
|
||||
# We try to fill the quantity from multiple listings if needed
|
||||
listings = CardListing.objects.filter(
|
||||
card__in=cards,
|
||||
quantity__gt=0
|
||||
).order_by('price')
|
||||
|
||||
qty_remaining = qty_needed
|
||||
|
||||
for listing in listings:
|
||||
if qty_remaining <= 0:
|
||||
break
|
||||
|
||||
qty_to_take = min(listing.quantity, qty_remaining)
|
||||
|
||||
found_items.append({
|
||||
'listing': listing,
|
||||
'quantity': qty_to_take,
|
||||
'card_name': listing.card.name,
|
||||
'price': listing.price,
|
||||
'total': listing.price * qty_to_take
|
||||
})
|
||||
|
||||
qty_remaining -= qty_to_take
|
||||
|
||||
if qty_remaining > 0:
|
||||
missing_items.append({'name': name, 'quantity': qty_remaining})
|
||||
|
||||
return found_items, missing_items
|
||||
|
||||
def get_user_collection(user):
|
||||
"""
|
||||
Returns a dict {card_name: quantity} of cards in user's vault.
|
||||
"""
|
||||
owned = {}
|
||||
if not user.is_authenticated:
|
||||
return owned
|
||||
|
||||
vault_items = VaultItem.objects.filter(user=user).select_related('card')
|
||||
for item in vault_items:
|
||||
owned[item.card.name] = item.quantity
|
||||
|
||||
return owned
|
||||
|
||||
def filter_deck_by_collection(parsed_cards, owned_cards):
|
||||
"""
|
||||
Subtracts owned quantities from parsed_cards.
|
||||
Returns new list of parsed_cards.
|
||||
"""
|
||||
filtered = []
|
||||
for item in parsed_cards:
|
||||
name = item['name']
|
||||
needed = item['quantity']
|
||||
# Simple name match
|
||||
owned_qty = 0
|
||||
# Try exact match first
|
||||
if name in owned_cards:
|
||||
owned_qty = owned_cards[name]
|
||||
else:
|
||||
# Try case insensitive fallback
|
||||
for key in owned_cards:
|
||||
if key.lower() == name.lower():
|
||||
owned_qty = owned_cards[key]
|
||||
break
|
||||
|
||||
remaining = needed - owned_qty
|
||||
if remaining > 0:
|
||||
filtered.append({'name': name, 'quantity': remaining})
|
||||
|
||||
return filtered
|
||||
Reference in New Issue
Block a user