Spaces:
Sleeping
Sleeping
| # ============================================ | |
| # 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' | |