Skip to content

StudentCompetencyCriteriaStatus and StudentCompetencyCriteriaGroupStatus data models - #20

Open
jesperhodge wants to merge 1 commit into
cbe-642-03-competency-statusfrom
jesperhodge/642b-stack-base
Open

jesperhodge wants to merge 1 commit into
cbe-642-03-competency-statusfrom
jesperhodge/642b-stack-base

Conversation

@jesperhodge

@jesperhodge jesperhodge commented Sep 28, 2026 •

Copy link
Copy Markdown
Owner

AI usage

This PR stack was generated by AI and reviewed by a human, plus went through a code review by @tbain.

Description

This PR is the base branch for the reviewable stack that implements part B of openedx#642, the two learner status models that point into the criteria tree from openedx#641: StudentCompetencyCriteriaStatus, a learner's current mastery status for one leaf criterion, and StudentCompetencyCriteriaGroupStatus, the same for one criteria group.

Supporting information

Deviations from the acceptance criteria

Criterion as written What the stack does
created uses auto_now_add=True and modified uses auto_now=True (openedx#642 and openedx#613). Part A and part B use manual_date_time_field() instead. auto_now does not fire on QuerySet.update(), so it would leave modified stale on the single conditional UPDATE that raises a status, which the criterion on mastery status order exists to enable. openedx#642's Open Questions already records this divergence. The tests check that both columns exist, not how they are filled.

How to review this PR

Review the stack bottom to top. Each PR targets the one below it, and #21 targets this PR's branch (jesperhodge/642b-stack-base).

Order PR What it adds
1 #21 StudentCompetencyCriteriaStatus, its migration 0011, and its tests.
2 #22 StudentCompetencyCriteriaGroupStatus, its migration 0012, its tests, and the ADR-0002 index test.

How to merge

  1. Approve each PR in the stack, bottom first.
  2. Once every PR is approved, merge feat: add StudentCompetencyCriteriaStatus for per-criterion mastery #21 and then feat: add StudentCompetencyCriteriaGroupStatus for per-group mastery #22 into this PR's branch.
  3. Landing part B upstream takes one more step. After CompetencyMasteryStatus and StudentCompetencyStatus data models openedx/openedx-core#830 merges, part B is rebased onto openedx/openedx-core main, and the upstream PR is opened against main, because GitHub cannot change an existing PR's base repository. That upstream PR closes Mastery status lookup + learner progress models openedx/openedx-core#642.

Testing instructions

Confirm no migration drift:

python manage.py makemigrations --check --dry-run openedx_learning   # expect: no changes detected

The snippet below covers the whole stack's main happy paths. Check out jesperhodge/642b-02-group-status, where both models exist, and run python manage.py migrate. Then paste the snippet into python manage.py shell. The lines commented with an error are expected to raise, so in IPython, which stops a pasted block at its first exception, paste one block at a time.

from django.contrib.auth import get_user_model
from django.utils import timezone
from openedx_learning.models import (
    CompetencyCriteriaGroup, CompetencyCriterion, CompetencyRuleProfile, CompetencyTaxonomy,
    MasteryStatus, StudentCompetencyCriteriaGroupStatus, StudentCompetencyCriteriaStatus,
)
from openedx_tagging.models import ObjectTag, Tag

now = timezone.now()
learner = get_user_model().objects.create(username="cbe-learner")
taxonomy = CompetencyTaxonomy.objects.create(name="T", export_id="t")
tag = Tag.objects.create(taxonomy=taxonomy, value="Writing")
root = CompetencyCriteriaGroup.objects.create(tag=tag)
child = CompetencyCriteriaGroup.objects.create(tag=tag, parent=root)
object_tag = ObjectTag.objects.create(object_id="block-v1:x+y+z+problem+p1", taxonomy=taxonomy, tag=tag)
default = CompetencyRuleProfile.objects.get(organization=None, course=None, competency_taxonomy=None)
criterion = CompetencyCriterion.objects.create(group=child, object_tag=object_tag, rule_profile=default)

# A learner holds one status row per criterion and one per group, any of the three values allowed.
leaf = StudentCompetencyCriteriaStatus.objects.create(
    user=learner, criterion=criterion, status_id=MasteryStatus.PARTIALLY_ATTEMPTED, created=now, modified=now,
)
StudentCompetencyCriteriaGroupStatus.objects.create(
    user=learner, group=child, status_id=MasteryStatus.ATTEMPTED_NOT_DEMONSTRATED, created=now, modified=now,
)
StudentCompetencyCriteriaStatus.objects.create(
    user=learner, criterion=criterion, status_id=MasteryStatus.DEMONSTRATED, created=now, modified=now,
)                                                                          # IntegrityError: second row

# The row is updated in place, so a raise is one conditional UPDATE.
raise_leaf = StudentCompetencyCriteriaStatus.objects.filter(pk=leaf.pk, status_id__lt=MasteryStatus.DEMONSTRATED)
raise_leaf.update(status_id=MasteryStatus.DEMONSTRATED, modified=timezone.now())  # 1
raise_leaf.update(status_id=MasteryStatus.DEMONSTRATED, modified=timezone.now())  # 0: already Demonstrated

# Learner status protects the definitions above it, including across the CASCADE chain.
criterion.delete()   # ProtectedError
root.delete()        # ProtectedError
tag.delete()         # ProtectedError
taxonomy.delete()    # ProtectedError

# Deleting the learner removes their status rows, and then the tree deletes.
learner.delete()     # deletes the user, one criterion status and one group status
root.delete()        # deletes both groups and the criterion

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@jesperhodge
jesperhodge removed this pull request from stack #23 October 2, 2026 17:17
@jesperhodge
jesperhodge changed the base branch from jesperhodge/642b-deps-641-and-642a to cbe-642-03-competency-status October 2, 2026 17:17
@jesperhodge
jesperhodge force-pushed the jesperhodge/642b-stack-base branch from a7aa1dd to 2f000d9 Compare October 2, 2026 17:17
@jesperhodge
jesperhodge changed the base branch from cbe-642-03-competency-status to main October 2, 2026 17:33
@jesperhodge
jesperhodge added this pull request to stack #25 October 2, 2026 17:33
@jesperhodge
jesperhodge removed this pull request from stack #25 October 2, 2026 17:33
@jesperhodge
jesperhodge changed the base branch from main to cbe-642-03-competency-status October 2, 2026 17:33
@jesperhodge
jesperhodge added this pull request to stack #26 October 2, 2026 17:33
Repository owner deleted a comment from coderabbitai Bot Oct 2, 2026
@jesperhodge

Copy link
Copy Markdown
Owner Author

Please review @ormsbee @kdmccormick

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.

Mastery status lookup + learner progress models

1 participant