from django import forms from .models import Comment, Ticket from django.core.exceptions import ValidationError 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': [], } } # 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) # 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""" if self.ticket.status == 'resolved' and is_creator and not is_superuser: for field_name in self.fields: if field_name == "answer": self.fields[field_name].disabled = True elif is_tutor and not is_superuser: # 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 not is_superuser 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): """Beschränkt verfügbare Status-Optionen basierend auf der zentralen Logik""" current_status = self.ticket.status if 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 if 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