71 lines
3.6 KiB
Python
71 lines
3.6 KiB
Python
|
|
from django.conf import settings
|
||
|
|
from django.db import models
|
||
|
|
from django.utils.translation import gettext_lazy as _
|
||
|
|
|
||
|
|
from apps.banker.models import Contact, ContactGroup, MessageTemplate
|
||
|
|
|
||
|
|
# این اپ فقط از مسیرهای رسمی هر پلتفرم برای ارسال استفاده میکند: پیامک از
|
||
|
|
# طریق درگاه بالک کاوهنگار (سمت سرور، خودکار)، واتساپ از طریق WhatsApp
|
||
|
|
# Business Cloud API رسمی، تلگرام/بله/ایتا از طریق Bot API رسمی هرکدام —
|
||
|
|
# فقط برای مخاطبینی که قبلا چت با بات را شروع کردهاند (opt-in). برای بقیهی
|
||
|
|
# موارد، MessageRecipient با status=needs_manual برمیگردد تا اپ یک صف
|
||
|
|
# deep-link یکلمسی به کاربر نشان دهد؛ هیچ اتوماسیون/شبیهسازی رفتار انسانی
|
||
|
|
# برای دور زدن ضدهرزنامهی این پلتفرمها در این اپ وجود ندارد.
|
||
|
|
|
||
|
|
|
||
|
|
class Channel(models.TextChoices):
|
||
|
|
SMS = "sms", _("پیامک")
|
||
|
|
WHATSAPP = "whatsapp", _("واتساپ")
|
||
|
|
TELEGRAM = "telegram", _("تلگرام")
|
||
|
|
BALE = "bale", _("بله")
|
||
|
|
EITAA = "eitaa", _("ایتا")
|
||
|
|
|
||
|
|
|
||
|
|
class BulkMessage(models.Model):
|
||
|
|
class Status(models.TextChoices):
|
||
|
|
DISPATCHED = "dispatched", _("ارسالشده")
|
||
|
|
PARTIALLY_MANUAL = "partially_manual", _("بخشی نیاز به تایید دستی")
|
||
|
|
|
||
|
|
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="bulk_messages")
|
||
|
|
# null = همهی مخاطبین کاربر
|
||
|
|
group = models.ForeignKey(ContactGroup, on_delete=models.SET_NULL, null=True, blank=True, related_name="+")
|
||
|
|
template = models.ForeignKey(
|
||
|
|
MessageTemplate, on_delete=models.SET_NULL, null=True, blank=True, related_name="+"
|
||
|
|
)
|
||
|
|
body_override = models.TextField(blank=True, verbose_name=_("متن آزاد (اگر قالب انتخاب نشده)"))
|
||
|
|
channels = models.JSONField(default=list, verbose_name=_("کانالهای انتخابشده"))
|
||
|
|
status = models.CharField(max_length=20, choices=Status.choices, default=Status.DISPATCHED)
|
||
|
|
created_at = models.DateTimeField(auto_now_add=True)
|
||
|
|
|
||
|
|
class Meta:
|
||
|
|
verbose_name = _("ارسال گروهی")
|
||
|
|
verbose_name_plural = _("ارسالهای گروهی")
|
||
|
|
ordering = ["-created_at"]
|
||
|
|
|
||
|
|
def __str__(self):
|
||
|
|
return f"#{self.pk} — {self.user.phone} — {', '.join(self.channels)}"
|
||
|
|
|
||
|
|
|
||
|
|
class MessageRecipient(models.Model):
|
||
|
|
class Status(models.TextChoices):
|
||
|
|
SENT = "sent", _("ارسالشده")
|
||
|
|
FAILED = "failed", _("ناموفق")
|
||
|
|
NEEDS_MANUAL = "needs_manual", _("نیاز به تایید دستی")
|
||
|
|
MANUAL_CONFIRMED = "manual_confirmed", _("تایید دستی شد")
|
||
|
|
|
||
|
|
bulk_message = models.ForeignKey(BulkMessage, on_delete=models.CASCADE, related_name="recipients")
|
||
|
|
contact = models.ForeignKey(Contact, on_delete=models.CASCADE, related_name="+")
|
||
|
|
channel = models.CharField(max_length=10, choices=Channel.choices)
|
||
|
|
status = models.CharField(max_length=20, choices=Status.choices)
|
||
|
|
rendered_body = models.TextField()
|
||
|
|
error = models.CharField(max_length=255, blank=True)
|
||
|
|
updated_at = models.DateTimeField(auto_now=True)
|
||
|
|
|
||
|
|
class Meta:
|
||
|
|
verbose_name = _("گیرندهی پیام")
|
||
|
|
verbose_name_plural = _("گیرندههای پیام")
|
||
|
|
indexes = [models.Index(fields=["bulk_message", "status"])]
|
||
|
|
|
||
|
|
def __str__(self):
|
||
|
|
return f"{self.contact.name} — {self.channel} — {self.status}"
|