103 lines
4.6 KiB
Python
103 lines
4.6 KiB
Python
"""معنای «زمانبندی» برای هر نوع پیامک.
|
|
|
|
هر نوع پیامک زمانبندی متفاوتی دارد و نمیشود همه را زیر یک برچسب «روز قبل از سررسید»
|
|
جمع کرد. این ماژول تنها مرجع این معناست: هم پنل قالبها بر اساسش فیلد درست را نشان
|
|
میدهد، هم اسکنر بر اساسش تصمیم میگیرد. هر نوع دقیقاً به یک فیلد زمانی نگاشت میشود
|
|
(``field``) تا داده هرگز ناهمخوان نشود؛ بقیهٔ فیلدهای زمانی صفر/خالی میمانند.
|
|
"""
|
|
from ..models import SMSType
|
|
|
|
NONE = "none"
|
|
BEFORE_DUE = "before_due"
|
|
AFTER_DUE = "after_due"
|
|
PERIOD_MONTHS = "period_months"
|
|
|
|
# پیشفرض دورهٔ بازدید (ماه) وقتی مدیر مقداری در قالب نگذاشته باشد.
|
|
DEFAULT_VISIT_MONTHS = 9
|
|
|
|
TIMING = {
|
|
SMSType.WELCOME: {
|
|
"kind": NONE,
|
|
"field": None,
|
|
"note": "بهمحض ثبت مشتری و بدون تأخیر ارسال میشود؛ تنظیم زمانی ندارد.",
|
|
},
|
|
SMSType.SURVEY: {
|
|
"kind": NONE,
|
|
"field": None,
|
|
"note": "بیدرنگ پس از ثبت فاکتور ارسال میشود؛ تنظیم زمانی ندارد.",
|
|
},
|
|
SMSType.CHEQUE_REGISTRATION: {
|
|
"kind": BEFORE_DUE,
|
|
"field": "offset_days",
|
|
"label": "چند روز قبل از سررسید چک",
|
|
"default": 1,
|
|
"note": "این تعداد روز پیش از سررسید چکِ پرداختنشده، پیامک یادآوری "
|
|
"تأمین موجودی با مبلغ چک ارسال میشود.",
|
|
},
|
|
SMSType.VISIT: {
|
|
"kind": PERIOD_MONTHS,
|
|
"field": "repeat_interval_months",
|
|
"label": "هر چند ماه یکبار",
|
|
"default": DEFAULT_VISIT_MONTHS,
|
|
"note": "برای مشتریانی که از این مدت بازدید نشدهاند ارسال میشود.",
|
|
},
|
|
SMSType.VISIT_CREATED: {
|
|
"kind": NONE,
|
|
"field": None,
|
|
"note": "بهمحض ثبت «اقدام از نوع بازدید» ارسال میشود؛ تنظیم زمانی ندارد.",
|
|
},
|
|
SMSType.PAYMENT_THANKS: {
|
|
"kind": NONE,
|
|
"field": None,
|
|
"note": "بیدرنگ پس از ثبت پرداخت (سند وصول/بستانکار) ارسال میشود؛ تنظیم زمانی ندارد.",
|
|
},
|
|
SMSType.NESIYE_DUE: {
|
|
"kind": BEFORE_DUE,
|
|
"field": "offset_days",
|
|
"label": "چند روز قبل از سررسید نسیه",
|
|
"default": 0,
|
|
"note": "پنجرهٔ یادآوری از «سررسید − این تعداد روز» باز میشود و تا سررسید ادامه دارد.",
|
|
},
|
|
}
|
|
|
|
|
|
def timing_for(sms_type):
|
|
"""اطلاعات زمانبندی یک نوع پیامک (با پیشفرض بیخطر برای انواع ناشناخته)."""
|
|
return TIMING.get(sms_type, {"kind": NONE, "field": None, "note": ""})
|
|
|
|
|
|
def apply_timing(template, value):
|
|
"""فیلد زمانیِ متناسب با نوع قالب را مینشاند و بقیه را صفر/خالی میکند.
|
|
|
|
``value`` عدد صحیحِ واردشده از فرم است (یا ``None``). این کار تضمین میکند صرفنظر از
|
|
اینکه فرم چه بفرستد، فقط یک فیلد زمانی برای هر قالب معنا داشته باشد.
|
|
"""
|
|
info = timing_for(template.sms_type)
|
|
field = info["field"]
|
|
template.offset_days = 0
|
|
template.repeat_interval_days = None
|
|
template.repeat_interval_months = None
|
|
if field == "offset_days":
|
|
template.offset_days = value if value is not None else info["default"]
|
|
elif field == "repeat_interval_days":
|
|
template.repeat_interval_days = value if value else info["default"]
|
|
elif field == "repeat_interval_months":
|
|
template.repeat_interval_months = value if value else None
|
|
return template
|
|
|
|
|
|
def current_timing_value(template):
|
|
"""مقدار فعلی فیلد زمانیِ متناسب (برای نمایش در فرم).
|
|
|
|
اگر مقدار خالی باشد، پیشفرض همان نوع برگردانده میشود تا فیلدِ تنظیمنشده هم در
|
|
فرم دیده شود و مدیر بتواند مقدارش را تغییر دهد.
|
|
"""
|
|
info = timing_for(template.sms_type)
|
|
field = info["field"]
|
|
if field is None:
|
|
return None
|
|
value = getattr(template, field)
|
|
if value is None:
|
|
value = info.get("default")
|
|
return value
|