Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion scripts/migrate_to_turn/fetch_rapidpro_contacts.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@
END_DATE = "2026-01-22 19:13:06"
LIMIT = 1000
INCLUDE_OPTED_OUT = False
# We want to import beta testing users as opted out and give them the chance to opt in.
IMPORT_AS_OPTED_OUT = True
# This is to identify invited users and schedule the invite message.
MIGRATION_KEY = "beta_testing_batch_1"

MSISDN_FILTER = (
os.environ.get("MSISDN_FILTER", "").split(",")
Expand All @@ -48,7 +52,7 @@
"education": {"turn_name": "education", "type": "custom"},
"opted_out": {
"turn_name": "opted_in",
"process": process_opted_in,
"process": lambda value: process_opted_in(value, IMPORT_AS_OPTED_OUT),
"type": "custom",
},
"prebirth_messaging": {
Expand Down Expand Up @@ -83,6 +87,7 @@
"pregnancy_loss_status": {"process": process_pregnancy_loss_status},
"is_new_user": {"process": lambda contact: "no"},
"babies": {"process": get_user_babies},
"migration_key": {"process": lambda contact: MIGRATION_KEY},
}


Expand Down
5 changes: 4 additions & 1 deletion scripts/migrate_to_turn/process_fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,10 @@ def process_datetime(value):
return value


def process_opted_in(value):
def process_opted_in(value, import_as_opted_out=False):
if import_as_opted_out:
return "false"

if not value:
return "true"

Expand Down
45 changes: 44 additions & 1 deletion scripts/migrate_to_turn/tests/test_fetch_rapidpro_contacts.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,46 @@ def get_contacts(self, before=None, after=None):


class FetchRapidproContactsTests(TestCase):
def test_get_field_data_uses_opted_out_when_import_override_is_false(self):
with patch.object(fetch_rapidpro_contacts, "IMPORT_AS_OPTED_OUT", False):
contact_opted_in = type(
"Contact",
(),
{
"fields": {"opted_out": "FALSE"},
"name": "Alice",
"language": "eng",
"urns": ["whatsapp:27820000000"],
"modified_on": datetime(2025, 1, 3, 12, 0, 0, tzinfo=pytz.utc),
},
)()
contact_opted_out = type(
"Contact",
(),
{
"fields": {"opted_out": "TRUE"},
"name": "Bob",
"language": "eng",
"urns": ["whatsapp:27820000001"],
"modified_on": datetime(2025, 1, 3, 12, 0, 0, tzinfo=pytz.utc),
},
)()

self.assertEqual(
fetch_rapidpro_contacts.get_field_data(contact_opted_in)["opted_in"],
"true",
)
self.assertEqual(
fetch_rapidpro_contacts.get_field_data(contact_opted_out)["opted_in"],
"false",
)
self.assertEqual(
fetch_rapidpro_contacts.get_field_data(contact_opted_in)[
"migration_key"
],
fetch_rapidpro_contacts.MIGRATION_KEY,
)

def test_fetch_rapidpro_contacts_writes_csv(self):
contact = type(
"Contact",
Expand Down Expand Up @@ -74,6 +114,7 @@ def test_fetch_rapidpro_contacts_writes_csv(self):
with (
patch.object(fetch_rapidpro_contacts, "START_DATE", start_date),
patch.object(fetch_rapidpro_contacts, "END_DATE", end_date),
patch.object(fetch_rapidpro_contacts, "IMPORT_AS_OPTED_OUT", True),
):
fetch_rapidpro_contacts.fetch_rapidpro_contacts(client)

Expand Down Expand Up @@ -101,6 +142,7 @@ def test_fetch_rapidpro_contacts_writes_csv(self):
"pregnancy_loss_status",
"is_new_user",
"babies",
"migration_key",
"urn",
]

Expand All @@ -117,7 +159,7 @@ def test_fetch_rapidpro_contacts_writes_csv(self):
"clinic_code": "123",
"referred_number": "+27123",
"education": "secondary",
"opted_in": "true",
"opted_in": "false",
"pregnancy_message_status": "true",
"baby_message_status": "true",
"minor_healthcare_consent": "true",
Expand All @@ -128,6 +170,7 @@ def test_fetch_rapidpro_contacts_writes_csv(self):
"pregnancy_loss_status": "",
"is_new_user": "no",
"babies": fetch_rapidpro_contacts.get_user_babies(contact),
"migration_key": fetch_rapidpro_contacts.MIGRATION_KEY,
"urn": "27820000000",
}

Expand Down
8 changes: 8 additions & 0 deletions scripts/migrate_to_turn/tests/test_process_fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,14 @@ def test_bool_values(self):
self.assertEqual(process_opted_in(True), "false")
self.assertEqual(process_opted_in(False), "true")

def test_import_as_opted_out_forces_false(self):
"""
Import override always sets opted_in to false
"""
for value in (None, "", "FALSE", "TRUE", False, True):
with self.subTest(value=value):
self.assertEqual(process_opted_in(value, True), "false")


class ProcessTruthyTests(TestCase):
def test_none_returns_false(self):
Expand Down