give the leaderboard and notifications a real producer
Three gaps found while seeding test data for the frontend, all of the same kind: a contract that looks complete from the outside and is empty underneath. Nothing in the codebase ever wrote a LeaderboardEntry. Not a signal, not a service — only the admin form and seed_test_data. So /api/leaderboard returned `entries: []` forever on any real server, and any row put there was a frozen number that never tracked activity. rebuild_leaderboard now derives both periods from real XP: all_time from UserStats.xp, weekly from a sum over content.UserLessonCompletion in a window. It deliberately does not count UserAnswer.xp_earned — that field is written but never added to UserStats, so summing both would report roughly double. deploy.sh runs it every release; a cron is the real answer once traffic is real, and the script says so. 'lesson_completed' was declared in Notification.TYPE_CHOICES but nothing called notify() with it, so finishing a lesson produced no notification at all. LessonCompleteView now emits one, on first completion only (the same condition that grants xp/coins), inside the completion transaction so a lost notification cannot leave a silent half-done state. The notification list serializer returned only id/type/title/isRead. body and created_at were on the model from the start but never exposed, so the frontend had neither the text of a notification nor its time. Both added; the change is purely additive, so the existing client keeps working. 472 tests green, up from 458. makemigrations --check, check and spectacular are all clean. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
13
deploy.sh
13
deploy.sh
@@ -175,6 +175,19 @@ step "محتوای پایه"
|
||||
python manage.py seed_content 2>&1 | sed 's/^/ /' \
|
||||
|| warn "seed_content شکست خورد؛ کد بهروز شد ولی محتوا دستنخورده ماند."
|
||||
|
||||
# جدولِ لیدربورد کاملاً مشتقشده است و تا پیش از این هیچ تولیدکنندهای نداشت —
|
||||
# یعنی /api/leaderboard روی سرورِ واقعی همیشه `entries: []` میداد. این مرحله
|
||||
# آن را در هر ریلیز از روی XPی واقعی از نو میسازد.
|
||||
#
|
||||
# ⚠️ این «تازهسازیِ هر ریلیز» است، نه یک زمانبندِ واقعی: بینِ دو دیپلوی،
|
||||
# رتبهها ثابت میمانند. وقتی ترافیک واقعی شد، همین دستور باید در یک cron
|
||||
# (مثلاً هر ساعت) بنشیند.
|
||||
#
|
||||
# ایدمپوتنت است و شکستش دیپلوی را نمیخواباند.
|
||||
step "بازسازیِ لیدربورد"
|
||||
python manage.py rebuild_leaderboard 2>&1 | sed 's/^/ /' \
|
||||
|| warn "rebuild_leaderboard شکست خورد؛ رتبهها از اجرای قبلی ماندهاند."
|
||||
|
||||
# ─── ۵. فایلهای استاتیک ───────────────────────────────────────────────────
|
||||
# بیقید و شرط اجرا میشود، حتی وقتی DEBUG روشن است.
|
||||
#
|
||||
|
||||
Reference in New Issue
Block a user