Files
Example-TCG-Site/store/forms.py
Ryan Westfall 739d136209 Last bit of major changes
Closes #1
Closes #5
Closes #6
Closes #8
Closes #9
Closes #10
2026-01-26 04:11:38 -06:00

190 lines
8.8 KiB
Python

from django import forms
from .models import Seller, CardListing, PackListing, Game, Bounty, BountyOffer
from users.models import Profile
class SellerThemeForm(forms.ModelForm):
class Meta:
model = Profile
fields = ['theme_preference']
widgets = {
'theme_preference': forms.Select(attrs={'class': 'form-select'})
}
class SellerRegistrationForm(forms.ModelForm):
street = forms.CharField(max_length=200, widget=forms.TextInput(attrs={'placeholder': 'Street Address'}))
city = forms.CharField(max_length=100, widget=forms.TextInput(attrs={'placeholder': 'City'}))
state = forms.CharField(max_length=100, widget=forms.TextInput(attrs={'placeholder': 'State'}))
zip_code = forms.CharField(max_length=20, widget=forms.TextInput(attrs={'placeholder': 'Zip Code'}))
class Meta:
model = Seller
fields = ['store_name', 'description', 'contact_email', 'contact_phone']
widgets = {
'description': forms.Textarea(attrs={'rows': 4}),
}
def save(self, commit=True):
seller = super().save(commit=False)
# Create address
# We need the user to link the address to? The Seller model has user.
# But here seller.user might not be set yet if it's done in the view.
# However, save(commit=True) usually saves.
# We'll create the Address instance but we need the user.
# We can't easily get the user here unless we pass it or it's already on seller.
# In the view `seller_register`, we do `form.instance.user = request.user` before saving?
# Let's check `seller_register` view.
# If we can't create Address yet, we might need to handle it in the view.
# BUT, standard ModelForm save() returns the instance.
# Let's attach the address data to the instance temporarily?
# Or better: Override save to creating the Address.
# We will assume seller.user is set by the view before save is called,
# or we just create the address without user first (but user is required in Address model).
# Actually, Address.user is required.
# So we MUST have the user.
return seller
class SellerEditForm(forms.ModelForm):
street = forms.CharField(max_length=200, required=False)
city = forms.CharField(max_length=100, required=False)
state = forms.CharField(max_length=100, required=False)
zip_code = forms.CharField(max_length=20, required=False)
tax_id = forms.CharField(required=False, widget=forms.TextInput(attrs={'type': 'password'}), help_text="SSN, ITIN, or EIN (Stored securely)")
payout_details = forms.CharField(required=False, widget=forms.Textarea(attrs={'rows': 3}), help_text="Bank account or other payout details (Stored securely)")
class Meta:
model = Seller
fields = ['store_name', 'description', 'contact_email', 'contact_phone', 'store_image', 'hero_image', 'minimum_order_amount', 'shipping_cost', 'tax_id', 'payout_details']
widgets = {
'description': forms.Textarea(attrs={'rows': 4}),
}
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if self.instance and self.instance.pk:
self.fields['tax_id'].initial = self.instance.tax_id
self.fields['payout_details'].initial = self.instance.payout_details
# Populate address fields
if self.instance.store_address:
self.fields['street'].initial = self.instance.store_address.street
self.fields['city'].initial = self.instance.store_address.city
self.fields['state'].initial = self.instance.store_address.state
self.fields['zip_code'].initial = self.instance.store_address.zip_code
def save(self, commit=True):
seller = super().save(commit=False)
seller.tax_id = self.cleaned_data.get('tax_id')
seller.payout_details = self.cleaned_data.get('payout_details')
# Handle Address
# We need to update existing or create new.
street = self.cleaned_data.get('street')
city = self.cleaned_data.get('city')
state = self.cleaned_data.get('state')
zip_code = self.cleaned_data.get('zip_code')
if street and city and state and zip_code:
from users.models import Address
if seller.store_address:
seller.store_address.street = street
seller.store_address.city = city
seller.store_address.state = state
seller.store_address.zip_code = zip_code
if commit:
seller.store_address.save()
else:
# Create new address. Requires user.
# seller.user should exist.
address = Address(
user=seller.user,
name=seller.store_name, # Use store name for address name
street=street,
city=city,
state=state,
zip_code=zip_code,
address_type='shipping' # Default
)
if commit:
address.save()
seller.store_address = address
if commit:
seller.save()
return seller
class CardListingForm(forms.ModelForm):
class Meta:
model = CardListing
fields = ['condition', 'price', 'quantity', 'status', 'image']
# TODO: Add search widget for card selection or filter by game/set
class PackListingForm(forms.ModelForm):
class Meta:
model = PackListing
fields = ['game', 'name', 'listing_type', 'price', 'quantity', 'image_url']
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# Helper to indicate quantity logic
self.fields['quantity'].help_text = "For Virtual packs, this is automatically updated based on inventory."
class AddCardListingForm(forms.Form):
card_name = forms.CharField(max_length=200, label="Card Name", help_text="Enter the card name.")
game = forms.ModelChoiceField(queryset=Game.objects.all(), empty_label="Select Game")
set_name = forms.CharField(max_length=200, label="Set Name", help_text="Enter the set name (e.g., 'Alpha', 'Base Set').")
collector_number = forms.CharField(max_length=20, required=False, label="Card Number", help_text="The number on the bottom of the card (e.g. '197'). Useful for variants.")
condition = forms.ChoiceField(choices=CardListing.CONDITION_CHOICES)
price = forms.DecimalField(max_digits=10, decimal_places=2)
quantity = forms.IntegerField(min_value=1, initial=1)
image = forms.ImageField(required=False, label="Card Image")
class BountyForm(forms.ModelForm):
card_name = forms.CharField(max_length=200, label="Card Name", help_text="Search for a card...", required=False)
card_id = forms.CharField(widget=forms.HiddenInput(), required=False)
class Meta:
model = Bounty
fields = ['title', 'description', 'target_price', 'quantity_wanted']
widgets = {
'description': forms.Textarea(attrs={'rows': 3}),
}
def clean(self):
cleaned_data = super().clean()
card_id = cleaned_data.get('card_id')
title = cleaned_data.get('title')
card_name = cleaned_data.get('card_name')
if not card_id and not title and not card_name:
raise forms.ValidationError("You must either select a Card or provide a Title.")
return cleaned_data
class BountyOfferForm(forms.ModelForm):
class Meta:
model = BountyOffer
fields = ['price', 'description']
widgets = {
'description': forms.Textarea(attrs={'rows': 3}),
}
class MultipleFileInput(forms.ClearableFileInput):
allow_multiple_selected = True
class BulkListingForm(forms.Form):
csv_file = forms.FileField(label="Upload CSV", help_text="Upload the filled-out template CSV.")
images = forms.FileField(widget=MultipleFileInput(attrs={'multiple': True}), required=False, label="Upload Images", help_text="Select all images referenced in your CSV.")
class CheckoutForm(forms.Form):
shipping_address = forms.ModelChoiceField(queryset=None, empty_label="Select Shipping Address", widget=forms.Select(attrs={'class': 'form-select'}))
payment_method = forms.ModelChoiceField(queryset=None, empty_label="Select Payment Method", widget=forms.Select(attrs={'class': 'form-select'}))
def __init__(self, *args, **kwargs):
user = kwargs.pop('user', None)
super().__init__(*args, **kwargs)
if user:
from users.models import Address, PaymentMethod
self.fields['shipping_address'].queryset = Address.objects.filter(user=user, address_type='shipping')
self.fields['payment_method'].queryset = PaymentMethod.objects.filter(user=user)