senior's post-demo changes: parent report in the student's own account, Jalali birth date, invoices, math-only tutor, priced quotas

- remove the family app from the root (separate parent accounts, invite codes, parental
  settings); progress.0006 drops its tables, permissions and migration history, and
  Profile.parent_phone, the two family notification types and ?userId= on
  /api/progress/nodes go with it
- GET /api/user/weekly-report: last 7 days next to the 7 before (estimated minutes,
  questions, accuracy, islands, tutor questions) for the "parent report" page
- profile birthDate in Jalali (accounts/jalali.py), ages 5-99, birthYear derived from it
- GET /api/payment/invoices; orders now snapshot list price and plan title
- tutor answers only math: server pre-filter, scope rule in the prompt (tutor-v11),
  refusal marker replaced with fixed text; self-harm gets a help line instead
- streamed answers now record token usage (it was always 0)
- daily tutor quota: AI_DAILY_QUOTA_FREE (default 3) vs Plan.ai_daily_quota
- delete_users management command for wiping test accounts across every app
- docs/ai-cost-and-guardrails.md: measured cost per question and guardrail results

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-02 02:38:43 +03:30
parent d5dbd1b23d
commit 39247f6d53
67 changed files with 1619 additions and 1140 deletions

View File

@@ -0,0 +1,28 @@
# Generated by Django 5.2.17 on 2026-10-01 21:01
from django.db import migrations, models
# اعلان‌های بخشِ والدین (اتصالِ خانواده، گزارشِ هفتگیِ والد) که ۲۰۲۶-۱۰-۰۱ حذف شد.
# نوعشان دیگر در choices نیست، پس ردیف‌های قدیمی هم پاک می‌شوند تا در اپ اعلانِ
# بی‌معنا («فرزندت دعوت را پذیرفت») نماند.
FAMILY_TYPES = ('family_link_accepted', 'weekly_report_ready')
def delete_family_notifications(apps, schema_editor):
apps.get_model('notifications', 'Notification').objects.filter(type__in=FAMILY_TYPES).delete()
class Migration(migrations.Migration):
dependencies = [
('notifications', '0002_alter_notification_type'),
]
operations = [
migrations.RunPython(delete_family_notifications, migrations.RunPython.noop),
migrations.AlterField(
model_name='notification',
name='type',
field=models.CharField(choices=[('xp_earned', 'امتیاز گرفتی'), ('lesson_completed', 'درس تکمیل شد'), ('node_completed', 'جزیره تمام شد'), ('order_paid', 'پرداخت موفق'), ('ticket_replied', 'پاسخ تیکت')], max_length=30),
),
]