Example #1
0
 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
Example #2
0
    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
Example #3
0
    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
Example #4
0
    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
Example #5
0
    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
Example #6
0
File: app.py Project: eliane/mctc
 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
Example #7
0
File: app.py Project: eliane/mctc
    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
Example #8
0
 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
Example #9
0
 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
Example #10
0
File: app.py Project: eliane/mctc
    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
Example #11
0
    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
Example #12
0
    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
Example #13
0
    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
Example #14
0
            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 " +
Example #15
0
    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
Example #16
0
    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        
Example #17
0
    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