furry/chat/models.py

207 lines
7.3 KiB
Python

"""
Chat Models für Live-Chat System
"""
from django.db import models
from django.contrib.auth.models import User
from django.utils import timezone
from django.conf import settings
import uuid
class ChatRoom(models.Model):
"""Chat-Raum für Kunde-Admin Kommunikation"""
ROOM_STATUS_CHOICES = [
('active', 'Aktiv'),
('waiting', 'Wartend'),
('closed', 'Geschlossen'),
('archived', 'Archiviert'),
]
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
customer = models.ForeignKey(User, on_delete=models.CASCADE, related_name='customer_chats')
admin = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True, related_name='admin_chats')
status = models.CharField(max_length=20, choices=ROOM_STATUS_CHOICES, default='waiting')
subject = models.CharField(max_length=200, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
last_message_at = models.DateTimeField(null=True, blank=True)
class Meta:
ordering = ['-last_message_at', '-created_at']
verbose_name = 'Chat-Raum'
verbose_name_plural = 'Chat-Räume'
def __str__(self):
return f"Chat {self.id} - {self.customer.username}"
def get_unread_count(self, user):
"""Anzahl ungelesener Nachrichten für User"""
return self.messages.filter(
sender__in=self.get_other_users(user),
read_at__isnull=True
).count()
def get_other_users(self, user):
"""Andere User im Chat"""
if user == self.customer:
return [self.admin] if self.admin else []
elif user == self.admin:
return [self.customer]
return []
def mark_messages_as_read(self, user):
"""Nachrichten als gelesen markieren"""
other_users = self.get_other_users(user)
self.messages.filter(
sender__in=other_users,
read_at__isnull=True
).update(read_at=timezone.now())
class ChatMessage(models.Model):
"""Chat-Nachricht"""
MESSAGE_TYPE_CHOICES = [
('text', 'Text'),
('image', 'Bild'),
('file', 'Datei'),
('system', 'System'),
]
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
room = models.ForeignKey(ChatRoom, on_delete=models.CASCADE, related_name='messages')
sender = models.ForeignKey(User, on_delete=models.CASCADE, related_name='sent_messages')
message_type = models.CharField(max_length=20, choices=MESSAGE_TYPE_CHOICES, default='text')
content = models.TextField()
file = models.FileField(upload_to='chat_files/', null=True, blank=True)
image = models.ImageField(upload_to='chat_images/', null=True, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
read_at = models.DateTimeField(null=True, blank=True)
is_system_message = models.BooleanField(default=False)
class Meta:
ordering = ['created_at']
verbose_name = 'Chat-Nachricht'
verbose_name_plural = 'Chat-Nachrichten'
def __str__(self):
return f"{self.sender.username}: {self.content[:50]}"
def save(self, *args, **kwargs):
"""Nachricht speichern und Room aktualisieren"""
is_new = self.pk is None
super().save(*args, **kwargs)
if is_new:
# Room last_message_at aktualisieren
self.room.last_message_at = self.created_at
self.room.save(update_fields=['last_message_at'])
class ChatNotification(models.Model):
"""Chat-Benachrichtigungen"""
NOTIFICATION_TYPE_CHOICES = [
('new_message', 'Neue Nachricht'),
('room_assigned', 'Raum zugewiesen'),
('room_closed', 'Raum geschlossen'),
('customer_online', 'Kunde online'),
('customer_offline', 'Kunde offline'),
]
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='chat_notifications')
room = models.ForeignKey(ChatRoom, on_delete=models.CASCADE, related_name='notifications')
notification_type = models.CharField(max_length=20, choices=NOTIFICATION_TYPE_CHOICES)
title = models.CharField(max_length=200)
message = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
read_at = models.DateTimeField(null=True, blank=True)
sent_via_email = models.BooleanField(default=False)
sent_via_push = models.BooleanField(default=False)
class Meta:
ordering = ['-created_at']
verbose_name = 'Chat-Benachrichtigung'
verbose_name_plural = 'Chat-Benachrichtigungen'
def __str__(self):
return f"{self.notification_type}: {self.title}"
class UserOnlineStatus(models.Model):
"""Online-Status von Benutzern"""
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='online_status')
is_online = models.BooleanField(default=False)
last_seen = models.DateTimeField(auto_now=True)
current_room = models.ForeignKey(ChatRoom, on_delete=models.SET_NULL, null=True, blank=True)
class Meta:
verbose_name = 'Online-Status'
verbose_name_plural = 'Online-Status'
def __str__(self):
status = "Online" if self.is_online else "Offline"
return f"{self.user.username} - {status}"
class QuickResponse(models.Model):
"""Schnelle Antworten für Admins"""
category = models.CharField(max_length=50, choices=[
('greeting', 'Begrüßung'),
('pricing', 'Preise'),
('shipping', 'Versand'),
('custom_order', 'Custom Order'),
('technical', 'Technische Fragen'),
('general', 'Allgemein'),
])
title = models.CharField(max_length=100)
content = models.TextField()
created_by = models.ForeignKey(User, on_delete=models.CASCADE, related_name='quick_responses')
created_at = models.DateTimeField(auto_now_add=True)
is_active = models.BooleanField(default=True)
use_count = models.IntegerField(default=0)
class Meta:
ordering = ['category', 'title']
verbose_name = 'Schnelle Antwort'
verbose_name_plural = 'Schnelle Antworten'
def __str__(self):
return f"{self.category}: {self.title}"
def increment_use_count(self):
"""Verwendungszähler erhöhen"""
self.use_count += 1
self.save(update_fields=['use_count'])
class ChatAnalytics(models.Model):
"""Chat-Analytics für Performance-Tracking"""
date = models.DateField()
total_messages = models.IntegerField(default=0)
total_rooms = models.IntegerField(default=0)
active_rooms = models.IntegerField(default=0)
avg_response_time = models.FloatField(default=0) # in Sekunden
customer_satisfaction = models.FloatField(default=0) # 0-5 Sterne
total_duration = models.FloatField(default=0) # in Minuten
class Meta:
unique_together = ['date']
verbose_name = 'Chat-Analytics'
verbose_name_plural = 'Chat-Analytics'
def __str__(self):
return f"Chat Analytics - {self.date}"
@classmethod
def get_or_create_today(cls):
"""Heutige Analytics erstellen oder abrufen"""
today = timezone.now().date()
analytics, created = cls.objects.get_or_create(date=today)
return analytics