from django.views.generic import ListView, TemplateView from django.views.generic.edit import CreateView, UpdateView from django.urls import reverse_lazy from django.views.generic.detail import DetailView from django.views.generic.edit import FormMixin from .forms import CommentForm from django.urls import reverse from django.contrib.auth.mixins import LoginRequiredMixin from django.contrib import messages from django.shortcuts import redirect from django.db.models import Q from .models import Ticket, TicketHistory class HomeView(TemplateView): template_name = "ticketsystem/home.html" class TicketListView(ListView): model = Ticket template_name = "ticketsystem/index.html" context_object_name = "tickets" ordering = ["-created_at"] paginate_by = 10 def get_queryset(self): queryset = super().get_queryset() status = self.request.GET.get("status") query = self.request.GET.get("q") if status: queryset = queryset.filter(status=status) if query: queryset = queryset.filter( Q(title__icontains=query) | Q(description__icontains=query) ) return queryset def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) context["selected_status"] = self.request.GET.get("status", "") context["search_query"] = self.request.GET.get("q", "") return context class TicketDetailUpdateView(UpdateView): model = Ticket fields = ["title", "description", "status", "priority", "assigned_to"] template_name = "ticketsystem/detail.html" comment_form_class = CommentForm def get_success_url(self): return reverse('detail-update', kwargs={'pk': self.object.pk}) def dispatch(self, request, *args, **kwargs): self.ticket = self.get_object() user = request.user # Prüfen, ob User bearbeiten darf self.can_edit = (user == self.ticket.assigned_to) or user.is_superuser return super().dispatch(request, *args, **kwargs) def get_form(self, form_class=None): form = super().get_form(form_class) if not self.can_edit: for field in form.fields: form.fields[field].disabled = True # Felder lesbar, aber nicht änderbar return form def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) # Kommentarformular hinzufügen if 'comment_form' not in context: context['comment_form'] = self.comment_form_class() return context def form_valid(self, form): ticket = form.instance original = Ticket.objects.get(pk=ticket.pk) response = super().form_valid(form) # Speichert das Ticket # History tracking für geänderte Felder tracked_fields = ["title", "description", "status", "priority", "assigned_to"] for field in tracked_fields: if field in form.changed_data: old_value = getattr(original, field) new_value = form.cleaned_data.get(field) # Für ForeignKey Felder den Display-Namen verwenden if field == "assigned_to": old_value = old_value.username if old_value else "Niemand" new_value = new_value.username if new_value else "Niemand" elif field == "status": old_value = original.get_status_display() new_value = ticket.get_status_display() elif field == "priority": old_value = original.get_priority_display() new_value = ticket.get_priority_display() TicketHistory.objects.create( ticket=ticket, changed_by=self.request.user, field=field, old_value=str(old_value), new_value=str(new_value), ) if form.changed_data: messages.success(self.request, f"Ticket erfolgreich aktualisiert. Geänderte Felder: {', '.join(form.changed_data)}") return response def post(self, request, *args, **kwargs): self.object = self.get_object() # Wichtig: object setzen für beide Fälle if 'comment_submit' in request.POST: # Kommentar absenden comment_form = self.comment_form_class(request.POST) if comment_form.is_valid(): comment = comment_form.save(commit=False) comment.ticket = self.object comment.author = request.user comment.save() messages.success(request, "Kommentar hinzugefügt.") return redirect(self.get_success_url()) else: # Kommentarformular fehlerhaft: Seite neu laden mit Fehlern context = self.get_context_data(comment_form=comment_form) return self.render_to_response(context) else: # Ticket bearbeiten (UpdateView standard) if not self.can_edit: messages.error(request, "⛔ Du darfst dieses Ticket nicht bearbeiten.") return redirect(self.get_success_url()) return super().post(request, *args, **kwargs) class AssignedTicketListView(LoginRequiredMixin, ListView): model = Ticket template_name = "ticketsystem/assigned_tickets.html" context_object_name = "tickets" ordering = ["-created_at"] def get_queryset(self): return Ticket.objects.filter( assigned_to=self.request.user ).exclude(status="closed") # oder "geschlossen", je nach Wahl class TicketCreateView(CreateView): model = Ticket fields = [ "title", "description", "priority", "assigned_to", ] # user & status wird automatisch gesetzt template_name = "ticketsystem/ticket_form.html" success_url = reverse_lazy("ticket-list") def form_valid(self, form): form.instance.created_by = ( self.request.user ) # Der angemeldete User wird automatisch gesetzt form.instance.status = "open" # Neues Ticket beginnt immer als "offen" return super().form_valid(form) class TicketUpdateView(LoginRequiredMixin, UpdateView): model = Ticket fields = ["title", "description", "status", "priority", "assigned_to"] template_name = "ticketsystem/ticket_form.html" def dispatch(self, request, *args, **kwargs): ticket = self.get_object() user = request.user if user != ticket.assigned_to and not user.is_staff: messages.error(request, "⛔ Du darfst dieses Ticket nicht bearbeiten.") return redirect("detail", pk=ticket.pk) return super().dispatch(request, *args, **kwargs) def get_queryset(self): return Ticket.objects.all() # Optional: Nur eigene Tickets bearbeiten lassen? def form_valid(self, form): ticket = form.instance original = Ticket.objects.get(pk=ticket.pk) response = super().form_valid(form) # Speichert das Ticket tracked_fields = ["status", "description", "priority"] for field in tracked_fields: if field in form.changed_data: old_value = getattr(original, field) new_value = form.cleaned_data.get(field) TicketHistory.objects.create( ticket=ticket, changed_by=self.request.user, field=field, old_value=str(old_value), new_value=str(new_value), ) return response def get_success_url(self): return reverse_lazy("detail", kwargs={"pk": self.object.pk})