19 KiB
Executable file
📱 سیستم نوتیفیکیشن جامع کسبوکارها
📋 فهرست مطالب
🎯 مقدمه
این سیستم یک راهکار جامع برای ارسال نوتیفیکیشن (پیامک و ایمیل) به مشتریان است که:
✅ برای هر کسبوکار: قالبهای سفارشی
✅ برای هر رویداد: فاکتور، تعمیر، پرداخت، و...
✅ تایید خودکار با AI: جلوگیری از spam
✅ بدون نیاز به اعتبار: AI مدیریت میشود توسط سیستم
✅ قابل استفاده در همه بخشها: فاکتور، تعمیرگاه، انبار، و...
🏗️ معماری سیستم
مراحل ارسال نوتیفیکیشن
┌─────────────┐
│ رویداد │ مثلاً: ثبت فاکتور جدید
│ (Event) │
└──────┬──────┘
│
▼
┌─────────────────────────────┐
│ جستجوی قالب فعال │
│ - business_id │
│ - event_type │
│ - channel (sms/email) │
└──────┬──────────────────────┘
│
▼
┌─────────────────────────────┐
│ بررسی محدودیت روزانه │
│ - daily_limit check │
└──────┬──────────────────────┘
│
▼
┌─────────────────────────────┐
│ رندر قالب │
│ - جایگزینی {{ متغیرها }} │
│ - اعمال فیلترها │
└──────┬──────────────────────┘
│
▼
┌─────────────────────────────┐
│ ارسال پیام │
│ - SMS Provider │
│ - Email Provider │
└──────┬──────────────────────┘
│
▼
┌─────────────────────────────┐
│ ثبت لاگ و آمار │
│ - notification_send_logs │
│ - notification_daily_stats │
└─────────────────────────────┘
Flow تایید قالبها
[کسبوکار] ایجاد قالب
↓
[وضعیت: draft]
↓
ارسال برای تایید
↓
[وضعیت: pending_approval]
[صف: pending]
↓
────────────────────────────────
AI Worker (هر 60 ثانیه)
────────────────────────────────
↓
بررسی محتوا:
• Rule-based checks
• Spam detection
• LLM analysis
↓
┌─────────┬──────────┬───────────┐
│ │ │ │
│ Score>90│ 40<Score<90│ Score<40│
│ │ │ │
▼ ▼ ▼
[Approve] [Review] [Reject]
[AI] [Admin] [Auto]
│ │ │
│ ▼ │
│ [مدیر سیستم] │
│ تایید/رد │
│ │ │
└─────────┴──────────┘
│
▼
[فعال شدن قالب]
[is_active = TRUE]
📊 جداول دیتابیس
1. notification_event_types
تعریف انواع رویدادها و متغیرهای قابل استفاده
مثال رکوردها:
| code | name | category | requires_approval |
|---|---|---|---|
| invoice.created | ثبت فاکتور فروش | sales | TRUE |
| repair_shop.received | دریافت کالا | repair_shop | TRUE |
| payment.received | دریافت پرداخت | financial | TRUE |
2. business_notification_templates
قالبهای هر کسبوکار
وضعیتهای قالب:
draft: پیشنویس (غیرفعال)pending_approval: در صف بررسیapproved: تایید شده (فعال)rejected: رد شدهsuspended: تعلیق شده
وضعیت تایید:
pending: در انتظار بررسیai_approved: تایید شده توسط AIadmin_approved: تایید شده توسط مدیرrejected: رد شده
3. notification_moderation_queue
صف بررسی قالبها
فیلدهای کلیدی:
ai_decision: approve, reject, review_requiredai_confidence: 0-100ai_flags: لیست مشکلات یافت شدهadmin_decision: approve, reject
4. notification_send_logs
لاگ کامل تمام ارسالها
برای:
- ردیابی ارسالها
- گزارشگیری
- Debugging
5. notification_daily_stats
آمار روزانه برای Rate Limiting
🚀 نحوه استفاده
مرحله 1: ایجاد Event Types
python scripts/seed_notification_event_types.py
این اسکریپت 7 event type اولیه ایجاد میکند.
مرحله 2: اجرای Migration
alembic upgrade head
مرحله 3: ایجاد قالب توسط کسبوکار
API Call:
POST /api/v1/business-notifications/businesses/1/templates
{
"code": "invoice_created_sms",
"name": "پیامک ثبت فاکتور",
"event_type": "invoice.created",
"channel": "sms",
"body": "سلام {{ customer_name }}، فاکتور {{ invoice_number }} به مبلغ {{ amount | format_currency }} ثبت شد. {{ business_name }}",
"daily_limit": 100,
"is_automated": true
}
Response:
{
"data": {
"id": 123,
"code": "invoice_created_sms",
"status": "draft",
"message": "قالب ایجاد شد. برای فعالسازی باید آن را برای تایید ارسال کنید."
}
}
مرحله 4: ارسال برای تایید
POST /api/v1/business-notifications/businesses/1/templates/123/submit-for-approval
قالب وارد صف میشود و:
- ✅ اگر AI Worker فعال باشد → بررسی خودکار (کمتر از 1 دقیقه)
- ⏳ اگر نیاز به بررسی داشته باشد → صف مدیر سیستم
مرحله 5: بررسی توسط AI Worker
# اجرای یک بار (تست)
python -m app.workers.notification_moderation_worker
# اجرای مداوم (production)
# این worker باید در background اجرا شود
خروجی:
🚀 شروع Notification Moderation Worker
✅ بررسی قالب 123 تکمیل شد
Decision: approve
Confidence: 95.0
Flags: []
مرحله 6: ارسال نوتیفیکیشن
from app.services.business_notification_service import BusinessNotificationService
service = BusinessNotificationService(db)
result = service.send_to_person(
business_id=1,
person_id=customer.id,
event_type="invoice.created",
context={
"invoice_number": "INV-2025-001",
"customer_name": "علی احمدی",
"amount": 1500000,
"invoice_date": "1403/12/15",
"due_date": "1403/12/30",
"business_name": "فروشگاه پارس",
"business_phone": "021-12345678"
},
triggered_by_user_id=user_id
)
💡 مثالهای کاربردی
مثال 1: ارسال پیامک هنگام ثبت فاکتور
# در invoice_service.py، بعد از ایجاد فاکتور:
from app.services.business_notification_service import BusinessNotificationService
def create_invoice(...):
# ... ایجاد فاکتور
# ارسال نوتیفیکیشن
try:
notif_service = BusinessNotificationService(db)
notif_service.send_to_person(
business_id=business_id,
person_id=invoice.person_id,
event_type="invoice.created",
context={
"invoice_number": invoice.code,
"customer_name": customer.name,
"amount": float(invoice.total_amount),
"invoice_date": invoice.document_date.isoformat(),
"due_date": invoice.due_date.isoformat() if invoice.due_date else "",
},
triggered_by_user_id=user_id
)
except Exception as e:
logger.error(f"خطا در ارسال نوتیفیکیشن: {e}")
# ادامه میدهیم - عدم ارسال نوتیفیکیشن نباید مانع ثبت فاکتور شود
مثال 2: پیشنمایش قالب قبل از ذخیره
service = BusinessNotificationService(db)
preview = service.preview_template(
business_id=1,
template_id=123,
sample_context={
"customer_name": "علی احمدی",
"invoice_number": "INV-001",
"amount": 1500000
}
)
print("متن نهایی:")
print(preview["rendered"]["body"])
# خروجی: سلام علی احمدی، فاکتور INV-001 به مبلغ 1,500,000 تومان ثبت شد.
مثال 3: ایجاد قالب با فیلترهای Jinja2
body = """
سلام {{ customer_name }} عزیز،
فاکتور شماره {{ invoice_number }} در تاریخ {{ invoice_date | format_date('%Y/%m/%d') }} ثبت شد.
مبلغ: {{ amount | format_currency('تومان') }}
سررسید: {{ due_date | format_date }}
لطفاً تا {{ days_remaining }} روز دیگر پرداخت فرمایید.
{{ business_name }}
"""
# فیلترهای موجود:
# - format_number: 1500000 → 1,500,000
# - format_date: datetime → 1403/12/15
# - format_currency: 1500000 → 1,500,000 تومان
🔐 امنیت و جلوگیری از Spam
سطوح بررسی
1️⃣ Rule-based Checks
- طول محتوا (10-1000 کاراکتر)
- استفاده صحیح از متغیرها
- Syntax قالب
2️⃣ Spam Detection
کلمات ممنوع:
- تخفیف ویژه، فقط امروز، رایگان
- کلیک کنید، همین حالا، محدود
- جایزه، مسابقه، قرعهکشی
Pattern های مشکوک:
\d+%\s*تخفیف→ 50% تخفیففقط\s+\d+\s+روز→ فقط 3 روز- تعداد زیاد لینک
- استفاده بیش از حد از emoji/علامت تعجب
3️⃣ AI Review (با LLM)
- تشخیص محتوای تبلیغاتی
- شناسایی spam patterns پیچیده
- بررسی تطابق با event_type
- پیشنهادات بهبود
تصمیمگیری خودکار
| Score | Confidence | تصمیم AI | اقدام نهایی |
|---|---|---|---|
| > 90 | High | ✅ Approve | فعالسازی خودکار |
| 70-90 | Medium | ⏳ Review | ارسال به مدیر |
| 40-70 | Low | ⚠️ Review | ارسال به مدیر با اولویت |
| < 40 | Very Low | ❌ Reject | رد خودکار |
📡 API Documentation
برای کسبوکار
دریافت لیست event types
GET /api/v1/business-notifications/event-types?category=sales
لیست قالبها
GET /api/v1/business-notifications/businesses/{business_id}/templates
ایجاد قالب
POST /api/v1/business-notifications/businesses/{business_id}/templates
Content-Type: application/json
{
"code": "unique_code",
"name": "نام قالب",
"event_type": "invoice.created",
"channel": "sms",
"body": "محتوا با {{ متغیرها }}",
"daily_limit": 100
}
پیشنمایش قالب
POST /api/v1/business-notifications/businesses/{business_id}/templates/{id}/preview
Content-Type: application/json
{
"sample_context": {
"customer_name": "علی احمدی",
"invoice_number": "INV-001"
}
}
ارسال نوتیفیکیشن
POST /api/v1/business-notifications/businesses/{business_id}/send
Content-Type: application/json
{
"person_id": 123,
"event_type": "invoice.created",
"context": {
"invoice_number": "INV-001",
"amount": 1500000
}
}
مشاهده لاگها
GET /api/v1/business-notifications/businesses/{business_id}/logs?channel=sms&status=sent
برای مدیر سیستم
صف بررسی
GET /api/v1/admin/notification-moderation/queue?status=admin_reviewing
آمار صف
GET /api/v1/admin/notification-moderation/queue/stats
تایید قالب
POST /api/v1/admin/notification-moderation/queue/{queue_id}/approve
Content-Type: application/json
{
"notes": "قالب مناسب است"
}
رد قالب
POST /api/v1/admin/notification-moderation/queue/{queue_id}/reject
Content-Type: application/json
{
"reason": "محتوا تبلیغاتی است",
"notes": "از کلمات 'تخفیف ویژه' استفاده نکنید"
}
🔧 تنظیمات و راهاندازی
تنظیمات AI (استفاده از AIService موجود)
توجه مهم: این سیستم از AIService موجود در نرمافزار استفاده میکند.
✅ مزایا:
- یکپارچه با سیستم موجود
- استفاده از تنظیمات OpenAI موجود
- بدون نیاز به نصب Ollama
- مدیریت یکپارچه اعتبار
✅ نحوه کار:
- از اعتبار سیستم استفاده میکند (نه کاربر)
- تنها superadmin ها بدون محدودیت از AI استفاده میکنند
- هزینه moderation بر عهده سیستم است (رایگان برای کسبوکارها)
✅ پیشنیاز:
- تنظیمات AI در پنل مدیر فعال باشد
- حداقل یک کاربر superadmin وجود داشته باشد
راهاندازی Worker
# در production، با supervisor یا systemd:
[program:notification_moderation_worker]
command=python -m app.workers.notification_moderation_worker
directory=/var/www/ark/hesabixAPI
autostart=true
autorestart=true
user=www-data
📈 گزارشات و آمار
آمار روزانه
from adapters.db.repositories.business_notification_repo import NotificationDailyStatRepository
from datetime import date, timedelta
stat_repo = NotificationDailyStatRepository(db)
stats = stat_repo.get_stats(
business_id=1,
from_date=date.today() - timedelta(days=30),
to_date=date.today()
)
for stat in stats:
print(f"{stat.date}: {stat.total_sent} sent, {stat.total_failed} failed")
لاگهای ارسال
from adapters.db.repositories.business_notification_repo import NotificationSendLogRepository
log_repo = NotificationSendLogRepository(db)
logs, total = log_repo.list_by_business(
business_id=1,
filters={"status": "failed", "channel": "sms"},
offset=0,
limit=50
)
🛡️ امنیت
محدودیتها
- Daily Limit: هر قالب حداکثر X ارسال در روز
- Template Approval: قالبها قبل از فعال شدن بررسی میشوند
- Content Filtering: محتوای تبلیغاتی و spam فیلتر میشود
- Audit Trail: تمام ارسالها ثبت میشوند
Best Practices
✅ DO:
- از متغیرها استفاده کنید:
{{ customer_name }} - پیامهای کوتاه و واضح بنویسید
- اطلاعات تماس کسبوکار را اضافه کنید
❌ DON'T:
- از کلمات تبلیغاتی استفاده نکنید
- محتوای طولانی ننویسید (SMS < 200 کاراکتر)
- لینکهای زیاد نگذارید
🔄 یکپارچهسازی با بخشهای دیگر
فاکتور (Invoice)
# در invoice_service.py
from app.services.business_notification_service import BusinessNotificationService
def create_invoice(...):
# ... ایجاد فاکتور
# ارسال نوتیفیکیشن
notif_service = BusinessNotificationService(db)
notif_service.send_to_person(
business_id=business_id,
person_id=invoice.person_id,
event_type="invoice.created",
context={...},
triggered_by_user_id=user_id
)
تعمیرگاه (Repair Shop)
# در repair_shop_service.py
from app.services.repair_shop_notification import send_repair_notification
def create_repair_order(...):
# ... ایجاد سفارش
# ارسال نوتیفیکیشن
send_repair_notification(
db=db,
business_id=business_id,
repair_order=order,
event_type="repair_shop.received",
triggered_by_user_id=user_id
)
پرداخت (Payment)
from app.services.business_notification_service import BusinessNotificationService
def record_payment(...):
# ... ثبت پرداخت
notif_service = BusinessNotificationService(db)
notif_service.send_to_person(
business_id=business_id,
person_id=payment.person_id,
event_type="payment.received",
context={...}
)
🎨 متغیرها و فیلترها
متغیرهای رایج
| متغیر | توضیح | مثال |
|---|---|---|
{{ customer_name }} |
نام مشتری | علی احمدی |
{{ business_name }} |
نام کسبوکار | فروشگاه پارس |
{{ business_phone }} |
تلفن کسبوکار | 021-12345678 |
{{ invoice_number }} |
شماره فاکتور | INV-2025-001 |
{{ amount }} |
مبلغ | 1500000 |
فیلترهای Jinja2
| فیلتر | کاربرد | مثال |
|---|---|---|
format_number |
جداکننده هزارگان | {{ 1500000 | format_number }} → 1,500,000 |
format_currency |
فرمت مبلغ با ارز | {{ amount | format_currency }} → 1,500,000 تومان |
format_date |
فرمت تاریخ | {{ date | format_date('%Y/%m/%d') }} → 1403/12/15 |
🐛 Troubleshooting
قالب تایید نمیشود
- بررسی لاگهای Worker
- اجرای دستی Worker برای debug
- بررسی صف در پنل مدیر
پیام ارسال نمیشود
- بررسی وجود قالب فعال
- بررسی محدودیت روزانه
- بررسی لاگهای ارسال
- بررسی تنظیمات SMS Provider
خطای Template Syntax
- از
{{ variable }}استفاده کنید (نه{ variable }) - متغیرها case-sensitive هستند
- از پیشنمایش استفاده کنید
📞 پشتیبانی
برای سوالات و مشکلات:
- بررسی این مستند
- بررسی لاگهای سیستم
- تماس با تیم پشتیبانی