Sith/counter/forms.py
Sli 652ceb27c2 Fix counter main
* Fix crash when submitting nothing
* Fix code field not being autofocus
2024-12-21 16:03:42 +01:00

222 lines
6.5 KiB
Python

from django import forms
from django.utils.translation import gettext_lazy as _
from phonenumber_field.widgets import RegionalPhoneNumberWidget
from club.widgets.select import AutoCompleteSelectClub
from core.views.forms import NFCTextInput, SelectDate, SelectDateTime
from core.views.widgets.select import (
AutoCompleteSelect,
AutoCompleteSelectMultipleGroup,
AutoCompleteSelectMultipleUser,
AutoCompleteSelectUser,
)
from counter.models import (
BillingInfo,
Counter,
Customer,
Eticket,
Product,
Refilling,
StudentCard,
)
from counter.widgets.select import (
AutoCompleteSelectMultipleCounter,
AutoCompleteSelectMultipleProduct,
AutoCompleteSelectProduct,
)
class BillingInfoForm(forms.ModelForm):
class Meta:
model = BillingInfo
fields = [
"first_name",
"last_name",
"address_1",
"address_2",
"zip_code",
"city",
"country",
"phone_number",
]
widgets = {
"phone_number": RegionalPhoneNumberWidget,
}
class StudentCardForm(forms.ModelForm):
"""Form for adding student cards"""
class Meta:
model = StudentCard
fields = ["uid"]
widgets = {"uid": NFCTextInput}
def clean(self):
cleaned_data = super().clean()
uid = cleaned_data.get("uid", None)
if not uid or not StudentCard.is_valid(uid):
raise forms.ValidationError(_("This UID is invalid"), code="invalid")
return cleaned_data
class GetUserForm(forms.Form):
"""The Form class aims at providing a valid user_id field in its cleaned data, in order to pass it to some view,
reverse function, or any other use.
The Form implements a nice JS widget allowing the user to type a customer account id, or search the database with
some nickname, first name, or last name (TODO)
"""
code = forms.CharField(
label="Code",
max_length=StudentCard.UID_SIZE,
required=False,
widget=NFCTextInput,
)
id = forms.CharField(
label=_("Select user"),
help_text=None,
widget=AutoCompleteSelectUser,
required=False,
)
def as_p(self):
self.fields["code"].widget.attrs["autofocus"] = True
return super().as_p()
def clean(self):
cleaned_data = super().clean()
customer = None
if cleaned_data["code"] != "":
if len(cleaned_data["code"]) == StudentCard.UID_SIZE:
card = (
StudentCard.objects.filter(uid=cleaned_data["code"])
.select_related("customer")
.first()
)
if card is not None:
customer = card.customer
if customer is None:
customer = Customer.objects.filter(
account_id__iexact=cleaned_data["code"]
).first()
elif cleaned_data["id"]:
customer = Customer.objects.filter(user=cleaned_data["id"]).first()
if customer is None or not customer.can_buy:
raise forms.ValidationError(_("User not found"))
cleaned_data["user_id"] = customer.user.id
cleaned_data["user"] = customer.user
return cleaned_data
class RefillForm(forms.ModelForm):
allowed_refilling_methods = ["CASH", "CARD"]
error_css_class = "error"
required_css_class = "required"
amount = forms.FloatField(
min_value=0, widget=forms.NumberInput(attrs={"class": "focus"})
)
class Meta:
model = Refilling
fields = ["amount", "payment_method", "bank"]
widgets = {"payment_method": forms.RadioSelect}
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields["payment_method"].choices = (
method
for method in self.fields["payment_method"].choices
if method[0] in self.allowed_refilling_methods
)
if self.fields["payment_method"].initial not in self.allowed_refilling_methods:
self.fields["payment_method"].initial = self.allowed_refilling_methods[0]
if "CHECK" not in self.allowed_refilling_methods:
del self.fields["bank"]
class CounterEditForm(forms.ModelForm):
class Meta:
model = Counter
fields = ["sellers", "products"]
widgets = {
"sellers": AutoCompleteSelectMultipleUser,
"products": AutoCompleteSelectMultipleProduct,
}
class ProductEditForm(forms.ModelForm):
class Meta:
model = Product
fields = [
"name",
"description",
"product_type",
"code",
"buying_groups",
"purchase_price",
"selling_price",
"special_selling_price",
"icon",
"club",
"limit_age",
"tray",
"archived",
]
widgets = {
"product_type": AutoCompleteSelect,
"buying_groups": AutoCompleteSelectMultipleGroup,
"club": AutoCompleteSelectClub,
}
counters = forms.ModelMultipleChoiceField(
help_text=None,
label=_("Counters"),
required=False,
widget=AutoCompleteSelectMultipleCounter,
queryset=Counter.objects.all(),
)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if self.instance.id:
self.fields["counters"].initial = self.instance.counters.all()
def save(self, *args, **kwargs):
ret = super().save(*args, **kwargs)
if self.fields["counters"].initial:
# Remove the product from all counter it was added to
# It will then only be added to selected counters
for counter in self.fields["counters"].initial:
counter.products.remove(self.instance)
counter.save()
for counter in self.cleaned_data["counters"]:
counter.products.add(self.instance)
counter.save()
return ret
class CashSummaryFormBase(forms.Form):
begin_date = forms.DateTimeField(
label=_("Begin date"), widget=SelectDateTime, required=False
)
end_date = forms.DateTimeField(
label=_("End date"), widget=SelectDateTime, required=False
)
class EticketForm(forms.ModelForm):
class Meta:
model = Eticket
fields = ["product", "banner", "event_title", "event_date"]
widgets = {
"product": AutoCompleteSelectProduct,
"event_date": SelectDate,
}