from django import forms from django.core.exceptions import ValidationError from .models import Comment, Ticket class CommentForm(forms.ModelForm): class Meta: model = Comment fields = ["text"] widgets = { "text": forms.Textarea( attrs={"rows": 3, "placeholder": "Kommentar schreiben..."} ), } class TicketForm(forms.ModelForm): # Zentrale Definition der Status-Übergänge STATUS_TRANSITIONS = { "tutor": { "new": ["in_progress"], "in_progress": ["resolved", "new"], "resolved": ["closed"], "closed": [], }, "creator": { "new": [], "in_progress": [], "resolved": ["closed", "new"], "closed": [], }, "superuser": { # Superuser können alle Übergänge machen "new": ["in_progress", "resolved", "closed"], "in_progress": ["new", "resolved", "closed"], "resolved": ["new", "in_progress", "closed"], "closed": ["new", "in_progress", "resolved"], }, } # Zentrale Definition welche Felder wann required sind REQUIRED_FIELDS_BY_STATUS = { "resolved": ["answer"], # Answer required when resolving } class Meta: model = Ticket fields = [ "title", "description", "status", "mistake", "course", "answer", "material", ] widgets = { "answer": forms.Textarea( attrs={ "rows": 4, "placeholder": "Beschreibe die Lösung des Problems...", } ) } def __init__(self, *args, **kwargs): self.user = kwargs.pop("user", None) self.ticket = kwargs.pop("ticket", None) super().__init__(*args, **kwargs) if self.ticket and self.user: self._configure_form_based_on_permissions() def _configure_form_based_on_permissions(self): """Konfiguriert das Formular basierend auf Benutzerrechten""" is_creator = self.user == self.ticket.created_by is_tutor = self.user == self.ticket.assigned_to is_superuser = self.user.is_superuser # Status-Choices einschränken self._limit_status_choices(is_tutor, is_creator, is_superuser) # Feld-Berechtigungen setzen self._set_field_permissions(is_tutor, is_creator, is_superuser) def _set_field_permissions(self, is_tutor, is_creator, is_superuser): """Setzt welche Felder bearbeitet werden dürfen""" # Superuser können alles bearbeiten if is_superuser: return if self.ticket.status == "resolved" and is_creator: for field_name in self.fields: if field_name == "answer": self.fields[field_name].disabled = True elif is_tutor: # Tutor darf ändern: readonly_fields = ["title", "description", "material"] for field_name in readonly_fields: if field_name in self.fields: self.fields[field_name].disabled = True elif is_creator and self.ticket.status != "resolved": for field_name in self.fields: self.fields[field_name].disabled = True def _limit_status_choices(self, is_tutor, is_creator, is_superuser): """Beschränkt verfügbare Status-Optionen basierend auf der zentralen Logik""" current_status = self.ticket.status # Superuser bekommen alle Status-Optionen if is_superuser: role = "superuser" elif is_tutor: role = "tutor" elif is_creator: role = "creator" else: role = None if role: allowed_statuses = self._get_allowed_transitions(current_status, role) else: # Andere User sehen nur aktuellen Status allowed_statuses = [current_status] # Status-Choices filtern all_choices = list(self.fields["status"].choices) self.fields["status"].choices = [ choice for choice in all_choices if choice[0] in allowed_statuses ] def _get_allowed_transitions(self, from_status, role): """Gibt erlaubte Status-Übergänge zurück (zentrale Logik)""" transitions = self.STATUS_TRANSITIONS.get(role, {}).get(from_status, []) return [from_status] + transitions def _is_transition_allowed(self, from_status, to_status, role): """Prüft ob ein Status-Übergang erlaubt ist""" if from_status == to_status: return True return to_status in self.STATUS_TRANSITIONS.get(role, {}).get(from_status, []) def _get_required_fields_for_status(self, status): """Gibt zurück, welche Felder für einen Status required sind""" return self.REQUIRED_FIELDS_BY_STATUS.get(status, []) def clean(self): cleaned_data = super().clean() status = cleaned_data.get("status") if not self.ticket or not status: return cleaned_data # Prüfe Status-Übergang old_status = self.ticket.status is_tutor = self.user == self.ticket.assigned_to is_creator = self.user == self.ticket.created_by is_superuser = self.user.is_superuser # Superuser dürfen alle Übergänge if is_superuser: role = "superuser" elif is_tutor: role = "tutor" elif is_creator: role = "creator" else: role = None if role and not self._is_transition_allowed(old_status, status, role): raise ValidationError( { "status": f'Übergang von "{self.ticket.get_status_display()}" zu "{dict(self.fields["status"].choices)[status]}" ist nicht erlaubt.' } ) # Prüfe required fields für neuen Status required_fields = self._get_required_fields_for_status(status) for field_name in required_fields: if not cleaned_data.get(field_name): field_label = self.fields[field_name].label raise ValidationError( { field_name: f'{field_label} ist erforderlich, wenn der Status auf "{dict(self.fields["status"].choices)[status]}" gesetzt wird.' } ) return cleaned_data def save(self, commit=True): ticket = super().save(commit=False) # Automatische Tutor-Zuweisung if ticket.course and ticket.course.tutor: ticket.assigned_to = ticket.course.tutor # Setze answered_at wenn eine Antwort gegeben wird if ticket.answer and not ticket.answered_at: from django.utils import timezone ticket.answered_at = timezone.now() if commit: ticket.save() return ticket