Files
claims-system/claims/forms.py
2025-11-09 21:49:44 +01:00

162 lines
6.4 KiB
Python

from django import forms
from django.contrib.auth import get_user_model, password_validation
from django.core.exceptions import ValidationError
from django.utils.translation import gettext_lazy as _
from .models import Claim, Project
User = get_user_model()
INPUT_CLASSES = "mt-1 block w-full rounded-lg border border-gray-300 bg-white px-3 py-2 text-sm text-gray-900 shadow-sm focus:border-indigo-500 focus:ring-2 focus:ring-indigo-500"
TEXTAREA_CLASSES = "mt-1 block w-full rounded-lg border border-gray-300 bg-white px-3 py-2 text-sm text-gray-900 shadow-sm focus:border-indigo-500 focus:ring-2 focus:ring-indigo-500"
SELECT_CLASSES = "mt-1 block w-full rounded-lg border border-gray-300 bg-white px-3 py-2 text-sm text-gray-900 shadow-sm focus:border-indigo-500 focus:ring-2 focus:ring-indigo-500"
FILE_CLASSES = "mt-1 block w-full text-sm text-gray-700 file:mr-4 file:rounded-md file:border-0 file:bg-indigo-600 file:px-4 file:py-2 file:text-sm file:font-medium file:text-white hover:file:bg-indigo-500"
class ClaimantForm(forms.Form):
full_name = forms.CharField(
max_length=255,
label=_("Namn"),
widget=forms.TextInput(attrs={"class": INPUT_CLASSES}),
)
email = forms.EmailField(
label=_("E-post"),
widget=forms.EmailInput(attrs={"class": INPUT_CLASSES}),
)
account_number = forms.CharField(
max_length=50,
label=_("Kontonummer"),
widget=forms.TextInput(attrs={"class": INPUT_CLASSES}),
)
class ClaimLineForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if not self.is_bound:
self.fields["currency"].initial = Claim.Currency.SEK
self.fields["project"].queryset = Project.objects.filter(is_active=True).order_by("name")
self.fields["project"].required = False
self.fields["project"].widget.attrs.update({"class": SELECT_CLASSES})
self.fields["currency"].widget.attrs.update({"class": SELECT_CLASSES})
self.fields["amount"].widget.attrs.update({"class": INPUT_CLASSES})
self.fields["receipt"].widget.attrs.update({"class": FILE_CLASSES})
class Meta:
model = Claim
fields = ["description", "amount", "currency", "project", "receipt"]
labels = {
"description": _("Beskrivning"),
"amount": _("Belopp"),
"currency": _("Valuta"),
"project": _("Evenemang/Projekt"),
"receipt": _("Kvitto"),
}
widgets = {
"description": forms.Textarea(attrs={"rows": 3, "class": TEXTAREA_CLASSES}),
}
class ClaimDecisionForm(forms.Form):
ACTION_APPROVE = "approve"
ACTION_REJECT = "reject"
ACTION_CHOICES = (
(ACTION_APPROVE, _("Godkänn")),
(ACTION_REJECT, _("Neka")),
)
claim_id = forms.IntegerField(widget=forms.HiddenInput)
action = forms.ChoiceField(choices=ACTION_CHOICES)
project = forms.ModelChoiceField(
queryset=Project.objects.none(),
required=False,
label=_("Evenemang/Projekt"),
)
decision_note = forms.CharField(
required=False,
widget=forms.Textarea(attrs={"rows": 2, "placeholder": _("Kommentar")}),
)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields["project"].queryset = Project.objects.filter(is_active=True).order_by("name")
def clean(self):
cleaned = super().clean()
action = cleaned.get("action")
note = cleaned.get("decision_note", "").strip()
if action == self.ACTION_REJECT and not note:
self.add_error("decision_note", _("Kommentar krävs när du nekar ett utlägg."))
return cleaned
class ClaimEditForm(forms.ModelForm):
class Meta:
model = Claim
fields = [
"full_name",
"email",
"account_number",
"amount",
"currency",
"project",
"description",
]
labels = {
"full_name": _("Namn"),
"email": _("E-post"),
"account_number": _("Kontonummer"),
"amount": _("Belopp"),
"currency": _("Valuta"),
"project": _("Evenemang/Projekt"),
"description": _("Beskrivning"),
}
class UserManagementForm(forms.Form):
username = forms.CharField(max_length=150, label=_("Användarnamn"))
email = forms.EmailField(required=False, label=_("E-post"))
first_name = forms.CharField(max_length=150, required=False, label=_("Förnamn"))
last_name = forms.CharField(max_length=150, required=False, label=_("Efternamn"))
password1 = forms.CharField(widget=forms.PasswordInput, label=_("Lösenord"))
password2 = forms.CharField(widget=forms.PasswordInput, label=_("Bekräfta lösenord"))
is_staff = forms.BooleanField(required=False, initial=True, label=_("Administratör (staff)"))
grant_view = forms.BooleanField(required=False, initial=True, label=_("Ge behörighet att se utlägg"))
grant_change = forms.BooleanField(required=False, initial=True, label=_("Ge behörighet att besluta utlägg"))
def clean_username(self):
username = self.cleaned_data["username"]
if User.objects.filter(username=username).exists():
raise forms.ValidationError(_("Användarnamnet är upptaget."))
return username
def clean(self):
cleaned = super().clean()
if cleaned.get("password1") != cleaned.get("password2"):
self.add_error("password2", _("Lösenorden matchar inte."))
password = cleaned.get("password1")
if password:
temp_user = User(
username=cleaned.get("username", ""),
email=cleaned.get("email", ""),
first_name=cleaned.get("first_name", ""),
last_name=cleaned.get("last_name", ""),
)
try:
password_validation.validate_password(password, temp_user)
except ValidationError as exc:
self.add_error("password1", exc)
return cleaned
class UserPermissionForm(forms.Form):
user_id = forms.IntegerField(widget=forms.HiddenInput)
is_staff = forms.BooleanField(required=False, label=_("Admin/staff"))
grant_view = forms.BooleanField(required=False, label=_("Får se utlägg"))
grant_change = forms.BooleanField(required=False, label=_("Får besluta utlägg"))
class DeleteUserForm(forms.Form):
user_id = forms.IntegerField(widget=forms.HiddenInput)