140 lines
5.1 KiB
Python
140 lines
5.1 KiB
Python
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):
|
|
class Meta:
|
|
model = Ticket
|
|
fields = ["title", "description", "status", "priority", "course", "answer", "material"]
|
|
widgets = {
|
|
'answer': forms.Textarea(attrs={
|
|
'rows': 4,
|
|
'placeholder': 'Beschreibe die Lösung des Problems...'
|
|
})
|
|
}
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
# User und ticket aus kwargs holen (werden von der View übergeben)
|
|
self.user = kwargs.pop('user', None)
|
|
self.ticket = kwargs.pop('ticket', None)
|
|
super().__init__(*args, **kwargs)
|
|
|
|
# Status-Choices basierend auf aktueller Situation einschränken
|
|
if self.ticket and self.user:
|
|
self._limit_status_choices()
|
|
self._set_field_permissions()
|
|
|
|
def _set_field_permissions(self):
|
|
"""Setzt welche Felder bearbeitet werden dürfen"""
|
|
is_creator = self.user == self.ticket.created_by
|
|
is_tutor = self.user == self.ticket.assigned_to
|
|
is_superuser = self.user.is_superuser
|
|
|
|
if is_tutor and not is_superuser:
|
|
# Tutor darf nur Status und Answer ändern
|
|
readonly_fields = ['title', 'description', 'course', 'priority']
|
|
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:
|
|
# Ersteller darf gar nichts ändern
|
|
for field_name in self.fields:
|
|
self.fields[field_name].disabled = True
|
|
|
|
def _limit_status_choices(self):
|
|
"""Beschränkt die verfügbaren Status-Optionen basierend auf Rolle und aktuellem Status"""
|
|
current_status = self.ticket.status
|
|
is_creator = self.user == self.ticket.created_by
|
|
is_tutor = self.user == self.ticket.assigned_to
|
|
|
|
# Alle möglichen Status
|
|
all_choices = list(self.fields['status'].choices)
|
|
allowed_choices = []
|
|
|
|
if is_tutor:
|
|
if current_status == 'new':
|
|
allowed_choices = ['new', 'in_progress']
|
|
elif current_status == 'in_progress':
|
|
allowed_choices = ['in_progress', 'resolved', 'new']
|
|
elif current_status == 'resolved':
|
|
allowed_choices = ['resolved', 'closed']
|
|
elif current_status == 'closed':
|
|
allowed_choices = ['closed']
|
|
else:
|
|
# Nicht-Tutoren sehen nur aktuellen Status
|
|
allowed_choices = [current_status]
|
|
|
|
# Filtern der erlaubten Choices
|
|
self.fields['status'].choices = [
|
|
choice for choice in all_choices
|
|
if choice[0] in allowed_choices
|
|
]
|
|
|
|
def clean(self):
|
|
cleaned_data = super().clean()
|
|
status = cleaned_data.get('status')
|
|
answer = cleaned_data.get('answer')
|
|
|
|
# Wenn Status auf "resolved" gesetzt wird, muss eine Antwort vorhanden sein
|
|
if status == 'resolved' and not answer:
|
|
raise ValidationError({
|
|
'answer': 'Eine Antwort ist erforderlich, wenn der Status auf "Gelöst" gesetzt wird.'
|
|
})
|
|
|
|
# Zusätzliche Validierung: Status-Übergang erlaubt?
|
|
if self.ticket and status:
|
|
old_status = self.ticket.status
|
|
if not self._is_status_transition_allowed(old_status, status):
|
|
raise ValidationError({
|
|
'status': f'Übergang von "{self.ticket.get_status_display()}" zu "{dict(self.fields["status"].choices)[status]}" ist nicht erlaubt.'
|
|
})
|
|
|
|
return cleaned_data
|
|
|
|
def _is_status_transition_allowed(self, old_status, new_status):
|
|
"""Prüft ob ein Status-Übergang erlaubt ist"""
|
|
if old_status == new_status:
|
|
return True
|
|
|
|
is_tutor = self.user == self.ticket.assigned_to
|
|
|
|
# Erlaubte Übergänge für Tutoren
|
|
allowed_transitions = {
|
|
'new': ['in_progress'],
|
|
'in_progress': ['resolved', 'new'],
|
|
'resolved': ['closed'],
|
|
'closed': [] # Keine Änderung von closed
|
|
}
|
|
|
|
if is_tutor and old_status in allowed_transitions:
|
|
return new_status in allowed_transitions[old_status]
|
|
|
|
return False
|
|
|
|
def save(self, commit=True):
|
|
ticket = super().save(commit=False)
|
|
|
|
# Automatische Tutor-Zuweisung basierend auf dem ausgewählten Kurs
|
|
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 |