2022-11-28 16:03:46 +00:00
|
|
|
from ajax_select import make_ajax_field
|
|
|
|
from ajax_select.fields import AutoCompleteSelectField, AutoCompleteSelectMultipleField
|
|
|
|
from django import forms
|
|
|
|
from django.utils.translation import gettext_lazy as _
|
2024-09-27 20:35:03 +00:00
|
|
|
from phonenumber_field.widgets import RegionalPhoneNumberWidget
|
2022-11-28 16:03:46 +00:00
|
|
|
|
2024-07-24 15:42:02 +00:00
|
|
|
from core.views.forms import NFCTextInput, SelectDate, SelectDateTime
|
2022-11-28 16:03:46 +00:00
|
|
|
from counter.models import (
|
|
|
|
BillingInfo,
|
|
|
|
Counter,
|
2024-06-24 11:07:36 +00:00
|
|
|
Customer,
|
2022-11-28 16:03:46 +00:00
|
|
|
Eticket,
|
2024-06-24 11:07:36 +00:00
|
|
|
Product,
|
|
|
|
Refilling,
|
|
|
|
StudentCard,
|
2022-11-28 16:03:46 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
class BillingInfoForm(forms.ModelForm):
|
|
|
|
class Meta:
|
|
|
|
model = BillingInfo
|
2024-06-27 13:48:07 +00:00
|
|
|
fields = [
|
|
|
|
"first_name",
|
|
|
|
"last_name",
|
|
|
|
"address_1",
|
|
|
|
"address_2",
|
|
|
|
"zip_code",
|
|
|
|
"city",
|
|
|
|
"country",
|
2024-09-26 15:55:53 +00:00
|
|
|
"phone_number",
|
2024-06-27 13:48:07 +00:00
|
|
|
]
|
2024-09-27 20:35:03 +00:00
|
|
|
widgets = {
|
|
|
|
"phone_number": RegionalPhoneNumberWidget,
|
|
|
|
}
|
2022-11-28 16:03:46 +00:00
|
|
|
|
|
|
|
|
|
|
|
class StudentCardForm(forms.ModelForm):
|
2024-07-12 07:34:16 +00:00
|
|
|
"""Form for adding student cards
|
|
|
|
Only used for user profile since CounterClick is to complicated.
|
2022-11-28 16:03:46 +00:00
|
|
|
"""
|
|
|
|
|
|
|
|
class Meta:
|
|
|
|
model = StudentCard
|
|
|
|
fields = ["uid"]
|
2024-07-24 15:42:02 +00:00
|
|
|
widgets = {
|
|
|
|
"uid": NFCTextInput,
|
|
|
|
}
|
2022-11-28 16:03:46 +00:00
|
|
|
|
|
|
|
def clean(self):
|
2024-06-27 12:46:43 +00:00
|
|
|
cleaned_data = super().clean()
|
2022-11-28 16:03:46 +00:00
|
|
|
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):
|
2024-07-12 07:34:16 +00:00
|
|
|
"""The Form class aims at providing a valid user_id field in its cleaned data, in order to pass it to some view,
|
2022-11-28 16:03:46 +00:00
|
|
|
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(
|
2024-07-24 15:42:02 +00:00
|
|
|
label="Code",
|
|
|
|
max_length=StudentCard.UID_SIZE,
|
|
|
|
required=False,
|
|
|
|
widget=NFCTextInput,
|
2022-11-28 16:03:46 +00:00
|
|
|
)
|
|
|
|
id = AutoCompleteSelectField(
|
|
|
|
"users", required=False, label=_("Select user"), help_text=None
|
|
|
|
)
|
|
|
|
|
|
|
|
def as_p(self):
|
|
|
|
self.fields["code"].widget.attrs["autofocus"] = True
|
2024-06-27 12:46:43 +00:00
|
|
|
return super().as_p()
|
2022-11-28 16:03:46 +00:00
|
|
|
|
|
|
|
def clean(self):
|
2024-06-27 12:46:43 +00:00
|
|
|
cleaned_data = super().clean()
|
2022-11-28 16:03:46 +00:00
|
|
|
cus = None
|
|
|
|
if cleaned_data["code"] != "":
|
|
|
|
if len(cleaned_data["code"]) == StudentCard.UID_SIZE:
|
|
|
|
card = StudentCard.objects.filter(uid=cleaned_data["code"])
|
|
|
|
if card.exists():
|
|
|
|
cus = card.first().customer
|
|
|
|
if cus is None:
|
|
|
|
cus = Customer.objects.filter(
|
|
|
|
account_id__iexact=cleaned_data["code"]
|
|
|
|
).first()
|
|
|
|
elif cleaned_data["id"] is not None:
|
|
|
|
cus = Customer.objects.filter(user=cleaned_data["id"]).first()
|
|
|
|
if cus is None or not cus.can_buy:
|
|
|
|
raise forms.ValidationError(_("User not found"))
|
|
|
|
cleaned_data["user_id"] = cus.user.id
|
|
|
|
cleaned_data["user"] = cus.user
|
|
|
|
return cleaned_data
|
|
|
|
|
|
|
|
|
2024-07-24 15:42:02 +00:00
|
|
|
class NFCCardForm(forms.Form):
|
|
|
|
student_card_uid = forms.CharField(
|
|
|
|
max_length=StudentCard.UID_SIZE,
|
|
|
|
required=False,
|
|
|
|
widget=NFCTextInput,
|
|
|
|
)
|
|
|
|
|
|
|
|
|
2022-11-28 16:03:46 +00:00
|
|
|
class RefillForm(forms.ModelForm):
|
|
|
|
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"]
|
|
|
|
|
|
|
|
|
|
|
|
class CounterEditForm(forms.ModelForm):
|
|
|
|
class Meta:
|
|
|
|
model = Counter
|
|
|
|
fields = ["sellers", "products"]
|
|
|
|
|
|
|
|
sellers = make_ajax_field(Counter, "sellers", "users", help_text="")
|
|
|
|
products = make_ajax_field(Counter, "products", "products", help_text="")
|
|
|
|
|
|
|
|
|
|
|
|
class ProductEditForm(forms.ModelForm):
|
|
|
|
class Meta:
|
|
|
|
model = Product
|
|
|
|
fields = [
|
|
|
|
"name",
|
|
|
|
"description",
|
|
|
|
"product_type",
|
|
|
|
"code",
|
|
|
|
"parent_product",
|
|
|
|
"buying_groups",
|
|
|
|
"purchase_price",
|
|
|
|
"selling_price",
|
|
|
|
"special_selling_price",
|
|
|
|
"icon",
|
|
|
|
"club",
|
|
|
|
"limit_age",
|
|
|
|
"tray",
|
|
|
|
"archived",
|
|
|
|
]
|
|
|
|
|
|
|
|
parent_product = AutoCompleteSelectField(
|
|
|
|
"products", show_help_text=False, label=_("Parent product"), required=False
|
|
|
|
)
|
|
|
|
buying_groups = AutoCompleteSelectMultipleField(
|
|
|
|
"groups",
|
|
|
|
show_help_text=False,
|
|
|
|
help_text="",
|
|
|
|
label=_("Buying groups"),
|
|
|
|
required=True,
|
|
|
|
)
|
|
|
|
club = AutoCompleteSelectField("clubs", show_help_text=False)
|
|
|
|
counters = AutoCompleteSelectMultipleField(
|
|
|
|
"counters",
|
|
|
|
show_help_text=False,
|
|
|
|
help_text="",
|
|
|
|
label=_("Counters"),
|
|
|
|
required=False,
|
|
|
|
)
|
|
|
|
|
|
|
|
def __init__(self, *args, **kwargs):
|
2024-06-27 12:46:43 +00:00
|
|
|
super().__init__(*args, **kwargs)
|
2022-11-28 16:03:46 +00:00
|
|
|
if self.instance.id:
|
|
|
|
self.fields["counters"].initial = [
|
|
|
|
str(c.id) for c in self.instance.counters.all()
|
|
|
|
]
|
|
|
|
|
|
|
|
def save(self, *args, **kwargs):
|
2024-06-27 12:46:43 +00:00
|
|
|
ret = super().save(*args, **kwargs)
|
2022-11-28 16:03:46 +00:00
|
|
|
if self.fields["counters"].initial:
|
|
|
|
for cid in self.fields["counters"].initial:
|
|
|
|
c = Counter.objects.filter(id=int(cid)).first()
|
|
|
|
c.products.remove(self.instance)
|
|
|
|
c.save()
|
|
|
|
for cid in self.cleaned_data["counters"]:
|
|
|
|
c = Counter.objects.filter(id=int(cid)).first()
|
|
|
|
c.products.add(self.instance)
|
|
|
|
c.save()
|
|
|
|
return ret
|
|
|
|
|
|
|
|
|
|
|
|
class CashSummaryFormBase(forms.Form):
|
2024-07-21 14:16:40 +00:00
|
|
|
begin_date = forms.DateTimeField(
|
|
|
|
label=_("Begin date"), widget=SelectDateTime, required=False
|
|
|
|
)
|
|
|
|
end_date = forms.DateTimeField(
|
|
|
|
label=_("End date"), widget=SelectDateTime, required=False
|
|
|
|
)
|
2022-11-28 16:03:46 +00:00
|
|
|
|
|
|
|
|
|
|
|
class EticketForm(forms.ModelForm):
|
|
|
|
class Meta:
|
|
|
|
model = Eticket
|
|
|
|
fields = ["product", "banner", "event_title", "event_date"]
|
|
|
|
widgets = {"event_date": SelectDate}
|
|
|
|
|
|
|
|
product = AutoCompleteSelectField(
|
|
|
|
"products", show_help_text=False, label=_("Product"), required=True
|
|
|
|
)
|