Support program-specific pathway schools in learner record sharing - #3802
Support program-specific pathway schools in learner record sharing#3802AhtishamShahid wants to merge 11 commits into
Conversation
The new import in courses/serializers/v1/programs.py shifted 8 pre-existing ORM001 violations down one line, and routing partner_schools through the courses.api helper removed the violation formerly at line 368. The baseline matches on exact line numbers, so it needed realigning. Edited surgically rather than regenerated: a full --generate-baseline run also dropped 24 stale entries for files this branch does not touch (v1/courses.py, v2/programs.py, v3/courses.py), which is unrelated churn.
OpenAPI ChangesShow/hide changesUnexpected changes? Ensure your branch is up-to-date with |
There was a problem hiding this comment.
Pull request overview
Adds support for program-specific “pathway school” assignments when learners share program records, including per-program recipient routing and validation, shipped behind a new feature flag (default OFF) to preserve existing behavior until rollout.
Changes:
- Introduces
PartnerSchoolProgramthrough model to link partner schools to programs with per-program recipient email(s) (andalt_emailstored for reference only). - Filters/validates learner-visible partner schools via a shared helper (
partner_schools_for_program) and rejects sharing to non-assigned schools when the flag is ON. - Updates email sending to support multiple recipients (one email per recipient) when the flag is ON, plus extensive test coverage and admin UI for assignment entry.
Reviewed changes
Copilot reviewed 17 out of 17 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| main/features.py | Adds the ENABLE_PROGRAM_SPECIFIC_PATHWAY_SCHOOLS feature flag constant. |
| drf_lint_baseline.json | Updates baseline line references after serializer changes. |
| courses/views/v1/views_test.py | Adds endpoint-level tests for program-scoped validation and partner school filtering behavior. |
| courses/views/v1/init.py | Adds optional ?program= filtering to partner schools endpoint and enforces program-scoped school validation for record sharing. |
| courses/serializers/v1/programs.py | Routes partner school serialization through the shared helper to keep dropdown + validation consistent. |
| courses/serializers/v1/programs_test.py | Adds serializer tests for program-specific filtering, ordering, deduplication, and flag-off behavior. |
| courses/models.py | Adds PartnerSchoolProgram model, PartnerSchool↔Program M2M through it, alphabetical ordering, and recipient resolution helper. |
| courses/models_test.py | Adds unit tests for per-program recipient resolution, alt-email non-usage, and default ordering. |
| courses/migrations/0101_partnerschoolprogram.py | Creates the new through table, index, constraint, and ordering state change. |
| courses/mail_api.py | Adds feature-flag-gated per-program recipient routing and multi-recipient sending. |
| courses/mail_api_test.py | Adds mail routing tests for per-program, multi-recipient, alt-email exclusion, fallback, and flag-off behavior. |
| courses/factories.py | Adds PartnerSchoolProgramFactory for test data creation. |
| courses/api.py | Adds partner_schools_for_program helper with feature-flag gating and deduplication via distinct(). |
| courses/api_test.py | Adds API helper tests for flag-on filtering, flag-off behavior, and deduplication. |
| courses/admin.py | Adds admin inline and changelist enhancements for program assignments and filtering. |
| courses/admin_test.py | Adds admin tests ensuring inline presence and changelist filtering by program. |
| conftest.py | Defaults the new feature flag to OFF in tests. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 17 out of 17 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (1)
courses/models.py:2739
PartnerSchoolnow has a globalMeta.ordering = ["name"], which changes the default ordering for allPartnerSchool.objects...queries immediately (including whenENABLE_PROGRAM_SPECIFIC_PATHWAY_SCHOOLSis off). This appears to contradict the PR description’s claim that legacy behavior is preserved until the feature flag is enabled, and could affect any existing API/UI consuming partner schools where ordering was previously insertion/PK-based.
Consider either (a) gating ordering changes behind the feature flag (e.g., apply an explicit .order_by("name") only in the flagged code paths) or (b) updating the PR description/rollout expectations to acknowledge the behavior change if the new ordering is intentional.
class Meta:
ordering = ["name"]
A failure for one recipient aborted the loop, so remaining per-program recipients were never attempted and the log did not say which were skipped. Raised in review on PR #3802.
Closes mitodl/hq#12321
This pull request introduces program-specific pathway school assignments, allowing each program to be linked to specific partner schools and enabling per-program recipient addresses for learner record sharing. The changes are carefully feature-flagged to preserve legacy behavior until the new logic is enabled. Major updates span the admin interface, API, mail delivery, and test coverage.
These changes lay the groundwork for program-specific pathway school sharing, while ensuring that no behavioral changes occur until the feature flag is enabled.
Feature flag
Flag:
mitxonline-12321-program-specific-pathway-schools, ships off.Two functions read it, both deliberate and both commented:
courses.api.partner_schools_for_program— the learner's dropdown and the share endpoint's validationcourses.mail_api.send_partner_school_sharing_message— recipient routingGating mail matters because assignments are entered before the flip. Without it, a mistyped address among ~122 hand-entered rows would receive a real learner record — name, email, grades — while the flag still claimed nothing had changed.
With the flag off, the set of schools shown and accepted is unchanged, and the email recipient is unchanged, whether or not any assignments have been entered. Verified across the full matrix:
Rollout checklist
mitxonline-12321-program-specific-pathway-schoolsin PostHog, offPOSTHOG_ENABLED=True. If not, the flag falls back to theFEATURESenv var, and the name must beFEATURE_mitxonline-12321-program-specific-pathway-schools—get_features()strips theFEATURE_prefix and uses the remainder verbatim, so the hyphens are required and an underscored name silently never matches/admin/courses/partnerschool/if is_enabled(...)branches