Files
Example-TCG-Site/store/views.py
2026-01-20 05:22:38 -06:00

283 lines
9.7 KiB
Python

from django.shortcuts import render, get_object_or_404, redirect
from django.db.models import Q
from django.core.paginator import Paginator
from django.contrib.auth.decorators import login_required
from .models import Card, Game, Set, Cart, CartItem, CardListing, PackListing, VirtualPack, Order, OrderItem
import random
def card_list(request):
cards = Card.objects.all().select_related('set', 'set__game').prefetch_related('listings')
# Filtering
game_slug = request.GET.get('game')
if game_slug:
cards = cards.filter(set__game__slug=game_slug)
search_query = request.GET.get('q')
if search_query:
cards = cards.filter(name__icontains=search_query)
set_id = request.GET.get('set')
if set_id:
cards = cards.filter(set__id=set_id)
# Simple logic: only show cards that have listings or show all?
# Let's show all for browsing, but indicate stock.
paginator = Paginator(cards.order_by('name'), 24) # 24 cards per page
page_number = request.GET.get('page')
page_obj = paginator.get_page(page_number)
games = Game.objects.all()
# If a game is selected, getting its sets for the filter dropdown
sets = Set.objects.filter(game__slug=game_slug) if game_slug else Set.objects.all()[:50] # Limit default sets
return render(request, 'store/card_list.html', {
'page_obj': page_obj,
'games': games,
'sets': sets,
'current_game': game_slug,
'search_query': search_query,
})
def card_detail(request, card_id):
card = get_object_or_404(Card, id=card_id)
listings = card.listings.filter(quantity__gt=0).order_by('price')
return render(request, 'store/card_detail.html', {'card': card, 'listings': listings})
@login_required
def add_to_cart(request, listing_id):
listing = get_object_or_404(CardListing, id=listing_id)
cart, _ = Cart.objects.get_or_create(user=request.user)
cart_item, created = CartItem.objects.get_or_create(cart=cart, listing=listing)
if not created:
cart_item.quantity += 1
cart_item.save()
return redirect('store:cart')
@login_required
def cart_view(request):
try:
cart = request.user.cart
except Cart.DoesNotExist:
cart = None
return render(request, 'store/cart.html', {'cart': cart})
@login_required
def remove_from_cart(request, item_id):
if hasattr(request.user, 'cart'):
item = get_object_or_404(CartItem, id=item_id, cart=request.user.cart)
item.delete()
return redirect('store:cart')
@login_required
def toggle_insurance(request):
if hasattr(request.user, 'cart'):
cart = request.user.cart
cart.insurance = not cart.insurance
cart.save()
return redirect('store:cart')
from django.http import JsonResponse
def get_card_stock(request, card_id):
card = get_object_or_404(Card, id=card_id)
listings = card.listings.all()
stock_breakdown = {}
total_stock = 0
for listing in listings:
stock_breakdown[listing.get_condition_display()] = listing.quantity
total_stock += listing.quantity
return JsonResponse({
'card_id': card.id,
'total_stock': total_stock,
'breakdown': stock_breakdown
})
from .utils import parse_deck_list, find_best_listings_for_deck, get_user_collection, filter_deck_by_collection, add_to_vault
@login_required
def deck_buyer(request):
if request.method == 'POST':
action = request.POST.get('action')
if action == 'preview':
deck_text = request.POST.get('deck_text')
ignore_owned = request.POST.get('ignore_owned') == 'on'
parsed = parse_deck_list(deck_text)
if ignore_owned and request.user.is_authenticated:
owned = get_user_collection(request.user)
parsed = filter_deck_by_collection(parsed, owned)
found, missing = find_best_listings_for_deck(parsed)
total_cost = sum(item['total'] for item in found)
return render(request, 'store/deck_buyer.html', {
'found_items': found,
'missing_items': missing,
'deck_text': deck_text,
'total_cost': total_cost,
'preview': True,
'ignore_owned': ignore_owned
})
elif action == 'add_to_cart':
# Re-parse or rely on hidden fields?
# Re-parsing is safer/easier for now than passing complex data
deck_text = request.POST.get('deck_text')
parsed = parse_deck_list(deck_text)
found, _ = find_best_listings_for_deck(parsed)
cart, _ = Cart.objects.get_or_create(user=request.user)
count = 0
for item in found:
listing = item['listing']
qty = item['quantity']
# Check stock again? "Live stock"
if listing.quantity >= qty:
cart_item, created = CartItem.objects.get_or_create(cart=cart, listing=listing)
if not created:
cart_item.quantity += qty
else:
cart_item.quantity = qty
cart_item.save()
count += 1
return redirect('store:cart')
return render(request, 'store/deck_buyer.html')
from .models import Bounty
def bounty_board(request):
bounties = Bounty.objects.filter(is_active=True).select_related('card', 'card__set').order_by('-created_at')
return render(request, 'store/bounty_board.html', {'bounties': bounties})
def pack_list(request):
packs = PackListing.objects.all()
return render(request, 'store/pack_list.html', {'packs': packs})
@login_required
def add_pack_to_cart(request, pack_listing_id):
listing = get_object_or_404(PackListing, id=pack_listing_id)
cart, _ = Cart.objects.get_or_create(user=request.user)
cart_item, created = CartItem.objects.get_or_create(cart=cart, pack_listing=listing)
if not created:
cart_item.quantity += 1
cart_item.save()
return redirect('store:cart')
@login_required
def checkout(request):
try:
cart = request.user.cart
except Cart.DoesNotExist:
return redirect('store:cart')
if not cart.items.exists():
return redirect('store:cart')
# Create Order
order = Order.objects.create(
user=request.user,
status='paid',
total_price=cart.total_price
)
# Move items
for item in cart.items.all():
OrderItem.objects.create(
order=order,
listing=item.listing,
pack_listing=item.pack_listing,
price_at_purchase=item.listing.price if item.listing else item.pack_listing.price,
quantity=item.quantity
)
# Add single cards to vault
if item.listing:
add_to_vault(request.user, item.listing.card, item.quantity)
# If it's a pack, assign VirtualPacks to user
if item.pack_listing:
# Find available sealed packs
available_packs = list(VirtualPack.objects.filter(
listing=item.pack_listing,
owner__isnull=True,
status='sealed'
)[:item.quantity])
# If not enough, create more
if len(available_packs) < item.quantity:
needed = item.quantity - len(available_packs)
game = item.pack_listing.game
all_game_cards = list(Card.objects.filter(set__game=game))
if not all_game_cards:
# Fallback if no cards? Should not happen due to management command or basic setup
pass
for _ in range(needed):
pack = VirtualPack.objects.create(listing=item.pack_listing)
if all_game_cards:
pack.cards.set(random.sample(all_game_cards, min(len(all_game_cards), 5)))
available_packs.append(pack)
for pack in available_packs:
pack.owner = request.user
pack.save()
# Clear cart
cart.items.all().delete()
return redirect('store:my_packs')
@login_required
def my_packs(request):
packs = VirtualPack.objects.filter(owner=request.user, status='sealed').select_related('listing')
return render(request, 'store/my_packs.html', {'packs': packs})
@login_required
def open_pack(request, pack_id):
pack = get_object_or_404(VirtualPack, id=pack_id, owner=request.user)
if request.method == 'POST':
if pack.status == 'sealed':
pack.status = 'opened'
pack.save()
# Add cards to vault
for card in pack.cards.all():
add_to_vault(request.user, card)
data = {
'cards': [{
'name': c.name,
'image_url': c.image_url,
'rarity': c.rarity,
'set': c.set.name
} for c in pack.cards.all()]
}
return JsonResponse(data)
return render(request, 'store/open_pack.html', {'pack': pack})
@login_required
def order_detail(request, order_id):
order = get_object_or_404(Order, id=order_id)
# Security check: only allow viewing own orders (unless superuser)
if order.user != request.user and not request.user.is_superuser:
return redirect('users:profile')
return render(request, 'store/order_detail.html', {'order': order})