@@ -1723,38 +1723,44 @@ def recalculate_editors_storage(self):
17231723 for editor in self .files .values_list ('uploaded_by_id' , flat = True ).distinct ():
17241724 calculate_user_storage (editor )
17251725
1726- def mark_complete (self ):
1726+ def mark_complete (self ): # noqa C901
1727+ errors = []
17271728 # Is complete if title is falsy but only if not a root node.
1728- is_complete = (bool (self .title ) or self .parent_id is None )
1729+ if not (bool (self .title ) or self .parent_id is None ):
1730+ errors .append ("Empty title" )
17291731 if self .kind_id != content_kinds .TOPIC :
1730- is_complete = is_complete and bool (self .license )
1731- if self .license and self .license .is_custom :
1732- is_complete = is_complete and bool (self .license_description )
1733- if self .license and self .license .copyright_holder_required :
1734- is_complete = is_complete and bool (self .copyright_holder )
1735- if self .kind_id != content_kinds .EXERCISE :
1736- is_complete = is_complete and self .files .filter (preset__supplementary = False ).exists ()
1737- else :
1732+ if not self .license :
1733+ errors .append ("Missing license" )
1734+ if self .license and self .license .is_custom and not self .license_description :
1735+ errors .append ("Missing license description for custom license" )
1736+ if self .license and self .license .copyright_holder_required and not self .copyright_holder :
1737+ errors .append ("Missing required copyright holder" )
1738+ if self .kind_id != content_kinds .EXERCISE and not self .files .filter (preset__supplementary = False ).exists ():
1739+ errors .append ("Missing default file" )
1740+ if self .kind_id == content_kinds .EXERCISE :
17381741 # Check to see if the exercise has at least one assessment item that has:
1739- is_complete = is_complete and self .assessment_items .filter (
1742+ if not self .assessment_items .filter (
17401743 # A non-blank question
17411744 ~ Q (question = '' )
17421745 # Non-blank answers
17431746 & ~ Q (answers = '[]' )
17441747 # With either an input question or one answer marked as correct
17451748 & (Q (type = exercises .INPUT_QUESTION ) | Q (answers__iregex = r'"correct":\s*true' ))
1746- ).exists ()
1749+ ).exists ():
1750+ errors .append ("No questions with question text and complete answers" )
17471751 # Check that it has a mastery model set
17481752 # Either check for the previous location for the mastery model, or rely on our completion criteria validation
17491753 # that if it has been set, then it has been set correctly.
17501754 criterion = self .extra_fields .get ("options" , {}).get ("completion_criteria" )
1751- is_complete = is_complete and (self .extra_fields .get ("mastery_model" ) or criterion )
1755+ if not (self .extra_fields .get ("mastery_model" ) or criterion ):
1756+ errors .append ("Missing mastery criterion" )
17521757 if criterion :
17531758 try :
17541759 completion_criteria .validate (criterion , kind = content_kinds .EXERCISE )
17551760 except completion_criteria .ValidationError :
1756- is_complete = False
1757- self .complete = is_complete
1761+ errors .append ("Mastery criterion is defined but is invalid" )
1762+ self .complete = not errors
1763+ return errors
17581764
17591765 def on_create (self ):
17601766 self .changed = True
0 commit comments