Browse Source

Reimplement all logic for getting data and checking step completeness

pull/160/head
ariannedee 5 years ago
parent
commit
30c081547e
9 changed files with 429 additions and 691 deletions
  1. +142
    -388
      edivorce/apps/core/tests.py
  2. +69
    -0
      edivorce/apps/core/utils/conditional_logic.py
  3. +23
    -39
      edivorce/apps/core/utils/derived.py
  4. +4
    -0
      edivorce/apps/core/utils/question_step_mapping.py
  5. +10
    -109
      edivorce/apps/core/utils/step_completeness.py
  6. +112
    -96
      edivorce/apps/core/utils/user_response.py
  7. +36
    -19
      edivorce/apps/core/views/main.py
  8. +2
    -2
      edivorce/apps/core/views/pdf.py
  9. +31
    -38
      edivorce/fixtures/Question.json

+ 142
- 388
edivorce/apps/core/tests.py View File

@ -3,592 +3,346 @@ from edivorce.apps.core.models import UserResponse, Question, BceidUser
from edivorce.apps.core.utils.step_completeness import is_complete
from edivorce.apps.core.utils.question_step_mapping import question_step_mapping
# Create your tests here.
from edivorce.apps.core.utils.user_response import get_data_for_user, get_step_responses
class UserResponseTestCase(TestCase):
fixtures = ['Question.json']
def setUp(self):
BceidUser.objects.create(user_guid='1234')
self.user = BceidUser.objects.create(user_guid='1234')
def check_completeness(self, step):
responses_dict = get_data_for_user(self.user)
responses_dict_by_step = get_step_responses(responses_dict)
return is_complete(responses_dict_by_step[step])[0]
def create_response(self, question, value):
UserResponse.objects.create(bceid_user=self.user, question=Question.objects.get(key=question), value=value)
def test_which_order(self):
step = 'which_orders'
questions = question_step_mapping[step]
user = BceidUser.objects.get(user_guid='1234')
# No response should be False
lst = UserResponse.objects.filter(question_id__in=questions).values('question_id', 'value', 'question__conditional_target', 'question__reveal_response', 'question__required')
self.assertEqual(is_complete(step, lst)[0], False)
self.assertEqual(self.check_completeness(step), False)
# All required question
create_response(user, 'want_which_orders', '["nothing"]')
lst = UserResponse.objects.filter(question_id__in=questions).values('question_id', 'value', 'question__conditional_target', 'question__reveal_response', 'question__required')
self.assertEqual(is_complete(step, lst)[0], True)
self.create_response('want_which_orders', '["nothing"]')
self.assertEqual(self.check_completeness(step), True)
# Put empty response
UserResponse.objects.filter(question_id='want_which_orders').update(value="[]")
lst = UserResponse.objects.filter(question_id__in=questions).values('question_id', 'value', 'question__conditional_target', 'question__reveal_response', 'question__required')
self.assertEqual(is_complete(step, lst)[0], False)
self.assertEqual(self.check_completeness(step), False)
def test_your_info(self):
step = 'your_information'
questions = question_step_mapping[step]
user = BceidUser.objects.get(user_guid='1234')
# No response should be False
lst = UserResponse.objects.filter(question_id__in=questions).values('question_id', 'value', 'question__conditional_target', 'question__reveal_response', 'question__required')
self.assertEqual(is_complete(step, lst)[0], False)
self.assertEqual(self.check_completeness(step), False)
# Testing required questions
# Missing few required questions
create_response(user, 'name_you', 'John Doe')
create_response(user, 'last_name_before_married_you', 'Jackson')
create_response(user, 'birthday_you', '11/11/1111')
create_response(user, 'occupation_you', 'Plumber')
self.create_response('name_you', 'John Doe')
self.create_response('last_name_before_married_you', 'Jackson')
self.create_response('birthday_you', '11/11/1111')
self.create_response('occupation_you', 'Plumber')
lst = UserResponse.objects.filter(question_id__in=questions).values('question_id', 'value', 'question__conditional_target', 'question__reveal_response', 'question__required')
self.assertEqual(is_complete(step, lst)[0], False)
self.assertEqual(self.check_completeness(step), False)
# Few required questions with one checking question with hidden question not shown
create_response(user, 'lived_in_bc_you', '11/11/1111')
lst = UserResponse.objects.filter(question_id__in=questions).values('question_id', 'value', 'question__conditional_target', 'question__reveal_response', 'question__required')
self.assertEqual(is_complete(step, lst)[0], False)
self.create_response('lived_in_bc_you', '11/11/1111')
self.assertEqual(self.check_completeness(step), False)
# All required questions with one checking question with hidden question not shown
create_response(user, 'last_name_born_you', 'Jackson')
lst = UserResponse.objects.filter(question_id__in=questions).values('question_id', 'value', 'question__conditional_target', 'question__reveal_response', 'question__required')
self.assertEqual(is_complete(step, lst)[0], False)
self.create_response('last_name_born_you', 'Jackson')
self.assertEqual(self.check_completeness(step), False)
# All required questions with one checking question with hidden question missing
UserResponse.objects.filter(question_id='lived_in_bc_you').update(value="Moved to B.C. on")
lst = UserResponse.objects.filter(question_id__in=questions).values('question_id', 'value', 'question__conditional_target', 'question__reveal_response', 'question__required')
self.assertEqual(is_complete(step, lst)[0], False)
self.assertEqual(self.check_completeness(step), False)
# All required questions with one checking question with hidden question
create_response(user, 'moved_to_bc_date_you', '12/12/1212')
lst = UserResponse.objects.filter(question_id__in=questions).values('question_id', 'value', 'question__conditional_target', 'question__reveal_response', 'question__required')
self.assertEqual(is_complete(step, lst)[0], False)
self.create_response('moved_to_bc_date_you', '12/12/1212')
self.assertEqual(self.check_completeness(step), False)
# All required questions with two checking question with one hidden and one shown
create_response(user, 'any_other_name_you', 'NO')
lst = UserResponse.objects.filter(question_id__in=questions).values('question_id', 'value', 'question__conditional_target', 'question__reveal_response', 'question__required')
self.assertEqual(is_complete(step, lst)[0], True)
self.create_response('any_other_name_you', 'NO')
self.assertEqual(self.check_completeness(step), True)
# All required questions with two checking question with one hidden question missing
UserResponse.objects.filter(question_id='any_other_name_you').update(value="YES")
lst = UserResponse.objects.filter(question_id__in=questions).values('question_id', 'value', 'question__conditional_target', 'question__reveal_response', 'question__required')
self.assertEqual(is_complete(step, lst)[0], False)
self.assertEqual(self.check_completeness(step), False)
# All required questions with all checking question with all hidden questions
create_response(user, 'other_name_you', '[["also known as","Smith"]]')
lst = UserResponse.objects.filter(question_id__in=questions).values('question_id', 'value', 'question__conditional_target', 'question__reveal_response', 'question__required')
self.assertEqual(is_complete(step, lst)[0], True)
self.create_response('other_name_you', '[["also known as","Smith"]]')
self.assertEqual(self.check_completeness(step), True)
# Put empty response
UserResponse.objects.filter(question_id='other_name_you').update(value='[["",""]]')
lst = UserResponse.objects.filter(question_id__in=questions).values('question_id', 'value', 'question__conditional_target', 'question__reveal_response', 'question__required')
self.assertEqual(is_complete(step, lst)[0], False)
self.assertEqual(self.check_completeness(step), False)
def test_your_spouse(self):
step = 'your_spouse'
questions = question_step_mapping[step]
user = BceidUser.objects.get(user_guid='1234')
# No response should be False
lst = UserResponse.objects.filter(question_id__in=questions).values('question_id', 'value', 'question__conditional_target', 'question__reveal_response', 'question__required')
self.assertEqual(is_complete(step, lst)[0], False)
self.assertEqual(self.check_completeness(step), False)
# Testing required questions
# Missing few required questions
create_response(user, 'name_spouse', 'John Doe')
create_response(user, 'last_name_before_married_spouse', 'Jackson')
create_response(user, 'birthday_spouse', '11/11/1111')
create_response(user, 'occupation_spouse', 'Electrician')
self.create_response('name_spouse', 'John Doe')
self.create_response('last_name_before_married_spouse', 'Jackson')
self.create_response('birthday_spouse', '11/11/1111')
self.create_response('occupation_spouse', 'Electrician')
lst = UserResponse.objects.filter(question_id__in=questions).values('question_id', 'value', 'question__conditional_target', 'question__reveal_response', 'question__required')
self.assertEqual(is_complete(step, lst)[0], False)
self.assertEqual(self.check_completeness(step), False)
# Few required questions with one checking question with hidden question not shown
create_response(user, 'any_other_name_spouse', 'NO')
lst = UserResponse.objects.filter(question_id__in=questions).values('question_id', 'value', 'question__conditional_target', 'question__reveal_response', 'question__required')
self.assertEqual(is_complete(step, lst)[0], False)
self.create_response('any_other_name_spouse', 'NO')
self.assertEqual(self.check_completeness(step), False)
# All required questions with one checking question with hidden question not shown
create_response(user, 'last_name_born_spouse', 'Jackson')
lst = UserResponse.objects.filter(question_id__in=questions).values('question_id', 'value', 'question__conditional_target', 'question__reveal_response', 'question__required')
self.assertEqual(is_complete(step, lst)[0], False)
self.create_response('last_name_born_spouse', 'Jackson')
self.assertEqual(self.check_completeness(step), False)
# All required questions with one checking question with hidden question missing
UserResponse.objects.filter(question_id='any_other_name_spouse').update(value="YES")
lst = UserResponse.objects.filter(question_id__in=questions).values('question_id', 'value', 'question__conditional_target', 'question__reveal_response', 'question__required')
self.assertEqual(is_complete(step, lst)[0], False)
self.assertEqual(self.check_completeness(step), False)
# All required questions with one checking question with hidden question
create_response(user, 'lived_in_bc_spouse', 'Since birth')
lst = UserResponse.objects.filter(question_id__in=questions).values('question_id', 'value', 'question__conditional_target', 'question__reveal_response', 'question__required')
self.assertEqual(is_complete(step, lst)[0], False)
self.create_response('lived_in_bc_spouse', 'Since birth')
self.assertEqual(self.check_completeness(step), False)
# All required questions with two checking question with one hidden and one shown
create_response(user, 'other_name_spouse', '[["also known as","Smith"]]')
lst = UserResponse.objects.filter(question_id__in=questions).values('question_id', 'value', 'question__conditional_target', 'question__reveal_response', 'question__required')
self.assertEqual(is_complete(step, lst)[0], True)
self.create_response('other_name_spouse', '[["also known as","Smith"]]')
self.assertEqual(self.check_completeness(step), True)
# All required questions with two checking question with one hidden question missing
UserResponse.objects.filter(question_id='lived_in_bc_spouse').update(value="Moved to B.C. on")
lst = UserResponse.objects.filter(question_id__in=questions).values('question_id', 'value', 'question__conditional_target', 'question__reveal_response', 'question__required')
self.assertEqual(is_complete(step, lst)[0], False)
self.assertEqual(self.check_completeness(step), False)
# All required questions with all checking question with all hidden questions
create_response(user, 'moved_to_bc_date_spouse', '12/12/1212')
lst = UserResponse.objects.filter(question_id__in=questions).values('question_id', 'value', 'question__conditional_target', 'question__reveal_response', 'question__required')
self.assertEqual(is_complete(step, lst)[0], True)
self.create_response('moved_to_bc_date_spouse', '12/12/1212')
self.assertEqual(self.check_completeness(step), True)
# Put empty response
UserResponse.objects.filter(question_id='name_spouse').update(value="")
lst = UserResponse.objects.filter(question_id__in=questions).values('question_id', 'value', 'question__conditional_target', 'question__reveal_response', 'question__required')
self.assertEqual(is_complete(step, lst)[0], False)
self.assertEqual(self.check_completeness(step), False)
# Put empty response
UserResponse.objects.filter(question_id='other_name_spouse').update(value='[["",""]]')
lst = UserResponse.objects.filter(question_id__in=questions).values('question_id', 'value', 'question__conditional_target', 'question__reveal_response', 'question__required')
self.assertEqual(is_complete(step, lst)[0], False)
self.assertEqual(self.check_completeness(step), False)
def test_your_marriage(self):
step = 'your_marriage'
questions = question_step_mapping[step]
user = BceidUser.objects.get(user_guid='1234')
# No response should be False
lst = UserResponse.objects.filter(question_id__in=questions).values('question_id', 'value',
'question__conditional_target',
'question__reveal_response',
'question__required')
self.assertEqual(is_complete(step, lst)[0], False)
# Some required questions
create_response(user, 'when_were_you_live_married_like', '12/12/2007')
lst = UserResponse.objects.filter(question_id__in=questions).values('question_id', 'value',
'question__conditional_target',
'question__reveal_response',
'question__required')
self.assertEqual(is_complete(step, lst)[0], False)
self.assertEqual(self.check_completeness(step), False)
# Some required questions
create_response(user, 'when_were_you_married', '12/12/2008')
lst = UserResponse.objects.filter(question_id__in=questions).values('question_id', 'value',
'question__conditional_target',
'question__reveal_response',
'question__required')
self.assertEqual(is_complete(step, lst)[0], False)
self.create_response('when_were_you_live_married_like', '12/12/2007')
self.assertEqual(self.check_completeness(step), False)
# Some required questions
create_response(user, 'marital_status_before_you', 'Never married')
self.create_response('when_were_you_married', '12/12/2008')
self.assertEqual(self.check_completeness(step), False)
lst = UserResponse.objects.filter(question_id__in=questions).values('question_id', 'value',
'question__conditional_target',
'question__reveal_response',
'question__required')
self.assertEqual(is_complete(step, lst)[0], False)
# Some required questions
create_response(user, 'marital_status_before_spouse', 'Widowed')
self.create_response('marital_status_before_you', 'Never married')
self.assertEqual(self.check_completeness(step), False)
lst = UserResponse.objects.filter(question_id__in=questions).values('question_id', 'value',
'question__conditional_target',
'question__reveal_response',
'question__required')
self.assertEqual(is_complete(step, lst)[0], False)
self.create_response('marital_status_before_spouse', 'Widowed')
self.assertEqual(self.check_completeness(step), False)
# Some required questions
create_response(user, 'where_were_you_married_city', 'Vancouver')
lst = UserResponse.objects.filter(question_id__in=questions).values('question_id', 'value',
'question__conditional_target',
'question__reveal_response',
'question__required')
self.assertEqual(is_complete(step, lst)[0], False)
# Some required questions
create_response(user, 'where_were_you_married_prov', 'BC')
self.create_response('where_were_you_married_city', 'Vancouver')
self.assertEqual(self.check_completeness(step), False)
lst = UserResponse.objects.filter(question_id__in=questions).values('question_id', 'value',
'question__conditional_target',
'question__reveal_response',
'question__required')
self.assertEqual(is_complete(step, lst)[0], False)
self.create_response('where_were_you_married_prov', 'BC')
self.assertEqual(self.check_completeness(step), False)
# All required questions
create_response(user, 'where_were_you_married_country', 'Canada')
lst = UserResponse.objects.filter(question_id__in=questions).values('question_id', 'value',
'question__conditional_target',
'question__reveal_response',
'question__required')
self.assertEqual(is_complete(step, lst)[0], True)
self.create_response('where_were_you_married_country', 'Canada')
self.assertEqual(self.check_completeness(step), True)
# All required questions but missing conditional question
UserResponse.objects.filter(question_id='where_were_you_married_country').update(value="Other")
lst = UserResponse.objects.filter(question_id__in=questions).values('question_id', 'value',
'question__conditional_target',
'question__reveal_response',
'question__required')
self.assertEqual(is_complete(step, lst)[0], False)
self.assertEqual(self.check_completeness(step), False)
# All required questions
create_response(user, 'where_were_you_married_other_country', 'Peru')
lst = UserResponse.objects.filter(question_id__in=questions).values('question_id', 'value',
'question__conditional_target',
'question__reveal_response',
'question__required')
self.assertEqual(is_complete(step, lst)[0], True)
self.create_response('where_were_you_married_other_country', 'Peru')
self.assertEqual(self.check_completeness(step), True)
def test_your_separation(self):
step = 'your_separation'
questions = question_step_mapping[step]
user = BceidUser.objects.get(user_guid='1234')
# No response should be False
lst = UserResponse.objects.filter(question_id__in=questions).values('question_id', 'value', 'question__conditional_target', 'question__reveal_response', 'question__required')
self.assertEqual(is_complete(step, lst)[0], False)
self.assertEqual(self.check_completeness(step), False)
# All required question
create_response(user, 'no_reconciliation_possible', 'I agree')
lst = UserResponse.objects.filter(question_id__in=questions).values('question_id', 'value', 'question__conditional_target', 'question__reveal_response', 'question__required')
self.assertEqual(is_complete(step, lst)[0], False)
self.create_response('no_reconciliation_possible', 'I agree')
self.assertEqual(self.check_completeness(step), False)
# Put empty response
UserResponse.objects.filter(question_id='no_reconciliation_possible').update(value="")
lst = UserResponse.objects.filter(question_id__in=questions).values('question_id', 'value', 'question__conditional_target', 'question__reveal_response', 'question__required')
self.assertEqual(is_complete(step, lst)[0], False)
self.assertEqual(self.check_completeness(step), False)
def test_spousal_support(self):
step = 'spousal_support'
questions = question_step_mapping[step]
user = BceidUser.objects.get(user_guid='1234')
# No response should be False
lst = UserResponse.objects.filter(question_id__in=questions).values('question_id', 'value', 'question__conditional_target', 'question__reveal_response', 'question__required')
self.assertEqual(is_complete(step, lst)[0], False)
self.assertEqual(self.check_completeness(step), False)
# One required question
create_response(user, 'spouse_support_details', 'I will support you')
lst = UserResponse.objects.filter(question_id__in=questions).values('question_id', 'value', 'question__conditional_target', 'question__reveal_response', 'question__required')
self.assertEqual(is_complete(step, lst)[0], False)
self.create_response('spouse_support_details', 'I will support you')
self.assertEqual(self.check_completeness(step), False)
# Two required questions
create_response(user, 'spouse_support_act', 'Family Law')
lst = UserResponse.objects.filter(question_id__in=questions).values('question_id', 'value', 'question__conditional_target', 'question__reveal_response', 'question__required')
self.assertEqual(is_complete(step, lst)[0], True)
self.create_response('spouse_support_act', 'Family Law')
self.assertEqual(self.check_completeness(step), True)
# Remove first added required response to test the second required question
UserResponse.objects.get(question_id='spouse_support_details').delete()
lst = UserResponse.objects.filter(question_id__in=questions).values('question_id', 'value', 'question__conditional_target', 'question__reveal_response', 'question__required')
self.assertEqual(is_complete(step, lst)[0], False)
self.assertEqual(self.check_completeness(step), False)
# Put empty response
UserResponse.objects.filter(question_id='spouse_support_details').update(value="")
lst = UserResponse.objects.filter(question_id__in=questions).values('question_id', 'value', 'question__conditional_target', 'question__reveal_response', 'question__required')
self.assertEqual(is_complete(step, lst)[0], False)
self.assertEqual(self.check_completeness(step), False)
def test_property_and_debt(self):
step = 'property_and_debt'
questions = question_step_mapping[step]
user = BceidUser.objects.get(user_guid='1234')
# No response should be False
lst = UserResponse.objects.filter(question_id__in=questions).values('question_id', 'value', 'question__conditional_target', 'question__reveal_response', 'question__required')
self.assertEqual(is_complete(step, lst)[0], False)
self.assertEqual(self.check_completeness(step), False)
# All required question with no hidden shown
create_response(user, 'deal_with_property_debt', 'Equal division')
self.create_response('deal_with_property_debt', 'Equal division')
lst = UserResponse.objects.filter(question_id__in=questions).values('question_id', 'value', 'question__conditional_target', 'question__reveal_response', 'question__required')
self.assertEqual(is_complete(step, lst)[0], True)
self.assertEqual(self.check_completeness(step), True)
# All required question with hidden shown but no response
UserResponse.objects.filter(question_id='deal_with_property_debt').update(value="Unequal division")
lst = UserResponse.objects.filter(question_id__in=questions).values('question_id', 'value', 'question__conditional_target', 'question__reveal_response', 'question__required')
self.assertEqual(is_complete(step, lst)[0], False)
self.assertEqual(self.check_completeness(step), False)
# Only one required question with hidden shown and answered
create_response(user, 'how_to_divide_property_debt', 'Do not divide them')
lst = UserResponse.objects.filter(question_id__in=questions).values('question_id', 'value', 'question__conditional_target', 'question__reveal_response', 'question__required')
self.assertEqual(is_complete(step, lst)[0], True)
self.create_response('how_to_divide_property_debt', 'Do not divide them')
# Only two required question with hidden shown and answered
# NOTE: want_other_property_claims not in use anymore
# create_response(user, 'want_other_property_claims', '["Ask for other property claims"]')
#
# lst = UserResponse.objects.filter(question_id__in=questions).values('question_id', 'value', 'question__conditional_target', 'question__reveal_response', 'question__required')
# self.assertEqual(is_complete(step, lst)[0], False)
self.assertEqual(self.check_completeness(step), True)
# All required question with hidden shown and answered
create_response(user, 'other_property_claims', 'Want these property claims')
lst = UserResponse.objects.filter(question_id__in=questions).values('question_id', 'value', 'question__conditional_target', 'question__reveal_response', 'question__required')
self.assertEqual(is_complete(step, lst)[0], True)
# All required question with optional fields
self.create_response('other_property_claims', 'Want these property claims')
self.assertEqual(self.check_completeness(step), True)
# Put empty response
# UserResponse.objects.filter(question_id='want_other_property_claims').update(value="")
lst = UserResponse.objects.filter(question_id__in=questions).values('question_id', 'value', 'question__conditional_target', 'question__reveal_response', 'question__required')
self.assertEqual(is_complete(step, lst)[0], True)
UserResponse.objects.filter(question_id='want_other_property_claims').update(value="")
self.assertEqual(self.check_completeness(step), True)
def test_other_orders(self):
step = 'other_orders'
questions = question_step_mapping[step]
user = BceidUser.objects.get(user_guid='1234')
# No response should be False
lst = UserResponse.objects.filter(question_id__in=questions).values('question_id', 'value', 'question__conditional_target', 'question__reveal_response', 'question__required')
self.assertEqual(is_complete(step, lst)[0], False)
self.assertEqual(self.check_completeness(step), False)
# All required question
self.create_response('name_change_you', 'NO')
self.assertEqual(self.check_completeness(step), False)
create_response(user, 'name_change_you', 'NO')
self.assertEqual(is_complete(step, lst)[0], False)
create_response(user, 'name_change_spouse', 'NO')
create_response(user, 'other_orders_detail', 'I want more orders')
self.create_response('name_change_spouse', 'NO')
self.create_response('other_orders_detail', 'I want more orders')
lst = UserResponse.objects.filter(question_id__in=questions).values('question_id', 'value', 'question__conditional_target', 'question__reveal_response', 'question__required')
self.assertEqual(is_complete(step, lst)[0], True)
self.assertEqual(self.check_completeness(step), True)
# make incomplete
UserResponse.objects.filter(question_id='name_change_spouse').update(value="YES")
self.assertEqual(self.check_completeness(step), False)
lst = UserResponse.objects.filter(question_id__in=questions).values('question_id', 'value', 'question__conditional_target', 'question__reveal_response', 'question__required')
self.assertEqual(is_complete(step, lst)[0], False)
create_response(user, 'name_change_spouse_fullname', 'new name')
lst = UserResponse.objects.filter(question_id__in=questions).values('question_id', 'value', 'question__conditional_target', 'question__reveal_response', 'question__required')
self.assertEqual(is_complete(step, lst)[0], True)
self.create_response('name_change_spouse_fullname', 'new name')
self.assertEqual(self.check_completeness(step), True)
# Put empty response
UserResponse.objects.filter(question_id='other_orders_detail').update(value="")
lst = UserResponse.objects.filter(question_id__in=questions).values('question_id', 'value', 'question__conditional_target', 'question__reveal_response', 'question__required')
self.assertEqual(is_complete(step, lst)[0], True)
self.assertEqual(self.check_completeness(step), True)
def test_other_questions(self):
step = 'other_questions'
questions = question_step_mapping[step]
user = BceidUser.objects.get(user_guid='1234')
# No response should be False
lst = UserResponse.objects.filter(question_id__in=questions).values('question_id', 'value',
'question__conditional_target',
'question__reveal_response',
'question__required')
self.assertEqual(is_complete(step, lst)[0], False)
# One required question
create_response(user, 'address_to_send_official_document_street_you', '123 Cambie st')
lst = UserResponse.objects.filter(question_id__in=questions).values('question_id', 'value',
'question__conditional_target',
'question__reveal_response',
'question__required')
self.assertEqual(is_complete(step, lst)[0], False)
self.assertEqual(self.check_completeness(step), False)
# Two required question
create_response(user, 'address_to_send_official_document_city_you', 'Vancouver')
# Some required question
self.create_response('address_to_send_official_document_street_you', '123 Cambie st')
self.assertEqual(self.check_completeness(step), False)
lst = UserResponse.objects.filter(question_id__in=questions).values('question_id', 'value',
'question__conditional_target',
'question__reveal_response',
'question__required')
self.assertEqual(is_complete(step, lst)[0], False)
self.create_response('address_to_send_official_document_city_you', 'Vancouver')
self.assertEqual(self.check_completeness(step), False)
# Three required question
create_response(user, 'address_to_send_official_document_prov_you', 'BC')
self.create_response('address_to_send_official_document_prov_you', 'BC')
self.assertEqual(self.check_completeness(step), False)
lst = UserResponse.objects.filter(question_id__in=questions).values('question_id', 'value',
'question__conditional_target',
'question__reveal_response',
'question__required')
self.assertEqual(is_complete(step, lst)[0], False)
# Four required question
create_response(user, 'address_to_send_official_document_country_you', 'Canada')
lst = UserResponse.objects.filter(question_id__in=questions).values('question_id', 'value',
'question__conditional_target',
'question__reveal_response',
'question__required')
self.assertEqual(is_complete(step, lst)[0], False)
self.create_response('address_to_send_official_document_country_you', 'Canada')
self.assertEqual(self.check_completeness(step), False)
# All required questions for you
create_response(user, 'address_to_send_official_document_postal_code_you', 'Canada')
lst = UserResponse.objects.filter(question_id__in=questions).values('question_id', 'value',
'question__conditional_target',
'question__reveal_response',
'question__required')
self.assertEqual(is_complete(step, lst)[0], False)
self.create_response('address_to_send_official_document_postal_code_you', 'Canada')
self.assertEqual(self.check_completeness(step), False)
# One required question for spouse
create_response(user, 'address_to_send_official_document_street_spouse', '123 Cambie st')
lst = UserResponse.objects.filter(question_id__in=questions).values('question_id', 'value',
'question__conditional_target',
'question__reveal_response',
'question__required')
self.assertEqual(is_complete(step, lst)[0], False)
self.create_response('address_to_send_official_document_street_spouse', '123 Cambie st')
self.assertEqual(self.check_completeness(step), False)
# Two required question for spouse
create_response(user, 'address_to_send_official_document_city_spouse', 'Vancouver')
lst = UserResponse.objects.filter(question_id__in=questions).values('question_id', 'value',
'question__conditional_target',
'question__reveal_response',
'question__required')
self.assertEqual(is_complete(step, lst)[0], False)
self.create_response('address_to_send_official_document_city_spouse', 'Vancouver')
self.assertEqual(self.check_completeness(step), False)
# Three required question for spouse
create_response(user, 'address_to_send_official_document_prov_spouse', 'BC')
lst = UserResponse.objects.filter(question_id__in=questions).values('question_id', 'value',
'question__conditional_target',
'question__reveal_response',
'question__required')
self.assertEqual(is_complete(step, lst)[0], False)
self.create_response('address_to_send_official_document_prov_spouse', 'BC')
self.assertEqual(self.check_completeness(step), False)
# Four required question for spouse
create_response(user, 'address_to_send_official_document_country_spouse', 'Canada')
lst = UserResponse.objects.filter(question_id__in=questions).values('question_id', 'value',
'question__conditional_target',
'question__reveal_response',
'question__required')
self.assertEqual(is_complete(step, lst)[0], False)
self.create_response('address_to_send_official_document_country_spouse', 'Canada')
self.assertEqual(self.check_completeness(step), False)
# All required questions
create_response(user, 'divorce_take_effect_on', 'the 31st day after the date of this order')
lst = UserResponse.objects.filter(question_id__in=questions).values('question_id', 'value',
'question__conditional_target',
'question__reveal_response',
'question__required')
self.assertEqual(is_complete(step, lst)[0], True)
self.create_response('divorce_take_effect_on', 'the 31st day after the date of this order')
self.assertEqual(self.check_completeness(step), True)
# Missing conditional required question
UserResponse.objects.filter(question_id='divorce_take_effect_on').update(value="specific date")
lst = UserResponse.objects.filter(question_id__in=questions).values('question_id', 'value',
'question__conditional_target',
'question__reveal_response',
'question__required')
self.assertEqual(is_complete(step, lst)[0], False)
self.assertEqual(self.check_completeness(step), False)
# All required questions
create_response(user, 'divorce_take_effect_on_specific_date', '12/12/2018')
lst = UserResponse.objects.filter(question_id__in=questions).values('question_id', 'value',
'question__conditional_target',
'question__reveal_response',
'question__required')
self.assertEqual(is_complete(step, lst)[0], True)
self.create_response('divorce_take_effect_on_specific_date', '12/12/2018')
self.assertEqual(self.check_completeness(step), True)
# All required questions for spouse and you
create_response(user, 'address_to_send_official_document_postal_code_spouse', 'Canada')
self.create_response('address_to_send_official_document_postal_code_spouse', 'Canada')
lst = UserResponse.objects.filter(question_id__in=questions).values('question_id', 'value',
'question__conditional_target',
'question__reveal_response',
'question__required')
self.assertEqual(is_complete(step, lst)[0], True)
self.assertEqual(self.check_completeness(step), True)
# All required questions for spouse and you with empty email(optional so still true)
create_response(user, 'address_to_send_official_document_email_you', 'a@example.com')
lst = UserResponse.objects.filter(question_id__in=questions).values('question_id', 'value',
'question__conditional_target',
'question__reveal_response',
'question__required')
self.assertEqual(is_complete(step, lst)[0], True)
self.create_response('address_to_send_official_document_email_you', 'a@example.com')
self.assertEqual(self.check_completeness(step), True)
# Testing other country missing
UserResponse.objects.filter(question_id='address_to_send_official_document_country_spouse').update(value="Other")
lst = UserResponse.objects.filter(question_id__in=questions).values('question_id', 'value',
'question__conditional_target',
'question__reveal_response',
'question__required')
self.assertEqual(is_complete(step, lst)[0], False)
self.assertEqual(self.check_completeness(step), False)
# All required questions
create_response(user, 'address_to_send_official_document_other_country_spouse', 'Mexico')
lst = UserResponse.objects.filter(question_id__in=questions).values('question_id', 'value',
'question__conditional_target',
'question__reveal_response',
'question__required')
self.assertEqual(is_complete(step, lst)[0], True)
self.create_response('address_to_send_official_document_other_country_spouse', 'Mexico')
self.assertEqual(self.check_completeness(step), True)
# Set Specific date on to empty
UserResponse.objects.filter(question_id='divorce_take_effect_on_specific_date').update(value="")
lst = UserResponse.objects.filter(question_id__in=questions).values('question_id', 'value',
'question__conditional_target',
'question__reveal_response',
'question__required')
self.assertEqual(is_complete(step, lst)[0], False)
self.assertEqual(self.check_completeness(step), False)
def test_filing_locations(self):
step = 'filing_locations'
questions = question_step_mapping[step]
user = BceidUser.objects.get(user_guid='1234')
# No response should be False
lst = UserResponse.objects.filter(question_id__in=questions).values('question_id', 'value', 'question__conditional_target', 'question__reveal_response', 'question__required')
self.assertEqual(is_complete(step, lst)[0], False)
self.assertEqual(self.check_completeness(step), False)
# All required question
create_response(user, 'court_registry_for_filing', 'Vancouver')
lst = UserResponse.objects.filter(question_id__in=questions).values('question_id', 'value', 'question__conditional_target', 'question__reveal_response', 'question__required')
self.assertEqual(is_complete(step, lst)[0], True)
self.create_response('court_registry_for_filing', 'Vancouver')
self.assertEqual(self.check_completeness(step), True)
# Put empty response
UserResponse.objects.filter(question_id='court_registry_for_filing').update(value="")
lst = UserResponse.objects.filter(question_id__in=questions).values('question_id', 'value', 'question__conditional_target', 'question__reveal_response', 'question__required')
self.assertEqual(is_complete(step, lst)[0], False)
# Helper functions
def create_response(user, question, value):
UserResponse.objects.create(bceid_user=user, question=Question.objects.get(key=question), value=value)
self.assertEqual(self.check_completeness(step), False)

+ 69
- 0
edivorce/apps/core/utils/conditional_logic.py View File

@ -0,0 +1,69 @@
import json
def get_children(questions_dict):
children_json = questions_dict.get('claimant_children', '[]')
if isinstance(children_json, dict):
children_json = children_json.get('value', '[]')
return json.loads(children_json)
def determine_sole_custody(questions_dict):
child_list = get_children(questions_dict)
return (all([child['child_live_with'] == 'Lives with you' for child in child_list]) or
all([child['child_live_with'] == 'Lives with spouse' for child in child_list]))
def determine_shared_custody(questions_dict):
child_list = get_children(questions_dict)
return any([child['child_live_with'] == 'Lives with both'
for child in child_list])
def determine_split_custody(questions_dict):
child_list = get_children(questions_dict)
with_you = 0
with_spouse = 0
with_both = 0
for child in child_list:
if child['child_live_with'] == 'Lives with you':
with_you += 1
elif child['child_live_with'] == 'Lives with spouse':
with_spouse += 1
elif child['child_live_with'] == 'Lives with both':
with_both += 1
return (with_you > 0 and (with_spouse + with_both > 0) or
with_spouse > 0 and (with_you + with_both > 0))
def determine_child_over_19_supported(questions_dict):
try:
children_over_19 = float(questions_dict.get('number_children_over_19', 0))
except ValueError:
children_over_19 = 0
support = json.loads(questions_dict.get('children_financial_support', '[]'))
has_children_of_marriage = questions_dict.get('children_of_marriage', '') == 'YES'
return (len(support) > 0 and children_over_19 > 0 and
'NO' not in support and has_children_of_marriage)
def determine_missing_undue_hardship_reasons(questions_dict):
claiming_undue_hardship = questions_dict.get('claiming_undue_hardship', '') == 'YES'
if claiming_undue_hardship:
at_least_one_of = ["claimant_debts", "claimant_expenses", "supporting_non_dependents", "supporting_dependents",
"supporting_disabled", "undue_hardship"]
for question in at_least_one_of:
value = questions_dict.get(question)
if value:
try:
items = json.loads(value)
for item in items:
for key in item:
if item[key]:
return False
except json.JSONDecodeError:
if value:
return False
return True

+ 23
- 39
edivorce/apps/core/utils/derived.py View File

@ -13,6 +13,8 @@ under the _derived_ key.
import json
from edivorce.apps.core.utils import conditional_logic
# This array is order sensitive: later functions may depend on values from
# earlier ones
DERIVED_DATA = [
@ -72,6 +74,7 @@ DERIVED_DATA = [
'pursuant_parenting_arrangement',
'pursuant_child_support',
'sole_custody',
'missing_undue_hardship_details',
]
@ -150,9 +153,7 @@ def show_fact_sheet_b(responses, derived):
If any child lives with both parents, custody is shared, so Fact Sheet B
is indicated.
"""
return any([child['child_live_with'] == 'Lives with both'
for child in derived['children']])
return conditional_logic.determine_shared_custody(responses)
def show_fact_sheet_c(responses, derived):
@ -160,19 +161,7 @@ def show_fact_sheet_c(responses, derived):
If any child lives with one parent and there's another child who lives with
the other parent or is shared, Fact Sheet C is indicated.
"""
with_you = 0
with_spouse = 0
with_both = 0
for child in derived['children']:
if child['child_live_with'] == 'Lives with you':
with_you += 1
elif child['child_live_with'] == 'Lives with spouse':
with_spouse += 1
elif child['child_live_with'] == 'Lives with both':
with_both += 1
return (with_you > 0 and (with_spouse + with_both > 0) or
with_spouse > 0 and (with_you + with_both > 0))
return conditional_logic.determine_split_custody(responses)
def show_fact_sheet_d(responses, derived):
@ -180,15 +169,7 @@ def show_fact_sheet_d(responses, derived):
If a claimaint is claiming financial support for a child of the marriage
over 19, Fact Sheet D is indicated.
"""
try:
children_over_19 = float(responses.get('number_children_over_19', 0))
except ValueError:
children_over_19 = 0
support = json.loads(responses.get('children_financial_support', '[]'))
return (len(support) > 0 and children_over_19 > 0 and
'NO' not in support and has_children_of_marriage(responses, derived))
return conditional_logic.determine_child_over_19_supported(responses)
def show_fact_sheet_e(responses, derived):
@ -242,11 +223,11 @@ def show_fact_sheet_f_spouse(responses, derived):
def has_fact_sheets(responses, derived):
""" Return whether or not the user is submitting fact sheets """
return any([derived['show_fact_sheet_b'], derived['show_fact_sheet_c'],
derived['show_fact_sheet_d'], derived['show_fact_sheet_e'],
derived['show_fact_sheet_f'], ])
def child_support_payor_b(responses, derived):
""" Return who the payor is depends on the monthly amount from Factsheet B """
try:
@ -264,10 +245,11 @@ def child_support_payor_b(responses, derived):
elif amount_1 < amount_2:
payor = 'spouse'
else:
payor = 'both'
payor = 'both'
return payor
def child_support_payor_c(responses, derived):
""" Return who the payor is depends on the monthly amount from Factsheet C """
try:
@ -285,10 +267,11 @@ def child_support_payor_c(responses, derived):
elif amount_1 < amount_2:
payor = 'spouse'
else:
payor = 'both'
payor = 'both'
return payor
def guideline_amounts_difference_b(responses, derived):
"""
Return the difference between the guideline amounts to be paid by
@ -307,6 +290,7 @@ def guideline_amounts_difference_b(responses, derived):
return abs(amount_1 - amount_2)
def guideline_amounts_difference_c(responses, derived):
"""
Return the difference between the guideline amounts to be paid by
@ -325,6 +309,7 @@ def guideline_amounts_difference_c(responses, derived):
return abs(amount_1 - amount_2)
def guideline_amounts_difference_total(responses, derived):
"""
Return the sum of the guideline amounts B and C
@ -339,14 +324,15 @@ def guideline_amounts_difference_total(responses, derived):
if payor_b == payor_c:
return amount_b + amount_c
else:
return abs(amount_b - amount_c)
return abs(amount_b - amount_c)
def schedule_1_amount(responses, derived):
""" Return the amount as defined in schedule 1 for child support """
try:
if derived['show_fact_sheet_b'] or derived['show_fact_sheet_c']:
return derived['guideline_amounts_difference_total']
return derived['guideline_amounts_difference_total']
else:
return float(responses.get('payor_monthly_child_support_amount', 0))
except ValueError:
@ -540,13 +526,11 @@ def total_monthly_support_1_and_a(responses, derived):
total += derived['total_section_seven_expenses']
return total
def total_child_support_payment_a(response, derived):
""" Return the total monthly child support payable by the payor for Fact Sheet A """
total = 0
sole_custody = (all([child['child_live_with'] == 'Lives with you' for child in derived['children']]) or
all([child['child_live_with'] == 'Lives with spouse' for child in derived['children']]))
if sole_custody:
if sole_custody(response, derived):
total += derived['schedule_1_amount']
else:
if derived['show_fact_sheet_b']:
@ -717,8 +701,8 @@ def sole_custody(responses, derived):
"""
Return True if either parent has sole custody of the children
"""
you_have_sole_custody = all([child['child_live_with'] == 'Lives with you'
for child in derived['children']])
spouse_has_sole_custody = all([child['child_live_with'] == 'Lives with spouse'
for child in derived['children']])
return you_have_sole_custody or spouse_has_sole_custody
return conditional_logic.determine_sole_custody(responses)
def missing_undue_hardship_details(responses, derived):
return conditional_logic.determine_missing_undue_hardship_reasons(responses)

+ 4
- 0
edivorce/apps/core/utils/question_step_mapping.py View File

@ -128,6 +128,9 @@ question_step_mapping = {
'your_spouse_child_support_paid_b',
'your_child_support_paid_c',
'your_spouse_child_support_paid_c',
'agree_to_guideline_child_support_amount',
'appropriate_spouse_paid_child_support',
'suggested_child_support',
'extra_ordinary_expenses_you',
'extra_ordinary_expenses_spouse',
'additional_relevant_spouse_children_info',
@ -184,6 +187,7 @@ page_step_mapping = {
'property': 'property_and_debt',
'other_orders': 'other_orders',
'other_questions': 'other_questions',
'filing_locations': 'filing_locations',
}


+ 10
- 109
edivorce/apps/core/utils/step_completeness.py View File

@ -1,8 +1,7 @@
import ast
from django.urls import reverse
from edivorce.apps.core.models import Question
from edivorce.apps.core.utils.question_step_mapping import question_step_mapping, pre_qual_step_question_mapping
from edivorce.apps.core.utils.question_step_mapping import pre_qual_step_question_mapping
def evaluate_numeric_condition(target, reveal_response):
@ -32,14 +31,14 @@ def evaluate_numeric_condition(target, reveal_response):
return None
def get_step_status(responses_by_step):
def get_step_completeness(responses_by_step):
status_dict = {}
missing_response_dict = {}
for step, lst in responses_by_step.items():
if not lst:
for step, responses_list in responses_by_step.items():
if len(responses_list) == 0:
status_dict[step] = "Not started"
else:
complete, missing_responses = is_complete(step, lst)
complete, missing_responses = is_complete(responses_list)
if complete:
status_dict[step] = "Complete"
else:
@ -48,69 +47,12 @@ def get_step_status(responses_by_step):
return status_dict, missing_response_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: Optional question needed depends on reveal_response value of conditional_target.
"""
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
def is_complete(response_list):
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]
elif question_key == "special_extraordinary_expenses":
has_extraordinary_expenses = __get_value("special_extraordinary_expenses", lst)
if has_extraordinary_expenses.lower() == 'yes':
# validate at least one item is > 0
special_expenses_keys = ["child_care_expenses", "annual_child_care_expenses", "children_healthcare_premiums",
"annual_children_healthcare_premiums", "health_related_expenses", "annual_health_related_expenses",
"extraordinary_educational_expenses", "annual_extraordinary_educational_expenses",
"post_secondary_expenses", "annual_post_secondary_expenses", "extraordinary_extracurricular_expenses",
"annual_extraordinary_extracurricular_expenses"]
for expense in special_expenses_keys:
value = __get_value(expense, lst)
if value and float(value) > 0:
break
else:
missing_responses.append('special_extraordinary_expenses_details')
for question in conditional_list:
# check condition for payor_monthly_child_support_amount
# which needs sole_custody to be computed separately
# payor_monthly_child_support_ammount is required only if sole_custody is True
if question.key == "payor_monthly_child_support_amount":
for target in lst:
if target["question_id"] == "claimant_children":
child_list = ast.literal_eval(target['value'])
sole_custody = (all([child['child_live_with'] == 'Lives with you' for child in child_list]) or
all([child['child_live_with'] == 'Lives with spouse' for child in child_list]))
if sole_custody:
if not __has_value(question.key, lst):
complete = False
missing_responses += [question.key]
break
else:
# 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
for question_dict in response_list:
if question_dict['error']:
missing_responses.append(question_dict)
return len(missing_responses) == 0, missing_responses
def get_formatted_incomplete_list(missed_question_keys):
@ -131,44 +73,3 @@ def get_formatted_incomplete_list(missed_question_keys):
'step_url': reverse('prequalification', kwargs={'step': step})
})
return missed_questions
def __condition_met(reveal_response, target, lst):
# check whether using a numeric condition
numeric_condition_met = evaluate_numeric_condition(target["value"], reveal_response)
if numeric_condition_met is None:
# handle special negation options. ex) '!NO' matches anything but 'NO'
if reveal_response.startswith('!'):
if target["value"] == "" or target["value"] == reveal_response[1:]:
return False
elif target["value"] != reveal_response:
return False
elif numeric_condition_met is False:
return False
# return true if the target is not Conditional
if target['question__required'] != 'Conditional':
return True
else:
# if the target is Conditional 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 __get_value(key, lst):
for user_response in lst:
if user_response["question_id"] == key:
return user_response["value"]
def __has_value(key, lst):
value = __get_value(key, lst)
return value and value != "" and value != "[]" and value != '[["",""]]' and value != "\n"

+ 112
- 96
edivorce/apps/core/utils/user_response.py View File

@ -1,90 +1,128 @@
from edivorce.apps.core.models import UserResponse, Question
from edivorce.apps.core.utils.question_step_mapping import question_step_mapping
from edivorce.apps.core.utils import conditional_logic
from edivorce.apps.core.utils.question_step_mapping import page_step_mapping, question_step_mapping
from edivorce.apps.core.utils.step_completeness import evaluate_numeric_condition
from collections import OrderedDict
def get_responses_from_db(bceid_user):
""" Get UserResponses from the database for a user."""
married, married_questions, responses = __get_data(bceid_user)
responses_dict = {}
for answer in responses:
if not married and answer.question_id in married_questions:
responses_dict[answer.question.key] = ''
elif answer.value.strip('[').strip(']'):
responses_dict[answer.question.key] = answer.value
return responses_dict
def get_responses_from_db_grouped_by_steps(bceid_user, hide_failed_conditionals=False):
def get_data_for_user(bceid_user):
"""
Group questions and responses by steps to which they belong
`hide_failed_conditionals` goes through the responses after grouping and
tests their conditionality. If they fail, the response is blanked (this is
to hide conditional responses that are no longer applicable but haven't been
erased, mainly for the question review page).
Return a dictionary of {question_key: user_response_value}
"""
married, married_questions, responses = __get_data(bceid_user)
responses = UserResponse.objects.filter(bceid_user=bceid_user)
responses_dict = {}
for response in responses:
if response.value.strip('[').strip(']'):
responses_dict[response.question_id] = response.value
for step, questions in question_step_mapping.items():
return responses_dict
lst = []
step_responses = responses.filter(question_id__in=questions).exclude(
value__in=['', '[]', '[["",""]]']).order_by('question')
for answer in step_responses:
if not married and answer.question_id in married_questions:
value = ''
def get_step_responses(responses_by_key):
"""
Accepts a dictionary of {question_key: user_response_value} (from get_data_for_user)
Returns a dictionary of {step: {question_id: {question__name, question_id, value, error}}}
"""
responses_by_step = {}
for step in page_step_mapping.values():
questions_dict = _get_questions_dict_set_for_step(step)
step_responses = []
for question in questions_dict:
question_details = _get_question_details(question, questions_dict, responses_by_key)
if question_details['show']:
question_dict = questions_dict[question]
question_dict['value'] = question_details['value']
question_dict['error'] = question_details['error']
step_responses.append(question_dict)
responses_by_step[step] = step_responses
return responses_by_step
def _get_questions_dict_set_for_step(step):
questions = Question.objects.filter(key__in=question_step_mapping[step])
questions_dict = {}
for question in questions:
question_dict = {
'question__conditional_target': question.conditional_target,
'question__reveal_response': question.reveal_response,
'question__name': question.name,
'question__required': question.required,
'question_id': question.key,
}
questions_dict[question.pk] = question_dict
return questions_dict
def _cleaned_response_value(response):
ignore_values = [None, '', '[]', '[["",""]]', '[["also known as",""]]']
if response not in ignore_values:
return response
return None
def _condition_met(target_response, reveal_response):
# check whether using a numeric condition
numeric_condition_met = evaluate_numeric_condition(target_response, reveal_response)
if numeric_condition_met is None:
# handle special negation options. ex) '!NO' matches anything but 'NO'
if reveal_response.startswith('!'):
if target_response == "" or target_response.lower() == reveal_response[1:].lower():
return False
elif str(target_response) != reveal_response:
return False
elif numeric_condition_met is False:
return False
return True
def _get_question_details(question, questions_dict, responses_by_key):
"""
Return details for a question given the set of question details and user responses.
value: The user's response to a question (or None if unanswered)
error: True if the question has an error (e.g. required but not answered)
show: False if the response shouldn't be displayed (e.g. don't show 'Also known as' name, but 'Does your spouse go by any other names' is NO)
"""
question_dict = questions_dict[question]
required = False
show = True
if question_dict["question__required"] == 'Required':
required = True
elif question_dict["question__required"] == 'Conditional':
target = question_dict["question__conditional_target"]
if target.startswith('determine_'):
# Look for the right function to evaluate conditional logic
derived_condition = getattr(conditional_logic, target)
if not derived_condition:
raise NotImplemented(target)
result = derived_condition(responses_by_key)
if result and _condition_met(result, question_dict["question__reveal_response"]):
required = True
else:
show = False
elif question in questions_dict:
target_response = responses_by_key.get(target)
if target_response and _condition_met(target_response, question_dict["question__reveal_response"]):
required = True
else:
value = answer.value
lst += [{'question__conditional_target': answer.question.conditional_target,
'question__reveal_response': answer.question.reveal_response,
'value': value,
'question__name': answer.question.name,
'question__required': answer.question.required,
'question_id': answer.question.pk}]
# This was added for DIV-514, where the user entered a name change for
# their spouse but then said 'no', they won't be changing their name.
# Since we don't blank related answers, we need to hide it dynamically.
# This only works for questions in the same step.
if hide_failed_conditionals:
values = {q['question_id']: q['value'] for q in lst}
for q in lst:
if q['question__required'] != 'Conditional':
continue
target = q['question__conditional_target']
if target.startswith('['):
targets = target.strip('[]').split(',')
filtered_targets = [t for t in targets if t not in values]
# filtered_targets = list(filter(lambda t: t not in values, targets))
if len(filtered_targets):
continue
reveal_responses = dict(zip(targets, q['question__reveal_response'].strip('[]').split(',')))
present = [val for key, val in reveal_responses.items() if val != values[key]]
if len(present):
q['value'] = ''
continue
if target not in values:
continue
numeric_condition = evaluate_numeric_condition(values[target], q['question__reveal_response'])
if numeric_condition is None:
if q['question__reveal_response'].startswith('!'):
if values[target] == "" or values[target] == q['question__reveal_response'][1:]:
q['value'] = ''
elif q['question__reveal_response'] and q['question__reveal_response'] != values[target]:
q['value'] = ''
elif numeric_condition is False:
q['value'] = ''
responses_dict[step] = lst
show = False
if show:
value = None
response = responses_by_key.get(question)
if response:
value = _cleaned_response_value(response)
error = required and not value
else:
value = None
error = None
return responses_dict
details = {
'value': value,
'error': error,
'show': show
}
return details
def get_responses_from_session(request):
@ -139,25 +177,3 @@ def copy_session_to_db(request, bceid_user):
# clear the response from the session
request.session[q.key] = None
def __get_data(bceid_user):
"""
Gets UserResponses from the database for a user, plus a boolean indicating
if the user is married or common-law, and a list of questions that only apply to
married couples
"""
COMMON_LAW = 'Living together in a marriage like relationship'
MARRIED = 'Legally married'
responses = UserResponse.objects.filter(bceid_user=bceid_user).select_related('question')
married_status = responses.filter(question_id='married_marriage_like')
if married_status.count() > 0:
married = married_status[0].value != COMMON_LAW
else:
married = False
married_questions = list(
Question.objects.filter(reveal_response=MARRIED).values_list("key", flat=True))
return married, married_questions, responses

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

@ -1,4 +1,5 @@
import datetime
from copy import deepcopy
from django.conf import settings
from django.shortcuts import render, redirect
@ -7,11 +8,15 @@ from django.utils import timezone
from edivorce.apps.core.utils.derived import get_derived_data
from ..decorators import bceid_required, intercept
from ..utils.question_step_mapping import list_of_registries, page_step_mapping
from ..utils.step_completeness import get_step_status, is_complete, get_formatted_incomplete_list
from ..utils.step_completeness import get_step_completeness, is_complete, get_formatted_incomplete_list
from ..utils.template_step_order import template_step_order
from ..utils.user_response import get_responses_from_db, copy_session_to_db, \
get_responses_from_db_grouped_by_steps, get_responses_from_session, \
get_responses_from_session_grouped_by_steps
from ..utils.user_response import (
get_data_for_user,
copy_session_to_db,
get_step_responses,
get_responses_from_session,
get_responses_from_session_grouped_by_steps,
)
def home(request):
@ -40,10 +45,10 @@ def prequalification(request, step):
if not request.user.is_authenticated:
responses_dict = get_responses_from_session(request)
else:
responses_dict = get_responses_from_db(request.user)
responses_dict = get_data_for_user(request.user)
responses_dict['active_page'] = 'prequalification'
responses_by_step = get_responses_from_db_grouped_by_steps(request.user)
step_status, _ = get_step_status(responses_by_step)
responses_by_step = get_step_responses(responses_dict)
step_status, _ = get_step_completeness(responses_by_step)
responses_dict['step_status'] = step_status
return render(request, template_name=template, context=responses_dict)
@ -154,13 +159,14 @@ def overview(request):
"""
Dashboard: Process overview page.
"""
responses_dict_by_step = get_responses_from_db_grouped_by_steps(request.user)
responses_dict = get_data_for_user(request.user)
responses_dict_by_step = get_step_responses(responses_dict)
# Add step status dictionary
step_status, _ = get_step_status(responses_dict_by_step)
step_status, _ = get_step_completeness(responses_dict_by_step)
responses_dict_by_step['step_status'] = step_status
responses_dict_by_step['active_page'] = 'overview'
responses_dict_by_step['derived'] = get_derived_data(get_responses_from_db(request.user))
responses_dict_by_step['derived'] = get_derived_data(responses_dict)
response = render(request, 'overview.html', context=responses_dict_by_step)
@ -175,7 +181,7 @@ def dashboard_nav(request, nav_step):
"""
Dashboard: All other pages
"""
responses_dict = get_responses_from_db(request.user)
responses_dict = get_data_for_user(request.user)
responses_dict['active_page'] = nav_step
template_name = 'dashboard/%s.html' % nav_step
return render(request, template_name=template_name, context=responses_dict)
@ -189,19 +195,30 @@ def question(request, step, sub_step=None):
sub_page_template = '_{}'.format(sub_step) if sub_step else ''
template = 'question/%02d_%s%s.html' % (template_step_order[step], step, sub_page_template)
responses_dict_by_step = get_responses_from_db_grouped_by_steps(request.user, True)
step_status, missing_questions = get_step_status(responses_dict_by_step)
if step == "review":
responses_dict = responses_dict_by_step
derived = get_derived_data(get_responses_from_db(request.user))
responses_dict = get_data_for_user(request.user)
responses_dict_by_step = get_step_responses(responses_dict)
step_status, missing_questions = get_step_completeness(responses_dict_by_step)
derived = get_derived_data(responses_dict)
responses_dict = {}
# Just for now (until showing missing questions in review is implemented) remove unanswered questions
for step, question_list in responses_dict_by_step.items():
copy = deepcopy(question_list)
for question_dict in question_list:
if question_dict['value'] is None:
copy.remove(question_dict)
responses_dict[step] = copy
else:
responses_dict = get_data_for_user(request.user)
responses_dict_by_step = get_step_responses(responses_dict)
step_status, missing_questions = get_step_completeness(responses_dict_by_step)
question_step = page_step_mapping.get(step, step)
show_errors = step_status.get(question_step) == 'Started'
responses_dict = get_responses_from_db(request.user)
derived = get_derived_data(responses_dict)
if show_errors:
for key in missing_questions.get(question_step):
responses_dict[key + '_error'] = True
for question_dict in missing_questions.get(question_step):
responses_dict[question_dict['question_id'] + '_error'] = True
# Add step status dictionary
responses_dict['step_status'] = step_status
@ -258,7 +275,7 @@ def intercept_page(request):
input.
"""
template = 'question/%02d_%s.html' % (template_step_order['orders'], 'orders')
responses_dict = get_responses_from_db(request.user)
responses_dict = get_data_for_user(request.user)
responses_dict['intercepted'] = True
return render(request, template_name=template, context=responses_dict)


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

@ -10,7 +10,7 @@ import requests
from ..decorators import bceid_required
from ..utils.derived import get_derived_data
from ..utils.user_response import get_responses_from_db
from ..utils.user_response import get_data_for_user
EXHIBITS = list('ABCDEFGHIJKLMNOPQRSTUVWXYZ'[::-1])
@ -19,7 +19,7 @@ EXHIBITS = list('ABCDEFGHIJKLMNOPQRSTUVWXYZ'[::-1])
def form(request, form_number):
""" View for rendering PDF's and previews """
responses = get_responses_from_db(request.user)
responses = get_data_for_user(request.user)
if (form_number == '1' or form_number.startswith('37') or
form_number.startswith('38') or


+ 31
- 38
edivorce/fixtures/Question.json View File

@ -395,7 +395,7 @@
"name": "Where were you married? Prov",
"description": "For step 4, Form 1 2. Divorce section A, Form 52 Court orders that section",
"summary_order": 38,
"required": "Required"
"required": ""
},
"model": "core.question",
"pk": "where_were_you_married_prov"
@ -504,15 +504,6 @@
"model": "core.question",
"pk": "how_to_divide_property_debt"
},
{
"fields": {
"name": "Claimant 1 and Claimant 2 ask for an order respecting an interest in property or for compensation instead of an interest in that property, as follows",
"description": "For step 7, Form 1 6. Property and debt",
"summary_order": 49
},
"model": "core.question",
"pk": "want_other_property_claims"
},
{
"fields": {
"name": "Please list any other property claims.",
@ -1219,8 +1210,8 @@
"description": "For Step 6, Your children - Income & expenses - Spouse Fact Sheet F",
"summary_order": 0,
"required": "Conditional",
"conditional_target": "claiming_undue_hardship",
"reveal_response": "YES"
"conditional_target": "determine_missing_undue_hardship_reasons",
"reveal_response": "True"
},
"model": "core.question",
"pk": "claimant_debts"
@ -1231,8 +1222,8 @@
"description": "For Step 6, Your children - Income & expenses - Spouse Fact Sheet F",
"summary_order": 0,
"required": "Conditional",
"conditional_target": "claiming_undue_hardship",
"reveal_response": "YES"
"conditional_target": "determine_missing_undue_hardship_reasons",
"reveal_response": "True"
},
"model": "core.question",
"pk": "claimant_expenses"
@ -1243,8 +1234,8 @@
"description": "For Step 6, Your children - Income & expenses - Spouse Fact Sheet F",
"summary_order": 0,
"required": "Conditional",
"conditional_target": "claiming_undue_hardship",
"reveal_response": "YES"
"conditional_target": "determine_missing_undue_hardship_reasons",
"reveal_response": "True"
},
"model": "core.question",
"pk": "supporting_non_dependents"
@ -1255,8 +1246,8 @@
"description": "For Step 6, Your children - Income & expenses - Spouse Fact Sheet F",
"summary_order": 0,
"required": "Conditional",
"conditional_target": "claiming_undue_hardship",
"reveal_response": "YES"
"conditional_target": "determine_missing_undue_hardship_reasons",
"reveal_response": "True"
},
"model": "core.question",
"pk": "supporting_dependents"
@ -1267,8 +1258,8 @@
"description": "For Step 6, Your children - Income & expenses - Spouse Fact Sheet F",
"summary_order": 0,
"required": "Conditional",
"conditional_target": "claiming_undue_hardship",
"reveal_response": "YES"
"conditional_target": "determine_missing_undue_hardship_reasons",
"reveal_response": "True"
},
"model": "core.question",
"pk": "supporting_disabled"
@ -1279,8 +1270,8 @@
"description": "For Step 6, Your children - Income & expenses - Spouse Fact Sheet F",
"summary_order": 0,
"required": "Conditional",
"conditional_target": "claiming_undue_hardship",
"reveal_response": "YES"
"conditional_target": "determine_missing_undue_hardship_reasons",
"reveal_response": "True"
},
"model": "core.question",
"pk": "undue_hardship"
@ -1290,9 +1281,7 @@
"name": "Income of Other Persons in Household",
"description": "For Step 6, Your children - Income & expenses - Spouse Fact Sheet F",
"summary_order": 0,
"required": "Conditional",
"conditional_target": "claiming_undue_hardship",
"reveal_response": "YES"
"required": ""
},
"model": "core.question",
"pk": "income_others"
@ -1540,7 +1529,8 @@
"summary_order": 0,
"required": "Conditional",
"conditional_target": "claimant_children",
"reveal_response": ""
"conditional_target": "determine_shared_custody",
"reveal_response": "True"
},
"model": "core.question",
"pk": "number_of_children"
@ -1551,8 +1541,8 @@
"description": "For Step 6, Your children - Your children - Fact Sheet B Shared Custody",
"summary_order": 0,
"required": "Conditional",
"conditional_target": "claimant_children",
"reveal_response": ""
"conditional_target": "determine_shared_custody",
"reveal_response": "True"
},
"model": "core.question",
"pk": "time_spent_with_you"
@ -1563,8 +1553,8 @@
"description": "For Step 6, Your children - Your children - Fact Sheet B Shared Custody",
"summary_order": 0,
"required": "Conditional",
"conditional_target": "claimant_children",
"reveal_response": ""
"conditional_target": "determine_shared_custody",
"reveal_response": "True"
},
"model": "core.question",
"pk": "time_spent_with_spouse"
@ -1575,8 +1565,8 @@
"description": "For Step 6, Your children - Your children - Fact Sheet B Shared Custody",
"summary_order": 0,
"required": "Conditional",
"conditional_target": "claimant_children",
"reveal_response": ""
"conditional_target": "determine_shared_custody",
"reveal_response": "True"
},
"model": "core.question",
"pk": "your_child_support_paid_b"
@ -1587,8 +1577,8 @@
"description": "For Step 6, Your children - Your children - Fact Sheet B Shared Custody",
"summary_order": 0,
"required": "Conditional",
"conditional_target": "claimant_children",
"reveal_response": ""
"conditional_target": "determine_shared_custody",
"reveal_response": "True"
},
"model": "core.question",
"pk": "your_spouse_child_support_paid_b"
@ -1779,7 +1769,8 @@
"description": "For Step 6, Your children - Income & expenses - Fact Sheet D Child(ren) 19 Years or Older",
"summary_order": 0,
"required": "Conditional",
"reveal_response": ""
"conditional_target": "determine_child_over_19_supported",
"reveal_response": "True"
},
"model": "core.question",
"pk": "agree_to_guideline_child_support_amount"
@ -1790,7 +1781,8 @@
"description": "For Step 6, Your children - Income & expenses - Fact Sheet D Child(ren) 19 Years or Older",
"summary_order": 0,
"required": "Conditional",
"reveal_response": ""
"conditional_target": "agree_to_guideline_child_support_amount",
"reveal_response": "NO"
},
"model": "core.question",
"pk": "appropriate_spouse_paid_child_support"
@ -1802,7 +1794,7 @@
"summary_order": 0,
"required": "Conditional",
"conditional_target": "agree_to_guideline_child_support_amount",
"reveal_response": "YES"
"reveal_response": "NO"
},
"model": "core.question",
"pk": "suggested_child_support"
@ -1823,7 +1815,8 @@
"description": "For Step 6, Your children - Income & expenses",
"summary_order": 0,
"required": "Conditional",
"reveal_response": ""
"conditional_target": "determine_sole_custody",
"reveal_response": "True"
},
"model": "core.question",
"pk": "payor_monthly_child_support_amount"


Loading…
Cancel
Save