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
Represents an internal boolean-expression node for `CompetencyAchievementCriteria`.
64
64
@@ -74,7 +74,7 @@ Decision
74
74
This new database table will have the following columns:
75
75
76
76
1. `id`: unique primary key
77
-
2. `parent_id`: The `oel_competency_criteria_group.id` of the parent group. Null means this is a root group.
77
+
2. `parent_id`: The `CompetencyCriteriaGroup.id` of the parent group. Null means this is a root group.
78
78
3. `oel_tagging_tag_id`: The `oel_tagging_tag.id` for the competency represented by this criteria tree.
79
79
4. `course_id`: Nullable foreign key to `openedx_catalog_courserun.id` for the course that scopes this criteria tree.
80
80
5. `name`: string
@@ -102,10 +102,10 @@ Decision
102
102
- Empty groups: Persisted criteria definitions should not contain empty groups. Authoring flows may temporarily create empty groups while editing, but backend validation must reject them.
103
103
- Mixed tree depths: Backend supports deeply nested groups. Current frontend authoring constraint is a maximum depth of 3 layers total, using zero-indexed depth (`0=root`, `1=course-scope group`, `2=leaf criteria/group`).
104
104
- Retrieval scope: Evaluation/read paths should be windowed by course run dates, not full-history by default. For a requested date window `[window_start, window_end]`, include (a) all nodes where `course_id is null`, and (b) complete subtrees for course-scoped groups whose course run overlaps the window (`course_start <= window_end` and `course_end >= window_start`, with null `course_end` treated as ongoing). Do not return partial subtrees.
105
-
- Practical size and growth: Total rows in `oel_competency_criteria_group` are expected to grow over time as course runs are added; this ADR sets no global DB row cap. No max total node-count cap is required per root group. For `course_id is null` branches, expected size is small (realistically <=500 nodes). Pagination is supported for authoring/list APIs.
105
+
- Practical size and growth: Total rows in `CompetencyCriteriaGroup` are expected to grow over time as course runs are added; this ADR sets no global DB row cap. No max total node-count cap is required per root group. For `course_id is null` branches, expected size is small (realistically <=500 nodes). Pagination is supported for authoring/list APIs.
Represents a reusable default rule configuration that can be applied to many `CompetencyCriterion` rows.
111
111
@@ -119,13 +119,13 @@ Decision
119
119
1. `id`: unique primary key
120
120
2. `organization_id`: The `organization_id` of the organization that this competency rule profile is scoped to. Null if it is not scoped to a specific organization.
121
121
3. `course_id`: The `course_id` of the course that this competency rule profile is scoped to. Null if it is not scoped to a specific course.
122
-
4. `competency_taxonomy_id`: The `oel_competency_taxonomy.taxonomy_ptr_id` of the competency taxonomy that this competency rule profile is scoped to.
122
+
4. `competency_taxonomy_id`: The `CompetencyTaxonomy.taxonomy_ptr_id` of the competency taxonomy that this competency rule profile is scoped to.
123
123
5. `rule_type`: “View”, “Grade”, “MasteryLevel” (Only “Grade” will be supported for now)
124
124
6. `rule_payload`: JSON payload keyed by `rule_type` to avoid freeform strings. It is structured JSON (not arbitrary freeform data): each `rule_type` defines the allowed payload shape and required keys, and validation enforces this contract. JSON is used instead of fixed columns like `op`, `value`, and `scale` so that future rule types (for example, `MasteryLevel` thresholds or plugin-defined evaluators such as CEL-based rules) can add their own fields without repeated schema migrations or many nullable columns. Examples:
6. Learner progress status concepts (`student_competency*status`)
162
+
6. Learner progress status concepts (`StudentCompetency*Status` database tables)
163
163
164
164
When a completion event (graded, completed, mastered, etc.) occurs for an object, determine and track the learner's status in earning the competency. To reduce recalculation frequency, store results at each level.
165
165
166
166
Relationship to other concepts:
167
167
168
-
- `student_competencycriteriastatus` tracks status at `CompetencyCriterion` leaf level.
169
-
- `student_competencycriteriagroupstatus` tracks status at `CompetencyCriteriaGroup` node level.
- All learner status rows use a shared lookup table (`oel_competency_mastery_statuses`) so status semantics live in one place and student status tables stay structurally consistent.
168
+
- `StudentCompetencyCriteriaStatus` tracks status at `CompetencyCriterion` leaf level.
169
+
- `StudentCompetencyCriteriaGroupStatus` tracks status at `CompetencyCriteriaGroup` node level.
- All learner status rows use a shared lookup table (`CompetencyMasteryStatuses`) so status semantics live in one place and student status tables stay structurally consistent.
172
172
173
173
Intended update flow (bottom-up materialization):
174
174
175
-
- A learner event updates one `student_competencycriteriastatus` row.
175
+
- A learner event updates one `StudentCompetencyCriteriaStatus` row.
176
176
- Recompute ancestor `CompetencyCriteriaGroup` statuses upward to the root.
177
177
- At each group, evaluate children in `ordering` sequence and short-circuit when the group's result is already determined by its `logic_operator`.
178
178
- Persist only rows whose status changed.
179
179
180
-
1. Add new database table for `oel_competency_mastery_statuses` with these columns:
180
+
1. Add new database table for `CompetencyMasteryStatuses` with these columns:
181
181
182
182
1. `id`: unique primary key
183
183
2. `status`: unique status value (seeded values: “Demonstrated”, “AttemptedNotDemonstrated”, and “PartiallyAttempted”)
@@ -186,35 +186,35 @@ Decision
186
186
187
187
- This table is system-owned lookup data and should be treated as immutable configuration, not user-authored rows.
188
188
189
-
2. Add new database table for `student_competencycriteriastatus` with these columns:
189
+
2. Add new database table for `StudentCompetencyCriteriaStatus` with these columns:
190
190
191
191
1. `id`: unique primary key
192
192
2. `competency_criteria_id`: Foreign key to `CompetencyCriterion.id`
193
193
3. `user_id`: Foreign key pointing to user_id (presumably the learner's id, although it appears that it is possible for staff to get grades as well) in `auth_user` table
194
-
4. `status_id`: Foreign key to `oel_competency_mastery_statuses.id`
194
+
4. `status_id`: Foreign key to `CompetencyMasteryStatuses.id`
195
195
5. `created`: The timestamp at which the student's criterion status was set.
196
196
197
-
3. Add a new database table for `student_competencycriteriagroupstatus` with these columns:
197
+
3. Add a new database table for `StudentCompetencyCriteriaGroupStatus` with these columns:
198
198
199
199
1. `id`: unique primary key
200
200
2. `competency_criteria_group_id`: Foreign key to `CompetencyCriteriaGroup.id`
201
201
3. `user_id`: Foreign key pointing to user_id (presumably the learner's id, although it appears that it is possible for staff to get grades as well) in `auth_user` table
202
-
4. `status_id`: Foreign key to `oel_competency_mastery_statuses.id`
202
+
4. `status_id`: Foreign key to `CompetencyMasteryStatuses.id`
203
203
5. `created`: The timestamp at which the student's criteria-group status was set.
204
204
205
-
4. Add a new database table for `student_competencystatus` with these columns:
205
+
4. Add a new database table for `StudentCompetencyStatus` with these columns:
206
206
207
207
1. `id`: unique primary key
208
208
2. `oel_tagging_tag_id`: Foreign key pointing to Tag id
209
209
3. `user_id`: Foreign key pointing to user_id (presumably the learner's id, although it appears that it is possible for staff to get grades as well) in `auth_user` table
210
-
4. `status_id`: Foreign key to `oel_competency_mastery_statuses.id`. This table should have a constraint to only allow status values of “Demonstrated” and “PartiallyAttempted” since it represents overall competency demonstration state, not in-progress states.
210
+
4. `status_id`: Foreign key to `CompetencyMasteryStatuses.id`. This table should have a constraint to only allow status values of “Demonstrated” and “PartiallyAttempted” since it represents overall competency demonstration state, not in-progress states.
211
211
5. `created`: The timestamp at which the student's competency status was set.
212
212
213
213
7. Delete protection boundaries
214
214
215
215
- If no learner status rows exist for a competency definition, hard delete is allowed and cascades through competency metadata tables.
216
-
- Once any related learner status exists in `student_competencystatus`, `student_competencycriteriagroupstatus`, or `student_competencycriteriastatus`, deletion of associated competency definition rows is blocked.
217
-
- This delete protection applies to `oel_tagging_taxonomy`, `oel_competency_taxonomy`, `oel_tagging_tag`, `oel_tagging_objecttag`, `oel_competency_criteria_group`, `oel_competency_criteria`, and `oel_competency_rule_profile`.
216
+
- Once any related learner status exists in `StudentCompetencyStatus`, `StudentCompetencyCriteriaGroupStatus`, or `StudentCompetencyCriteriaStatus`, deletion of associated competency definition rows is blocked.
217
+
- This delete protection applies to `oel_tagging_taxonomy`, `CompetencyTaxonomy`, `oel_tagging_tag`, `oel_tagging_objecttag`, `CompetencyCriteriaGroup`, `CompetencyCriteria`, and `CompetencyRuleProfile`.
218
218
- Once any related learner status exists, retiring definitions may be archive-only (hidden from authoring and new associations), not hard delete.
219
219
220
220
.. image:: images/CompetencyCriteriaModel.png
@@ -241,17 +241,17 @@ Content objects:
241
241
- Assignment 7 tagged with "Writing Poetry"
242
242
- Assignment 9 tagged with "Writing Poetry"
243
243
244
-
2. `oel_competency_rule_profile`:
244
+
2. `CompetencyRuleProfile`:
245
245
246
246
- Course-scoped default: `Grade >= 75%` for this competency taxonomy
247
247
248
-
3. `oel_competency_criteria_group`:
248
+
3. `CompetencyCriteriaGroup`:
249
249
250
250
- Root group uses `OR`
251
251
- Group A (`ordering=1`) uses `AND`
252
252
- Group B (`ordering=2`) uses `AND`
253
253
254
-
4. `oel_competency_criteria`:
254
+
4. `CompetencyCriteria`:
255
255
256
256
- Group A + Assignment 7 (uses default rule profile)
257
257
- Group A + Assignment 9 (override to `Grade >= 85%`)
@@ -278,7 +278,7 @@ Rejected Alternatives
278
278
4. Makes it harder to keep competency features optional for deployments that only want generic tagging
279
279
5. Increases risk of future refactor/migration work if the competency domain later needs to be split from tagging
280
280
281
-
2. Same as above except combine the `oel_competency_criteria` and `oel_tagging_objecttag` tables by adding the rule information as columns on the `oel_tagging_objecttag` table. This would be a more denormalized approach that would reduce the number of joins needed to retrieve competency achievement criteria information but would add complexity to the `oel_tagging_objecttag` table and make it less flexible for other uses.
281
+
2. Same as above except combine the `CompetencyCriteria` and `oel_tagging_objecttag` tables by adding the rule information as columns on the `oel_tagging_objecttag` table. This would be a more denormalized approach that would reduce the number of joins needed to retrieve competency achievement criteria information but would add complexity to the `oel_tagging_objecttag` table and make it less flexible for other uses.
0 commit comments