def handle(self, *args, **options):
        for domain in Domain.get_all():
            if domain['commtrack_enabled']:
                fields_definition = cdm.CustomDataFieldsDefinition.get_or_create(
                    domain['name'], 'ProductFields')
                had_fields = bool(fields_definition.fields)

                product_ids = Product.ids_by_domain(domain['name'])

                existing_field_slugs = set(
                    [field.slug for field in fields_definition.fields])
                for product in iter_docs(Product.get_db(), product_ids):
                    product_data = product.get('product_data', {})
                    for key in product_data.keys():
                        if key and key not in existing_field_slugs:
                            existing_field_slugs.add(key)
                            fields_definition.fields.append(
                                cdm.CustomDataField(
                                    slug=key,
                                    label=key,
                                    is_required=False,
                                ))

                for field in fields_definition.fields:
                    if cdm.is_system_key(field.slug):
                        fields_definition.fields.remove(field)
                # Only save a definition for domains which use custom product data
                if fields_definition.fields or had_fields:
                    fields_definition.save()
            print 'finished domain "{}"'.format(domain['name'])
def update_product_availability_facility_data(org_summary):
    # product availability

    facility = Location.get(docid=org_summary.supply_point)
    assert facility.location_type == "FACILITY"
    prods = Product.ids_by_domain(facility.domain)
    for p in prods:
        product_data, created = ProductAvailabilityData.objects.get_or_create(
            product=p,
            supply_point=facility._id,
            date=org_summary.date
        )

        if created:
            # set defaults
            product_data.total = 1
            previous_reports = ProductAvailabilityData.objects.filter(
                product=p,
                supply_point=facility._id,
                date__lt=org_summary.date
            )
            if previous_reports.count():
                prev = previous_reports.order_by("-date")[0]
                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
            product_data.save()
        assert (product_data.with_stock + product_data.without_stock + product_data.without_data) == 1, \
            "bad product data config"
    def handle(self, *args, **options):
        for domain in Domain.get_all():
            if domain['commtrack_enabled']:
                fields_definition = CustomDataFieldsDefinition.get_or_create(
                    domain['name'],
                    'ProductFields'
                )

                product_ids = Product.ids_by_domain(domain['name'])

                existing_field_slugs = set(
                    [field.slug for field in fields_definition.fields]
                )
                for product in iter_docs(Product.get_db(), product_ids):
                    product_data = product.get('product_data', {})
                    for key in product_data.keys():
                        if key and key not in existing_field_slugs:
                            existing_field_slugs.add(key)
                            fields_definition.fields.append(CustomDataField(
                                slug=key,
                                label=key,
                                is_required=False
                            ))

                # Only save a definition for domains which use custom product data
                if fields_definition.fields:
                    fields_definition.save()
 def get_products(self):
     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'])
     return product_ids
Example #5
0
def ils_clear_stock_data_task(domain):
    assert ILSGatewayConfig.for_domain(domain)
    locations = SQLLocation.objects.filter(domain=domain)
    SupplyPointStatus.objects.filter(location_id__in=locations.values_list('location_id', flat=True)).delete()
    DeliveryGroupReport.objects.filter(location_id__in=locations.values_list('location_id', flat=True)).delete()
    products = Product.ids_by_domain(domain)
    StockState.objects.filter(product_id__in=products).delete()
    StockTransaction.objects.filter(
        case_id__in=locations.exclude(supply_point_id__isnull=True).values_list('supply_point_id', flat=True)
    ).delete()
    StockReport.objects.filter(domain=domain).delete()
    StockDataCheckpoint.objects.filter(domain=domain).delete()
Example #6
0
 def get_ota_restore_settings(self):
     # for some reason it doesn't like this import
     from casexml.apps.phone.restore import StockSettings
     default_product_ids = Product.ids_by_domain(self.domain) \
         if self.ota_restore_config.use_dynamic_product_list else []
     case_filter = lambda stub: stub.type in set(self.ota_restore_config.force_consumption_case_types)
     return StockSettings(
         section_to_consumption_types=self.ota_restore_config.section_to_consumption_types,
         consumption_config=self.get_consumption_config(),
         default_product_list=default_product_ids,
         force_consumption_case_filter=case_filter,
     )
Example #7
0
 def get_ota_restore_settings(self):
     # for some reason it doesn't like this import
     from casexml.apps.phone.restore import StockSettings
     default_product_ids = Product.ids_by_domain(self.domain) \
         if self.ota_restore_config.use_dynamic_product_list else []
     case_filter = lambda case: case.type in set(self.ota_restore_config.force_consumption_case_types)
     return StockSettings(
         section_to_consumption_types=self.ota_restore_config.section_to_consumption_types,
         consumption_config=self.get_consumption_config(),
         default_product_list=default_product_ids,
         force_consumption_case_filter=case_filter,
     )
    def handle(self, *args, **options):
        for domain in Domain.get_all():
            if domain["commtrack_enabled"]:
                fields_definition = cdm.CustomDataFieldsDefinition.get_or_create(domain["name"], "ProductFields")
                had_fields = bool(fields_definition.fields)

                product_ids = Product.ids_by_domain(domain["name"])

                existing_field_slugs = set([field.slug for field in fields_definition.fields])
                for product in iter_docs(Product.get_db(), product_ids):
                    product_data = product.get("product_data", {})
                    for key in product_data.keys():
                        if key and key not in existing_field_slugs:
                            existing_field_slugs.add(key)
                            fields_definition.fields.append(cdm.CustomDataField(slug=key, label=key, is_required=False))

                for field in fields_definition.fields:
                    if cdm.is_system_key(field.slug):
                        fields_definition.fields.remove(field)
                # Only save a definition for domains which use custom product data
                if fields_definition.fields or had_fields:
                    fields_definition.save()
            print 'finished domain "{}"'.format(domain["name"])
Example #9
0
 def _get_products(domain):
     for p_doc in iter_docs(Product.get_db(), Product.ids_by_domain(domain)):
         # filter out archived products from export
         if not ('is_archived' in p_doc and p_doc['is_archived']):
             yield Product.wrap(p_doc)
Example #10
0
 def product_ids(self):
     from corehq.apps.products.models import Product
     return Product.ids_by_domain(self.domain)
Example #11
0
 def product_ids(self):
     from corehq.apps.products.models import Product
     return Product.ids_by_domain(self.domain)
def _init_with_product(location, date):
    for p in Product.ids_by_domain(location.domain):
        ProductAvailabilityData.objects.get_or_create(supply_point=location._id, date=date, product=p)
def process_non_facility_warehouse_data(location, start_date, end_date, strict=True):
    facs = get_nested_children(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(supply_point=location._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(location.domain)
        for p in prods:
            product_data = ProductAvailabilityData.objects.get_or_create(product=p,
                                                                         supply_point=location._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 status_type in 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 [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(location._id, window_date, sub_alerts, alert_type)
    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
    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'}
Example #16
0
 def _get_products(domain):
     for p_doc in iter_docs(Product.get_db(),
                            Product.ids_by_domain(domain)):
         # filter out archived products from export
         if not ('is_archived' in p_doc and p_doc['is_archived']):
             yield Product.wrap(p_doc)
Example #17
0
def ils_clear_stock_data_task():
    StockTransaction.objects.filter(report__domain='ilsgateway-test-1').delete()
    StockReport.objects.filter(domain='ilsgateway-test-1').delete()
    products = Product.ids_by_domain('ilsgateway-test-1')
    StockState.objects.filter(product_id__in=products).delete()