Paywall: first unit of each grade free; 1/3/6-month subscriptions; AI sold separately
- content: unit_is_free/has_unit_access; questions, node quiz, answer and lesson/node complete return 402 subscription_required outside the first unit without an active subscription. /api/home units carry requiresSubscription. - subscription.0013: monthly 498k, quarterly 798k, six-month 1,298k toman, unlimited hearts, 3 AI questions/day; packs stay on sale for more questions. - AI_DAILY_QUOTA_FREE default 3 -> 2. - /api/subscription/status adds planTitle, planDurationDays, aiDailyQuota. - tests: content/tests_paywall.py; existing unlock-order tests get a subscription. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -51,8 +51,9 @@ Message.objects.filter(role='assistant', created_at__gte=since).values('conversa
|
||||
|
||||
پلنهای اشتراکی پاک نشدند (`on_sale=False`) تا مشترکِ فعلی سقفش را نگه دارد.
|
||||
|
||||
- **ترتیبِ خرج:** اول `AI_DAILY_QUOTA_FREE` سوالِ رایگانِ همان روز (پیشفرض ۳)، بعد اعتبارِ بسته؛ مشترکِ
|
||||
قدیمی سقفِ `Plan.ai_daily_quota`ِ خودش را دارد.
|
||||
- **ترتیبِ خرج:** اول سقفِ روزانه (بیاشتراک `AI_DAILY_QUOTA_FREE`، پیشفرض ۲؛ مشترک `Plan.ai_daily_quota`،
|
||||
برای یک/سه/ششماهه ۳)، بعد اعتبارِ بسته. اشتراک محتوا و قلب میفروشد؛ سوالِ بیشتر از دستیار فقط با بسته.
|
||||
بدترین حالتِ مشترکِ ششماهه با سقفِ ۳: ~۶۳ هزار تومان در ماه، ۲۹٪ِ سهمِ ماهانهی قیمت.
|
||||
- **چه چیزی خرج میشود:** هر سوالی که به API برسد، از جمله ردِ «غیرِ ریاضی» توسطِ مدل. ردِ صافیِ سرور،
|
||||
جوابِ کششده و جوابی که ساخته نشد چیزی کم نمیکنند. `Message.charge` روی هر پیامِ کاربر میگوید
|
||||
سوال از کجا پرداخت شد (`free` / `credit` / `none`).
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
| ۸ | سرور بدونِ ArvanCloud روی پورتِ ۸۰ هم جواب میدهد | متوسط | ادمینِ سرور |
|
||||
| ۹ | کشِ مشترک بینِ workerها نیست (Redisِ اختصاصی)؛ سقفهای مبتنی بر کش ≈ ۳ برابرند | متوسط | تصمیم + ساختِ Redis |
|
||||
| ۱۱ | کدِ OTP بیهش در دیتابیس و در فهرستِ پنل | کم | کد |
|
||||
| ۱۲ | هزینهی دستیارِ AI با ساختِ شمارهی تازه (هر شماره ۳ سوالِ رایگان) قابلِ بالا بردن است | کم (مالی) | کد |
|
||||
| ۱۲ | هزینهی دستیارِ AI با ساختِ شمارهی تازه (هر شماره ۲ سوالِ رایگان) قابلِ بالا بردن است | کم (مالی) | کد |
|
||||
| ۱۴ | SQLite روی دیسکِ مشترکِ پُر؛ بکاپِ پیش از migrate خودکار است ولی بیرون از ماشین نیست | کم (داده) | زیرساخت |
|
||||
| ۱۵ | دسترسیِ سرور: حسابِ مشترک، رمز، sudoِ کامل | بالا | ادمینِ سرور |
|
||||
| ۱۶ | فرانت توکن را در `localStorage` نگه میدارد | کم | فرانت |
|
||||
@@ -106,8 +106,8 @@
|
||||
|
||||
## ۱۲. هزینهی دستیارِ AI
|
||||
|
||||
- **چیست:** هر کاربر روزی ۳ سؤالِ رایگان دارد (`AI_DAILY_QUOTA_FREE`)
|
||||
و بعد فقط با اعتبارِ خریدهشده؛ ۲۰ در ساعت. هر شمارهی تازه ۳ سؤالِ رایگان میگیرد و ساختنِ شماره با سقفِ پیامک
|
||||
- **چیست:** هر کاربر روزی ۲ سؤالِ رایگان دارد (`AI_DAILY_QUOTA_FREE`)
|
||||
و بعد فقط با اعتبارِ خریدهشده؛ ۲۰ در ساعت. هر شمارهی تازه ۲ سؤالِ رایگان میگیرد و ساختنِ شماره با سقفِ پیامک
|
||||
(بند ۲۴) محدود است. سقفِ
|
||||
روزانهی کلِ سامانه (`AI_GLOBAL_DAILY_MAX`، ۳۰۰۰) خرجِ کل را محدود میکند. طولِ سؤال حداکثر ۲۰۰۰ نویسه است.
|
||||
- **خطر:** با چند IP، اعتبارِ GapGPT در چند ساعت تمام میشود (اعتبار یک بار در ۲۰۲۶-۰۹-۲۵
|
||||
|
||||
@@ -700,7 +700,7 @@ if (Math.sign(y) !== Math.sign(py)) { const r = bisect(f, px, x); if (Math.abs(f
|
||||
| انتخابِ مدلِ جواب: ۱۰۲ مسئلهی تصحیحشدهی دستی | `gpt-4.1-mini` : ۹۵–۹۶ درست · `gpt-4o-mini` : ۸۵–۹۰ |
|
||||
| شکلها: ۶۴ مسئلهی تصادفیِ کتاب، وارسیِ چشمیِ تکتک | ۴۰ درست، ۱۲ قابلِ قبول، ۷ غلط، ۵ بیشکل — حدودِ یکی از پنج هنوز ایراد دارد؛ برای همین شکل همیشه کنارِ حلِ متنی میآید |
|
||||
| سرعت | جوابِ کامل با شکل ~۳۰ ثانیه؛ اندازهگیری شد که در خودِ GapGPT است («فقط بگو سلام» = ۷ ثانیه) |
|
||||
| سقفها | ۳ سؤالِ رایگان در روز، بعد از اعتبارِ بسته؛ ۲۰ در ساعت؛ مهمانها بر اساسِ IP (تا با ساختِ حسابِ مهمانِ تازه دور زده نشود) |
|
||||
| سقفها | ۲ سؤالِ رایگان در روز (مشترک ۳)، بعد از اعتبارِ بسته؛ ۲۰ در ساعت؛ مهمانها بر اساسِ IP (تا با ساختِ حسابِ مهمانِ تازه دور زده نشود) |
|
||||
|
||||
### ۹-۷ فقط ریاضی، و چه چیزی هزینه دارد
|
||||
|
||||
@@ -708,7 +708,7 @@ if (Math.sign(y) !== Math.sign(py)) { const r = bisect(f, px, x); if (Math.abs(f
|
||||
|
||||
| قاعدهی خرج | |
|
||||
|---|---|
|
||||
| ترتیب | اول ۳ سوالِ رایگانِ همان روز، بعد اعتبارِ بسته ( `Message.charge` : `free` / `credit` / `none` ) |
|
||||
| ترتیب | اول سقفِ روزانه (۲ رایگان، مشترک ۳)، بعد اعتبارِ بسته ( `Message.charge` : `free` / `credit` / `none` ) |
|
||||
| خرج میشود | هر سوالی که به مدل برسد، از جمله ردِ «غیرِ ریاضی» توسطِ مدل |
|
||||
| خرج نمیشود | ردِ صافیِ سرور، جوابِ کششده، جوابی که ساخته نشد، و تکرارِ درخواست با همان `Idempotency-Key` |
|
||||
| همزمانی | دو سوالِ همزمان با یک اعتبار فقط یک جواب میگیرند؛ با دو thread واقعی آزموده میشود ( `ai_tutor/tests_credit_concurrency.py` ) |
|
||||
@@ -881,7 +881,7 @@ fetch ← `npm ci` ← بررسیِ نوعها ← build در `dist.next` ←
|
||||
| `ZARINPAL_MERCHANT_ID` · `BAZAAR_*` | پرداخت بسته میماند (۵۰۳). |
|
||||
| `CACHE_URL` | کشِ جدا برای هر worker؛ `/api/health` هشدار میدهد. |
|
||||
| `HEARTS_ENFORCED` · `TEST_LOGIN_PHONES` | روشن (قلب واقعی؛ `0` خاموشش میکند) · هیچ حسابِ آزمایشی. |
|
||||
| `AI_DAILY_QUOTA_FREE` | ۳ سوالِ رایگان در روز. |
|
||||
| `AI_DAILY_QUOTA_FREE` | ۲ سوالِ رایگان در روز (پیشفرض). |
|
||||
| `DJANGO_DEBUG` | خاموش — و **هرگز روی سرور روشن نشود** (کدِ ورودِ همگانیِ `0000` را فعال میکند). |
|
||||
|
||||
مقدارهای `.env` با پیشفرضهای کد ادغام میشوند؛ یک `.env` ِ ناقص سرویس را نمیخواباند. شرحِ کامل در `.env.example` و `docs/operations.md`.
|
||||
|
||||
Reference in New Issue
Block a user