Esempio n. 1
0
    def handle(self, text):

        if not is_eligible_for_results(self.msg.connection):
            self.respond(self.NOT_ELIGIBLE)
            return
        if not text or not text.strip():
            return

        pin = text.split()[0]

        text = text.strip()

        text2 = self.msg.contact.pin
        if text2 == text:

            staff_name = self.msg.contact.name
            staff_location = self.msg.contact.location
            pe = PatientEvent.objects.filter(notification_status='new').\
                filter(cba_conn__contact__location__parent=staff_location)

            str = ''
            str = ", ".join(i.patient.name + ":" + i.date.strftime("%d/%m/%Y")
                            for i in pe.all())
            self.respond("Hello %s! The births from %s are: ***%s" %
                         (staff_name, staff_location, str))
            return

        msg = self.BAD_PIN

        self.respond(msg)
Esempio n. 2
0
 def default(self, message):
     if hasattr(message, "possible_bad_mock_pin"):
         message.respond(BAD_PIN)                
         return True
     elif is_eligible_for_results(message.connection) \
        and message.connection.contact.location in self.last_collectors \
        and message.text.strip().upper() == message.connection.contact.pin.upper():
         if message.connection.contact == self.last_collectors[message.connection.contact.location]:
             message.respond(SELF_COLLECTED, name=message.connection.contact.name)
         else:
             message.respond(ALREADY_COLLECTED, name=message.connection.contact.name, 
                         collector=self.last_collectors[message.connection.contact.location])
         return True
Esempio n. 3
0
 def default(self, message):
     if hasattr(message, "possible_bad_mock_pin"):
         message.respond(BAD_PIN)
         return True
     elif is_eligible_for_results(message.connection) \
        and message.connection.contact.location in self.last_collectors \
        and message.text.strip().upper() == message.connection.contact.pin.upper():
         if message.connection.contact == self.last_collectors[
                 message.connection.contact.location]:
             message.respond(SELF_COLLECTED,
                             name=message.connection.contact.name)
         else:
             message.respond(ALREADY_COLLECTED,
                             name=message.connection.contact.name,
                             collector=self.last_collectors[
                                 message.connection.contact.location])
         return True
Esempio n. 4
0
 def default(self, message):
     # collect our bad pin responses, if they were generated.  See comment
     # in handle()
     if hasattr(message, "possible_bad_pin"):
         message.respond(BAD_PIN)                
         return True
     
     # additionally if this is your correct pin then respond that someone
     # has already processed the results (this assumes the only reason
     # you'd ever send your PIN in would be after receiving a notification)
     # This could be more robust, but keeping it simple.
     clinic = get_clinic_or_default(message.contact)
     if is_eligible_for_results(message.connection) \
        and clinic in self.last_collectors \
        and message.text.strip().upper() == message.contact.pin.upper():
         if message.contact == self.last_collectors[clinic]:
             message.respond(SELF_COLLECTED, name=message.connection.contact.name)
         else:
             message.respond(ALREADY_COLLECTED, name=message.connection.contact.name, 
                      collector=self.last_collectors[clinic])
         return True
     return self.mocker.default(message)
Esempio n. 5
0
 def handle (self, message):
     key = message.text.strip().upper()
     key = key[:4]
     
     if re.match(self.CHECK_REGEX, message.text, re.IGNORECASE):
         if not is_eligible_for_results(message.connection):
             message.respond(NOT_REGISTERED)
             return True
         
         clinic = get_clinic_or_default(message.contact)
         # this allows people to check the results for their clinic rather
         # than wait for them to be initiated by us on a schedule
         results = self._pending_results(clinic)
         if results:
             message.respond(RESULTS_READY, name=message.contact.name,
                             count=results.count())
             self._mark_results_pending(results, [message.connection])
         else:
             message.respond(NO_RESULTS, name=message.contact.name,
                             clinic=clinic.name)
         return True
     elif message.connection in self.waiting_for_pin \
        and message.connection.contact:
         pin = message.text.strip()
         if pin.upper() == message.connection.contact.pin.upper():
             self.send_results(message)
             return True
         else:
             # lets hide a magic field in the message so we can respond 
             # in the default phase if no one else catches this.  We 
             # don't respond here or return true in case this was a 
             # valid keyword for another app.
             message.possible_bad_pin = True
     
     # Finally, check if our mocker wants to do anything with this message, 
     # and notify the router if so.
     elif self.mocker.handle(message):
         return True
Esempio n. 6
0
    def handle(self, text):
        b = InputCleaner()
        if not is_eligible_for_results(self.msg.connection):
            # essentially checking for an active clinic_worker
            self.respond(self.INELIGIBLE)
            return

        text = text.strip()
        text = b.remove_double_spaces(text)
        location = self.msg.contact.location
        if location.type == const.get_zone_type():
            location = location.parent
        cba = None

        if text[1:].isdigit() and len(text) >= self.MIN_PHONE_LENGTH:
            try:
                cba = \
                Contact.active.get(connection__identity__icontains=text,
                                   location__parent=location,
                                   types=const.get_cba_type())
            except Contact.DoesNotExist:
                self.respond('The phone number %(phone)s does not belong to any'
                             + ' CBA at %(clinic)s. Make sure you typed it '
                             + 'correctly', phone=text, clinic=location)
            except Contact.MultipleObjectsReturned:
                logger.warning("Bug. phone number %s is used by multiple cba's "
                +"at same clinic" % text)
                return

        if not cba:
            cbas = \
            Contact.active.filter(name__icontains=text,
                                  location__parent=location,
                                  types=const.get_cba_type())
            if not cbas:
                self.respond('The name %(name)s does not belong to any'
                             + ' CBA at %(clinic)s. Make sure you typed it '
                             + 'correctly', name=text,
                             clinic=location)
                return
            if len(cbas) == 1:
                cba = cbas[0]
            elif len(cbas) < 5:
                self.respond("Try sending DEREGISTER <CBA_PHONE_NUMBER>. Which "
                             + "CBA did you mean? %(cbas)s", cbas=' or '.join(
                             cba.name + ":" + cba.default_connection.identity
                             for cba in cbas))
                return
            else:
                self.respond("There are %(len)s CBA's who's names match %(name)s"
                             + " at %(clinic)s. Try to use the phone number "
                             + "instead", len=len(cbas), name=text,
                             clinic=location.name)
                return
        if cba:
            cba.is_active = False
            cba.save()
            self.respond("You have successfully deregistered %(name)s:"
                         + "%(phone)s of zone %(zone)s at %(clinic)s",
                         name=cba.name, phone=cba.default_connection.identity,
                         zone=cba.location.name, clinic=location.name)
            worker = self.msg.contact
            for help_admin in Contact.active.filter(is_help_admin=True):
                OutgoingMessage(
                                help_admin.default_connection,
                                "%s:%s has deregistered %s:%s of zone %s at %s" %
                                (worker.name,
                                worker.default_connection.identity,
                                cba.name,
                                cba.default_connection.identity,
                                cba.location.name,
                                location.name
                                )).send()
Esempio n. 7
0
    def handle(self, text):
        b = InputCleaner()
        if is_eligible_for_results(self.msg.connection):
            # refuse re-registration if they're still active and eligible
            self.respond(self.ALREADY_REGISTERED, 
                         name=self.msg.connection.contact.name,
                         location=self.msg.connection.contact.location)
            return
        
        text = text.strip()
        text = b.remove_double_spaces(text)
        if len(text) < (self.PIN_LENGTH + self.MIN_CLINIC_CODE_LENGTH + self.MIN_NAME_LENGTH + 1):
            self.mulformed_msg_help()
            return

        #signed pin
        if text[-5:-4] == '-' or text[-5:-4] == '+':
            self.invalid_pin(text[-5:])
            return
        #too long pin
        if ' ' in text and text[1 + text.rindex(' '):].isdigit() and len(text[1 + text.rindex(' '):]) > self.PIN_LENGTH:
            self.invalid_pin(text[1 + text.rindex(' '):])
            return
        #non-white space before pin
        if text[-5:-4] != ' ' and text[-4:-3] != ' ':
            self.respond("Sorry, you should put a space before your pin. "
                         "Please make sure your code is a %s-digit number like %s. "
                         "Send JOIN <CLINIC CODE> <YOUR NAME> <SECURITY CODE>." % (
                         self.PIN_LENGTH, ''.join(str(i) for i in range(1, int(self.PIN_LENGTH) + 1))))
            return
        #reject invalid pin
        user_pin = text[-4:]
        if not user_pin:
            self.help()
            return
        elif len(user_pin) < 4:
            self.invalid_pin(user_pin)
            return
        elif not user_pin.isdigit():
            self.invalid_pin(user_pin)
            return

        
        group = self.PATTERN.search(text)
        if group is None:
            self.mulformed_msg_help()
            return

        tokens = group.groups()
        if not tokens:
            self.mulformed_msg_help()
            return

        clinic_code = tokens[0].strip()
        clinic_code = b.try_replace_oil_with_011(clinic_code)
        #we expect all codes have format PPDDFF or PPDDFFS
        clinic_code = clinic_code[0:6]
        name = tokens[2]
        name = name.title().strip()
        pin = tokens[4].strip()
        if len(pin) != self.PIN_LENGTH:
            self.respond(self.INVALID_PIN)
            return
        if not name:
            self.respond("Sorry, you must provide a name to register. %s" % self.HELP_TEXT)
            return
        elif len(name) < self.MIN_NAME_LENGTH:
            self.respond("Sorry, you must provide a valid name to register. %s" % self.HELP_TEXT)
            return
        try:
            location = Location.objects.get(slug__iexact=clinic_code,
                                            type__slug__in=const.CLINIC_SLUGS)
            if self.msg.connection.contact is not None \
               and self.msg.connection.contact.is_active:
                # this means they were already registered and active, but not yet 
                # receiving results.
                clinic = get_clinic_or_default(self.msg.connection.contact) 
                if clinic != location:
                    self.respond(self.ALREADY_REGISTERED,
                                 name=self.msg.connection.contact.name,
                                 location=clinic)
                    return True
                else: 
                    contact = self.msg.contact
            else:
                contact = Contact(location=location)
                clinic = get_clinic_or_default(contact)
            contact.name = name
            contact.pin = pin
            contact.save()
            contact.types.add(const.get_clinic_worker_type())
            
            self.msg.connection.contact = contact
            self.msg.connection.save()
            
            self.respond("Hi %(name)s, thanks for registering for "
                         "Results160 from %(location)s. "
                         "Your PIN is %(pin)s. "
                         "Reply with keyword 'HELP' if this is "
                         "incorrect", name=contact.name, location=clinic.name,
                         pin=pin)
        except Location.DoesNotExist:
            self.respond("Sorry, I don't know about a location with code %(code)s. Please check your code and try again.",
                         code=clinic_code)
Esempio n. 8
0
    def handle(self, text):
        b = InputCleaner()
        if not is_eligible_for_results(self.msg.connection):
            self.respond(self.NOT_ELIGIBLE)
            return
        if not text or not text.strip():
            return
        clinic_code = text.split()[0]
        #staff with zeros in case someone just send PP or PPDD
        if b.try_replace_oil_with_011(clinic_code[0:6]).isdigit():
            clinic_code = clinic_code + "00000"
            clinic_code = clinic_code[0:6]
        district_facilities = None
        province_facilities = None
        try:
            location = Location.objects.get(slug__iexact=clinic_code)
            if location.type.slug == 'districts':
                district_facilities = Location.objects.filter(parent=location,
                                                              type__slug__in=
                                                              const.CLINIC_SLUGS)
            elif location.type.slug == 'provinces':
                province_facilities = Location.objects.filter(parent__parent=
                                                              location,
                                                              type__slug__in=
                                                              const.CLINIC_SLUGS)

        except Location.DoesNotExist:
            # maybe it's a district like 403000
            try:
                clinic_code = clinic_code.replace('000', '0')
                district_facilities = Location.objects.filter(slug__startswith=
                                                              clinic_code,
                                                              type__slug__in=
                                                              const.CLINIC_SLUGS)
                location = district_facilities[0].parent
            except IndexError:
                #maybe it's a province like 400000
                try:
                    clinic_code = clinic_code.replace('000', '0')
                    province_facilities = Location.objects.filter(slug__startswith=
                                                                  clinic_code,
                                                                  type__slug__in=
                                                                  const.CLINIC_SLUGS)
                    location = province_facilities[0].parent.parent
                    
                except IndexError:
                    self.respond("Sorry, I don't know about a location with code %(code)s. Please check your code and try again.",
                                 code=clinic_code)
                    return
        text = text.strip()
        text = b.remove_double_spaces(text)
        today = datetime.datetime.today()
        try:
            month = int(b.words_to_digits(text.split()[1][0:3]))
        except (IndexError, TypeError):
            month = today.month
        if month not in range(1, 13):
            month = today.month
        startdate = datetime.datetime(today.year, month, 1)
        if month == 12:
            enddate = datetime.datetime(today.year, 12, 31)
        else:
            enddate = datetime.datetime(today.year, month + 1, 1) - datetime.timedelta(seconds=1)
        report_values = self.get_facility_report(location, startdate, enddate,
                                                 district_facilities,
                                                 province_facilities)

        rpt_header = "SENT RESULTS\n%s\n%s to %s" % (location.name,
                                                     startdate.strftime("%d/%m/%Y"), enddate.strftime("%d/%m/%Y"))
        rpt_data = '\n'.join(key + ";" + str(value) for key, value in
                             report_values.items())
        msg = rpt_header + '\n' + rpt_data         
        
        self.respond(msg)
Esempio n. 9
0
    def handle(self, text):
        b = InputCleaner()
        if not is_eligible_for_results(self.msg.connection):
            self.respond(self.NOT_ELIGIBLE)
            return
        if not text or not text.strip():
            return
        clinic_code = text.split()[0]
        #staff with zeros in case someone just send PP or PPDD
        if b.try_replace_oil_with_011(clinic_code[0:6]).isdigit():
            clinic_code = clinic_code + "00000"
            clinic_code = clinic_code[0:6]
        district_facilities = None
        province_facilities = None
        try:
            location = Location.objects.get(slug__iexact=clinic_code)
            if location.type.slug == 'districts':
                district_facilities = Location.objects.filter(
                    parent=location, type__slug__in=const.CLINIC_SLUGS)
            elif location.type.slug == 'provinces':
                province_facilities = Location.objects.filter(
                    parent__parent=location, type__slug__in=const.CLINIC_SLUGS)

        except Location.DoesNotExist:
            # maybe it's a district like 403000
            try:
                clinic_code = clinic_code.replace('000', '0')
                district_facilities = Location.objects.filter(
                    slug__startswith=clinic_code,
                    type__slug__in=const.CLINIC_SLUGS)
                location = district_facilities[0].parent
            except IndexError:
                #maybe it's a province like 400000
                try:
                    clinic_code = clinic_code.replace('000', '0')
                    province_facilities = Location.objects.filter(
                        slug__startswith=clinic_code,
                        type__slug__in=const.CLINIC_SLUGS)
                    location = province_facilities[0].parent.parent

                except IndexError:
                    self.respond(
                        "Sorry, I don't know about a location with code %(code)s. Please check your code and try again.",
                        code=clinic_code)
                    return
        text = text.strip()
        text = b.remove_double_spaces(text)
        today = datetime.datetime.today()
        try:
            month = int(b.words_to_digits(text.split()[1][0:3]))
        except (IndexError, TypeError):
            month = today.month
        if month not in range(1, 13):
            month = today.month
        startdate = datetime.datetime(today.year, month, 1)
        if month == 12:
            enddate = datetime.datetime(today.year, 12, 31)
        else:
            enddate = datetime.datetime(today.year, month + 1,
                                        1) - datetime.timedelta(seconds=1)
        report_values = self.get_facility_report(location, startdate, enddate,
                                                 district_facilities,
                                                 province_facilities)

        rpt_header = "SENT RESULTS\n%s\n%s to %s" % (
            location.name, startdate.strftime("%d/%m/%Y"),
            enddate.strftime("%d/%m/%Y"))
        rpt_data = '\n'.join(key + ";" + str(value)
                             for key, value in report_values.items())
        msg = rpt_header + '\n' + rpt_data

        self.respond(msg)
Esempio n. 10
0
    def handle(self, text):
        b = InputCleaner()
        if not is_eligible_for_results(self.msg.connection):
            # essentially checking for an active clinic_worker
            self.respond(self.INELIGIBLE)
            return

        text = text.strip()
        text = b.remove_double_spaces(text)
        worker = self.msg.contact
        location = worker.location
        if location.type == const.get_zone_type():
            location = location.parent
        cba = None

        # we expect phone numbers like +260977123456, 0977123456, 977123456
        # (a phone number is unique to each cba at a clinic)
        if text[1:].isdigit() and len(text) >= self.MIN_PHONE_LENGTH:
            try:
                cba = \
                Contact.active.get(connection__identity__endswith=text,
                                   location__parent=location,
                                   types=const.get_cba_type())
            except Contact.DoesNotExist:
                self.respond('The phone number %(phone)s does not belong to any'
                             ' CBA at %(clinic)s. Make sure you typed it '
                             'correctly', phone=text, clinic=location)
            # we do not expect this to happen. phone number is excpected to be
            # unique (>=9 chars) project wide
            except Contact.MultipleObjectsReturned:
                logger.warning("Bug. phone number %s is used by multiple cba's "
                               "at same clinic" % text)

                self.respond("Sorry %(name)s, the CBA with phone number %(phone)s"
                             " could not be deregistered. This matter will be"
                             " followed up by Support Staff immediately",
                             name=worker.name, phone=text)

                msg = (self.FOLLOWUP_MESSAGE % (text, worker.name,
                       worker.default_connection.identity,
                       location.name))
                self.notify_help_admins(msg)
                return

        if not cba:
            cbas = \
            Contact.active.filter(name__icontains=text,
                                  location__parent=location,
                                  types=const.get_cba_type())
            if not cbas:
                self.respond('The name %(name)s does not belong to any'
                             ' CBA at %(clinic)s. Make sure you typed it '
                             'correctly', name=text,
                             clinic=location)
                return
            if len(cbas) == 1:
                cba = cbas[0]
            elif len(cbas) < 5:
                self.respond("Try sending REMOVE <CBA_PHONE_NUMBER>. Which "
                             + "CBA did you mean? %(cbas)s", cbas=' or '.join(
                             cba.name + ":" + cba.default_connection.identity
                             for cba in cbas))
                return
            else:
                self.respond("There are %(len)s CBA's who's names match %(name)s"
                             + " at %(clinic)s. Try to use the phone number "
                             + "instead", len=len(cbas), name=text,
                             clinic=location.name)
                return
        if cba:
            cba.is_active = False
            cba.save()
            self.respond("You have successfully deregistered %(name)s:"
                         + "%(phone)s of zone %(zone)s at %(clinic)s",
                         name=cba.name, phone=cba.default_connection.identity,
                         zone=cba.location.name, clinic=location.name)
            msg = ("%s:%s has deregistered %s:%s of zone %s at %s" %
                   (worker.name,
                   worker.default_connection.identity,
                   cba.name,
                   cba.default_connection.identity,
                   cba.location.name,
                   location.name))
            self.notify_help_admins(msg)
Esempio n. 11
0
    def handle(self, text):
        b = InputCleaner()
        if not is_eligible_for_results(self.msg.connection):
            # essentially checking for an active clinic_worker
            self.respond(self.INELIGIBLE)
            return

        text = text.strip()
        text = b.remove_double_spaces(text)
        worker = self.msg.contact
        location = worker.location
        if location.type == const.get_zone_type():
            location = location.parent
        cba = None

        # we expect phone numbers like +260977123456, 0977123456, 977123456
        # (a phone number is unique to each cba at a clinic)
        if text[1:].isdigit() and len(text) >= self.MIN_PHONE_LENGTH:
            try:
                cba = \
                Contact.active.get(connection__identity__endswith=text,
                                   location__parent=location,
                                   types=const.get_cba_type())
            except Contact.DoesNotExist:
                self.respond(
                    'The phone number %(phone)s does not belong to any'
                    ' CBA at %(clinic)s. Make sure you typed it '
                    'correctly',
                    phone=text,
                    clinic=location)
            # we do not expect this to happen. phone number is excpected to be
            # unique (>=9 chars) project wide
            except Contact.MultipleObjectsReturned:
                logger.warning(
                    "Bug. phone number %s is used by multiple cba's "
                    "at same clinic" % text)

                self.respond(
                    "Sorry %(name)s, the CBA with phone number %(phone)s"
                    " could not be deregistered. This matter will be"
                    " followed up by Support Staff immediately",
                    name=worker.name,
                    phone=text)

                msg = (self.FOLLOWUP_MESSAGE %
                       (text, worker.name, worker.default_connection.identity,
                        location.name))
                self.notify_help_admins(msg)
                return

        if not cba:
            cbas = \
            Contact.active.filter(name__icontains=text,
                                  location__parent=location,
                                  types=const.get_cba_type())
            if not cbas:
                self.respond(
                    'The name %(name)s does not belong to any'
                    ' CBA at %(clinic)s. Make sure you typed it '
                    'correctly',
                    name=text,
                    clinic=location)
                return
            if len(cbas) == 1:
                cba = cbas[0]
            elif len(cbas) < 5:
                self.respond("Try sending REMOVE <CBA_PHONE_NUMBER>. Which " +
                             "CBA did you mean? %(cbas)s",
                             cbas=' or '.join(cba.name + ":" +
                                              cba.default_connection.identity
                                              for cba in cbas))
                return
            else:
                self.respond(
                    "There are %(len)s CBA's who's names match %(name)s" +
                    " at %(clinic)s. Try to use the phone number " + "instead",
                    len=len(cbas),
                    name=text,
                    clinic=location.name)
                return
        if cba:
            cba.is_active = False
            cba.save()
            self.respond("You have successfully deregistered %(name)s:" +
                         "%(phone)s of zone %(zone)s at %(clinic)s",
                         name=cba.name,
                         phone=cba.default_connection.identity,
                         zone=cba.location.name,
                         clinic=location.name)
            msg = ("%s:%s has deregistered %s:%s of zone %s at %s" %
                   (worker.name, worker.default_connection.identity, cba.name,
                    cba.default_connection.identity, cba.location.name,
                    location.name))
            self.notify_help_admins(msg)