diff --git a/src/openedx_learning/applets/cbe/models/criteria.py b/src/openedx_learning/applets/cbe/models/criteria.py index 084ae81f2..d8086496e 100644 --- a/src/openedx_learning/applets/cbe/models/criteria.py +++ b/src/openedx_learning/applets/cbe/models/criteria.py @@ -96,6 +96,14 @@ class CompetencyCriteriaGroup(models.Model): "logic is moot; the application layer treats null the same as OR." ), ) + archived = models.BooleanField( + default=False, + help_text=_( + "Set instead of deleting this group once learner status exists for it or anything beneath " + "it. Hides the group from authoring and new associations while keeping it queryable, so its " + "criteria and existing learner status rows stay resolvable." + ), + ) history = HistoricalRecords() @@ -307,6 +315,14 @@ class CompetencyCriterion(models.Model): null=True, blank=True, help_text=_("Overrides rule_profile's rule_payload for this criterion. Set only when rule_profile is null."), ) + archived = models.BooleanField( + default=False, + help_text=_( + "Set instead of deleting this criterion once learner status exists for it. Hides the " + "criterion from authoring and new associations while keeping it queryable, so existing " + "learner status rows stay resolvable." + ), + ) history = HistoricalRecords() diff --git a/src/openedx_learning/migrations/0014_add_archived_to_criteria_group_and_criterion.py b/src/openedx_learning/migrations/0014_add_archived_to_criteria_group_and_criterion.py new file mode 100644 index 000000000..ad8da9468 --- /dev/null +++ b/src/openedx_learning/migrations/0014_add_archived_to_criteria_group_and_criterion.py @@ -0,0 +1,48 @@ +# Generated by Django 5.2.17 on 2026-10-12 14:50 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ( + "openedx_learning", + "0013_alter_historicalcompetencycriteriagroup_history_date_and_more", + ), + ] + + operations = [ + migrations.AddField( + model_name="competencycriteriagroup", + name="archived", + field=models.BooleanField( + default=False, + help_text="Set instead of deleting this group once learner status exists for it or anything beneath it. Hides the group from authoring and new associations while keeping it queryable, so its criteria and existing learner status rows stay resolvable.", + ), + ), + migrations.AddField( + model_name="competencycriterion", + name="archived", + field=models.BooleanField( + default=False, + help_text="Set instead of deleting this criterion once learner status exists for it. Hides the criterion from authoring and new associations while keeping it queryable, so existing learner status rows stay resolvable.", + ), + ), + migrations.AddField( + model_name="historicalcompetencycriteriagroup", + name="archived", + field=models.BooleanField( + default=False, + help_text="Set instead of deleting this group once learner status exists for it or anything beneath it. Hides the group from authoring and new associations while keeping it queryable, so its criteria and existing learner status rows stay resolvable.", + ), + ), + migrations.AddField( + model_name="historicalcompetencycriterion", + name="archived", + field=models.BooleanField( + default=False, + help_text="Set instead of deleting this criterion once learner status exists for it. Hides the criterion from authoring and new associations while keeping it queryable, so existing learner status rows stay resolvable.", + ), + ), + ] diff --git a/tests/openedx_learning/applets/cbe/test_criteria_group.py b/tests/openedx_learning/applets/cbe/test_criteria_group.py index 39bb755f0..4836c4292 100644 --- a/tests/openedx_learning/applets/cbe/test_criteria_group.py +++ b/tests/openedx_learning/applets/cbe/test_criteria_group.py @@ -21,6 +21,18 @@ pytestmark = pytest.mark.django_db +# --------------------------------------------------------------------------------------------- +# Columns + + +# --------------------------------------------------------------------------------------------- + + +def test_group_archived_defaults_to_false(tag: Tag) -> None: + group = CompetencyCriteriaGroup.objects.create(tag=tag) + assert group.archived is False + + # --------------------------------------------------------------------------------------------- # Tree shape, and the two constraints ADR-0002 Decision 2 deliberately leaves out diff --git a/tests/openedx_learning/applets/cbe/test_criterion.py b/tests/openedx_learning/applets/cbe/test_criterion.py index d700dda6c..5d69d87d0 100644 --- a/tests/openedx_learning/applets/cbe/test_criterion.py +++ b/tests/openedx_learning/applets/cbe/test_criterion.py @@ -22,6 +22,22 @@ ] +# --------------------------------------------------------------------------------------------- +# Columns + + +# --------------------------------------------------------------------------------------------- + + +def test_criterion_archived_defaults_to_false( + group: CompetencyCriteriaGroup, object_tag: ObjectTag, default_rule_profile: CompetencyRuleProfile +) -> None: + criterion = CompetencyCriterion.objects.create( + group=group, object_tag=object_tag, rule_profile=default_rule_profile + ) + assert criterion.archived is False + + # --------------------------------------------------------------------------------------------- # Either a rule_profile or both overrides. Never both, never neither.