All checks were successful
Gitea Actions Demo / build-and-push (push) Successful in 25s
- Implemented PendingRewardDialog for handling pending reward requests. - Created RewardConfirmDialog for confirming reward redemption. - Developed TaskConfirmDialog for task confirmation with child name display. test: add unit tests for ChildView and ParentView components - Added comprehensive tests for ChildView including task triggering and SSE event handling. - Implemented tests for ParentView focusing on override modal and SSE event management. test: add ScrollingList component tests - Created tests for ScrollingList to verify item fetching, loading states, and custom item classes. - Included tests for two-step click interactions and edit button display logic. - Moved toward hashed passwords.
113 lines
6.3 KiB
Markdown
113 lines
6.3 KiB
Markdown
# Feature: Task and Reward Tracking
|
|
|
|
## Overview
|
|
|
|
**Goal:** Tasks, Penalties, and Rewards should be recorded when completed (activated), requested, redeemed, and cancelled. A record of the date and time should also be kept for these actions. A log file shall be produced that shows the child's points before and after the action happened.
|
|
|
|
**User Story:**
|
|
As an administrator, I want to know what kind and when a task, penalty, or reward was activated.
|
|
As an administrator, I want a log created detailing when a task, penalty, or reward was activated and how points for the affected child has changed.
|
|
As a user (parent), when I activate a task or penalty, I want to record the time and what task or penalty was activated.
|
|
As a user (parent), when I redeem a reward, I want to record the time and what reward was redeeemed.
|
|
As a user (parent/child), when I cancel a reward, I want to record the time and what reward was cancelled.
|
|
As a user (child), when I request a reward, I want to record the time and what reward was requested.
|
|
|
|
**Questions:**
|
|
|
|
- Tasks/Penalty, rewards should be tracked per child. Should the tracking be recorded in the child database, or should a new database be used linking the tracking to the child?
|
|
- If using a new database, should tracking also be linking to user in case of account deletion?
|
|
- Does there need to be any frontend changes for now?
|
|
|
|
**Decisions:**
|
|
|
|
- Use a **new TinyDB table** (`tracking_events.json`) for tracking records (append-only). Do **not** embed tracking in `child` to avoid large child docs and preserve audit history. Each record includes `child_id` and `user_id`.
|
|
- Track events for: task/penalty activated, reward requested, reward redeemed, reward cancelled.
|
|
- Store timestamps in **UTC ISO 8601** with timezone (e.g. `2026-02-09T18:42:15Z`). Always use **server time** for `occurred_at` to avoid client clock drift.
|
|
- On user deletion: **anonymize** tracking records by setting `user_id` to `null`, preserving child activity history for compliance/audit.
|
|
- Keep an **audit log file per user** (e.g. `tracking_user_<user_id>.log`) with points before/after and event metadata. Use rotating file handler.
|
|
- Use **offset-based pagination** for tracking queries (simpler with TinyDB, sufficient for expected scale).
|
|
- **Frontend changes deferred**: Ship backend API, models, and SSE events only. No UI components in this phase.
|
|
|
|
---
|
|
|
|
## Configuration
|
|
|
|
## Acceptance Criteria (Definition of Done)
|
|
|
|
### Data Model
|
|
|
|
- [x] Add `TrackingEvent` model in `backend/models/` with `from_dict()`/`to_dict()` and 1:1 TS interface in [frontend/vue-app/src/common/models.ts](frontend/vue-app/src/common/models.ts)
|
|
- [x] `TrackingEvent` fields include: `id`, `user_id`, `child_id`, `entity_type` (task|reward|penalty), `entity_id`, `action` (activated|requested|redeemed|cancelled), `points_before`, `points_after`, `delta`, `occurred_at`, `created_at`, `metadata` (optional dict)
|
|
- [x] Ensure `delta == points_after - points_before` invariant
|
|
|
|
### Backend Implementation
|
|
|
|
- [x] Create TinyDB table (e.g., `tracking_events.json`) with helper functions in `backend/db/`
|
|
- [x] Add tracking write in all mutation endpoints:
|
|
- task/penalty activation
|
|
- reward request
|
|
- reward redeem
|
|
- reward cancel
|
|
- [x] Build `TrackingEvent` instances from models (no raw dict writes)
|
|
- [x] Add server-side validation for required fields and action/entity enums
|
|
- [x] Add `send_event_for_current_user` calls for tracking mutations
|
|
|
|
### Frontend Implementation
|
|
|
|
- [x] Add `TrackingEvent` interface and enums to [frontend/vue-app/src/common/models.ts](frontend/vue-app/src/common/models.ts)
|
|
- [x] Add API helpers for tracking (list per child, optional filters) in [frontend/vue-app/src/common/api.ts](frontend/vue-app/src/common/api.ts)
|
|
- [x] Register SSE event type `tracking_event_created` in [frontend/vue-app/src/common/backendEvents.ts](frontend/vue-app/src/common/backendEvents.ts)
|
|
- [x] **No UI components** — deferred to future phase
|
|
|
|
### Admin API
|
|
|
|
- [x] Add admin endpoint to query tracking by `child_id`, date range, and `entity_type` (e.g. `GET /admin/tracking`)
|
|
- [x] Add offset-based pagination parameters (`limit`, `offset`) with sensible defaults (e.g. limit=50, max=500)
|
|
- [x] Return total count for pagination UI (future)
|
|
|
|
### SSE Event
|
|
|
|
- [x] Add event type `tracking_event_created` with payload containing `tracking_event_id` and minimal denormalized info
|
|
- [x] Update [backend/events/types/event_types.py](backend/events/types/event_types.py) and [frontend/vue-app/src/common/backendEvents.ts](frontend/vue-app/src/common/backendEvents.ts)
|
|
|
|
### Backend Unit Tests
|
|
|
|
- [x] Create tests for tracking creation on each mutation endpoint (task/penalty activated, reward requested/redeemed/cancelled)
|
|
- [x] Validate `points_before/after` and `delta` are correct
|
|
- [x] Ensure tracking write does not block core mutation (failure behavior defined)
|
|
|
|
### Frontend Unit Tests
|
|
|
|
- [x] Test API helper functions for tracking queries
|
|
- [x] Test TypeScript interface matches backend model (type safety)
|
|
|
|
#### Edge Cases
|
|
|
|
- [x] Reward cancel after redeem should not create duplicate inconsistent entries
|
|
- [x] Multiple activations in rapid sequence must be ordered by `occurred_at` then `created_at`
|
|
- [x] Child deleted: tracking records retained and still queryable by admin (archive mode)
|
|
- [x] User deleted: anonymize tracking by setting `user_id` to `null`, retain all other fields for audit history
|
|
|
|
#### Integration Tests
|
|
|
|
- [x] End-to-end: activate task -> tracking created -> SSE event emitted -> audit log written
|
|
- [x] Verify user deletion anonymizes tracking records without breaking queries
|
|
|
|
### Logging & Monitoring
|
|
|
|
- [x] Add dedicated tracking logger with **per-user rotating file handler** (e.g. `logs/tracking_user_<user_id>.log`)
|
|
- [x] Log one line per tracking event with `user_id`, `child_id`, `entity_type`, `entity_id`, `action`, `points_before`, `points_after`, `delta`, `occurred_at`
|
|
- [x] Configure max file size and backup count (e.g. 10MB, 5 backups)
|
|
|
|
### Documentation
|
|
|
|
- [x] Update README or docs to include tracking endpoints, schema, and sample responses
|
|
- [x] Add migration note for new `tracking_events.json`
|
|
|
|
---
|
|
|
|
## Future Considerations
|
|
|
|
- Reward tracking will be used to determine child ranking (badges and certificates!)
|
|
- is_good vs not is_good in task tracking can be used to show the child their balance in good vs not good
|