113 lines
5.1 KiB
Python
113 lines
5.1 KiB
Python
"""معنای «زمانبندی» برای هر نوع پیامک.
|
|
|
|
هر نوع پیامک زمانبندی متفاوتی دارد و نمیشود همه را زیر یک برچسب «روز قبل از سررسید»
|
|
جمع کرد. این ماژول تنها مرجع این معناست: هم پنل قالبها بر اساسش فیلد درست را نشان
|
|
میدهد، هم اسکنر بر اساسش تصمیم میگیرد. هر نوع دقیقاً به یک فیلد زمانی نگاشت میشود
|
|
(``field``) تا داده هرگز ناهمخوان نشود؛ بقیهٔ فیلدهای زمانی صفر/خالی میمانند.
|
|
"""
|
|
from ..models import SMSType
|
|
|
|
NONE = "none"
|
|
BEFORE_DUE = "before_due"
|
|
AFTER_CREATION = "after_creation"
|
|
RECURRING = "recurring"
|
|
PERIOD_MONTHS = "period_months"
|
|
|
|
# پیشفرض دورهٔ بازدید (ماه) وقتی مدیر مقداری در قالب نگذاشته باشد.
|
|
DEFAULT_VISIT_MONTHS = 9
|
|
|
|
TIMING = {
|
|
SMSType.WELCOME: {
|
|
"kind": NONE,
|
|
"field": None,
|
|
"note": "بهمحض ثبت مشتری و بدون تأخیر ارسال میشود؛ تنظیم زمانی ندارد.",
|
|
},
|
|
SMSType.CHEQUE_DUE: {
|
|
"kind": BEFORE_DUE,
|
|
"field": "offset_days",
|
|
"label": "چند روز قبل از سررسید چک",
|
|
"default": 2,
|
|
"note": "پنجرهٔ یادآوری از «سررسید − این تعداد روز» باز میشود و تا سررسید ادامه دارد.",
|
|
},
|
|
SMSType.NESIYE_DUE: {
|
|
"kind": BEFORE_DUE,
|
|
"field": "offset_days",
|
|
"label": "چند روز قبل از سررسید نسیه",
|
|
"default": 2,
|
|
"note": "پنجرهٔ یادآوری از «سررسید − این تعداد روز» باز میشود و تا سررسید ادامه دارد.",
|
|
},
|
|
SMSType.CHEQUE_REGISTRATION: {
|
|
"kind": RECURRING,
|
|
"field": "repeat_interval_days",
|
|
"label": "هر چند روز یکبار",
|
|
"default": 3,
|
|
"note": "تا زمانی که اطلاعات ثبت چک (شمارهٔ صیادی) وارد نشده و چک پرداخت نشده، "
|
|
"با این فاصله تکرار میشود.",
|
|
},
|
|
SMSType.SURVEY: {
|
|
"kind": AFTER_CREATION,
|
|
"field": "offset_days",
|
|
"label": "چند روز بعد از صدور فاکتور",
|
|
"default": 3,
|
|
"note": "این تعداد روز پس از ثبت فاکتور ارسال میشود.",
|
|
},
|
|
SMSType.DEBT_DUE: {
|
|
"kind": NONE,
|
|
"field": None,
|
|
"note": "روی سررسیدِ وصول مطالبات و فقط برای مشتریانی که مانده بدهکارند ارسال میشود.",
|
|
},
|
|
SMSType.VISIT: {
|
|
"kind": PERIOD_MONTHS,
|
|
"field": "repeat_interval_months",
|
|
"label": "هر چند ماه یکبار",
|
|
"default": DEFAULT_VISIT_MONTHS,
|
|
"note": "برای مشتریانی که از این مدت بازدید نشدهاند ارسال میشود.",
|
|
},
|
|
SMSType.CUSTOM: {
|
|
"kind": NONE,
|
|
"field": None,
|
|
"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
|