Ejemplo n.º 1
0
def update_historical_data(domain, locations=None):
    """
    If we don't have a record of this supply point being updated, run
    through all historical data and just fill in with zeros.
    """
    org_summaries = OrganizationSummary.objects.order_by('date')
    if org_summaries.count() == 0:
        return

    start_date = org_summaries[0].date

    if locations is None:
        if not ILSGatewayConfig.for_domain(domain).all_stock_data:
            locations = _get_test_locations(domain)
        else:
            locations = Location.by_domain(domain)

    for sp in locations:
        try:
            SupplyPointWarehouseRecord.objects.get(supply_point=sp._id)
        except SupplyPointWarehouseRecord.DoesNotExist:
            # we didn't have a record so go through and historically update
            # anything we maybe haven't touched
            for year, month in months_between(start_date, sp.sql_location.created_at):
                window_date = datetime(year, month, 1)
                for cls in [OrganizationSummary, ProductAvailabilityData, GroupSummary]:
                    _init_warehouse_model(cls, sp, window_date)
            SupplyPointWarehouseRecord.objects.create(supply_point=sp._id,
                                                      create_date=datetime.utcnow())
Ejemplo n.º 2
0
def update_historical_data_for_location(loc):
    """
        Fill with zeros data for all months between default start date and date of earliest location's summary.
        E.g. Location is created at 2016-02-10 and earliest summary is from 2016-03-01 whereas
        default start date is equal to 2012-01-01, so we need to generate data for all months
        between 2012-01-01 and 2016-03-01.
        This function is important for all locations created after initial run of report runner.
    """
    start_date = default_start_date()
    try:
        earliest_org_summary = OrganizationSummary.objects.filter(
            location_id=loc.location_id).earliest('date')
        earliest_org_summary_date = earliest_org_summary.date
    except OrganizationSummary.DoesNotExist:
        earliest_org_summary_date = loc.created_at

    if start_date >= earliest_org_summary_date:
        return

    for year, month in months_between(start_date, earliest_org_summary_date):
        window_date = datetime(year, month, 1)
        for cls in [
                OrganizationSummary, ProductAvailabilityData, GroupSummary
        ]:
            _init_warehouse_model(cls, loc, window_date)
Ejemplo n.º 3
0
def update_historical_data(domain, locations=None):
    """
    If we don't have a record of this supply point being updated, run
    through all historical data and just fill in with zeros.
    """
    org_summaries = OrganizationSummary.objects.order_by('date')
    if org_summaries.count() == 0:
        return

    start_date = org_summaries[0].date

    if locations is None:
        if not ILSGatewayConfig.for_domain(domain).all_stock_data:
            locations = _get_test_locations(domain)
        else:
            locations = Location.by_domain(domain)

    for sp in locations:
        try:
            SupplyPointWarehouseRecord.objects.get(supply_point=sp._id)
        except SupplyPointWarehouseRecord.DoesNotExist:
            # we didn't have a record so go through and historically update
            # anything we maybe haven't touched
            for year, month in months_between(start_date,
                                              sp.sql_location.created_at):
                window_date = datetime(year, month, 1)
                for cls in [
                        OrganizationSummary, ProductAvailabilityData,
                        GroupSummary
                ]:
                    _init_warehouse_model(cls, sp, window_date)
            SupplyPointWarehouseRecord.objects.create(
                supply_point=sp._id, create_date=datetime.utcnow())
Ejemplo n.º 4
0
    def child_age(self):
        if self.status == 'mother':
            non_adjusted_month = len(months_between(self.dod, self.reporting_window_start)) - 1
            # anchor date should be their one month birthday
            anchor_date = add_months_to_date(self.dod, 1)

            month = self._adjust_for_vhnd_presence(non_adjusted_month, anchor_date)
            if month < 1:
                self.case_is_out_of_range = True
            return month
Ejemplo n.º 5
0
    def child_age(self):
        if self.status == 'mother':
            non_adjusted_month = len(months_between(self.dod, self.reporting_window_start)) - 1
            # anchor date should be their one month birthday
            anchor_date = add_months_to_date(self.dod, 1)

            month = self._adjust_for_vhnd_presence(non_adjusted_month, anchor_date)
            if month < 1:
                self.case_is_out_of_range = True
            return month
Ejemplo n.º 6
0
    def child_age(self):
        if self.status == 'mother':
            non_adjusted_month = len(months_between(self.dod, self.reporting_window_start)) - 1
            # anchor date should be their one month birthday
            anchor_date = add_months_to_date(self.dod, 1)

            month = self._adjust_for_vhnd_presence(non_adjusted_month, anchor_date)
            if month < 1:
                raise InvalidRow('child month %s not valid' % month)

            return month
Ejemplo n.º 7
0
    def child_age(self):
        if self.status == 'mother':
            non_adjusted_month = len(months_between(self.dod, self.reporting_window_start)) - 1
            # anchor date should be their one month birthday
            anchor_date = add_months_to_date(self.dod, 1)

            month = self._adjust_for_vhnd_presence(non_adjusted_month, anchor_date)
            if month < 1:
                raise InvalidRow('child month %s not valid' % month)

            return month
Ejemplo n.º 8
0
def _get_keys(startdate, enddate, clinic_id):
    # assumes the start date is set to the first the end date to the last of the month
    # if there's no clinic specified just use the whole range
    if not clinic_id:
        startkey = [startdate.year, startdate.month - 1]
        endkey = [enddate.year, enddate.month - 1, {}]
        return [{"startkey": startkey, "endkey": endkey}]
    else:
        # otherwise only include results for this clinic
        return [{"startkey": [year, month - 1, clinic_id],
                 "endkey": [year, month -1, clinic_id, {}]} \
                 for year, month in months_between(startdate, enddate)]
Ejemplo n.º 9
0
    def preg_month(self):
        if self.status == 'pregnant':
            base_window_start = add_months_to_date(self.edd, -9)
            non_adjusted_month = len(months_between(base_window_start, self.reporting_window_start)) - 1

            # the date to check one month after they first become eligible,
            # aka the end of their fourth month of pregnancy
            vhnd_date_to_check = add_months_to_date(self.preg_first_eligible_date, 1)

            month = self._adjust_for_vhnd_presence(non_adjusted_month, vhnd_date_to_check)
            if month < 4 or month > 9:
                raise InvalidRow('pregnancy month %s not valid' % month)
            return month
Ejemplo n.º 10
0
    def preg_month(self):
        if self.status == 'pregnant':
            base_window_start = add_months_to_date(self.edd, -9)
            non_adjusted_month = len(months_between(base_window_start, self.reporting_window_start)) - 1

            # the date to check one month after they first become eligible,
            # aka the end of their fourth month of pregnancy
            vhnd_date_to_check = add_months_to_date(self.preg_first_eligible_date, 1)

            month = self._adjust_for_vhnd_presence(non_adjusted_month, vhnd_date_to_check)
            if month < 4 or month > 9:
                raise InvalidRow('pregnancy month %s not valid' % month)
            return month
Ejemplo n.º 11
0
    def get_first_days(self, current_month, num_previous_months, as_datespans=False):
        enddate = current_month or datetime.datetime.utcnow()
        enddate = self.get_first_day_of_month(enddate.year, enddate.month)
        (start_year, start_month) = add_months(enddate.year, enddate.month, -num_previous_months)
        startdate = self.get_last_day_of_month(start_year, start_month)

        months = months_between(startdate, enddate)

        month_dates = list()
        for year, month in months:
            if as_datespans:
                month_dates.append(self.get_month_datespan((year, month)))
            else:
                month_dates.append(self.get_first_day_of_month(year, month))

        datespan = self.get_month_datespan((startdate.year, startdate.month), (enddate.year, enddate.month))
        return month_dates, datespan
Ejemplo n.º 12
0
    def preg_month(self):
        if self.status == 'pregnant':
            if not self.edd:
                raise InvalidRow('No edd found for pregnant mother.')
            base_window_start = add_months_to_date(self.edd, -9)
            try:
                non_adjusted_month = len(months_between(base_window_start, self.reporting_window_start)) - 1
            except AssertionError:
                self.case_is_out_of_range = True
                non_adjusted_month = 0

            # the date to check one month after they first become eligible,
            # aka the end of their fourth month of pregnancy
            vhnd_date_to_check = add_months_to_date(self.preg_first_eligible_date, 1)

            month = self._adjust_for_vhnd_presence(non_adjusted_month, vhnd_date_to_check)
            if month < 4 or month > 9:
                self.case_is_out_of_range = True
            return month
Ejemplo n.º 13
0
    def preg_month(self):
        if self.status == 'pregnant':
            if not self.edd:
                raise InvalidRow('No edd found for pregnant mother.')
            base_window_start = add_months_to_date(self.edd, -9)
            try:
                non_adjusted_month = len(months_between(base_window_start, self.reporting_window_start)) - 1
            except AssertionError:
                self.case_is_out_of_range = True
                non_adjusted_month = 0

            # the date to check one month after they first become eligible,
            # aka the end of their fourth month of pregnancy
            vhnd_date_to_check = add_months_to_date(self.preg_first_eligible_date, 1)

            month = self._adjust_for_vhnd_presence(non_adjusted_month, vhnd_date_to_check)
            if month < 4 or month > 9:
                self.case_is_out_of_range = True
            return month
Ejemplo n.º 14
0
    def get_first_days(self, current_month, num_previous_months, as_datespans=False):
        enddate = current_month or datetime.datetime.utcnow()
        enddate = self.get_first_day_of_month(enddate.year, enddate.month)
        (start_year, start_month) = add_months(enddate.year, enddate.month, -num_previous_months)
        startdate = self.get_last_day_of_month(start_year, start_month)

        months = months_between(startdate, enddate)

        month_dates = list()
        for year, month in months:
            if as_datespans:
                month_dates.append(self.get_month_datespan((year, month)))
            else:
                month_dates.append(self.get_first_day_of_month(year, month))

        datespan = self.get_month_datespan(
            (startdate.year, startdate.month),
            (enddate.year, enddate.month)
        )
        return month_dates, datespan
Ejemplo n.º 15
0
def update_historical_data_for_location(loc):
    """
        Fill with zeros data for all months between default start date and date of earliest location's summary.
        E.g. Location is created at 2016-02-10 and earliest summary is from 2016-03-01 whereas
        default start date is equal to 2012-01-01, so we need to generate data for all months
        between 2012-01-01 and 2016-03-01.
        This function is important for all locations created after initial run of report runner.
    """
    start_date = default_start_date()
    try:
        earliest_org_summary = OrganizationSummary.objects.filter(location_id=loc.location_id).earliest('date')
        earliest_org_summary_date = earliest_org_summary.date
    except OrganizationSummary.DoesNotExist:
        earliest_org_summary_date = loc.sql_location.created_at

    if start_date >= earliest_org_summary_date:
        return

    for year, month in months_between(start_date, earliest_org_summary_date):
        window_date = datetime(year, month, 1)
        for cls in [OrganizationSummary, ProductAvailabilityData, GroupSummary]:
            _init_warehouse_model(cls, loc, window_date)
Ejemplo n.º 16
0
class ConditionsMet(object):

    method_map = {
        "atri": [('name', "List of Beneficiary", True),
                 ('awc_name', "AWC Name", True),
                 ('husband_name', "Husband Name", True),
                 ('month', "Month", True), ('window', "Window", True),
                 ('one', "1", True), ('two', "2", True), ('three', "3", True),
                 ('four', "4", True), ('five', "5", True),
                 ('cash', "Cash to be transferred", True),
                 ('owner_id', "Owner Id", False),
                 ('block_name', "Block Name", False),
                 ('closed', 'Closed', False)],
        'wazirganj': [('name', "List of Beneficiary", True),
                      ('awc_name', "AWC Name", True),
                      ('status', "Current status", True),
                      ('month', "Month", True), ('window', "Window", True),
                      ('one', "1", True), ('two', "2", True),
                      ('four', "3", True), ('five', "4", True),
                      ('cash', "Cash to be transferred", True),
                      ('owner_id', "Owner Id", False),
                      ('block_name', "Block Name", False),
                      ('closed', 'Closed', False)]
    }

    def __init__(self, case, report):
        if report.snapshot is not None:
            report.filter(
                lambda key: case['_source'][key],
                # case.awc_name, case.block_name
                [('awc_name', 'awcs'), ('block_name', 'block'),
                 ('owner_id', 'gp'), ('closed', 'is_open')],
            )
        img_elem = '<div style="width:100px !important;"><img src="/static/opm/img/%s"></div>'

        met = {
            'window_1_1': None,
            'window_1_2': None,
            'window_2_1': None,
            'window_2_2': None,
            'attendance_vhnd_3': None,
            'attendance_vhnd_6': None,
            'child1_vhndattend_calc': None,
            'prev_child1_vhndattend_calc': None,
            'child1_attendance_vhnd': None,
            'weight_tri_1': None,
            'prev_weight_tri_1': None,
            'weight_tri_2': None,
            'prev_weight_tri_2': None,
            'child1_growthmon_calc': None,
            'prev_child1_growthmon_calc': None,
            'child1_excl_breastfeed_calc': None,
            'prev_child1_excl_breastfeed_calc': None,
            'child1_ors_calc': None,
            'prev_child1_ors_calc': None,
            'child1_weight_calc': None,
            'child1_register_calc': None,
            'child1_measles_calc': None,
            'prev_child1_weight_calc': None,
            'prev_child1_register_calc': None,
            'prev_child1_measles_calc': None,
            'child1_suffer_diarrhea': None,
            'interpret_grade_1': None
        }

        def get_property(obj, name, default=None):
            if name in obj:
                if type(obj[name]) is dict:
                    return obj[name]
                return obj[name]
            else:
                return default if default is not None else EMPTY_FIELD

        def get_property_from_forms(forms, met_properties):
            for form in forms:
                for k, v in met_properties.iteritems():
                    if k == 'child1_suffer_diarrhea':
                        if 'child_1' in form.form and k in form.form['child_1']:
                            met_properties[k] = form.form['child_1'][k]
                    else:
                        if k in form.form:
                            met_properties[k] = form.form[k]
            return met_properties

        case_obj = CommCareCase.get(case['_source']['_id'])
        self.block_name = get_property(case_obj, 'block_name', '')
        self.owner_id = get_property(case_obj, 'owner_id', '')
        self.closed = get_property(case_obj, 'closed', False)
        forms = case_obj.get_forms()
        birth_spacing_prompt = []
        for form in forms:
            if 'birth_spacing_prompt' in form.form:
                birth_spacing_prompt.append(form.form['birth_spacing_prompt'])

        filtered_forms = [
            form for form in case_obj.get_forms() if report.datespan.startdate
            <= form.received_on <= report.datespan.enddate
        ]

        get_property_from_forms(filtered_forms, met)

        dod = get_property(case_obj, 'dod')
        if dod and dod != EMPTY_FIELD:
            try:
                child_age = len(
                    months_between(
                        datetime.datetime(dod.year, dod.month, dod.day),
                        datetime.datetime.now()))
            except AssertionError:
                child_age = -1
        else:
            child_age = -1

        if get_property(case_obj, 'mother_preg_outcome', '') == '1':
            self.status = 'mother'
        elif get_property(case_obj, 'mother_preg_outcome', '') == '':
            self.status = 'pregnant'
        else:
            raise InvalidRow

        met_one = False
        met_two = False
        met_three = False
        met_four = False
        met_five = False
        preg_month = get_property(case_obj, 'pregnancy_month', 0) or 0
        if self.status == 'pregnant':
            if '1' in [
                    met['window_1_1'], met['window_1_2'], met['window_2_1'],
                    met['window_2_2'], met['attendance_vhnd_3'],
                    met['attendance_vhnd_6']
            ]:
                met_one = True
            if (preg_month == '6' and '1' in [
                    met['weight_tri_1'], met['prev_weight_tri_1']
            ]) or (preg_month == '9'
                   and '1' in [met['weight_tri_2'], met['prev_weight_tri_2']]):
                met_two = True
        elif self.status == 'mother':
            if '1' in [
                    met['child1_vhndattend_calc'],
                    met['prev_child1_vhndattend_calc'],
                    met['child1_attendance_vhnd']
            ]:
                met_one = True
            if '1' in [
                    met['child1_growthmon_calc'],
                    met['prev_child1_growthmon_calc']
            ]:
                met_two = True
            if (child_age == 3 and (met['child1_weight_calc'] or met['prev_child1_weight_calc'])) or \
                    (child_age == 6 and (met['child1_register_calc'] or met['prev_child1_register_calc'])) or \
                    (child_age == 9 and (met['child1_measles_calc'] or met['prev_child1_measles_calc'])):
                met_three = True
            if child_age == 6 and ('1' in [
                    met['child1_excl_breastfeed_calc'],
                    met['prev_child1_excl_breastfeed_calc']
            ]):
                met_four = True
            if child_age in [6, 9, 12] and '1' in [
                    met['child1_ors_calc'], met['prev_child1_ors_calc']
            ]:
                met_five = True

        self.name = get_property(case_obj, 'name')
        self.awc_name = get_property(case_obj, 'awc_name')
        self.husband_name = get_property(case_obj, 'husband_name')
        self.window = get_property(case_obj, 'which_window')
        if self.status == 'pregnant':
            self.month = get_property(case_obj, 'pregnancy_month')
            self.one = img_elem % M_ATTENDANCE_Y if preg_month == '9' else img_elem % M_ATTENDANCE_N
            self.two = img_elem % M_WEIGHT_Y if preg_month in [
                '6', '9'
            ] else img_elem % M_WEIGHT_N
            self.three = img_elem % IFA_Y if int(
                preg_month) < 7 else img_elem % IFA_N
            self.four = ''
            if report.block.lower() == 'wazirganj':
                if child_age > 23 and '1' in birth_spacing_prompt:
                    self.five = img_elem % SPACING_PROMPT_Y
                else:
                    self.five = img_elem % SPACING_PROMPT_N
            else:
                self.five = ''

        elif self.status == 'mother':
            if child_age != -1:
                self.month = child_age
            else:
                self.month = EMPTY_FIELD

            self.one = img_elem % C_ATTENDANCE_Y if 0 <= child_age <= 1 else img_elem % C_ATTENDANCE_N
            self.two = img_elem % C_WEIGHT_Y if child_age % 3 == 0 else img_elem % C_WEIGHT_N

            if child_age == 3:
                if met['child1_weight_calc'] or met['prev_child1_weight_calc']:
                    self.three = img_elem % CHILD_WEIGHT_Y
                else:
                    self.three = img_elem % CHILD_WEIGHT_N
            elif child_age == 6:
                if met['child1_register_calc'] or met[
                        'prev_child1_register_calc']:
                    self.three = img_elem % C_REGISTER_Y
                else:
                    self.three = img_elem % C_REGISTER_N
            elif child_age == 9:
                if met['child1_measles_calc'] or met[
                        'prev_child1_measles_calc']:
                    self.three = img_elem % MEASLEVACC_Y
                else:
                    self.three = img_elem % MEASLEVACC_N
            else:
                self.three = ''

            self.four = img_elem % EXCBREASTFED_Y if child_age == 6 else img_elem % EXCBREASTFED_N

            if child_age in [3, 6, 9]:
                if met['child1_suffer_diarrhea'] == '1':
                    self.five = img_elem % ORSZNTREAT_Y
                else:
                    self.five = img_elem % ORSZNTREAT_N
            elif child_age == [24, 36]:
                if met['interpret_grade_1'] == 'normal':
                    self.five = img_elem % GRADE_NORMAL_Y
                else:
                    self.five = img_elem % GRADE_NORMAL_N
            else:
                self.five = ''

        if report.block.lower() == 'atri':
            if child_age == 24:
                self.cash = '<span style="color: green;">Rs. 2000</span>'
            elif child_age == 36:
                self.cash = '<span style="color: green;">Rs. 3000</span>'
            elif met_one or met_two or met_three or met_four or met_five:
                self.cash = '<span style="color: green;">Rs. 250</span>'
            else:
                self.cash = '<span style="color: red;">Rs. 0</span>'

        elif report.block.lower() == 'wazirganj':
            if met_one or met_two or met_four or met_five:
                self.cash = '<span style="color: green;">Rs. 250</span>'
            else:
                self.cash = '<span style="color: red;">Rs. 0</span>'
Ejemplo n.º 17
0
def process_non_facility_warehouse_data(org, start_date, end_date, strict=True):
    facs = get_nested_children(org)
    fac_ids = [f._id for f in facs]
    logging.info("processing non-facility %s (%s), %s children" % (org.name, str(org._id), len(facs)))
    for year, month in months_between(start_date, end_date):
        window_date = datetime(year, month, 1)
        org_summary = OrganizationSummary.objects.get_or_create(supply_point=org._id, date=window_date)[0]

        org_summary.total_orgs = len(facs)
        sub_summaries = OrganizationSummary.objects.filter(date=window_date, supply_point__in=fac_ids)

        subs_with_lead_time = [s for s in sub_summaries if s.average_lead_time_in_days]
        # lead times
        if subs_with_lead_time:
            days_sum = sum([s.average_lead_time_in_days for s in subs_with_lead_time])
            org_summary.average_lead_time_in_days = days_sum / len(subs_with_lead_time)
        else:
            org_summary.average_lead_time_in_days = 0

        org_summary.save()
        # product availability
        prods = Product.ids_by_domain(org.domain)
        for p in prods:
            product_data = ProductAvailabilityData.objects.get_or_create(product=p,
                                                                         supply_point=org._id,
                                                                         date=window_date)[0]

            sub_prods = ProductAvailabilityData.objects.filter(product=p,
                                                               supply_point__in=fac_ids,
                                                               date=window_date)

            product_data.total = sum([p.total for p in sub_prods])
            if strict:
                assert product_data.total == len(facs), \
                    "total should match number of sub facilities"
            product_data.with_stock = sum([p.with_stock for p in sub_prods])
            product_data.without_stock = sum([p.without_stock for p in sub_prods])
            product_data.without_data = product_data.total - product_data.with_stock - product_data.without_stock
            product_data.save()

        dg = DeliveryGroups(month=month, facs=facs)
        for type in NEEDED_STATUS_TYPES:
            gsum = GroupSummary.objects.get_or_create(org_summary=org_summary, title=type)[0]
            sub_sums = GroupSummary.objects.filter(title=type, org_summary__in=sub_summaries).all()

            # TODO: see if moving the aggregation to the db makes it
            # faster, if this is slow
            gsum.total = sum([s.total for s in sub_sums])
            gsum.responded = sum([s.responded for s in sub_sums])
            gsum.on_time = sum([s.on_time for s in sub_sums])
            gsum.complete = sum([s.complete for s in sub_sums])
            # gsum.missed_response = sum([s.missed_response for s in sub_sums])
            gsum.save()

            if type == SupplyPointStatusTypes.DELIVERY_FACILITY:
                expected = len(dg.delivering())
            elif type == SupplyPointStatusTypes.R_AND_R_FACILITY:
                expected = len(dg.submitting())
            elif type == SupplyPointStatusTypes.SOH_FACILITY \
                    or type == SupplyPointStatusTypes.SUPERVISION_FACILITY:
                expected = len(facs)
            if gsum.total != expected:
                logging.info("expected %s but was %s for %s" % (expected, gsum.total, gsum))

        for alert_type in ['rr_not_submitted', 'delivery_not_received',
                           'soh_not_responding', 'rr_not_responded', 'delivery_not_responding']:
            sub_alerts = Alert.objects.filter(supply_point__in=fac_ids, date=window_date, type=alert_type)
            aggregate_response_alerts(org, window_date, sub_alerts, alert_type)
Ejemplo n.º 18
0
def process_facility_warehouse_data(fac, start_date, end_date):
    """
    process all the facility-level warehouse tables
    """
    logging.info("processing facility %s (%s)" % (fac.name, str(fac._id)))
    for alert_type in ['soh_not_responding', 'rr_not_responded', 'delivery_not_responding']:
        alert = Alert.objects.filter(supply_point=fac._id, date__gte=start_date, date__lt=end_date,
                                     type=alert_type)
        alert.delete()

    supply_point_id = fac.linked_supply_point()._id
    new_statuses = SupplyPointStatus.objects.filter(
        supply_point=fac._id,
        status_date__gte=start_date,
        status_date__lt=end_date
    ).order_by('status_date')
    process_facility_statuses(fac, new_statuses)

    new_reports = StockReport.objects.filter(
        stocktransaction__case_id=supply_point_id,
        date__gte=start_date,
        date__lt=end_date,
        stocktransaction__type='stockonhand'
    ).order_by('date')
    process_facility_product_reports(fac, new_reports)

    new_trans = StockTransaction.objects.filter(
        case_id=supply_point_id,
        report__date__gte=start_date,
        report__date__lt=end_date
    ).order_by('report__date')
    process_facility_transactions(fac, new_trans)

    # go through all the possible values in the date ranges
    # and make sure there are warehouse tables there
    for year, month in months_between(start_date, end_date):
        window_date = datetime(year, month, 1)

        # create org_summary for every fac/date combo
        org_summary, created = OrganizationSummary.objects.get_or_create(supply_point=fac._id, date=window_date)

        org_summary.total_orgs = 1
        alt = average_lead_time(fac, window_date)
        if alt:
            alt = alt.days
        org_summary.average_lead_time_in_days = alt or 0
        org_summary.save()

        # create group_summary for every org_summary title combo
        for title in NEEDED_STATUS_TYPES:
            group_summary, created = GroupSummary.objects.get_or_create(org_summary=org_summary,
                                                                        title=title)
        # update all the non-response data
        not_responding_facility(org_summary)

        # update product availability data
        update_product_availability_facility_data(org_summary)

        # alerts
        populate_no_primary_alerts(fac, window_date)
        populate_facility_stockout_alerts(fac, window_date)
Ejemplo n.º 19
0
def update_product_availability_facility_data(facility, products, start_date,
                                              end_date):
    # product availability

    existing_data = ProductAvailabilityData.objects.filter(
        date__range=(datetime(start_date.year, start_date.month,
                              1), datetime(end_date.year, end_date.month, 1)),
        location_id=facility.get_id)

    product_data_dict = {(pa.date, pa.location_id, pa.product): pa
                         for pa in existing_data}

    product_data_list = []
    previous_month = {}
    for year, month in months_between(start_date, end_date):
        window_date = datetime(year, month, 1)
        for p in products:
            now = datetime.utcnow()
            if (window_date, facility.get_id,
                    p.product_id) in product_data_dict:
                previous_month[p.product_id] = product_data_dict[
                    window_date, facility.get_id, p.product_id]
                continue
            else:
                product_data = ProductAvailabilityData(
                    date=window_date,
                    location_id=facility.get_id,
                    product=p.product_id,
                    create_date=now,
                    update_date=now)

            # set defaults
            product_data.total = 1
            prev = None
            if p.product_id in previous_month:
                prev = previous_month[p.product_id]
            if not prev:
                previous_reports = ProductAvailabilityData.objects.filter(
                    product=p.product_id,
                    location_id=facility.location_id,
                    date__lt=window_date,
                    total=1)
                if previous_reports.count():
                    prev = previous_reports.latest('date')

            if prev:
                product_data.with_stock = prev.with_stock
                product_data.without_stock = prev.without_stock
                product_data.without_data = prev.without_data
            else:
                # otherwise we use the defaults
                product_data.with_stock = 0
                product_data.without_stock = 0
                product_data.without_data = 1
            if product_data.pk is not None:
                product_data.save()
            else:
                product_data_list.append(product_data)
            assert (product_data.with_stock + product_data.without_stock + product_data.without_data) == 1, \
                "bad product data config for %s" % product_data
            previous_month[p.product_id] = product_data
    ProductAvailabilityData.objects.bulk_create(product_data_list)
Ejemplo n.º 20
0
def process_facility_warehouse_data(facility, start_date, end_date, runner):
    """
    process all the facility-level warehouse tables
    """
    logging.info("processing facility %s (%s)" %
                 (facility.name, str(facility._id)))
    try:
        runner.location = facility.sql_location
        runner.save()
    except SQLLocation.DoesNotExist:
        # TODO Temporary fix
        facility.delete()
        return

    for alert_type in [
            const.SOH_NOT_RESPONDING, const.RR_NOT_RESPONDED,
            const.DELIVERY_NOT_RESPONDING
    ]:
        alert = Alert.objects.filter(location_id=facility._id,
                                     date__gte=start_date,
                                     date__lt=end_date,
                                     type=alert_type)
        alert.delete()

    supply_point_id = facility.linked_supply_point()._id
    location_id = facility._id
    new_statuses = SupplyPointStatus.objects.filter(
        location_id=facility._id,
        status_date__gte=start_date,
        status_date__lt=end_date).order_by('status_date').iterator()
    process_facility_statuses(location_id, new_statuses)

    new_reports = StockReport.objects.filter(
        stocktransaction__case_id=supply_point_id,
        date__gte=start_date,
        date__lt=end_date,
        stocktransaction__type='stockonhand').order_by('date').iterator()
    process_facility_product_reports(location_id, new_reports)

    new_trans = StockTransaction.objects.filter(
        case_id=supply_point_id,
        report__date__gte=start_date,
        report__date__lt=end_date,
    ).exclude(type='consumption').order_by('report__date').iterator()
    process_facility_transactions(location_id, new_trans)

    # go through all the possible values in the date ranges
    # and make sure there are warehouse tables there
    for year, month in months_between(start_date, end_date):
        window_date = datetime(year, month, 1)
        # create org_summary for every fac/date combo
        org_summary, created = OrganizationSummary.objects.get_or_create(
            location_id=facility._id, date=window_date)

        org_summary.total_orgs = 1
        alt = average_lead_time(facility._id, window_date)
        if alt:
            alt = alt.days
        org_summary.average_lead_time_in_days = alt or 0
        org_summary.save()

        # create group_summary for every org_summary title combo
        for title in const.NEEDED_STATUS_TYPES:
            GroupSummary.objects.get_or_create(org_summary=org_summary,
                                               title=title)
        # update all the non-response data
        not_responding_facility(org_summary)

        # update product availability data
        update_product_availability_facility_data(org_summary)

        # alerts
        with transaction.atomic():
            populate_no_primary_alerts(facility, window_date)
            populate_facility_stockout_alerts(facility, window_date)
Ejemplo n.º 21
0
def process_non_facility_warehouse_data(location,
                                        start_date,
                                        end_date,
                                        runner=None,
                                        strict=True):
    facs = get_non_archived_facilities_below(location, end_date)

    start_date = datetime(start_date.year, start_date.month, 1)
    end_date = datetime(end_date.year, end_date.month, 1)

    if runner:
        runner.location = location
        runner.save()
    fac_ids = [f.location_id for f in facs]
    logging.info("processing non-facility %s (%s), %s children" %
                 (location.name, str(location.location_id), len(facs)))
    prods = SQLProduct.objects.filter(domain=location.domain,
                                      is_archived=False)

    sub_summaries = OrganizationSummary.objects.filter(
        location_id__in=fac_ids,
        date__range=(start_date, end_date),
        average_lead_time_in_days__gt=0).values('date').annotate(
            average_time=Avg('average_lead_time_in_days'))

    sub_summaries = {(subsummary['date'].year, subsummary['date'].month):
                     subsummary
                     for subsummary in sub_summaries}

    sub_prods = ProductAvailabilityData.objects.filter(
        location_id__in=fac_ids,
        date__range=(start_date, end_date)).values('product', 'date').annotate(
            total_sum=Sum('total'),
            with_stock_sum=Sum('with_stock'),
            without_stock_sum=Sum('without_stock'),
        )

    sub_prods = {((sub_prod['date'].year, sub_prod['date'].month),
                  sub_prod['product']): sub_prod
                 for sub_prod in sub_prods}

    sub_group_summaries = GroupSummary.objects.filter(
        org_summary__location_id__in=fac_ids,
        org_summary__date__range=(start_date, end_date)).values(
            'title',
            'org_summary__date').annotate(total_sum=Sum('total'),
                                          responded_sum=Sum('responded'),
                                          on_time_sum=Sum('on_time'),
                                          complete_sum=Sum('complete'))

    sub_group_summaries = {((sub_group_summary['org_summary__date'].year,
                             sub_group_summary['org_summary__date'].month),
                            sub_group_summary['title']): sub_group_summary
                           for sub_group_summary in sub_group_summaries}

    total_orgs = len(facs)
    for year, month in months_between(start_date, end_date):
        window_date = datetime(year, month, 1)
        org_summary = OrganizationSummary.objects.get_or_create(
            location_id=location.location_id, date=window_date)[0]

        org_summary.total_orgs = total_orgs

        # lead times
        if (year, month) in sub_summaries:
            sub_summary = sub_summaries[year, month]
            org_summary.average_lead_time_in_days = sub_summary['average_time']
        else:
            org_summary.average_lead_time_in_days = 0

        org_summary.save()
        # product availability
        for p in prods:
            product_data = ProductAvailabilityData.objects.get_or_create(
                product=p.product_id,
                location_id=location.location_id,
                date=window_date)[0]

            sub_prod = sub_prods.get(((year, month), p.product_id), {})

            product_data.total = sub_prod.get('total_sum', 0)
            if strict:
                assert product_data.total == total_orgs, \
                    "total should match number of sub facilities %s-%s" % (product_data.total, total_orgs)
            product_data.with_stock = sub_prod.get('with_stock_sum', 0)
            product_data.without_stock = sub_prod.get('without_stock_sum', 0)
            product_data.without_data = product_data.total - product_data.with_stock - product_data.without_stock
            product_data.save()

        dg = DeliveryGroups(month=month, facs=facs)
        for status_type in const.NEEDED_STATUS_TYPES:
            gsum = GroupSummary.objects.get_or_create(org_summary=org_summary,
                                                      title=status_type)[0]

            sub_sum = sub_group_summaries.get(((year, month), status_type), {})

            gsum.total = sub_sum.get('total_sum', 0)
            gsum.responded = sub_sum.get('responded_sum', 0)
            gsum.on_time = sub_sum.get('on_time_sum', 0)
            gsum.complete = sub_sum.get('complete_sum', 0)
            gsum.save()

            if status_type == SupplyPointStatusTypes.DELIVERY_FACILITY:
                expected = len(dg.delivering())
            elif status_type == SupplyPointStatusTypes.R_AND_R_FACILITY:
                expected = len(dg.submitting())
            elif status_type == SupplyPointStatusTypes.SOH_FACILITY \
                    or status_type == SupplyPointStatusTypes.SUPERVISION_FACILITY:
                expected = len(facs)
            if gsum.total != expected:
                logging.info("expected %s but was %s for %s" %
                             (expected, gsum.total, gsum))

        for alert_type in [
                const.RR_NOT_SUBMITTED, const.DELIVERY_NOT_RECEIVED,
                const.SOH_NOT_RESPONDING, const.RR_NOT_RESPONDED,
                const.DELIVERY_NOT_RESPONDING
        ]:
            sub_alerts = Alert.objects.filter(location_id__in=fac_ids,
                                              date=window_date,
                                              type=alert_type)
            aggregate_response_alerts(location.location_id, window_date,
                                      sub_alerts, alert_type)

    update_historical_data_for_location(location)
Ejemplo n.º 22
0
def process_facility_warehouse_data(facility, start_date, end_date, runner):
    """
    process all the facility-level warehouse tables
    """
    logging.info("processing facility %s (%s)" % (facility.name, str(facility._id)))
    try:
        runner.location = facility.sql_location
        runner.save()
    except SQLLocation.DoesNotExist:
        # TODO Temporary fix
        facility.delete()
        return

    for alert_type in [const.SOH_NOT_RESPONDING, const.RR_NOT_RESPONDED, const.DELIVERY_NOT_RESPONDING]:
        alert = Alert.objects.filter(location_id=facility._id, date__gte=start_date, date__lt=end_date,
                                     type=alert_type)
        alert.delete()

    supply_point_id = facility.linked_supply_point()._id
    location_id = facility._id
    new_statuses = SupplyPointStatus.objects.filter(
        location_id=facility._id,
        status_date__gte=start_date,
        status_date__lt=end_date
    ).order_by('status_date').iterator()
    process_facility_statuses(location_id, new_statuses)

    new_reports = StockReport.objects.filter(
        stocktransaction__case_id=supply_point_id,
        date__gte=start_date,
        date__lt=end_date,
        stocktransaction__type='stockonhand'
    ).order_by('date').iterator()
    process_facility_product_reports(location_id, new_reports)

    new_trans = StockTransaction.objects.filter(
        case_id=supply_point_id,
        report__date__gte=start_date,
        report__date__lt=end_date,
    ).exclude(type='consumption').order_by('report__date').iterator()
    process_facility_transactions(location_id, new_trans)

    # go through all the possible values in the date ranges
    # and make sure there are warehouse tables there
    for year, month in months_between(start_date, end_date):
        window_date = datetime(year, month, 1)
        # create org_summary for every fac/date combo
        org_summary, created = OrganizationSummary.objects.get_or_create(
            location_id=facility._id,
            date=window_date
        )

        org_summary.total_orgs = 1
        alt = average_lead_time(facility._id, window_date)
        if alt:
            alt = alt.days
        org_summary.average_lead_time_in_days = alt or 0
        org_summary.save()

        # create group_summary for every org_summary title combo
        for title in const.NEEDED_STATUS_TYPES:
            GroupSummary.objects.get_or_create(org_summary=org_summary,
                                               title=title)
        # update all the non-response data
        not_responding_facility(org_summary)

        # update product availability data
        update_product_availability_facility_data(org_summary)

        # alerts
        with transaction.atomic():
            populate_no_primary_alerts(facility, window_date)
            populate_facility_stockout_alerts(facility, window_date)
Ejemplo n.º 23
0
    def __init__(self, case, report):
        report.filter(
            lambda key: case['_source'][key],
            # case.awc_name, case.block_name
            [('awc_name', 'awcs'), ('block_name', 'block'), ('owner_id', 'gp'), ('closed', 'is_open')],
        )
        img_elem = '<div style="width:100px !important;"><img src="/static/opm/img/%s"></div>'

        met = {
            'window_1_1': None,
            'window_1_2': None,
            'window_2_1': None,
            'window_2_2': None,
            'attendance_vhnd_3': None,
            'attendance_vhnd_6': None,
            'child1_vhndattend_calc': None,
            'prev_child1_vhndattend_calc': None,
            'child1_attendance_vhnd': None,
            'weight_tri_1': None,
            'prev_weight_tri_1': None,
            'weight_tri_2': None,
            'prev_weight_tri_2': None,
            'child1_growthmon_calc': None,
            'prev_child1_growthmon_calc': None,
            'child1_excl_breastfeed_calc': None,
            'prev_child1_excl_breastfeed_calc': None,
            'child1_ors_calc': None,
            'prev_child1_ors_calc': None,
            'child1_weight_calc': None,
            'child1_register_calc': None,
            'child1_measles_calc': None,
            'prev_child1_weight_calc': None,
            'prev_child1_register_calc': None,
            'prev_child1_measles_calc': None,
            'child1_suffer_diarrhea': None,
            'interpret_grade_1': None
        }

        def get_property(obj, name, default=None):
            if name in obj:
                if type(obj[name]) is dict:
                    return obj[name]
                return obj[name]
            else:
                return default if default is not None else EMPTY_FIELD

        def get_property_from_forms(forms, met_properties):
            for form in forms:
                for k, v in met_properties.iteritems():
                    if k == 'child1_suffer_diarrhea':
                        if 'child_1' in form.form and k in form.form['child_1']:
                            met_properties[k] = form.form['child_1'][k]
                    else:
                        if k in form.form:
                            met_properties[k] = form.form[k]
            return met_properties

        case_obj = CommCareCase.get(case['_source']['_id'])
        self.block_name = get_property(case_obj, 'block_name', '')
        self.owner_id = get_property(case_obj, 'owner_id', '')
        self.closed = get_property(case_obj, 'closed', False)
        forms = case_obj.get_forms()
        birth_spacing_prompt = []
        for form in forms:
            if 'birth_spacing_prompt' in form.form:
                birth_spacing_prompt.append(form.form['birth_spacing_prompt'])

        filtered_forms = [form for form in case_obj.get_forms() if report.datespan.startdate <= form.received_on <= report.datespan.enddate]

        get_property_from_forms(filtered_forms, met)

        dod = get_property(case_obj, 'dod')
        if dod and dod != EMPTY_FIELD:
            try:
                child_age = len(months_between(datetime.datetime(dod.year, dod.month, dod.day), datetime.datetime.now()))
            except AssertionError:
                child_age = -1
        else:
            child_age = -1

        if get_property(case_obj, 'mother_preg_outcome', '') == '1':
            self.status = 'mother'
        elif get_property(case_obj, 'mother_preg_outcome', '') == '':
            self.status = 'pregnant'
        else:
            raise InvalidRow

        met_one = False
        met_two = False
        met_three = False
        met_four = False
        met_five = False
        preg_month = get_property(case_obj, 'pregnancy_month', 0) or 0
        if self.status == 'pregnant':
            if '1' in [met['window_1_1'], met['window_1_2'], met['window_2_1'], met['window_2_2'], met['attendance_vhnd_3'], met['attendance_vhnd_6']]:
                met_one = True
            if (preg_month == '6' and '1' in [met['weight_tri_1'], met['prev_weight_tri_1']]) or (preg_month == '9' and '1' in [met['weight_tri_2'], met['prev_weight_tri_2']]):
                met_two = True
        elif self.status == 'mother':
            if '1' in [met['child1_vhndattend_calc'], met['prev_child1_vhndattend_calc'], met['child1_attendance_vhnd']]:
                met_one = True
            if '1' in [met['child1_growthmon_calc'], met['prev_child1_growthmon_calc']]:
                met_two = True
            if (child_age == 3 and (met['child1_weight_calc'] or met['prev_child1_weight_calc'])) or \
                    (child_age == 6 and (met['child1_register_calc'] or met['prev_child1_register_calc'])) or \
                    (child_age == 9 and (met['child1_measles_calc'] or met['prev_child1_measles_calc'])):
                met_three = True
            if child_age == 6 and ('1' in [met['child1_excl_breastfeed_calc'], met['prev_child1_excl_breastfeed_calc']]):
                met_four = True
            if child_age in [6, 9, 12] and '1' in [met['child1_ors_calc'], met['prev_child1_ors_calc']]:
                met_five = True

        self.name = get_property(case_obj, 'name')
        self.awc_name = get_property(case_obj, 'awc_name')
        self.husband_name = get_property(case_obj, 'husband_name')
        self.window = get_property(case_obj, 'which_window')
        if self.status == 'pregnant':
            self.month = get_property(case_obj, 'pregnancy_month')
            self.one = img_elem % M_ATTENDANCE_Y if preg_month == '9' else img_elem % M_ATTENDANCE_N
            self.two = img_elem % M_WEIGHT_Y if preg_month in ['6', '9'] else img_elem % M_WEIGHT_N
            self.three = img_elem % IFA_Y if int(preg_month) < 7 else img_elem % IFA_N
            self.four = ''
            if report.block.lower() == 'wazirganj':
                if child_age > 23 and '1' in birth_spacing_prompt:
                    self.five = img_elem % SPACING_PROMPT_Y
                else:
                    self.five = img_elem % SPACING_PROMPT_N
            else:
                self.five = ''

        elif self.status == 'mother':
            if child_age != -1:
                self.month = child_age
            else:
                self.month = EMPTY_FIELD

            self.one = img_elem % C_ATTENDANCE_Y if 0 <= child_age <= 1 else img_elem % C_ATTENDANCE_N
            self.two = img_elem % C_WEIGHT_Y if child_age % 3 == 0 else img_elem % C_WEIGHT_N

            if child_age == 3:
                if met['child1_weight_calc'] or met['prev_child1_weight_calc']:
                    self.three = img_elem % CHILD_WEIGHT_Y
                else:
                    self.three = img_elem % CHILD_WEIGHT_N
            elif child_age == 6:
                if met['child1_register_calc'] or met['prev_child1_register_calc']:
                    self.three = img_elem % C_REGISTER_Y
                else:
                    self.three = img_elem % C_REGISTER_N
            elif child_age == 9:
                if met['child1_measles_calc'] or met['prev_child1_measles_calc']:
                    self.three = img_elem % MEASLEVACC_Y
                else:
                    self.three = img_elem % MEASLEVACC_N
            else:
                self.three = ''

            self.four = img_elem % EXCBREASTFED_Y if child_age == 6 else img_elem % EXCBREASTFED_N

            if child_age in [3, 6, 9]:
                if met['child1_suffer_diarrhea'] == '1':
                    self.five = img_elem % ORSZNTREAT_Y
                else:
                    self.five = img_elem % ORSZNTREAT_N
            elif child_age == [24, 36]:
                if met['interpret_grade_1'] == 'normal':
                    self.five = img_elem % GRADE_NORMAL_Y
                else:
                    self.five = img_elem % GRADE_NORMAL_N
            else:
                self.five = ''

        if report.block.lower() == 'atri':
            if child_age == 24:
                self.cash = '<span style="color: green;">Rs. 2000</span>'
            elif child_age == 36:
                self.cash = '<span style="color: green;">Rs. 3000</span>'
            elif met_one or met_two or met_three or met_four or met_five:
                self.cash = '<span style="color: green;">Rs. 250</span>'
            else:
                self.cash = '<span style="color: red;">Rs. 0</span>'

        elif report.block.lower == 'wazirganj':
            if met_one or met_two or met_four or met_five:
                self.cash = '<span style="color: green;">Rs. 250</span>'
            else:
                self.cash = '<span style="color: red;">Rs. 0</span>'
Ejemplo n.º 24
0
def process_non_facility_warehouse_data(location, start_date, end_date, runner=None, strict=True):
    if runner:
        runner.location = location.sql_location
        runner.save()
    facs = get_non_archived_facilities_below(location)
    fac_ids = [f._id for f in facs]
    logging.info("processing non-facility %s (%s), %s children"
                 % (location.name, str(location.location_id), len(facs)))
    for year, month in months_between(start_date, end_date):
        window_date = datetime(year, month, 1)
        org_summary = OrganizationSummary.objects.get_or_create(
            location_id=location.location_id, date=window_date
        )[0]

        org_summary.total_orgs = len(facs)
        sub_summaries = OrganizationSummary.objects.filter(date=window_date, location_id__in=fac_ids)

        subs_with_lead_time = [s for s in sub_summaries if s.average_lead_time_in_days]
        # lead times
        if subs_with_lead_time:
            days_sum = sum([s.average_lead_time_in_days for s in subs_with_lead_time])
            org_summary.average_lead_time_in_days = days_sum / len(subs_with_lead_time)
        else:
            org_summary.average_lead_time_in_days = 0

        org_summary.save()
        # product availability
        prods = SQLProduct.objects.filter(domain=location.domain, is_archived=False)
        for p in prods:
            product_data = ProductAvailabilityData.objects.get_or_create(product=p.product_id,
                                                                         location_id=location.location_id,
                                                                         date=window_date)[0]

            sub_prods = ProductAvailabilityData.objects.filter(product=p.product_id,
                                                               location_id__in=fac_ids,
                                                               date=window_date)

            product_data.total = sum([p.total for p in sub_prods])
            if strict:
                assert product_data.total == len(facs), \
                    "total should match number of sub facilities"
            product_data.with_stock = sum([p.with_stock for p in sub_prods])
            product_data.without_stock = sum([p.without_stock for p in sub_prods])
            product_data.without_data = product_data.total - product_data.with_stock - product_data.without_stock
            product_data.save()

        dg = DeliveryGroups(month=month, facs=facs)
        for status_type in const.NEEDED_STATUS_TYPES:
            gsum = GroupSummary.objects.get_or_create(org_summary=org_summary, title=status_type)[0]
            sub_sums = GroupSummary.objects.filter(title=status_type, org_summary__in=sub_summaries).all()

            # TODO: see if moving the aggregation to the db makes it
            # faster, if this is slow
            gsum.total = sum([s.total for s in sub_sums])
            gsum.responded = sum([s.responded for s in sub_sums])
            gsum.on_time = sum([s.on_time for s in sub_sums])
            gsum.complete = sum([s.complete for s in sub_sums])
            # gsum.missed_response = sum([s.missed_response for s in sub_sums])
            gsum.save()

            if status_type == SupplyPointStatusTypes.DELIVERY_FACILITY:
                expected = len(dg.delivering())
            elif status_type == SupplyPointStatusTypes.R_AND_R_FACILITY:
                expected = len(dg.submitting())
            elif status_type == SupplyPointStatusTypes.SOH_FACILITY \
                    or status_type == SupplyPointStatusTypes.SUPERVISION_FACILITY:
                expected = len(facs)
            if gsum.total != expected:
                logging.info("expected %s but was %s for %s" % (expected, gsum.total, gsum))

        for alert_type in [const.RR_NOT_SUBMITTED, const.DELIVERY_NOT_RECEIVED,
                           const.SOH_NOT_RESPONDING, const.RR_NOT_RESPONDED, const.DELIVERY_NOT_RESPONDING]:
            sub_alerts = Alert.objects.filter(location_id__in=fac_ids, date=window_date, type=alert_type)
            aggregate_response_alerts(location.location_id, window_date, sub_alerts, alert_type)
Ejemplo n.º 25
0
def process_non_facility_warehouse_data(location,
                                        start_date,
                                        end_date,
                                        runner,
                                        strict=True):
    runner.location = location.sql_location
    runner.save()
    facs = get_non_archived_facilities_below(location)
    fac_ids = [f._id for f in facs]
    logging.info("processing non-facility %s (%s), %s children" %
                 (location.name, str(location._id), len(facs)))
    for year, month in months_between(start_date, end_date):
        window_date = datetime(year, month, 1)
        org_summary = OrganizationSummary.objects.get_or_create(
            location_id=location._id, date=window_date)[0]

        org_summary.total_orgs = len(facs)
        sub_summaries = OrganizationSummary.objects.filter(
            date=window_date, location_id__in=fac_ids)

        subs_with_lead_time = [
            s for s in sub_summaries if s.average_lead_time_in_days
        ]
        # lead times
        if subs_with_lead_time:
            days_sum = sum(
                [s.average_lead_time_in_days for s in subs_with_lead_time])
            org_summary.average_lead_time_in_days = days_sum / len(
                subs_with_lead_time)
        else:
            org_summary.average_lead_time_in_days = 0

        org_summary.save()
        # product availability
        prods = SQLProduct.objects.filter(domain=location.domain,
                                          is_archived=False)
        for p in prods:
            product_data = ProductAvailabilityData.objects.get_or_create(
                product=p.product_id,
                location_id=location._id,
                date=window_date)[0]

            sub_prods = ProductAvailabilityData.objects.filter(
                product=p.product_id,
                location_id__in=fac_ids,
                date=window_date)

            product_data.total = sum([p.total for p in sub_prods])
            if strict:
                assert product_data.total == len(facs), \
                    "total should match number of sub facilities"
            product_data.with_stock = sum([p.with_stock for p in sub_prods])
            product_data.without_stock = sum(
                [p.without_stock for p in sub_prods])
            product_data.without_data = product_data.total - product_data.with_stock - product_data.without_stock
            product_data.save()

        dg = DeliveryGroups(month=month, facs=facs)
        for status_type in const.NEEDED_STATUS_TYPES:
            gsum = GroupSummary.objects.get_or_create(org_summary=org_summary,
                                                      title=status_type)[0]
            sub_sums = GroupSummary.objects.filter(
                title=status_type, org_summary__in=sub_summaries).all()

            # TODO: see if moving the aggregation to the db makes it
            # faster, if this is slow
            gsum.total = sum([s.total for s in sub_sums])
            gsum.responded = sum([s.responded for s in sub_sums])
            gsum.on_time = sum([s.on_time for s in sub_sums])
            gsum.complete = sum([s.complete for s in sub_sums])
            # gsum.missed_response = sum([s.missed_response for s in sub_sums])
            gsum.save()

            if status_type == SupplyPointStatusTypes.DELIVERY_FACILITY:
                expected = len(dg.delivering())
            elif status_type == SupplyPointStatusTypes.R_AND_R_FACILITY:
                expected = len(dg.submitting())
            elif status_type == SupplyPointStatusTypes.SOH_FACILITY \
                    or status_type == SupplyPointStatusTypes.SUPERVISION_FACILITY:
                expected = len(facs)
            if gsum.total != expected:
                logging.info("expected %s but was %s for %s" %
                             (expected, gsum.total, gsum))

        for alert_type in [
                const.RR_NOT_SUBMITTED, const.DELIVERY_NOT_RECEIVED,
                const.SOH_NOT_RESPONDING, const.RR_NOT_RESPONDED,
                const.DELIVERY_NOT_RESPONDING
        ]:
            sub_alerts = Alert.objects.filter(location_id__in=fac_ids,
                                              date=window_date,
                                              type=alert_type)
            aggregate_response_alerts(location._id, window_date, sub_alerts,
                                      alert_type)
Ejemplo n.º 26
0
def process_facility_warehouse_data(facility, start_date, end_date, runner=None):
    """
    process all the facility-level warehouse tables
    """
    logging.info("processing facility %s (%s)" % (facility.name, str(facility._id)))

    sql_location = facility.sql_location
    if runner:
        runner.location = sql_location
        runner.save()

    for alert_type in [const.SOH_NOT_RESPONDING, const.RR_NOT_RESPONDED, const.DELIVERY_NOT_RESPONDING]:
        alert = Alert.objects.filter(location_id=facility._id, date__gte=start_date, date__lt=end_date,
                                     type=alert_type)
        alert.delete()

    supply_point_id = sql_location.supply_point_id
    location_id = facility._id
    new_statuses = SupplyPointStatus.objects.filter(
        location_id=facility._id,
        status_date__gte=start_date,
        status_date__lt=end_date
    ).order_by('status_date').iterator()
    process_facility_statuses(location_id, new_statuses)

    new_reports = StockReport.objects.filter(
        stocktransaction__case_id=supply_point_id,
        date__gte=start_date,
        date__lt=end_date,
        stocktransaction__type='stockonhand'
    ).distinct().order_by('date').iterator()
    process_facility_product_reports(location_id, new_reports)

    new_trans = get_latest_transaction_from_each_month(supply_point_id, start_date, end_date)
    process_facility_transactions(location_id, new_trans, start_date, end_date)

    products = SQLProduct.objects.filter(domain=facility.domain, is_archived=False)
    users = get_users_by_location_id(facility.domain, facility.get_id)

    # go through all the possible values in the date ranges
    # # and make sure there are warehouse tables there
    for year, month in months_between(start_date, end_date):
        window_date = datetime(year, month, 1)
        # create org_summary for every fac/date combo
        org_summary, created = OrganizationSummary.objects.get_or_create(
            location_id=facility._id,
            date=window_date
        )

        org_summary.total_orgs = 1
        alt = average_lead_time(facility._id, window_date)
        if alt:
            alt = alt.days
        org_summary.average_lead_time_in_days = alt or 0
        org_summary.save()

        # create group_summary for every org_summary title combo
        for title in const.NEEDED_STATUS_TYPES:
            GroupSummary.objects.get_or_create(org_summary=org_summary,
                                               title=title)
        # update all the non-response data
        not_responding_facility(org_summary)
        # alerts
        with transaction.atomic():
            populate_no_primary_alerts(facility, window_date, users)
            populate_facility_stockout_alerts(facility, window_date)

    update_product_availability_facility_data(facility, products, start_date, end_date)
    update_historical_data_for_location(facility)
Ejemplo n.º 27
0
def process_facility_warehouse_data(facility,
                                    start_date,
                                    end_date,
                                    runner=None):
    """
    process all the facility-level warehouse tables
    """
    logging.info("processing facility %s (%s)" %
                 (facility.name, str(facility.location_id)))

    sql_location = facility.sql_location
    if runner:
        runner.location = sql_location
        runner.save()

    for alert_type in [
            const.SOH_NOT_RESPONDING, const.RR_NOT_RESPONDED,
            const.DELIVERY_NOT_RESPONDING
    ]:
        alert = Alert.objects.filter(location_id=facility.location_id,
                                     date__gte=start_date,
                                     date__lt=end_date,
                                     type=alert_type)
        alert.delete()

    supply_point_id = sql_location.supply_point_id
    location_id = facility.location_id
    new_statuses = SupplyPointStatus.objects.filter(
        location_id=facility.location_id,
        status_date__gte=start_date,
        status_date__lt=end_date).order_by('status_date').iterator()
    process_facility_statuses(location_id, new_statuses)

    new_reports = StockReport.objects.filter(
        stocktransaction__case_id=supply_point_id,
        date__gte=start_date,
        date__lt=end_date,
        stocktransaction__type='stockonhand').distinct().order_by(
            'date').iterator()
    process_facility_product_reports(location_id, new_reports)

    new_trans = get_latest_transaction_from_each_month(supply_point_id,
                                                       start_date, end_date)
    process_facility_transactions(location_id, new_trans, start_date, end_date)

    products = SQLProduct.objects.filter(domain=facility.domain,
                                         is_archived=False)
    users = get_users_by_location_id(facility.domain, facility.get_id)

    # go through all the possible values in the date ranges
    # # and make sure there are warehouse tables there
    for year, month in months_between(start_date, end_date):
        window_date = datetime(year, month, 1)
        # create org_summary for every fac/date combo
        org_summary, created = OrganizationSummary.objects.get_or_create(
            location_id=facility.location_id, date=window_date)

        org_summary.total_orgs = 1
        alt = average_lead_time(facility.location_id, window_date)
        if alt:
            alt = alt.days
        org_summary.average_lead_time_in_days = alt or 0
        org_summary.save()

        # create group_summary for every org_summary title combo
        for title in const.NEEDED_STATUS_TYPES:
            GroupSummary.objects.get_or_create(org_summary=org_summary,
                                               title=title)
        # update all the non-response data
        not_responding_facility(org_summary)
        # alerts
        with transaction.atomic():
            populate_no_primary_alerts(facility, window_date, users)
            populate_facility_stockout_alerts(facility, window_date)

    update_product_availability_facility_data(facility, products, start_date,
                                              end_date)
    update_historical_data_for_location(facility)
Ejemplo n.º 28
0
def process_non_facility_warehouse_data(location, start_date, end_date, runner=None, strict=True):
    start_date = datetime(start_date.year, start_date.month, 1)
    end_date = datetime(end_date.year, end_date.month, 1)

    if runner:
        runner.location = location.sql_location
        runner.save()
    facs = get_non_archived_facilities_below(location)
    fac_ids = [f._id for f in facs]
    logging.info("processing non-facility %s (%s), %s children"
                 % (location.name, str(location.location_id), len(facs)))
    prods = SQLProduct.objects.filter(domain=location.domain, is_archived=False)

    sub_summaries = OrganizationSummary.objects.filter(
        location_id__in=fac_ids, date__range=(start_date, end_date), average_lead_time_in_days__gt=0
    ).values('date').annotate(average_time=Avg('average_lead_time_in_days'))

    sub_summaries = {
        (subsummary['date'].year, subsummary['date'].month): subsummary
        for subsummary in sub_summaries
    }

    sub_prods = ProductAvailabilityData.objects.filter(
        location_id__in=fac_ids, date__range=(start_date, end_date)
    ).values('product', 'date').annotate(
        total_sum=Sum('total'),
        with_stock_sum=Sum('with_stock'),
        without_stock_sum=Sum('without_stock'),
    )

    sub_prods = {
        ((sub_prod['date'].year, sub_prod['date'].month), sub_prod['product']): sub_prod for sub_prod in sub_prods
    }

    sub_group_summaries = GroupSummary.objects.filter(
        org_summary__location_id__in=fac_ids,
        org_summary__date__range=(start_date, end_date)
    ).values('title', 'org_summary__date').annotate(
        total_sum=Sum('total'),
        responded_sum=Sum('responded'),
        on_time_sum=Sum('on_time'),
        complete_sum=Sum('complete')
    )

    sub_group_summaries = {
        ((sub_group_summary['org_summary__date'].year, sub_group_summary['org_summary__date'].month), sub_group_summary['title']): sub_group_summary
        for sub_group_summary in sub_group_summaries
    }

    total_orgs = len(facs)
    for year, month in months_between(start_date, end_date):
        window_date = datetime(year, month, 1)
        org_summary = OrganizationSummary.objects.get_or_create(
            location_id=location.location_id, date=window_date
        )[0]

        org_summary.total_orgs = total_orgs

        # lead times
        if (year, month) in sub_summaries:
            sub_summary = sub_summaries[year, month]
            org_summary.average_lead_time_in_days = sub_summary['average_time']
        else:
            org_summary.average_lead_time_in_days = 0

        org_summary.save()
        # product availability
        for p in prods:
            product_data = ProductAvailabilityData.objects.get_or_create(product=p.product_id,
                                                                         location_id=location.location_id,
                                                                         date=window_date)[0]

            sub_prod = sub_prods.get(((year, month), p.product_id), {})

            product_data.total = sub_prod.get('total_sum', 0)
            if strict:
                assert product_data.total == total_orgs, \
                    "total should match number of sub facilities %s-%s" % (product_data.total, total_orgs)
            product_data.with_stock = sub_prod.get('with_stock_sum', 0)
            product_data.without_stock = sub_prod.get('without_stock_sum', 0)
            product_data.without_data = product_data.total - product_data.with_stock - product_data.without_stock
            product_data.save()

        dg = DeliveryGroups(month=month, facs=facs)
        for status_type in const.NEEDED_STATUS_TYPES:
            gsum = GroupSummary.objects.get_or_create(org_summary=org_summary, title=status_type)[0]

            sub_sum = sub_group_summaries.get(((year, month), status_type), {})

            gsum.total = sub_sum.get('total_sum', 0)
            gsum.responded = sub_sum.get('responded_sum', 0)
            gsum.on_time = sub_sum.get('on_time_sum', 0)
            gsum.complete = sub_sum.get('complete_sum', 0)
            gsum.save()

            if status_type == SupplyPointStatusTypes.DELIVERY_FACILITY:
                expected = len(dg.delivering())
            elif status_type == SupplyPointStatusTypes.R_AND_R_FACILITY:
                expected = len(dg.submitting())
            elif status_type == SupplyPointStatusTypes.SOH_FACILITY \
                    or status_type == SupplyPointStatusTypes.SUPERVISION_FACILITY:
                expected = len(facs)
            if gsum.total != expected:
                logging.info("expected %s but was %s for %s" % (expected, gsum.total, gsum))

        for alert_type in [const.RR_NOT_SUBMITTED, const.DELIVERY_NOT_RECEIVED,
                           const.SOH_NOT_RESPONDING, const.RR_NOT_RESPONDED, const.DELIVERY_NOT_RESPONDING]:
            sub_alerts = Alert.objects.filter(location_id__in=fac_ids, date=window_date, type=alert_type)
            aggregate_response_alerts(location.location_id, window_date, sub_alerts, alert_type)

    update_historical_data_for_location(location)
Ejemplo n.º 29
0
def update_product_availability_facility_data(facility, products, start_date, end_date):
    # product availability

    existing_data = ProductAvailabilityData.objects.filter(
        date__range=(
            datetime(start_date.year, start_date.month, 1),
            datetime(end_date.year, end_date.month, 1)
        ),
        location_id=facility.get_id
    )

    product_data_dict = {
        (pa.date, pa.location_id, pa.product): pa for pa in existing_data
    }

    product_data_list = []
    previous_month = {}
    for year, month in months_between(start_date, end_date):
        window_date = datetime(year, month, 1)
        for p in products:
            now = datetime.utcnow()
            if (window_date, facility.get_id, p.product_id) in product_data_dict:
                previous_month[p.product_id] = product_data_dict[window_date, facility.get_id, p.product_id]
                continue
            else:
                product_data = ProductAvailabilityData(
                    date=window_date,
                    location_id=facility.get_id,
                    product=p.product_id,
                    create_date=now,
                    update_date=now
                )

            # set defaults
            product_data.total = 1
            prev = None
            if p.product_id in previous_month:
                prev = previous_month[p.product_id]
            if not prev:
                previous_reports = ProductAvailabilityData.objects.filter(
                    product=p.product_id,
                    location_id=facility._id,
                    date__lt=window_date,
                    total=1
                )
                if previous_reports.count():
                    prev = previous_reports.latest('date')

            if prev:
                product_data.with_stock = prev.with_stock
                product_data.without_stock = prev.without_stock
                product_data.without_data = prev.without_data
            else:
                # otherwise we use the defaults
                product_data.with_stock = 0
                product_data.without_stock = 0
                product_data.without_data = 1
            if product_data.pk is not None:
                product_data.save()
            else:
                product_data_list.append(product_data)
            assert (product_data.with_stock + product_data.without_stock + product_data.without_data) == 1, \
                "bad product data config for %s" % product_data
            previous_month[p.product_id] = product_data
    ProductAvailabilityData.objects.bulk_create(product_data_list)
Ejemplo n.º 30
0
    def __init__(self, case, report):
        if report.snapshot is not None:
            report.filter(
                lambda key: case["_source"][key],
                # case.awc_name, case.block_name
                [("awc_name", "awcs"), ("block_name", "block"), ("owner_id", "gp"), ("closed", "is_open")],
            )
        img_elem = '<div style="width:100px !important;"><img src="/static/opm/img/%s"></div>'

        met = {
            "window_1_1": None,
            "window_1_2": None,
            "window_2_1": None,
            "window_2_2": None,
            "attendance_vhnd_3": None,
            "attendance_vhnd_6": None,
            "child1_vhndattend_calc": None,
            "prev_child1_vhndattend_calc": None,
            "child1_attendance_vhnd": None,
            "weight_tri_1": None,
            "prev_weight_tri_1": None,
            "weight_tri_2": None,
            "prev_weight_tri_2": None,
            "child1_growthmon_calc": None,
            "prev_child1_growthmon_calc": None,
            "child1_excl_breastfeed_calc": None,
            "prev_child1_excl_breastfeed_calc": None,
            "child1_ors_calc": None,
            "prev_child1_ors_calc": None,
            "child1_weight_calc": None,
            "child1_register_calc": None,
            "child1_measles_calc": None,
            "prev_child1_weight_calc": None,
            "prev_child1_register_calc": None,
            "prev_child1_measles_calc": None,
            "child1_suffer_diarrhea": None,
            "interpret_grade_1": None,
        }

        def get_property(obj, name, default=None):
            if name in obj:
                if type(obj[name]) is dict:
                    return obj[name]
                return obj[name]
            else:
                return default if default is not None else EMPTY_FIELD

        def get_property_from_forms(forms, met_properties):
            for form in forms:
                for k, v in met_properties.iteritems():
                    if k == "child1_suffer_diarrhea":
                        if "child_1" in form.form and k in form.form["child_1"]:
                            met_properties[k] = form.form["child_1"][k]
                    else:
                        if k in form.form:
                            met_properties[k] = form.form[k]
            return met_properties

        case_obj = CommCareCase.get(case["_source"]["_id"])
        self.case_id = get_property(case_obj, "_id", "")
        self.block_name = get_property(case_obj, "block_name", "")
        self.owner_id = get_property(case_obj, "owner_id", "")
        self.closed = get_property(case_obj, "closed", False)
        forms = case_obj.get_forms()
        birth_spacing_prompt = []
        for form in forms:
            if "birth_spacing_prompt" in form.form:
                birth_spacing_prompt.append(form.form["birth_spacing_prompt"])

        filtered_forms = [
            form
            for form in case_obj.get_forms()
            if report.datespan.startdate <= form.received_on <= report.datespan.enddate
        ]

        get_property_from_forms(filtered_forms, met)

        dod = get_property(case_obj, "dod")
        if dod and dod != EMPTY_FIELD:
            try:
                child_age = len(
                    months_between(datetime.datetime(dod.year, dod.month, dod.day), datetime.datetime.now())
                )
            except AssertionError:
                child_age = -1
        else:
            child_age = -1

        if get_property(case_obj, "mother_preg_outcome", "") == "1":
            self.status = "mother"
        elif get_property(case_obj, "mother_preg_outcome", "") == "":
            self.status = "pregnant"
        else:
            raise InvalidRow

        met_one = False
        met_two = False
        met_three = False
        met_four = False
        met_five = False
        preg_month = get_property(case_obj, "pregnancy_month", 0) or 0
        if self.status == "pregnant":
            if "1" in [
                met["window_1_1"],
                met["window_1_2"],
                met["window_2_1"],
                met["window_2_2"],
                met["attendance_vhnd_3"],
                met["attendance_vhnd_6"],
            ]:
                met_one = True
            if (preg_month == "6" and "1" in [met["weight_tri_1"], met["prev_weight_tri_1"]]) or (
                preg_month == "9" and "1" in [met["weight_tri_2"], met["prev_weight_tri_2"]]
            ):
                met_two = True
        elif self.status == "mother":
            if "1" in [
                met["child1_vhndattend_calc"],
                met["prev_child1_vhndattend_calc"],
                met["child1_attendance_vhnd"],
            ]:
                met_one = True
            if "1" in [met["child1_growthmon_calc"], met["prev_child1_growthmon_calc"]]:
                met_two = True
            if (
                (child_age == 3 and (met["child1_weight_calc"] or met["prev_child1_weight_calc"]))
                or (child_age == 6 and (met["child1_register_calc"] or met["prev_child1_register_calc"]))
                or (child_age == 9 and (met["child1_measles_calc"] or met["prev_child1_measles_calc"]))
            ):
                met_three = True
            if child_age == 6 and (
                "1" in [met["child1_excl_breastfeed_calc"], met["prev_child1_excl_breastfeed_calc"]]
            ):
                met_four = True
            if child_age in [6, 9, 12] and "1" in [met["child1_ors_calc"], met["prev_child1_ors_calc"]]:
                met_five = True

        self.name = get_property(case_obj, "name")
        self.awc_name = get_property(case_obj, "awc_name")
        self.husband_name = get_property(case_obj, "husband_name")
        self.window = get_property(case_obj, "which_window")
        if self.status == "pregnant":
            self.preg_month = get_property(case_obj, "pregnancy_month")
            self.child_age = EMPTY_FIELD
            self.one = img_elem % M_ATTENDANCE_Y if preg_month == "9" else img_elem % M_ATTENDANCE_N
            self.two = img_elem % M_WEIGHT_Y if preg_month in ["6", "9"] else img_elem % M_WEIGHT_N
            self.three = img_elem % IFA_Y if int(preg_month) < 7 else img_elem % IFA_N
            self.four = ""
            if report.block.lower() == "wazirganj":
                if child_age > 23 and "1" in birth_spacing_prompt:
                    self.five = img_elem % SPACING_PROMPT_Y
                else:
                    self.five = img_elem % SPACING_PROMPT_N
            else:
                self.five = ""

        elif self.status == "mother":
            self.preg_month = EMPTY_FIELD
            if child_age != -1:
                self.child_age = child_age
            else:
                self.child_age = EMPTY_FIELD

            self.one = img_elem % C_ATTENDANCE_Y if 0 <= child_age <= 1 else img_elem % C_ATTENDANCE_N
            self.two = img_elem % C_WEIGHT_Y if child_age % 3 == 0 else img_elem % C_WEIGHT_N

            if child_age == 3:
                if met["child1_weight_calc"] or met["prev_child1_weight_calc"]:
                    self.three = img_elem % CHILD_WEIGHT_Y
                else:
                    self.three = img_elem % CHILD_WEIGHT_N
            elif child_age == 6:
                if met["child1_register_calc"] or met["prev_child1_register_calc"]:
                    self.three = img_elem % C_REGISTER_Y
                else:
                    self.three = img_elem % C_REGISTER_N
            elif child_age == 9:
                if met["child1_measles_calc"] or met["prev_child1_measles_calc"]:
                    self.three = img_elem % MEASLEVACC_Y
                else:
                    self.three = img_elem % MEASLEVACC_N
            else:
                self.three = ""

            self.four = img_elem % EXCBREASTFED_Y if child_age == 6 else img_elem % EXCBREASTFED_N

            if child_age in [3, 6, 9]:
                if met["child1_suffer_diarrhea"] == "1":
                    self.five = img_elem % ORSZNTREAT_Y
                else:
                    self.five = img_elem % ORSZNTREAT_N
            elif child_age == [24, 36]:
                if met["interpret_grade_1"] == "normal":
                    self.five = img_elem % GRADE_NORMAL_Y
                else:
                    self.five = img_elem % GRADE_NORMAL_N
            else:
                self.five = ""

        if report.block.lower() == "atri":
            if child_age == 24:
                self.cash = '<span style="color: green;">Rs. 2000</span>'
            elif child_age == 36:
                self.cash = '<span style="color: green;">Rs. 3000</span>'
            elif met_one or met_two or met_three or met_four or met_five:
                self.cash = '<span style="color: green;">Rs. 250</span>'
            else:
                self.cash = '<span style="color: red;">Rs. 0</span>'

        elif report.block.lower() == "wazirganj":
            if met_one or met_two or met_four or met_five:
                self.cash = '<span style="color: green;">Rs. 250</span>'
            else:
                self.cash = '<span style="color: red;">Rs. 0</span>'