def note_case (self, message, ref_id, note): case = self.find_case(ref_id) CaseNote(case=case, created_by=message.sender, text=note).save() #message.respond(_("Note added to case +%s.") % ref_id) self.int2dom(message, _("Note added to case +%s.") % ref_id) log(case, "note_added") return True
def new_case (self, message, last, first, gender, dob,guardian="", contact="", zone=None): """Expected format for nnnnew command, sent as a reminder""" """Format: <>new [patient last name] [patient first name] gender[m/f] [dob ddmmyy] [guardian] [contact #] [zone - optional]<> Purpose: register a new patient into the system. Receive patient ID number back""" # reporter reporter = message.persistant_connection.reporter dob = re.sub(r'\D', '', dob) try: dob = time.strptime(dob, "%d%m%y") except ValueError: try: dob = time.strptime(dob, "%d%m%Y") except ValueError: raise HandlerFailed(_("Couldn't understand date: %s") % dob) dob = datetime.date(*dob[:3]) if guardian: guardian = guardian.title() # todo: move this to a more generic get_description info = { "first_name" : first.title(), "last_name" : last.title(), "gender" : gender.upper()[0], "dob" : dob, "guardian" : guardian, "mobile" : contact, "reporter" : reporter, "location" : reporter.location } ## check to see if the case already exists iscase = Case.objects.filter(first_name=info['first_name'], last_name=info['last_name'], reporter=info['reporter'], dob=info['dob']) if iscase: #message.respond(_( #"%(last_name)s, %(first_name)s has already been registered by you.") % info) info["PID"] = iscase[0].ref_id self.info(iscase[0].id) self.info(info) message.respond(_( "%(last_name)s, %(first_name)s (+%(PID)s) has already been registered by %(reporter)s.") % info) # TODO: log this message return True case = Case(**info) case.save() info.update({ "id": case.ref_id, "last_name": last.upper(), "age": case.age() }) message.respond(_( "New +%(id)s: %(last_name)s, %(first_name)s %(gender)s/%(age)s " + "(%(guardian)s) %(location)s") % info) log(case, "patient_created") return True
def join (self, message, code, last_name, first_name, username=None): try: clinic = Facility.objects.get(codename__iexact=code) except Facility.DoesNotExist: raise HandlerFailed(_("The given password is not recognized.")) if username is None: # FIXME: this is going to run into charset issues username = (first_name[0] + last_name).lower() else: # lower case usernames ... also see FIXME above? username = username.lower() if User.objects.filter(username__iexact=username).count(): raise HandlerFailed(_( "Username '%s' is already in use. " + "Reply with: JOIN <last> <first> <username>") % username) # todo: use the more generic get_description if possible info = { "username" : username, "user_first_name" : first_name.title(), "user_last_name" : last_name.title() } user = User(username=username, first_name=first_name.title(), last_name=last_name.title()) user.save() mobile = message.peer in_use = Provider.by_mobile(mobile) provider = Provider(mobile=mobile, user=user, clinic=clinic, active=not bool(in_use)) provider.save() if in_use: info.update({ "user_last_name" : in_use.user.last_name.upper(), "user_first_name" : in_use.user.first_name, "other" : in_use.user.username, "mobile" : mobile, "clinic" : provider.clinic.name, }) #message.respond(_( # "Phone %(mobile)s is already registered to %(user_last_name)s, " + # "%(user_first_name)s. Reply with 'CONFIRM %(username)s'.") % info) self.int2dom(message, _( "Phone %(mobile)s is already registered to %(user_last_name)s, " + "%(user_first_name)s. Reply with 'CONFIRM %(username)s'.") % info) else: info.update({ "id" : provider.id, "mobile" : mobile, "clinic" : provider.clinic.name, "user_last_name" : last_name.upper() }) self.respond_to_join(message, info) log(provider, "provider_registered") return True
def note_case (self, message, ref_id, note): """NOTE MY DOCSTRING :( """ reporter = message.persistant_connection.reporter case = self.find_case(ref_id) CaseNote(case=case, created_by=reporter, text=note).save() message.respond(_("Note added to case +%s.") % ref_id) log(case, "note_added") return True
def transfer_case (self, message, ref_id, target): provider = message.sender.provider case = self.find_case(ref_id) new_provider = self.find_provider(target) case.provider = new_provider case.save() info = new_provider.get_dictionary() info["ref_id"] = case.ref_id message.respond(_("Case +%(ref_id)s transferred to @%(username)s " + "(%(user_last_name)s, %(user_last_name)s).") % info) message.forward(_("Case +%s transferred to you from @%s.") % ( case.ref_id, provider.user.username)) log(case, "case_transferred") return True
def new_case (self, message, last, first, gender, dob, guardian="", contact="", zone=None): provider = message.sender.provider if not zone: if provider.clinic: zone = provider.clinic.zone else: zone = Zone.objects.get(number=zone[1:]) dob = re.sub(r'\D', '', dob) try: dob = time.strptime(dob, "%d%m%y") except ValueError: try: dob = time.strptime(dob, "%d%m%Y") except ValueError: raise HandlerFailed(_("Couldn't understand date: %s") % dob) dob = datetime.date(*dob[:3]) if guardian: guardian = guardian.title() # todo: move this to a more generic get_description info = { "first_name" : first.title(), "last_name" : last.title(), "gender" : gender.upper()[0], "dob" : dob, "guardian" : guardian, "mobile" : contact, "provider" : provider, "zone" : zone } ## TODO: check to see if the case already exists case = Case(**info) case.save() info.update({ "id": case.ref_id, "last_name": last.upper(), "age": case.age() }) if zone: info["zone"] = zone.name message.respond(_( "New +%(id)s: %(last_name)s, %(first_name)s %(gender)s/%(age)s " + "(%(guardian)s) %(zone)s") % info) log(case, "patient_created") return True
def confirm_join (self, message, username): mobile = message.peer try: user = User.objects.get(username__iexact=username) except User.DoesNotExist: self.respond_not_registered(username) for provider in Provider.objects.filter(mobile=mobile): if provider.user.id == user.id: provider.active = True else: provider.active = False provider.save() info = provider.get_dictionary() self.respond_to_join(message, info) log(provider, "confirmed_join") return True
def cancel_case (self, message, ref_id): case = self.find_case(ref_id) if case.reportmalnutrition_set.count(): raise HandlerFailed(_( "Cannot cancel +%s: case has malnutrition reports.") % ref_id) if case.reportmalaria_set.count(): raise HandlerFailed(_( "Cannot cancel +%s: case has malaria reports.") % ref_id) if case.reportdiagnosis_set.count(): raise HandlerFailed(_( "Cannot cancel +%s: case has diagnosis reports.") % ref_id) case.delete() message.respond(_("Case +%s cancelled.") % ref_id) log(message.sender.provider, "case_cancelled") return True
def report_diarrhea(self, message, ref_id, ors, days, complications): case = self.find_case(ref_id) ors = True if ors == "y" else False days = int(days) observed, choices = self.get_diarrheaobservations(complications) self.delete_similar(case.reportdiarrhea_set) provider = message.sender.provider report = ReportDiarrhea(case=case, provider=provider, ors=ors, days=days) report.save() for obs in observed: report.observed.add(obs) report.diagnose() report.save() choice_term = dict(choices) info = case.get_dictionary() info.update(report.get_dictionary()) msg = _("%(diagnosis_msg)s. +%(ref_id)s %(last_name)s, %(first_name_short)s, %(gender)s/%(months)s (%(guardian)s). %(days)s, %(ors)s") % info if observed: msg += ", " + info["observed"] #message.respond("DIARRHEA> " + msg) self.int2dom(message, "DIARRHEA> " + msg) if report.status in (report.MODERATE_STATUS, report.SEVERE_STATUS, report.DANGER_STATUS): alert = _("@%(username)s reports %(msg)s") % {"username":provider.user.username, "msg":msg} recipients = [provider] for query in (Provider.objects.filter(alerts=True), Provider.objects.filter(clinic=provider.clinic)): for recipient in query: if recipient in recipients: continue recipients.append(recipient) #message.forward(recipient.mobile, alert) self.int2dom(message, alert,recipient.mobile) log(case, "diarrhea_taken") return True
def transfer_case (self, message, ref_id, target): """heyExpected format for transfer command, sent as a reminder""" reporter = message.persistant_connection.reporter case = self.find_case(ref_id) new_provider = self.find_provider(target) case.reporter = new_provider case.save() info = { 'username': new_provider.alias, 'name': new_provider.full_name(), 'location':new_provider.location } info["ref_id"] = case.ref_id message.respond(_("Case +%(ref_id)s transferred to @%(username)s " + "(%(name)s - %(location)s).") % info) message.forward(new_provider.connection().identity, _("Case +%s transferred to you from @%s (%s - %s).")% (case.ref_id, reporter.alias, reporter.full_name(), reporter.location)) log(case, "case_transferred") return True
def followup_diarrhea(self, message, ref_id, is_ok): case = self.find_case(ref_id) is_ok = True if is_ok == "y" else False provider = message.sender.provider report = ReportDiarrhea.objects.get(case=case) if is_ok: report.status = ReportDiarrhea.HEALTHY_STATUS report.save() else: report.status = ReportDiarrhea.SEVERE_STATUS report.save() info = report.case.get_dictionary() info.update(report.get_dictionary()) msg = _("%(diagnosis_msg)s. +%(ref_id)s %(last_name)s, %(first_name_short)s, %(gender)s/%(months)s (%(guardian)s). %(days)s, %(ors)s") % info if report.observed.all().count() > 0: msg += ", " + info["observed"] #message.respond("DIARRHEA> " + msg) self.int2dom(message, "DIARRHEA> " + msg) if report.status in (report.MODERATE_STATUS, report.SEVERE_STATUS, report.DANGER_STATUS): alert = _("@%(username)s reports %(msg)s") % {"username":provider.user.username, "msg":msg} recipients = [provider] for query in (Provider.objects.filter(alerts=True), Provider.objects.filter(clinic=provider.clinic)): for recipient in query: if recipient in recipients: continue recipients.append(recipient) #message.forward(recipient.mobile, alert) self.int2dom(message, alert, recipient.mobile) log(case, "diarrhea_fu_taken") return True
raise HandlerFailed(_( "Cannot cancel +%s: case has malnutrition reports.") % ref_id) if case.reportmalaria_set.count(): raise HandlerFailed(_( "Cannot cancel +%s: case has malaria reports.") % ref_id) if case.reportdiagnosis_set.count(): raise HandlerFailed(_( "Cannot cancel +%s: case has diagnosis reports.") % ref_id) case.delete() #message.respond(_("Case +%s cancelled.") % ref_id) self.int2dom(message, _("Case +%s cancelled.") % ref_id) log(message.sender.provider, "case_cancelled") return True @keyword(r'transfer \+?(\d+) (?:to )?\@?(\w+)') @authenticated def transfer_case (self, message, ref_id, target): provider = message.sender.provider case = self.find_case(ref_id) new_provider = self.find_provider(target) case.provider = new_provider case.save() info = new_provider.get_dictionary() info["ref_id"] = case.ref_id #message.respond(_("Case +%(ref_id)s transferred to @%(username)s " + # "(%(user_last_name)s, %(user_last_name)s).") % info) self.int2dom(message, _("Case +%(ref_id)s transferred to @%(username)s " +
def report_malaria(self, message, ref_id, result, bednet, observed): case = self.find_case(ref_id) observed, choices = self.get_observations(observed) self.delete_similar(case.reportmalaria_set) provider = message.sender.provider result = result.lower() == "y" bednet = bednet.lower() == "y" report = ReportMalaria(case=case, provider=provider, result=result, bednet=bednet) report.save() for obs in observed: report.observed.add(obs) report.save() # build up an information dictionary info = case.get_dictionary() info.update(report.get_dictionary()) info.update(provider.get_dictionary()) # this could all really do with cleaning up # note that there is always an alert that goes out if not result: if observed: info["observed"] = ", (%s)" % info["observed"] msg = _("MRDT> Child +%(ref_id)s, %(last_name)s, %(first_name)s, "\ "%(gender)s/%(months)s (%(guardian)s), %(village)s. RDT=%(result_text)s,"\ " Bednet=%(bednet_text)s%(observed)s. Please refer patient IMMEDIATELY "\ "for clinical evaluation" % info) # alerts to health team alert = _("MRDT> Negative MRDT with Fever. +%(ref_id)s, %(last_name)s,"\ " %(first_name)s, %(gender)s/%(months)s %(village)s. Patient "\ "requires IMMEDIATE referral. Reported by CHW %(provider_name)s "\ "@%(provider_user)s m:%(provider_mobile)s." % info) else: # this is all for if child has tested postive # and is really just abut years, months = case.years_months() tabs, yage = None, None # just reformatted to make it look like less ugh if years < 1: if months < 2: tabs, yage = None, None else: tabs, yage = 1, "less than 3" elif years < 3: tabs, yage = 1, "less than 3" elif years < 9: tabs, yage = 2, years elif years < 15: tabs, yage = 3, years else: tabs, yage = 4, years # messages change depending upon age and dangers dangers = report.observed.filter(uid__in=("vomiting", "appetite", "breathing", "confusion", "fits")) # no tabs means too young if not tabs: info["instructions"] = "Child is too young for treatment. Please refer IMMEDIATELY to clinic" else: # old enough to take tabs, but lets format msg if dangers: info["danger"] = " and danger signs (" + ",".join([ u.name for u in dangers ]) + ")" info["instructions"] = "Refer to clinic immediately after %s "\ "tab%s of Coartem is given" % (tabs, (tabs > 1) and "s" or "") else: info["danger"] = "" info["instructions"] = "Child is %s. Please provide %s tab%s "\ "of Coartem (ACT) twice a day for 3 days" % (yage, tabs, (tabs > 1) and "s" or "") # finally build out the messages msg = _("MRDT> Child +%(ref_id)s, %(last_name)s, %(first_name)s, "\ "%(gender)s/%(months)s has MALARIA%(danger)s. %(instructions)s" % info) alert = _("MRDT> Child +%(ref_id)s, %(last_name)s, %(first_name)s, "\ "%(gender)s/%(months)s (%(village)s) has MALARIA%(danger)s. "\ "CHW: @%(provider_user)s %(provider_mobile)s" % info) #message.respond(msg) self.int2dom(message, msg) recipients = report.get_alert_recipients() for recipient in recipients: #message.forward(recipient.mobile, alert) self.int2dom(message, alert,recipient.mobile) log(case, "mrdt_taken") return True
def diagnosis(self, message, ref_id, text): case = self.find_case(ref_id) provider = message.sender.provider diags = [] labs = [] hits = find_diagnostic_re.findall(message.text) for hit in hits: code = hit[2:] try: diags.append(Diagnosis.objects.get(code__iexact=code)) except Diagnosis.DoesNotExist: raise HandlerFailed("Unknown diagnosis code: %s" % code) hits = find_lab_re.findall(text) for hit in hits: code, sign, number = hit try: # the code starts with / labs.append([Lab.objects.get(code__iexact=code[1:]), sign, number]) except Lab.DoesNotExist: raise HandlerFailed("Unknown lab code: %s" % code) self.delete_similar(case.reportdiagnosis_set) report = ReportDiagnosis(case=case, provider=provider, text=message.text) report.save() for diag in diags: report.diagnosis.add(diag) for lab, sign, number in labs: ld = LabDiagnosis() ld.lab = lab ld.result = int(sign == "+") if number: ld.amount = number ld.diagnosis = report ld.save() report.save() info = case.get_dictionary() info.update(report.get_dictionary()) if info["labs_text"]: info["labs_text"] = "%sLabs: %s" % (info["diagnosis"] and " " or "", info["labs_text"]) #message.respond(_("D> +%(ref_id)s %(first_name_short)s.%(last_name)s %(diagnosis)s%(labs_text)s") % info) self.int2dom(message, _("D> +%(ref_id)s %(first_name_short)s.%(last_name)s %(diagnosis)s%(labs_text)s") % info) # add in the forward of instructions to the case provider # if that it is not the reporter of the issue instructions = [] for diagnosis in report.diagnosis.all(): if diagnosis.instructions: instructions.append(diagnosis.instructions) if instructions: if provider != case.provider: # there's a different provider info = {"ref_id":ref_id, "instructions":(", ".join(instructions))} #message.forward(case.provider.mobile, "D> +%(ref_id)s %(instructions)s" % info) self.int2dom(message, "D> +%(ref_id)s %(instructions)s" % info,case.provider.mobile) log(case, "diagnosis_taken") return True
def report_case (self, message, ref_id, muac, weight, height, complications): case = self.find_case(ref_id) try: muac = float(muac) if muac < 30: # muac is in cm? muac *= 10 muac = int(muac) except ValueError: raise HandlerFailed( _("Can't understand MUAC (mm): %s") % muac) if weight is not None: try: weight = float(weight) if weight > 100: # weight is in g? weight /= 1000.0 except ValueError: raise HandlerFailed("Can't understand weight (kg): %s" % weight) if height is not None: try: height = float(height) if height < 3: # weight height in m? height *= 100 height = int(height) except ValueError: raise HandlerFailed("Can't understand height (cm): %s" % height) observed, choices = self.get_observations(complications) self.delete_similar(case.reportmalnutrition_set) provider = message.sender.provider report = ReportMalnutrition(case=case, provider=provider, muac=muac, weight=weight, height=height) report.save() for obs in observed: report.observed.add(obs) report.diagnose() report.save() choice_term = dict(choices) info = case.get_dictionary() info.update(report.get_dictionary()) msg = _("%(diagnosis_msg)s. +%(ref_id)s %(last_name)s, %(first_name_short)s, %(gender)s/%(months)s (%(guardian)s). MUAC %(muac)s") % info if weight: msg += ", %.1f kg" % weight if height: msg += ", %.1d cm" % height if observed: msg += ", " + info["observed"] #message.respond("MUAC> " + msg) self.int2dom(message, "MUAC> " + msg) if report.status in (report.MODERATE_STATUS, report.SEVERE_STATUS, report.SEVERE_COMP_STATUS): alert = _("@%(username)s reports %(msg)s") % {"username":provider.user.username, "msg":msg} recipients = [provider] for query in (Provider.objects.filter(alerts=True), Provider.objects.filter(clinic=provider.clinic)): for recipient in query: if recipient in recipients: continue recipients.append(recipient) #message.forward(recipient.mobile, alert) log(case, "muac_taken") return True