[BE] Add Archived Course Keys to GET Competency Criteria & Groups Endpoint
维护者通常 1 天内回复
@ufedaseyeuconsultant 已经在做这个了。
开始于 2026年10月16日。
评估
调研方向
Start at the GET Competency Criteria & Groups endpoint and trace how its response is assembled. Determine where archived course keys belong in the response, then verify that the endpoint returns them as expected without changing existing criteria or group data.
由索引模型根据 Issue 内容生成。
描述
User Story
As a course author, I need the Competency Management page to know which courses can no longer take new rules for a competency, in order to be told up front instead of having my new associations rejected.
Description
This ticket adds an archived_course_keys field to the response of the GET Competency Criteria & Groups endpoint that lists the course run keys whose course-level group for the selected competency is archived. Unarchiving course-level groups is out of scope for MVP, so the frontend needs to know which courses to pre-emptively prevent course authors from trying to recreate.
Context
- #681 is the endpoint this ticket extends.
- #674 and #675 archive a course-level group when a delete would otherwise destroy learner progress.
- #717 prevents creating new Competency Criteria in an archived course-level group.
- #841 is the frontend ticket that uses this list to hide archived courses in the Browse Courses panel.
Acceptance Criteria
These scenarios can be checked by calling the endpoint directly, for example with Postman. Unless a scenario says otherwise, the caller has permission to view the competency's taxonomy. "Reported as archived" means the course run's key appears in the response's new list of archived course runs.
Scenario: A course run with an archived course-level group is reported by its course run key
Given a competency's course-level group for course run X is archived
And the competency has active course-level groups for course run Y and for another run of X's course (for example "course-v1:OrgX+CS101+2027")
When a caller fetches the competency's criteria structure
Then course run X is reported as archived, identified by its course run key (for example "course-v1:OrgX+CS101+2026"), never by an internal id
And neither course run Y nor the other run of X's course is reported as archived
Scenario: Archived Rule Groups and criteria under an active course-level group are not reported
Given a competency's course-level group for course run Y is active
And one of Y's Rule Groups is archived, and another of Y's Rule Groups is active but holds an archived criterion alongside an active one
When a caller fetches the competency's criteria structure
Then course run Y is not reported as archived
Scenario: An archived root group is not reported and does not hide the archived courses under it
Given a competency's course-level groups for course runs X and Y are both archived, and so is the competency's root group above them
When a caller fetches the competency's criteria structure
Then exactly course runs X and Y are reported as archived
And the list contains no entry without a course run key
Scenario: Only the selected competency's own course-level groups are reported
Given competency P has a sub-competency S
And P's course-level group for course run X is archived, and S's course-level group for course run Y is archived
When a caller fetches P's criteria structure
Then course run X is reported as archived
And course run Y is not reported as archived
Scenario: The list is empty when no course-level group is archived
Given a competency has no archived course-level group, whether because it has no criteria structure yet or because every course-level group it has is active
When a caller fetches the competency's criteria structure
Then the response includes the list of archived course runs, and that list is empty
Scenario Outline: The list follows the same course-run scope as the criteria structure
This scenario needs #682's optional course-run filter on this endpoint. Whichever of #682 and this ticket merges second makes it pass.
Given a competency's course-level groups for course runs X and Y are archived, and its course-level group for course run Z is active
When a caller fetches the competency's criteria structure <scope>
Then the course runs reported as archived are <reported>
Examples:
| scope | reported |
| with no course-run scope | X and Y |
| scoped to course runs X and Z | X only |
| scoped to an empty set of course runs | none |
Scenario: The criteria structure leaves out archived rows
Given a competency's course-level group for course run X is archived, along with every Rule Group and criterion under it
And its course-level group for course run Y is active, with active Rule Groups and criteria
When a caller fetches the competency's criteria structure
Then course run X is reported as archived
And the structure includes course run Y's groups and criteria and none of course run X's
Scenario: A delete that archives a course-level group is reported on the next fetch
Given a competency's course-level group for course run X is active and holds a single Rule Group
And a learner has recorded progress on a criterion in that Rule Group
When an author deletes that Rule Group
And a caller then fetches the competency's criteria structure
Then course run X is reported as archived
And course run X's groups and criteria no longer appear in the structure
Scenario: Archived course runs are reported regardless of the caller's access to those courses
Given a competency's course-level group for course run X is archived
And the caller can view the competency's taxonomy but has no Studio access to course run X
When the caller fetches the competency's criteria structure
Then course run X is reported as archived
Scenario: A caller who cannot view the competency learns nothing about archived courses
Given a competency's course-level group for course run X is archived
And the caller cannot view the competency's taxonomy
When the caller fetches the competency's criteria structure
Then the request is refused for lack of permission
And no course run is disclosed as archived
Technical Details
This is a suggested approach, not the source of truth. The User Story, Description, and Acceptance Criteria define what must be true when the work is done.
Approach
File paths and names are those on #681's PR branch (alezconsultant/openedx-core#3).
- Add
archived_course_keys: list[CourseKey]to theCompetencyCriteriaTreedataclass and fill it inget_competency_criteria_tree()insrc/openedx_learning/applets/cbe/api.py, so Python and REST callers get the same list from one place. - Compute it with one flat query over the competency's groups, so an archived root can't hide the course-level groups under it:
CompetencyCriteriaGroup.objects.filter(tag_id=tag_id, archived=True, course__isnull=False, parent__isnull=False, parent__parent__isnull=True).values_list("course__course_key", flat=True). Return each key once, sorted by its string. - The
parent__parent__isnull=Trueclause (the group's parent is a root) is what makes a group course-level, and it selects the same group #717 checks before rejecting a new association. Don't select oncourse__isnull=Falsealone. ADR 0002 has every group in a course subtree carry the course, while #665 sets it only on the course-level group, so under ADR 0002's shape that filter also reports a course when one of its Rule Groups is archived. Build the archived Rule Group in the tests both with and without the course set, so the test fails under a course-only filter whichever shape lands. - Derive this query and the
groupsquery from one queryset filtered to the competency, so that #682'scourse_keyspredicate scopes both. Whencourse_keysis omitted the list covers every course run, when it is a list the list covers only those runs, and when it is empty the list is empty. If this ticket merges first, #682 applies the scope to the list. - In
CompetencyCriteriaTreeView.get()insrc/openedx_learning/applets/cbe/rest_api/v1/views.py, add the list to the response next togroupsandcriteriaas course run key strings. The key is always present, for example"archived_course_keys": ["course-v1:OrgX+CS101+2026"], and is[]when nothing is archived.
The field is additive to #681's unshipped contract and leaves its groups and criteria rows unchanged. Explaining archived courses in the Courses & Content panel is out of scope; #841 covers it.
Additional context
- #716 adds the
archivedcolumn to both the group and criterion models. docs/openedx_learning/decisions/0002-competency-criteria-model.rst: Decision 2 forcourse_id, and Decision 7 for archiving instead of deleting once learner status exists.
- 主要语言
- Python
- 星标
- 10
- 派生
- 33
- 平均合并
- 4 天 1 小时
- 30 天内合并 PR
- 34
环境准备
- 没有 Dockerfile 或 Docker Compose 文件
- 没有 Pull Request 模板
- 阅读贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
openedx/openedx-core 的其他 Issue
-
难度 2/5 1-3 小时 新手友好度 75/100
openedx/openedx-core#831 ·
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 85/100
openedx/openedx-core#827 ·
维护者通常 1 天内回复
-
[Follow-up BE] Scope the criteria-groups query by course instead of loading every group可能已有人在做 @ufedaseyeuconsultant 于 3 天前认领。 未关闭
openedx/openedx-core#919 · 2 条评论 · 已指派 1 人 ·
维护者通常 1 天内回复
-
[Release Docs - Follow up] Docs Notes for Competency ID after additional work is completed可能已有人在做 @thelmick-unicon 于 4 天前认领。 未关闭
openedx/openedx-core#917 · 已指派 1 人 ·
维护者通常 1 天内回复
-
难度 5/5 一周以上 新手友好度 28/100
openedx/openedx-core#916 ·
维护者通常 1 天内回复
查看 openedx/openedx-core 的全部 Issue
相似的 Issue
-
难度 2/5 1-3 小时 新手友好度 72/100
维护者通常 1 天内回复
-
enhancement good first issue
难度 2/5 1-3 小时 新手友好度 78/100
elviskahoro/sdk-python-attio#144 · 1 条评论 ·
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 84/100
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 72/100
维护者通常 1 天内回复
-
RenyiELBO raises TypeError when model has no sample sites可能已有人在做 @alibb007 今天认领。 未关闭
难度 1/5 1 小时以内 新手友好度 85/100
维护者通常 1 天内回复