8.1 KiB
Profile Gamification Implementation Plan
Overview
Replace the signed-in profile overview's duplicate recent-events section with a lifetime community-contribution rank card. Calculate points from verified event attendance and real blog contributions, show a global level plus separate activity badges, and expose earned badges on public profiles. Payments, transaction amounts, a leaderboard, and a new Q&A feature are out of scope.
Decisions
- Lifetime global levels are fixed thresholds: همراه (0), مشارکتگر (30), همیار (150), اثرگذار (750), and پیشرو (1,500). The first advancement is one verified attendance; the second aligns with five verified attendances. The dry run showed no event-only history above 150 points, so the remaining thresholds stay aspirational until trusted blog contributions accumulate.
- Draft point values: verified attendance 30; published/coauthored post 20 per credited author; approved comment or reply 5; like and save 1 to the actor and 1 to each credited post author. No caps; reverse points when the source activity becomes invalid.
- A user's own like/save counts, but this plan assumes one point total for a self-action rather than awarding the same user in both roles. For a coauthored post, this plan assumes each credited author receives the engagement point.
- Badge ladders are separate for attendance (1/5/10/25), published posts (1/5/10), approved comments/replies (5/20/50), and likes given plus received combined (10/50/100). Saves have no badge ladder. These are draft thresholds; tune them alongside global thresholds.
- Public profiles show the global level badge and earned activity badges regardless of personal-detail visibility. They do not show points, progress, category totals, or a leaderboard.
- Trust existing event registrations whose current status is attended for historical backfill. Going forward, only staff/system actions can verify attendance. Do not backfill blog activity because existing activity is not reliable; scoring starts with valid actions after rollout.
- Remove the recent-events card from the overview only; retain the Events tab and its registration list.
- Start with existing blog posts, comments/replies, likes, and saves. Defer Q&A, votes, and accepted answers.
Architecture
Add an apps/gamification domain to the backend. Keep source actions in their owning apps and record their scoring effects in an idempotent, auditable ledger. Each award must identify the user, activity category, source action, point amount, and reversal relationship/reason. Use database uniqueness and transactions so retries cannot award twice. The displayed score is the sum of valid awards and reversals; levels and badges are derived from that current valid state.
Integrate the ledger at the domain transition points: staff/system attendance verification; post publication and credited-writer changes; comment approval/removal; like and save creation/removal. Avoid relying only on model signals where bulk updates bypass them; route admin actions and APIs through shared services. Reconciliation commands should be safe to rerun.
Expose an authenticated summary for the signed-in user and add badge-only fields to the public-profile response. The authenticated summary includes lifetime points, current/next level and progress, event/blog point totals, and earned badges. Public serialization includes only public badge identifiers/labels and the level badge, without numeric scores or category activity.
Frontend changes belong in the profile overview and public profile. Use the existing Dialog component for an accessible Persian help modal. Reuse existing design tokens, number formatting, RTL layout, loading, and error patterns.
Ordered Tasks
Phase 1: Scoring foundation
- Add gamification models, fixed rule definitions, aggregation services, and tests for ledger idempotency, reversal, tier thresholds, badge thresholds, and current totals.
- Add a dry-run/report command for event-history distributions and threshold calibration. It must not write ledger rows by default.
Checkpoint: tests cover duplicate delivery and reversal; dry run reports attendance counts and projected point/level/badge distributions without modifying data.
Phase 2: Trusted source activity
- Secure attendance verification: reject attendee self-updates to attended, persist who/what verified attendance and when for new records, and route staff/admin attendance changes through the scoring service.
- Add an idempotent event backfill for existing attended registrations. Provide dry-run and apply modes; exclude confirmed, pending, cancelled, payment, and transaction data.
- Connect blog publication/coauthoring, approved comments/replies, likes, and saves to the ledger. Reverse entries when a source is unpublished, unapproved, hidden, deleted, unliked, or unsaved. Do not import historical blog activity.
Checkpoint: integration tests prove attendance cannot be self-awarded, trusted history is backfilled once, valid blog sources award once, and invalidated sources reverse points and badges.
Phase 3: API and profile surfaces
- Add the authenticated gamification summary endpoint and extend public-profile output with only earned badges and the global level badge. Add authorization, privacy, and serialization tests.
- Replace the recent-events card in the signed-in overview with a rank card showing level, points-to-next-level progress, event/blog point breakdown, and earned badges. Add a question-mark control opening a keyboard-accessible help dialog explaining scores, reversals, badge ladders, and rank progression.
- Display earned rank/activity badges on public profiles even when personal details are hidden. Do not expose scores, category totals, or progress publicly.
Checkpoint: authenticated and public-profile tests confirm the separate data contracts and badge visibility; frontend build and local browser inspection confirm the RTL layout and modal behavior.
Phase 4: Calibration and release
- Run dry-run reports using approved event history, review projected level/badge distribution, tune draft thresholds, apply the event backfill once, and verify reconciled totals. Completed in the local development database: 297 attended registrations across 248 users, 8,910 net attendance points, and level projection of 245 contributors / 3 allies.
- Deploy scoring and UI together; monitor award/reversal errors and provide a safe reconciliation command for recovery.
Likely Files
Backend: apps/gamification (new app), apps/events/models.py, apps/events/api/views.py, apps/events/admin.py, apps/blog/models.py, apps/blog/api/views.py, apps/users/api/views.py, apps/users/api/schemas.py, config/api.py, and focused app tests/migrations.
Frontend: src/views/Profile.tsx, src/views/PublicProfile.tsx, src/lib/api.ts, src/lib/types.ts, and focused component/API tests. Reuse src/components/ui/dialog.tsx.
Risks and Mitigations
| Risk | Mitigation |
|---|---|
| Current event rows do not record who marked attendance | Trust current attended rows only for the explicitly approved historical backfill; persist verifier/source metadata for future transitions. |
| Bulk updates can bypass model hooks | Centralize scoring in domain services and route API/admin transitions through them; include reconciliation tests. |
| Repeated callbacks or toggling actions can inflate totals | Unique source-action awards, atomic updates, reversal linkage, and tests for unlike/relike and repeated delivery. |
| Historical blog actions are not trustworthy | Start blog scoring at rollout and do not backfill those rows. |
| Draft thresholds could make top levels too easy or unreachable | Dry-run against trusted event history before applying the final thresholds. |
| Public rank could leak private activity | Public API returns badges only; keep exact points and category totals in the authenticated endpoint. |
Open Assumptions for Review
- Confirmed implementation choices: a self-like/save earns one point total; engagement on a coauthored post credits each other credited author.
- Activity badge thresholds remain provisional; blog data will not be used for historical calibration.