def _is_valid_status(facility, date, status_type): if status_type not in const.NEEDED_STATUS_TYPES: return False groups = HistoricalLocationGroup.objects.filter( date__month=date.month, date__year=date.year, location_id=facility.sql_location ) if (not facility.metadata.get('group', None)) and (groups.count() == 0): return False if groups.count() > 0: codes = [group.group for group in groups] else: try: latest_group = HistoricalLocationGroup.objects.filter( location_id=facility.sql_location ).latest('date') if date.date() < latest_group.date: return False else: codes = [facility.metadata['group']] except HistoricalLocationGroup.DoesNotExist: codes = [facility.metadata['group']] dg = DeliveryGroups(date.month) if status_type == SupplyPointStatusTypes.R_AND_R_FACILITY: return dg.current_submitting_group() in codes elif status_type == SupplyPointStatusTypes.DELIVERY_FACILITY: return dg.current_delivering_group() in codes return True
def last_location_group(location): try: gs = GroupSummary.objects.filter( total=1, org_summary__location_id=location.get_id, title=SupplyPointStatusTypes.DELIVERY_FACILITY ).latest('org_summary__date') except GroupSummary.DoesNotExist: return delivery_groups = DeliveryGroups(gs.org_summary.date.month) return delivery_groups.current_delivering_group()
def _is_valid_status(facility, date, status_type): if status_type not in const.NEEDED_STATUS_TYPES: return False code = facility.metadata.get('group') if not code: return False dg = DeliveryGroups(date.month) if status_type == SupplyPointStatusTypes.R_AND_R_FACILITY: return dg.current_submitting_group() == code elif status_type == SupplyPointStatusTypes.DELIVERY_FACILITY: return dg.current_delivering_group() == code return True
def rows(self): if self.config['org_summary']: def prepare_processing_info(data): return { 'total': data[0] - (data[1] + data[2]), 'complete': 0 } org_summary = self.config['org_summary'][0] total = org_summary.total_orgs avg_lead_time = org_summary.average_lead_time_in_days if avg_lead_time: avg_lead_time = "%.1f" % avg_lead_time endmonth = self.config['enddate'].month dg = DeliveryGroups(month=endmonth) rr_data = RandRSubmissionData(config=self.config).rows[0] delivery_data = DeliverySubmissionData(config=self.config).rows[0] submitting_group = dg.current_submitting_group(month=endmonth) processing_group = dg.current_processing_group(month=endmonth) delivery_group = dg.current_delivering_group(month=endmonth) (rr_complete, rr_total) = (rr_data.complete, rr_data.total) if rr_data else (0, 0) if delivery_data: (delivery_complete, delivery_total) = (delivery_data.complete, delivery_data.total) else: (delivery_complete, delivery_total) = (0, 0) processing_numbers = prepare_processing_info([total, rr_total, delivery_total]) return { "processing_total": processing_numbers['total'], "processing_complete": processing_numbers['complete'], "submitting_total": rr_total, "submitting_complete": rr_complete, "delivery_total": delivery_total, "delivery_complete": delivery_complete, "delivery_group": delivery_group, "submitting_group": submitting_group, "processing_group": processing_group, "total": total, "avg_lead_time": avg_lead_time, } else: return None
def __init__(self, config=None, css_class='row_chart'): super(RRReportingHistory, self).__init__(config, css_class) self.config = config or {} self.css_class = css_class datespan_type = self.config.get('datespan_type') if datespan_type == 1: self.title = "R&R Reporting History (Group %s)" %\ DeliveryGroups(int(self.config['datespan_first'])).current_submitting_group() else: self.title = "R&R Reporting History"
def __init__(self, config=None, css_class='row_chart'): super(DeliveryStatus, self).__init__(config, css_class) self.config = config or {} self.css_class = css_class datespan_type = self.config.get('datespan_type') if datespan_type == 1: self.title = "Delivery Status: Group %s" %\ DeliveryGroups(int(self.config['datespan_first'])).current_delivering_group() else: self.title = "Delivery Status"
def setUpClass(cls): super(TestReportSummaryBase, cls).setUpClass() delete_domain_phone_numbers(TEST_DOMAIN) cls.sms_backend, cls.sms_backend_mapping = setup_default_sms_test_backend() cls.domain = prepare_domain(TEST_DOMAIN) cls.district = make_loc(code="dis1", name="TEST DISTRICT", type="DISTRICT", domain=TEST_DOMAIN, metadata={'group': DeliveryGroups().current_submitting_group()}) cls.facility = make_loc(code="d10001", name="Test Facility 1", type="FACILITY", domain=TEST_DOMAIN, parent=cls.district, metadata={'group': DeliveryGroups().current_submitting_group()}) cls.facility2 = make_loc(code="d10002", name="Test Facility 2", type="FACILITY", domain=TEST_DOMAIN, parent=cls.district, metadata={'group': DeliveryGroups().current_delivering_group()}) cls.facility3 = make_loc(code="d10003", name="Test Facility 3", type="FACILITY", domain=TEST_DOMAIN, parent=cls.district, metadata={'group': DeliveryGroups().current_submitting_group()}) cls.facilities = [cls.facility, cls.facility2, cls.facility3] cls.district_user = bootstrap_user( cls.district, username='******', domain=TEST_DOMAIN, home_loc='dis1', phone_number='1234', first_name='test', last_name='Test' ) cls.contact1 = bootstrap_user( cls.facility, username='******', domain=TEST_DOMAIN, home_loc='d10001', phone_number='1235', first_name='test', last_name='Test' ) cls.contact2 = bootstrap_user( cls.facility2, username='******', domain=TEST_DOMAIN, home_loc='d10002', phone_number='1236', first_name='test', last_name='Test' ) cls.contact3 = bootstrap_user( cls.facility3, username='******', domain=TEST_DOMAIN, home_loc='d10003', phone_number='1237', first_name='test', last_name='Test' ) for facility in cls.facilities: facility.metadata['group'] = cls.relevant_group() facility.save() create_products(cls, TEST_DOMAIN, ["id", "dp", "fs", "md", "ff", "dx", "bp", "pc", "qi", "jd", "mc", "ip"])
def test_group_exclusion(self): people = list( RandrReminder(TEST_DOMAIN, datetime.utcnow()).get_people()) self.assertEqual(len(people), 1) self.assertEqual(people[0].get_id, self.user1.get_id) self.facility.metadata['group'] = DeliveryGroups( ).current_delivering_group() self.facility.save() people = list( RandrReminder(TEST_DOMAIN, datetime.utcnow()).get_people()) self.assertEqual(len(people), 0) self.facility.metadata['group'] = DeliveryGroups( ).current_processing_group() self.facility.save() people = list( RandrReminder(TEST_DOMAIN, datetime.utcnow()).get_people()) self.assertEqual(len(people), 0)
def _is_valid_status(facility, date, status_type): if status_type not in NEEDED_STATUS_TYPES: return False groups = HistoricalLocationGroup.objects.filter( date__month=date.month, date__year=date.year, location_id=facility.sql_location ) if (not facility.metadata.get('group', None)) and (groups.count() == 0): return False if groups.count() > 0: code = groups[0].group else: code = facility.metadata['group'] dg = DeliveryGroups(date.month) if status_type == SupplyPointStatusTypes.R_AND_R_FACILITY: return code == dg.current_submitting_group() elif status_type == SupplyPointStatusTypes.DELIVERY_FACILITY: return code == dg.current_delivering_group() return True
def rows(self): rows = [] locations = SQLLocation.objects.filter(parent__location_id=self.config['location_id']) dg = [] for date in list(rrule.rrule(rrule.MONTHLY, dtstart=self.config['startdate'], until=self.config['enddate'])): dg.extend(DeliveryGroups().delivering(locations, date.month)) for child in dg: group_summary = GroupSummary.objects.filter( org_summary__date__lte=self.config['startdate'], org_summary__location_id=child.location_id, title=SupplyPointStatusTypes.DELIVERY_FACILITY, total=1 ).exists() if not group_summary: continue latest = latest_status_or_none( child.location_id, SupplyPointStatusTypes.DELIVERY_FACILITY, self.config['startdate'], self.config['enddate'] ) status_name = latest.name if latest else "" status_date = latest.status_date.strftime("%d-%m-%Y") if latest else "None" url = make_url(FacilityDetailsReport, self.config['domain'], '?location_id=%s&filter_by_program=%s&' 'datespan_type=%s&datespan_first=%s&datespan_second=%s', (child.location_id, self.config['program'], self.config['datespan_type'], self.config['datespan_first'], self.config['datespan_second'])) cycle_lead_time = get_this_lead_time( child.location_id, self.config['startdate'], self.config['enddate'] ) avg_lead_time = get_avg_lead_time(child.location_id, self.config['startdate'], self.config['enddate']) rows.append( [ child.site_code, link_format(child.name, url), status_name, status_date, cycle_lead_time, avg_lead_time ] ) return rows
def _is_valid_status(facility, date, type): if type not in NEEDED_STATUS_TYPES: return False facility = Location.get(docid=facility) groups = HistoricalLocationGroup.objects.filter( date__month=date.month, date__year=date.year, location_id=facility.sql_location ) if (not facility.metadata.get('groups', [])) and (groups.count() == 0): return False if groups.count() > 0: code = groups[0].group else: code = facility.metadata['groups'][0] dg = DeliveryGroups(date.month) if type.startswith('rr'): return code == dg.current_submitting_group() elif type.startswith('del'): return code == dg.current_delivering_group() return True
def test_delivery_group_basic(self): submitting_group = DeliveryGroups().current_submitting_group() original_submitting = len( list( get_sql_locations_by_domain_and_group(TEST_DOMAIN, submitting_group))) for location in Location.by_domain(TEST_DOMAIN): if location.metadata.get('group') != submitting_group: location.metadata['group'] = submitting_group location.save() break new_submitting = len( list( get_sql_locations_by_domain_and_group(TEST_DOMAIN, submitting_group))) self.assertEqual(original_submitting + 1, new_submitting)
def delivery_data_total(self): current_delivering_group = DeliveryGroups(self.start_date.month).current_delivering_group() location_ids = self.get_location_ids(current_delivering_group) if not location_ids: return {} query = """ SELECT status_value, COUNT(location_id) FROM ( SELECT DISTINCT ON (location_id) location_id, status_value FROM ilsgateway_supplypointstatus WHERE status_date BETWEEN %s AND %s AND status_type = 'del_fac' AND status_value != 'reminder_sent' AND location_id IN %s ORDER BY location_id, status_date DESC )x GROUP BY status_value; """ with connection.cursor() as cursor: cursor.execute(query, [self.start_date, self.end_date, location_ids]) rows = cursor.fetchall() rows.append(('total', len(location_ids))) return dict(rows)
def send_delivery_reminder(domain, date, loc_type='FACILITY', test_list=None): if loc_type == 'FACILITY': status_type = SupplyPointStatusTypes.DELIVERY_FACILITY sms_text = REMINDER_DELIVERY_FACILITY elif loc_type == 'DISTRICT': status_type = SupplyPointStatusTypes.DELIVERY_DISTRICT sms_text = REMINDER_DELIVERY_DISTRICT else: return current_group = DeliveryGroups().current_delivering_group(date.month) sp_ids = set() users = CommCareUser.by_domain(domain) if not test_list else test_list for user in users: location = user.location if user.is_active and location and location.location_type == loc_type: status_exists = SupplyPointStatus.objects.filter( location_id=location.get_id, status_type=status_type, status_date__gte=date).exists() groups = location.metadata.get('group', None) if groups and current_group in groups and not status_exists: send_translated_message(user, sms_text) update_statuses(sp_ids, status_type, SupplyPointStatusValues.REMINDER_SENT)
def relevant_group(cls): # this doesn't really matter since it's relevant every month return DeliveryGroups().current_delivering_group()
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)
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)
def relevant_group(cls): return DeliveryGroups().current_submitting_group()
def current_group(self): return DeliveryGroups().current_delivering_group(self.date.month)
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)
def rows(self): rows = [] locations = SQLLocation.objects.filter( parent__location_id=self.config['location_id']) dg = [] for date in list( rrule.rrule(rrule.MONTHLY, dtstart=self.config['startdate'], until=self.config['enddate'])): dg.extend(DeliveryGroups().submitting(locations, date.month)) for child in dg: total_responses = 0 total_possible = 0 submitted, rr_value = randr_value(child.location_id, self.config['startdate'], self.config['enddate']) if child.is_archived and not rr_value: continue group_summaries = GroupSummary.objects.filter( org_summary__date__lte=self.config['startdate'], org_summary__location_id=child.location_id, title=SupplyPointStatusTypes.R_AND_R_FACILITY, total=1) if not group_summaries: continue for group_summary in group_summaries: if group_summary: total_responses += group_summary.responded total_possible += group_summary.total hist_resp_rate = rr_format_percent(total_responses, total_possible) url = make_url( FacilityDetailsReport, self.config['domain'], '?location_id=%s&filter_by_program=%s&' 'datespan_type=%s&datespan_first=%s&datespan_second=%s', (child.location_id, self.config['program'], self.config['datespan_type'], self.config['datespan_first'], self.config['datespan_second'])) contact = get_one_user_at_location(self.config['domain'], child.location_id) if contact: role = contact.user_data.get('role') or "" args = (contact.first_name, contact.last_name, role, contact.default_phone_number) contact_string = "%s %s (%s) %s" % args else: contact_string = "" rows.append([ child.site_code, link_format(child.name, url), get_span(submitted) % (rr_value.strftime("%d %b %Y") if rr_value else "Not reported"), contact_string, hist_resp_rate ]) return rows
def setUp(self): super(TestDeliveryReminder, self).setUp() self.facility.metadata['group'] = DeliveryGroups( ).current_delivering_group() self.facility.save()
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)
def setUp(self): super(TestSupervisionStatusSet, self).setUp() self.facility.metadata['group'] = DeliveryGroups( ).current_submitting_group() self.facility.save()
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)