Question packs removed at the root; all subscriptions 4 assistant questions a day; Bazaar is subscription-only

- subscription.0017/0018, payment.0013: pack plans deleted, QuestionCredit/HeartsPass models and Plan.kind /
  question_credits / hearts_days / Order.question_credits / hearts_days dropped. The only paid pack order was the
  company owner's test account (user 26).
- Assistant: no credit spending; quota is the daily cap only (free 2, every plan 4, gift subscription 4).
- Bazaar: verify_purchase is subscription-only (no inapp guess), start/purchase responses lose productType,
  verify refuses an order without a subscription. A paid order with no subscription now logs ERROR.
- Removed POST /api/payment/orders (internal; no caller). Its permission tests stay.
- Pack-based tests rewritten on subscriptions (refund, security, Bazaar token); pack-only test files deleted.
- docs: profit table for 4/day on both payment routes plus free users; handbook, operations, CLAUDE.md current.
949 tests green.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-12 20:33:38 +03:30
parent 9c3adc3e60
commit 947f946909
39 changed files with 398 additions and 1174 deletions

View File

@@ -25,9 +25,9 @@ class Message(models.Model):
role = models.CharField(max_length=10, choices=ROLE_CHOICES)
text = models.TextField()
question_id = models.IntegerField(null=True, blank=True) # ارجاع سبک به content.Question
# فقط برای پیامِ کاربر: این سوال از کجا پرداخت شد. «free» از سهمیه‌ی روزانه، «credit» از
# اعتبارِ بسته (subscription.QuestionCredit)، «none» هیچ (رد در صافیِ سرور یا جوابِ کش‌شده که
# به API نرسید). سهمیه‌ی رایگانِ امروز = تعدادِ «free»های امروز.
# فقط برای پیامِ کاربر: این سوال از کجا پرداخت شد. «free» از سهمیه‌ی روزانه، «none» هیچ (رد در صافیِ
# سرور یا جوابِ کش‌شده که به API نرسید). سهمیه‌ی امروز = تعدادِ «free»های امروز. «credit» (اعتبارِ بسته‌ی
# سوال) فقط روی پیام‌های پیش از subscription.0017 است؛ دیگر نوشته نمی‌شود ولی ردِ تاریخیِ آن پیام‌هاست.
CHARGE_CHOICES = [('free', 'رایگانِ روزانه'), ('credit', 'اعتبارِ بسته'), ('none', 'بی‌هزینه')]
charge = models.CharField(max_length=6, choices=CHARGE_CHOICES, blank=True, default='')
# ایندکس: سقفِ روزانه‌ی کلِ سامانه (_check_global_daily_cap) در هر سوال پیام‌های امروزِ همه را