Files
MathApp/subscription/migrations/0016_subscriptions_only_2026_10.py
Zareian 9c3adc3e60 Subscriptions only: Bazaar panel prices (598/898/1398k), assistant quota 5/3/3 from a cost calculation, packs off sale
- subscription.0016: prices equal to the Bazaar panel (senior), ai_daily_quota 5/3/3, card features; packs on_sale=False
  (one paid pack order, user 26, keeps its credits; pack paths stay for that order and for admin).
- Quota math in docs/ai-cost-and-guardrails.md: ~77% of a Bazaar sale reaches us; worst case (full quota every day)
  the assistant costs 23/27/35% of it.
- Assistant quota message points to the subscription, not packs.
982 tests green.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 19:57:16 +03:30

39 lines
2.8 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
فقط اشتراک (تصمیمِ سینیور، ۲۰۲۶-۱۰-۱۲): بسته‌های سوال از فروش برمی‌دارند، قیمت‌ها همان قیمتِ پیشخانِ بازار.
- قیمت: یک‌ماهه ۵۹۸، سه‌ماهه ۸۹۸، شش‌ماهه ۱٬۳۹۸ هزار تومان (به گفته‌ی سینیور همان قیمتِ پیشخان؛ ما پیشخان را ندیده‌ایم).
- سقفِ دستیار در روز: یک‌ماهه ۵، سه‌ماهه و شش‌ماهه ۳. حساب (docs/ai-cost-and-guardrails.md «اشتراک‌ها»): هر سوال ~۷۰۰ تومان
(دستِ بالا)، و از هر خریدِ بازار پس از ارزشِ افزوده و سهمِ ۱۵٪ِ بازار ~۷۷٪ می‌رسد. اگر کسی هر روز کلِ سقف را بپرسد، هزینه‌ی
دستیار ۲۳٪، ۲۷٪ و ۳۵٪ِ آن می‌شود. ادمین می‌تواند عوضش کند.
- مزیت‌های کارت: دو خطِ ثابت؛ خطِ دستیار را فرانت از `aiDailyQuota` می‌سازد تا با سقفِ واقعی جدا نیفتد.
- بسته‌ها on_sale=False، نه حذف: یک خریدِ واقعی (کاربرِ ۲۶) و اعتبارِ مانده‌اش به آن‌ها بسته است و بازپرداخت از سفارش می‌خواند.
پلن‌ها با مدت پیدا می‌شوند (idها بین دیتابیس‌ها فرق دارند)؛ اگر دقیقاً یکی نباشد، migration می‌شکند.
"""
from django.core.cache import cache
from django.db import migrations
PLANS = {30: (598000, 5), 90: (898000, 3), 180: (1398000, 3)}
FEATURES = ['همه‌ی فصل‌ها و جزیره‌ها باز', 'قلبِ نامحدود']
def forward(apps, schema_editor):
Plan = apps.get_model('subscription', 'Plan')
for days, (price, quota) in PLANS.items():
plans = list(Plan.objects.filter(kind='subscription', on_sale=True, duration_days=days))
if len(plans) != 1:
raise RuntimeError(f'باید دقیقاً یک اشتراکِ فروشیِ {days} روزه باشد، {len(plans)} تا پیدا شد.')
plan = plans[0]
plan.price = price
plan.ai_daily_quota = quota
plan.features = FEATURES
plan.save(update_fields=['price', 'ai_daily_quota', 'features'])
Plan.objects.filter(kind='pack').update(on_sale=False)
cache.delete('subscription:plans:v3') # migration سیگنالِ post_save را نمی‌زند (0014)
class Migration(migrations.Migration):
dependencies = [('subscription', '0015_bazaar_sku_monthly')]
# بازگشت ندارد: قیمت و سقفِ قبلی تصمیمِ کهنه‌اند، نه حالتی که بخواهیم به آن برگردیم.
operations = [migrations.RunPython(forward, migrations.RunPython.noop)]