docs: spec unified outbound SMS log in compose modal
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
# لاگ یکپارچهٔ پیامک خروجی در دیالوگ ارسال
|
||||
|
||||
تاریخ: ۲۰۲۶-۱۰-۱۷
|
||||
وضعیت: تأیید شده؛ آمادهٔ پلن پیادهسازی.
|
||||
|
||||
## هدف
|
||||
|
||||
در دیالوگ ارسال پیامک (لید و شخص)، لیست پیامکهایی که از این به بعد برای همان مخاطب رفته نمایش داده شود: دستی، کمپین گروهی، اتوماسیون.
|
||||
|
||||
## تصمیمها
|
||||
|
||||
| موضوع | تصمیم |
|
||||
| --- | --- |
|
||||
| منبع حقیقت | جدول جدید `OutboundSmsLog` |
|
||||
| تاریخچهٔ قبل از استقرار | مهم نیست؛ فقط از این به بعد |
|
||||
| پوشش | manual + campaign + automation |
|
||||
| UI | همان `SmsComposeModal` برای لید و شخص |
|
||||
|
||||
## مدل داده
|
||||
|
||||
`OutboundSmsLog`:
|
||||
|
||||
- `id`, `organizationId`
|
||||
- `personId` اختیاری، `leadId` اختیاری (حداقل یکی در عمل پر میشود)
|
||||
- `mobile`, `body` (متن نهایی پس از توکن/لینک)
|
||||
- `source`: `manual` | `campaign` | `automation`
|
||||
- `sourceId` اختیاری (شناسهٔ کمپین / قانون اتوماسیون)
|
||||
- `status`: `sent` | `failed`
|
||||
- `error` اختیاری
|
||||
- `actorUserId` اختیاری (برای دستی)
|
||||
- `createdAt`
|
||||
- ایندکس: `(organizationId, personId, createdAt)`, `(organizationId, leadId, createdAt)`
|
||||
|
||||
## نقاط ثبت
|
||||
|
||||
1. `PeopleService.sendSms` — source=`manual`
|
||||
2. `LeadsService.sendSms` — source=`manual` (LeadEvent فعلی میتواند بماند)
|
||||
3. `SmsCampaignsService.processCampaign` پس از هر تلاش ارسال — source=`campaign`, `sourceId`=campaignId
|
||||
4. ارسال SMS در message-automations — source=`automation`, `sourceId`=ruleId، با `personId` وقتی موجود است
|
||||
|
||||
ثبت نباید ارسال را بشکند: اگر لاگ fail شد، فقط log خطا؛ نتیجهٔ SMS حفظ شود.
|
||||
|
||||
## API
|
||||
|
||||
- `GET /people/:id/sms-history?limit=50`
|
||||
- `GET /leads/:id/sms-history?limit=50`
|
||||
|
||||
`OutboundSmsHistoryResponse`:
|
||||
|
||||
```ts
|
||||
{
|
||||
items: Array<{
|
||||
id: string;
|
||||
body: string;
|
||||
mobile: string;
|
||||
source: 'manual' | 'campaign' | 'automation';
|
||||
sourceLabel: string; // دستی | کمپین | اتوماسیون
|
||||
status: 'sent' | 'failed';
|
||||
createdAt: string;
|
||||
}>;
|
||||
}
|
||||
```
|
||||
|
||||
مرتبسازی: جدیدترین اول. Scope دسترسی همان دسترسی به شخص/لید.
|
||||
|
||||
## UI
|
||||
|
||||
در `SmsComposeModal`:
|
||||
|
||||
- prop اختیاری `historyEndpoint`
|
||||
- با `open` لود تاریخچه
|
||||
- بلوک «پیامکهای قبلی» زیر پیشنمایش؛ اسکرول؛ خالی = «هنوز پیامکی ثبت نشده»
|
||||
- پس از ارسال موفق، رفرش لیست (یا prepend محلی)
|
||||
|
||||
`LeadDetailView` و `PersonProfileView` endpoint تاریخچه را پاس میدهند.
|
||||
|
||||
## خارج از محدوده
|
||||
|
||||
- بکفیل تاریخچهٔ قدیمی
|
||||
- نمایش در صفحهٔ جدا / گزارش سازمانی کامل
|
||||
- ویرایش یا حذف لاگ از UI
|
||||
|
||||
## معیار پذیرش
|
||||
|
||||
1. بعد از ارسال دستی به لید/شخص، همان متن در دیالوگ دیده شود.
|
||||
2. پیامک کمپین و اتوماسیون (برای شخص) در تاریخچه ظاهر شود.
|
||||
3. لید و شخص هر دو از همان مودال تاریخچه بگیرند.
|
||||
Reference in New Issue
Block a user