示例#1
0
    def get_data(self):
        sp_ids = get_relevant_supply_point_ids(
            self.domain,
            self.active_location
        )

        products = Product.by_domain(self.domain)
        if self.program_id:
            products = filter(
                lambda product: product.program_id == self.program_id, products
            )

        for sp_id in sp_ids:
            for product in products:
                loc = SupplyPointCase.get(sp_id).location
                last_transaction = StockTransaction.latest(
                    sp_id,
                    STOCK_SECTION_TYPE,
                    product._id
                )

                yield {
                    'loc_id': loc._id,
                    'loc_path': loc.path,
                    'name': loc.name,
                    'type': loc.location_type,
                    'reporting_status': reporting_status(
                        last_transaction,
                        self.start_date,
                        self.end_date
                    ),
                    'geo': loc._geopoint,
                }
示例#2
0
    def get_prod_data(self):
        sp_ids = get_relevant_supply_point_ids(self.domain, self.active_location)

        stock_states = StockState.objects.filter(case_id__in=sp_ids).order_by('product_id')

        product_grouping = {}
        for state in stock_states:
            status = state.stock_category()
            if state.product_id in product_grouping:
                product_grouping[state.product_id][status] += 1
                product_grouping[state.product_id]['facility_count'] += 1

            else:
                product_grouping[state.product_id] = {
                    'obj': Product.get(state.product_id),
                    'stockout': 0,
                    'understock': 0,
                    'overstock': 0,
                    'adequate': 0,
                    'nodata': 0,
                    'facility_count': 1
                }
                product_grouping[state.product_id][status] = 1

        for product in product_grouping.values():
            yield [
                product['obj'].name,
                product['facility_count'],
                100.0 * product['stockout'] / product['facility_count'],
                100.0 * product['understock'] / product['facility_count'],
                100.0 * product['adequate'] / product['facility_count'],
                100.0 * product['overstock'] / product['facility_count'],
                100.0 * product['nodata'] / product['facility_count'],
            ]
    def chart_data(self):
        def calculate_weeks_remaining(stock_state, date):

            if stock_state.last_modified_date < date:
                if not stock_state.daily_consumption:
                    return 0
                consumption = float(stock_state.daily_consumption) * 7.0
                quantity = float(stock_state.stock_on_hand) - int((date - state.last_modified_date).days / 7.0) \
                    * consumption
                if consumption and consumption > 0 and quantity > 0:
                    return quantity / consumption
            return 0

        stock_states = StockState.include_archived.filter(
            case_id__in=get_relevant_supply_point_ids(self.config['domain'], self.sublocations[0]),
            section_id=STOCK_SECTION_TYPE,
            product_id__in=self.get_products(),
            last_modified_date__lte=self.config['enddate'],
        ).order_by('last_modified_date')

        rows = {}
        for state in stock_states:
            product_name = Product.get(state.product_id).name
            rows[product_name] = []
            weeks = ceil((self.config['enddate'] - self.config['startdate']).days / 7.0)
            for i in range(1, int(weeks + 1)):
                rows[product_name].append({'x': i, 'y': calculate_weeks_remaining(state, self.config['startdate'] +
                                                                                  timedelta(weeks=i))})
        return rows
示例#4
0
    def get_data(self):
        sp_ids = get_relevant_supply_point_ids(self.domain, self.active_location)

        stock_states = StockState.objects.filter(
            section_id=STOCK_SECTION_TYPE,
        )

        if self.program_id:
            stock_states = stock_states.filter(sql_product__program_id=self.program_id)

        if len(sp_ids) == 1:
            stock_states = stock_states.filter(
                case_id=sp_ids[0],
            )

            return self.leaf_node_data(stock_states)
        else:
            stock_states = stock_states.filter(
                case_id__in=sp_ids,
            )

            if self.config.get('aggregate'):
                return self.aggregated_data(stock_states)
            else:
                return self.raw_product_states(stock_states)
示例#5
0
    def get_data(self, slugs=None):
        sp_ids = get_relevant_supply_point_ids(self.domain, self.active_location)

        if len(sp_ids) == 1:
            stock_states = StockState.objects.filter(
                case_id=sp_ids[0],
                section_id=STOCK_SECTION_TYPE,
                last_modified_date__lte=self.end_date,
                last_modified_date__gte=self.start_date,
            )

            if self.program_id:
                stock_states = self.filter_by_program(stock_states)

            return self.leaf_node_data(stock_states)
        else:
            stock_states = StockState.objects.filter(
                case_id__in=sp_ids,
                section_id=STOCK_SECTION_TYPE,
                last_modified_date__lte=self.end_date,
                last_modified_date__gte=self.start_date,
            )

            if self.program_id:
                stock_states = self.filter_by_program(stock_states)

            if self.config.get('aggregate'):
                aggregates = stock_states.values('product_id').annotate(
                    avg_consumption=Avg('daily_consumption'),
                    total_stock=Sum('stock_on_hand')
                )
                return self.aggregated_data(aggregates)
            else:
                return self.raw_product_states(stock_states, slugs)
示例#6
0
    def get_data(self, slugs=None):
        sp_ids = get_relevant_supply_point_ids(self.domain,
                                               self.active_location)

        if len(sp_ids) == 1:
            stock_states = StockState.objects.filter(
                case_id=sp_ids[0],
                section_id=STOCK_SECTION_TYPE,
                last_modified_date__lte=self.end_date,
                last_modified_date__gte=self.start_date,
            )

            if self.program_id:
                stock_states = self.filter_by_program(stock_states)

            return self.leaf_node_data(stock_states)
        else:
            stock_states = StockState.objects.filter(
                case_id__in=sp_ids,
                section_id=STOCK_SECTION_TYPE,
                last_modified_date__lte=self.end_date,
                last_modified_date__gte=self.start_date,
            )

            if self.program_id:
                stock_states = self.filter_by_program(stock_states)

            if self.config.get('aggregate'):
                return self.aggregated_data(stock_states)
            else:
                return self.raw_product_states(stock_states, slugs)
示例#7
0
    def get_data(self, slugs=None):
        sp_ids = get_relevant_supply_point_ids(self.domain, self.active_location)

        stock_states = StockState.objects.filter(
            section_id=STOCK_SECTION_TYPE,
            last_modified_date__lte=self.end_date,
            last_modified_date__gte=self.start_date,
        )

        if len(sp_ids) == 1:
            stock_states = stock_states.filter(
                case_id=sp_ids[0],
            )

            if self.program_id:
                stock_states = self.filter_by_program(stock_states)

            return self.leaf_node_data(stock_states)
        else:
            stock_states = stock_states.filter(
                case_id__in=sp_ids,
            )

            if self.program_id:
                stock_states = self.filter_by_program(stock_states)

            if self.config.get('aggregate'):
                return self.aggregated_data(stock_states)
            else:
                return self.raw_product_states(stock_states, slugs)
示例#8
0
 def total_records(self):
     sp_ids = get_relevant_supply_point_ids(self.domain,
                                            self.active_location)
     product_ids = get_product_ids_for_program(
         self.domain, self.program_id) if self.program_id else None
     return get_total_records(self.domain, sp_ids, STOCK_SECTION_TYPE,
                              product_ids)
示例#9
0
 def get_data(self):
     sp_ids = get_relevant_supply_point_ids(self.domain, self.active_location)
     if len(sp_ids) == 1:
         return self.leaf_node_data(sp_ids[0])
     else:
         if self.config.get('aggregate'):
             return self.aggregated_data(sp_ids)
         else:
             return self.raw_product_states(sp_ids)
示例#10
0
    def get_data(self):
        # todo: this will probably have to paginate eventually
        if self.all_relevant_forms:
            sp_ids = get_relevant_supply_point_ids(
                self.domain,
                self.active_location,
            )

            form_xmlnses = [form['xmlns'] for form in self.all_relevant_forms.values()]
            spoint_loc_map = {
                doc['_id']: doc['location_id']
                for doc in iter_docs(SupplyPointCase.get_db(), sp_ids)
            }
            locations = {
                doc['_id']: Location.wrap(doc)
                for doc in iter_docs(Location.get_db(), spoint_loc_map.values())
            }

            for spoint_id, loc_id in spoint_loc_map.items():
                loc = locations[loc_id]

                form_ids = StockReport.objects.filter(
                    stocktransaction__case_id=spoint_id
                ).exclude(
                    date__lte=self.start_date
                ).exclude(
                    date__gte=self.end_date
                ).values_list(
                    'form_id', flat=True
                ).order_by('-date').distinct()  # not truly distinct due to ordering
                matched = False
                for form_id in form_ids:
                    try:
                        if XFormInstance.get(form_id).xmlns in form_xmlnses:
                            yield {
                                'loc_id': loc._id,
                                'loc_path': loc.path,
                                'name': loc.name,
                                'type': loc.location_type,
                                'reporting_status': 'reporting',
                                'geo': loc._geopoint,
                            }
                            matched = True
                            break
                    except ResourceNotFound:
                        logging.error('Stock report for location {} in {} references non-existent form {}'.format(
                            loc._id, loc.domain, form_id
                        ))
                if not matched:
                    yield {
                        'loc_id': loc._id,
                        'loc_path': loc.path,
                        'name': loc.name,
                        'type': loc.location_type,
                        'reporting_status': 'nonreporting',
                        'geo': loc._geopoint,
                    }
示例#11
0
 def get_data(self):
     sp_ids = get_relevant_supply_point_ids(self.domain, self.active_location)
     if len(sp_ids) == 1:
         return self.leaf_node_data(sp_ids[0])
     else:
         if self.config.get('aggregate'):
             return self.aggregated_data(sp_ids)
         else:
             return self.raw_product_states(sp_ids)
示例#12
0
    def rows(self):
        rows = []
        if not self.config['products']:
            prd_id = SQLProduct.objects.filter(domain=self.config['domain'])\
                .order_by('code').values_list('product_id')
        else:
            prd_id = self.config['products']

        if self.config['location_id']:

            location = Location.get(self.config['location_id'])
            for loc in location.children:
                org_summary = OrganizationSummary.objects.filter(date__range=(self.config['startdate'],
                                                                 self.config['enddate']),
                                                                 supply_point=loc._id)[0]

                soh_data = GroupSummary.objects.get(title=SupplyPointStatusTypes.SOH_FACILITY,
                                                    org_summary=org_summary)
                facs = Location.filter_by_type(self.config['domain'], 'FACILITY', loc)
                facs_count = (float(len(list(facs))) or 1)
                soh_on_time = soh_data.on_time * 100 / facs_count
                soh_late = soh_data.late * 100 / facs_count
                soh_not_responding = soh_data.not_responding * 100 / facs_count
                fac_ids = get_relevant_supply_point_ids(self.config['domain'], loc)
                stockouts = (StockTransaction.objects.filter(
                    case_id__in=fac_ids, quantity__lte=0,
                    report__date__month=int(self.config['month']),
                    report__date__year=int(self.config['year'])).count() or 0) / facs_count

                url = make_url(
                    StockOnHandReport,
                    self.config['domain'],
                    '?location_id=%s&month=%s&year=%s',
                    (loc._id, self.config['month'], self.config['year']))

                row_data = [
                    link_format(loc.name, url),
                    format_percent(soh_on_time),
                    format_percent(soh_late),
                    format_percent(soh_not_responding),
                    format_percent(stockouts)
                ]

                for product in prd_id:
                    ps = ProductAvailabilityData.objects.filter(
                        supply_point=loc._id,
                        product=product,
                        date=self.config['startdate'])
                    if ps:
                        row_data.append(format_percent(ps[0].without_stock * 100 / float(ps[0].total)))
                    else:
                        row_data.append("<span class='no_data'>None</span>")
                rows.append(row_data)

        return rows
示例#13
0
    def get_prod_data(self):
        sp_ids = get_relevant_supply_point_ids(self.domain, self.active_location)

        stock_states = StockState.include_archived.filter(
            case_id__in=sp_ids,
            last_modified_date__lte=self.datespan.enddate_utc,
            last_modified_date__gte=self.datespan.startdate_utc,
            section_id=STOCK_SECTION_TYPE
        )
        if not self.archived_products:
            stock_states = stock_states.exclude(
                sql_product__is_archived=True
            )

        stock_states = stock_states.order_by('product_id')

        if self.program_id:
            stock_states = stock_states.filter(
                product_id__in=product_ids_filtered_by_program(
                    self.domain,
                    self.program_id
                )
            )

        product_grouping = {}
        for state in stock_states:
            status = state.stock_category
            if state.product_id in product_grouping:
                product_grouping[state.product_id][status] += 1
                product_grouping[state.product_id]['facility_count'] += 1

            else:
                product_grouping[state.product_id] = {
                    'obj': Product.get(state.product_id),
                    'stockout': 0,
                    'understock': 0,
                    'overstock': 0,
                    'adequate': 0,
                    'nodata': 0,
                    'facility_count': 1
                }
                product_grouping[state.product_id][status] = 1

        for product in product_grouping.values():
            yield [
                product['obj'].name,
                product['facility_count'],
                100.0 * product['stockout'] / product['facility_count'],
                100.0 * product['understock'] / product['facility_count'],
                100.0 * product['adequate'] / product['facility_count'],
                100.0 * product['overstock'] / product['facility_count'],
                100.0 * product['nodata'] / product['facility_count'],
            ]
示例#14
0
 def get_data(self, slugs=None):
     sp_ids = get_relevant_supply_point_ids(self.domain, self.active_location)
     if len(sp_ids) == 1:
         stock_states = StockState.objects.filter(case_id=sp_ids[0])
         return self.leaf_node_data(stock_states)
     else:
         stock_states = StockState.objects.filter(case_id__in=sp_ids)
         if self.config.get('aggregate'):
             aggregates = stock_states.values('product_id').annotate(
                 avg_consumption=Avg('daily_consumption'),
                 total_stock=Sum('stock_on_hand')
             )
             return self.aggregated_data(aggregates)
         else:
             return self.raw_cases(stock_states, slugs)
示例#15
0
    def get_prod_data(self):
        sp_ids = get_relevant_supply_point_ids(self.domain,
                                               self.active_location)

        stock_states = StockState.include_archived.filter(
            case_id__in=sp_ids,
            last_modified_date__lte=self.datespan.enddate_utc,
            last_modified_date__gte=self.datespan.startdate_utc,
            section_id=STOCK_SECTION_TYPE)
        if not self.archived_products:
            stock_states = stock_states.exclude(sql_product__is_archived=True)

        stock_states = stock_states.order_by('product_id')

        if self.program_id:
            stock_states = stock_states.filter(
                product_id__in=product_ids_filtered_by_program(
                    self.domain, self.program_id))

        product_grouping = {}
        for state in stock_states:
            status = state.stock_category
            if state.product_id in product_grouping:
                product_grouping[state.product_id][status] += 1
                product_grouping[state.product_id]['facility_count'] += 1

            else:
                product_grouping[state.product_id] = {
                    'obj': Product.get(state.product_id),
                    'stockout': 0,
                    'understock': 0,
                    'overstock': 0,
                    'adequate': 0,
                    'nodata': 0,
                    'facility_count': 1
                }
                product_grouping[state.product_id][status] = 1

        for product in product_grouping.values():
            yield [
                product['obj'].name,
                product['facility_count'],
                100.0 * product['stockout'] / product['facility_count'],
                100.0 * product['understock'] / product['facility_count'],
                100.0 * product['adequate'] / product['facility_count'],
                100.0 * product['overstock'] / product['facility_count'],
                100.0 * product['nodata'] / product['facility_count'],
            ]
示例#16
0
    def get_prod_data(self):
        sp_ids = get_relevant_supply_point_ids(self.domain,
                                               self.active_location)
        product_ids = get_product_ids_for_program(
            self.domain, self.program_id) if self.program_id else None

        ledger_values = get_wrapped_ledger_values(
            domain=self.domain,
            case_ids=sp_ids,
            section_id=STOCK_SECTION_TYPE,
            entry_ids=product_ids,
            pagination=self.pagination,
        )
        product_grouping = {}
        for ledger_value in ledger_values:
            consumption_helper = get_consumption_helper_from_ledger_value(
                Domain.get_by_name(self.domain), ledger_value)
            status = consumption_helper.get_stock_category()
            if ledger_value.entry_id in product_grouping:
                product_grouping[ledger_value.entry_id][status] += 1
                product_grouping[ledger_value.entry_id]['facility_count'] += 1

            else:
                product_grouping[ledger_value.entry_id] = {
                    'entry_id': ledger_value.entry_id,
                    'stockout': 0,
                    'understock': 0,
                    'overstock': 0,
                    'adequate': 0,
                    'nodata': 0,
                    'facility_count': 1
                }
                product_grouping[ledger_value.entry_id][status] = 1

        product_name_map = get_product_id_name_mapping(self.domain)
        rows = [[
            product_name_map.get(product['entry_id'], product['entry_id']),
            product['facility_count'],
            100.0 * product['stockout'] / product['facility_count'],
            100.0 * product['understock'] / product['facility_count'],
            100.0 * product['adequate'] / product['facility_count'],
            100.0 * product['overstock'] / product['facility_count'],
            100.0 * product['nodata'] / product['facility_count'],
        ] for product in product_grouping.values()]

        return sorted(rows, key=lambda r: r[0].lower())
示例#17
0
    def get_data(self):
        # todo: this will probably have to paginate eventually
        if self.all_relevant_forms:
            sp_ids = get_relevant_supply_point_ids(
                self.domain,
                self.active_location,
            )

            supply_points = (
                SupplyPointCase.wrap(doc)
                for doc in iter_docs(SupplyPointCase.get_db(), sp_ids))
            form_xmlnses = [
                form['xmlns'] for form in self.all_relevant_forms.values()
            ]

            for supply_point in supply_points:
                # todo: get locations in bulk
                loc = supply_point.location
                transactions = StockTransaction.objects.filter(
                    case_id=supply_point._id,
                ).exclude(report__date__lte=self.start_date).exclude(
                    report__date__gte=self.end_date).order_by('-report__date')
                matched = False
                for trans in transactions:
                    if XFormInstance.get(
                            trans.report.form_id).xmlns in form_xmlnses:
                        yield {
                            'loc_id': loc._id,
                            'loc_path': loc.path,
                            'name': loc.name,
                            'type': loc.location_type,
                            'reporting_status': 'reporting',
                            'geo': loc._geopoint,
                        }
                        matched = True
                        break
                if not matched:
                    yield {
                        'loc_id': loc._id,
                        'loc_path': loc.path,
                        'name': loc.name,
                        'type': loc.location_type,
                        'reporting_status': 'nonreporting',
                        'geo': loc._geopoint,
                    }
示例#18
0
    def get_prod_data(self):
        sp_ids = get_relevant_supply_point_ids(self.domain, self.active_location)

        stock_states = StockState.objects.filter(
            case_id__in=sp_ids,
            last_modified_date__lte=self.datespan.enddate_utc,
            last_modified_date__gte=self.datespan.startdate_utc,
            section_id=STOCK_SECTION_TYPE
        )

        stock_states = stock_states.order_by('product_id')

        if self.program_id:
            stock_states = stock_states.filter(sql_product__program_id=self.program_id)

        product_grouping = {}
        for state in stock_states:
            status = state.stock_category
            if state.product_id in product_grouping:
                product_grouping[state.product_id][status] += 1
                product_grouping[state.product_id]['facility_count'] += 1

            else:
                product_grouping[state.product_id] = {
                    'obj': Product.get(state.product_id),
                    'stockout': 0,
                    'understock': 0,
                    'overstock': 0,
                    'adequate': 0,
                    'nodata': 0,
                    'facility_count': 1
                }
                product_grouping[state.product_id][status] = 1

        rows = [[
            product['obj'].name,
            product['facility_count'],
            100.0 * product['stockout'] / product['facility_count'],
            100.0 * product['understock'] / product['facility_count'],
            100.0 * product['adequate'] / product['facility_count'],
            100.0 * product['overstock'] / product['facility_count'],
            100.0 * product['nodata'] / product['facility_count'],
        ] for product in product_grouping.values()]

        return sorted(rows, key=lambda r: r[0].lower())
示例#19
0
    def get_prod_data(self):
        sp_ids = get_relevant_supply_point_ids(self.domain, self.active_location)
        product_ids = get_product_ids_for_program(self.domain, self.program_id) if self.program_id else None

        ledger_values = get_wrapped_ledger_values(
            domain=self.domain,
            case_ids=sp_ids,
            section_id=STOCK_SECTION_TYPE,
            entry_ids=product_ids,
        )
        product_grouping = {}
        for ledger_value in ledger_values:
            consumption_helper = get_consumption_helper_from_ledger_value(
                Domain.get_by_name(self.domain), ledger_value
            )
            status = consumption_helper.get_stock_category()
            if ledger_value.entry_id in product_grouping:
                product_grouping[ledger_value.entry_id][status] += 1
                product_grouping[ledger_value.entry_id]['facility_count'] += 1

            else:
                product_grouping[ledger_value.entry_id] = {
                    'entry_id': ledger_value.entry_id,
                    'stockout': 0,
                    'understock': 0,
                    'overstock': 0,
                    'adequate': 0,
                    'nodata': 0,
                    'facility_count': 1
                }
                product_grouping[ledger_value.entry_id][status] = 1

        product_name_map = get_product_id_name_mapping(self.domain)
        rows = [[
            product_name_map.get(product['entry_id'], product['entry_id']),
            product['facility_count'],
            100.0 * product['stockout'] / product['facility_count'],
            100.0 * product['understock'] / product['facility_count'],
            100.0 * product['adequate'] / product['facility_count'],
            100.0 * product['overstock'] / product['facility_count'],
            100.0 * product['nodata'] / product['facility_count'],
        ] for product in product_grouping.values()]

        return sorted(rows, key=lambda r: r[0].lower())
示例#20
0
    def get_data(self):
        # todo: this will probably have to paginate eventually
        if self.all_relevant_forms:
            sp_ids = get_relevant_supply_point_ids(
                self.domain,
                self.active_location,
            )

            supply_points = (SupplyPointCase.wrap(doc) for doc in iter_docs(SupplyPointCase.get_db(), sp_ids))
            form_xmlnses = [form['xmlns'] for form in self.all_relevant_forms.values()]

            for supply_point in supply_points:
                # todo: get locations in bulk
                loc = supply_point.location
                transactions = StockTransaction.objects.filter(
                    case_id=supply_point._id,
                ).exclude(
                    report__date__lte=self.start_date
                ).exclude(
                    report__date__gte=self.end_date
                ).order_by('-report__date')
                matched = False
                for trans in transactions:
                    if XFormInstance.get(trans.report.form_id).xmlns in form_xmlnses:
                        yield {
                            'loc_id': loc._id,
                            'loc_path': loc.path,
                            'name': loc.name,
                            'type': loc.location_type,
                            'reporting_status': 'reporting',
                            'geo': loc._geopoint,
                        }
                        matched = True
                        break
                if not matched:
                    yield {
                        'loc_id': loc._id,
                        'loc_path': loc.path,
                        'name': loc.name,
                        'type': loc.location_type,
                        'reporting_status': 'nonreporting',
                        'geo': loc._geopoint,
                    }
示例#21
0
    def get_data(self):
        sp_ids = get_relevant_supply_point_ids(
            self.domain,
            self.active_location
        )

        products = Product.by_domain(self.domain)
        if self.program_id:
            products = filter(
                lambda product: product.program_id == self.program_id, products
            )

        for sp_id in sp_ids:
            loc = SupplyPointCase.get(sp_id).location
            transactions = StockTransaction.objects.filter(
                case_id=sp_id,
                section_id=STOCK_SECTION_TYPE,
            )

            if transactions:
                last_transaction = sorted(
                    transactions,
                    key=lambda trans: trans.report.date
                )[-1]
            else:
                last_transaction = None

            yield {
                'loc_id': loc._id,
                'loc_path': loc.path,
                'name': loc.name,
                'type': loc.location_type,
                'reporting_status': reporting_status(
                    last_transaction,
                    self.start_date,
                    self.end_date
                ),
                'geo': loc._geopoint,
            }
示例#22
0
    def get_data(self):
        # todo: this will probably have to paginate eventually
        if self.all_relevant_forms:
            sp_ids = get_relevant_supply_point_ids(
                self.domain,
                self.active_location,
            )

            form_xmlnses = [
                form['xmlns'] for form in self.all_relevant_forms.values()
            ]
            form_xmlnses.append(COMMTRACK_REPORT_XMLNS)
            spoint_loc_map = {
                doc['_id']: doc['location_id']
                for doc in iter_docs(SupplyPointCase.get_db(), sp_ids)
            }
            locations = _location_map(list(spoint_loc_map.values()))

            for spoint_id, loc_id in spoint_loc_map.items():
                if loc_id not in locations:
                    continue  # it's archived, skip
                loc = locations[loc_id]

                results = StockReport.objects.filter(
                    stocktransaction__case_id=spoint_id).filter(
                        date__gte=self.converted_start_datetime,
                        date__lte=self.converted_end_datetime).values_list(
                            'form_id', 'date').distinct(
                            )  # not truly distinct due to ordering

                matched = False
                for form_id, date in results:
                    try:
                        if XFormInstance.get(form_id).xmlns in form_xmlnses:
                            yield {
                                'parent_name':
                                loc.parent.name if loc.parent else '',
                                'loc_id': loc.location_id,
                                'loc_path': loc.path,
                                'name': loc.name,
                                'type': loc.location_type.name,
                                'reporting_status': 'reporting',
                                'geo': geopoint(loc),
                                'last_reporting_date': date,
                            }
                            matched = True
                            break
                    except ResourceNotFound:
                        logging.error(
                            'Stock report for location {} in {} references non-existent form {}'
                            .format(loc.location_id, loc.domain, form_id))

                if not matched:
                    result = StockReport.objects.filter(
                        stocktransaction__case_id=spoint_id).values_list(
                            'date').order_by('-date')[:1]
                    yield {
                        'parent_name': loc.parent.name if loc.parent else '',
                        'loc_id': loc.location_id,
                        'loc_path': loc.path,
                        'name': loc.name,
                        'type': loc.location_type.name,
                        'reporting_status': 'nonreporting',
                        'geo': geopoint(loc),
                        'last_reporting_date': result[0][0] if result else ''
                    }
示例#23
0
    def get_data(self):
        # todo: this will probably have to paginate eventually
        if self.all_relevant_forms:
            sp_ids = get_relevant_supply_point_ids(
                self.domain,
                self.active_location,
            )

            form_xmlnses = [form['xmlns'] for form in self.all_relevant_forms.values()]
            spoint_loc_map = {
                doc['_id']: doc['location_id']
                for doc in iter_docs(SupplyPointCase.get_db(), sp_ids)
            }
            locations = _location_map(spoint_loc_map.values())

            for spoint_id, loc_id in spoint_loc_map.items():
                if loc_id not in locations:
                    continue  # it's archived, skip
                loc = locations[loc_id]

                results = StockReport.objects.filter(
                    stocktransaction__case_id=spoint_id
                ).filter(
                    date__gte=self.converted_start_datetime,
                    date__lte=self.converted_end_datetime
                ).values_list(
                    'form_id',
                    'date'
                ).distinct()  # not truly distinct due to ordering

                matched = False
                for form_id, date in results:
                    try:
                        if XFormInstance.get(form_id).xmlns in form_xmlnses:
                            yield {
                                'loc': loc,
                                'loc_id': loc.location_id,
                                'loc_path': loc.path,
                                'name': loc.name,
                                'type': loc.location_type.name,
                                'reporting_status': 'reporting',
                                'geo': geopoint(loc),
                                'last_reporting_date': date,
                            }
                            matched = True
                            break
                    except ResourceNotFound:
                        logging.error('Stock report for location {} in {} references non-existent form {}'.format(
                            loc.location_id, loc.domain, form_id
                        ))

                if not matched:
                    result = StockReport.objects.filter(
                        stocktransaction__case_id=spoint_id
                    ).values_list(
                        'date'
                    ).order_by('-date')[:1]
                    yield {
                        'loc': loc,
                        'loc_id': loc.location_id,
                        'loc_path': loc.path,
                        'name': loc.name,
                        'type': loc.location_type.name,
                        'reporting_status': 'nonreporting',
                        'geo': geopoint(loc),
                        'last_reporting_date': result[0][0] if result else ''
                    }
示例#24
0
 def _sp_ids(self):
     return get_relevant_supply_point_ids(self.domain, self.active_location)
示例#25
0
 def _sp_ids(self):
     return get_relevant_supply_point_ids(self.domain, self.active_location)
示例#26
0
    def get_prod_data(self):
        def get_months_until_stockout_icon(value):
            STOCKOUT = 0.0
            LOW = 1
            ADEQUATE = 3
            if float(value) == STOCKOUT:
                return '%s <span class="icon-remove" style="color:red"/>' % value
            elif float(value) < LOW:
                return '%s <span class="icon-warning-sign" style="color:orange"/>' % value
            elif float(value) <= ADEQUATE:
                return '%s <span class="icon-ok" style="color:green"/>' % value
            elif float(value) > ADEQUATE:
                return '%s <span class="icon-arrow-up" style="color:purple"/>' % value

        state_grouping = {}
        if self.config['program'] and not self.config['product']:
            product_ids = [product.get_id for product in Product.by_program_id(self.config['domain'],
                                                                               self.config['program'])]
        elif self.config['program'] and self.config['product']:
            product_ids = [self.config['product']]
        else:
            product_ids = Product.ids_by_domain(self.config['domain'])

        stock_states = StockState.objects.filter(
            case_id__in=get_relevant_supply_point_ids(self.config['domain'], self.sublocations[0]),
            section_id=STOCK_SECTION_TYPE,
            product_id__in=product_ids
        ).order_by('-last_modified_date')

        for state in stock_states:
            days = (datetime.now() - state.last_modified_date).days
            monthly_consumption = int(state.get_monthly_consumption()) if state.get_monthly_consumption() else 0
            if state.product_id not in state_grouping:
                state_grouping[state.product_id] = {
                    'commodity': Product.get(state.product_id).name,
                    'months_until_stockout': "%.2f" % (days / 30.0) if state.stock_on_hand else '',
                    'months_until_stockout_helper': state.stock_on_hand != 0,
                    'stockout_duration': timesince(state.last_modified_date) if state.stock_on_hand == 0 else '',
                    'stockout_duration_helper': state.stock_on_hand == 0,
                    'current_stock': state.stock_on_hand,
                    'monthly_consumption': monthly_consumption,
                    'reorder_level': int(monthly_consumption * REORDER_LEVEL),
                    'maximum_level': int(monthly_consumption * MAXIMUM_LEVEL),
                    'date_of_last_report': state.last_modified_date.strftime("%Y-%m-%d")
                }
            else:
                if not state_grouping[state.product_id]['months_until_stockout_helper']:
                    if state.stock_on_hand:
                        state_grouping[state.product_id]['months_until_stockout'] = "%.2f" % (days / 30.0)
                    else:
                        state_grouping[state.product_id]['stockout_duration_helper'] = False
                if state_grouping[state.product_id]['stockout_duration_helper']:
                    if not state.stock_on_hand:
                        state_grouping[state.product_id]['stockout_duration'] = timesince(state.last_modified_date)
                    else:
                        state_grouping[state.product_id]['stockout_duration_helper'] = False

        for values in state_grouping.values():
            yield {
                'commodity': values['commodity'],
                'current_stock': int(values['current_stock']),
                'monthly_consumption': values['monthly_consumption'] if values['monthly_consumption'] != 0.00
                else 'not enough data',
                'months_until_stockout': get_months_until_stockout_icon(values['months_until_stockout']
                                                                        if values['months_until_stockout']
                                                                        else 0.0),
                'stockout_duration': values['stockout_duration'],
                'date_of_last_report': values['date_of_last_report'],
                'reorder_level': values['reorder_level'] if values['reorder_level'] != 0.00
                else 'unknown',
                'maximum_level': values['maximum_level'] if values['maximum_level'] != 0.00
                else 'unknown'}
示例#27
0
    def get_data(self):
        sp_ids = get_relevant_supply_point_ids(
            self.domain,
            self.active_location
        )

        products = Product.by_domain(self.domain)
        if self.program_id:
            products = filter(
                lambda product: product.program_id == self.program_id, products
            )

        for sp_id in sp_ids:
            loc = SupplyPointCase.get(sp_id).location
            transactions = StockTransaction.objects.filter(
                case_id=sp_id,
            ).exclude(
                report__date__lte=self.start_date
            ).exclude(
                report__date__gte=self.end_date
            )

            if transactions:
                last_transaction = sorted(
                    transactions,
                    key=lambda trans: trans.report.date
                )[-1]
            else:
                last_transaction = None

            if self.all_relevant_forms:
                forms_xmlns = []
                for form in self.all_relevant_forms.values():
                    forms_xmlns.append(form['xmlns'])
                if last_transaction:
                    form = XFormInstance.get(last_transaction.report.form_id)
                    if form.xmlns in forms_xmlns:
                        yield {
                            'loc_id': loc._id,
                            'loc_path': loc.path,
                            'name': loc.name,
                            'type': loc.location_type,
                            'reporting_status': reporting_status(
                                last_transaction,
                                self.start_date,
                                self.end_date
                            ),
                            'geo': loc._geopoint,
                        }
                else:
                    yield {
                        'loc_id': loc._id,
                        'loc_path': loc.path,
                        'name': loc.name,
                        'type': loc.location_type,
                        'reporting_status': reporting_status(
                            None,
                            self.start_date,
                            self.end_date
                        ),
                        'geo': loc._geopoint,
                    }
示例#28
0
    def get_prod_data(self):

        for sublocation in self.sublocations:
            sp_ids = get_relevant_supply_point_ids(self.config['domain'], sublocation)
            stock_states = StockState.include_archived.filter(
                case_id__in=sp_ids,
                last_modified_date__lte=self.config['enddate'],
                last_modified_date__gte=self.config['startdate'],
                section_id=STOCK_SECTION_TYPE
            )

            stock_states = stock_states.order_by('product_id')
            state_grouping = {}
            for state in stock_states:
                status = state.stock_category
                if state.product_id in state_grouping:
                    state_grouping[state.product_id][status] += 1
                else:
                    state_grouping[state.product_id] = {
                        'id': state.product_id,
                        'stockout': 0,
                        'understock': 0,
                        'overstock': 0,
                        'adequate': 0,
                        'nodata': 0,
                        'facility_count': 1,
                        'amc': int(state.get_monthly_consumption() or 0)
                    }
                    state_grouping[state.product_id][status] = 1

            location_grouping = {
                'location': sublocation.name,
                'stockout': 0,
                'understock': 0,
                'adequate': 0,
                'overstock': 0,
                'total': 0,
                'amc': 0
            }
            product_ids = []
            if self.config['program'] != '' and self.config['product'] == '':
                product_ids = [product.get_id for product in Product.by_program_id(self.config['domain'],
                                                                                   self.config['program'])]
            elif self.config['program'] != '' and self.config['product'] != '':
                product_ids = [self.config['product']]
            else:
                product_ids = Product.ids_by_domain(self.config['domain'])

            for product in state_grouping.values():
                if product['id'] in product_ids:
                    location_grouping['stockout'] += product['stockout']
                    location_grouping['understock'] += product['understock']
                    location_grouping['adequate'] += product['adequate']
                    location_grouping['overstock'] += product['overstock']
                    location_grouping['total'] += sum([product['stockout'], product['understock'],
                                                       product['adequate'], product['overstock']])
                    location_grouping['amc'] += product['amc']

            location_grouping['stockout'] = self.percent_fn(location_grouping['total'],
                                                            location_grouping['stockout'])
            location_grouping['understock'] = self.percent_fn(location_grouping['total'],
                                                              location_grouping['understock'])
            location_grouping['adequate'] = self.percent_fn(location_grouping['total'],
                                                            location_grouping['adequate'])
            location_grouping['overstock'] = self.percent_fn(location_grouping['total'],
                                                             location_grouping['overstock'])

            yield location_grouping