161 lines
5.9 KiB
Python
161 lines
5.9 KiB
Python
from django.contrib import messages
|
|
from django.db.models import Count, Q
|
|
from django.shortcuts import get_object_or_404, redirect, render
|
|
|
|
from .forms import ReplyForm, TicketForm, TicketTriageForm
|
|
from .models import Ticket
|
|
|
|
|
|
def _ticket_stats():
|
|
return {
|
|
"total": Ticket.objects.count(),
|
|
"open": Ticket.objects.exclude(status=Ticket.Status.RESOLVED).count(),
|
|
"triage": Ticket.objects.filter(status=Ticket.Status.TRIAGE).count(),
|
|
"resolved": Ticket.objects.filter(status=Ticket.Status.RESOLVED).count(),
|
|
}
|
|
|
|
|
|
def home(request):
|
|
"""Render the branded support center landing page and quick ticket intake."""
|
|
if request.method == "POST":
|
|
ticket_form = TicketForm(request.POST)
|
|
if ticket_form.is_valid():
|
|
ticket = ticket_form.save()
|
|
messages.success(request, "Ticket submitted. Your support thread is ready.")
|
|
return redirect("ticket_success", public_id=ticket.public_id)
|
|
else:
|
|
ticket_form = TicketForm()
|
|
|
|
status_counts = dict(
|
|
Ticket.objects.values_list("status").annotate(total=Count("id"))
|
|
)
|
|
recent_tickets = Ticket.objects.select_related("assigned_to")[:5]
|
|
|
|
context = {
|
|
"project_name": "RelayDesk",
|
|
"page_description": "A lightweight support center for ticket submission, triage, threaded replies, and status tracking.",
|
|
"ticket_form": ticket_form,
|
|
"stats": _ticket_stats(),
|
|
"status_choices": Ticket.Status.choices,
|
|
"status_counts": status_counts,
|
|
"recent_tickets": recent_tickets,
|
|
}
|
|
return render(request, "core/index.html", context)
|
|
|
|
|
|
def ticket_create(request):
|
|
if request.method == "POST":
|
|
form = TicketForm(request.POST)
|
|
if form.is_valid():
|
|
ticket = form.save()
|
|
messages.success(request, "Ticket submitted. We created a trackable support thread for you.")
|
|
return redirect("ticket_success", public_id=ticket.public_id)
|
|
else:
|
|
form = TicketForm()
|
|
|
|
return render(
|
|
request,
|
|
"core/ticket_form.html",
|
|
{
|
|
"form": form,
|
|
"project_name": "RelayDesk",
|
|
"page_description": "Submit a support ticket with category, priority, and details.",
|
|
},
|
|
)
|
|
|
|
|
|
def ticket_success(request, public_id):
|
|
ticket = get_object_or_404(Ticket.objects.select_related("assigned_to"), public_id=public_id)
|
|
return render(
|
|
request,
|
|
"core/ticket_success.html",
|
|
{
|
|
"ticket": ticket,
|
|
"project_name": "RelayDesk",
|
|
"page_description": f"Confirmation for support ticket {ticket.ticket_number}.",
|
|
},
|
|
)
|
|
|
|
|
|
def ticket_list(request):
|
|
tickets = Ticket.objects.select_related("assigned_to").annotate(reply_count=Count("replies"))
|
|
query = request.GET.get("q", "").strip()
|
|
status = request.GET.get("status", "").strip()
|
|
priority = request.GET.get("priority", "").strip()
|
|
category = request.GET.get("category", "").strip()
|
|
|
|
if query:
|
|
tickets = tickets.filter(
|
|
Q(subject__icontains=query)
|
|
| Q(description__icontains=query)
|
|
| Q(requester_name__icontains=query)
|
|
| Q(requester_email__icontains=query)
|
|
)
|
|
if status in Ticket.Status.values:
|
|
tickets = tickets.filter(status=status)
|
|
if priority in Ticket.Priority.values:
|
|
tickets = tickets.filter(priority=priority)
|
|
if category in Ticket.Category.values:
|
|
tickets = tickets.filter(category=category)
|
|
|
|
context = {
|
|
"project_name": "RelayDesk",
|
|
"page_description": "Search, filter, and triage support tickets.",
|
|
"tickets": tickets,
|
|
"stats": _ticket_stats(),
|
|
"query": query,
|
|
"selected_status": status,
|
|
"selected_priority": priority,
|
|
"selected_category": category,
|
|
"status_choices": Ticket.Status.choices,
|
|
"priority_choices": Ticket.Priority.choices,
|
|
"category_choices": Ticket.Category.choices,
|
|
}
|
|
return render(request, "core/ticket_list.html", context)
|
|
|
|
|
|
def ticket_detail(request, public_id):
|
|
ticket = get_object_or_404(
|
|
Ticket.objects.select_related("assigned_to").prefetch_related("replies"),
|
|
public_id=public_id,
|
|
)
|
|
reply_form = ReplyForm(
|
|
initial={
|
|
"author_name": request.user.get_full_name() or request.user.get_username() if request.user.is_authenticated else "",
|
|
"author_email": request.user.email if request.user.is_authenticated else "",
|
|
}
|
|
)
|
|
triage_form = TicketTriageForm(instance=ticket)
|
|
|
|
if request.method == "POST" and "reply_submit" in request.POST:
|
|
reply_form = ReplyForm(request.POST)
|
|
if reply_form.is_valid():
|
|
reply = reply_form.save(commit=False)
|
|
reply.ticket = ticket
|
|
if request.user.is_authenticated:
|
|
reply.author_user = request.user
|
|
reply.is_staff_reply = request.user.is_staff
|
|
if not reply.author_name:
|
|
reply.author_name = request.user.get_full_name() or request.user.get_username()
|
|
if not reply.author_email:
|
|
reply.author_email = request.user.email
|
|
reply.save()
|
|
messages.success(request, "Reply added to the ticket thread.")
|
|
return redirect("ticket_detail", public_id=ticket.public_id)
|
|
|
|
if request.method == "POST" and "triage_submit" in request.POST and request.user.is_staff:
|
|
triage_form = TicketTriageForm(request.POST, instance=ticket)
|
|
if triage_form.is_valid():
|
|
triage_form.save()
|
|
messages.success(request, "Ticket triage fields updated.")
|
|
return redirect("ticket_detail", public_id=ticket.public_id)
|
|
|
|
context = {
|
|
"project_name": "RelayDesk",
|
|
"page_description": f"Ticket thread and status for {ticket.ticket_number}.",
|
|
"ticket": ticket,
|
|
"reply_form": reply_form,
|
|
"triage_form": triage_form,
|
|
}
|
|
return render(request, "core/ticket_detail.html", context)
|