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)
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
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
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)
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
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()
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)
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)
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)
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)
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)