Exemple #1
0
def bootstrap_commtrack_settings_if_necessary(domain, requisitions_enabled=False):
    if not (domain and domain.commtrack_enabled and not CommtrackConfig.for_domain(domain.name)):
        return

    c = CommtrackConfig(
        domain=domain.name,
        multiaction_enabled=True,
        multiaction_keyword="report",
        actions=[
            CommtrackActionConfig(action="receipts", keyword="r", caption="Received"),
            CommtrackActionConfig(action="consumption", keyword="c", caption="Consumed"),
            CommtrackActionConfig(action="consumption", subaction="loss", keyword="l", caption="Losses"),
            CommtrackActionConfig(action="stockonhand", keyword="soh", caption="Stock on hand"),
            CommtrackActionConfig(action="stockout", keyword="so", caption="Stock-out"),
        ],
        location_types=[
            LocationType(name="state", allowed_parents=[""], administrative=True),
            LocationType(name="district", allowed_parents=["state"], administrative=True),
            LocationType(name="block", allowed_parents=["district"], administrative=True),
            LocationType(name="village", allowed_parents=["block"], administrative=True),
            LocationType(name="outlet", allowed_parents=["village"]),
        ],
        supply_point_types=[],
    )
    if requisitions_enabled:
        c.requisition_config = get_default_requisition_config()

    c.save()

    program = make_program(domain.name, "Default", "def")
    make_product(domain.name, "Sample Product 1", "pp", program.get_id)
    make_product(domain.name, "Sample Product 2", "pq", program.get_id)
    make_product(domain.name, "Sample Product 3", "pr", program.get_id)

    return c
Exemple #2
0
def make_psi_config(domain):
    c = CommtrackConfig(
        domain=domain,
        multiaction_enabled=True,
        multiaction_keyword="s",
        actions=[
            CommtrackActionConfig(action_type="stockedoutfor", keyword="d", caption="Stock-out Days"),
            CommtrackActionConfig(action_type="receipts", keyword="r", caption="Other Receipts"),
            CommtrackActionConfig(action_type="stockonhand", keyword="b", caption="Balance"),
            CommtrackActionConfig(action_type="receipts", name="sales", keyword="p", caption="Placements"),
        ],
        supply_point_types=[
            SupplyPointType(name="CHC", categories=["Public"]),
            SupplyPointType(name="PHC", categories=["Public"]),
            SupplyPointType(name="SC", categories=["Public"]),
            SupplyPointType(name="MBBS", categories=["Private"]),
            SupplyPointType(name="Pediatrician", categories=["Private"]),
            SupplyPointType(name="AYUSH", categories=["Private"]),
            SupplyPointType(name="Medical Store / Chemist", categories=["Traditional"]),
            SupplyPointType(name="RP", categories=["Traditional"]),
            SupplyPointType(name="Asha", categories=["Frontline Workers"]),
            SupplyPointType(name="AWW", categories=["Public", "Frontline Workers"]),
            SupplyPointType(name="NGO", categories=["Non-traditional"]),
            SupplyPointType(name="CBO", categories=["Non-traditional"]),
            SupplyPointType(name="SHG", categories=["Non-traditional"]),
            SupplyPointType(name="Pan Store", categories=["Traditional"]),
            SupplyPointType(name="General Store", categories=["Traditional"]),
        ],
    )
    c.save()
    return c
 def test_get_docs_in_domain_by_class(self):
     commtrack_config = CommtrackConfig(domain=self.domain)
     group = Group(domain=self.domain)
     xform = XFormInstance(domain=self.domain)
     commtrack_config.save()
     group.save()
     xform.save()
     self.addCleanup(commtrack_config.delete)
     self.addCleanup(group.delete)
     self.addCleanup(xform.delete)
     [commtrack_config_2] = get_docs_in_domain_by_class(self.domain, CommtrackConfig)
     self.assertEqual(commtrack_config_2.to_json(), commtrack_config.to_json())
Exemple #4
0
 def test_get_docs_in_domain_by_class(self):
     commtrack_config = CommtrackConfig(domain=self.domain)
     group = Group(domain=self.domain)
     xform = XFormInstance(domain=self.domain)
     commtrack_config.save()
     group.save()
     xform.save()
     self.addCleanup(commtrack_config.delete)
     self.addCleanup(group.delete)
     self.addCleanup(xform.delete)
     [commtrack_config_2
      ] = get_docs_in_domain_by_class(self.domain, CommtrackConfig)
     self.assertEqual(commtrack_config_2.to_json(),
                      commtrack_config.to_json())
Exemple #5
0
 def _create_unsynced_couch(self):
     """
         Create a CommtrackConfig matching the one created by _create_unsynced_sql
     """
     couch = CommtrackConfig(
         domain='my_project',
         use_auto_emergency_levels=False,
         sync_consumption_fixtures=False,
         use_auto_consumption=False,
         individual_consumption_defaults=True,
         ota_restore_config=StockRestoreConfig(
             section_to_consumption_types={'s1': 'c1'},
             force_consumption_case_types=['type1'],
             use_dynamic_product_list=True,
         ),
         alert_config=AlertConfig(
             stock_out_facilities=True,
             stock_out_commodities=True,
             stock_out_rates=True,
             non_report=True,
         ),
         actions=[
             CommtrackActionConfig(
                 action='receipts',
                 subaction='sub-receipts',
                 _keyword='one',
                 caption='first action',
             ),
             CommtrackActionConfig(
                 action='receipts',
                 subaction='sub-receipts',
                 _keyword='two',
                 caption='second action',
             ),
         ],
         consumption_config=ConsumptionConfig(
             min_transactions=1,
             min_window=2,
             optimal_window=3,
             use_supply_point_type_default_consumption=True,
             exclude_invalid_periods=False,
         ),
         stock_levels_config=StockLevelsConfig(
             emergency_level=0.5,
             understock_threshold=1.5,
             overstock_threshold=3,
         ))
     couch.save(sync_to_sql=False)
     return couch
Exemple #6
0
def make_psi_config(domain):
    c = CommtrackConfig(
        domain=domain,
        multiaction_enabled=True,
        multiaction_keyword='s',
        actions=[
            CommtrackActionConfig(
                action_type='stockedoutfor',
                keyword='d',
                caption='Stock-out Days'
            ),
            CommtrackActionConfig(
                action_type='receipts',
                keyword='r',
                caption='Other Receipts'
            ),
            CommtrackActionConfig(
                action_type='stockonhand',
                keyword='b',
                caption='Balance'
            ),
            CommtrackActionConfig(
                action_type='receipts',
                name='sales',
                keyword='p',
                caption='Placements'
            ),
        ],
        supply_point_types=[
            SupplyPointType(name='CHC', categories=['Public']),
            SupplyPointType(name='PHC', categories=['Public']),
            SupplyPointType(name='SC', categories=['Public']),
            SupplyPointType(name='MBBS', categories=['Private']),
            SupplyPointType(name='Pediatrician', categories=['Private']),
            SupplyPointType(name='AYUSH', categories=['Private']),
            SupplyPointType(name='Medical Store / Chemist', categories=['Traditional']),
            SupplyPointType(name='RP', categories=['Traditional']),
            SupplyPointType(name='Asha', categories=['Frontline Workers']),
            SupplyPointType(name='AWW', categories=['Public', 'Frontline Workers']),
            SupplyPointType(name='NGO', categories=['Non-traditional']),
            SupplyPointType(name='CBO', categories=['Non-traditional']),
            SupplyPointType(name='SHG', categories=['Non-traditional']),
            SupplyPointType(name='Pan Store', categories=['Traditional']),
            SupplyPointType(name='General Store', categories=['Traditional']),
        ]
    )
    c.save()
    return c
Exemple #7
0
    def setUpClass(cls):
        super(TestStockOut, cls).setUpClass()
        cls.facility2 = make_loc(code="loc2", name="Test Facility 2", type="FACILITY",
                                 domain=TEST_DOMAIN, parent=cls.district)
        cls.user2 = bootstrap_user(
            cls.facility2, username='******', domain=TEST_DOMAIN, home_loc='loc2', phone_number='5551235',
            first_name='test', last_name='Test'
        )
        SLABConfig.objects.create(
            is_pilot=True,
            sql_location=cls.facility.sql_location
        )

        slab_config = SLABConfig.objects.create(
            is_pilot=True,
            sql_location=cls.facility2.sql_location
        )
        slab_config.closest_supply_points.add(cls.facility.sql_location)
        slab_config.save()

        config = CommtrackConfig.for_domain(TEST_DOMAIN)
        config.use_auto_consumption = False
        config.individual_consumption_defaults = True
        config.consumption_config = ConsumptionConfig(
            use_supply_point_type_default_consumption=True,
            exclude_invalid_periods=True
        )
        config.save()

        set_default_consumption_for_supply_point(TEST_DOMAIN, cls.id.get_id, cls.facility_sp_id, 100)
        set_default_consumption_for_supply_point(TEST_DOMAIN, cls.dp.get_id, cls.facility_sp_id, 100)
        set_default_consumption_for_supply_point(TEST_DOMAIN, cls.ip.get_id, cls.facility_sp_id, 100)
Exemple #8
0
    def prepare_commtrack_config(self):
        for location_type in LocationType.objects.by_domain(self.domain):
            location_type.delete()

        country = self._make_loc_type(name="country", administrative=True)
        self._make_loc_type(name="Central Medical Store", parent_type=country)

        region = self._make_loc_type(name="region", administrative=True,
                                     parent_type=country)
        self._make_loc_type(name="Teaching Hospital", parent_type=region)
        self._make_loc_type(name="Regional Medical Store", parent_type=region)
        self._make_loc_type(name="Regional Hospital", parent_type=region)

        district = self._make_loc_type(name="district", administrative=True,
                                       parent_type=region)
        self._make_loc_type(name="Clinic", parent_type=district)
        self._make_loc_type(name="District Hospital", parent_type=district)
        self._make_loc_type(name="Health Centre", parent_type=district)
        self._make_loc_type(name="CHPS Facility", parent_type=district)
        self._make_loc_type(name="Hospital", parent_type=district)
        self._make_loc_type(name="Psychiatric Hospital", parent_type=district)
        self._make_loc_type(name="Polyclinic", parent_type=district)
        self._make_loc_type(name="facility", parent_type=district)

        config = CommtrackConfig.for_domain(self.domain)
        config.consumption_config.exclude_invalid_periods = True
        config.save()
Exemple #9
0
 def commtrack_settings(self):
     # this import causes some dependency issues so lives in here
     from corehq.apps.commtrack.models import CommtrackConfig
     if self.commtrack_enabled:
         return CommtrackConfig.for_domain(self.name)
     else:
         return None
Exemple #10
0
def commtrack_settings_sync(project, locations_types):
    if MigrationCheckpoint.objects.filter(domain=project).count() != 0:
        return

    config = CommtrackConfig.for_domain(project)
    domain = Domain.get_by_name(project)
    domain.location_types = []
    for i, value in enumerate(locations_types):
        if not any(lt.name == value
                   for lt in domain.location_types):
            allowed_parents = [locations_types[i - 1]] if i > 0 else [""]

            domain.location_types.append(
                LocationType(
                    name=value,
                    allowed_parents=allowed_parents,
                    administrative=(value.lower() != 'facility')
                )
            )
    actions = [action.keyword for action in config.actions]
    if 'delivered' not in actions:
        config.actions.append(
            CommtrackActionConfig(
                action='receipts',
                keyword='delivered',
                caption='Delivered')
        )
    config.save()
Exemple #11
0
def stock_level_config_for_domain(domain, commtrack_enabled):
    from corehq.apps.commtrack.models import CommtrackConfig
    ct_config = CommtrackConfig.for_domain(domain)
    if ct_config is None or not commtrack_enabled:
        return None
    else:
        return ct_config.stock_levels_config
Exemple #12
0
    def prepare_commtrack_config(self):
        """
        Bootstraps the domain-level metadata according to the static config.
        - Sets the proper location types hierarchy on the domain object.
        - Sets a keyword handler for reporting receipts
        """
        for location_type in LocationType.objects.by_domain(self.domain):
            location_type.delete()

        previous = None
        for loc_type in LOCATION_TYPES:
            previous, _ = LocationType.objects.get_or_create(
                domain=self.domain,
                name=loc_type,
                parent_type=previous,
                administrative=(loc_type != 'FACILITY'),
            )

        config = CommtrackConfig.for_domain(self.domain)
        config.consumption_config.exclude_invalid_periods = True
        actions = [action.keyword for action in config.actions]
        if 'delivered' not in actions:
            config.actions.append(
                CommtrackActionConfig(action='receipts',
                                      keyword='delivered',
                                      caption='Delivered'))
            config.save()
Exemple #13
0
def process(domain, instance):
    """process an incoming commtrack stock report instance"""
    config = CommtrackConfig.for_domain(domain)
    root = etree.fromstring(instance)
    user_id, transactions = unpack_transactions(root, config)
    transactions = list(normalize_transactions(transactions))

    def get_transactions(all_tx, type_filter):
        """get all the transactions of the relevant type (filtered by type_filter),
        grouped by product (returns a dict of 'product subcase id' => list of transactions),
        with each set of transactions sorted in the correct order for processing
        """
        return map_reduce(
            lambda tx: [(tx.case_id, )],
            lambda v: sorted(v, key=lambda tx: tx.priority_order
                             ),  # important!
            data=filter(type_filter, all_tx),
            include_docs=True)

    # split transactions by type and product
    stock_transactions = get_transactions(transactions,
                                          lambda tx: tx.category == 'stock')
    requisition_transactions = get_transactions(
        transactions, lambda tx: tx.category == 'requisition')

    case_ids = list(
        set(itertools.chain(*[tx.get_case_ids() for tx in transactions])))
    cases = dict((c._id, c) for c in CommCareCase.view(
        '_all_docs', keys=case_ids, include_docs=True))

    # TODO: code to auto generate / update requisitions from transactions if
    # project is configured for that.

    # TODO: when we start receiving commcare-submitted reports, we should be using a server time rather
    # than relying on timeStart (however timeStart is set to server time for reports received via sms)
    submit_time = root.find('.//%s' % _('timeStart', META_XMLNS)).text
    post_processed_transactions = list(transactions)
    for product_id, product_case in cases.iteritems():
        stock_txs = stock_transactions.get(product_id, [])
        if stock_txs:
            case_block, reconciliations = process_product_transactions(
                user_id, submit_time, product_case, stock_txs)
            root.append(case_block)
            post_processed_transactions.extend(reconciliations)

        req_txs = requisition_transactions.get(product_id, [])
        if req_txs and config.requisitions_enabled:
            req = RequisitionState.from_transactions(user_id, product_case,
                                                     req_txs)
            case_block = etree.fromstring(req.to_xml())
            root.append(case_block)
    replace_transactions(root, post_processed_transactions)

    submission = etree.tostring(root)
    logger.debug('submitting: %s' % submission)

    spoof_submission(get_submit_url(domain),
                     submission,
                     headers={'HTTP_X_SUBMIT_TIME': submit_time},
                     hqsubmission=False)
Exemple #14
0
def process_stock(xform, case_db=None):
    """
    process the commtrack xml constructs in an incoming submission
    """
    case_db = case_db or CaseDbCache()
    assert isinstance(case_db, CaseDbCache)
    if is_device_report(xform):
        return []

    domain = xform.domain

    config = CommtrackConfig.for_domain(domain)

    # these are the raw stock report objects from the xml
    stock_reports = list(unpack_commtrack(xform, config))
    # flattened transaction list spanning all stock reports in the form
    transactions = [t for r in stock_reports for t in r.transactions]
    # omitted: normalize_transactions (used for bulk requisitions?)

    if not transactions:
        return []

    # transactions grouped by case/product id
    grouped_tx = map_reduce(lambda tx: [((tx.case_id, tx.product_id),)],
                            lambda v: sorted(v, key=lambda tx: tx.timestamp),
                            data=transactions,
                            include_docs=True)

    case_ids = list(set(k[0] for k in grouped_tx))
    # list of cases that had stock reports in the form
    # there is no need to wrap them by case type
    relevant_cases = [case_db.get(case_id) for case_id in case_ids]

    user_id = xform.form['meta']['userID']
    submit_time = xform['received_on']

    # touch every case for proper ota restore logic syncing to be preserved
    for case in relevant_cases:
        case_action = CommCareCaseAction.from_parsed_action(
            submit_time, user_id, xform, AbstractAction(CASE_ACTION_COMMTRACK)
        )
        # hack: clear the sync log id so this modification always counts
        # since consumption data could change server-side
        case_action.sync_log_id = ''
        case.actions.append(case_action)
        case_db.mark_changed(case)

    # also purge the sync token cache for the same reason
    if relevant_cases and xform.get_sync_token():
        xform.get_sync_token().invalidate_cached_payloads()

    # create the django models
    for report in stock_reports:
        report.create_models(domain)

    # TODO make this a signal
    from corehq.apps.commtrack.signals import send_notifications, raise_events
    send_notifications(xform, relevant_cases)
    raise_events(xform, relevant_cases)
    return relevant_cases
Exemple #15
0
    def testOTASettings(self):
        ct_settings = CommtrackConfig.for_domain(self.domain)
        ct_settings.consumption_config = ConsumptionConfig(
            min_transactions=10,
            min_window=20,
            optimal_window=60,
        )
        ct_settings.ota_restore_config = StockRestoreConfig(
            section_to_consumption_types={'stock': 'consumption'},
        )
        set_default_monthly_consumption_for_domain(self.domain, 5 * DAYS_IN_MONTH)
        restore_settings = ct_settings.get_ota_restore_settings()
        self.assertEqual(1, len(restore_settings.section_to_consumption_types))
        self.assertEqual('consumption', restore_settings.section_to_consumption_types['stock'])
        self.assertEqual(10, restore_settings.consumption_config.min_periods)
        self.assertEqual(20, restore_settings.consumption_config.min_window)
        self.assertEqual(60, restore_settings.consumption_config.max_window)
        self.assertEqual(150, restore_settings.consumption_config.default_monthly_consumption_function('foo', 'bar'))
        self.assertFalse(restore_settings.force_consumption_case_filter(CommCareCase(type='force-type')))
        self.assertEqual(0, len(restore_settings.default_product_list))

        ct_settings.ota_restore_config.force_consumption_case_types=['force-type']
        ct_settings.ota_restore_config.use_dynamic_product_list=True
        restore_settings = ct_settings.get_ota_restore_settings()
        self.assertTrue(restore_settings.force_consumption_case_filter(CommCareCase(type='force-type')))
        self.assertEqual(3, len(restore_settings.default_product_list))
Exemple #16
0
def prepare_commtrack_config(domain):
    def _make_loc_type(name, administrative=False, parent_type=None):
        return LocationType.objects.get_or_create(
            domain=domain,
            name=name,
            administrative=administrative,
            parent_type=parent_type,
        )[0]

    for location_type in LocationType.objects.by_domain(domain):
        location_type.delete()

    country = _make_loc_type(name="country", administrative=True)
    _make_loc_type(name="Central Medical Store", parent_type=country)

    region = _make_loc_type(name="region", administrative=True,
                                 parent_type=country)
    _make_loc_type(name="Teaching Hospital", parent_type=region)
    _make_loc_type(name="Regional Medical Store", parent_type=region)
    _make_loc_type(name="Regional Hospital", parent_type=region)

    district = _make_loc_type(name="district", administrative=True,
                                   parent_type=region)
    _make_loc_type(name="Clinic", parent_type=district)
    _make_loc_type(name="District Hospital", parent_type=district)
    _make_loc_type(name="Health Centre", parent_type=district)
    _make_loc_type(name="CHPS Facility", parent_type=district)
    _make_loc_type(name="Hospital", parent_type=district)
    _make_loc_type(name="Psychiatric Hospital", parent_type=district)
    _make_loc_type(name="Polyclinic", parent_type=district)
    _make_loc_type(name="facility", parent_type=district)

    config = CommtrackConfig.for_domain(domain)
    config.consumption_config.exclude_invalid_periods = True
    config.save()
Exemple #17
0
    def page_context(self):
        try:
            runner = ReportRun.objects.filter(
                domain=self.domain, complete=False).latest('start_run')
        except ReportRun.DoesNotExist:
            runner = None

        return {
            'runner':
            runner,
            'settings':
            self.settings_context,
            'source':
            self.source,
            'sync_url':
            self.sync_urlname,
            'sync_stock_url':
            self.sync_stock_url,
            'clear_stock_url':
            self.clear_stock_url,
            'is_developer':
            toggles.IS_DEVELOPER.enabled(self.request.couch_user.username),
            'is_commtrack_enabled':
            CommtrackConfig.for_domain(self.domain)
        }
Exemple #18
0
def process(domain, instance):
    """process an incoming commtrack stock report instance"""
    config = CommtrackConfig.for_domain(domain)
    root = etree.fromstring(instance)
    transactions = unpack_transactions(root, config)

    case_ids = [tx["case_id"] for tx in transactions]
    cases = dict((c._id, c) for c in CommCareCase.view("_all_docs", keys=case_ids, include_docs=True))

    # ensure transaction types are processed in the correct order
    def transaction_order(tx):
        return [action.action_name for action in config.actions].index(tx["action"])

    transactions.sort(key=transaction_order)
    # apply all transactions to each product case in bulk
    transactions_by_product = map_reduce(lambda tx: [(tx["case_id"],)], data=transactions, include_docs=True)

    for product_id, txs in transactions_by_product.iteritems():
        product_case = cases[product_id]
        case_block, reconciliations = process_product_transactions(product_case, txs)
        for recon in reconciliations:
            root.append(recon)
        root.append(case_block)

    submission = etree.tostring(root)
    logger.debug("submitting: %s" % submission)

    submit_time = root.find(".//%s" % _("timeStart", META_XMLNS)).text
    spoof_submission(get_submit_url(domain), submission, headers={"HTTP_X_SUBMIT_TIME": submit_time})
Exemple #19
0
    def setUp(self):
        # might as well clean house before doing anything
        delete_all_xforms()
        delete_all_cases()
        StockReport.objects.all().delete()
        StockTransaction.objects.all().delete()

        self.backend = test.bootstrap(TEST_BACKEND, to_console=True)
        self.domain = bootstrap_domain()
        self.ct_settings = CommtrackConfig.for_domain(self.domain.name)
        if self.requisitions_enabled:
            self.ct_settings.requisition_config = get_default_requisition_config()
            self.ct_settings.save()

        self.loc = make_loc('loc1')
        self.sp = make_supply_point(self.domain.name, self.loc)
        self.users = [bootstrap_user(self, **user_def) for user_def in self.user_definitions]

        if False:
            # bootstrap additional users for requisitions
            # needs to get reinserted for requisition stuff later
            self.approver = bootstrap_user(self, **APPROVER_USER)
            self.packer = bootstrap_user(self, **PACKER_USER)
            self.users += [self.approver, self.packer]

        # everyone should be in a group.
        self.group = Group(domain=TEST_DOMAIN, name='commtrack-folks',
                           users=[u._id for u in self.users],
                           case_sharing=True)
        self.group.save()
        self.sp.owner_id = self.group._id
        self.sp.save()
        self.products = sorted(Product.by_domain(self.domain.name), key=lambda p: p._id)
        self.assertEqual(3, len(self.products))
Exemple #20
0
    def prepare_commtrack_config(self):
        for location_type in LocationType.objects.by_domain(self.domain):
            location_type.delete()

        country = self._make_loc_type(name="country", administrative=True)
        self._make_loc_type(name="Central Medical Store", parent_type=country)

        region = self._make_loc_type(name="region",
                                     administrative=True,
                                     parent_type=country)
        self._make_loc_type(name="Teaching Hospital", parent_type=region)
        self._make_loc_type(name="Regional Medical Store", parent_type=region)
        self._make_loc_type(name="Regional Hospital", parent_type=region)

        district = self._make_loc_type(name="district",
                                       administrative=True,
                                       parent_type=region)
        self._make_loc_type(name="Clinic", parent_type=district)
        self._make_loc_type(name="District Hospital", parent_type=district)
        self._make_loc_type(name="Health Centre", parent_type=district)
        self._make_loc_type(name="CHPS Facility", parent_type=district)
        self._make_loc_type(name="Hospital", parent_type=district)
        self._make_loc_type(name="Psychiatric Hospital", parent_type=district)
        self._make_loc_type(name="Polyclinic", parent_type=district)
        self._make_loc_type(name="facility", parent_type=district)

        config = CommtrackConfig.for_domain(self.domain)
        config.consumption_config.exclude_invalid_periods = True
        config.save()
    def setUpClass(cls):
        super(TestStockOut, cls).setUpClass()
        cls.facility2 = make_loc(code="loc2", name="Test Facility 2", type="FACILITY",
                                 domain=TEST_DOMAIN, parent=cls.district)
        cls.user2 = bootstrap_user(
            cls.facility2, username='******', domain=TEST_DOMAIN, home_loc='loc2', phone_number='5551235',
            first_name='test', last_name='Test'
        )
        SLABConfig.objects.create(
            is_pilot=True,
            sql_location=cls.facility.sql_location
        )

        slab_config = SLABConfig.objects.create(
            is_pilot=True,
            sql_location=cls.facility2.sql_location
        )
        slab_config.closest_supply_points.add(cls.facility.sql_location)
        slab_config.save()

        config = CommtrackConfig.for_domain(TEST_DOMAIN)
        config.use_auto_consumption = False
        config.individual_consumption_defaults = True
        config.consumption_config = ConsumptionConfig(
            use_supply_point_type_default_consumption=True,
            exclude_invalid_periods=True
        )
        config.save()

        set_default_consumption_for_supply_point(TEST_DOMAIN, cls.id.get_id, cls.facility_sp_id, 100)
        set_default_consumption_for_supply_point(TEST_DOMAIN, cls.dp.get_id, cls.facility_sp_id, 100)
        set_default_consumption_for_supply_point(TEST_DOMAIN, cls.ip.get_id, cls.facility_sp_id, 100)
Exemple #22
0
 def commtrack_settings(self):
     # this import causes some dependency issues so lives in here
     from corehq.apps.commtrack.models import CommtrackConfig
     if self.commtrack_enabled:
         return CommtrackConfig.for_domain(self.name)
     else:
         return None
    def testOTASettings(self):
        domain = bootstrap_domain()
        ct_settings = CommtrackConfig.for_domain(domain.name)
        ct_settings.consumption_config = ConsumptionConfig(
            min_transactions=10,
            min_window=20,
            optimal_window=60,
        )
        ct_settings.ota_restore_config = StockRestoreConfig(
            section_to_consumption_types={'stock': 'consumption'},
        )
        set_default_monthly_consumption_for_domain(domain.name, 5 * DAYS_IN_MONTH)
        restore_settings = ct_settings.get_ota_restore_settings()
        self.assertEqual(1, len(restore_settings.section_to_consumption_types))
        self.assertEqual('consumption', restore_settings.section_to_consumption_types['stock'])
        self.assertEqual(10, restore_settings.consumption_config.min_periods)
        self.assertEqual(20, restore_settings.consumption_config.min_window)
        self.assertEqual(60, restore_settings.consumption_config.max_window)
        self.assertEqual(150, restore_settings.consumption_config.default_monthly_consumption_function('foo', 'bar'))
        self.assertFalse(restore_settings.force_consumption_case_filter(CommCareCase(type='force-type')))
        self.assertEqual(0, len(restore_settings.default_product_list))

        ct_settings.ota_restore_config.force_consumption_case_types=['force-type']
        ct_settings.ota_restore_config.use_dynamic_product_list=True
        restore_settings = ct_settings.get_ota_restore_settings()
        self.assertTrue(restore_settings.force_consumption_case_filter(CommCareCase(type='force-type')))
        self.assertEqual(3, len(restore_settings.default_product_list))
Exemple #24
0
def _create_commtrack_config_if_needed(domain):
    if CommtrackConfig.for_domain(domain):
        return

    CommtrackConfig(
        domain=domain,
        actions=[
            CommtrackActionConfig(
                action='receipts',
                keyword='r',
                caption='Received',
            ),
            CommtrackActionConfig(
                action='consumption',
                keyword='c',
                caption='Consumed',
            ),
            CommtrackActionConfig(
                action='consumption',
                subaction='loss',
                keyword='l',
                caption='Losses',
            ),
            CommtrackActionConfig(
                action='stockonhand',
                keyword='soh',
                caption='Stock on hand',
            ),
            CommtrackActionConfig(
                action='stockout',
                keyword='so',
                caption='Stock-out',
            ),
        ],
    ).save()
Exemple #25
0
    def setUp(self):
        super(XMLTest, self).setUp()
        self.domain = util.bootstrap_domain(util.TEST_DOMAIN)
        util.bootstrap_location_types(self.domain.name)
        util.bootstrap_products(self.domain.name)
        self.products = sorted(Product.by_domain(self.domain.name),
                               key=lambda p: p._id)
        self.ct_settings = CommtrackConfig.for_domain(self.domain.name)
        self.ct_settings.consumptionconfig = ConsumptionConfig(
            min_transactions=0,
            min_window=0,
            optimal_window=60,
        )
        self.ct_settings.save()
        self.ct_settings.consumptionconfig.commtrack_settings = self.ct_settings
        self.ct_settings.consumptionconfig.save()
        self.domain = Domain.get(self.domain._id)

        self.loc = make_loc('loc1')
        self.sp = self.loc.linked_supply_point()
        self.users = [
            util.bootstrap_user(self, **user_def)
            for user_def in self.user_definitions
        ]
        self.user = self.users[0]
        self.case_ids = [self.sp.case_id]
        self.addCleanup(self.delete_ledger_values, self.sp.case_id)
Exemple #26
0
    def prepare_commtrack_config(self):
        """
        Bootstraps the domain-level metadata according to the static config.
        - Sets the proper location types hierarchy on the domain object.
        - Sets a keyword handler for reporting receipts
        """
        for location_type in LocationType.objects.by_domain(self.domain):
            location_type.delete()

        previous = None
        for loc_type in LOCATION_TYPES:
            previous, _ = LocationType.objects.get_or_create(
                domain=self.domain,
                name=loc_type,
                parent_type=previous,
                administrative=(loc_type != 'FACILITY'),
            )

        config = CommtrackConfig.for_domain(self.domain)
        config.consumption_config.exclude_invalid_periods = True
        actions = [action.keyword for action in config.actions]
        if 'delivered' not in actions:
            config.actions.append(
                CommtrackActionConfig(
                    action='receipts',
                    keyword='delivered',
                    caption='Delivered')
            )
            config.save()
Exemple #27
0
    def get_data(self):
        if self.active_product:
            sql_product = SQLProduct.objects.get(product_id=self.active_product.get_id)
            filtered_locations = [
                location for location in self.locations
                if sql_product in location.products
            ]
        else:
            filtered_locations = []
        for location in filtered_locations:
            if location.supply_point_id:
                stock_states = StockState.objects.filter(
                    case_id=location.supply_point_id,
                    section_id=STOCK_SECTION_TYPE,
                    product_id=self.active_product.get_id
                ).order_by('-last_modified_date')
            else:
                stock_states = None
            stock_levels = CommtrackConfig.for_domain(self.domain).stock_levels_config
            category = "no-data"
            if not stock_states:
                quantity = "No data"
                months_until_stockout = None
            else:
                monthly_consumption = stock_states[0].get_monthly_consumption()
                quantity = stock_states[0].stock_on_hand
                if not monthly_consumption:
                    months_until_stockout = None
                else:
                    months_until_stockout = (float(stock_states[0].stock_on_hand) / float(monthly_consumption))

                if quantity == 0:
                    category = 'stockout'
                    months_until_stockout = 0
                elif months_until_stockout is None:
                    category = "no-data"
                elif months_until_stockout < location.location_type.understock_threshold:
                    category = 'understock'
                elif stock_levels.understock_threshold < months_until_stockout < \
                        location.location_type.overstock_threshold:
                    category = 'adequate'
                elif months_until_stockout > location.location_type.overstock_threshold:
                    category = 'overstock'
            icon, color = self._get_icon_and_color(category)
            geo_point = None
            if location.latitude is not None and location.latitude is not None:
                geo_point = '%s %s' % (location.latitude, location.longitude)
            yield {
                'name': location.name,
                'type': location.location_type.name,
                'geo': geo_point,
                'quantity': quantity,
                'category': category,
                'icon': icon,
                'color': color,
                'months_until_stockout': "%.2f" % months_until_stockout if months_until_stockout is not None
                else "No data",
                'last_reported': stock_states[0].last_modified_date if stock_states else None
            }
Exemple #28
0
    def get_data(self):
        if self.active_product:
            sql_product = SQLProduct.objects.get(product_id=self.active_product.get_id)
            filtered_locations = [
                location for location in self.locations
                if sql_product in location.products
            ]
        else:
            filtered_locations = []
        for location in filtered_locations:
            if location.supply_point_id:
                stock_states = StockState.objects.filter(
                    case_id=location.supply_point_id,
                    section_id=STOCK_SECTION_TYPE,
                    product_id=self.active_product.get_id
                ).order_by('-last_modified_date')
            else:
                stock_states = None
            stock_levels = CommtrackConfig.for_domain(self.domain).stock_levels_config
            category = "no-data"
            if not stock_states:
                quantity = "No data"
                months_until_stockout = None
            else:
                monthly_consumption = stock_states[0].get_monthly_consumption()
                quantity = stock_states[0].stock_on_hand
                if not monthly_consumption:
                    months_until_stockout = None
                else:
                    months_until_stockout = (float(stock_states[0].stock_on_hand) / float(monthly_consumption))

                if quantity == 0:
                    category = 'stockout'
                    months_until_stockout = 0
                elif months_until_stockout is None:
                    category = "no-data"
                elif months_until_stockout < location.location_type.understock_threshold:
                    category = 'understock'
                elif stock_levels.understock_threshold < months_until_stockout < \
                        location.location_type.overstock_threshold:
                    category = 'adequate'
                elif months_until_stockout > location.location_type.overstock_threshold:
                    category = 'overstock'
            icon, color = self._get_icon_and_color(category)
            geo_point = None
            if location.latitude is not None and location.latitude is not None:
                geo_point = '%s %s' % (location.latitude, location.longitude)
            yield {
                'name': location.name,
                'type': location.location_type.name,
                'geo': geo_point,
                'quantity': quantity,
                'category': category,
                'icon': icon,
                'color': color,
                'months_until_stockout': "%.2f" % months_until_stockout if months_until_stockout is not None
                else "No data",
                'last_reported': stock_states[0].last_modified_date if stock_states else None
            }
Exemple #29
0
def all_sms_codes(domain):
    config = CommtrackConfig.for_domain(domain)

    actions = dict((action.keyword, action) for action in config.actions)
    products = dict((p.code, p) for p in Product.by_domain(domain))

    sms_codes = zip(('action', 'product'), (actions, products))
    return dict(itertools.chain(*([(k.lower(), (type, v)) for k, v in six.iteritems(codes)] for type, codes in sms_codes)))
Exemple #30
0
def stock_level_config_for_domain(domain, commtrack_enabled):
    from corehq.apps.commtrack.models import CommtrackConfig
    ct_config = CommtrackConfig.for_domain(domain)
    if ((ct_config is None) or (not commtrack_enabled)
            or LOCATION_TYPE_STOCK_RATES.enabled(domain)):
        return None
    else:
        return ct_config.stock_levels_config
def process_stock(xform):
    """
    process the commtrack xml constructs in an incoming submission
    """
    if is_device_report(xform):
        return

    domain = xform.domain

    config = CommtrackConfig.for_domain(domain)

    # these are the raw stock report objects from the xml
    stock_reports = list(unpack_commtrack(xform, config))
    # flattened transaction list spanning all stock reports in the form
    transactions = [t for r in stock_reports for t in r.transactions]
    # omitted: normalize_transactions (used for bulk requisitions?)

    if not transactions:
        return

    # transactions grouped by case/product id
    grouped_tx = map_reduce(lambda tx: [((tx.case_id, tx.product_id),)],
                            lambda v: sorted(v, key=lambda tx: tx.timestamp),
                            data=transactions,
                            include_docs=True)

    # list of cases that had stock reports in the form, properly wrapped by case type
    try:
        relevant_cases = [wrap_commtrack_case(result['doc']) for result in
                          CommCareCase.get_db().view('_all_docs',
                                                     keys=list(set(k[0] for k in grouped_tx)),
                                                     include_docs=True)]
    except KeyError:
        raise Exception("Cannot find case matching supplied entity id")

    user_id = xform.form['meta']['userID']
    submit_time = xform['received_on']

    # touch every case for proper ota restore logic syncing to be preserved
    for case in relevant_cases:
        case_action = CommCareCaseAction.from_parsed_action(
            submit_time, user_id, xform, AbstractAction(CASE_ACTION_COMMTRACK)
        )
        # hack: clear the sync log id so this modification always counts
        # since consumption data could change server-side
        case_action.sync_log_id = ''
        case.actions.append(case_action)
        case.save()

    # create the django models
    for report in stock_reports:
        report.create_models()

    # TODO make this a signal
    from corehq.apps.commtrack.signals import send_notifications, raise_events
    send_notifications(xform, relevant_cases)
    raise_events(xform, relevant_cases)
 def setUp(self):
     self.endpoint = MockEndpoint('http://test-api.com/', 'dummy', 'dummy')
     self.api_object = ILSGatewayAPI(TEST_DOMAIN, self.endpoint)
     self.datapath = os.path.join(os.path.dirname(__file__), 'data')
     domain = initial_bootstrap(TEST_DOMAIN)
     CommtrackConfig(domain=domain.name).save()
     self.api_object.prepare_commtrack_config()
     for location in Location.by_domain(TEST_DOMAIN):
         location.delete()
Exemple #33
0
def all_sms_codes(domain):
    config = CommtrackConfig.for_domain(domain)

    actions = dict((action.keyword, action) for action in config.actions)
    products = dict((p.code, p) for p in Product.by_domain(domain))
    commands = {config.multiaction_keyword: {"type": "stock_report_generic", "caption": "Stock Report"}}

    sms_codes = zip(("action", "product", "command"), (actions, products, commands))
    return dict(itertools.chain(*([(k.lower(), (type, v)) for k, v in codes.iteritems()] for type, codes in sms_codes)))
Exemple #34
0
def _prepare_ledger_for_es(ledger):
    from corehq.apps.commtrack.models import CommtrackConfig
    commtrack_config = CommtrackConfig.for_domain(ledger['domain'])

    if commtrack_config and commtrack_config.use_auto_consumption:
        daily_consumption = _get_daily_consumption_for_ledger(ledger)
        ledger['daily_consumption'] = daily_consumption

    return ledger
 def test_report_with_exclude_disabled(self):
     commtrack_config = CommtrackConfig(domain=self.domain.name)
     commtrack_config.consumption_config = ConsumptionConfig()
     commtrack_config.save()
     self.create_transactions(self.domain.name)
     self.assertEqual(StockTransaction.objects.all().count(), 3)
     self.assertEqual(StockTransaction.objects.filter(type='receipts').count(), 1)
     commtrack_config.delete()
Exemple #36
0
def should_exclude_invalid_periods(domain):
    """
    Whether the domain's consumption calculation should exclude invalid periods
    """
    from corehq.apps.commtrack.models import CommtrackConfig
    if domain:
        config = CommtrackConfig.for_domain(domain)
        if config:
            return config.consumption_config.exclude_invalid_periods
    return False
 def get_months_until_stockout_icon(value):
     stock_levels = CommtrackConfig.for_domain(self.config['domain']).stock_levels_config
     if float(value) == 0.0:
         return '%s <span class="icon-remove" style="color:red"/>' % value
     elif float(value) < stock_levels.understock_threshold:
         return '%s <span class="icon-warning-sign" style="color:orange"/>' % value
     elif stock_levels.understock_threshold < float(value) < stock_levels.overstock_threshold:
         return '%s <span class="icon-ok" style="color:green"/>' % value
     elif float(value) >= stock_levels.overstock_threshold:
         return '%s <span class="icon-arrow-up" style="color:purple"/>' % value
def should_exclude_invalid_periods(domain):
    """
    Whether the domain's consumption calculation should exclude invalid periods
    """
    from corehq.apps.commtrack.models import CommtrackConfig
    if domain:
        config = CommtrackConfig.for_domain(domain)
        if config:
            return config.consumption_config.exclude_invalid_periods
    return False
    def setUp(self):
        super(ConfirmDeliveryTest, self).setUp()
        self.api = MockOpenLMISEndpoint("uri://mock/lmis/endpoint", username='******', password='******')

        openlmis_config = OpenLMISConfig()
        openlmis_config.enabled = True

        commtrack_config = CommtrackConfig.get(self.domain.commtrack_settings._id)
        commtrack_config.openlmis_config = openlmis_config
        commtrack_config.save()
Exemple #40
0
    def setUp(self):
        super(OpenLMISTestBase, self).setUp()
        self.api = MockOpenLMISEndpoint("uri://mock/lmis/endpoint", username="******", password="******")

        openlmis_config = OpenLMISConfig()
        openlmis_config.enabled = True

        commtrack_config = CommtrackConfig.for_domain(self.domain.name)
        commtrack_config.openlmis_config = openlmis_config
        commtrack_config.save()
Exemple #41
0
 def _populate_stock_levels(self):
     from corehq.apps.commtrack.models import CommtrackConfig
     ct_config = CommtrackConfig.for_domain(self.domain)
     if ((ct_config is None) or (not self.commtrack_enabled)
             or LOCATION_TYPE_STOCK_RATES.enabled(self.domain)):
         return
     config = ct_config.stock_levels_config
     self.emergency_level = config.emergency_level
     self.understock_threshold = config.understock_threshold
     self.overstock_threshold = config.overstock_threshold
Exemple #42
0
def should_exclude_invalid_periods(domain):
    """
    Whether the domain's consumption calculation should exclude invalid periods
    i.e. periods where the stock went up without a receipt being reported
    """
    from corehq.apps.commtrack.models import CommtrackConfig
    if domain:
        config = CommtrackConfig.for_domain(domain)
        if config:
            return config.consumption_config.exclude_invalid_periods
    return False
Exemple #43
0
def should_exclude_invalid_periods(domain):
    """
    Whether the domain's consumption calculation should exclude invalid periods
    i.e. periods where the stock went up without a receipt being reported
    """
    from corehq.apps.commtrack.models import CommtrackConfig
    if domain:
        config = CommtrackConfig.for_domain(domain)
        if config:
            return config.consumption_config.exclude_invalid_periods
    return False
Exemple #44
0
def all_sms_codes(domain):
    config = CommtrackConfig.for_domain(domain)

    actions = dict((action.keyword, action) for action in config.actions)
    products = dict((p.code, p) for p in Product.by_domain(domain))
    commands = {
        config.multiaction_keyword: {'type': 'stock_report_generic', 'caption': 'Stock Report'},
    }

    sms_codes = zip(('action', 'product', 'command'), (actions, products, commands))
    return dict(itertools.chain(*([(k.lower(), (type, v)) for k, v in codes.iteritems()] for type, codes in sms_codes)))
Exemple #45
0
def all_sms_codes(domain):
    config = CommtrackConfig.for_domain(domain)

    actions = dict((action.keyword, action) for action in config.actions)
    products = dict((p.code, p) for p in Product.by_domain(domain))
    commands = {
        config.multiaction_keyword: {'type': 'stock_report_generic', 'caption': 'Stock Report'},
    }

    sms_codes = zip(('action', 'product', 'command'), (actions, products, commands))
    return dict(itertools.chain(*([(k.lower(), (type, v)) for k, v in codes.iteritems()] for type, codes in sms_codes)))
Exemple #46
0
def stock_level_config_for_domain(domain, commtrack_enabled):
    from corehq.apps.commtrack.models import CommtrackConfig
    ct_config = CommtrackConfig.for_domain(domain)
    if (
        (ct_config is None) or
        (not commtrack_enabled) or
        LOCATION_TYPE_STOCK_RATES.enabled(domain)
    ):
        return None
    else:
        return ct_config.stock_levels_config
def process(domain, instance):
    """process an incoming commtrack stock report instance"""
    config = CommtrackConfig.for_domain(domain)
    root = etree.fromstring(instance)
    user_id, transactions = unpack_transactions(root, config)
    transactions = list(normalize_transactions(transactions))

    def get_transactions(all_tx, type_filter):
        """get all the transactions of the relevant type (filtered by type_filter),
        grouped by product (returns a dict of 'product subcase id' => list of transactions),
        with each set of transactions sorted in the correct order for processing
        """
        return map_reduce(
            lambda tx: [(tx.case_id,)],
            lambda v: sorted(v, key=lambda tx: tx.priority_order),  # important!
            data=filter(type_filter, all_tx),
            include_docs=True,
        )

    # split transactions by type and product
    stock_transactions = get_transactions(transactions, lambda tx: tx.category == "stock")
    requisition_transactions = get_transactions(transactions, lambda tx: tx.category == "requisition")

    case_ids = list(set(itertools.chain(*[tx.get_case_ids() for tx in transactions])))
    cases = dict((c._id, c) for c in CommCareCase.view("_all_docs", keys=case_ids, include_docs=True))

    # TODO: code to auto generate / update requisitions from transactions if
    # project is configured for that.

    # TODO: when we start receiving commcare-submitted reports, we should be using a server time rather
    # than relying on timeStart (however timeStart is set to server time for reports received via sms)
    submit_time = root.find(".//%s" % _("timeStart", META_XMLNS)).text
    post_processed_transactions = list(transactions)
    for product_id, product_case in cases.iteritems():
        stock_txs = stock_transactions.get(product_id, [])
        if stock_txs:
            case_block, reconciliations = process_product_transactions(user_id, submit_time, product_case, stock_txs)
            root.append(case_block)
            post_processed_transactions.extend(reconciliations)

        req_txs = requisition_transactions.get(product_id, [])
        if req_txs and config.requisitions_enabled:
            req = RequisitionState.from_transactions(user_id, product_case, req_txs)
            case_block = etree.fromstring(req.to_xml())
            root.append(case_block)
    replace_transactions(root, post_processed_transactions)

    submission = etree.tostring(root)
    logger.debug("submitting: %s" % submission)

    spoof_submission(
        get_submit_url(domain), submission, headers={"HTTP_X_SUBMIT_TIME": submit_time}, hqsubmission=False
    )
Exemple #48
0
def _prepare_ledger_for_es(ledger):
    from corehq.apps.commtrack.models import CommtrackConfig
    commtrack_config = CommtrackConfig.for_domain(ledger['domain'])

    if commtrack_config and commtrack_config.use_auto_consumption:
        daily_consumption = _get_daily_consumption_for_ledger(ledger)
        ledger['daily_consumption'] = daily_consumption

    if not ledger.get('location_id') and ledger.get('case_id'):
        ledger['location_id'] = _location_id_for_case(ledger['case_id'])

    return ledger
Exemple #49
0
    def setUp(self):
        super(OpenLMISTestBase, self).setUp()
        self.api = MockOpenLMISEndpoint("uri://mock/lmis/endpoint",
                                        username='******',
                                        password='******')

        openlmis_config = OpenLMISConfig()
        openlmis_config.enabled = True

        commtrack_config = CommtrackConfig.for_domain(self.domain.name)
        commtrack_config.openlmis_config = openlmis_config
        commtrack_config.save()
Exemple #50
0
def _prepare_ledger_for_es(ledger):
    from corehq.apps.commtrack.models import CommtrackConfig
    commtrack_config = CommtrackConfig.for_domain(ledger['domain'])

    if commtrack_config and commtrack_config.use_auto_consumption:
        daily_consumption = _get_daily_consumption_for_ledger(ledger)
        ledger['daily_consumption'] = daily_consumption

    if not ledger.get('location_id') and ledger.get('case_id'):
        ledger['location_id'] = _location_id_for_case(ledger['case_id'])

    return ledger
Exemple #51
0
    def setUpClass(cls):
        domain = prepare_domain(TEST_DOMAIN)
        p = Product(domain=domain.name, name='Jadelle', code='jd', unit='each')
        p.save()
        p2 = Product(domain=domain.name,
                     name='Male Condom',
                     code='mc',
                     unit='each')
        p2.save()
        p3 = Product(domain=domain.name, name='Lofem', code='lf', unit='each')
        p3.save()
        p4 = Product(domain=domain.name, name='Ng', code='ng', unit='each')
        p4.save()
        p5 = Product(domain=domain.name,
                     name='Micro-G',
                     code='mg',
                     unit='each')
        p5.save()
        loc = make_loc(code="garms",
                       name="Test RMS",
                       type="Regional Medical Store",
                       domain=domain.name)
        test.bootstrap(TEST_BACKEND, to_console=True)
        cls.user1 = bootstrap_user(username='******',
                                   first_name='test1',
                                   last_name='test1',
                                   domain=domain.name,
                                   home_loc=loc)
        cls.user2 = bootstrap_user(username='******',
                                   domain=domain.name,
                                   home_loc=loc,
                                   first_name='test2',
                                   last_name='test2',
                                   phone_number='222222',
                                   user_data={'role': 'In Charge'})

        try:
            XFormInstance.get(docid='test-xform')
        except ResourceNotFound:
            xform = XFormInstance(_id='test-xform')
            xform.save()
        sql_location = loc.sql_location
        sql_location.products = SQLProduct.objects.filter(product_id=p5.get_id)
        sql_location.save()
        config = CommtrackConfig.for_domain(domain.name)
        config.actions.append(
            CommtrackActionConfig(action='receipts',
                                  keyword='rec',
                                  caption='receipts'))
        config.consumption_config = ConsumptionConfig(min_transactions=0,
                                                      min_window=0,
                                                      optimal_window=60)
        config.save()
Exemple #52
0
    def handle(self, *args, **options):
        view = CommtrackConfig.get_db().view(
            'commtrack/domain_config',
            reduce=False
        )

        # preload domains
        domains_map = {
            d.name: d for d in Domain.get_all()
        }

        """
        Default mode is to only copy types over to
        the domain objects. This is meant to be run after
        preindexing.

        Note this will run on both pre and post deploy instances
        to make sure there aren't any new changes the second time.
        """
        def _process_fn(config):
            if 'location_types' in config:
                domain = domains_map[config['domain']].to_json()
                domain['location_types'] = config['location_types']
                return True, domain

            return False, None

        migrate_data_command(
            view=view,
            fetch_class=CommtrackConfig,
            process_fn=_process_fn,
            save_class=Domain
        )

        if 'post_deploy' in args:
            """
            If user explicitly triggers post_deploy flag,
            then we will actually delete from the commtrack
            config objects.
            """
            def _post_process_fn(config):
                if 'location_types' in config:
                    del config['location_types']
                    return True, config
                else:
                    return False, None

            migrate_data_command(
                view=view,
                fetch_class=CommtrackConfig,
                process_fn=_post_process_fn,
            )
Exemple #53
0
    def process_change(self, change):
        ledger = change.get_document()
        from corehq.apps.commtrack.models import CommtrackConfig
        commtrack_config = CommtrackConfig.for_domain(ledger['domain'])

        if commtrack_config and commtrack_config.use_auto_consumption:
            daily_consumption = _get_daily_consumption_for_ledger(ledger)
            ledger['daily_consumption'] = daily_consumption

        if not ledger.get('location_id') and ledger.get('case_id'):
            ledger['location_id'] = _location_id_for_case(ledger['case_id'])

        _update_ledger_section_entry_combinations(ledger)
Exemple #54
0
def _create_commtrack_config_if_needed(domain):
    if CommtrackConfig.for_domain(domain):
        return

    CommtrackConfig(
        domain=domain,
        multiaction_enabled=True,
        multiaction_keyword='report',
        actions=[
            CommtrackActionConfig(
                action='receipts',
                keyword='r',
                caption='Received',
            ),
            CommtrackActionConfig(
                action='consumption',
                keyword='c',
                caption='Consumed',
            ),
            CommtrackActionConfig(
                action='consumption',
                subaction='loss',
                keyword='l',
                caption='Losses',
            ),
            CommtrackActionConfig(
                action='stockonhand',
                keyword='soh',
                caption='Stock on hand',
            ),
            CommtrackActionConfig(
                action='stockout',
                keyword='so',
                caption='Stock-out',
            ),
        ],
    ).save()
Exemple #55
0
    def setUp(self):
        # might as well clean house before doing anything
        delete_all_xforms()
        delete_all_cases()
        StockReport.objects.all().delete()
        StockTransaction.objects.all().delete()

        self.backend = test.bootstrap(TEST_BACKEND, to_console=True)
        self.domain = bootstrap_domain()
        self.ct_settings = CommtrackConfig.for_domain(self.domain.name)
        self.ct_settings.consumption_config = ConsumptionConfig(
            min_transactions=0,
            min_window=0,
            optimal_window=60,
            min_periods=0,
        )
        if self.requisitions_enabled:
            self.ct_settings.requisition_config = get_default_requisition_config(
            )

        self.ct_settings.save()

        self.domain = Domain.get(self.domain._id)

        self.loc = make_loc('loc1')
        self.sp = make_supply_point(self.domain.name, self.loc)
        self.users = [
            bootstrap_user(self, **user_def)
            for user_def in self.user_definitions
        ]

        if False:
            # bootstrap additional users for requisitions
            # needs to get reinserted for requisition stuff later
            self.approver = bootstrap_user(self, **APPROVER_USER)
            self.packer = bootstrap_user(self, **PACKER_USER)
            self.users += [self.approver, self.packer]

        # everyone should be in a group.
        self.group = Group(domain=TEST_DOMAIN,
                           name='commtrack-folks',
                           users=[u._id for u in self.users],
                           case_sharing=True)
        self.group.save()
        self.sp.owner_id = self.group._id
        self.sp.save()
        self.products = sorted(Product.by_domain(self.domain.name),
                               key=lambda p: p._id)
        self.assertEqual(3, len(self.products))
Exemple #56
0
def bootstrap_commtrack_settings_if_necessary(domain, requisitions_enabled=False):
    if not(domain and domain.commtrack_enabled and not CommtrackConfig.for_domain(domain.name)):
        return

    c = CommtrackConfig(
        domain=domain.name,
        multiaction_enabled=True,
        multiaction_keyword='report',
        actions=[
            CommtrackActionConfig(
                action='receipts',
                keyword='r',
                caption='Received',
            ),
            CommtrackActionConfig(
                action='consumption',
                keyword='c',
                caption='Consumed',
            ),
            CommtrackActionConfig(
                action='consumption',
                subaction='loss',
                keyword='l',
                caption='Losses',
            ),
            CommtrackActionConfig(
                action='stockonhand',
                keyword='soh',
                caption='Stock on hand',
            ),
            CommtrackActionConfig(
                action='stockout',
                keyword='so',
                caption='Stock-out',
            ),
        ],
        location_types=[
            LocationType(name='state', allowed_parents=[''], administrative=True),
            LocationType(name='district', allowed_parents=['state'], administrative=True),
            LocationType(name='block', allowed_parents=['district'], administrative=True),
            LocationType(name='village', allowed_parents=['block'], administrative=True),
            LocationType(name='outlet', allowed_parents=['block', 'village']),
        ],
        supply_point_types=[],
    )
    if requisitions_enabled:
        c.requisition_config = get_default_requisition_config()

    c.save()

    program = make_program(domain.name, 'Default', 'def')
    make_product(domain.name, 'Sample Product 1', 'pp', program.get_id)
    make_product(domain.name, 'Sample Product 2', 'pq', program.get_id)
    make_product(domain.name, 'Sample Product 3', 'pr', program.get_id)

    return c