rinogeek's picture
first commit
fafd0bb
# ============================================
# apps/messaging/models.py - Système Messagerie
# ============================================
from django.db import models
from apps.core.models import TimestampMixin, SoftDeleteMixin, VersionedFieldMixin
from apps.users.models import User
class Conversation(TimestampMixin, SoftDeleteMixin):
"""Conversation entre utilisateurs"""
last_message_at = models.DateTimeField(null=True, blank=True, db_index=True)
class Meta:
db_table = 'conversations'
verbose_name = 'Conversation'
verbose_name_plural = 'Conversations'
ordering = ['-last_message_at']
def __str__(self):
participants = self.participants.filter(is_active=True)
users = [p.user.email for p in participants[:3]]
return f"Conversation: {', '.join(users)}"
class ConversationParticipant(TimestampMixin, SoftDeleteMixin):
"""Participants d'une conversation"""
conversation = models.ForeignKey(Conversation, on_delete=models.CASCADE, related_name='participants')
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='conversation_participations')
joined_at = models.DateTimeField(auto_now_add=True)
left_at = models.DateTimeField(null=True, blank=True)
last_read_at = models.DateTimeField(null=True, blank=True)
class Meta:
db_table = 'conversation_participants'
unique_together = ['conversation', 'user', 'is_active']
indexes = [
models.Index(fields=['user', 'is_active']),
]
def get_unread_count(self):
"""Nombre de messages non lus"""
if not self.last_read_at:
return self.conversation.messages.filter(is_active=True).count()
return self.conversation.messages.filter(
is_active=True,
created_at__gt=self.last_read_at
).exclude(sender=self.user).count()
class Message(TimestampMixin, SoftDeleteMixin):
"""Message dans une conversation"""
conversation = models.ForeignKey(Conversation, on_delete=models.CASCADE, related_name='messages')
sender = models.ForeignKey(User, on_delete=models.CASCADE, related_name='sent_messages')
is_encrypted = models.BooleanField(default=False)
encrypted_keys = models.JSONField(default=dict, blank=True)
is_visible_to_recipient = models.BooleanField(default=False, help_text="Visible seulement pendant un rendez-vous")
class Meta:
db_table = 'messages'
verbose_name = 'Message'
verbose_name_plural = 'Messages'
indexes = [
models.Index(fields=['conversation', '-created_at']),
models.Index(fields=['sender', '-created_at']),
]
ordering = ['created_at']
def __str__(self):
content = self.contents.filter(is_current=True).first()
return f"Message from {self.sender.email}: {content.content[:50] if content else ''}"
class MessageContent(TimestampMixin, VersionedFieldMixin):
"""Contenu du message (éditable)"""
message = models.ForeignKey(Message, on_delete=models.CASCADE, related_name='contents')
content = models.TextField()
class Meta:
db_table = 'message_contents'
class MessageReadStatus(TimestampMixin):
"""Statut de lecture par utilisateur"""
message = models.ForeignKey(Message, on_delete=models.CASCADE, related_name='read_statuses')
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='message_reads')
read_at = models.DateTimeField(auto_now_add=True)
class Meta:
db_table = 'message_read_statuses'
unique_together = ['message', 'user']
class MessageAttachment(TimestampMixin, SoftDeleteMixin):
"""Pièces jointes (optionnel)"""
message = models.ForeignKey(Message, on_delete=models.CASCADE, related_name='attachments')
file_url = models.URLField(max_length=500)
file_name = models.CharField(max_length=255)
file_type = models.CharField(max_length=50)
file_size = models.IntegerField() # en bytes
class Meta:
db_table = 'message_attachments'