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) reporter = message.persistant_connection.reporter report = ReportDiarrhea(case=case, reporter=reporter, 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) """ 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) """ log(case, "diarrhea_taken") 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 reporter = message.persistant_connection.reporter 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) """ if report.status in (report.MODERATE_STATUS, report.SEVERE_STATUS, report.DANGER_STATUS): alert = _("@%(username)s reports %(msg)s") % {"username":reporter.alias, "msg":msg} recipients = [reporter] 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, "diarrhea_fu_taken") return True
def report_malaria(self, message, ref_id, result, bednet, observed): """Processes incoming mrdt reports. Expected format is as above. Can process inputs without spaces, but symptoms must have spaces between them. '+' and 'y' register as positive for malaria, all other characters register as negative. 'y' registers as yes for a bednet, all other characters register as no.""" case = self.find_case(ref_id) observed, choices = self.get_observations(observed) self.delete_similar(case.reportmalaria_set) reporter = message.persistant_connection.reporter result = result == "+" or result.lower() == "y" bednet = bednet.lower() == "y" report = ReportMalaria(case=case, reporter=reporter, 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( { "reporter_name": reporter.full_name(), "reporter_alias": reporter.alias, "reporter_identity": reporter.connection().identity, } ) # 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/%(age)s (%(guardian)s), %(location)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/%(age)s %(location)s. Patient " "requires IMMEDIATE referral. Reported by CHW %(reporter_name)s " "@%(reporter_alias)s m:%(reporter_identity)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 < 5: tabs, yage = None, None else: tabs, yage = "one quarter", "under one year (5-10kg)" elif years < 7: tabs, yage = "one half", "1-6 years (11-24kg)" elif years < 14: tabs, yage = "one ", "7-13 years (25-50kg)" elif years < 18: tabs, yage = "one and a half", "14 - 17 years (50-70kg)" else: tabs, yage = "two", "18+ years (70+ kg)" # 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 after %s " " each of Artesunate 50mg and Amodiaquine 150mg is given" % (tabs) else: info["danger"] = "" info["instructions"] = ( "Child is %s. %s each of Artesunate 50mg and Amodiaquine 150mg morning and evening for 3 days" % (yage, tabs) ) # finally build out the messages msg = _( "Patient +%(ref_id)s, %(first_name)s %(last_name)s, %(gender)s/%(age)s (%(guardian)s). Bednet=%(bednet_text)s %(observed)s. Patient has MALARIA%(danger)s." % (info) ) alert = _( "MRDT> Child +%(ref_id)s, %(last_name)s, %(first_name)s, " "%(gender)s/%(months)s (%(location)s) has MALARIA%(danger)s. " "CHW: @%(reporter_alias)s %(reporter_identity)s" % info ) message.respond(msg) message.respond(_(info["instructions"])) """ @todo: enable alerts """ """ recipients = report.get_alert_recipients() for recipient in recipients: message.forward(recipient.mobile, alert) """ log(case, "mrdt_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) reporter = message.persistant_connection.reporter report = ReportMalnutrition(case=case, reporter=reporter, 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) """ @todo enable alerts """ """ 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
def report_birth(self, message, last, first, gender, dob, weight,where, guardian, complications=""): if len(dob) != 6: # There have been cases where a date like 30903 have been sent and # when saved it gives some date that is way off raise HandlerFailed(_("Date must be in the format ddmmyy: %s") % dob) else: 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]) reporter = message.persistant_connection.reporter location = None if not location: if reporter.location: location = reporter.location info = { "first_name" : first.title(), "last_name" : last.title(), "gender" : gender.upper(), "dob" : dob, "guardian" : guardian.title(), "mobile" : "", "reporter" : reporter, "location" : location } abirth = ReportBirth(where=where.upper()) #Perform Location checks if abirth.get_where() is None: raise HandlerFailed(_("Location `%s` is not known. Please try again with a known location") % where) iscase = Case.objects.filter(first_name=info['first_name'], last_name=info['last_name'], reporter=info['reporter'], dob=info['dob']) if iscase: 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 %(provider)s.") % info) # TODO: log this message case = iscase[0] else: case = Case(**info) case.save() log(case, "patient_created") info.update({ "id": case.ref_id, "last_name": last.upper(), "age": case.age(), "dob": dob.strftime("%d/%m/%y") }) info2 = { "case":case, "weight": weight, "where": where, "reporter": reporter, "complications": complications } #check if birth has already been reported rbirth = ReportBirth.objects.filter(case=case) if rbirth: raise HandlerFailed(_( "The birth of %(last_name)s, %(first_name)s (+%(PID)s) has already been reported by %(reporter)s.") % info) abirth = ReportBirth(**info2) abirth.save() info.update({"where":abirth.get_where()}) message.respond(_( "Birth +%(id)s: %(last_name)s, %(first_name)s %(gender)s/%(dob)s " + "(%(guardian)s) %(location)s at %(where)s") % info) return True
def diagnosis(self, message, ref_id, text): case = self.find_case(ref_id) reporter = message.persistant_connection.reporter 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, reporter=reporter, 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) # 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 reporter != case.reporter: # there's a different provider info = {"ref_id":ref_id, "instructions":(", ".join(instructions))} message.forward(case.reporter.connection().identity, "D> +%(ref_id)s %(instructions)s" % info) log(case, "diagnosis_taken") return True