Files
chore/specs/archive/feat-dynamic-points/IMPLEMENTATION_SUMMARY.md
T
ryan 7f0326eff1
Chore App Build, Test, and Push Docker Images / build-and-push (push) Successful in 4m51s
feat: add child actions menu and achievements feature design
- Introduced a new feature specification for displaying a menu with actions (Award Certificate, Award Badge) when a child's card is clicked in ParentView.
- Created a detailed plan for an achievements system, outlining phases for implementation, including achievement taxonomy, MVP set, and UX considerations.
- Added a template for future feature specifications to standardize documentation.
2026-07-12 18:52:59 -04:00

4.9 KiB

Tracking Feature Implementation Summary

Implementation Complete

All acceptance criteria from feat-tracking.md have been implemented and tested.


📦 What Was Delivered

Backend

  1. Data Model (tracking_event.py)

    • TrackingEvent dataclass with full type safety
    • Factory method create_event() for server-side timestamp generation
    • Delta invariant validation (delta == points_after - points_before)
  2. Database Layer (tracking.py)

    • New TinyDB table: tracking_events.json
    • Helper functions: insert_tracking_event, get_tracking_events_by_child, get_tracking_events_by_user, anonymize_tracking_events_for_user
    • Offset-based pagination with sorting by occurred_at (desc)
  3. Audit Logging (tracking_logger.py)

    • Per-user rotating file handlers (logs/tracking_user_<user_id>.log)
    • 10MB max file size, 5 backups
    • Structured log format with all event metadata
  4. API Integration (child_api.py)

    • Tracking added to:
      • POST /child/<id>/trigger-task → action: activated
      • POST /child/<id>/request-reward → action: requested
      • POST /child/<id>/trigger-reward → action: redeemed
      • POST /child/<id>/cancel-request-reward → action: cancelled
  5. Admin API (tracking_api.py)

    • GET /admin/tracking with filters:
      • child_id (required if no user_id)
      • user_id (admin only)
      • entity_type (task|reward|penalty)
      • action (activated|requested|redeemed|cancelled)
      • limit (default 50, max 500)
      • offset (default 0)
    • Returns total count for future pagination UI
  6. SSE Events (event_types.py, tracking_event_created.py)

    • New event type: TRACKING_EVENT_CREATED
    • Payload: tracking_event_id, child_id, entity_type, action
    • Emitted on every tracking event creation

Frontend

  1. TypeScript Models (models.ts)

    • TrackingEvent interface (1:1 parity with Python)
    • Type aliases: EntityType, ActionType
    • TrackingEventCreatedPayload for SSE events
  2. API Helpers (api.ts)

    • getTrackingEventsForChild() function with all filter params
  3. SSE Registration

    • Event type registered in type union
    • Ready for future UI components

Tests

Backend Unit Tests (test_tracking.py):

  • Tracking event creation with factory method
  • Delta invariant validation
  • Insert and query tracking events
  • Filtering by entity_type and action
  • Offset-based pagination
  • User anonymization on deletion
  • Points change correctness (positive/negative/zero delta)
  • No points change for request/cancel actions

🔑 Key Design Decisions

  1. Append-only tracking table - No deletions, only anonymization on user deletion
  2. Server timestamps - occurred_at always uses server time (UTC) to avoid client clock drift
  3. Separate logging - Per-user audit logs independent of database
  4. Offset pagination - Simpler than cursors, sufficient for expected scale
  5. No UI (yet) - API/models/SSE only; UI deferred to future phase

🚀 Usage Examples

Backend: Create a tracking event

from models.tracking_event import TrackingEvent
from db.tracking import insert_tracking_event
from utils.tracking_logger import log_tracking_event

event = TrackingEvent.create_event(
    user_id='user123',
    child_id='child456',
    entity_type='task',
    entity_id='task789',
    action='activated',
    points_before=50,
    points_after=60,
    metadata={'task_name': 'Homework'}
)

insert_tracking_event(event)
log_tracking_event(event)

Frontend: Query tracking events

import { getTrackingEventsForChild } from "@/common/api";

const res = await getTrackingEventsForChild({
  childId: "child456",
  entityType: "task",
  limit: 20,
  offset: 0,
});

const data = await res.json();
// { tracking_events: [...], total: 42, count: 20, limit: 20, offset: 0 }

📋 Migration Notes

  1. New database file: backend/data/db/tracking_events.json will be created automatically on first tracking event.
  2. New log directory: backend/logs/tracking_user_<user_id>.log files will be created per user.
  3. No breaking changes to existing APIs or data models.

🔮 Future Enhancements (Not in This Phase)

  • Admin/parent UI for viewing tracking history
  • Badges and certificates based on tracking data
  • Analytics and reporting dashboards
  • Export tracking data (CSV, JSON)
  • Time-based filters (date range queries)