symposion_app/registrasion/forms.py

200 lines
5.7 KiB
Python
Raw Normal View History

from registrasion.models import commerce
from registrasion.models import inventory
from django import forms
class ApplyCreditNoteForm(forms.Form):
def __init__(self, user, *a, **k):
''' User: The user whose invoices should be made available as
choices. '''
self.user = user
super(ApplyCreditNoteForm, self).__init__(*a, **k)
self.fields["invoice"].choices = self._unpaid_invoices_for_user
def _unpaid_invoices_for_user(self):
invoices = commerce.Invoice.objects.filter(
status=commerce.Invoice.STATUS_UNPAID,
user=self.user,
)
return [
(invoice.id, "Invoice %(id)d - $%(value)d" % invoice.__dict__)
for invoice in invoices
]
invoice = forms.ChoiceField(
required=True,
)
class ManualCreditNoteRefundForm(forms.ModelForm):
class Meta:
model = commerce.ManualCreditNoteRefund
fields = ["reference"]
2016-04-07 09:19:19 +00:00
class ManualPaymentForm(forms.ModelForm):
class Meta:
model = commerce.ManualPayment
2016-04-07 09:19:19 +00:00
fields = ["reference", "amount"]
# Products forms -- none of these have any fields: they are to be subclassed
# and the fields added as needs be. ProductsForm (the function) is responsible
# for the subclassing.
def ProductsForm(category, products):
''' Produces an appropriate _ProductsForm subclass for the given render
type. '''
# Each Category.RENDER_TYPE value has a subclass here.
RENDER_TYPES = {
inventory.Category.RENDER_TYPE_QUANTITY: _QuantityBoxProductsForm,
inventory.Category.RENDER_TYPE_RADIO: _RadioButtonProductsForm,
}
# Produce a subclass of _ProductsForm which we can alter the base_fields on
class ProductsForm(RENDER_TYPES[category.render_type]):
pass
ProductsForm.set_fields(category, products)
return ProductsForm
class _HasProductsFields(object):
PRODUCT_PREFIX = "product_"
''' Base class for product entry forms. '''
def __init__(self, *a, **k):
if "product_quantities" in k:
initial = self.initial_data(k["product_quantities"])
k["initial"] = initial
del k["product_quantities"]
super(_HasProductsFields, self).__init__(*a, **k)
@classmethod
def field_name(cls, product):
return cls.PRODUCT_PREFIX + ("%d" % product.id)
@classmethod
2016-03-27 00:18:26 +00:00
def set_fields(cls, category, products):
''' Sets the base_fields on this _ProductsForm to allow selecting
from the provided products. '''
pass
@classmethod
def initial_data(cls, product_quantites):
''' Prepares initial data for an instance of this form.
product_quantities is a sequence of (product,quantity) tuples '''
return {}
def product_quantities(self):
''' Yields a sequence of (product, quantity) tuples from the
cleaned form data. '''
return iter([])
class _ProductsForm(_HasProductsFields, forms.Form):
pass
class _QuantityBoxProductsForm(_ProductsForm):
''' Products entry form that allows users to enter quantities
of desired products. '''
@classmethod
2016-03-27 00:18:26 +00:00
def set_fields(cls, category, products):
for product in products:
if product.description:
2016-04-07 03:26:25 +00:00
help_text = "$%d each -- %s" % (
product.price,
product.description,
)
else:
help_text = "$%d each" % product.price
field = forms.IntegerField(
label=product.name,
help_text=help_text,
min_value=0,
max_value=500, # Issue #19. We should figure out real limit.
)
cls.base_fields[cls.field_name(product)] = field
@classmethod
def initial_data(cls, product_quantities):
initial = {}
for product, quantity in product_quantities:
initial[cls.field_name(product)] = quantity
return initial
def product_quantities(self):
for name, value in self.cleaned_data.items():
if name.startswith(self.PRODUCT_PREFIX):
product_id = int(name[len(self.PRODUCT_PREFIX):])
yield (product_id, value, name)
2016-03-27 00:18:26 +00:00
class _RadioButtonProductsForm(_ProductsForm):
''' Products entry form that allows users to enter quantities
of desired products. '''
FIELD = "chosen_product"
@classmethod
def set_fields(cls, category, products):
choices = []
for product in products:
choice_text = "%s -- $%d" % (product.name, product.price)
choices.append((product.id, choice_text))
if not category.required:
choices.append((0, "No selection"))
2016-03-27 00:18:26 +00:00
cls.base_fields[cls.FIELD] = forms.TypedChoiceField(
label=category.name,
widget=forms.RadioSelect,
choices=choices,
empty_value=0,
coerce=int,
)
@classmethod
def initial_data(cls, product_quantities):
initial = {}
for product, quantity in product_quantities:
if quantity > 0:
initial[cls.FIELD] = product.id
break
return initial
def product_quantities(self):
ours = self.cleaned_data[self.FIELD]
choices = self.fields[self.FIELD].choices
for choice_value, choice_display in choices:
if choice_value == 0:
continue
2016-03-27 00:18:26 +00:00
yield (
choice_value,
1 if ours == choice_value else 0,
self.FIELD,
)
class VoucherForm(forms.Form):
voucher = forms.CharField(
label="Voucher code",
help_text="If you have a voucher code, enter it here",
required=False,
)