You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
N/A — tracked internally as Witan project wp-needs-attention-aggregate-for-b2b-learner-progre-09344a, no GitHub issue.
Description (What does it do?)
Wires the learner-progress endpoint's last_active_on to the real column ol-data-platform#2693 added to mv_b2b_learner_enrollment, instead of a hardcoded NULL.
Updates completion_status's in_progress branch to also count tracked activity, matching the fix already shipped on the b2b_learner_records tenant in #62 — otherwise the two endpoints disagree on what counts as in-progress.
Adds needs_attention_count to the response envelope: a learner needs attention if they never started, or have gone quiet for 30+ days.
Implementation details
needs_attention is computed as completion_status = 'not_started' OR last_active_on <= DATE_SUB(CURRENT_DATE(), INTERVAL 30 DAY), gated by the same consent check (outcomes_shared) as the other outcome aggregates. It's an overlapping count, not a new disjoint bucket — a row can be both in_progress and counted in needs_attention_count.
How can this be tested?
uv run pytest — 303 passed, including new tests asserting the needs_attention_count SQL and the updated in_progress CASE. OpenAPI spec regenerated via uv run bin/generate-openapi-spec.
Not exercised against a live StarRocks instance — these tests mock the DB layer (per the test module's own docstring) rather than executing SQL. I confirmed DATE_SUB/CURRENT_DATE() syntax against StarRocks docs, but a reviewer should sanity-check the query against a real mv_b2b_learner_enrollment before this ships to production.
Additional Context
Unblocks the "Needs attention" KPI tile on mit-learn's org/contract analytics dashboard (LearnerProgressCard.tsx), which currently omits it pending this field.
Post-merge correction to this description only; no code changed. The line above originally read last_active_on < DATE_SUB(...). The merged code uses <=, which is correct: the rule is "last recorded activity at least 30 days ago", so the 30th day itself counts, and test_needs_attention_boundary_is_computed_from_real_rows pins that boundary. Corrected here so the prose matches the shipped behavior. See #84, which adds the matching filter and row field and makes the intent explicit in a comment.
… on learner-progress
ol-data-platform#2693 added a real last_active_on to mv_b2b_learner_enrollment;
the learner-progress endpoint still projected it as a hardcoded NULL. Wire it
through, match completion_status's in_progress branch to the activity-aware
definition already used by b2b_learner_records, and add needs_attention_count
to the envelope (not_started, or quiet for 30+ days) per wp-needs-attention-
aggregate-for-b2b-learner-progre-09344a.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
## Changes for b2b_dashboard.yaml:
1 changes: 0 error, 0 warning, 1 info
info [response-required-property-added] at head/openapi/specs/b2b_dashboard.yaml
in API GET /api/v1/analytics/organizations/{organization_id}/contracts/{contract_id}/learner-progress
added the required property `needs_attention_count` to the response with the `200` status
## Changes for b2b_learner_records.yaml:
No changes detected
Unexpected changes? Ensure your branch is up-to-date with main (consider rebasing).
…ity buckets
Switch the needs-attention staleness check from < to <= so a learner
qualifies once 30 full days have passed with no activity, matching the
product definition, instead of requiring 31. Also update the
in_progress/not_started descriptions on CompletionStatusCounts to
mention activity, since in_progress already includes activity-only
enrollments with no grade.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The existing test fabricated needs_attention_count via _FakePool, so it
couldn't catch a broken day-30 boundary or consent gate. Run the actual
_COMPLETION_STATUS/_NEEDS_ATTENTION strings against sqlite with
never-started, day-29 and exactly-day-30 rows, and with consent
fail-closed/open, so a regression in either fails here instead of only
passing through a mocked count.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
"No activity for 30 days or more" oversells the check: a grade-only
in_progress enrollment with no last_active_on has nothing to judge
staleness against, so it's never flagged even though it has no
recorded activity. Reword to "last recorded activity was at least 30
days ago" and regenerate the OpenAPI spec.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Addressed the "Clarify stale enrollment criteria and regenerate OpenAPI spec" item from Copilot's latest review (learner_models.py:227) in 3897077: reworded needs_attention_count's description from "haven't done anything in the course for 30 days or more" to "their last recorded activity was at least 30 days ago," since a grade-only in_progress enrollment with no last_active_on timestamp has nothing to judge staleness against and was never actually flagged. Applied the same wording to the module docstring and the _NEEDS_ATTENTION code comment for consistency, and regenerated openapi/specs/b2b_dashboard.yaml.
The reason will be displayed to describe this comment to others. Learn more.
Copilot review overview
🔵 Needs a closer look
The production StarRocks query has not been exercised live, and the activity-date response still needs positive-path regression coverage.
Review effort: Balanced Findings: None
Previously missed (1)
In code that hasn't changed since last review
Test non-null last_active_on propagation and consent masking
tests/test_dashboard_learner_progress.py:405
The query test checks only that last_active_on is masked when consent is off; the endpoint's shared-outcome fixture still supplies None for this field. If the new MV projection is replaced with NULL, these tests can pass even though the API never serves an activity date. Please assert that the inner query selects last_active_on from the MV and exercise a non-null date through the shared response, while checking it remains hidden without consent.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What are the relevant tickets?
N/A — tracked internally as Witan project
wp-needs-attention-aggregate-for-b2b-learner-progre-09344a, no GitHub issue.Description (What does it do?)
last_active_onto the real column ol-data-platform#2693 added tomv_b2b_learner_enrollment, instead of a hardcodedNULL.completion_status'sin_progressbranch to also count tracked activity, matching the fix already shipped on theb2b_learner_recordstenant in #62 — otherwise the two endpoints disagree on what counts as in-progress.needs_attention_countto the response envelope: a learner needs attention if they never started, or have gone quiet for 30+ days.Implementation details
needs_attentionis computed ascompletion_status = 'not_started' OR last_active_on <= DATE_SUB(CURRENT_DATE(), INTERVAL 30 DAY), gated by the same consent check (outcomes_shared) as the other outcome aggregates. It's an overlapping count, not a new disjoint bucket — a row can be bothin_progressand counted inneeds_attention_count.How can this be tested?
uv run pytest— 303 passed, including new tests asserting theneeds_attention_countSQL and the updatedin_progressCASE. OpenAPI spec regenerated viauv run bin/generate-openapi-spec.Not exercised against a live StarRocks instance — these tests mock the DB layer (per the test module's own docstring) rather than executing SQL. I confirmed
DATE_SUB/CURRENT_DATE()syntax against StarRocks docs, but a reviewer should sanity-check the query against a realmv_b2b_learner_enrollmentbefore this ships to production.Additional Context
Unblocks the "Needs attention" KPI tile on mit-learn's org/contract analytics dashboard (
LearnerProgressCard.tsx), which currently omits it pending this field.🤖 Generated with Claude Code
Post-merge correction to this description only; no code changed. The line above originally read
last_active_on < DATE_SUB(...). The merged code uses<=, which is correct: the rule is "last recorded activity at least 30 days ago", so the 30th day itself counts, andtest_needs_attention_boundary_is_computed_from_real_rowspins that boundary. Corrected here so the prose matches the shipped behavior. See #84, which adds the matching filter and row field and makes the intent explicit in a comment.