Files
thrilltrack-explorer/django-backend/apps/contact/models.py

136 lines
4.0 KiB
Python

"""
Contact submission models for user inquiries and support tickets.
"""
import uuid
import pghistory
from django.db import models
from django.utils import timezone
@pghistory.track()
class ContactSubmission(models.Model):
"""
User-submitted contact form messages and support tickets.
Tracks all communication from users for admin follow-up.
"""
STATUS_CHOICES = [
('pending', 'Pending Review'),
('in_progress', 'In Progress'),
('resolved', 'Resolved'),
('archived', 'Archived'),
]
CATEGORY_CHOICES = [
('general', 'General Inquiry'),
('bug', 'Bug Report'),
('feature', 'Feature Request'),
('abuse', 'Report Abuse'),
('data', 'Data Correction'),
('account', 'Account Issue'),
('other', 'Other'),
]
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
# Contact Information
name = models.CharField(max_length=255)
email = models.EmailField()
subject = models.CharField(max_length=255)
message = models.TextField()
category = models.CharField(
max_length=50,
choices=CATEGORY_CHOICES,
default='general'
)
# Status & Assignment
status = models.CharField(
max_length=20,
choices=STATUS_CHOICES,
default='pending',
db_index=True
)
ticket_number = models.CharField(
max_length=20,
unique=True,
null=True,
blank=True,
help_text="Auto-generated ticket number for tracking"
)
# User Association (if logged in when submitting)
user = models.ForeignKey(
'users.User',
null=True,
blank=True,
on_delete=models.SET_NULL,
related_name='contact_submissions'
)
# Assignment & Resolution
assigned_to = models.ForeignKey(
'users.User',
null=True,
blank=True,
on_delete=models.SET_NULL,
related_name='assigned_contacts'
)
admin_notes = models.TextField(
null=True,
blank=True,
help_text="Internal notes for admin use only"
)
resolved_at = models.DateTimeField(null=True, blank=True)
resolved_by = models.ForeignKey(
'users.User',
null=True,
blank=True,
on_delete=models.SET_NULL,
related_name='resolved_contacts'
)
# Timestamps
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
verbose_name = 'Contact Submission'
verbose_name_plural = 'Contact Submissions'
ordering = ['-created_at']
indexes = [
models.Index(fields=['status', '-created_at']),
models.Index(fields=['category', '-created_at']),
models.Index(fields=['ticket_number']),
]
def __str__(self):
ticket = f" ({self.ticket_number})" if self.ticket_number else ""
return f"{self.name} - {self.get_category_display()}{ticket}"
def save(self, *args, **kwargs):
# Auto-generate ticket number if not set
if not self.ticket_number:
# Format: CONT-YYYYMMDD-XXXX
from django.db.models import Max
today = timezone.now().strftime('%Y%m%d')
prefix = f"CONT-{today}"
# Get the highest ticket number for today
last_ticket = ContactSubmission.objects.filter(
ticket_number__startswith=prefix
).aggregate(Max('ticket_number'))['ticket_number__max']
if last_ticket:
# Extract the sequence number and increment
seq = int(last_ticket.split('-')[-1]) + 1
else:
seq = 1
self.ticket_number = f"{prefix}-{seq:04d}"
# Set resolved_at when status changes to resolved
if self.status == 'resolved' and not self.resolved_at:
self.resolved_at = timezone.now()
super().save(*args, **kwargs)