def get_data(self): startkey = [self.domain, self.active_location._id if self.active_location else None] product_cases = SPPCase.view('commtrack/product_cases', startkey=startkey, endkey=startkey + [{}], include_docs=True) if self.program_id: product_cases = filter(lambda c: Product.get(c.product).program_id == self.program_id, product_cases) def latest_case(cases): # getting last report date should probably be moved to a util function in a case wrapper class return max(cases, key=lambda c: getattr(c, 'last_reported', datetime(2000, 1, 1)).date()) cases_by_site = map_reduce(lambda c: [(tuple(c.location_),)], lambda v: reporting_status(latest_case(v), self.start_date, self.end_date), data=product_cases, include_docs=True) # TODO if aggregating, won't want to fetch all these locs (will only want to fetch aggregation sites) locs = dict((loc._id, loc) for loc in Location.view( '_all_docs', keys=[path[-1] for path in cases_by_site.keys()], include_docs=True)) for path, status in cases_by_site.iteritems(): loc = locs[path[-1]] yield { 'loc_id': loc._id, 'loc_path': loc.path, 'name': loc.name, 'type': loc.location_type, 'reporting_status': status, 'geo': loc._geopoint, }
def get_data(self, slugs=None): startkey = [self.domain, self.active_location._id if self.active_location else None] if self.active_product: startkey.append(self.active_product['_id']) product_cases = SPPCase.view('commtrack/product_cases', startkey=startkey, endkey=startkey + [{}], include_docs=True) if self.config.get('aggregate'): return self.aggregate_cases(product_cases, slugs) else: return self.raw_cases(product_cases, slugs)
def _data(self): startkey = [self.domain, self.active_location._id if self.active_location else None] product_cases = SPPCase.view('commtrack/product_cases', startkey=startkey, endkey=startkey + [{}], include_docs=True) def latest_case(cases): # getting last report date should probably be moved to a util function in a case wrapper class return max(cases, key=lambda c: getattr(c, 'last_reported', datetime(2000, 1, 1)).date()) cases_by_site = map_reduce(lambda c: [(tuple(c.location_),)], lambda v: reporting_status(latest_case(v)), data=product_cases, include_docs=True) def child_loc(path): root = self.active_location ix = path.index(root._id) if root else -1 try: return path[ix + 1] except IndexError: return None def case_iter(): for k, v in cases_by_site.iteritems(): if child_loc(k) is not None: yield (k, v) status_by_agg_site = map_reduce(lambda (path, status): [(child_loc(path), status)], data=case_iter()) sites_by_agg_site = map_reduce(lambda (path, status): [(child_loc(path), path[-1])], data=case_iter()) def status_tally(statuses): total = len(statuses) return map_reduce(lambda s: [(s,)], lambda v: {'count': len(v), 'pct': len(v) / float(total)}, data=statuses) status_counts = dict((loc_id, status_tally(statuses)) for loc_id, statuses in status_by_agg_site.iteritems()) master_tally = status_tally(cases_by_site.values()) locs = sorted(Location.view('_all_docs', keys=status_counts.keys(), include_docs=True), key=lambda loc: loc.name) def fmt(pct): return '%.1f%%' % (100. * pct) def fmt_col(loc, col_type): return fmt(status_counts[loc._id].get(col_type, {'pct': 0.})['pct']) def _rows(): for loc in locs: num_sites = len(sites_by_agg_site[loc._id]) yield [loc.name, len(sites_by_agg_site[loc._id])] + [fmt_col(loc, k) for k in ('ontime', 'late', 'nonreporting')] return master_tally, _rows()
def get_prod_data(self): startkey = [self.domain, self.active_location._id if self.active_location else None] product_cases = SPPCase.view('commtrack/product_cases', startkey=startkey, endkey=startkey + [{}], include_docs=True) cases_by_product = map_reduce(lambda c: [(c.product,)], data=product_cases, include_docs=True) products = Product.view('_all_docs', keys=cases_by_product.keys(), include_docs=True) def status(case): return case.current_stock_category if is_timely(case, 1000) else 'nonreporting' status_by_product = dict((p, map_reduce(lambda c: [(status(c),)], len, data=cases)) for p, cases in cases_by_product.iteritems()) cols = ['stockout', 'understock', 'adequate', 'overstock', 'nodata'] #'nonreporting', 'nodata'] for p in sorted(products, key=lambda p: p.name): cases = cases_by_product.get(p._id, []) results = status_by_product.get(p._id, {}) def val(key): return results.get(key, 0) / float(len(cases)) yield [p.name, len(cases)] + [100. * val(key) for key in cols]
def get_prod_data(self): startkey = [self.domain, self.active_location._id if self.active_location else None] product_cases = SPPCase.view('commtrack/product_cases', startkey=startkey, endkey=startkey + [{}], include_docs=True) cases_by_product = map_reduce(lambda c: [(c.product,)], data=product_cases, include_docs=True) products = Product.view('_all_docs', keys=cases_by_product.keys(), include_docs=True) def _sum(vals): return sum(vals) if vals else None def aggregate_product(cases): data = [(c.current_stock_level, c.monthly_consumption) for c in cases if is_timely(c, 1000)] total_stock = _sum([d[0] for d in data if d[0] is not None]) total_consumption = _sum([d[1] for d in data if d[1] is not None]) # exclude stock values w/o corresponding consumption figure from total months left calculation consumable_stock = _sum([d[0] for d in data if d[0] is not None and d[1] is not None]) return { 'total_stock': total_stock, 'total_consumption': total_consumption, 'consumable_stock': consumable_stock, } status_by_product = dict((p, aggregate_product(cases)) for p, cases in cases_by_product.iteritems()) for p in sorted(products, key=lambda p: p.name): stats = status_by_product[p._id] months_left = SPPCase.months_of_stock_remaining(stats['consumable_stock'], stats['total_consumption']) category = SPPCase.stock_category(stats['total_stock'], stats['total_consumption'], stats['consumable_stock']) yield [ p.name, stats['total_stock'], stats['total_consumption'], months_left, category, ]