Browse Source

DIV-185 - split out step_completeness from user_response lib

pull/160/head
Mike Olund 8 years ago
parent
commit
00670dd16f
4 changed files with 90 additions and 84 deletions
  1. +1
    -1
      edivorce/apps/core/tests.py
  2. +82
    -0
      edivorce/apps/core/utils/step_completeness.py
  3. +5
    -81
      edivorce/apps/core/utils/user_response.py
  4. +2
    -2
      edivorce/apps/core/views/main.py

+ 1
- 1
edivorce/apps/core/tests.py View File

@ -1,6 +1,6 @@
from django.test import TestCase
from edivorce.apps.core.models import UserResponse, Question, BceidUser
from edivorce.apps.core.utils.user_response import is_complete
from edivorce.apps.core.utils.step_completeness import is_complete
from edivorce.apps.core.utils.question_step_mapping import question_step_mapping


+ 82
- 0
edivorce/apps/core/utils/step_completeness.py View File

@ -0,0 +1,82 @@
from edivorce.apps.core.models import Question
from edivorce.apps.core.utils.question_step_mapping import question_step_mapping
def get_step_status(responses_by_step):
status_dict = {}
for step, lst in responses_by_step.items():
if not lst:
status_dict[step] = "Not started"
else:
if is_complete(step, lst)[0]:
status_dict[step] = "Complete"
else:
status_dict[step] = "Started"
return status_dict
def is_complete(step, lst):
"""
Check required field of question for complete state
Required: question is always require user response to be complete
Conditional: question itself is required and depends on the response to this question,
optional question may be also required
"""
if not lst:
return False, []
question_list = Question.objects.filter(key__in=question_step_mapping[step])
required_list = list(question_list.filter(required='Required').values_list("key", flat=True))
conditional_list = list(question_list.filter(required='Conditional'))
complete = True
missing_responses = []
for question_key in required_list:
# everything in the required_list is required
if not __has_value(question_key, lst):
complete = False
missing_responses += [question_key]
for question in conditional_list:
# find the response to the conditional target
for target in lst:
if target["question_id"] == question.conditional_target:
if __condition_met(question.reveal_response, target, lst):
# the condition was met then the question is required.
# ... so check if it has a value
if not __has_value(question.key, lst):
complete = False
missing_responses += [question.key]
return complete, missing_responses
def __condition_met(reveal_response, target, lst):
# return false if the condition was not met
if target["value"] != reveal_response:
return False
# return true if the target is not Conditional
if target['question__required'] != 'Conditional':
return True
else:
# if the target is Conitional and the condition was met, check the target next
reveal_response = target["question__reveal_response"]
conditional_target = target["question__conditional_target"]
for new_target in lst:
if new_target["question_id"] == conditional_target:
# recursively search up the tree
return __condition_met(reveal_response, new_target, lst)
# if the for loop above didn't find the target, then the target question
# is unanswered and the condition was not met
return False
def __has_value(key, lst):
for user_response in lst:
if user_response["question_id"] == key:
answer = user_response["value"]
if answer != "" and answer != "[]" and answer != '[["",""]]':
return True
return False

+ 5
- 81
edivorce/apps/core/utils/user_response.py View File

@ -15,23 +15,14 @@ def get_responses_from_db_grouped_by_steps(bceid_user):
responses = UserResponse.objects.filter(bceid_user=bceid_user)
responses_dict = {}
for step, questions in question_step_mapping.items():
responses_dict[step] = responses.filter(question_id__in=questions).exclude(value__in=['', '[]', '[["",""]]']).order_by('question').values('question_id', 'value', 'question__name', 'question__required', 'question__conditional_target', 'question__reveal_response')
responses_dict[step] = responses.filter(question_id__in=questions).exclude(
value__in=['', '[]', '[["",""]]']).order_by('question').values('question_id', 'value', 'question__name',
'question__required',
'question__conditional_target',
'question__reveal_response')
return responses_dict
def get_step_status(responses_by_step):
status_dict = {}
for step, lst in responses_by_step.items():
if not lst:
status_dict[step] = "Not started"
else:
if is_complete(step, lst)[0]:
status_dict[step] = "Complete"
else:
status_dict[step] = "Started"
return status_dict
def get_responses_from_session(request):
return sorted(request.session.items())
@ -84,70 +75,3 @@ def copy_session_to_db(request, bceid_user):
# clear the response from the session
request.session[q.key] = None
def is_complete(step, lst):
"""
Check required field of question for complete state
Required: question is always require user response to be complete
Conditional: question itself is required and depends on the response to this question,
optional question may be also required
"""
if not lst:
return False, []
question_list = Question.objects.filter(key__in=question_step_mapping[step])
required_list = list(question_list.filter(required='Required').values_list("key", flat=True))
conditional_list = list(question_list.filter(required='Conditional'))
complete = True
missing_responses = []
for question_key in required_list:
# everything in the required_list is required
if not has_value(question_key, lst):
complete = False
missing_responses += [question_key]
for question in conditional_list:
# find the response to the conditional target
for target in lst:
if target["question_id"] == question.conditional_target:
if condition_met(question.reveal_response, target, lst):
# question is required
if not has_value(question.key, lst):
complete = False
missing_responses += [question.key]
return complete, missing_responses
def condition_met(reveal_response, target, lst):
# return false if the condition was not met
if target["value"] != reveal_response:
return False
# return true if the target is not Conditional
if target['question__required'] != 'Conditional':
return True
else:
# if the target is Conitional and the condition was met, check the target next
reveal_response = target["question__reveal_response"]
conditional_target = target["question__conditional_target"]
for new_target in lst:
if new_target["question_id"] == conditional_target:
# recursively search up the tree
return condition_met(reveal_response, new_target, lst)
# if the for loop above didn't find the target, then the target question
# is unanswered and the condition was not met
return False
def has_value(key, lst):
for user_response in lst:
if user_response["question_id"] == key:
answer = user_response["value"]
if answer != "" and answer != "[]" and answer != '[["",""]]':
return True
return False

+ 2
- 2
edivorce/apps/core/views/main.py View File

@ -7,8 +7,8 @@ from ..decorators import bceid_required
import datetime
from ..models import BceidUser
from ..utils.user_response import get_responses_from_db, get_responses_from_db_grouped_by_steps, \
get_responses_from_session, copy_session_to_db, get_step_status, is_complete, \
get_responses_from_session_grouped_by_steps
get_responses_from_session, copy_session_to_db, get_responses_from_session_grouped_by_steps
from ..utils.step_completeness import get_step_status, is_complete
from edivorce.apps.core.utils.question_step_mapping import list_of_registries


Loading…
Cancel
Save