Files
Lucky_Wheel/docs/Lucky_Wheel_Lottery_Spec_v1_0.md
T
2026-09-10 01:58:29 +03:30

25 KiB

داکیومنت فنی و اجرایی سامانه گردونه شانس و قرعه‌کشی

نسخه: 1.0
نوع سیستم: Web Application / Mobile First
وضعیت: MVP Specification
هدف: ایجاد و مدیریت کمپین‌های گردونه شانس با قابلیت تعریف جایزه، تخصیص شانس به کاربران، ثبت قرعه‌کشی، مدیریت برندگان، ارسال پیامک و گزارش‌گیری.


1. خلاصه محصول

سامانه از دو بخش اصلی تشکیل می‌شود:

  1. پنل کاربر و تجربه گردونه شانس
  2. پنل مدیریت

مدیر سیستم باید بتواند کمپین ایجاد کند، جوایز و موجودی آن‌ها را تعریف کند، تعداد شانس کاربران را مدیریت کند و نتایج تمام 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-otp
  • POST /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 زمان ویرایش

وضعیت‌ها

  • Draft
  • Active
  • Paused
  • Finished

شرط فعال بودن

فقط کمپین‌هایی که وضعیت 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 نوع جایزه

نوع جایزه

  • Physical
  • Discount Code
  • Credit
  • Cash
  • No Prize
  • Other

نوع موجودی

  • Limited
  • Unlimited

نمونه:

  • آیفون — 1 عدد
  • کارت هدیه — 10 عدد
  • تخفیف 30٪ — 100 عدد
  • تخفیف 10٪ — نامحدود
  • بدون جایزه — نامحدود

7. موتور Spin

اصل کلیدی

Spin باید کاملاً Backend-Based باشد.

Frontend فقط درخواست را ارسال می‌کند و پس از دریافت نتیجه، Animation را اجرا می‌کند.

ترتیب اجرای Spin

  1. بررسی Authentication Token
  2. بررسی فعال بودن کمپین
  3. بررسی تعداد شانس کاربر
  4. بررسی Prizeهای فعال
  5. بررسی موجودی Prizeهای محدود
  6. اعمال قوانین کمپین
  7. انتخاب نتیجه توسط Backend
  8. مصرف یک Chance
  9. کاهش موجودی Prize در صورت محدود بودن
  10. ثبت Spin
  11. بازگرداندن نتیجه به Frontend
  12. اجرای انیمیشن گردونه روی Segment تعیین‌شده
  13. ارسال 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_chances
  • used_chances
  • remaining_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

  1. کاربر دکمه Spin را لمس می‌کند.
  2. دکمه فوراً Disable می‌شود.
  3. Loading کوتاه نمایش داده می‌شود.
  4. درخواست به Backend ارسال می‌شود.
  5. Backend نتیجه را مشخص می‌کند.
  6. گردونه چند دور کامل می‌چرخد.
  7. گردونه دقیقاً روی Segment برگردانده‌شده متوقف می‌شود.
  8. تا پایان Animation امکان Spin مجدد وجود ندارد.
  9. Modal نتیجه نمایش داده می‌شود.

15. صفحه نتیجه

در صورت برد

🎉 تبریک!

شما برنده شدید

[ تصویر جایزه ]

نام جایزه

کد جایزه: MNT-X7D92

CTA:

  • در صورت وجود شانس: «یک شانس دیگه دارم»
  • در صورت تمام شدن شانس: «مشاهده جوایز من»

16. جوایز من

کاربر باید تاریخچه جوایز خود را مشاهده کند.

هر Card شامل:

  • تصویر
  • عنوان
  • تاریخ برد
  • کد جایزه
  • وضعیت
  • تاریخ انقضا

وضعیت‌ها

  • New
  • Used
  • Delivered
  • Expired

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

  • id
  • name
  • mobile
  • email
  • password
  • status
  • created_at

users

  • id
  • mobile
  • name
  • status
  • last_login_at
  • created_at

campaigns

  • id
  • title
  • slug
  • description
  • image
  • banner
  • logo
  • start_at
  • end_at
  • status
  • default_chances
  • rules
  • cta_text
  • settings
  • created_at
  • updated_at

prizes

  • id
  • campaign_id
  • title
  • description
  • image
  • type
  • stock_type
  • initial_stock
  • remaining_stock
  • weight
  • status
  • sort_order
  • segment_color
  • expires_at
  • sms_template
  • created_at

user_campaigns

  • id
  • user_id
  • campaign_id
  • total_chances
  • used_chances
  • created_at

chance_transactions

  • id
  • user_id
  • campaign_id
  • amount
  • type
  • reference_type
  • reference_id
  • description
  • created_by
  • created_at

spins

  • id
  • user_id
  • campaign_id
  • prize_id
  • idempotency_key
  • ip
  • user_agent
  • created_at

user_prizes

  • id
  • user_id
  • campaign_id
  • prize_id
  • spin_id
  • code
  • status
  • won_at
  • redeemed_at

sms_logs

  • id
  • user_id
  • mobile
  • type
  • message
  • provider
  • status
  • provider_response
  • created_at

admin_logs

  • id
  • admin_id
  • action
  • entity_type
  • entity_id
  • old_value
  • new_value
  • ip
  • created_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

اولویت تجربه کاربر

  1. Mobile
  2. Tablet
  3. 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

نسخه اول شامل موارد زیر است:

  1. ورود با موبایل و OTP
  2. ایجاد کمپین
  3. مدیریت کمپین
  4. تعریف جوایز
  5. موجودی جایزه
  6. Weight جایزه
  7. تعریف تعداد شانس
  8. مدیریت کاربران
  9. اضافه / کم کردن دستی شانس
  10. گردونه کاربر
  11. Spin سمت Backend
  12. کسر شانس
  13. ثبت نتیجه
  14. مدیریت موجودی
  15. نمایش نتیجه
  16. ارسال SMS
  17. صفحه جوایز من
  18. لیست Spinها
  19. لیست برندگان
  20. داشبورد آماری
  21. گزارش اولیه
  22. Audit Log
  23. 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. نکات پیاده‌سازی برای تیم توسعه

  1. منطق Spin را داخل یک Service مستقل نگه دارید.
  2. تغییر Chance و Inventory باید قابل Audit باشد.
  3. هیچ نتیجه‌ای از Frontend قابل اعتماد نیست.
  4. idempotency_key باید برای هر Spin یکتا و قابل ردیابی باشد.
  5. عملیات Spin شامل مصرف Chance، انتخاب Prize، کنترل Inventory و ثبت نتیجه باید Atomic باشد.
  6. ارسال SMS از فرآیند اصلی Spin جدا و ترجیحاً Queue-based باشد.
  7. معماری برای Campaignهای متعدد و قابلیت‌های Gamification آینده قابل توسعه نگه داشته شود.

مرجع اصلی این سند: مشخصات اولیه سامانه گردونه شانس و قرعه‌کشی، نسخه 1.0.