docs: spec SMS campaign people/leads tabs and batch send
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
# پیامک گروهی: تب اشخاص/لیدها، فیلتر کامل، انتخابهمه، بچ ۵۰
|
||||
|
||||
تاریخ: ۲۰۲۶-۱۰-۱۷
|
||||
وضعیت: تأیید شده؛ آمادهٔ پلن پیادهسازی.
|
||||
|
||||
## هدف
|
||||
|
||||
صفحهٔ پیامک گروهی بتواند مخاطب را از **اشخاص** یا **لیدها** (جدا از هم) با فیلترهای واقعی (از جمله استان/شهر) انتخاب کند، همهٔ نتایج فیلتر را یکجا انتخاب کند، متن را با فیلدهای پویا بنویسد، و ساخت/ارسال را در تکههای ۵۰تایی انجام دهد.
|
||||
|
||||
## تصمیمهای تأییدشده
|
||||
|
||||
| موضوع | تصمیم |
|
||||
| --- | --- |
|
||||
| نوع مخاطب در یک کمپین | فقط اشخاص **یا** فقط لیدها (تب جدا؛ نه مخلوط) |
|
||||
| انتخابهمه | همهٔ نتایج مطابق فیلتر در کل دیتابیس (با تأیید تعداد) |
|
||||
| بچ | ارسال سرور ۵۰تایی؛ ساخت کمپین هم در صورت نیاز تکهتکهٔ ۵۰تایی |
|
||||
| فیلتر مکان اشخاص | از `company.province` / `company.city` + جستجو در آدرسها (بدون ستون استان روی Person) |
|
||||
| فیلتر مکان لیدها | `city` و `region` (+ بقیهٔ فیلترهای موجود لیست لید) |
|
||||
| فیلدهای پویا | همان توکنهای اتوماسیون پیام: `{نام}`، `{شماره}`، `{تاریخ}`، `{عنوان}`، `{شرکت}` |
|
||||
|
||||
## UX
|
||||
|
||||
1. دو تب روی فرم کمپین جدید: **اشخاص** | **لیدها**.
|
||||
2. تعویض تب با انتخاب موجود → تأیید و پاک شدن انتخاب.
|
||||
3. لیست صفحهبندیشده با جستجو و فیلترهای همسطح صفحات اصلی هر بخش.
|
||||
4. نمایش تعداد انتخابشده؛ دکمهٔ «انتخاب همهٔ نتایج فیلتر» → دریافت `total`/`ids` → تأیید → جایگزینی مجموعهٔ انتخاب.
|
||||
5. بالای textarea دکمهٔ **فیلدهای پویا** (الگوی UI اتوماسیون پیام) برای درج توکن در متن.
|
||||
6. پس از ذخیره/صف، لیست کمپینها مثل قبل؛ گزارش کلیک اگر از قبل برای لید/شخص آماده است همان مسیر را میرود.
|
||||
|
||||
## API
|
||||
|
||||
### فیلتر لیست
|
||||
|
||||
- گسترش `GET /people` با فیلترهای کمپین: حداقل `province`, `city` (از شرکت)، و فیلترهای موجود (`q`, `mood`, `importSource`, …).
|
||||
- اطمینان از پوشش فیلترهای لید برای کمپین: `q`, `city`, `region`, `stageId`, و فیلترهای موجود دیگر لیست لید.
|
||||
|
||||
### شناسههای فیلترشده
|
||||
|
||||
- `GET /people/ids` — همان queryهای لیست؛ پاسخ `{ ids: string[], total: number }`.
|
||||
- `GET /leads/ids` — همان برای لید.
|
||||
- هر دو با `ownerWhere` / scope بازیگر.
|
||||
- سقف سخت برای جلوگیری از پاسخ غولآسا (مثلاً ۵۰٬۰۰۰)؛ بیش از سقف → خطای فارسی با پیشنهاد محدود کردن فیلتر.
|
||||
|
||||
### ساخت و تکمیل کمپین
|
||||
|
||||
- `CreateSmsCampaignRequest`:
|
||||
- `name`, `body`, `queueNow?`, `scheduledAt?`
|
||||
- دقیقاً یکی از `personIds` یا `leadIds` (آرایهٔ غیرخالی).
|
||||
- ساخت اولیه حداکثر ۵۰ گیرنده؛ اگر فرانت بیشتر دارد، بعد از ساخت:
|
||||
- `POST /sms-campaigns/:id/recipients` با `{ personIds }` یا `{ leadIds }` همنوع با کمپین؛ هر درخواست حداکثر ۵۰ id.
|
||||
- تا پایان تکهها کمپین `draft` میماند؛ سپس در صورت `queueNow` صف میشود (یا کاربر دستی queue میزند).
|
||||
- گیرنده بدون موبایل → `skipped`؛ شمارندهها بهروز میشوند.
|
||||
|
||||
### ارسال
|
||||
|
||||
- در `processCampaign` مقدار `take` بچ از ۴۰ به **۵۰**.
|
||||
- قبل از `sendSmsDetailed`: اعمال `renderSmsText` روی body با متغیرهای گیرنده (شخص یا لید)، سپس `personalizeSmsBody` برای لینک یکتا (ترتیب: ابتدا توکنهای پویا، بعد لینکها).
|
||||
|
||||
## داده
|
||||
|
||||
- مدل `SmsCampaignRecipient` از قبل `personId` و `leadId` دارد؛ migration جدید لازم نیست مگر برای ایندکس/قید اختیاری.
|
||||
- کمپین صریحاً audience را از روی گیرندگان مشخص میکند؛ نیازی به ستون `audienceType` نیست اگر validation در create/add-recipients نوع را یکدست نگه دارد.
|
||||
|
||||
## خطاها
|
||||
|
||||
- هر دو `personIds` و `leadIds` با هم → `400`.
|
||||
- افزودن نوع مخالف به کمپین موجود → `400`.
|
||||
- قطع میانهراه تکهها → کمپین `draft` با گیرندگان اضافهشده؛ پیام تعداد موفق/ناموفق.
|
||||
- ماژول غیرفعال → همان `403` فعلی.
|
||||
|
||||
## خارج از محدوده
|
||||
|
||||
- کمپین ترکیبی اشخاص+لیدها
|
||||
- ستون استان/شهر مستقیم روی Person
|
||||
- ویرایش متن بعد از شروع ارسال
|
||||
- زمانبندی تقویمی جدید فراتر از `scheduledAt` فعلی
|
||||
|
||||
## معیار پذیرش
|
||||
|
||||
1. تب لید و تب شخص جدا؛ یک کمپین فقط یکی را میپذیرد.
|
||||
2. فیلتر استان/شهر (و فیلترهای کلیدی دیگر) کار میکند؛ انتخابهمه همهٔ نتایج فیلتر را میگیرد نه فقط صفحه.
|
||||
3. فیلدهای پویا در UI درج میشوند و در SMS واقعی جایگزین میگردند.
|
||||
4. ساخت لیست بزرگ در تکههای ۵۰؛ ارسال صف هم ۵۰تایی است.
|
||||
)
|
||||
Reference in New Issue
Block a user