Add campaigns/ Add supervisor/ Add messaging features/ Separate SMS
This commit is contained in:
68
campaigns/admin.py
Normal file
68
campaigns/admin.py
Normal file
@@ -0,0 +1,68 @@
|
||||
"""
|
||||
ثبتِ MessageCampaign و CampaignDelivery در Django Admin.
|
||||
|
||||
این ماژول صرفاً برای مشاهده/مدیریتِ دستیِ کمپینها و بررسیِ وضعیتِ
|
||||
تحویلهاست؛ هیچ منطقِ اجرای کمپین (execute_campaign) اینجا صدا زده
|
||||
نمیشه — طبق MessageCampaign.__doc__ و CampaignDelivery.__doc__، اجرا
|
||||
و پنلِ ادمینِ مربوط به execution فیچرِ بعدیه.
|
||||
|
||||
- MessageCampaignAdmin: امکانِ ساخت/ویرایش/حذفِ کمپین (فیلدهای معمولی،
|
||||
بدون منطقِ اجرا) رو با ModelAdmin پیشفرضِ Django فراهم میکنه.
|
||||
- CampaignDeliveryAdmin: صرفاً read-only. CampaignDelivery یک لاگِ
|
||||
وضعیتِ تولیدشده توسطِ execute_campaign()ه (طبق docstring خودش)؛
|
||||
دستکاریِ دستیِ status/error_message از ادمین میتونه این لاگ رو با
|
||||
چیزی که واقعاً برای کاربر اتفاق افتاده (یا نیفتاده) ناسازگار کنه و
|
||||
رفتارِ idempotency/unique-constraint که در campaigns.services روی
|
||||
همین رکوردها تکیه میکنه رو دور بزنه. به همین دلیل add/change/delete
|
||||
همه غیرفعالن؛ تنها راهِ دیدنِ رکوردها لیست/دیتیلِ read-onlyه.
|
||||
"""
|
||||
from django.contrib import admin
|
||||
|
||||
from .models import CampaignDelivery, MessageCampaign
|
||||
|
||||
|
||||
@admin.register(MessageCampaign)
|
||||
class MessageCampaignAdmin(admin.ModelAdmin):
|
||||
list_display = ('id', 'title', 'channel', 'created_at')
|
||||
list_filter = ('channel',)
|
||||
search_fields = ('title', 'body')
|
||||
readonly_fields = ('created_at',)
|
||||
fields = ('title', 'body', 'channel', 'target_filter', 'created_at')
|
||||
|
||||
|
||||
@admin.register(CampaignDelivery)
|
||||
class CampaignDeliveryAdmin(admin.ModelAdmin):
|
||||
"""
|
||||
نمایشِ read-only: لیست و صفحهی جزئیاتِ هر رکورد همیشه قابلِ
|
||||
مشاهدهست (has_view_permission صریحاً True)، ولی هیچ راهی برای
|
||||
افزودن، ویرایش یا حذفِ رکورد از ادمین وجود نداره تا وضعیتِ تحویل
|
||||
(که فقط باید توسطِ campaigns.services.execute_campaign آپدیت بشه)
|
||||
از ادمین دستکاری نشه.
|
||||
"""
|
||||
|
||||
list_display = ('id', 'campaign', 'user_id', 'channel', 'status', 'created_at')
|
||||
list_filter = ('channel', 'status')
|
||||
search_fields = ('user_id', 'error_message')
|
||||
fields = ('campaign', 'user_id', 'channel', 'status', 'error_message', 'created_at')
|
||||
readonly_fields = fields
|
||||
|
||||
def has_view_permission(self, request, obj=None):
|
||||
# صریحاً True: نباید به fallbackِ مبتنیبر codename پرمیشنِ
|
||||
# پیشفرضِ Django (has_perm('view_...') or has_perm('change_...'))
|
||||
# تکیه کنیم. بدونِ این override، یک کاربرِ staff که پرمیشنِ
|
||||
# view/change روی این مدل رو نداره، حتی برای دیدنِ صفحهی
|
||||
# جزئیاتِ read-only هم 403 میگیره — یعنی مدل عملاً "view-only"
|
||||
# نیست بلکه کاملاً غیرقابلِدسترسه. این متد مستقل از
|
||||
# has_change_permission (که پایین همیشه False برمیگردونه)
|
||||
# تضمین میکنه که دیدن همیشه مجازه، صرفِنظر از پرمیشنهای
|
||||
# دیتابیسی.
|
||||
return True
|
||||
|
||||
def has_add_permission(self, request):
|
||||
return False
|
||||
|
||||
def has_change_permission(self, request, obj=None):
|
||||
return False
|
||||
|
||||
def has_delete_permission(self, request, obj=None):
|
||||
return False
|
||||
Reference in New Issue
Block a user