Skip to content

Commit

Permalink
Merge pull request #655 from praekeltfoundation/validation_fix
Browse files Browse the repository at this point in the history
Validation fix
  • Loading branch information
Hlamallama authored Aug 8, 2023
2 parents 1ee7d7e + 6ddd75c commit 5435178
Show file tree
Hide file tree
Showing 4 changed files with 564 additions and 54 deletions.
9 changes: 9 additions & 0 deletions yal/assessments.py
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,15 @@ async def state_handle_assessment_reminder_response(self):
return await self.go_to_state("state_pre_mainmenu")

async def state_not_interested(self):
msisdn = utils.normalise_phonenumber(self.inbound.from_addr)
whatsapp_id = msisdn.lstrip(" + ")
data = {
"endline_survey_started": "",
}
error = await rapidpro.update_profile(whatsapp_id, data, self.user.metadata)
if error:
return await self.go_to_state("state_error")

return WhatsAppButtonState(
self,
question=self._(
Expand Down
112 changes: 59 additions & 53 deletions yal/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,32 @@ async def process_message(self, message):
self.delete_metadata(key)

keyword = utils.clean_inbound(message.content)

baseline_survey_completed = self.user.metadata.get(
"baseline_survey_completed"
)
endline_survey_completed = self.user.metadata.get(
"endline_survey_completed"
)

endline_survey_started = self.user.metadata.get("endline_survey_started")
endline_reminder = self.user.metadata.get("endline_reminder")
feedback_state = await self.get_feedback_state()
payload = utils.get_by_path(
message.transport_metadata, "message", "button", "payload"
)

# Restart keywords that interrupt the current flow

if (
keyword in GREETING_KEYWORDS
or keyword in TRACKING_KEYWORDS
or keyword in TRACKING_KEYWORDS_ROUND_2
):
self.user.session_id = None
self.state_name = self.START_STATE

elif (
keyword in EMERGENCY_KEYWORDS
and message.transport_metadata.get("message", {}).get("type")
!= "interactive"
Expand All @@ -149,62 +173,46 @@ async def process_message(self, message):
self.user.session_id = None
self.state_name = PleaseCallMeApplication.CONFIRM_REDIRECT

if (
keyword in GREETING_KEYWORDS
or keyword in TRACKING_KEYWORDS
or keyword in TRACKING_KEYWORDS_ROUND_2
):
self.user.session_id = None
self.state_name = self.START_STATE

if keyword in HELP_KEYWORDS:
elif keyword in HELP_KEYWORDS:
self.user.session_id = None
self.state_name = PleaseCallMeApplication.START_STATE

if keyword in OPTOUT_KEYWORDS:
elif keyword in OPTOUT_KEYWORDS:
self.user.session_id = None
self.state_name = OptOutApplication.START_STATE

if keyword in FEEDBACK_KEYWORDS:
elif keyword in FEEDBACK_KEYWORDS:
self.user.session_id = None
self.state_name = FeedbackApplication.START_STATE

if keyword in AAQ_KEYWORDS:
elif keyword in AAQ_KEYWORDS:
self.user.session_id = None
self.state_name = AaqApplication.START_STATE

if keyword in CALLBACK_CHECK_KEYWORDS:
elif keyword in CALLBACK_CHECK_KEYWORDS:
self.user.session_id = None
self.state_name = PleaseCallMeApplication.CALLBACK_RESPONSE_STATE

if keyword in QA_RESET_FEEDBACK_TIMESTAMP_KEYWORDS:
elif keyword in QA_RESET_FEEDBACK_TIMESTAMP_KEYWORDS:
self.user.session_id = None
self.state_name = "state_qa_reset_feedback_timestamp_keywords"

if keyword in ONBOARDING_REMINDER_KEYWORDS:
if self.user.metadata.get("onboarding_reminder_sent"):
self.user.session_id = None
self.state_name = OnboardingApplication.REMINDER_STATE
if keyword in ASSESSMENT_REENGAGEMENT_KEYWORDS:
if self.user.metadata.get("assessment_reminder_sent"):
self.user.session_id = None
self.state_name = AssessmentApplication.REMINDER_STATE
elif keyword in ONBOARDING_REMINDER_KEYWORDS and self.user.metadata.get(
"onboarding_reminder_sent"
):
self.user.session_id = None
self.state_name = OnboardingApplication.REMINDER_STATE
elif keyword in ASSESSMENT_REENGAGEMENT_KEYWORDS and self.user.metadata.get(
"assessment_reminder_sent"
):
self.user.session_id = None
self.state_name = AssessmentApplication.REMINDER_STATE

if keyword in SURVEY_KEYWORDS:
elif keyword in SURVEY_KEYWORDS:
self.user.session_id = None
self.state_name = "state_baseline_start"

baseline_survey_completed = self.user.metadata.get(
"baseline_survey_completed"
)
endline_survey_completed = self.user.metadata.get(
"endline_survey_completed"
)

endline_survey_started = self.user.metadata.get("endline_survey_started")
endline_reminder = self.user.metadata.get("endline_reminder")

if (
elif (
keyword in EJAF_ENDLINE_SURVEY_KEYWORDS
and baseline_survey_completed
and not endline_survey_completed
Expand All @@ -225,32 +233,30 @@ async def process_message(self, message):
else:
self.state_name = EndlineTermsApplication.START_STATE

if endline_survey_started and keyword not in EJAF_ENDLINE_SURVEY_KEYWORDS:
self.user.session_id = None
self.state_name = EndlineSurveyApplication.SURVEY_VALIDATION_STATE

# Fields that RapidPro sets after a feedback push message
feedback_state = await self.get_feedback_state()
if feedback_state:
elif feedback_state:
if not self.user.session_id:
self.user.session_id = random_id()
message.session_event = Message.SESSION_EVENT.RESUME
self.state_name = feedback_state

# Replies to template push messages
payload = utils.get_by_path(
message.transport_metadata, "message", "button", "payload"
)
if payload:
if payload.startswith("state_") and payload in dir(self):
self.user.session_id = None
self.state_name = payload
elif payload.startswith("page_id_") and is_integer(
payload.split("_")[-1]
):
self.user.session_id = None
self.save_metadata("push_related_page_id", payload.split("_")[-1])
self.state_name = "state_prep_push_msg_related_page"
elif payload and payload.startswith("state_") and payload in dir(self):
self.user.session_id = None
self.state_name = payload

elif (
payload
and payload.startswith("page_id_")
and is_integer(payload.split("_")[-1])
):
self.user.session_id = None
self.save_metadata("push_related_page_id", payload.split("_")[-1])
self.state_name = "state_prep_push_msg_related_page"

elif endline_survey_started and keyword not in EJAF_ENDLINE_SURVEY_KEYWORDS:
self.user.session_id = None
self.state_name = EndlineSurveyApplication.SURVEY_VALIDATION_STATE

except Exception:
logger.exception("Application error")
Expand Down
18 changes: 17 additions & 1 deletion yal/tests/surveys/test_endline.py
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,11 @@ async def test_endline_survey_validation(tester: AppTester, rapidpro_mock):
[reply] = await app.process_message(msg)

assert user.state.name == "state_survey_validation"
assert reply.content in GENERIC_ERROR_OPTIONS
error_content = reply.content
if "Umm.." in error_content:
error_content = error_content.replace("🤖", "[persona_emoji]")

assert error_content in GENERIC_ERROR_OPTIONS


@pytest.mark.asyncio
Expand Down Expand Up @@ -1033,6 +1037,18 @@ async def test_state_body_image_assessment_endline_reminder(
tester.assert_metadata("assessment_reminder_type", "endline reengagement 30min")


@pytest.mark.asyncio
async def test_endline_stop_during_assessment(tester: AppTester, rapidpro_mock):
tester.user.metadata["endline_survey_started"] = True
tester.user.metadata["baseline_survey_completed"] = True
tester.user.metadata["terms_accepted"] = True
tester.user.metadata["onboarding_completed"] = True
tester.setup_state("state_gender_attitude_assessment_endline")

await tester.user_input("stop")
tester.assert_state("state_optout")


@pytest.mark.asyncio
async def test_endline_flow(tester: AppTester, rapidpro_mock):
await tester.user_input(
Expand Down
Loading

0 comments on commit 5435178

Please sign in to comment.