Example #1
0
def report_chooser(request, report_type, period_type,
                   period_str=None, export=False):

    if not report_type in ('children', 'maternal', 'commodities'):
        raise Http404(u"Invalid report type")

    if (not period_type in ('monthly', 'annual', 'quarterly', 'weekly')
        or (report_type == 'commodities' and period_type == 'weekly')):
        raise Http404(u"Invalid period type")

    # web views and export views are named the same.
    # difference is the _export suffix.
    func_suffix = '_export' if export else ''

    try:
        view = import_path('unfpa_web.views.%(report_type)s.'
                           '%(period_type)s_%(report_type)s%(suffix)s'
                           % {'report_type': report_type,
                              'period_type': period_type,
                              'suffix': func_suffix})
    except:
        raise Http404(u"Incorrect URL.")

    try:
        if '-' in period_str:
            indice, year = period_str.split('-')
            indice = int(indice)
            year = int(year)
        else:
            indice = None
            year = int(period_str)
    except:
        raise Http404(u"Incorrect period.")

    if period_type == 'weekly':
        period = WeekPeriod.find_create_by_weeknum(year, indice)
    elif period_type == 'monthly':
        period = MonthPeriod.find_create_from(year, month=indice)
    elif period_type == 'quarterly':
        period = QuarterPeriod.find_create_by_quarter(year, indice)
    elif period_type == 'annual':
        period = YearPeriod.find_create_from(year)
    else:
        # default period is current Month
        period = MonthPeriod.find_create_by_date(date.today())

    return view(request, period)
Example #2
0
    def create_report(self, author):
        """ creates and save a MalariaReport based on current data_browser

        No check nor validation is performed """
        period = MonthPeriod.find_create_from(year=self.get('year'), \
                                              month=self.get('month'))
        entity = Entity.objects.get(slug=self.get('hc'), type__slug='cscom')
        report = MalariaReport.start(period, entity, author, \
                                     type=MalariaReport.TYPE_SOURCE)

        report.add_underfive_data(*self.data_for_cat('u5'))
        report.add_overfive_data(*self.data_for_cat('o5'))
        report.add_pregnantwomen_data(*self.data_for_cat('pw'))
        report.add_stockout_data(*self.data_for_cat('so'))
        with reversion.create_revision():
            report.save()
            reversion.set_user(author.user)
            #report.save()

        return report
Example #3
0
def unfpa_monthly_product_stockouts(message, args, sub_cmd, **kwargs):
    """  Incomming:
            fnuap mps family_planning delivery_services male_condom
            female_condom oral_pills injectable iud implants
            female_sterilization male_sterilization
            amoxicillin_ij amoxicillin_cap_gel
            amoxicillin_suspension azithromycine_tab
            azithromycine_suspension benzathine_penicillin cefexime
            clotrimazole ergometrine_tab ergometrine_vials iron
            folate iron_folate magnesium_sulfate metronidazole
            oxytocine ceftriaxone_500 ceftriaxone_1000 comment
        example:
           'fnuap mps 2012 05 wolo 0 0 20 - - - - - 0 0 - - - - - - - - - - - -
             - - - - - - -'
        Outgoing:
            [SUCCES] Le rapport de name a ete enregistre.
            or [ERREUR] message """

    try:
        # -1 represente le non disponible
        args = args.replace("-", "-1")
        reporting_year, reporting_month, location_of_sdp, family_planning, \
        delivery_services, male_condom, female_condom,\
        oral_pills, injectable, iud, implants, female_sterilization, \
        male_sterilization, amoxicillin_ij, amoxicillin_cap_gel, \
        amoxicillin_suspension, azithromycine_tab, azithromycine_suspension, \
        benzathine_penicillin, cefexime, clotrimazole, ergometrine_tab, \
        ergometrine_vials, iron, folate, iron_folate, magnesium_sulfate, \
        metronidazole, oxytocine, ceftriaxone_500, ceftriaxone_1000, \
        comment = args.split()
    except:
        return resp_error(message, u"le rapport")

    try:
        period = MonthPeriod.find_create_from(year=int(reporting_year),
                                              month=int(reporting_month))
    except:
        message.respond(u"La periode (%s %s) n'est pas valide" %
                        (reporting_month, reporting_year))
        return True

    if period != current_period().previous():
        message.respond(u"La periode (%s %s) n'est pas valide, "
                        u"elle doit etre %s" % (reporting_month,
                                                reporting_year,
                                                current_period().previous()))
        return True

    # Entity code
    try:
        entity = Entity.objects.get(slug=location_of_sdp)
    except Entity.DoesNotExist:
        message.respond(u"Le code %s n'existe pas" % location_of_sdp)
        return True

    def check_int(val):
        try:
            return int(val)
        except:
            return -1

    try:
        comment = comment.replace(u"_", u" ")
    except:
        comment = u""

    contact = contact_for(message.identity)

    report = RHCommoditiesReport()

    if contact:
        report.created_by = contact
    else:
        return resp_error_provider(message)

    report.type = 0
    report.period = period
    report.entity = entity
    report.family_planning = check_int(family_planning)
    report.delivery_services = check_int(delivery_services)
    report.male_condom = check_int(male_condom)
    report.female_condom = check_int(female_condom)
    report.oral_pills = check_int(oral_pills)
    report.injectable = check_int(injectable)
    report.iud = check_int(iud)
    report.implants = check_int(implants)
    report.female_sterilization = YESNOAVAIL.get(female_sterilization,
                                    RHCommoditiesReport.SUPPLIES_NOT_PROVIDED)
    report.male_sterilization = YESNOAVAIL.get(male_sterilization,
                                    RHCommoditiesReport.SUPPLIES_NOT_PROVIDED)
    report.amoxicillin_ij = check_int(amoxicillin_ij)
    report.amoxicillin_cap_gel = check_int(amoxicillin_cap_gel)
    report.amoxicillin_suspension = check_int(amoxicillin_suspension)
    report.azithromycine_tab = check_int(azithromycine_tab)
    report.azithromycine_suspension = check_int(azithromycine_suspension)
    report.benzathine_penicillin = check_int(benzathine_penicillin)
    report.cefexime = check_int(cefexime)
    report.clotrimazole = check_int(clotrimazole)
    report.ergometrine_tab = check_int(ergometrine_tab)
    report.ergometrine_vials = check_int(ergometrine_vials)
    report.iron = check_int(iron)
    report.folate = check_int(folate)
    report.iron_folate = check_int(iron_folate)
    report.magnesium_sulfate = check_int(magnesium_sulfate)
    report.metronidazole = check_int(metronidazole)
    report.oxytocine = check_int(oxytocine)

    report.ceftriaxone_500 = check_int(ceftriaxone_500)
    report.ceftriaxone_1000 = check_int(ceftriaxone_1000)
    report.comment = check_int(comment)
    report._status = report.STATUS_VALIDATED

    try:
        report.save()
        message.respond(u"[SUCCES] Le rapport de %(cscom)s pour %(period)s "
                        u"a ete enregistre. "
                        u"Le No de recu est #%(receipt)s."
                        % {'cscom': report.entity.display_full_name(),
                           'period': report.period,
                           'receipt': report.receipt})
    except IntegrityError:
        message.respond(u"[ERREUR] il ya deja un rapport pour cette periode")
    except:
        message.respond(u"[ERREUR] Le rapport n est pas enregiste")

    return True
Example #4
0
    def validate(self):
        """ Test whether attached data matches PNLP's logic requirements """

        no_more_than_text = _("%(field2)s (%(f2value)d) can't be more " \
                            "than %(field1)s (%(f1value)d)")
        allcats = ('u5', 'o5', 'pw')
        noo5cat = ('u5', 'pw')
        nopwcat = ('u5', 'o5')

        def test_value_under(fieldref, fieldtest, cats):
            for cat in cats:
                try:
                    dic = {'field2': self.field_name('%s_%s' \
                                                     % (cat, fieldtest)), \
                           'f2value': self.get('%s_%s' % (cat, fieldtest)), \
                           'field1': self.field_name('%s_%s' \
                                                     % (cat, fieldref)), \
                           'f1value': self.get('%s_%s' % (cat, fieldref))}
                    if dic['f1value'] < dic['f2value']:
                        self.errors.add(no_more_than_text % dic, cat)
                except MissingData:
                    # this missing data should have already been reported
                    pass

        # total > malaria cases
        test_value_under('total_consultation_all_causes', \
                         'total_suspected_malaria_cases', allcats)

        # total >  malaria simple
        test_value_under('total_consultation_all_causes', \
                         'total_simple_malaria_cases', nopwcat)

        # total >  malaria severe
        test_value_under('total_consultation_all_causes', \
                         'total_severe_malaria_cases', allcats)

        # suspected > malaria simple
        test_value_under('total_suspected_malaria_cases', \
                         'total_simple_malaria_cases', nopwcat)

        # suspected > malaria severe
        test_value_under('total_suspected_malaria_cases', \
                         'total_severe_malaria_cases', allcats)

        # suspected > malaria tested
        test_value_under('total_suspected_malaria_cases', \
                         'total_tested_malaria_cases', allcats)

        # suspected > malaria confirmed
        test_value_under('total_suspected_malaria_cases', \
                         'total_confirmed_malaria_cases', allcats)

        # suspected > simple + severe
        for cat in nopwcat:
            try:
                dic = {'field2': _(u"%(simple)s + %(severe)s") % {'simple': \
                      self.field_name('%s_total_simple_malaria_cases' % cat), \
                      'severe': \
                     self.field_name('%s_total_severe_malaria_cases' % cat)}, \
                      'f2value': int(self.get('%s_total_simple_malaria_cases' \
                                              % cat)) \
                               + int(self.get('%s_total_severe_malaria_cases' \
                                              % cat)), \
                      'field1': \
                           self.field_name('%s_total_suspected_malaria_cases' \
                                           % cat), \
                      'f1value': self.get('%s_total_suspected_malaria_cases' \
                                           % cat)}
                if dic['f1value'] < dic['f2value']:
                    self.errors.add(no_more_than_text % dic, cat)
            except MissingData:
                pass

        # confirmed > simple + severe
        for cat in nopwcat:
            try:
                dic = {'field2': _(u"%(simple)s + %(severe)s") % {'simple': \
                      self.field_name('%s_total_simple_malaria_cases' % cat), \
                      'severe': \
                     self.field_name('%s_total_severe_malaria_cases' % cat)}, \
                      'f2value': int(self.get('%s_total_simple_malaria_cases' \
                                              % cat)) \
                               + int(self.get('%s_total_severe_malaria_cases' \
                                              % cat)), \
                      'field1': \
                           self.field_name('%s_total_confirmed_malaria_cases' \
                                           % cat), \
                      'f1value': self.get('%s_total_confirmed_malaria_cases' \
                                           % cat)}
                if dic['f1value'] < dic['f2value']:
                    self.errors.add(no_more_than_text % dic, cat)
            except MissingData:
                pass

        # tested > confirmed
        test_value_under('total_tested_malaria_cases', \
                         'total_confirmed_malaria_cases', allcats)

        # tested > ACT
        test_value_under('total_tested_malaria_cases', \
                         'total_treated_malaria_cases', allcats)

        # confirmed > act
        test_value_under('total_confirmed_malaria_cases', \
                         'total_treated_malaria_cases', allcats)

        # total inpatient > malaria inpatient
        test_value_under('total_inpatient_all_causes', \
                         'total_malaria_inpatient', allcats)

        # total death > malaria death
        test_value_under('total_death_all_causes', \
                         'total_malaria_death', allcats)

        # PERIOD MONTH
        # range(1, 12)
        # already handled.

        # PERIOD YEAR
        # range(2010, 2020)
        # already handled

        # NO FUTURE
        if self.get('year') >= date.today().year \
           and self.get('month') >= date.today().month:
            self.errors.add(_(u"The period of data (%(period)s) " \
                            "is in the future.") % \
                            {'period': u"%s %d" % \
                                       (self.get('month').__str__().zfill(2), \
                                        self.get('year'))}, 'period')

        # NO PAST
        period = MonthPeriod.find_create_from(year=self.get('year'), \
                                                  month=self.get('month'))

        if self.options.is_editing:
            if self.options.level == 'district':
                time_over = time_district_over
            elif self.options.level == 'region':
                time_over = time_region_over
            else:
                time_over = time_cscom_over
        else:
            time_over = time_cscom_over

        if time_over(period) and not self.options.bulk_import:
            self.errors.add(_(u"The reporting time frame for that " \
                              "period (%(period)s) is over.") \
                            % {'period': period}, 'period')

        # DATE DAY / MONTH / YEAR
        try:
            date(self.get('fillin_year'), \
                 self.get('fillin_month'), self.get('fillin_day'))
        except ValueError:
            self.errors.add(_(u"The fillin day (%(day)s) is out of range " \
                            "for that month (%(month)s)") \
                            % {'day': \
                                   self.get('fillin_day').__str__().zfill(2), \
                               'month': \
                                self.get('fillin_month').__str__().zfill(2)}, \
                               'fillin')

        # REPORTER NAME
        pass

        # ENTITY
        try:
            entity = Entity.objects.get(slug=self.get('hc'), \
                                        type__slug='cscom')
        except Entity.DoesNotExist:
            entity = None
            self.errors.add(_(u"The entity code (%(code)s) does not " \
                              "match any HC.") % {'code': \
                                                  self.get('hc')}, 'period')

        # NO DUPLICATE
        if not self.options.data_only:
            period = MonthPeriod.find_create_from(year=self.get('year'), \
                                                  month=self.get('month'))
            if entity \
            and MalariaReport.objects.filter(entity=entity, \
                                             period=period).count() > 0:
                report = MalariaReport.objects.get(entity=entity,
                                                   period=period)
                self.errors.add(_(u"There is already a report for " \
                                  "that HC (%(entity)s) and that " \
                                  "period (%(period)s)") % \
                                  {'entity': entity.display_full_name(), \
                                   'period': period.name()}
                                   + u" Recu: %s." % report.receipt, 'period')

        # User can create such report
        if self.options.author:
            if not provider_can('can_submit_report', \
                                self.options.author, entity) \
               and not self.options.bulk_import:
                self.errors.add(_(u"You don't have permission to send " \
                                  "a report for that " \
                                  "location (%(loc)s).") \
                                % {'loc': entity.display_full_name()})
Example #5
0
def nut_report_update(message, args, sub_cmd, **kwargs):
    """ Client sent an update to an existing report

    Only the modified fields are sent.
    Each section is coded accoding to report codes.
    All fields are coded according to nutrsc.

    > nut report-update rgaudin -1355030878 0112  #P &SAM 1d:2 "
      1h:2 1l6:2 #C &MAM a0:100 #T v:1 w:0 u:0-EOM-"""

    def resp_error(code, msg):
        # make sure we cancel whatever addition
        message.respond(u"nut report-update error %(code)s|%(msg)s" \
                        % {'code': code, 'msg': msg})
        return True

    def provider_entity(provider):
        """ Entity a Provider is attached to """
        try:
            return NUTEntity.objects.get(id=provider.first_access().target.id)
        except:
            return None

    # check that all parts made it together
    if not args.strip().endswith('-eom-'):
        return resp_error('BAD_FORM', REPORT_ERRORS['BAD_FORM'])
    else:
        args = args.strip()[:-5].strip()

    # split up sections
    sections = {}
    try:
        parts = args.strip().lower().split('#')
        for index in range(0, len(parts)):
            if index == 0:
                infos = parts[index]
            else:
                sections[parts[index][0].upper()] = parts[index][1:]
        pec_sec = sections.get('P', '').strip()
        cons_sec = sections.get('C', '').strip()
        order_sec = sections.get('O', '').strip()
        other_sec = sections.get('T', '').strip()
    except:
        return resp_error('BAD_FORM', REPORT_ERRORS['BAD_FORM'])

    # split up infos
    try:
        username, pwhash, date_str = infos.strip().split()
    except:
        return resp_error('BAD_FORM_INFO', REPORT_ERRORS['BAD_FORM_INFO'])

    # get Provider based on username
    try:
        provider = Provider.objects.get(user__username=username)
    except Provider.DoesNotExist:
        return resp_error('NO_ACC', REPORT_ERRORS['NO_ACC'])

    # check that provider pwhash is good
    if not provider.check_hash(pwhash):
        return resp_error('BAD_PASS', REPORT_ERRORS['BAD_PASS'])

    # check that user is not disabled
    if not provider.is_active:
        return resp_error('ACC_DIS', REPORT_ERRORS['ACC_DIS'])

    # check that user has permission to submit report on entity
    entity = provider_entity(provider)

    if not entity:
        return resp_error('NOT_ENT', REPORT_ERRORS['NOT_ENT'])

    eentity = Entity.objects.get(id=entity.id)
    if not provider_can('can_submit_report', provider, eentity):
        return resp_error('NO_PERM', REPORT_ERRORS['NO_PERM'])

    # parse date and check if period is valid
    try:
        month = int(date_str[0:2])
        year = int('%s%s' % ('20', date_str[2:4]))
        period = MonthPeriod.find_create_from(year=year, month=month)
    except:
        return resp_error('BAD_FORM_PERIOD', REPORT_ERRORS['BAD_FORM_PERIOD'])

    # check period is the one we want
    if not period == current_reporting_period():
        return resp_error('BAD_PERIOD', REPORT_ERRORS['BAD_PERIOD'])

    # global infos
    infos = {'entity': entity,
             'eentity': eentity,
             'provider': provider,
             'month': month,
             'year': year,
             'period': period,
             'username': username,
             'pwhash': pwhash}

    # Retrieve report
    try:
        nut_report = NutritionReport.objects.get(period=infos['period'],
                                                 entity=infos['entity'],
                                                 type=Report.TYPE_SOURCE)
    except:
        return resp_error('MISS', REPORT_ERRORS['MISS'])

    reports = []
    # common start of error message
    error_start = u"Impossible d'enregistrer le rapport. "

    logger.info("Processing PEC")

    if pec_sec:
        subs = pec_sec.split('&')
        subs = subs[1:]
        for sub in subs:
            fields = sub.split()
            cap = fields[0].lower()
            sub_report = getattr(nut_report, 'pec_%s_report' % cap)
            for field in fields[1:]:
                cfield, value = field.split(':')
                rfield = uncompress_pec_field(cfield)
                setattr(sub_report, rfield, int(value))
            validator = PECReportValidator(sub_report)
            validator.errors.reset()
            try:
                validator.validate()
            except AttributeError as e:
                return resp_error('PEC_%s' % cap.upper(),
                                  error_start + e.__str__())
            except:
                pass
            errors = validator.errors
            # return first error to user
            if errors.count() > 0:
                return resp_error('PEC_%s' % cap.upper(),
                                  error_start + errors.all()[0])
            else:
                reports.append(sub_report)

    logger.info("Processing CONS")

    if cons_sec:
        subs = cons_sec.split('&')
        subs = subs[1:]
        for sub in subs:
            fields = sub.split()
            cap = fields[0].lower()
            logger.info(cap.upper())
            for field in fields[1:]:
                cfield, value = field.split(':')
                rinpc, rfield = uncompress_cons_field(cfield)
                sub_report = getattr(getattr(nut_report, 
                                             'cons_%s_report' % cap),
                                     'icr')(rinpc)
                setattr(sub_report, rfield, int(value))
                if sub_report.valid and not sub_report in reports:
                    reports.append(sub_report)

    logger.info("Processing ORDER")

    if order_sec:
        subs = order_sec.split('&')
        subs = subs[1:]
        for sub in subs:
            logger.info("\t%s" % sub)
            fields = sub.split()
            cap = fields[0].lower()
            for field in fields[1:]:
                cfield, value = field.split(':')
                rinpc, rfield = uncompress_cons_field(cfield)
                sub_report = getattr(getattr(nut_report,
                                             'order_%s_report' % cap),
                                     'icr')(rinpc)
                setattr(sub_report, rfield, int(value))
                if not sub_report in reports:
                    reports.append(sub_report)

    logger.info("Processing OTHER")

    if other_sec:
        fields = other_sec.split()
        for field in fields[1:]:
            cfield, value = field.split(':')
            rfield = uncompress_pec_field(cfield)
            sub_report = nut_report.pec_other_report
            setattr(sub_report, rfield, int(value))
        # check validity relative to PEC
        if not sub_report.total == sub_report.nut_report.sum_all_other:
            return resp_error('OTHER_INT', REPORT_ERRORS['OTHER_INT'])
        else:
            reports.append(sub_report)


    # check validity of changes
    # save to DB
    @reversion.create_revision()
    @transaction.commit_manually
    def save_reports(reports, nut_report, provider=None):
        reversion.set_user(provider.user)
        reversion.set_comment("SMS report update")
        for report in reports:
            print("saving %s" % report)
            try:
                sub_report.save()
            except:
                transaction.rollback()
                return False
        try:
            nut_report._status = nut_report.STATUS_MODIFIED_AUTHOR
            nut_report.modified_by = provider
            nut_report.save()
        except:
            transaction.rollback()
            return False

        transaction.commit()
        return True

    logger.info("Saving reports")
    if not save_reports(reports, nut_report, provider):
        logger.warning("Unable to save reports")
        return resp_error('SRV', REPORT_ERRORS['SRV'])
    logger.info("Reports saved")

    ## CONFIRM RESPONSE
    
    confirm = "nut report-update ok %s" % nut_report.receipt

    message.respond(confirm)
    return True
Example #6
0
    def validate(self):
        """ Test whether attached data matches PNLP's logic requirements """

        no_more_than_text = _("%(field2)s (%(f2value)d) can't be more " \
                            "than %(field1)s (%(f1value)d)")
        allcats = ('u5', 'o5', 'pw')
        noo5cat = ('u5', 'pw')
        nopwcat = ('u5', 'o5')

        def test_value_under(fieldref, fieldtest, cats):
            for cat in cats:
                try:
                    dic = {'field2': self.field_name('%s_%s' \
                                                     % (cat, fieldtest)), \
                           'f2value': self.get('%s_%s' % (cat, fieldtest)), \
                           'field1': self.field_name('%s_%s' \
                                                     % (cat, fieldref)), \
                           'f1value': self.get('%s_%s' % (cat, fieldref))}
                    if dic['f1value'] < dic['f2value']:
                        self.errors.add(no_more_than_text % dic, cat)
                except MissingData:
                    # this missing data should have already been reported
                    pass

        # total > malaria cases
        test_value_under('total_consultation_all_causes', \
                         'total_suspected_malaria_cases', allcats)

        # total >  malaria simple
        test_value_under('total_consultation_all_causes', \
                         'total_simple_malaria_cases', nopwcat)

        # total >  malaria severe
        test_value_under('total_consultation_all_causes', \
                         'total_severe_malaria_cases', allcats)

        # suspected > malaria simple
        test_value_under('total_suspected_malaria_cases', \
                         'total_simple_malaria_cases', nopwcat)

        # suspected > malaria severe
        test_value_under('total_suspected_malaria_cases', \
                         'total_severe_malaria_cases', allcats)

        # suspected > malaria tested
        test_value_under('total_suspected_malaria_cases', \
                         'total_tested_malaria_cases', allcats)

        # suspected > malaria confirmed
        test_value_under('total_suspected_malaria_cases', \
                         'total_confirmed_malaria_cases', allcats)

        # suspected > simple + severe
        for cat in nopwcat:
            try:
                dic = {'field2': _(u"%(simple)s + %(severe)s") % {'simple': \
                      self.field_name('%s_total_simple_malaria_cases' % cat), \
                      'severe': \
                     self.field_name('%s_total_severe_malaria_cases' % cat)}, \
                      'f2value': int(self.get('%s_total_simple_malaria_cases' \
                                              % cat)) \
                               + int(self.get('%s_total_severe_malaria_cases' \
                                              % cat)), \
                      'field1': \
                           self.field_name('%s_total_suspected_malaria_cases' \
                                           % cat), \
                      'f1value': self.get('%s_total_suspected_malaria_cases' \
                                           % cat)}
                if dic['f1value'] < dic['f2value']:
                    self.errors.add(no_more_than_text % dic, cat)
            except MissingData:
                pass

        # confirmed > simple + severe
        for cat in nopwcat:
            try:
                dic = {'field2': _(u"%(simple)s + %(severe)s") % {'simple': \
                      self.field_name('%s_total_simple_malaria_cases' % cat), \
                      'severe': \
                     self.field_name('%s_total_severe_malaria_cases' % cat)}, \
                      'f2value': int(self.get('%s_total_simple_malaria_cases' \
                                              % cat)) \
                               + int(self.get('%s_total_severe_malaria_cases' \
                                              % cat)), \
                      'field1': \
                           self.field_name('%s_total_confirmed_malaria_cases' \
                                           % cat), \
                      'f1value': self.get('%s_total_confirmed_malaria_cases' \
                                           % cat)}
                if dic['f1value'] < dic['f2value']:
                    self.errors.add(no_more_than_text % dic, cat)
            except MissingData:
                pass

        # tested > confirmed
        test_value_under('total_tested_malaria_cases', \
                         'total_confirmed_malaria_cases', allcats)

        # tested > ACT
        test_value_under('total_tested_malaria_cases', \
                         'total_treated_malaria_cases', allcats)

        # confirmed > act
        test_value_under('total_confirmed_malaria_cases', \
                         'total_treated_malaria_cases', allcats)

        # total inpatient > malaria inpatient
        test_value_under('total_inpatient_all_causes', \
                         'total_malaria_inpatient', allcats)

        # total death > malaria death
        test_value_under('total_death_all_causes', \
                         'total_malaria_death', allcats)

        # PERIOD MONTH
        # range(1, 12)
        # already handled.

        # PERIOD YEAR
        # range(2010, 2020)
        # already handled

        # NO FUTURE
        if self.get('year') >= date.today().year \
           and self.get('month') >= date.today().month:
            self.errors.add(_(u"The period of data (%(period)s) " \
                            "is in the future.") % \
                            {'period': u"%s %d" % \
                                       (self.get('month').__str__().zfill(2), \
                                        self.get('year'))}, 'period')

        # NO PAST
        period = MonthPeriod.find_create_from(year=self.get('year'), \
                                                  month=self.get('month'))

        if self.options.is_editing:
            if self.options.level == 'district':
                time_over = time_district_over
            elif self.options.level == 'region':
                time_over = time_region_over
            else:
                time_over = time_cscom_over
        else:
            time_over = time_cscom_over

        if time_over(period) and not self.options.bulk_import:
            self.errors.add(_(u"The reporting time frame for that " \
                              "period (%(period)s) is over.") \
                            % {'period': period}, 'period')

        # DATE DAY / MONTH / YEAR
        try:
            date(self.get('fillin_year'), \
                 self.get('fillin_month'), self.get('fillin_day'))
        except ValueError:
            self.errors.add(_(u"The fillin day (%(day)s) is out of range " \
                            "for that month (%(month)s)") \
                            % {'day': \
                                   self.get('fillin_day').__str__().zfill(2), \
                               'month': \
                                self.get('fillin_month').__str__().zfill(2)}, \
                               'fillin')

        # REPORTER NAME
        pass

        # ENTITY
        try:
            entity = Entity.objects.get(slug=self.get('hc'), \
                                        type__slug='cscom')
        except Entity.DoesNotExist:
            entity = None
            self.errors.add(_(u"The entity code (%(code)s) does not " \
                              "match any HC.") % {'code': \
                                                  self.get('hc')}, 'period')

        # NO DUPLICATE
        if not self.options.data_only:
            period = MonthPeriod.find_create_from(year=self.get('year'), \
                                                  month=self.get('month'))
            if entity \
            and MalariaReport.objects.filter(entity=entity, \
                                             period=period).count() > 0:
                report = MalariaReport.objects.get(entity=entity, period=period)
                self.errors.add(_(u"There is already a report for " \
                                  "that HC (%(entity)s) and that " \
                                  "period (%(period)s)") % \
                                  {'entity': entity.display_full_name(), \
                                   'period': period.name()}
                                   + u" Recu: %s." % report.receipt, 'period')

        # User can create such report
        if self.options.author:
            if not provider_can('can_submit_report', \
                                self.options.author, entity) \
               and not self.options.bulk_import:
                self.errors.add(_(u"You don't have permission to send " \
                                  "a report for that " \
                                  "location (%(loc)s).") \
                                % {'loc': entity.display_full_name()})
Example #7
0
def palu(message):

    # common start of error message
    error_start = u"Impossible d'enregistrer le rapport. "

    # create variables from text messages.
    try:
        args_names = ['kw1', 'username', 'password', 'month', 'year', \
        'u5_total_consultation_all_causes', \
        'u5_total_suspected_malaria_cases', \
        'u5_total_simple_malaria_cases', \
        'u5_total_severe_malaria_cases', \
        'u5_total_tested_malaria_cases', \
        'u5_total_confirmed_malaria_cases', \
        'u5_total_treated_malaria_cases', \
        'u5_total_inpatient_all_causes', \
        'u5_total_malaria_inpatient', \
        'u5_total_death_all_causes', \
        'u5_total_malaria_death', \
        'u5_total_distributed_bednets', \
        'o5_total_consultation_all_causes', \
        'o5_total_suspected_malaria_cases', \
        'o5_total_simple_malaria_cases', \
        'o5_total_severe_malaria_cases', \
        'o5_total_tested_malaria_cases', \
        'o5_total_confirmed_malaria_cases', \
        'o5_total_treated_malaria_cases', \
        'o5_total_inpatient_all_causes', \
        'o5_total_malaria_inpatient', \
        'o5_total_death_all_causes', \
        'o5_total_malaria_death', \
        'pw_total_consultation_all_causes', \
        'pw_total_suspected_malaria_cases', \
        'pw_total_severe_malaria_cases', \
        'pw_total_tested_malaria_cases', \
        'pw_total_confirmed_malaria_cases', \
        'pw_total_treated_malaria_cases', \
        'pw_total_inpatient_all_causes', \
        'pw_total_malaria_inpatient', \
        'pw_total_death_all_causes', \
        'pw_total_malaria_death', \
        'pw_total_distributed_bednets', \
        'pw_total_anc1', \
        'pw_total_sp1', \
        'pw_total_sp2', \
        'stockout_act_children', 'stockout_act_youth', 'stockout_act_adult', \
        'stockout_artemether', 'stockout_quinine', 'stockout_serum', \
        'stockout_bednet', 'stockout_rdt', 'stockout_sp']
        args_values = message.content.strip().lower().split()
        arguments = dict(zip(args_names, args_values))
    except ValueError:
        # failure to split means we proabably lack a data or more
        # we can't process it.
        message.respond(error_start + u" Le format du SMS est incorrect.")
        return True

    # convert form-data to int or bool respectively
    try:
        for key, value in arguments.items():
            if key.split('_')[0] in ('u5', 'o5', 'pw', 'month', 'year'):
                arguments[key] = int(value)
            if key.split('_')[0] == 'stockout':
                arguments[key] = MalariaReport.YES if bool(int(value)) \
                                                   else MalariaReport.NO
    except:
        raise
        # failure to convert means non-numeric value which we can't process.
        message.respond(error_start + u" Les données sont malformées.")
        return True

    # check credentials
    try:
        provider = Provider.active.get(user__username=arguments['username'])
    except Provider.DoesNotExist:
        message.respond(error_start + u"Ce nom d'utilisateur " +
                                      u"(%s) n'existe pas." % \
                                      arguments['username'])
        return True
    if not provider.check_password(arguments['password']):
        message.respond(error_start + u"Votre mot de passe est incorrect.")
        return True

    # now we have well formed and authenticated data.
    # let's check for business-logic errors.

    # create a data holder for validator
    data_browser = MalariaDataHolder()

    # feed data holder with sms provided data
    for key, value in arguments.items():
        if key.split('_')[0] in ('u5', 'o5', 'pw', \
                                 'stockout', 'year', 'month'):
            data_browser.set(key, value)

    # feed data holder with guessable data
    try:
        hc = entity_for(provider).slug
    except:
        hc = None
    data_browser.set('hc', hc)
    today = datetime.date.today()
    data_browser.set('fillin_day', today.day)
    data_browser.set('fillin_month', today.month)
    data_browser.set('fillin_year', today.year)
    data_browser.set('author', provider.name())

    # create validator and fire
    validator = MalariaReportValidator(data_browser)
    validator.errors.reset()
    try:
        validator.validate()
    except AttributeError as e:
        message.respond(error_start + e.__str__())
        return True
    errors = validator.errors

    # return first error to user
    if errors.count() > 0:
        message.respond(error_start + errors.all()[0])
        return True

    # create the report
    try:
        period = MonthPeriod.find_create_from(year=data_browser.get('year'), \
                                              month=data_browser.get('month'))
        entity = Entity.objects.get(slug=data_browser.get('hc'), \
                                    type__slug='cscom')
        report = MalariaReport.start(period, entity, provider, \
                                     type=MalariaReport.TYPE_SOURCE)

        report.add_underfive_data(*data_browser.data_for_cat('u5'))
        report.add_overfive_data(*data_browser.data_for_cat('o5'))
        report.add_pregnantwomen_data(*data_browser.data_for_cat('pw'))
        report.add_stockout_data(*data_browser.data_for_cat('so'))
        #report.save()
        with reversion.create_revision():
            report.save()
            reversion.set_user(provider.user)

    except Exception as e:
        message.respond(error_start + u"Une erreur technique s'est " \
                        u"produite. Reessayez plus tard et " \
                        u"contactez ANTIM si le probleme persiste.")
        logger.error(u"Unable to save report to DB. Message: %s | Exp: %r" \
                     % (message.content, e))
        return True

    message.respond(u"[SUCCES] Le rapport de %(cscom)s pour %(period)s "
                    u"a ete enregistre. " \
                    u"Le No de recu est #%(receipt)s." \
                    % {'cscom': report.entity.display_full_name(), \
                       'period': report.period, \
                       'receipt': report.receipt})
    try:
        to = contact_for(report.entity.parent).phone_number
    except:
        to = None
    if not to:
        return True
    send_sms(to, u"[ALERTE] Le CSCom %(cscom)s vient d'envoyer le " \
                 u"rapport #%(receipt)s pour %(period)s." \
                 % {'cscom': report.entity.display_full_name(), \
                    'period': report.period, \
                    'receipt': report.receipt})
    return True
Example #8
0
def data_browser(request, entity_code=None, period_str=None):
    context = {'category': 'raw_data'}
    web_provider = request.user.get_profile()

    root = web_provider.first_target()

    period = None
    entity = None

    # find period from string or default to current reporting
    if period_str:
        try:
            period = MonthPeriod.find_create_from(year=int(period_str[-4:]), \
                                                  month=int(period_str[:2]), \
                                                  dont_create=True)
        except:
            pass
    if not period:
        period = current_reporting_period()

    # find entity or default to provider target
    # raise 404 on wrong provided entity code
    if entity_code:
        entity = get_object_or_404(Entity, slug=entity_code)

    if not entity:
        entity = web_provider.first_target()
    context.update({'entity': entity})

    # check permissions on this entity and raise 403
    provider_can_or_403('can_view_raw_data', web_provider, entity)

    # build entities browser
    context.update({'root': root, \
                    'paths': entities_path(root, entity)})

    # build periods list
    all_periods = raw_data_periods_for(entity)
    if period_str and not period in all_periods:
        raise Http404(_(u"No report for that period"))

    try:
        # get validated report for that period and location
        report = MalariaReport.validated.get(entity=entity, period=period)
    except MalariaReport.DoesNotExist:
        # district users need to be able to see the generated report
        # which have been created based on their validations/data.
        # if a district is looking at its root district and report exist
        # but not validated, we show it (with period) and no valid flag
        if web_provider.first_role().slug == 'district' and root == entity:
            try:
                report = MalariaReport.unvalidated.get(entity=entity, \
                                                       period=period)
                if not period in all_periods:
                    all_periods.insert(0, period)
            except:
                report = None
        else:
            report = None

    # send period variables to template
    context.update({'periods': [(p.middle().strftime('%m%Y'), p.middle()) \
                                for p in all_periods], \
                    'period': period})

    if report:
        context.update({'report': report})
        form = MalariaReportForm(instance=report)
        context.update({'form': form})
    else:
        context.update({'no_report': True})

    return render(request, 'raw_data.html', context)
Example #9
0
def indicator_browser(request, entity_code=None, period_str=None, \
                    section_index='1', sub_section=None):
    context = {'category': 'indicator_data'}
    web_provider = request.user.get_profile()

    root = web_provider.first_target()

    periods = []
    speriod = eperiod = None
    entity = None
    #section_index = int(section_index) - 1

    # find entity or default to provider target
    # raise 404 on wrong provided entity code
    if entity_code:
        entity = get_object_or_404(Entity, slug=entity_code)

    if not entity:
        entity = web_provider.first_target()
    context.update({'entity': entity})

    # define a list of all possible periods.
    # this is the list of all existing MonthPeriod anterior to current
    def all_anterior_periods(period):
        return MonthPeriod.objects\
                          .filter(start_on__lte=period.start_on)\
                          .order_by('start_on')

    all_periods = all_anterior_periods(current_reporting_period())

    # retrieve Periods from string
    # if period_string include innexistant periods -> 404.
    if period_str:
        speriod_str, eperiod_str = period_str.split('-')
        try:
            speriod = MonthPeriod.find_create_from(
                                                  year=int(speriod_str[-4:]),
                                                  month=int(speriod_str[:2]),
                                                  dont_create=True)
            eperiod = MonthPeriod.find_create_from(
                                                  year=int(eperiod_str[-4:]),
                                                  month=int(eperiod_str[:2]),
                                                  dont_create=True)

            # loop on Period.next() from start one to end one.
            period = speriod
            while period.middle() <= eperiod.middle():
                periods.append(period)
                period = period.next()
        except:
            raise Http404(_(u"Requested period interval (%(period_str)s) "
                            u"includes inexistant periods.")
                          % {'period': period_str})

    # in case user did not request a specific interval
    # default to current_reporting_period
    if not speriod or not eperiod:
        speriod = eperiod = current_reporting_period()
        periods = [speriod]

    # if end period is before start period, redirect to opposite
    if eperiod.middle() < speriod.middle():
        return redirect('indicator_data',
                        entity_code=entity.slug,
                        period_str='%s-%s' % (eperiod.pid, speriod.pid))

    # periods variables
    context.update({'period_str': '%s-%s' % (speriod.pid, eperiod.pid),
                    'speriod': speriod, 'eperiod': eperiod})
    context.update({'periods': [(p.pid, p.middle()) for p in periods],
                    'all_periods': [(p.pid, p.middle()) for p in all_periods]})

    # check permissions on this entity and raise 403
    provider_can_or_403('can_view_indicator_data', web_provider, entity)

    # build entities browser
    context.update({'root': root, \
                    'paths': entities_path(root, entity)})

    # from pnlp_core.indicators import INDICATOR_SECTIONS

    # context.update({'sections': \
    #                 sorted(INDICATOR_SECTIONS.values(), \
    #                       cmp=lambda a, b: int(a['id'].strip('a').strip('b')) \
    #                                     - int(b['id'].strip('a').strip('b')))})

    # try:
    #     section = INDICATOR_SECTIONS[section_index]
    #     if not sub_section:
    #         if len(section['sections']):
    #             sub_section = section['sections'].keys()[0]
    #     sname = 'pnlp_core.indicators.section%s' % section_index.__str__()
    #     if sub_section:
    #         sname = '%s_%s' % (sname, sub_section.__str__())
    #     sm = import_path(sname)
    # except:
    #     raise
    #     raise Http404(_(u"This section does not exist."))

    # section 1 specifics
    if section_index == '1':
        context.update({'contact': contact_for(entity)})

    # context.update({'section': section, 'sub_section': sub_section})

    context.update({'section': {}, 'sub_section': sub_section})

    # context.update({'widgets': [widget(entity=entity, periods=periods) \
    #                             for widget in sm.WIDGETS]})

    return render(request, 'indicator_data.html', context)
Example #10
0
def add_last_period(request):
    """ Add the last period string """

    last_period = MonthPeriod.find_create_by_date(date.today()).previous().middle().strftime('%m-%Y')
    return {'last_period': last_period}
Example #11
0
File: data.py Project: yeleman/nut
def current_period():
    """ Period of current date """
    return MonthPeriod.find_create_by_date(date.today())
Example #12
0
def nut_report(message, args, sub_cmd, **kwargs):

    """ Client sent report for PEC CONS & ORDER

    Once the PEC MAM/SAM/SAM+ & CONS & ORDER is filled, all the data
    is sent via one single multipart SMS.
    SMS is divided in sections and sub sections
    #P #C #O respectively PEC, CONS and ORDER
    We don't combine sections in case we'll have to split message
    in different SMS.
    SMS can be 1000chars+
    Sub sections for capabilities: &MAM, &SAM &SAMP
    Sub sub sections for age break downs |u6 |u59 |o59 |pw |fu1 |fu12

    > nut report rgaudin 89080392890 1111
    #P&MAM|u59 6817 7162 2164 1033 6527 5715 6749 2174 4201
    3675 8412 2331 4868 4765 1896 2107 3457 6308 6238 6589 2432 5983 3871|pw
    6817 7162 2164 1033 6527 5715 6749 2174 4201 3675 8412 2331 4868 4765
    1896 2107 3457 6308 6238 6589 2432 5983 3871|fu12 6817 7162 2164 1033
    6527 5715 6749 2174 4201 3675 8412 2331 4868 4765 1896 2107 3457 6308
    6238 6589 2432 5983 3871&SAM|u59 6817 7162 2164 1033 6527 5715 6749 2174
    4201 3675 8412 2331 4868 4765 1896 2107 3457 6308 6238 6589 2432 5983
    3871|o59 6817 7162 2164 1033 6527 5715 6749 2174 4201 3675 8412 2331 4868
    4765 1896 2107 3457 6308 6238 6589 2432 5983 3871|fu1 6817 7162 2164 1033
    6527 5715 6749 2174 4201 3675 8412 2331 4868 4765 1896 2107 3457 6308
    6238 6589 2432 5983 3871#C&MAM|csb 1199 1199 1199 1199|unimix 1199 1199
    1199 1199|oil 1199 1199 1199 1199|sugar 1199 1199 1199 1199|mil 1199 1199
    1199 1199|niebe 1199 1199 1199 1199&SAM|plumpy 1199 1199 1199
    1199#O&MAM|csb 1199|unimix 1199|oil 1199|sugar 1199|mil 1199|niebe
    1199&SAM|plumpy 1199#T 1 2 3-EOM-
    
    T lwb tb hiv
    < nut report error Error-code | Error Message
    < nut report ok #P$MAM GA1/gao-343-VO5$SAM GA1/gao-343-VO5#C$MAM
    GA1/gao-343-VO5$SAM GA1/gao-343-VO5#O$MAM GA1/gao-343-VO5$SAM
    GA1/gao-343-VO5 """

    def resp_error(code, msg):
        # make sure we cancel whatever addition
        message.respond(u"nut report error %(code)s|%(msg)s" \
                        % {'code': code, 'msg': msg})
        return True

    def provider_entity(provider):
        """ Entity a Provider is attached to """
        try:
            return NUTEntity.objects.get(id=provider.first_access().target.id)
        except:
            return None


    def sub_sections_from_section(section):
        """ Returns an organised hash from raw string

        {'mam': {'u6': 'xx xx xx', 'o59': 'xx xx xx'}, 'sam': {}} """

        subs = section.split('&')
        subs = subs[1:]
        subsh = {}
        for sub in subs:
            sub_data = sub.split('|')
            subh = {}
            for age_line in sub_data[1:]:
                age_ls = age_line.split()
                subh[age_ls[0]] = ' '.join(age_ls[1:])
            subsh[sub_data[0]] = subh
        return subsh

    def check_capabilities(section, entity):
        """ return True if section's subs matches entity cap """
        for cap in ('mam', 'sam', 'samp'):
            if getattr(entity, 'is_%s' % cap):
                if not cap in section.keys():
                    return False
            else:
                if cap in section.keys():
                    return False
        return True

    @reversion.create_revision()
    @transaction.commit_manually
    def save_reports(reports, user=None):
        reversion.set_user(provider.user)
        reversion.set_comment("SMS transmitted report")   
        # save main first
        reports['main'].save()

        for secid, section in reports.items():
            if secid == 'main':
                continue
                      
            for catid, reports in section.items():
                    
                for report in reports:
                    logger.info("%s > %s > %s" \
                                % (secid, catid, report.__class__))
                    try:
                        # HACK: write foreign key id if needed
                        if hasattr(report, 'nut_report_id'):
                            report.nut_report_id = report.nut_report.id

                        if hasattr(report, 'cons_report_id'):
                            report.cons_report_id = report.cons_report.id

                        if hasattr(report, 'order_report_id'):
                            report.order_report_id = report.order_report.id

                        report.save()
                    except Exception as e:
                        logger.error(u"Unable to save report to DB. " \
                                     u"Message: %s | Exp: %r" \
                                     % (message.content, e))
                        transaction.rollback()
                        return False
        transaction.commit()
        return True

    # check that all parts made it together
    if not args.strip().endswith('-eom-'):
        return resp_error('BAD_FORM', REPORT_ERRORS['BAD_FORM'])
    else:
        args = args.strip()[:-5].strip()

    # split up sections
    try:
        infos, pec_sec, cons_sec, order_sec, other_sec = \
                                                 args.strip().lower().split('#')
        pec_sec = pec_sec[1:]
        cons_sec = cons_sec[1:]
        order_sec = order_sec[1:]
        other_sec = other_sec[1:]
    except:
        return resp_error('BAD_FORM', REPORT_ERRORS['BAD_FORM'])

    # split up infos
    try:
        username, pwhash, date_str = infos.strip().split()
    except:
        return resp_error('BAD_FORM_INFO', REPORT_ERRORS['BAD_FORM_INFO'])

    # get Provider based on username
    try:
        provider = Provider.objects.get(user__username=username)
    except Provider.DoesNotExist:
        return resp_error('NO_ACC', REPORT_ERRORS['NO_ACC'])

    # check that provider pwhash is good
    if not provider.check_hash(pwhash):
        return resp_error('BAD_PASS', REPORT_ERRORS['BAD_PASS'])

    # check that user is not disabled
    if not provider.is_active:
        return resp_error('ACC_DIS', REPORT_ERRORS['ACC_DIS'])

    # check that user has permission to submit report on entity
    entity = provider_entity(provider)

    if not entity:
        return resp_error('NOT_ENT', REPORT_ERRORS['NOT_ENT'])

    eentity = Entity.objects.get(id=entity.id)
    if not provider_can('can_submit_report', provider, eentity):
        return resp_error('NO_PERM', REPORT_ERRORS['NO_PERM'])

    # parse date and check if period is valid
    try:
        month = int(date_str[0:2])
        year = int('%s%s' % ('20', date_str[2:4]))
        period = MonthPeriod.find_create_from(year=year, month=month)
    except:
        return resp_error('BAD_FORM_PERIOD', REPORT_ERRORS['BAD_FORM_PERIOD'])

    # check period is the one we want
    if not period == current_reporting_period():
        return resp_error('BAD_PERIOD', REPORT_ERRORS['BAD_PERIOD'])

    # report receipts holder for confirm message
    #report_receipts = {}

    # reports holder for delayed database commit
    reports = {}

    # global infos
    infos = {'entity': entity,
             'eentity': eentity,
             'provider': provider,
             'month': month,
             'year': year,
             'period': period,
             'username': username,
             'pwhash': pwhash}

    # UNIQUENESS
    if NutritionReport.objects.filter(period=infos['period'],
                                      entity=infos['entity'],
                                      type=Report.TYPE_SOURCE).count() > 0:
        return resp_error('UNIQ', REPORT_ERRORS['UNIQ'])

    # create main report
    try:
        period = MonthPeriod.find_create_from(year=year, month=month)
        nut_report = NutritionReport.start(period, entity, provider,
                                           type=Report.TYPE_SOURCE)
        reports['main'] = nut_report
    except Exception as e:
        #raise
        logger.error(u"Unable to save report to DB. Message: %s | Exp: %r" \
                     % (message.content, e))
        return resp_error('SRV', REPORT_ERRORS['SRV'])

    # SECTIONS
    for sid, section in {'P': 'pec', 'C': 'cons',
                         'O': 'order', 'T': 'other'}.items():

        logger.info("Processing %s" % section)

        # extract/split sub sections info from string
        if sid == 'T':
            sec = eval('%s_sec' % section)
        else:
            sec = sub_sections_from_section(eval('%s_sec' % section))

        # check that capabilities correspond to entity
        if sid != 'T' and not check_capabilities(sec, entity):
            return resp_error('BAD_CAP', REPORT_ERRORS['BAD_CAP'])

        # call sub-report section handler
        sec_succ, sec_data = SUB_REPORTS.get(section)(message,
                                                      sec, infos, reports,
                                                      nut_report=nut_report)
        # cancel if sub report failed.
        if not sec_succ:
            logger.warning(u"   FAILED.")
            return resp_error(sec_data[0], sec_data[1])

        # add sub-report to list of reports
        reports[sid] = sec_data
        logger.info("---- Ended %s" % section)
    
    ## DB COMMIT
    
    # create the reports in DB
    # save receipts number
    logger.info("Saving reports")
    if not save_reports(reports, user=provider.user):
        logger.warning("Unable to save reports")
        return resp_error('SRV', REPORT_ERRORS['SRV'])
    logger.info("Reports saved")

    def flatten(iterable):
        values = []

        def add(value):
            if not isinstance(value, (list, dict)):
                values.append(value)
                return True
            return False

        if not add(iterable):
            miterable = iterable.values() if isinstance(iterable, dict) \
                                          else iterable
            for item in miterable:
                values += flatten(item)
        return values

    # for report in flatten(reports):
    #     with reversion.create_revision():
    #         reversion.set_user(provider.user)
    #         reversion.set_comment("SMS transmitted report")
    #         report.save()

    ## CONFIRM RESPONSE
    
    confirm = "nut report ok %s" % nut_report.receipt

    message.respond(confirm)
    return True

    ## TRIGGER ALERT
    
    """
Example #13
0
def data_browser(request, entity_code=None, period_str=None):
    context = {'category': 'raw_data'}
    web_provider = request.user.get_profile()

    root = web_provider.first_target()

    period = None
    entity = None

    # find period from string or default to current reporting
    if period_str:
        try:
            period = MonthPeriod.find_create_from(year=int(period_str[-4:]),
                                                  month=int(period_str[:2]),
                                                  dont_create=True)
        except:
            pass
    if not period:
        period = current_reporting_period()

    # find entity or default to provider target
    # raise 404 on wrong provided entity code
    if entity_code:
        entity = get_object_or_404(Entity, slug=entity_code)

    if not entity:
        entity = web_provider.first_target()
    context.update({'entity': entity})

    # check permissions on this entity and raise 403
    provider_can_or_403('can_view_raw_data', web_provider, entity)

    # build entities browser
    context.update({'root': root, \
                    'paths': entities_path(root, entity)})

    # build periods list
    all_periods = raw_data_periods_for(entity)
    if period_str and not period in all_periods:
        raise Http404(_(u"No report for that period"))

    try:
        # get validated report for that period and location
        report = NutritionReport.validated.get(entity=entity, period=period)
    except NutritionReport.DoesNotExist:
        # district users need to be able to see the generated report
        # which have been created based on their validations/data.
        # if a district is looking at its root district and report exist
        # but not validated, we show it (with period) and no valid flag
        if web_provider.first_role().slug == 'district' and root == entity:
            try:
                report = NutritionReport.unvalidated.get(entity=entity,
                                                         period=period)
                if not period in all_periods:
                    all_periods.insert(0, period)
            except:
                report = None
        else:
            report = None

    # send period variables to template
    context.update({'periods': [(p.middle().strftime('%m%Y'), p.middle()) \
                                for p in all_periods], \
                    'period': period})

    if report:
        context.update({'report': report})
        #form = MalariaReportForm(instance=report)
        form = {}
        context.update({'form': form})
    else:
        context.update({'no_report': True})

    return render(request, 'raw_data.html', context)
Example #14
0
def current_period():
    """ Period of current date """
    return MonthPeriod.find_create_by_date(date.today())
Example #15
0
    except:
        return resp_error_dob(message)

    # reccord date
    try:
        reccord_date, _reccord_date = parse_age_dob(reccord_date)
    except:
        return resp_error_date(message)

    try:
        date_is_old(reccord_date)
    except ValueError, e:
        message.respond(u"[ERREUR] %s" % e)
        return True

    MonthPeriod.find_create_from(year=reccord_date.year,
                                 month=reccord_date.month)

    # Date of Death, YYYY-MM-DD
    try:
        dod = parse_age_dob(dod_text, True)
    except:
        return resp_error_dod(message)

    # Place of death, entity code
    try:
        death_location = Entity.objects.get(slug=death_location_code)
    except Entity.DoesNotExist:
        return resp_error_death_location(message, death_location_code)

    # Nb of living children
    try:
Example #16
0
    def handle(self, *args, **options):

        current_period = MonthPeriod.find_create_by_date(date.today())

        now = datetime.now()

        # find our date of first report (begining of activities)
        first_report = date.today()
        try:
            child = ChildrenMortalityReport.objects.all().order_by('dod')[0].dod
        except:
            child = None
        try:
            mat = MaternalMortalityReport.objects.all().order_by('dod')[0].dod
        except:
            mat = None
        try: 
            preg = PregnancyReport.objects.all().order_by('creatd_on')[0].creatd_on
        except:
            preg = None
        try: 
            bir = BirthReport.objects.all().order_by('creatd_on')[0].created_on
        except:
            bir = None
        try: 
            commod = RHCommoditiesReport.objects.all().order_by('period')[0].period.start_on
            commod = date(commod.year, commod.month, commod.day)
        except:
            commod = None
        if child:
            first_report = child
        if mat and mat < first_report:
            first_report = mat
        if preg and preg < first_report:
            first_report = preg
        if bir and bir < first_report:
            first_report = bir
        if commod and commod < first_report:
            first_report = commod

        first_period = MonthPeriod.find_create_by_date(first_report)

        for year in range(first_period.start_on.year, current_period.end_on.year + 1):

            # create year
            y = YearPeriod.find_create_from(year)
            print(y)

            # create quarter
            for quarter in y.quarters_:
                if quarter.start_on > now:
                    break
                quarter.save()
                print(u"\t%s" % quarter)

            # create months:
            for month in y.months:
                if month.start_on > now:
                    break
                month.save()
                print(u"\t\t%s" % month)

                # create weeks
                for week in month.weeks:
                    if week.start_on > now:
                       break
                    week.save()
                    print(u"\t\t\t%s" % week)
Example #17
0
def palu(message):

    # common start of error message
    error_start = u"Impossible d'enregistrer le rapport. "

    # create variables from text messages.
    try:
        args_names = ['kw1', 'username', 'password', 'month', 'year', \
        'u5_total_consultation_all_causes', \
        'u5_total_suspected_malaria_cases', \
        'u5_total_simple_malaria_cases', \
        'u5_total_severe_malaria_cases', \
        'u5_total_tested_malaria_cases', \
        'u5_total_confirmed_malaria_cases', \
        'u5_total_treated_malaria_cases', \
        'u5_total_inpatient_all_causes', \
        'u5_total_malaria_inpatient', \
        'u5_total_death_all_causes', \
        'u5_total_malaria_death', \
        'u5_total_distributed_bednets', \
        'o5_total_consultation_all_causes', \
        'o5_total_suspected_malaria_cases', \
        'o5_total_simple_malaria_cases', \
        'o5_total_severe_malaria_cases', \
        'o5_total_tested_malaria_cases', \
        'o5_total_confirmed_malaria_cases', \
        'o5_total_treated_malaria_cases', \
        'o5_total_inpatient_all_causes', \
        'o5_total_malaria_inpatient', \
        'o5_total_death_all_causes', \
        'o5_total_malaria_death', \
        'pw_total_consultation_all_causes', \
        'pw_total_suspected_malaria_cases', \
        'pw_total_severe_malaria_cases', \
        'pw_total_tested_malaria_cases', \
        'pw_total_confirmed_malaria_cases', \
        'pw_total_treated_malaria_cases', \
        'pw_total_inpatient_all_causes', \
        'pw_total_malaria_inpatient', \
        'pw_total_death_all_causes', \
        'pw_total_malaria_death', \
        'pw_total_distributed_bednets', \
        'pw_total_anc1', \
        'pw_total_sp1', \
        'pw_total_sp2', \
        'stockout_act_children', 'stockout_act_youth', 'stockout_act_adult', \
        'stockout_artemether', 'stockout_quinine', 'stockout_serum', \
        'stockout_bednet', 'stockout_rdt', 'stockout_sp']
        args_values = message.content.strip().lower().split()
        arguments = dict(zip(args_names, args_values))
    except ValueError:
        # failure to split means we proabably lack a data or more
        # we can't process it.
        message.respond(error_start + u" Le format du SMS est incorrect.")
        return True

    # convert form-data to int or bool respectively
    try:
        for key, value in arguments.items():
            if key.split('_')[0] in ('u5', 'o5', 'pw', 'month', 'year'):
                arguments[key] = int(value)
            if key.split('_')[0] == 'stockout':
                arguments[key] = MalariaReport.YES if bool(int(value)) \
                                                   else MalariaReport.NO
    except:
        raise
        # failure to convert means non-numeric value which we can't process.
        message.respond(error_start + u" Les données sont malformées.")
        return True

    # check credentials
    try:
        provider = Provider.active.get(user__username=arguments['username'])
    except Provider.DoesNotExist:
        message.respond(error_start + u"Ce nom d'utilisateur " +
                                      u"(%s) n'existe pas." % \
                                      arguments['username'])
        return True
    if not provider.check_password(arguments['password']):
        message.respond(error_start + u"Votre mot de passe est incorrect.")
        return True

    # now we have well formed and authenticated data.
    # let's check for business-logic errors.

    # create a data holder for validator
    data_browser = MalariaDataHolder()

    # feed data holder with sms provided data
    for key, value in arguments.items():
        if key.split('_')[0] in ('u5', 'o5', 'pw', \
                                 'stockout', 'year', 'month'):
            data_browser.set(key, value)

    # feed data holder with guessable data
    try:
        hc = entity_for(provider).slug
    except:
        hc = None
    data_browser.set('hc', hc)
    today = datetime.date.today()
    data_browser.set('fillin_day', today.day)
    data_browser.set('fillin_month', today.month)
    data_browser.set('fillin_year', today.year)
    data_browser.set('author', provider.name())

    # create validator and fire
    validator = MalariaReportValidator(data_browser)
    validator.errors.reset()
    try:
        validator.validate()
    except AttributeError as e:
        message.respond(error_start + e.__str__())
        return True
    errors = validator.errors

    # return first error to user
    if errors.count() > 0:
        message.respond(error_start + errors.all()[0])
        return True

    # create the report
    try:
        period = MonthPeriod.find_create_from(year=data_browser.get('year'), \
                                              month=data_browser.get('month'))
        entity = Entity.objects.get(slug=data_browser.get('hc'), \
                                    type__slug='cscom')
        report = MalariaReport.start(period, entity, provider, \
                                     type=MalariaReport.TYPE_SOURCE)

        report.add_underfive_data(*data_browser.data_for_cat('u5'))
        report.add_overfive_data(*data_browser.data_for_cat('o5'))
        report.add_pregnantwomen_data(*data_browser.data_for_cat('pw'))
        report.add_stockout_data(*data_browser.data_for_cat('so'))
        #report.save()
        with reversion.create_revision():
            report.save()
            reversion.set_user(provider.user)

    except Exception as e:
        message.respond(error_start + u"Une erreur technique s'est " \
                        u"produite. Reessayez plus tard et " \
                        u"contactez ANTIM si le probleme persiste.")
        logger.error(u"Unable to save report to DB. Message: %s | Exp: %r" \
                     % (message.content, e))
        return True

    message.respond(u"[SUCCES] Le rapport de %(cscom)s pour %(period)s "
                    u"a ete enregistre. " \
                    u"Le No de recu est #%(receipt)s." \
                    % {'cscom': report.entity.display_full_name(), \
                       'period': report.period, \
                       'receipt': report.receipt})
    try:
        to = contact_for(report.entity.parent).phone_number
    except:
        to = None
    if not to:
        return True
    send_sms(to, u"[ALERTE] Le CSCom %(cscom)s vient d'envoyer le " \
                 u"rapport #%(receipt)s pour %(period)s." \
                 % {'cscom': report.entity.display_full_name(), \
                    'period': report.period, \
                    'receipt': report.receipt})
    return True