feat: add ticket comments attachments and export

This commit is contained in:
hailin
2026-06-30 18:42:04 +08:00
parent c293e3f56a
commit f8298632b6
3 changed files with 154 additions and 2 deletions

View File

@@ -1,10 +1,23 @@
import csv
from django.contrib.auth import get_user_model
from django.db.models import Q
from django.http import HttpResponse
from django.utils import timezone
from ninja import Router
from apps.tickets.models import Ticket, TicketEvent
from apps.tickets.schemas import TicketIn, TicketOut, TicketStatusIn, TicketUpdateIn
from apps.audit.models import OperationAuditLog
from apps.tickets.models import Ticket, TicketAttachment, TicketComment, TicketEvent
from apps.tickets.schemas import (
TicketAttachmentIn,
TicketAttachmentOut,
TicketCommentIn,
TicketCommentOut,
TicketIn,
TicketOut,
TicketStatusIn,
TicketUpdateIn,
)
from apps.tickets.services import transition_ticket
router = Router(tags=["tickets"])
@@ -50,6 +63,33 @@ def list_tickets(request, status: str | None = None, q: str | None = None):
return queryset[:100]
@router.get("/export")
def export_tickets(request):
response = HttpResponse(content_type="text/csv")
response["Content-Disposition"] = 'attachment; filename="tickets.csv"'
writer = csv.writer(response)
writer.writerow(["ticket_no", "title", "status", "priority", "created_at"])
for ticket in Ticket.objects.all().order_by("ticket_no"):
writer.writerow(
[
ticket.ticket_no,
ticket.title,
ticket.status,
ticket.priority,
ticket.created_at.isoformat(),
]
)
OperationAuditLog.objects.create(
user=request.user if request.user.is_authenticated else None,
module="tickets",
action="export",
target_type="ticket",
result="success",
request_snapshot={},
)
return response
@router.get("/{ticket_id}", response=TicketOut)
def get_ticket(request, ticket_id: int):
return Ticket.objects.get(id=ticket_id)
@@ -91,3 +131,34 @@ def update_ticket_status(request, ticket_id: int, payload: TicketStatusIn):
payload.remark,
request.user if request.user.is_authenticated else None,
)
@router.post("/{ticket_id}/comments", response=TicketCommentOut)
def add_ticket_comment(request, ticket_id: int, payload: TicketCommentIn):
ticket = Ticket.objects.get(id=ticket_id)
comment = TicketComment.objects.create(
ticket=ticket,
content=payload.content,
comment_type=payload.comment_type,
visibility=payload.visibility,
created_by=request.user if request.user.is_authenticated else None,
)
TicketEvent.objects.create(
ticket=ticket,
event_type="commented",
to_value={"comment_id": comment.id, "comment_type": comment.comment_type},
operator=request.user if request.user.is_authenticated else None,
)
return comment
@router.post("/{ticket_id}/attachments", response=TicketAttachmentOut)
def add_ticket_attachment(request, ticket_id: int, payload: TicketAttachmentIn):
ticket = Ticket.objects.get(id=ticket_id)
attachment = TicketAttachment.objects.create(ticket=ticket, **payload.dict())
TicketEvent.objects.create(
ticket=ticket,
event_type="attachment_added",
to_value={"attachment_id": attachment.id, "file_name": attachment.file_name},
)
return attachment