Skip to content

Commit

Permalink
1694: added stipulations to program electives causes 500 error in Dja…
Browse files Browse the repository at this point in the history
…ngo admin (#1751)

* Don't save the program if there are errors

* Program django admin validation error messages

Errors messages are displayed for:
- Minimum # of" operator must have Value equal to 1 or more.
- Minimum # of" operator must have Value equal to 1 or more.
- Minimum # of" operator must have Value equal to or less than the number of elective courses in the section.
- Section must have a Title.
This also adds operator_value and elective_flag to the default requirements section in order to allow the user to change the section to an elective section.

* Revert save method changes

* Handle elective stipulations

* Improve commenting
  • Loading branch information
collinpreston authored Jul 19, 2023
1 parent d8b2172 commit 5698a0d
Showing 1 changed file with 68 additions and 3 deletions.
71 changes: 68 additions & 3 deletions courses/forms.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from django.db import transaction
from django.forms import ModelForm
from django.forms import ModelForm, ValidationError
from django.forms.fields import JSONField
from webpack_loader import utils as webpack_loader_utils

Expand Down Expand Up @@ -200,7 +200,9 @@ def __init__(self, *args, **kwargs):
"data": {
"node_type": ProgramRequirementNodeType.OPERATOR.value,
"title": "Required Courses",
"operator_value": None,
"operator": ProgramRequirement.Operator.ALL_OF.value,
"elective_flag": False,
},
"children": [],
},
Expand Down Expand Up @@ -231,13 +233,76 @@ def _serialize(node):

return [_serialize(node) for node in data]

def clean(self):
def _verify_elective_operator(operator):
"""
Verifies that a Program's elective operator contains
a defined Value field.
Args:
operator (dict):
{
'children': [],
'id': None,
'data': {
'node_type': 'operator',
'title': 'Only 1 of',
'operator': 'min_number_of',
'operator_value': '1',
'elective_flag': False
}
}
Raises:
ValidationError: operator_value does not exist.
ValidationError: operator_value does exist but is empty.
ValidationError: operator_value is not equal to or less than the total number of child courses.
"""
if (
operator["data"]["operator"]
== ProgramRequirement.Operator.MIN_NUMBER_OF.value
):
if "operator_value" not in operator["data"]:
raise ValidationError(
'"Minimum # of" operator must have Value equal to 1 or more.'
)
if operator["data"]["operator_value"] == "":
raise ValidationError(
'"Minimum # of" operator must have Value equal to 1 or more.'
)

# Check all of the child nodes to count the total number of elective courses
# and validate any elective stipulations.
total_child_courses = 0
for child in operator["children"]:
if child["data"]["node_type"] == "operator":
_verify_elective_operator(child)
else:
# Assume the child must be a course.
total_child_courses += 1

if total_child_courses < int(operator["data"]["operator_value"]):
raise ValidationError(
'"Minimum # of" operator must have Value equal to or less than the number of elective courses in the section.'
)
if operator["data"]["title"] == "":
raise ValidationError("Operator must have a Title.")

if "requirements" in self.cleaned_data:
for operator in self.cleaned_data["requirements"]:
if (
operator["data"]["operator"]
== ProgramRequirement.Operator.MIN_NUMBER_OF.value
):
_verify_elective_operator(operator)

def save(self, commit=True):
"""Save requirements"""
program = super().save(commit=commit)
transaction.on_commit(self.save_requirements)
transaction.on_commit(self._save_requirements)
return program

def save_requirements(self):
def _save_requirements(self):
"""
Save related program requirements.
"""
Expand Down

0 comments on commit 5698a0d

Please sign in to comment.