inital checkin
This commit is contained in:
282
store/views.py
Normal file
282
store/views.py
Normal file
@@ -0,0 +1,282 @@
|
||||
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})
|
||||
|
||||
Reference in New Issue
Block a user