This commit is contained in:
javad committed 2026-10-11 19:04:20 +03:30
1 parent 1dea3509a7
commit e3a6d1f9d4
42 files changed
+33086 -15779

No files matched your search

@@ -0,0 +1,174 @@
"""کاهش انواع پیامک به همان ۷ نوع مصوب + هم‌راستاسازی قالب‌ها.
* سه نوع قدیمی (``cheque_due``، ``debt_due``، ``custom``) حذف می‌شوند:
قالب‌ها و تنظیمات opt-out مربوط به آن‌ها پاک می‌شود.
* دو نوع جدید اضافه می‌شود: ``visit_created`` (ثبت اقدام بازدید) و
``payment_thanks`` (تشکر از پرداخت).
* متن/زمان‌بندی نوع‌های باقی‌مانده به معنای جدید هم‌راستا می‌شود
(مثلاً «تأمین موجودی چک» = چند روز پس از سررسید، و نظرسنجی = بی‌درنگ پس از فاکتور).
"""
from django.db import migrations, models
SMS_TYPE_CHOICES = [
("welcome", "خوش‌آمدگویی (ایجاد مشتری)"),
("survey", "نظرسنجی پس از ثبت فاکتور"),
("cheque_registration", "یادآوری تأمین موجودی چک"),
("visit", "یادآوری بازدید خدمات دستگاه"),
("visit_created", "ثبت بازدید (اقدام از نوع بازدید)"),
("payment_thanks", "تشکر از پرداخت"),
("nesiye_due", "یادآوری سررسید نسیه"),
]
REMOVED_TYPES = ["cheque_due", "debt_due", "custom"]
# نوع → مقادیر پیش‌فرض (خالی‌نماندن قالب‌های جدید و هم‌راستایی نوع‌های تغییریافته).
DEFAULT_TEMPLATES = {
"welcome": {
"title": "خوش‌آمدگویی",
"text": "{name} عزیز، از خرید شما سپاسگزاریم. به‌امید دیدار دوباره.",
"offset_days": 0,
"repeat_interval_days": None,
"repeat_interval_months": None,
},
"survey": {
"title": "نظرسنجی پس از فاکتور",
"text": "{name} عزیز، از خرید شما سپاسگزاریم. لطفاً با ثبت نظر خود در "
"نظرسنجی ما را همراهی کنید.",
"offset_days": 0,
"repeat_interval_days": None,
"repeat_interval_months": None,
},
"cheque_registration": {
"title": "یادآوری تأمین موجودی چک",
"text": "{name} عزیز، چک شما به مبلغ {amount_sep} ریال سررسید شده است. "
"لطفاً نسبت به تأمین موجودی حساب اقدام فرمایید.",
"offset_days": 1,
"repeat_interval_days": None,
"repeat_interval_months": None,
},
"visit": {
"title": "یادآوری بازدید خدمات دستگاه",
"text": "{name} عزیز، بیش از ۹ ماه از تعویض فیلتر دستگاه شما گذشته است. "
"لطفاً جهت هماهنگی برای ثبت بازدید رایگان با تلفن 09139741111 "
"تماس بگیرید.",
"offset_days": 0,
"repeat_interval_days": None,
"repeat_interval_months": 9,
},
"visit_created": {
"title": "ثبت بازدید",
"text": "{name} عزیز، بازدید شما برای تاریخ {date} ثبت شد. "
"از همکاری شما سپاسگزاریم.",
"offset_days": 0,
"repeat_interval_days": None,
"repeat_interval_months": None,
},
"payment_thanks": {
"title": "تشکر از پرداخت",
"text": "{name} عزیز، از پرداخت شما به مبلغ {amount_sep} ریال سپاسگزاریم.",
"offset_days": 0,
"repeat_interval_days": None,
"repeat_interval_months": None,
},
"nesiye_due": {
"title": "یادآوری سررسید نسیه",
"text": "{name} عزیز، سررسید بدهی شما به مبلغ {amount_sep} ریال نزدیک است "
"({date}). لطفاً نسبت به تسویه اقدام فرمایید.",
"offset_days": 0,
"repeat_interval_days": None,
"repeat_interval_months": None,
},
}
def align_templates(apps, schema_editor):
SMSTemplate = apps.get_model("admin_panel", "SMSTemplate")
CustomerSMSSetting = apps.get_model("admin_panel", "CustomerSMSSetting")
# ۱. پاک‌سازی انواع حذف‌شده.
SMSTemplate.objects.filter(sms_type__in=REMOVED_TYPES).delete()
CustomerSMSSetting.objects.filter(sms_type__in=REMOVED_TYPES).delete()
# ۲. ایجاد/به‌روزرسانی قالب‌های ۷ نوع مجاز (متن پیش‌فرض جدید + زمان‌بندی).
for sms_type, data in DEFAULT_TEMPLATES.items():
_template, created = SMSTemplate.objects.get_or_create(
sms_type=sms_type,
defaults={
"title": data["title"],
"text": data["text"],
"is_enabled": True,
"offset_days": data["offset_days"],
"repeat_interval_days": data["repeat_interval_days"],
"repeat_interval_months": data["repeat_interval_months"],
},
)
if not created:
SMSTemplate.objects.filter(sms_type=sms_type).update(
offset_days=data["offset_days"],
repeat_interval_days=data["repeat_interval_days"],
repeat_interval_months=data["repeat_interval_months"],
)
# ۳. متن/عنوانِ نوع‌های تغییریافته به معنای جدید هم‌راستا می‌شود.
SMSTemplate.objects.filter(sms_type="visit").update(
title=DEFAULT_TEMPLATES["visit"]["title"],
text=DEFAULT_TEMPLATES["visit"]["text"],
)
SMSTemplate.objects.filter(sms_type="cheque_registration").update(
title=DEFAULT_TEMPLATES["cheque_registration"]["title"],
text=DEFAULT_TEMPLATES["cheque_registration"]["text"],
)
SMSTemplate.objects.filter(sms_type="survey").update(
title=DEFAULT_TEMPLATES["survey"]["title"],
text=DEFAULT_TEMPLATES["survey"]["text"],
)
def clear_removed_queue_types(apps, schema_editor):
"""نوعِ ردیف‌های صفِ باقی‌مانده از انواع حذف‌شده را خالی می‌کند.
ردیف صف حذف نمی‌شود (متن و تاریخچه‌اش می‌ماند) چون ممکن است هنوز ارسال‌نشده
باشد؛ فقط ``sms_type`` آن خالی می‌شود تا کدِ نوعِ نامعتبر در دیتابیس نماند.
"""
SMSQueue = apps.get_model("admin_panel", "SMSQueue")
SMSQueue.objects.filter(sms_type__in=REMOVED_TYPES).update(sms_type="")
def noop(apps, schema_editor):
pass
class Migration(migrations.Migration):
dependencies = [
("admin_panel", "0069_smstemplate_auto_send"),
]
operations = [
migrations.AlterField(
model_name="smstemplate",
name="sms_type",
field=models.CharField(
choices=SMS_TYPE_CHOICES, max_length=40, unique=True,
verbose_name="نوع پیامک",
),
),
migrations.AlterField(
model_name="customersmssetting",
name="sms_type",
field=models.CharField(
choices=SMS_TYPE_CHOICES, max_length=40, verbose_name="نوع پیامک",
),
),
migrations.AlterField(
model_name="smsqueue",
name="sms_type",
field=models.CharField(
blank=True, choices=SMS_TYPE_CHOICES, default="", max_length=40,
verbose_name="نوع",
),
),
migrations.RunPython(align_templates, noop),
migrations.RunPython(clear_removed_queue_types, noop),
]
@@ -0,0 +1,47 @@
"""افزودن پرمیشن جداگانهٔ ``ManageSMSSettings`` برای صفحات تنظیمات/قالب‌های پیامک.
پیش از این، همهٔ مسیرهای پیامک با ``ManageSMS`` کنترل می‌شد. از این پس صفحات
«تنظیمات سامانه» و «قالب‌ها» با ``ManageSMSSettings`` جدا می‌شوند تا مدیر بتواند
دسترسی به آن‌ها را فقط به کاربران مشخصی بدهد، بدون دادن کل اختیارات پیامک.
"""
from django.db import migrations
from django.db.models import F
def ensure_permission(apps, schema_editor):
"""رکورد Permission جدید را (اگر نبود) می‌سازد و نام نمایشی‌اش را اصلاح می‌کند."""
Permission = apps.get_model('auth', 'Permission')
ContentType = apps.get_model('contenttypes', 'ContentType')
content_type, _created = ContentType.objects.get_or_create(
app_label='admin_panel', model='smsproviderconfig',
)
Permission.objects.get_or_create(
content_type=content_type,
codename='ManageSMSSettings',
defaults={'name': 'ManageSMSSettings'},
)
# نام نمایشی هر دو پرمیشن پیامک را با قرارداد پروژه هم‌راستا می‌کند.
Permission.objects.filter(
content_type=content_type, codename__in=['ManageSMS', 'ManageSMSSettings'],
).update(name=F('codename'))
class Migration(migrations.Migration):
dependencies = [
('admin_panel', '0070_sms_types_seven'),
]
operations = [
migrations.AlterModelOptions(
name='smsproviderconfig',
options={
'permissions': [('ManageSMS', 'ManageSMS'),
('ManageSMSSettings', 'ManageSMSSettings')],
'verbose_name': 'تنظیمات سامانه پیامک',
'verbose_name_plural': 'تنظیمات سامانه پیامک',
},
),
migrations.RunPython(ensure_permission, migrations.RunPython.noop),
]