Skip to content

feat(b2b_learner_records): serve activity from the learner-records MVs - #62

Open
blarghmatey wants to merge 1 commit into
feat/b2b-learner-records-coursesfrom
feat/learner-records-activity
Open

blarghmatey wants to merge 1 commit into
feat/b2b-learner-records-coursesfrom
feat/learner-records-activity

Conversation

@blarghmatey

Copy link
Copy Markdown
Member

What are the relevant tickets?

N/A. Stacked on #60. Reads the columns added in mitodl/ol-data-platform#2693.

Description (What does it do?)

Replaces the NULL placeholders for last_active_on, days_active, videos_watched, problems_attempted and chatbot_interactions on /enrollments, and last_active_on and courses_in_progress on /learners, with the MV columns. videos_watched is the MV's videos_played. outcomes_consent_on stays NULL.

completion_status = in_progress now means a nonzero grade or any tracked activity. mv_b2b_learner.courses_in_progress uses that definition. Without this change, the default /learners count and the /enrollments statuses would disagree. The recomputed rollup (contract_id / include_inactive) counts courses_in_progress with the same CASE and takes MAX(last_active_on) over the enrollments already in scope. By default that's active enrollments only, like the MV. Under include_inactive it's every enrollment.

Spec and model descriptions:

  • The counters were described as distinct blocks. The MV sums per-day distinct counts, so a block used on two days counts twice. organization_administration_report counts videos_watched per day too, and the b2b_dashboard totals sum it.
  • x-data-readiness on the activity fields moves off pending-model.
  • Activity doesn't move updated_since. A day's activity first shows up at a refresh after that day began, so a cursor derived from it would already sort below the as_of a partner passes. Partners get activity from a full reload. Real change tracking is a separate piece of work.

How can this be tested?

  • uv run pytest: 241 passed. New cases cover the enrollment projection and status CASE, the default learner projection, the recomputed courses_in_progress/last_active_on, and a shared enrollment keeping its activity fields.
  • ruff check, ruff format --check and mypy src are clean.
  • Ran the generated SQL for /enrollments (with and without include_inactive) and all three /learners paths against DuckDB stub tables shaped like the MVs. Statuses, last_active_on and courses_in_progress agree across the paths. Not run on StarRocks: the columns don't exist there until #2693 merges and the MVs rebuild.

Checklist:

🤖 Generated with Claude Code

https://claude.ai/code/session_01XMuwnLQwHtHuH7aECS7sf3

@blarghmatey
blarghmatey added this pull request to stack #63 September 17, 2026 14:32
@blarghmatey
blarghmatey marked this pull request as ready for review September 17, 2026 14:32
@blarghmatey
blarghmatey requested a balanced review from Copilot September 17, 2026 14:32

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Deployment depends on an unmerged cross-repository MV schema change that has not yet been validated in StarRocks.

Pull request overview

Populates learner-record activity fields from the new materialized-view columns and aligns progress calculations across endpoints.

Changes:

  • Projects enrollment and learner activity metrics.
  • Includes tracked activity in in_progress calculations.
  • Updates tests and API documentation.
File summaries
File Description
queries.py Reads activity columns and updates rollups/statuses.
models.py Documents populated activity fields.
test_learner_records.py Tests activity projections and calculations.
b2b-learner-records-v1.yaml Updates the public API contract.
b2b-learner-records-onepager.md Marks the activity model available.
b2b-learner-records-design.md Documents the implemented activity pipeline.
Review details
  • Files reviewed: 6/6 changed files
  • Comments generated: 0
  • Review effort level: Balanced

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

ol-data-platform#2693 adds last_active_on, days_active and the three
counters to mv_b2b_learner_enrollment, and last_active_on and
courses_in_progress to mv_b2b_learner. The tenant projected all of them as
NULL.

in_progress now also counts activity. mv_b2b_learner.courses_in_progress is
defined that way, so /learners and /enrollments disagree unless the
completion_status CASE matches it.

The counter descriptions said "distinct blocks". The MV sums per-day
distinct counts, so a block used on two days counts twice. The spec also
says activity doesn't move updated_since: record_updated_on can't carry a
day-granular activity date without falling below the partner's cursor.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XMuwnLQwHtHuH7aECS7sf3
@blarghmatey
blarghmatey force-pushed the feat/learner-records-activity branch from da3b9b2 to 8625454 Compare September 17, 2026 20:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants