Esempio n. 1
0
def process_sms_registration(msg):
    """
    This method handles registration via sms.
    Returns True if a contact was registered, False if not.
    
    To have a case register itself, do the following:

        1) Select "Enable Case Registration Via SMS" in project settings, and fill in the
        associated Case Registration settings.

        2) Text in "join <domain>", where <domain> is the domain to join. If the sending
        number does not exist in the system, a case will be registered tied to that number.
        The "join" keyword can be any keyword in REGISTRATION_KEYWORDS. This is meant to
        support multiple translations.
    
    To have a mobile worker register itself, do the following:

        NOTE: This is not yet implemented and may change slightly.

        1) Select "Enable Mobile Worker Registration via SMS" in project settings.

        2) Text in "join <domain> worker", where <domain> is the domain to join. If the
        sending number does not exist in the system, a PendingCommCareUser object will be
        created, tied to that number.
        The "join" and "worker" keywords can be any keyword in REGISTRATION_KEYWORDS and
        REGISTRATION_MOBILE_WORKER_KEYWORDS, respectively. This is meant to support multiple 
        translations.

        3) A domain admin will have to approve the addition of the mobile worker before
        a CommCareUser can actually be created.
    """
    registration_processed = False
    text_words = msg.text.upper().split()
    keyword1 = text_words[0] if len(text_words) > 0 else ""
    keyword2 = text_words[1].lower() if len(text_words) > 1 else ""
    keyword3 = text_words[2] if len(text_words) > 2 else ""
    if keyword1 in REGISTRATION_KEYWORDS and keyword2 != "":
        domain = Domain.get_by_name(keyword2, strict=True)
        if domain is not None:
            if domain_has_privilege(domain, privileges.INBOUND_SMS):
                if keyword3 in REGISTRATION_MOBILE_WORKER_KEYWORDS and domain.sms_mobile_worker_registration_enabled:
                    #TODO: Register a PendingMobileWorker object that must be approved by a domain admin
                    pass
                elif domain.sms_case_registration_enabled:
                    register_sms_contact(
                        domain=domain.name,
                        case_type=domain.sms_case_registration_type,
                        case_name="unknown",
                        user_id=domain.sms_case_registration_user_id,
                        contact_phone_number=strip_plus(msg.phone_number),
                        contact_phone_number_is_verified="1",
                        owner_id=domain.sms_case_registration_owner_id,
                    )
                    registration_processed = True
            msg.domain = domain.name
            msg.save()

    return registration_processed
Esempio n. 2
0
def process_sms_registration(msg):
    """
    This method handles registration via sms.
    Returns True if a contact was registered, False if not.
    
    To have a case register itself, do the following:

        1) Select "Enable Case Registration Via SMS" in project settings, and fill in the
        associated Case Registration settings.

        2) Text in "join <domain>", where <domain> is the domain to join. If the sending
        number does not exist in the system, a case will be registered tied to that number.
        The "join" keyword can be any keyword in REGISTRATION_KEYWORDS. This is meant to
        support multiple translations.
    
    To have a mobile worker register itself, do the following:

        NOTE: This is not yet implemented and may change slightly.

        1) Select "Enable Mobile Worker Registration via SMS" in project settings.

        2) Text in "join <domain> worker", where <domain> is the domain to join. If the
        sending number does not exist in the system, a PendingCommCareUser object will be
        created, tied to that number.
        The "join" and "worker" keywords can be any keyword in REGISTRATION_KEYWORDS and
        REGISTRATION_MOBILE_WORKER_KEYWORDS, respectively. This is meant to support multiple 
        translations.

        3) A domain admin will have to approve the addition of the mobile worker before
        a CommCareUser can actually be created.
    """
    registration_processed = False
    text_words = msg.text.upper().split()
    keyword1 = text_words[0] if len(text_words) > 0 else ""
    keyword2 = text_words[1].lower() if len(text_words) > 1 else ""
    keyword3 = text_words[2] if len(text_words) > 2 else ""
    if keyword1 in REGISTRATION_KEYWORDS and keyword2 != "":
        domain = Domain.get_by_name(keyword2, strict=True)
        if domain is not None:
            if keyword3 in REGISTRATION_MOBILE_WORKER_KEYWORDS and domain.sms_mobile_worker_registration_enabled:
                #TODO: Register a PendingMobileWorker object that must be approved by a domain admin
                pass
            elif domain.sms_case_registration_enabled:
                register_sms_contact(
                    domain=domain.name,
                    case_type=domain.sms_case_registration_type,
                    case_name="unknown",
                    user_id=domain.sms_case_registration_user_id,
                    contact_phone_number=strip_plus(msg.phone_number),
                    contact_phone_number_is_verified="1",
                    owner_id=domain.sms_case_registration_owner_id,
                )
                msg.domain = domain.name
                msg.save()
                registration_processed = True

    return registration_processed
Esempio n. 3
0
def process_sms_registration(msg):
    """
    This method handles registration via sms.
    Returns True if a contact was registered, False if not.

    To have a case register itself, do the following:

        1) Select "Enable Case Registration Via SMS" in project settings, and fill in the
        associated Case Registration settings.

        2) Text in "join <domain>", where <domain> is the domain to join. If the sending
        number does not exist in the system, a case will be registered tied to that number.
        The "join" keyword can be any keyword in REGISTRATION_KEYWORDS. This is meant to
        support multiple translations.

    To have a mobile worker register itself, do the following:

        1) Select "Enable Mobile Worker Registration via SMS" in project settings.

        2) Text in "join <domain> worker <username>", where <domain> is the domain to join and <username> is the
        requested username.  If the username doesn't exist it will be created, otherwise the registration will error.
        If the username argument is not specified, the username will be the mobile number

        The "join" and "worker" keywords can be any keyword in REGISTRATION_KEYWORDS and
        REGISTRATION_MOBILE_WORKER_KEYWORDS, respectively. This is meant to support multiple
        translations.
    """
    registration_processed = False
    text_words = msg.text.upper().split()
    keyword1 = text_words[0] if len(text_words) > 0 else ""
    keyword2 = text_words[1].lower() if len(text_words) > 1 else ""
    keyword3 = text_words[2] if len(text_words) > 2 else ""
    keyword4 = text_words[3] if len(text_words) > 3 else ""
    cleaned_phone_number = strip_plus(msg.phone_number)
    if is_registration_text(msg.text) and keyword2 != "":
        domain_name = keyword2

        if any_migrations_in_progress(domain_name):
            raise DelayProcessing()

        domain_obj = Domain.get_by_name(domain_name, strict=True)

        if domain_obj is not None:
            if domain_has_privilege(domain_obj, privileges.INBOUND_SMS):
                if (keyword3 in REGISTRATION_MOBILE_WORKER_KEYWORDS
                        and domain_obj.sms_mobile_worker_registration_enabled):
                    if keyword4 != '':
                        username = keyword4
                    else:
                        username = cleaned_phone_number
                    try:
                        user_data = {}

                        invitation = SelfRegistrationInvitation.by_phone(
                            msg.phone_number)
                        if invitation:
                            invitation.completed()
                            user_data = invitation.custom_user_data

                        username = process_username(username, domain_obj)
                        password = random_password()
                        new_user = CommCareUser.create(domain_obj.name,
                                                       username,
                                                       password,
                                                       user_data=user_data)
                        new_user.add_phone_number(cleaned_phone_number)
                        new_user.save()

                        entry = new_user.get_or_create_phone_entry(
                            cleaned_phone_number)
                        entry.set_two_way()
                        entry.set_verified()
                        entry.save()
                        registration_processed = True

                        if domain_obj.enable_registration_welcome_sms_for_mobile_worker:
                            send_sms(
                                domain_obj.name, None, cleaned_phone_number,
                                get_message(
                                    MSG_REGISTRATION_WELCOME_MOBILE_WORKER,
                                    domain=domain_obj.name))
                    except ValidationError as e:
                        send_sms(domain_obj.name, None, cleaned_phone_number,
                                 e.messages[0])

                elif domain_obj.sms_case_registration_enabled:
                    register_sms_contact(
                        domain=domain_obj.name,
                        case_type=domain_obj.sms_case_registration_type,
                        case_name="unknown",
                        user_id=domain_obj.sms_case_registration_user_id,
                        contact_phone_number=cleaned_phone_number,
                        contact_phone_number_is_verified="1",
                        owner_id=domain_obj.sms_case_registration_owner_id,
                    )
                    registration_processed = True
                    if domain_obj.enable_registration_welcome_sms_for_case:
                        send_sms(
                            domain_obj.name, None, cleaned_phone_number,
                            get_message(MSG_REGISTRATION_WELCOME_CASE,
                                        domain=domain_obj.name))
            msg.domain = domain_obj.name
            msg.save()

    return registration_processed
Esempio n. 4
0
    def testOutbound(self):
        # Send an outbound call using self.reminder1 to self.case
        # and answer it
        CaseReminderHandler.now = datetime(2014, 6, 23, 10, 0)
        self.case = CommCareCase.get(
            register_sms_contact(
                self.domain,
                'participant',
                'case1',
                self.user1._id,
                '91000',
                owner_id=self.groups[0]._id,
            ))
        CaseReminderHandler.now = datetime(2014, 6, 23, 12, 0)
        CaseReminderHandler.fire_reminders()
        reminder = self.reminder1.get_reminder(self.case)
        self.assertEquals(reminder.next_fire, datetime(2014, 6, 23, 12, 30))

        call = self.get_last_outbound_call(self.case)
        self.assertTrue(call.use_precached_first_response)

        kookoo_session_id = call.gateway_session_id[7:]
        resp = self.kookoo_in({
            "cid": "0000",
            "sid": kookoo_session_id,
            "event": "NewCall",
        })
        self.assertEqual(
            resp, '<response sid="%s"><collectdtmf l="1" o="3000">'
            '<playtext>How do you feel today? Press 1 for good, 2 for bad.'
            '</playtext></collectdtmf></response>' % kookoo_session_id)

        resp = self.kookoo_in({
            "cid": "0000",
            "sid": kookoo_session_id,
            "event": "GotDTMF",
            "data": "1",
        })
        self.assertEqual(
            resp, '<response sid="%s"><collectdtmf l="1" o="3000">'
            '<playtext>Did you remember to take your meds today? Press 1 for yes, 2 for no.'
            '</playtext></collectdtmf></response>' % kookoo_session_id)

        resp = self.kookoo_in({
            "cid": "0000",
            "sid": kookoo_session_id,
            "event": "GotDTMF",
            "data": "2",
        })
        self.assertEqual(
            resp,
            '<response sid="%s"><hangup/></response>' % kookoo_session_id)

        self.kookoo_finished({
            "sid": kookoo_session_id,
            "status": "answered",
            "duration": "20",
        })

        call = CallLog.get(call._id)
        self.assertTrue(call.answered)
        self.assertEqual(call.duration, 20)

        form = self.get_last_form_submission()
        self.assertFormQuestionEquals(form, "how_feel", "1")
        self.assertFormQuestionEquals(form, "take_meds", "2")
        case = CommCareCase.get(self.case._id)
        self.assertCasePropertyEquals(case, "how_feel", "1")
        self.assertCasePropertyEquals(case, "take_meds", "2")

        CaseReminderHandler.now = datetime(2014, 6, 23, 12, 30)
        CaseReminderHandler.fire_reminders()

        reminder = self.reminder1.get_reminder(self.case)
        self.assertEquals(reminder.next_fire, datetime(2014, 6, 23, 13, 0))

        last_call = self.get_last_outbound_call(self.case)
        self.assertEqual(call._id, last_call._id)

        # Move on to the second event which now uses an all-label form and
        # should not precache the first ivr response
        CaseReminderHandler.now = datetime(2014, 6, 23, 13, 0)
        CaseReminderHandler.fire_reminders()

        reminder = self.reminder1.get_reminder(self.case)
        self.assertEquals(reminder.next_fire, datetime(2014, 6, 23, 13, 30))

        call = self.get_last_outbound_call(self.case)
        self.assertFalse(call.use_precached_first_response)

        kookoo_session_id = call.gateway_session_id[7:]
        resp = self.kookoo_in({
            "cid": "0000",
            "sid": kookoo_session_id,
            "event": "NewCall",
        })
        self.assertEqual(
            resp, '<response sid="%s">'
            '<playtext>This is just a reminder to take your meds.'
            '</playtext><hangup/></response>' % kookoo_session_id)

        self.kookoo_finished({
            "sid": kookoo_session_id,
            "status": "answered",
            "duration": "5",
        })

        call = CallLog.get(call._id)
        self.assertTrue(call.answered)
        self.assertEqual(call.duration, 5)

        form = self.get_last_form_submission()
        self.assertFormQuestionEquals(form, "label", "ok")

        CaseReminderHandler.now = datetime(2014, 6, 23, 13, 30)
        CaseReminderHandler.fire_reminders()

        reminder = self.reminder1.get_reminder(self.case)
        self.assertEquals(reminder.next_fire, datetime(2014, 6, 24, 12, 0))

        last_call = self.get_last_outbound_call(self.case)
        self.assertEqual(call._id, last_call._id)

        # Now test sending outbound calls to a group of users (the owners
        # of the case)

        # Allow sending to unverified numbers
        self.domain_obj = Domain.get(self.domain_obj._id)
        self.domain_obj.send_to_duplicated_case_numbers = True
        self.domain_obj.save()

        CaseReminderHandler.now = datetime(2014, 6, 24, 10, 0)
        self.case = CommCareCase.get(
            register_sms_contact(
                self.domain,
                'participant',
                'case2',
                self.user1._id,
                '91003',
                owner_id=self.groups[0]._id,
            ))
        reminder = self.reminder2.get_reminder(self.case)
        self.assertEquals(reminder.next_fire, datetime(2014, 6, 24, 12, 0))

        CaseReminderHandler.now = datetime(2014, 6, 24, 12, 0)
        CaseReminderHandler.fire_reminders()
        reminder = self.reminder2.get_reminder(self.case)
        self.assertEquals(reminder.next_fire, datetime(2014, 6, 24, 12, 30))

        call1 = self.get_last_outbound_call(self.user1)
        self.assertTrue(call1.use_precached_first_response)
        self.assertFalse(call1.answered)

        call2 = self.get_last_outbound_call(self.user2)
        self.assertTrue(call2.use_precached_first_response)
        self.assertFalse(call2.answered)

        old_call1 = call1
        old_call2 = call2

        CaseReminderHandler.now = datetime(2014, 6, 24, 12, 30)
        CaseReminderHandler.fire_reminders()
        reminder = self.reminder2.get_reminder(self.case)
        self.assertEquals(reminder.next_fire, datetime(2014, 6, 24, 13, 0))

        call1 = self.get_last_outbound_call(self.user1)
        self.assertTrue(call1.use_precached_first_response)
        self.assertNotEqual(call1._id, old_call1._id)

        call2 = self.get_last_outbound_call(self.user2)
        self.assertTrue(call2.use_precached_first_response)
        self.assertFalse(call2.answered)
        self.assertNotEqual(call2._id, old_call2._id)

        kookoo_session_id = call1.gateway_session_id[7:]
        resp = self.kookoo_in({
            "cid": "0001",
            "sid": kookoo_session_id,
            "event": "NewCall",
        })
        self.assertEqual(
            resp, '<response sid="%s"><collectdtmf l="1" o="3000">'
            '<playtext>How do you feel today? Press 1 for good, 2 for bad.'
            '</playtext></collectdtmf></response>' % kookoo_session_id)

        resp = self.kookoo_in({
            "cid": "0001",
            "sid": kookoo_session_id,
            "event": "GotDTMF",
            "data": "2",
        })
        self.assertEqual(
            resp, '<response sid="%s"><collectdtmf l="1" o="3000">'
            '<playtext>Did you remember to take your meds today? Press 1 for yes, 2 for no.'
            '</playtext></collectdtmf></response>' % kookoo_session_id)

        resp = self.kookoo_in({
            "cid": "0001",
            "sid": kookoo_session_id,
            "event": "GotDTMF",
            "data": "1",
        })
        self.assertEqual(
            resp,
            '<response sid="%s"><hangup/></response>' % kookoo_session_id)

        self.kookoo_finished({
            "sid": kookoo_session_id,
            "status": "answered",
            "duration": "20",
        })
        call1 = CallLog.get(call1._id)
        self.assertTrue(call1.answered)
        self.assertEqual(call1.duration, 20)

        form = self.get_last_form_submission()
        self.assertFormQuestionEquals(form, "how_feel", "2")
        self.assertFormQuestionEquals(form, "take_meds", "1")
        self.assertEqual(form.form["meta"]["userID"], self.user1._id)
        case = CommCareCase.get(self.case._id)
        self.assertCasePropertyEquals(case, "how_feel", "2")
        self.assertCasePropertyEquals(case, "take_meds", "1")
        self.assertEqual(case.user_id, self.user1._id)

        old_call1 = call1
        old_call2 = call2

        CaseReminderHandler.now = datetime(2014, 6, 24, 13, 0)
        CaseReminderHandler.fire_reminders()
        reminder = self.reminder2.get_reminder(self.case)
        self.assertEquals(reminder.next_fire, datetime(2014, 6, 25, 12, 0))

        call1 = self.get_last_outbound_call(self.user1)
        # No new call for user1 since it was already answered
        self.assertEqual(call1._id, old_call1._id)

        call2 = self.get_last_outbound_call(self.user2)
        self.assertTrue(call2.use_precached_first_response)
        self.assertNotEqual(call2._id, old_call2._id)

        kookoo_session_id = call2.gateway_session_id[7:]
        resp = self.kookoo_in({
            "cid": "0002",
            "sid": kookoo_session_id,
            "event": "NewCall",
        })
        self.assertEqual(
            resp, '<response sid="%s"><collectdtmf l="1" o="3000">'
            '<playtext>How do you feel today? Press 1 for good, 2 for bad.'
            '</playtext></collectdtmf></response>' % kookoo_session_id)

        resp = self.kookoo_in({
            "cid": "0002",
            "sid": kookoo_session_id,
            "event": "GotDTMF",
            "data": "1",
        })
        self.assertEqual(
            resp, '<response sid="%s"><collectdtmf l="1" o="3000">'
            '<playtext>Did you remember to take your meds today? Press 1 for yes, 2 for no.'
            '</playtext></collectdtmf></response>' % kookoo_session_id)

        resp = self.kookoo_in({
            "cid": "0002",
            "sid": kookoo_session_id,
            "event": "GotDTMF",
            "data": "2",
        })
        self.assertEqual(
            resp,
            '<response sid="%s"><hangup/></response>' % kookoo_session_id)

        self.kookoo_finished({
            "sid": kookoo_session_id,
            "status": "answered",
            "duration": "20",
        })
        call2 = CallLog.get(call2._id)
        self.assertTrue(call2.answered)
        self.assertEqual(call2.duration, 20)

        form = self.get_last_form_submission()
        self.assertFormQuestionEquals(form, "how_feel", "1")
        self.assertFormQuestionEquals(form, "take_meds", "2")
        self.assertEqual(form.form["meta"]["userID"], self.user2._id)
        case = CommCareCase.get(self.case._id)
        self.assertCasePropertyEquals(case, "how_feel", "1")
        self.assertCasePropertyEquals(case, "take_meds", "2")
        self.assertEqual(case.user_id, self.user2._id)
Esempio n. 5
0
def add_sample(request, domain, sample_id=None):
    sample = None
    if sample_id is not None:
        sample = SurveySample.get(sample_id)
    
    if request.method == "POST":
        form = SurveySampleForm(request.POST, request.FILES)
        if form.is_valid():
            name            = form.cleaned_data.get("name")
            sample_contacts = form.cleaned_data.get("sample_contacts")
            time_zone       = form.cleaned_data.get("time_zone")
            use_contact_upload_file = form.cleaned_data.get("use_contact_upload_file")
            contact_upload_file = form.cleaned_data.get("contact_upload_file")
            
            if sample is None:
                sample = SurveySample (
                    domain = domain,
                    name = name,
                    time_zone = time_zone.zone
                )
            else:
                sample.name = name
                sample.time_zone = time_zone.zone
            
            errors = []
            
            phone_numbers = []
            if use_contact_upload_file == "Y":
                for contact in contact_upload_file:
                    phone_numbers.append(contact["phone_number"])
            else:
                for contact in sample_contacts:
                    phone_numbers.append(contact["phone_number"])
            
            existing_number_entries = VerifiedNumber.view('sms/verified_number_by_number',
                                            keys=phone_numbers,
                                            include_docs=True
                                       ).all()
            
            for entry in existing_number_entries:
                if entry.domain != domain or entry.owner_doc_type != "CommCareCase":
                    errors.append("Cannot use phone number %s" % entry.phone_number)
            
            if len(errors) > 0:
                if use_contact_upload_file == "Y":
                    form._errors["contact_upload_file"] = form.error_class(errors)
                else:
                    form._errors["sample_contacts"] = form.error_class(errors)
            else:
                existing_numbers = [v.phone_number for v in existing_number_entries]
                nonexisting_numbers = list(set(phone_numbers).difference(existing_numbers))
                
                id_range = DomainCounter.increment(domain, "survey_contact_id", len(nonexisting_numbers))
                ids = iter(range(id_range[0], id_range[1] + 1))
                for phone_number in nonexisting_numbers:
                    register_sms_contact(domain, "participant", str(ids.next()), request.couch_user.get_id, phone_number, contact_phone_number_is_verified="1", contact_backend_id="MOBILE_BACKEND_TROPO_US", language_code="en", time_zone=time_zone.zone)
                
                newly_registered_entries = VerifiedNumber.view('sms/verified_number_by_number',
                                                keys=nonexisting_numbers,
                                                include_docs=True
                                           ).all()
                
                sample.contacts = [v.owner_id for v in existing_number_entries] + [v.owner_id for v in newly_registered_entries]
                
                sample.save()
                
                # Update delegation tasks for surveys using this sample
                surveys = Survey.view("reminders/sample_to_survey", key=[domain, sample._id, "CATI"], include_docs=True).all()
                for survey in surveys:
                    survey.update_delegation_tasks(request.couch_user.get_id)
                    survey.save()
                
                return HttpResponseRedirect(reverse("sample_list", args=[domain]))
    else:
        initial = {}
        if sample is not None:
            initial["name"] = sample.name
            initial["time_zone"] = sample.time_zone
            contact_info = []
            for case_id in sample.contacts:
                case = CommCareCase.get(case_id)
                contact_info.append({"id":case.name, "phone_number":case.contact_phone_number, "case_id" : case_id})
            initial["sample_contacts"] = contact_info
        form = SurveySampleForm(initial=initial)
    
    context = {
        "domain" : domain,
        "form" : form,
        "sample_id" : sample_id
    }
    return render(request, "reminders/partial/add_sample.html", context)
Esempio n. 6
0
def process_sms_registration(msg):
    """
    This method handles registration via sms.
    Returns True if a contact was registered, False if not.

    To have a case register itself, do the following:

        1) Select "Enable Case Registration Via SMS" in project settings, and fill in the
        associated Case Registration settings.

        2) Text in "join <domain>", where <domain> is the domain to join. If the sending
        number does not exist in the system, a case will be registered tied to that number.
        The "join" keyword can be any keyword in REGISTRATION_KEYWORDS. This is meant to
        support multiple translations.

    To have a mobile worker register itself, do the following:

        1) Select "Enable Mobile Worker Registration via SMS" in project settings.

        2) Text in "join <domain> worker <username>", where <domain> is the domain to join and <username> is the
        requested username.  If the username doesn't exist it will be created, otherwise the registration will error.
        If the username argument is not specified, the username will be the mobile number

        The "join" and "worker" keywords can be any keyword in REGISTRATION_KEYWORDS and
        REGISTRATION_MOBILE_WORKER_KEYWORDS, respectively. This is meant to support multiple
        translations.
    """
    registration_processed = False
    text_words = msg.text.upper().split()
    keyword1 = text_words[0] if len(text_words) > 0 else ""
    keyword2 = text_words[1].lower() if len(text_words) > 1 else ""
    keyword3 = text_words[2] if len(text_words) > 2 else ""
    keyword4 = text_words[3] if len(text_words) > 3 else ""
    cleaned_phone_number = strip_plus(msg.phone_number)
    if keyword1 in REGISTRATION_KEYWORDS and keyword2 != "":
        domain = Domain.get_by_name(keyword2, strict=True)
        if domain is not None:
            if domain_has_privilege(domain, privileges.INBOUND_SMS):
                if keyword3 in REGISTRATION_MOBILE_WORKER_KEYWORDS and domain.sms_mobile_worker_registration_enabled:
                    if keyword4 != '':
                        username = keyword4
                    else:
                        username = cleaned_phone_number
                    try:
                        username = process_username(username, domain)
                        password = random_password()
                        new_user = CommCareUser.create(domain.name, username,
                                                       password)
                        new_user.add_phone_number(cleaned_phone_number)
                        new_user.save_verified_number(domain.name,
                                                      cleaned_phone_number,
                                                      True, None)
                        new_user.save()
                        registration_processed = True
                    except ValidationError as e:
                        send_sms(domain.name, None, cleaned_phone_number,
                                 e.messages[0])

                elif domain.sms_case_registration_enabled:
                    register_sms_contact(
                        domain=domain.name,
                        case_type=domain.sms_case_registration_type,
                        case_name="unknown",
                        user_id=domain.sms_case_registration_user_id,
                        contact_phone_number=strip_plus(msg.phone_number),
                        contact_phone_number_is_verified="1",
                        owner_id=domain.sms_case_registration_owner_id,
                    )
                    registration_processed = True
            msg.domain = domain.name
            msg.save()

    return registration_processed
Esempio n. 7
0
def process_sms_registration(msg):
    """
    This method handles registration via sms.
    Returns True if a contact was registered, False if not.

    To have a case register itself, do the following:

        1) Select "Enable Case Registration Via SMS" in project settings, and fill in the
        associated Case Registration settings.

        2) Text in "join <domain>", where <domain> is the domain to join. If the sending
        number does not exist in the system, a case will be registered tied to that number.
        The "join" keyword can be any keyword in REGISTRATION_KEYWORDS. This is meant to
        support multiple translations.

    To have a mobile worker register itself, do the following:

        1) Select "Enable Mobile Worker Registration via SMS" in project settings.

        2) Text in "join <domain> worker <username>", where <domain> is the domain to join and <username> is the
        requested username.  If the username doesn't exist it will be created, otherwise the registration will error.
        If the username argument is not specified, the username will be the mobile number

        The "join" and "worker" keywords can be any keyword in REGISTRATION_KEYWORDS and
        REGISTRATION_MOBILE_WORKER_KEYWORDS, respectively. This is meant to support multiple
        translations.
    """
    registration_processed = False
    text_words = msg.text.upper().split()
    keyword1 = text_words[0] if len(text_words) > 0 else ""
    keyword2 = text_words[1].lower() if len(text_words) > 1 else ""
    keyword3 = text_words[2] if len(text_words) > 2 else ""
    keyword4 = text_words[3] if len(text_words) > 3 else ""
    cleaned_phone_number = strip_plus(msg.phone_number)
    if is_registration_text(msg.text) and keyword2 != "":
        domain = Domain.get_by_name(keyword2, strict=True)
        if domain is not None:
            if domain_has_privilege(domain, privileges.INBOUND_SMS):
                if keyword3 in REGISTRATION_MOBILE_WORKER_KEYWORDS and domain.sms_mobile_worker_registration_enabled:
                    if keyword4 != '':
                        username = keyword4
                    else:
                        username = cleaned_phone_number
                    try:
                        user_data = {}

                        invitation = SelfRegistrationInvitation.by_phone(msg.phone_number)
                        if invitation:
                            invitation.completed()
                            user_data = invitation.custom_user_data

                        username = process_username(username, domain)
                        password = random_password()
                        new_user = CommCareUser.create(domain.name, username, password, user_data=user_data)
                        new_user.add_phone_number(cleaned_phone_number)
                        new_user.save_verified_number(domain.name, cleaned_phone_number, True, None)
                        new_user.save()
                        registration_processed = True

                        if domain.enable_registration_welcome_sms_for_mobile_worker:
                            send_sms(domain.name, None, cleaned_phone_number,
                                     get_message(MSG_REGISTRATION_WELCOME_MOBILE_WORKER, domain=domain.name))
                    except ValidationError as e:
                        send_sms(domain.name, None, cleaned_phone_number, e.messages[0])

                elif domain.sms_case_registration_enabled:
                    register_sms_contact(
                        domain=domain.name,
                        case_type=domain.sms_case_registration_type,
                        case_name="unknown",
                        user_id=domain.sms_case_registration_user_id,
                        contact_phone_number=cleaned_phone_number,
                        contact_phone_number_is_verified="1",
                        owner_id=domain.sms_case_registration_owner_id,
                    )
                    registration_processed = True
                    if domain.enable_registration_welcome_sms_for_case:
                        send_sms(domain.name, None, cleaned_phone_number,
                                 get_message(MSG_REGISTRATION_WELCOME_CASE, domain=domain.name))
            msg.domain = domain.name
            msg.save()

    return registration_processed
Esempio n. 8
0
    def testOutbound(self):
        # Send an outbound call using self.reminder1 to self.case
        # and answer it
        CaseReminderHandler.now = datetime(2014, 6, 23, 10, 0)
        self.case = CommCareCase.get(register_sms_contact(
            self.domain,
            'participant',
            'case1',
            self.user1._id,
            '91000',
            owner_id=self.groups[0]._id,
            contact_ivr_backend_id='MOBILE_BACKEND_KOOKOO'
        ))
        CaseReminderHandler.now = datetime(2014, 6, 23, 12, 0)
        CaseReminderHandler.fire_reminders()
        reminder = self.reminder1.get_reminder(self.case)
        self.assertEquals(reminder.next_fire, datetime(2014, 6, 23, 12, 30))

        call = self.get_last_outbound_call(self.case)
        self.assertTrue(call.use_precached_first_response)

        kookoo_session_id = call.gateway_session_id[7:]
        resp = self.kookoo_in({
            "cid": "0000",
            "sid": kookoo_session_id,
            "event": "NewCall",
        })
        self.assertEqual(resp, '<response sid="%s"><collectdtmf l="1" o="3000">'
            '<playtext>How do you feel today? Press 1 for good, 2 for bad.'
            '</playtext></collectdtmf></response>' % kookoo_session_id)

        resp = self.kookoo_in({
            "cid": "0000",
            "sid": kookoo_session_id,
            "event": "GotDTMF",
            "data": "1",
        })
        self.assertEqual(resp, '<response sid="%s"><collectdtmf l="1" o="3000">'
            '<playtext>Did you remember to take your meds today? Press 1 for yes, 2 for no.'
            '</playtext></collectdtmf></response>' % kookoo_session_id)

        resp = self.kookoo_in({
            "cid": "0000",
            "sid": kookoo_session_id,
            "event": "GotDTMF",
            "data": "2",
        })
        self.assertEqual(resp, '<response sid="%s"><hangup/></response>' % kookoo_session_id)

        self.kookoo_finished({
            "sid": kookoo_session_id,
            "status": "answered",
            "duration": "20",
        })

        call = CallLog.get(call._id)
        self.assertTrue(call.answered)
        self.assertEqual(call.duration, 20)

        form = self.get_last_form_submission()
        self.assertFormQuestionEquals(form, "how_feel", "1")
        self.assertFormQuestionEquals(form, "take_meds", "2")
        case = CommCareCase.get(self.case._id)
        self.assertCasePropertyEquals(case, "how_feel", "1")
        self.assertCasePropertyEquals(case, "take_meds", "2")

        CaseReminderHandler.now = datetime(2014, 6, 23, 12, 30)
        CaseReminderHandler.fire_reminders()

        reminder = self.reminder1.get_reminder(self.case)
        self.assertEquals(reminder.next_fire, datetime(2014, 6, 23, 13, 0))

        last_call = self.get_last_outbound_call(self.case)
        self.assertEqual(call._id, last_call._id)

        # Move on to the second event which now uses an all-label form and
        # should not precache the first ivr response
        CaseReminderHandler.now = datetime(2014, 6, 23, 13, 0)
        CaseReminderHandler.fire_reminders()

        reminder = self.reminder1.get_reminder(self.case)
        self.assertEquals(reminder.next_fire, datetime(2014, 6, 23, 13, 30))

        call = self.get_last_outbound_call(self.case)
        self.assertFalse(call.use_precached_first_response)

        kookoo_session_id = call.gateway_session_id[7:]
        resp = self.kookoo_in({
            "cid": "0000",
            "sid": kookoo_session_id,
            "event": "NewCall",
        })
        self.assertEqual(resp, '<response sid="%s">'
            '<playtext>This is just a reminder to take your meds.'
            '</playtext><hangup/></response>' % kookoo_session_id)

        self.kookoo_finished({
            "sid": kookoo_session_id,
            "status": "answered",
            "duration": "5",
        })

        call = CallLog.get(call._id)
        self.assertTrue(call.answered)
        self.assertEqual(call.duration, 5)

        form = self.get_last_form_submission()
        self.assertFormQuestionEquals(form, "label", "ok")

        CaseReminderHandler.now = datetime(2014, 6, 23, 13, 30)
        CaseReminderHandler.fire_reminders()

        reminder = self.reminder1.get_reminder(self.case)
        self.assertEquals(reminder.next_fire, datetime(2014, 6, 24, 12, 0))

        last_call = self.get_last_outbound_call(self.case)
        self.assertEqual(call._id, last_call._id)

        # Now test sending outbound calls to a group of users (the owners
        # of the case)

        # Allow sending to unverified numbers
        self.domain_obj = Domain.get(self.domain_obj._id)
        self.domain_obj.send_to_duplicated_case_numbers = True
        self.domain_obj.save()

        CaseReminderHandler.now = datetime(2014, 6, 24, 10, 0)
        self.case = CommCareCase.get(register_sms_contact(
            self.domain,
            'participant',
            'case2',
            self.user1._id,
            '91003',
            owner_id=self.groups[0]._id,
        ))
        reminder = self.reminder2.get_reminder(self.case)
        self.assertEquals(reminder.next_fire, datetime(2014, 6, 24, 12, 0))

        CaseReminderHandler.now = datetime(2014, 6, 24, 12, 0)
        CaseReminderHandler.fire_reminders()
        reminder = self.reminder2.get_reminder(self.case)
        self.assertEquals(reminder.next_fire, datetime(2014, 6, 24, 12, 30))

        call1 = self.get_last_outbound_call(self.user1)
        self.assertTrue(call1.use_precached_first_response)
        self.assertFalse(call1.answered)

        call2 = self.get_last_outbound_call(self.user2)
        self.assertTrue(call2.use_precached_first_response)
        self.assertFalse(call2.answered)

        old_call1 = call1
        old_call2 = call2

        CaseReminderHandler.now = datetime(2014, 6, 24, 12, 30)
        CaseReminderHandler.fire_reminders()
        reminder = self.reminder2.get_reminder(self.case)
        self.assertEquals(reminder.next_fire, datetime(2014, 6, 24, 13, 0))

        call1 = self.get_last_outbound_call(self.user1)
        self.assertTrue(call1.use_precached_first_response)
        self.assertNotEqual(call1._id, old_call1._id)

        call2 = self.get_last_outbound_call(self.user2)
        self.assertTrue(call2.use_precached_first_response)
        self.assertFalse(call2.answered)
        self.assertNotEqual(call2._id, old_call2._id)

        kookoo_session_id = call1.gateway_session_id[7:]
        resp = self.kookoo_in({
            "cid": "0001",
            "sid": kookoo_session_id,
            "event": "NewCall",
        })
        self.assertEqual(resp, '<response sid="%s"><collectdtmf l="1" o="3000">'
            '<playtext>How do you feel today? Press 1 for good, 2 for bad.'
            '</playtext></collectdtmf></response>' % kookoo_session_id)

        resp = self.kookoo_in({
            "cid": "0001",
            "sid": kookoo_session_id,
            "event": "GotDTMF",
            "data": "2",
        })
        self.assertEqual(resp, '<response sid="%s"><collectdtmf l="1" o="3000">'
            '<playtext>Did you remember to take your meds today? Press 1 for yes, 2 for no.'
            '</playtext></collectdtmf></response>' % kookoo_session_id)

        resp = self.kookoo_in({
            "cid": "0001",
            "sid": kookoo_session_id,
            "event": "GotDTMF",
            "data": "1",
        })
        self.assertEqual(resp, '<response sid="%s"><hangup/></response>' % kookoo_session_id)

        self.kookoo_finished({
            "sid": kookoo_session_id,
            "status": "answered",
            "duration": "20",
        })
        call1 = CallLog.get(call1._id)
        self.assertTrue(call1.answered)
        self.assertEqual(call1.duration, 20)

        form = self.get_last_form_submission()
        self.assertFormQuestionEquals(form, "how_feel", "2")
        self.assertFormQuestionEquals(form, "take_meds", "1")
        self.assertEqual(form.form["meta"]["userID"], self.user1._id)
        case = CommCareCase.get(self.case._id)
        self.assertCasePropertyEquals(case, "how_feel", "2")
        self.assertCasePropertyEquals(case, "take_meds", "1")
        self.assertEqual(case.user_id, self.user1._id)

        old_call1 = call1
        old_call2 = call2

        CaseReminderHandler.now = datetime(2014, 6, 24, 13, 0)
        CaseReminderHandler.fire_reminders()
        reminder = self.reminder2.get_reminder(self.case)
        self.assertEquals(reminder.next_fire, datetime(2014, 6, 25, 12, 0))

        call1 = self.get_last_outbound_call(self.user1)
        # No new call for user1 since it was already answered
        self.assertEqual(call1._id, old_call1._id)

        call2 = self.get_last_outbound_call(self.user2)
        self.assertTrue(call2.use_precached_first_response)
        self.assertNotEqual(call2._id, old_call2._id)

        kookoo_session_id = call2.gateway_session_id[7:]
        resp = self.kookoo_in({
            "cid": "0002",
            "sid": kookoo_session_id,
            "event": "NewCall",
        })
        self.assertEqual(resp, '<response sid="%s"><collectdtmf l="1" o="3000">'
            '<playtext>How do you feel today? Press 1 for good, 2 for bad.'
            '</playtext></collectdtmf></response>' % kookoo_session_id)

        resp = self.kookoo_in({
            "cid": "0002",
            "sid": kookoo_session_id,
            "event": "GotDTMF",
            "data": "1",
        })
        self.assertEqual(resp, '<response sid="%s"><collectdtmf l="1" o="3000">'
            '<playtext>Did you remember to take your meds today? Press 1 for yes, 2 for no.'
            '</playtext></collectdtmf></response>' % kookoo_session_id)

        resp = self.kookoo_in({
            "cid": "0002",
            "sid": kookoo_session_id,
            "event": "GotDTMF",
            "data": "2",
        })
        self.assertEqual(resp, '<response sid="%s"><hangup/></response>' % kookoo_session_id)

        self.kookoo_finished({
            "sid": kookoo_session_id,
            "status": "answered",
            "duration": "20",
        })
        call2 = CallLog.get(call2._id)
        self.assertTrue(call2.answered)
        self.assertEqual(call2.duration, 20)

        form = self.get_last_form_submission()
        self.assertFormQuestionEquals(form, "how_feel", "1")
        self.assertFormQuestionEquals(form, "take_meds", "2")
        self.assertEqual(form.form["meta"]["userID"], self.user2._id)
        case = CommCareCase.get(self.case._id)
        self.assertCasePropertyEquals(case, "how_feel", "1")
        self.assertCasePropertyEquals(case, "take_meds", "2")
        self.assertEqual(case.user_id, self.user2._id)
Esempio n. 9
0
def add_sample(request, domain, sample_id=None):
    sample = None
    if sample_id is not None:
        sample = SurveySample.get(sample_id)

    if request.method == "POST":
        form = SurveySampleForm(request.POST, request.FILES)
        if form.is_valid():
            name = form.cleaned_data.get("name")
            sample_contacts = form.cleaned_data.get("sample_contacts")
            time_zone = form.cleaned_data.get("time_zone")
            use_contact_upload_file = form.cleaned_data.get(
                "use_contact_upload_file")
            contact_upload_file = form.cleaned_data.get("contact_upload_file")

            if sample is None:
                sample = SurveySample(domain=domain,
                                      name=name,
                                      time_zone=time_zone.zone)
            else:
                sample.name = name
                sample.time_zone = time_zone.zone

            errors = []

            phone_numbers = []
            if use_contact_upload_file == "Y":
                for contact in contact_upload_file:
                    phone_numbers.append(contact["phone_number"])
            else:
                for contact in sample_contacts:
                    phone_numbers.append(contact["phone_number"])

            existing_number_entries = VerifiedNumber.view(
                'sms/verified_number_by_number',
                keys=phone_numbers,
                include_docs=True).all()

            for entry in existing_number_entries:
                if entry.domain != domain or entry.owner_doc_type != "CommCareCase":
                    errors.append("Cannot use phone number %s" %
                                  entry.phone_number)

            if len(errors) > 0:
                if use_contact_upload_file == "Y":
                    form._errors["contact_upload_file"] = form.error_class(
                        errors)
                else:
                    form._errors["sample_contacts"] = form.error_class(errors)
            else:
                existing_numbers = [
                    v.phone_number for v in existing_number_entries
                ]
                nonexisting_numbers = list(
                    set(phone_numbers).difference(existing_numbers))

                id_range = DomainCounter.increment(domain, "survey_contact_id",
                                                   len(nonexisting_numbers))
                ids = iter(range(id_range[0], id_range[1] + 1))
                for phone_number in nonexisting_numbers:
                    register_sms_contact(
                        domain,
                        "participant",
                        str(ids.next()),
                        request.couch_user.get_id,
                        phone_number,
                        contact_phone_number_is_verified="1",
                        contact_backend_id="MOBILE_BACKEND_TROPO_US",
                        language_code="en",
                        time_zone=time_zone.zone)

                newly_registered_entries = VerifiedNumber.view(
                    'sms/verified_number_by_number',
                    keys=nonexisting_numbers,
                    include_docs=True).all()

                sample.contacts = [
                    v.owner_id for v in existing_number_entries
                ] + [v.owner_id for v in newly_registered_entries]

                sample.save()

                # Update delegation tasks for surveys using this sample
                surveys = Survey.view("reminders/sample_to_survey",
                                      key=[domain, sample._id, "CATI"],
                                      include_docs=True).all()
                for survey in surveys:
                    survey.update_delegation_tasks(request.couch_user.get_id)
                    survey.save()

                return HttpResponseRedirect(
                    reverse("sample_list", args=[domain]))
    else:
        initial = {}
        if sample is not None:
            initial["name"] = sample.name
            initial["time_zone"] = sample.time_zone
            contact_info = []
            for case_id in sample.contacts:
                case = CommCareCase.get(case_id)
                contact_info.append({
                    "id": case.name,
                    "phone_number": case.contact_phone_number,
                    "case_id": case_id
                })
            initial["sample_contacts"] = contact_info
        form = SurveySampleForm(initial=initial)
Esempio n. 10
0
 def setUp(self):
     self.domain = 'test-log-call-domain'
     self.delete_call_logs(self.domain)
     self.case_id = register_sms_contact(self.domain, 'participant', 'test',
         'system', self.phone_number)
     self.case = CommCareCase.get(self.case_id)