Skip to content

Commit

Permalink
Merge pull request #714 from praekeltfoundation/endline_fixes
Browse files Browse the repository at this point in the history
Endline fixes
  • Loading branch information
Hlamallama authored Nov 22, 2023
2 parents 86f7ab3 + e2e96da commit 1628daa
Show file tree
Hide file tree
Showing 6 changed files with 292 additions and 47 deletions.
35 changes: 35 additions & 0 deletions yal/endline_terms_and_conditions.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
WhatsAppButtonState,
WhatsAppListState,
)
from vaccine.utils import get_display_choices
from yal import rapidpro
from yal.surveys.endline import Application as EndlineApplication
from yal.utils import get_current_datetime, get_generic_error, normalise_phonenumber
Expand All @@ -16,6 +17,7 @@
class Application(BaseApplication):
START_STATE = "state_start_terms"
NO_CONSENT_STATE = "state_no_consent"
ENDLINE_LIMIT_REACHED_STATE = "state_endline_limit_reached"

async def state_start_terms(self):
question = self._(
Expand Down Expand Up @@ -346,3 +348,36 @@ async def state_submit_terms_and_conditions_endline(self):
)
await asyncio.sleep(0.5)
return await self.go_to_state(EndlineApplication.START_STATE)

async def state_endline_limit_reached(self):
choices = [
Choice("menu", "Go to the menu"),
Choice("aaq", "Ask a question"),
]

question = self._(
"\n".join(
[
"Eish! It looks like you just missed the cut off for our survey. "
"No worries, we get it, life happens!",
"",
"Stay tuned for more survey opportunities. We appreciate your "
"enthusiasm and hope you can catch the next one.",
"",
"Go ahead and browse the menu or ask us a question.",
"",
get_display_choices(choices),
]
)
)

return WhatsAppButtonState(
self,
question=question,
choices=choices,
error=self._(get_generic_error()),
next={
"menu": "state_pre_mainmenu",
"aaq": "state_aaq_start",
},
)
15 changes: 15 additions & 0 deletions yal/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,21 @@ async def process_message(self, message):
elif keyword == "i m not interested":
self.state_name = AssessmentApplication.NOT_INTERESTED_STATE
else:
endline_study_max_participant_count = (
await rapidpro.get_global_value(
"endline_study_max_participant_count"
)
)

group_count = await rapidpro.get_group_membership_count(
group_name="Endline Survey Completed"
)

if group_count >= int(endline_study_max_participant_count):
return await self.go_to_state(
EndlineTermsApplication.ENDLINE_LIMIT_REACHED_STATE
)

self.state_name = EndlineTermsApplication.START_STATE

data = {
Expand Down
28 changes: 28 additions & 0 deletions yal/rapidpro.py
Original file line number Diff line number Diff line change
Expand Up @@ -187,3 +187,31 @@ async def get_global_flag(global_name):
else:
continue
return is_active


async def get_global_value(global_name):
"""
Fetches a global variable.
"""
async with get_rapidpro_api() as session:
for i in range(3):
try:
response = await session.get(
urljoin(
config.RAPIDPRO_URL,
f"/api/v2/globals.json?key={global_name}",
),
)
response.raise_for_status()
response_body = await response.json()

rapidpro_global = str(response_body["results"][0]["value"]).lower()

except HTTP_EXCEPTIONS as e:
if i == 2:
logger.exception(e)
return False
else:
continue

return rapidpro_global
1 change: 1 addition & 0 deletions yal/tests/states_dictionary.md
Original file line number Diff line number Diff line change
Expand Up @@ -617,6 +617,7 @@
| state_platform_review_assessment_endline | False | Text | Review the platform |
| state_relationship_status_endline | False | Text | endline relationship status |
| state_submit_terms_and_conditions_endline | False | Text | Endline Terms and Condition Submit |
| state_endline_limit_reached | False | Text | Endline Maximum reached |
| state_not_interested | False | Text | Endline Survery not interested |
| state_monthly_household_income_endline | False | Text | Endline household income |
| state_start_terms | False | Text | Endline terms and conditions |
Expand Down
108 changes: 67 additions & 41 deletions yal/tests/surveys/test_endline.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ def get_rapidpro_contact(urn):
}


def get_rapidpro_group(name):
return {"count": 100}


@pytest.fixture(autouse=True)
async def rapidpro_mock():
Sanic.test_mode = True
Expand Down Expand Up @@ -61,6 +65,40 @@ def update_contact(request):
return response.json({}, status=500)
return response.json({}, status=200)

@app.route("/api/v2/globals.json", methods=["GET"])
def get_global_value(request):
tstate.requests.append(request)
assert request.args.get("key") == "endline_study_max_participant_count"
return response.json(
{
"next": None,
"previous": None,
"results": [
{
"key": "Endline Study Max Participant Count",
"name": "endline_study_max_participant_count",
"value": 250,
"modified_on": "2023-05-30T07:34:06.216776Z",
}
],
},
status=200,
)

@app.route("/api/v2/groups.json", methods=["GET"])
def get_group(request):
tstate.requests.append(request)

group = [get_rapidpro_group("Endline Survey Completed")]

return response.json(
{
"results": group,
"next": None,
},
status=200,
)

async with run_sanic(app) as server:
url = config.RAPIDPRO_URL
config.RAPIDPRO_URL = f"http://{server.host}:{server.port}"
Expand All @@ -71,29 +109,21 @@ def update_contact(request):


@pytest.mark.asyncio
async def test_endline_invitation_i_want_to_answer(tester: AppTester, rapidpro_mock):
@mock.patch("yal.rapidpro.get_group_membership_count")
async def test_endline_invitation_i_want_to_answer(
get_group_membership_count, tester: AppTester, rapidpro_mock
):

user = User(
addr="278201234567",
state=StateData(),
session_id=1,
metadata={
"baseline_survey_completed": True,
"endline_survey_started": "Pending",
},
)
app = Application(user)
msg = Message(
content="Yes, I want to answer",
to_addr="27820001002",
from_addr="27820001003",
transport_name="whatsapp",
transport_type=Message.TRANSPORT_TYPE.HTTP_API,
)
get_group_membership_count.return_value = 100

[reply] = await app.process_message(msg)
tester.user.metadata["baseline_survey_completed"] = True
tester.user.metadata["endline_survey_started"] = "Pending"
tester.user.metadata["terms_accepted"] = True
tester.user.metadata["onboarding_completed"] = True

await tester.user_input("Yes, I want to answer")

assert user.state.name == "state_start_terms"
tester.assert_state("state_start_terms")


@pytest.mark.asyncio
Expand Down Expand Up @@ -153,29 +183,21 @@ async def test_endline_invitation_not_interested(


@pytest.mark.asyncio
async def test_endline_invitation_answer(tester: AppTester, rapidpro_mock):
@mock.patch("yal.rapidpro.get_group_membership_count")
async def test_endline_invitation_answer(
get_group_membership_count, tester: AppTester, rapidpro_mock
):

user = User(
addr="278201234567",
state=StateData(),
session_id=1,
metadata={
"baseline_survey_completed": True,
"endline_survey_started": "Pending",
},
)
app = Application(user)
msg = Message(
content="answer",
to_addr="27820001002",
from_addr="27820001003",
transport_name="whatsapp",
transport_type=Message.TRANSPORT_TYPE.HTTP_API,
)
get_group_membership_count.return_value = 100

[reply] = await app.process_message(msg)
tester.user.metadata["baseline_survey_completed"] = True
tester.user.metadata["endline_survey_started"] = "Pending"
tester.user.metadata["terms_accepted"] = True
tester.user.metadata["onboarding_completed"] = True

assert user.state.name == "state_start_terms"
await tester.user_input("Yes, I want to answer")

tester.assert_state("state_start_terms")


@pytest.mark.asyncio
Expand Down Expand Up @@ -1268,7 +1290,11 @@ async def test_endline_flow(tester: AppTester, rapidpro_mock):


@pytest.mark.asyncio
async def test_endline_agree_terms_and_condition(tester: AppTester, rapidpro_mock):
@mock.patch("yal.rapidpro.get_group_membership_count")
async def test_endline_agree_terms_and_condition(
get_group_membership_count, tester: AppTester, rapidpro_mock
):
get_group_membership_count.return_value = 100
tester.user.metadata["baseline_survey_completed"] = True
tester.user.metadata["endline_survey_started"] = "Pending"
tester.user.metadata["terms_accepted"] = True
Expand Down
Loading

0 comments on commit 1628daa

Please sign in to comment.