from django.db import models from osinacore.models import * from billing.models import * from django.shortcuts import get_object_or_404 from django.core.mail import send_mail from django.template.loader import render_to_string from django.utils.html import strip_tags from django.conf import settings from django.db.models.signals import post_save from django.dispatch import receiver from threading import Timer from datetime import time def send_ticket(ticket_id): ticket = get_object_or_404(Ticket, id=ticket_id) department = TicketDepartment.objects.filter(ticket=ticket).last().department staff_profiles = department.get_staff() for staff in staff_profiles: subject = f"New Ticket Opened: {ticket.title}" html_message = render_to_string('email_templates/new-ticket.html', { 'ticket': ticket, 'user': staff.user }) plain_message = strip_tags(html_message) from_email = settings.DEFAULT_FROM_EMAIL to_email = staff.user.email send_mail(subject, plain_message, from_email, [to_email], html_message=html_message) customer = ticket.customer subject = f"New Ticket Opened: {ticket.title}" html_message = render_to_string('email_templates/new-ticket.html', { 'ticket': ticket, 'user': customer.user }) plain_message = strip_tags(html_message) from_email = settings.DEFAULT_FROM_EMAIL to_email = customer.user.email send_mail(subject, plain_message, from_email, [to_email], html_message=html_message) def send_update(update_id): update = get_object_or_404(TicketUpdate, id=update_id) if TicketDepartment.objects.filter(ticket=update.ticket): department = TicketDepartment.objects.filter(ticket=update.ticket).last().department else: department = Department.objects.get(name='Support') if department: staff_profiles = department.get_staff() print(staff_profiles) for staff in staff_profiles: subject = f"New Ticket Update: {update.ticket.title}" html_message = render_to_string('email_templates/new-ticket-update.html', { 'update': update, 'user': staff.user }) plain_message = strip_tags(html_message) from_email = settings.DEFAULT_FROM_EMAIL to_email = staff.user.email send_mail(subject, plain_message, from_email, [to_email], html_message=html_message) customer = update.ticket.customer if customer: subject = f"New Ticket Update: {update.ticket.title}" html_message = render_to_string('email_templates/new-ticket-update.html', { 'update': update, 'user': customer.user }) plain_message = strip_tags(html_message) from_email = settings.DEFAULT_FROM_EMAIL to_email = customer.user.email send_mail(subject, plain_message, from_email, [to_email], html_message=html_message) # Create your models here. class Ticket(models.Model): REGARDING_CHOICES = ( ('General/Account/Billing', 'General/Account/Billing'), ('Project/Product', 'Project/Product'), ) ticket_number = models.CharField(max_length=400, blank=True) title = models.CharField(max_length=400) description = models.TextField(null=True, blank=True) regarding = models.CharField(max_length=50, choices=REGARDING_CHOICES, null=True) project = models.ForeignKey(Project, on_delete=models.SET_NULL, blank=True, null=True) product = models.ForeignKey(Item, on_delete=models.SET_NULL, blank=True, null=True) opened_by = models.ForeignKey(User, on_delete=models.SET_NULL, null=True) opened_date = models.DateField(null=True, blank=True) customer = models.ForeignKey(CustomerProfile, on_delete=models.SET_NULL, null=True) def save(self, *args, **kwargs): if not self.ticket_number: last_ticket = Ticket.objects.filter(opened_date__year=timezone.now().year).order_by('-ticket_number').first() if last_ticket and last_ticket.ticket_number: last_ticket_number = int(last_ticket.ticket_number[-4:]) new_ticket_number = last_ticket_number + 1 else: new_ticket_number = 1 current_year_last_two_digits = str(timezone.now().year)[-2:] self.ticket_number = f"{current_year_last_two_digits}{new_ticket_number:04}" super().save(*args, **kwargs) def get_customer_last_seen(self): connections = TicketConnection.objects.filter(user=self.customer.user).order_by('-date') if not connections.exists(): return "Not seen yet" last_connection = connections.first() if not last_connection.terminated: return "Online" last_seen_time = last_connection.date now = timezone.now() time_diff = now - last_seen_time if time_diff < timedelta(days=1): if last_seen_time.date() == now.date(): return f"last seen today at {last_seen_time.strftime('%I:%M %p')}" else: return f"last seen yesterday at {last_seen_time.strftime('%I:%M %p')}" else: return f"last seen on {last_seen_time.strftime('%b %d at %I:%M %p')}" def get_all_ticket_staff(self): ticket_staff = TicketStaff.objects.filter(ticket=self) staff_members = [entry.staff for entry in ticket_staff] latest_department = TicketDepartment.objects.filter(ticket=self).order_by('-date_added').first() if latest_department: department_staff = latest_department.department.get_staff() else: department_staff = [] all_staff = list(staff_members) + list(department_staff) return all_staff @receiver(post_save, sender=Ticket) def send_signal_on_save(sender, instance, created, **kwargs): if created: def send_after_delay(): send_ticket(instance.id) timer = Timer(10, send_after_delay) timer.start() class TicketDepartment(models.Model): department = models.ForeignKey(Department, on_delete=models.CASCADE) ticket = models.ForeignKey(Ticket, on_delete=models.CASCADE) date_added = models.DateTimeField() class TicketStaff(models.Model): staff = models.ForeignKey(StaffProfile, on_delete=models.CASCADE) ticket = models.ForeignKey(Ticket, on_delete=models.CASCADE) date_added = models.DateTimeField() def get_last_seen(self): connections = TicketConnection.objects.filter(user=self.staff.user).order_by('-date') if not connections.exists(): return "Not seen yet" last_connection = connections.first() if not last_connection.terminated: return "Online" last_seen_time = last_connection.date now = timezone.now() time_diff = now - last_seen_time if time_diff < timedelta(days=1): if last_seen_time.date() == now.date(): return f"last seen today at {last_seen_time.strftime('%I:%M %p')}" else: return f"last seen yesterday at {last_seen_time.strftime('%I:%M %p')}" else: return f"last seen on {last_seen_time.strftime('%b %d at %I:%M %p')}" class TicketStatus(models.Model): STATUS_CHOICES = ( ('Open', 'Open'), ('Working On', 'Working On'), ('Closed', 'Closed'), ) ticket = models.ForeignKey(Ticket, on_delete=models.CASCADE) status = models.CharField(max_length=50, choices=STATUS_CHOICES, null=True) added_by = models.ForeignKey(User, on_delete=models.SET_NULL, null=True) date_added = models.DateTimeField() class TicketTask(models.Model): ticket = models.ForeignKey(Ticket, on_delete=models.CASCADE) task = models.ForeignKey(Task, on_delete=models.CASCADE) class TicketConnection(models.Model): ticket = models.ForeignKey(Ticket, on_delete=models.CASCADE) user = models.ForeignKey(User, on_delete=models.CASCADE) date = models.DateTimeField() terminated = models.BooleanField(default=False) class TicketUpdate(models.Model): ticket = models.ForeignKey(Ticket, on_delete=models.CASCADE) description = models.TextField(null=True, blank=True) added_by = models.ForeignKey(User, on_delete=models.SET_NULL, null=True) date_added = models.DateTimeField() @receiver(post_save, sender=TicketUpdate) def send_signal_on_save(sender, instance, created, **kwargs): if created: def send_after_delay(): send_update(instance.id) timer = Timer(10, send_after_delay) timer.start() class TicketRead(models.Model): ticket_update = models.ForeignKey(TicketUpdate, on_delete=models.CASCADE) user = models.ForeignKey(User, on_delete=models.CASCADE) read = models.BooleanField(default=False) class TicketAttachment(models.Model): ticket = models.ForeignKey(Ticket, on_delete=models.CASCADE, null=True, blank=True) ticket_update = models.ForeignKey(TicketUpdate, on_delete=models.CASCADE, null=True, blank=True) file_path = models.CharField(max_length=255, null=True) class TicketUpdateReaction(models.Model): REACTION_CHOICES = ( ('Happy', 'Happy'), ('Indifferent', 'Indifferent'), ('Sad', 'Sad'), ) customer = models.ForeignKey(User, on_delete=models.CASCADE, null=True) reaction = models.CharField(max_length=50, choices=REACTION_CHOICES, null=True) ticket_update = models.ForeignKey(TicketUpdate, on_delete=models.CASCADE)