sms
This commit is contained in:
1 parent
250cdbab7f
commit
5c6069c3ef
87 files changed
+29209
-3697
No files matched your search
@@ -0,0 +1,74 @@
|
||||
"""قرار دادن پیامک در صف ارسال (insert-only، بیخطر برای مسیر request)."""
|
||||
import logging
|
||||
from uuid import uuid4
|
||||
|
||||
from django.db import IntegrityError
|
||||
|
||||
from ..models import SMSDedup, SMSQueue, SMSTemplate, SMSType
|
||||
from .recipients import resolve_recipients
|
||||
from .render import render_template
|
||||
from .rules import is_sms_enabled
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def enqueue_sms(*, customer=None, sms_type, context=None, dedup_key=None,
|
||||
message=None, recipients=None, created_by=None, approved=False):
|
||||
"""پیامک را در صف قرار میدهد و تعداد رکوردهای ساختهشده را برمیگرداند.
|
||||
|
||||
بهصورت پیشفرض پیامک در وضعیت «در انتظار تأیید» ثبت میشود و تا وقتی مدیر
|
||||
آن را از پنل تأیید نکند، worker آن را ارسال نمیکند. دو راه برای پرش از این
|
||||
بازبینی هست: ``approved=True`` برای ارسالهای دستیِ صریح مدیر (مثل پیامک سفارشی
|
||||
یا آزمایشی)، و ``SMSTemplate.auto_send`` که مدیر در صفحهٔ قالبها برای هر نوع
|
||||
پیامک روشن میکند تا پیامکهای خودکارِ اسکنر بدون صف تأیید ارسال شوند.
|
||||
|
||||
هیچ استثنایی به فراخوان پرتاب نمیشود؛ خطاها فقط لاگ میشوند تا مسیر اصلی
|
||||
(مثلاً ایجاد مشتری یا اسکنر) هرگز بهخاطر پیامک مختل نشود.
|
||||
"""
|
||||
try:
|
||||
if message is None:
|
||||
template = SMSTemplate.objects.filter(sms_type=sms_type, is_enabled=True).first()
|
||||
if template is None:
|
||||
return 0
|
||||
message = render_template(template.text, context)
|
||||
# «ارسال خودکار» هر نوع پیامک در صفحهٔ قالبها تعیین میشود؛ خاموش = بازبینی مدیر.
|
||||
approved = approved or template.auto_send
|
||||
|
||||
if not is_sms_enabled(customer, sms_type):
|
||||
return 0
|
||||
|
||||
numbers = recipients if recipients is not None else resolve_recipients(customer)
|
||||
if not numbers:
|
||||
return 0
|
||||
|
||||
if dedup_key is None:
|
||||
dedup_key = f"{sms_type}:{uuid4().hex}"
|
||||
|
||||
created = 0
|
||||
for number in numbers:
|
||||
key = dedup_key if len(numbers) == 1 else f"{dedup_key}:{number}"
|
||||
try:
|
||||
# دفتر کلیدها مستقل از صف است: کلیدِ یکبار خورده هرگز دوباره
|
||||
# ایجاد نمیشود، حتی اگر رکورد صف را مدیر حذف کرده باشد.
|
||||
if not SMSDedup.objects.get_or_create(key=key)[1]:
|
||||
continue
|
||||
_, made = SMSQueue.objects.get_or_create(
|
||||
dedup_key=key,
|
||||
defaults={
|
||||
"customer": customer,
|
||||
"sms_type": sms_type,
|
||||
"phone_number": number,
|
||||
"message": message,
|
||||
"created_by": created_by,
|
||||
"status": (SMSQueue.Status.APPROVED if approved
|
||||
else SMSQueue.Status.PENDING),
|
||||
},
|
||||
)
|
||||
created += 1 if made else 0
|
||||
except IntegrityError:
|
||||
# رقابت همزمان روی dedup_key؛ نادیده گرفته میشود.
|
||||
continue
|
||||
return created
|
||||
except Exception:
|
||||
logger.exception("enqueue_sms برای نوع=%s شکست خورد", sms_type)
|
||||
return 0
|
||||
Reference in new issue
Block a user