"""تریگرهای رویدادی پیامک (لایهٔ سرویس، بدون signal). چهار نوع پیامک «رویدادی» هستند و لحظهٔ وقوع‌شان یک اکشن پنل است، نه یک سررسید تاریخی؛ پس به‌جای اسکنر دوره‌ای، ویوها بعد از انجام کارِ اصلی این توابع را صدا می‌زنند: * :func:`notify_welcome` — ایجاد مشتری. * :func:`notify_factor_survey` — ثبت فاکتور (نظرسنجی). * :func:`notify_visit_scheduled` — ثبت «اقدام از نوع بازدید». * :func:`notify_install_scheduled` — ثبت «اقدام از نوع نصب». * :func:`notify_payment_thanks` — ثبت پرداخت (سند بستانکار / وصول). قرارداد پروژه: استفاده از signal ممنوع است؛ همه‌چیز صریح از دلِ ویو صدا زده می‌شود. این توابع هیچ استثنایی به فراخوان پرتاب نمی‌کنند (``enqueue_sms`` خودش مقاوم است) تا مسیر اصلی هرگز به‌خاطر پیامک مختل نشود. """ import logging from ..models import SMSType from .enqueue import enqueue_sms logger = logging.getLogger(__name__) # روش‌های «غیرپرداخت»: سند بستانکاری که به‌خاطر تخفیف صادر شده، پرداختِ واقعی نیست # و نباید پیامک «تشکر از پرداخت» بگیرد. NON_PAYMENT_METHODS = {"تخفیف"} def notify_welcome(customer, *, created_by=None): """پیامک خوش‌آمدگویی در لحظهٔ ساخت مشتری.""" if customer is None or customer.pk is None: return 0 return enqueue_sms( customer=customer, sms_type=SMSType.WELCOME, context={"name": customer.name_family}, dedup_key=f"welcome:{customer.pk}", created_by=created_by, ) def notify_factor_survey(customer, factor, *, created_by=None): """پیامک نظرسنجی، بی‌درنگ پس از ثبت فاکتور.""" if customer is None or factor is None or factor.pk is None: return 0 return enqueue_sms( customer=customer, sms_type=SMSType.SURVEY, context={"name": customer.name_family, "amount": factor.amount}, dedup_key=f"survey:{factor.pk}", created_by=created_by, ) def notify_visit_scheduled(customer, action, *, created_by=None): """پیامک «بازدید شما برای تاریخ … ثبت شد» پس از ایجاد اقدام بازدید.""" if customer is None or action is None or action.pk is None: return 0 return enqueue_sms( customer=customer, sms_type=SMSType.VISIT_CREATED, context={"name": customer.name_family, "date": action.actionDateTime}, dedup_key=f"visit_created:{action.pk}", created_by=created_by, ) def notify_install_scheduled(customer, action, *, created_by=None): """پیامک «نصب شما برای تاریخ … ثبت شد» پس از ایجاد اقدام نصب. قرینهٔ :func:`notify_visit_scheduled` است و همان قرارداد را دارد: فقط برای اقدام ``nasb`` صدا زده می‌شود، متن از قالب ``install_created`` می‌آید و یکتاسازی با شناسهٔ همان رکورد اقدام انجام می‌شود (ویرایش دوباره = بدون تکرار). """ if customer is None or action is None or action.pk is None: return 0 return enqueue_sms( customer=customer, sms_type=SMSType.INSTALL_CREATED, context={"name": customer.name_family, "date": action.actionDateTime}, dedup_key=f"install_created:{action.pk}", created_by=created_by, ) def notify_payment_thanks(customer, amount, *, article_id=None, method=None, created_by=None): """پیامک تشکر از پرداخت؛ پس از ثبت سند پرداخت (بستانکار/وصول). ``article_id`` برای یکتاسازی استفاده می‌شود تا یک پرداخت هرگز دو پیامک نگیرد. ``method`` نحوهٔ پرداخت است؛ اگر «تخفیف» باشد (که پرداختِ واقعی نیست) هیچ پیامکی ساخته نمی‌شود. """ if customer is None: return 0 if method and str(method).strip() in NON_PAYMENT_METHODS: return 0 dedup_key = f"payment_thanks:{article_id}" if article_id is not None else None return enqueue_sms( customer=customer, sms_type=SMSType.PAYMENT_THANKS, context={"name": customer.name_family, "amount": amount}, dedup_key=dedup_key, created_by=created_by, )