share ticket and ticket message

This commit is contained in:
javad committed 2026-10-04 16:42:19 +03:30
1 parent 39e64854b8
commit 79fe1cddbb
35 files changed
+1742 -95

No files matched your search

+39 -1
View File
@@ -128,13 +128,51 @@ class Ticket(PersianTextNormalizationMixin, PublicIdModel, TimeStampedModel):
profile=getattr(expert,"staff_profile",None) if expert else None
return getattr(profile,"display_name","") or "صف عمومی"
class TicketAccessGrant(models.Model):
note = models.CharField(max_length=500, blank=True)
first_viewed_at = models.DateTimeField(null=True, blank=True)
last_viewed_at = models.DateTimeField(null=True, blank=True)
view_count = models.PositiveIntegerField(default=0)
revoked_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.PROTECT, null=True, blank=True, related_name="revoked_ticket_grants")
class Level(models.TextChoices): VIEW_ONLY="VIEW_ONLY","فقط مشاهده"; REPLY="REPLY","پاسخ"; FULL="FULL","کامل"
ticket=models.ForeignKey(Ticket,on_delete=models.CASCADE,related_name="access_grants"); user=models.ForeignKey(settings.AUTH_USER_MODEL,on_delete=models.CASCADE,related_name="ticket_grants"); granted_by=models.ForeignKey(settings.AUTH_USER_MODEL,on_delete=models.PROTECT,related_name="granted_ticket_access"); permission_level=models.CharField(max_length=15,choices=Level.choices,default=Level.FULL); created_at=models.DateTimeField(auto_now_add=True); revoked_at=models.DateTimeField(null=True,blank=True)
class Meta:
constraints=[models.UniqueConstraint(fields=["ticket","user"],condition=Q(revoked_at__isnull=True),name="unique_active_ticket_grant")]
class TicketEvent(models.Model):
class Type(models.TextChoices): CREATED="CREATED","ایجاد"; CLAIMED="CLAIMED","برداشت"; TRANSFERRED="TRANSFERRED","انتقال"; SHARED="SHARED","اشتراک"; ACCESS_REVOKED="ACCESS_REVOKED","لغو دسترسی"; STATUS_CHANGED="STATUS_CHANGED","تغییر وضعیت"; PRIORITY_CHANGED="PRIORITY_CHANGED","تغییر اولویت"; REOPENED="REOPENED","بازگشایی"; RESOLVED="RESOLVED","حل"; CLOSED="CLOSED","بستن"
class Type(models.TextChoices):
CREATED="CREATED","ایجاد"
CLAIMED="CLAIMED","برداشت"
TRANSFERRED="TRANSFERRED","انتقال"
SHARED="SHARED","اشتراک تیکت"
ACCESS_REVOKED="ACCESS_REVOKED","لغو دسترسی تیکت"
SHARE_OPENED="SHARE_OPENED","مشاهده تیکت اشتراکی"
MESSAGE_SHARED="MESSAGE_SHARED","اشتراک یک پیام"
MESSAGE_SHARE_REVOKED="MESSAGE_SHARE_REVOKED","لغو اشتراک پیام"
MESSAGE_SHARE_OPENED="MESSAGE_SHARE_OPENED","مشاهده پیام اشتراکی"
STATUS_CHANGED="STATUS_CHANGED","تغییر وضعیت"
PRIORITY_CHANGED="PRIORITY_CHANGED","تغییر اولویت"
REOPENED="REOPENED","بازگشایی"
RESOLVED="RESOLVED","حل"
CLOSED="CLOSED","بستن"
ticket=models.ForeignKey(Ticket,on_delete=models.CASCADE,related_name="events"); event_type=models.CharField(max_length=30,choices=Type.choices); actor=models.ForeignKey(settings.AUTH_USER_MODEL,on_delete=models.PROTECT,null=True); metadata=models.JSONField(default=dict,blank=True); created_at=models.DateTimeField(auto_now_add=True)
class MessageShare(PublicIdModel, models.Model):
"""A staff-only grant to one message; never confers ticket access."""
message = models.ForeignKey("messaging.Message", on_delete=models.CASCADE, related_name="staff_shares")
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="received_message_shares")
granted_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.PROTECT, related_name="sent_message_shares")
note = models.CharField(max_length=500, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
first_viewed_at = models.DateTimeField(null=True, blank=True)
last_viewed_at = models.DateTimeField(null=True, blank=True)
view_count = models.PositiveIntegerField(default=0)
revoked_at = models.DateTimeField(null=True, blank=True)
revoked_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.PROTECT, null=True, blank=True, related_name="revoked_message_shares")
class Meta:
ordering = ["-created_at", "-pk"]
constraints = [models.UniqueConstraint(fields=["message", "user"], condition=Q(revoked_at__isnull=True), name="unique_active_message_share")]
class TicketReadState(models.Model):
ticket=models.ForeignKey(Ticket,on_delete=models.CASCADE,related_name="read_states"); user=models.ForeignKey(settings.AUTH_USER_MODEL,on_delete=models.CASCADE); last_read_at=models.DateTimeField(); last_read_message=models.ForeignKey("messaging.Message",on_delete=models.SET_NULL,null=True,blank=True)
class Meta: constraints=[models.UniqueConstraint(fields=["ticket","user"],name="unique_ticket_read_state")]