25 KiB
داکیومنت فنی و اجرایی سامانه گردونه شانس و قرعهکشی
نسخه: 1.0
نوع سیستم: Web Application / Mobile First
وضعیت: MVP Specification
هدف: ایجاد و مدیریت کمپینهای گردونه شانس با قابلیت تعریف جایزه، تخصیص شانس به کاربران، ثبت قرعهکشی، مدیریت برندگان، ارسال پیامک و گزارشگیری.
1. خلاصه محصول
سامانه از دو بخش اصلی تشکیل میشود:
- پنل کاربر و تجربه گردونه شانس
- پنل مدیریت
مدیر سیستم باید بتواند کمپین ایجاد کند، جوایز و موجودی آنها را تعریف کند، تعداد شانس کاربران را مدیریت کند و نتایج تمام Spinها و برندگان را مشاهده و مدیریت کند.
کاربر با شماره موبایل وارد سامانه میشود و بر اساس تعداد شانس موجود، گردونه را میچرخاند و نتیجه دریافت میکند.
اصل معماری: نتیجه Spin همیشه در Backend تعیین و ثبت میشود و انیمیشن گردونه صرفاً نتیجهای را که Backend تعیین کرده نمایش میدهد. Frontend نباید هیچ نقش تصمیمگیرندهای در انتخاب جایزه داشته باشد.
2. نقشها و دسترسیها
2.1 مدیر (Admin)
- مدیریت کمپینها
- مدیریت جوایز
- مدیریت کاربران
- مدیریت شانسها
- مشاهده Spinها
- مشاهده و مدیریت برندگان
- مدیریت پیامکها
- گزارشگیری
- مشاهده Audit Log
- مدیریت تنظیمات سیستم
2.2 کاربر (User)
- ورود با شماره موبایل و OTP
- مشاهده تعداد شانس
- چرخاندن گردونه
- مشاهده نتیجه
- مشاهده شانسهای باقیمانده
- مشاهده تاریخچه جوایز
3. جریان اصلی کاربر
شماره موبایل
↓
ارسال OTP
↓
تأیید شماره
↓
ایجاد یا شناسایی کاربر
↓
بررسی کمپین فعال
↓
محاسبه تعداد شانس
↓
نمایش گردونه
↓
درخواست Spin
↓
انتخاب نتیجه توسط Backend
↓
کسر یک شانس
↓
ثبت Transaction
↓
نمایش انیمیشن گردونه
↓
نمایش جایزه
↓
ارسال SMS
↓
Spin مجدد در صورت وجود شانس
4. احراز هویت
ورود کاربران با شماره موبایل انجام میشود.
APIهای پایه
POST /api/auth/send-otpPOST /api/auth/verify-otp
قوانین
- شماره موبایل فیلد اصلی شناسایی کاربر است.
- پس از ارسال شماره، OTP ارسال شود.
- پس از تأیید OTP، Token یا Session معتبر ایجاد شود.
- محدودیت ارسال مجدد OTP اعمال شود.
- تعداد تلاش ناموفق OTP محدود شود.
- کاربر بدون شماره موبایل تأییدشده نباید امکان Spin داشته باشد.
نمونه پیام:
کد ورود شما به گردونه شانس: 48215
5. مدیریت کمپین
سیستم باید Multi-Campaign باشد.
فیلدهای کمپین
| فیلد | توضیح |
|---|---|
| id | شناسه یکتا |
| title | عنوان کمپین |
| slug | شناسه URL |
| description | توضیحات |
| image / banner | تصویر یا بنر |
| logo | لوگو |
| start_at | زمان شروع |
| end_at | زمان پایان |
| status | وضعیت کمپین |
| default_chances | تعداد شانس پیشفرض |
| rules | قوانین کمپین |
| cta_text | متن CTA |
| settings | تنظیمات ظاهری |
| created_at | زمان ایجاد |
| updated_at | زمان ویرایش |
وضعیتها
DraftActivePausedFinished
شرط فعال بودن
فقط کمپینهایی که وضعیت Active دارند و زمان فعلی داخل بازه start_at تا end_at است، قابل استفاده و Spin هستند.
6. مدیریت جوایز
برای هر کمپین تعداد نامحدودی Prize قابل تعریف است.
فیلدهای جایزه
| فیلد | توضیح |
|---|---|
| title | عنوان جایزه |
| description | توضیح |
| image | تصویر |
| stock | موجودی |
| stock_type | محدود یا نامحدود |
| weight | وزن برد |
| sort_order | ترتیب Segment روی گردونه |
| segment_color | رنگ Segment |
| status | وضعیت |
| sms_template | متن پیامک |
| expires_at | تاریخ اعتبار |
| type | نوع جایزه |
نوع جایزه
PhysicalDiscount CodeCreditCashNo PrizeOther
نوع موجودی
LimitedUnlimited
نمونه:
- آیفون — 1 عدد
- کارت هدیه — 10 عدد
- تخفیف 30٪ — 100 عدد
- تخفیف 10٪ — نامحدود
- بدون جایزه — نامحدود
7. موتور Spin
اصل کلیدی
Spin باید کاملاً Backend-Based باشد.
Frontend فقط درخواست را ارسال میکند و پس از دریافت نتیجه، Animation را اجرا میکند.
ترتیب اجرای Spin
- بررسی Authentication Token
- بررسی فعال بودن کمپین
- بررسی تعداد شانس کاربر
- بررسی Prizeهای فعال
- بررسی موجودی Prizeهای محدود
- اعمال قوانین کمپین
- انتخاب نتیجه توسط Backend
- مصرف یک Chance
- کاهش موجودی Prize در صورت محدود بودن
- ثبت Spin
- بازگرداندن نتیجه به Frontend
- اجرای انیمیشن گردونه روی Segment تعیینشده
- ارسال SMS
تمام عملیات حساس Spin باید داخل Database Transaction و بهصورت Atomic انجام شود.
در صورت شکست عملیات، نباید Chance یا Prize Inventory بهصورت ناقص تغییر کند.
8. سیستم Weight و احتمال برد
هر Prize یک Weight دارد و احتمال برد بهصورت نسبی از مجموع Weightهای قابل انتخاب محاسبه میشود.
مثال:
| Prize | Weight |
|---|---|
| آیفون | 1 |
| کارت هدیه | 10 |
| تخفیف 30٪ | 50 |
| تخفیف 10٪ | 200 |
| بدون جایزه | 739 |
مجموع Weight در این مثال 1000 است.
الگوریتم نیازی ندارد مجموع Weight برابر 100 یا 1000 باشد. ترکیب زیر نیز معتبر است:
- A = 10
- B = 20
- C = 70
9. کنترل موجودی Prize
اگر موجودی یک Prize به صفر رسید:
- Prize نباید دوباره انتخاب شود.
- Backend باید آن را از Pool قرعهکشی خارج کند.
- نمایش Segment غیرفعال میتواند مطابق تنظیمات کمپین ادامه پیدا کند.
- کاهش موجودی باید داخل Transaction انجام شود.
- در درخواستهای همزمان، تعداد جوایز توزیعشده نباید از موجودی واقعی بیشتر شود.
Race Condition
مثال: فقط یک آیفون باقی مانده و دو کاربر همزمان Spin میکنند.
نتیجه صحیح این است که فقط یک کاربر آیفون دریافت کند.
بنابراین انتخاب Prize، کنترل موجودی، کاهش موجودی، مصرف Chance و ثبت Spin باید در یک Transaction با Lock مناسب انجام شود.
10. سیستم Chance
برای هر کاربر در هر کمپین تعداد شانس مستقل نگهداری شود.
Snapshot / Summary
total_chancesused_chancesremaining_chances
Chance Ledger
علاوه بر Summary، تمام تغییرات شانس باید در یک Ledger ثبت شوند.
نمونه:
+3 ثبتنام در کمپین
+2 اضافهشده توسط مدیر
-1 Spin
-1 Spin
+5 جایزه کمپین جانبی
Ledger برای Audit، گزارشگیری و بررسی اختلافات ضروری است.
11. شانس پیشفرض
هنگام ساخت کمپین، مدیر تعیین میکند هر کاربر جدید چند شانس دریافت کند.
مثال:
Default Chances = 3
کاربری که برای اولین بار وارد کمپین شود، 3 شانس دریافت میکند.
مدیر باید بتواند برای کاربران مشخص، شانس را بهصورت دستی اضافه یا کم کند.
12. مدیریت کاربران
لیست کاربران
- شماره موبایل
- نام در صورت وجود
- تاریخ عضویت
- آخرین ورود
- تعداد کمپینهای شرکتکرده
- وضعیت
جزئیات کاربر
- کمپینهای کاربر
- شانس کل
- شانس مصرفشده
- شانس باقیمانده
- تاریخچه Spin
- جوایز
- تاریخچه تغییر شانس
عملیات مدیریتی
- اضافه کردن شانس
- کم کردن شانس
- مسدود کردن کاربر
- مشاهده جزئیات فعالیت
13. UX صفحه اصلی گردونه
صفحه کاربر باید Mobile First باشد.
اجزای اصلی
- لوگوی برند
- نام کمپین
- توضیح کوتاه
- گردونه
- Pointer
- تعداد شانس باقیمانده
- دکمه «بچرخون»
- لینک قوانین
- دکمه «جوایز من»
نمونه نمایش:
3 شانس داری 🎟️
[ گردونه ]
بچرخون
14. رفتار UI هنگام Spin
- کاربر دکمه Spin را لمس میکند.
- دکمه فوراً Disable میشود.
- Loading کوتاه نمایش داده میشود.
- درخواست به Backend ارسال میشود.
- Backend نتیجه را مشخص میکند.
- گردونه چند دور کامل میچرخد.
- گردونه دقیقاً روی Segment برگرداندهشده متوقف میشود.
- تا پایان Animation امکان Spin مجدد وجود ندارد.
- Modal نتیجه نمایش داده میشود.
15. صفحه نتیجه
در صورت برد
🎉 تبریک!
شما برنده شدید
[ تصویر جایزه ]
نام جایزه
کد جایزه: MNT-X7D92
CTA:
- در صورت وجود شانس: «یک شانس دیگه دارم»
- در صورت تمام شدن شانس: «مشاهده جوایز من»
16. جوایز من
کاربر باید تاریخچه جوایز خود را مشاهده کند.
هر Card شامل:
- تصویر
- عنوان
- تاریخ برد
- کد جایزه
- وضعیت
- تاریخ انقضا
وضعیتها
NewUsedDeliveredExpired
17. ساختار پنل مدیریت
منوی اصلی پیشنهادی:
Dashboard
Campaigns
Prizes
Users
Spins
Winners
Chance Management
SMS
Reports
Settings
18. Dashboard
KPIها
- تعداد کاربران
- کاربران امروز
- تعداد کل Spin
- Spin امروز
- تعداد برندگان
- تعداد جوایز توزیعشده
- شانسهای مصرفشده
- موجودی جوایز
نمودارها
- Spin بر اساس روز
- ثبتنام بر اساس روز
- توزیع جوایز
جدول
آخرین برندگان نیز نمایش داده شوند.
19. صفحه Spinها
تمام چرخشها در این بخش ثبت و قابل مشاهده باشند.
ستونها
| ستون | توضیح |
|---|---|
| ID | شناسه Spin |
| Mobile | شماره موبایل |
| Campaign | کمپین |
| Prize | جایزه |
| Date | تاریخ |
| Time | ساعت |
| Status | وضعیت |
| IP | IP درخواست |
| User Agent | Device / Browser اطلاعاتی |
قابلیتها
- Search
- Filter
- Pagination
- Export Excel
20. صفحه Winners
اطلاعات
- شماره موبایل
- جایزه
- کمپین
- زمان برد
- کد جایزه
- وضعیت تحویل
وضعیت جایزه فیزیکی
جدید → تماس گرفته شد → تحویل شد
وضعیت کد تخفیف
فعال → استفاده شد → منقضی شد
21. سیستم کد جایزه
برای Prizeهایی که نیاز به Code دارند، سیستم باید Unique Code تولید کند.
نمونه:
MNT-8F4KD2
قوانین:
- هر Code فقط متعلق به یک Winner باشد.
- امکان Import مجموعه Codeها در نسخه توسعهیافته پیشبینی شود.
- نمونه: فروشگاه 500 کد تخفیف آماده دارد و آنها را وارد سامانه میکند.
22. SMS Service
SMS باید بهصورت Service مستقل پیادهسازی شود تا Provider در آینده قابل تعویض باشد.
Templateهای پایه
- OTP
- Winning
- No Prize
- Prize Reminder
نمونه پیام:
تبریک! شما برنده کارت هدیه ۱ میلیون تومانی شدید. کد پیگیری: MNT-72F5
SMS Log
تمام SMSها باید Log شوند.
| فیلد | توضیح |
|---|---|
| mobile | شماره گیرنده |
| template | Template |
| message | متن ارسالشده |
| provider | سرویسدهنده |
| created_at | زمان |
| status | وضعیت |
| provider_response | پاسخ Provider |
قانون مهم: Fail شدن SMS نباید باعث Rollback شدن Spin موفق شود.
23. جلوگیری از Spin تکراری
برای درخواست Spin از Idempotency Key استفاده شود.
هر درخواست Spin باید یک شناسه یکتا داشته باشد.
اگر همان Request دوباره ارسال شد:
- نتیجه قبلی برگردانده شود.
- Chance مجدد مصرف نشود.
- Prize مجدد توزیع نشود.
- Spin جدید ثبت نشود.
نمونه:
{
"idempotency_key": "uuid"
}
24. امنیت و Anti-Fraud
حداقل کنترلهای لازم:
- OTP Verification
- Rate Limiting
- Authentication Token / Session
- Server-Side Spin
- Idempotency
- IP Logging
- User Agent Logging
- محدودیت درخواست
- جلوگیری از Concurrent Spin
- Transaction برای Prize Inventory
- Admin Audit Log
هیچ مقدار حساسی مانند موارد زیر نباید توسط Frontend تعیین شود:
- Chance
- Prize ID
- Weight
- Winner
25. Admin Audit Log
تمام تغییرات مهم مدیر باید ثبت شوند.
نمونه:
Admin X
در تاریخ X
برای کاربر 0912...
5 شانس اضافه کرد.
یا:
احتمال جایزه «کارت هدیه»
از 10 به 20 تغییر کرد.
Audit Log برای بررسی اختلافات و Trace تغییرات ضروری است.
26. مدل پیشنهادی دیتابیس
admins
idnamemobileemailpasswordstatuscreated_at
users
idmobilenamestatuslast_login_atcreated_at
campaigns
idtitleslugdescriptionimagebannerlogostart_atend_atstatusdefault_chancesrulescta_textsettingscreated_atupdated_at
prizes
idcampaign_idtitledescriptionimagetypestock_typeinitial_stockremaining_stockweightstatussort_ordersegment_colorexpires_atsms_templatecreated_at
user_campaigns
iduser_idcampaign_idtotal_chancesused_chancescreated_at
chance_transactions
iduser_idcampaign_idamounttypereference_typereference_iddescriptioncreated_bycreated_at
spins
iduser_idcampaign_idprize_ididempotency_keyipuser_agentcreated_at
user_prizes
iduser_idcampaign_idprize_idspin_idcodestatuswon_atredeemed_at
sms_logs
iduser_idmobiletypemessageproviderstatusprovider_responsecreated_at
admin_logs
idadmin_idactionentity_typeentity_idold_valuenew_valueipcreated_at
27. APIهای اصلی کاربر
Authentication
POST /api/auth/send-otp
POST /api/auth/verify-otp
Campaign
GET /api/campaigns/{slug}
GET /api/campaigns/{slug}/wheel
User
GET /api/me
GET /api/me/chances
GET /api/me/prizes
Spin
POST /api/campaigns/{id}/spin
نمونه Request
{
"idempotency_key": "uuid"
}
نمونه Response
{
"success": true,
"spin_id": 1251,
"prize": {
"id": 7,
"title": "تخفیف 30 درصد",
"segment": 4,
"code": "MNT-7F92K"
},
"remaining_chances": 2
}
28. APIهای پنل مدیریت
- Campaign CRUD
- Prize CRUD
- User List / Detail
- Add / Remove Chance
- Spin List
- Winner List
- Prize Status Update
- Reports
- SMS Logs
- Admin Logs
تمام APIهای مدیریت باید Authentication و Authorization مستقل Admin داشته باشند.
29. خطاها و Edge Caseها
Frontend باید برای موارد زیر UI مناسب داشته باشد:
- شانس کافی نیست.
- کمپین هنوز شروع نشده.
- کمپین تمام شده.
- کمپین موقتاً متوقف است.
- درخواست نامعتبر است.
- اینترنت قطع شده است.
- درخواست Spin تکراری است.
- خطای سرور رخ داده است.
در خطای شبکه، کاربر نباید بدون مشخص شدن وضعیت Request قبلی، Spin جدید ایجاد کند.
30. تنظیمات ظاهری کمپین
ساختار settings باید برای توسعه آینده آماده باشد و حداقل موارد زیر را پشتیبانی کند:
- Logo
- Background
- Primary Color
- Secondary Color
- متن بالای گردونه
- متن دکمه
- تصویر Header
- قوانین
- Celebration Effect
بنابراین هر کمپین میتواند ظاهر برند مستقل خود را داشته باشد.
31. Responsive Design
اولویت تجربه کاربر
- Mobile
- Tablet
- Desktop
گردونه در موبایل باید بدون Horizontal Scroll و بهصورت کامل قابل مشاهده باشد.
پنل مدیریت Desktop First ولی Responsive باشد.
32. گزارشها
گزارشهای MVP
- تعداد کاربران
- تعداد Spin
- تعداد Spin موفق
- تعداد جوایز توزیعشده
- تعداد هر Prize
- شانس مصرفشده
- کاربران بدون Spin
- کاربران با شانس باقیمانده
- روند روزانه مشارکت
فیلترها
- از تاریخ
- تا تاریخ
- کمپین
- جایزه
خروجی
- Excel
33. قابلیتهای خارج از MVP اما معماریپذیر
معماری باید امکان افزودن موارد زیر را حفظ کند:
- دریافت شانس با خرید
- اتصال API فروشگاه
- QR Code
- Referral
- معرفی دوست
- Scratch Card
- Mystery Box
- مسابقه
- Quiz
- Daily Spin
- Birthday Spin
- Coupon System
- اتصال CRM
- Webhook
- Multi-Brand
- White Label
34. محدوده MVP
نسخه اول شامل موارد زیر است:
- ورود با موبایل و OTP
- ایجاد کمپین
- مدیریت کمپین
- تعریف جوایز
- موجودی جایزه
- Weight جایزه
- تعریف تعداد شانس
- مدیریت کاربران
- اضافه / کم کردن دستی شانس
- گردونه کاربر
- Spin سمت Backend
- کسر شانس
- ثبت نتیجه
- مدیریت موجودی
- نمایش نتیجه
- ارسال SMS
- صفحه جوایز من
- لیست Spinها
- لیست برندگان
- داشبورد آماری
- گزارش اولیه
- Audit Log
- Anti Duplicate Spin
35. Acceptance Criteria
| ID | معیار پذیرش |
|---|---|
| AC-01 | کاربر بدون شماره موبایل تأییدشده امکان Spin ندارد. |
| AC-02 | کاربری که صفر شانس دارد امکان Spin ندارد. |
| AC-03 | هر Spin دقیقاً یک Chance مصرف میکند. |
| AC-04 | Refresh صفحه باعث دریافت Chance جدید نمیشود. |
| AC-05 | نتیجه Spin فقط توسط Backend مشخص میشود. |
| AC-06 | کاربر نمیتواند Prize ID موردنظر خودش را برای Backend ارسال کند و با آن نتیجه را تعیین کند. |
| AC-07 | Prize بدون موجودی قابل برندهشدن نیست. |
| AC-08 | در درخواست همزمان، موجودی Prize منفی نمیشود و بیش از موجودی واقعی توزیع نمیشود. |
| AC-09 | ارسال مجدد یک Spin Request باعث مصرف Chance دوم نمیشود. |
| AC-10 | تمام Spinها قابل Audit هستند. |
| AC-11 | تغییر Chance توسط Admin در Log ثبت میشود. |
| AC-12 | نتیجه برد حتی در صورت Fail شدن SMS در سیستم ذخیره میماند. |
| AC-13 | کاربر پس از ورود مجدد میتواند جوایز قبلی خود را مشاهده کند. |
| AC-14 | کمپین خارج از بازه زمانی قابل Spin نیست. |
36. معماری پیشنهادی
┌─────────────────────┐
│ User Frontend │
│ Mobile First UI │
└──────────┬──────────┘
│
▼
┌─────────────────────┐
│ Backend API │
├─────────────────────┤
│ Auth / Campaign │
│ User / Chance │
│ Spin Engine │
│ Winner / Reports │
└──────────┬──────────┘
│
▼
┌─────────────────────┐
│ Business Logic │
│ / Spin Engine │
└──────────┬──────────┘
│
▼
┌─────────────────────┐
│ Database │
└─────────────────────┘
┌──────────────┐
│ SMS Service │
└──────┬───────┘
│
Queue / Job System
┌──────────────┐
│ Admin Panel │
└──────────────┘
منطق قرعهکشی باید بهصورت Service مستقل داخل Backend پیادهسازی شود تا الگوریتم در آینده بدون تغییر Frontend قابل توسعه یا تعویض باشد.
37. قاعده حیاتی اجرای Spin
ترتیب صحیح
Request Spin
↓
Backend Decision
↓
Database Commit
↓
Response
↓
Wheel Animation
ترتیب ممنوع
Wheel Animation
↓
Frontend Random
↓
Save Result
تمام قوانین Chance، Inventory و Winner باید در Backend کنترل شوند.
38. Definition of Done برای MVP
نسخه MVP زمانی آماده تحویل است که:
- تمام قابلیتهای Scope MVP پیادهسازی شده باشند.
- Spin فقط از Backend نتیجه بگیرد.
- Idempotency برای Spin فعال باشد.
- Race Condition مربوط به Inventory کنترل شده باشد.
- Chance Ledger و Audit Log ثبت شوند.
- SMS Failure باعث Rollback Spin نشود.
- Acceptance Criteriaهای AC-01 تا AC-14 پاس شوند.
- تجربه Mobile First گردونه بدون Horizontal Scroll باشد.
- پنل مدیریت برای Campaign، Prize، User، Spin، Winner و Report قابل استفاده باشد.
39. نکات پیادهسازی برای تیم توسعه
- منطق Spin را داخل یک Service مستقل نگه دارید.
- تغییر Chance و Inventory باید قابل Audit باشد.
- هیچ نتیجهای از Frontend قابل اعتماد نیست.
idempotency_keyباید برای هر Spin یکتا و قابل ردیابی باشد.- عملیات Spin شامل مصرف Chance، انتخاب Prize، کنترل Inventory و ثبت نتیجه باید Atomic باشد.
- ارسال SMS از فرآیند اصلی Spin جدا و ترجیحاً Queue-based باشد.
- معماری برای Campaignهای متعدد و قابلیتهای Gamification آینده قابل توسعه نگه داشته شود.
مرجع اصلی این سند: مشخصات اولیه سامانه گردونه شانس و قرعهکشی، نسخه 1.0.