예제 #1
0
    def test_archive(self):
        original_list = Product.by_domain(self.domain.name, wrap=False)

        self.products[0].archive()

        new_list = Product.by_domain(self.domain.name, wrap=False)

        self.assertTrue(
            self.products[0]._id not in [p['_id'] for p in new_list],
            "Archived product still returned by Product.by_domain()"
        )

        self.assertEqual(
            len(new_list),
            len(original_list) - 1
        )

        self.assertEqual(
            len(Product.by_domain(self.domain.name, wrap=False, include_archived=True)),
            len(original_list)
        )

        self.assertEqual(
            len(Product.archived_by_domain(self.domain.name, wrap=False, include_archived=True)),
            1
        )

        self.products[0].unarchive()

        self.assertEqual(
            len(original_list),
            len(Product.by_domain(self.domain.name, wrap=False))
        )
예제 #2
0
    def product_data(self):
        data = []
        if self.show_inactive:
            products = Product.archived_by_domain(
                domain=self.domain,
                limit=self.limit,
                skip=self.skip(),
            )
        else:
            products = Product.by_domain(
                domain=self.domain,
                limit=self.limit,
                skip=self.skip(),
            )

        for p in products:
            if p.program_id:
                program = Program.get(p.program_id)
            else:
                program = get_or_create_default_program(self.domain)
                p.program_id = program.get_id
                p.save()

            info = p._doc
            info['program'] = program.name
            info['edit_url'] = reverse('commtrack_product_edit', kwargs={'domain': self.domain, 'prod_id': p._id})
            info['archive_action_desc'] = self.get_archive_text(self.show_inactive)
            info['archive_action_text'] = _("Un-Archive") if self.show_inactive else _("Archive")
            info['archive_url'] = reverse(
                'unarchive_product' if self.show_inactive else 'archive_product',
                kwargs={'domain': self.domain, 'prod_id': p._id}
            )
            data.append(info)
        return data
예제 #3
0
def get_default_column_data(domain, location_types):
    data = {
        'headers': {},
        'values': {}
    }

    if Domain.get_by_name(domain).commtrack_settings.individual_consumption_defaults:
        products = Product.by_domain(domain)

        for loc_type in location_types:
            loc = get_loc_config(domain)[loc_type]
            if not loc.administrative:
                data['headers'][loc_type] = [
                    'default_' +
                    p.code for p in products
                ]

                locations = Location.filter_by_type(domain, loc_type)
                for loc in locations:
                    sp = SupplyPointCase.get_or_create_by_location(loc)

                    data['values'][loc._id] = [
                        get_default_monthly_consumption(
                            domain,
                            p._id,
                            loc_type,
                            sp._id
                        ) or '' for p in products
                    ]
            else:
                data['headers'][loc_type] = []
    return data
예제 #4
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))
예제 #5
0
    def setUp(self):
        # might as well clean house before doing anything
        delete_all_xforms()
        delete_all_cases()

        self.backend = test.bootstrap(TEST_BACKEND, to_console=True)
        self.domain = bootstrap_domain(requisitions_enabled=self.requisitions_enabled)
        self.loc = make_loc('loc1')

        self.reporters = dict((k, bootstrap_user(self, **v)) for k, v in REPORTING_USERS.iteritems())
        # backwards compatibility
        self.user = self.reporters['roaming']

        # bootstrap additional users for requisitions
        self.approver = bootstrap_user(self, **APPROVER_USER)
        self.packer = bootstrap_user(self, **PACKER_USER)

        self.users = self.reporters.values() + [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 = make_supply_point(self.domain.name, self.loc, owner_id=self.group._id)
        self.products = Product.by_domain(self.domain.name)
        self.assertEqual(3, len(self.products))
        self.spps = {}
        for p in self.products:
            self.spps[p.code] = make_supply_point_product(self.sp, p._id)
            self.assertEqual(self.spps[p.code].owner_id, self.group._id)
예제 #6
0
    def main_context(self):
        try:
            facilities = Location.filter_by_type_count(self.domain, 'FACILITY')
        except TypeError:
            facilities = 0

        contacts = CommCareUser.by_domain(self.domain, reduce=True)
        web_users = WebUser.by_domain(self.domain, reduce=True)

        try:
            products = len(Product.by_domain(self.domain))
        except ResourceNotFound:
            products = 0

        main_context = super(GlobalStats, self).main_context
        context = {
            'supply_points':  len(list(Location.by_domain(self.domain))),
            'facilities': facilities,
            'contacts':  contacts[0]['value'] if contacts else 0,
            'web_users': web_users[0]['value'] if web_users else 0,
            'products':  products,
            #TODO add next after the enlargement ILS migration
            'product_stocks':  0,
            'stock_transactions':  0,
            'inbound_messages':  0,
            'outbound_messages':  0
        }
        main_context.update(context)
        return main_context
예제 #7
0
    def setUp(self):
        # might as well clean house before doing anything
        delete_all_xforms()
        delete_all_cases()

        self.backend = test.bootstrap(TEST_BACKEND, to_console=True)
        self.domain = bootstrap_domain(requisitions_enabled=self.requisitions_enabled)
        self.user = bootstrap_user(**MAIN_USER)
        self.verified_number = self.user.get_verified_number()

        # bootstrap additional users for requisitions
        self.approver = bootstrap_user(**APPROVER_USER)
        self.packer = bootstrap_user(**PACKER_USER)

        self.users = [self.user, 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.loc = make_loc('loc1')
        self.sp = make_supply_point(self.domain.name, self.loc, owner_id=self.group._id)
        self.products = Product.by_domain(self.domain.name)
        self.assertEqual(3, len(self.products))
        self.spps = {}
        for p in self.products:
            self.spps[p.code] = make_supply_point_product(self.sp, p._id)
            self.assertEqual(self.spps[p.code].owner_id, self.group._id)
예제 #8
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,
                }
예제 #9
0
 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")
     initial_bootstrap(TEST_DOMAIN)
     for product in Prod.by_domain(TEST_DOMAIN):
         product.delete()
예제 #10
0
 def test_migration(self):
     bootstrap_domain(ILSGatewayAPI(TEST_DOMAIN, MockEndpoint('http://test-api.com/', 'dummy', 'dummy')))
     self.assertEqual(6, len(list(Product.by_domain(TEST_DOMAIN))))
     self.assertEqual(5, len(list(Location.by_domain(TEST_DOMAIN))))
     self.assertEqual(6, len(list(CommCareUser.by_domain(TEST_DOMAIN))))
     self.assertEqual(5, len(list(WebUser.by_domain(TEST_DOMAIN))))
     self.assertEqual(ILSMigrationStats.objects.filter(domain=TEST_DOMAIN).count(), 1)
 def setUp(self):
     self.datapath = os.path.join(os.path.dirname(__file__), 'data')
     self.api = MockOpenLMISEndpoint("uri://mock/lmis/endpoint", username='******', password='******')
     bootstrap_domain(TEST_DOMAIN)
     delete_all_cases()
     for product in Product.by_domain(TEST_DOMAIN):
         product.delete()
예제 #12
0
    def rows(self):

        def row_in_names(row, names):
            if row in names:
                return True, names.index(row)+1
            else:
                for idx, val in enumerate(names):
                    if unicode(row).lower() in PRODUCT_NAMES.get(val, []):
                        return True, idx+1
            return False, 0

        commandes = ['Comanndes']
        raux = ['Recu']
        taux = ['Taux']
        products = Product.by_domain(self.config['domain'])
        for product in products:
            commandes.append(0)
            raux.append(0)
            taux.append(0)
        names = []

        for product in products:
            names.append(unicode(product.name).lower())
        rows = super(DispDesProducts, self).rows
        for row in rows:
            exits, index = row_in_names(row[0], names)
            if exits:
                commandes[index] = row[1]
                raux[index] = row[2]
                taux[index] = "%d%%" % (100*row[2]['html']/(row[1]['html'] or 1))
        return [commandes, raux, taux]
예제 #13
0
def get_default_column_data(domain, location_types):
    data = {
        'headers': {},
        'values': {}
    }

    if Domain.get_by_name(domain).commtrack_settings.individual_consumption_defaults:
        products = Product.by_domain(domain, wrap=False)

        for loc_type in location_types:
            loc = get_loc_config(domain)[loc_type]
            if not loc.administrative:
                data['headers'][loc_type] = [
                    'default_' +
                    p['code_'] for p in products
                ]

                locations = Location.filter_by_type(domain, loc_type)
                for loc in locations:
                    data['values'][loc._id] = [
                        get_default_consumption(
                            domain,
                            p['_id'],
                            loc_type,
                            loc._id
                        ) or '' for p in products
                    ]
            else:
                data['headers'][loc_type] = []
    return data
예제 #14
0
 def product_data(self):
     data = []
     products = Product.by_domain(self.domain)
     for p in products:
         info = p._doc
         info['edit_url'] = reverse('commtrack_product_edit', kwargs={'domain': self.domain, 'prod_id': p._id})
         data.append(info)
     return data
예제 #15
0
    def clean_name(self):
        name = self.cleaned_data['name']

        other_products = [p for p in Product.by_domain(self.product.domain) if p._id != self.product._id]
        if name in [p.name for p in other_products]:
            raise forms.ValidationError('name already in use')

        return name
예제 #16
0
    def test_product_fixture(self):
        user = bootstrap_user(self, phone_number="1234567890")
        user_id = user.user_id
        products = ""
        product_list = Product.by_domain(user.domain)
        self._initialize_product_names(len(product_list))
        for i, product in enumerate(product_list):
            product_id = product._id
            product_name = self.product_names.next()
            product_unit = self._random_string(20)
            product_code = self._random_string(20)
            product_description = self._random_string(20)
            product_category = self._random_string(20)
            product_program_id = self._random_string(20)
            product_cost = 0 if i == 0 else float("%g" % random.uniform(1, 100))

            products += """
                <product id="{id}">
                    <name>{name}</name>
                    <unit>{unit}</unit>
                    <code>{code}</code>
                    <description>{description}</description>
                    <category>{category}</category>
                    <program_id>{program_id}</program_id>
                    <cost>{cost}</cost>
                </product>
            """.format(
                id=product_id,
                name=product_name,
                unit=product_unit,
                code=product_code,
                description=product_description,
                category=product_category,
                program_id=product_program_id,
                cost=product_cost,
            )

            product.name = product_name
            product.unit = product_unit
            product.code = product_code
            product.description = product_description
            product.category = product_category
            product.program_id = product_program_id
            product.cost = product_cost
            product.save()
        fixture = product_fixture_generator(user, V1, None)

        self.assertXmlEqual(
            """<fixture id="commtrack:products" user_id="{user_id}">
                                    <products>
                                        {products}
                                    </products>
                                </fixture>""".format(
                user_id=user_id, products=products
            ),
            ElementTree.tostring(fixture[0]),
        )
예제 #17
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)))
예제 #18
0
    def test_selective_product_sync(self):
        user = bootstrap_user(self, phone_number="1234567890")

        expected_xml = self.generate_product_fixture_xml(user)

        product_list = Product.by_domain(user.domain)
        self._initialize_product_names(len(product_list))

        fixture_original = product_fixture_generator(user, V1, None, None)
        generate_restore_payload(user.to_casexml_user())
        self.assertXmlEqual(
            expected_xml,
            ElementTree.tostring(fixture_original[0])
        )

        first_sync = sorted(SyncLog.view(
            "phone/sync_logs_by_user",
            include_docs=True,
            reduce=False
        ).all(), key=lambda x: x.date)[-1]

        # make sure the time stamp on this first sync is
        # not on the same second that the products were created
        first_sync.date += datetime.timedelta(seconds=1)

        # second sync is before any changes are made, so there should
        # be no products synced
        fixture_pre_change = product_fixture_generator(user, V1, None, first_sync)
        generate_restore_payload(user.to_casexml_user())
        self.assertEqual(
            [],
            fixture_pre_change,
            "Fixture was not empty on second sync"
        )

        second_sync = sorted(SyncLog.view(
            "phone/sync_logs_by_user",
            include_docs=True,
            reduce=False
        ).all(), key=lambda x: x.date)[-1]

        self.assertTrue(first_sync._id != second_sync._id)

        # save should make the product more recently updated than the
        # last sync
        for product in product_list:
            product.save()

        # now that we've updated a product, we should get
        # product data in sync again
        fixture_post_change = product_fixture_generator(user, V1, None, second_sync)

        # regenerate the fixture xml to make sure it is still legit
        self.assertXmlEqual(
            expected_xml,
            ElementTree.tostring(fixture_post_change[0])
        )
예제 #19
0
 def test_create_product(self):
     with open(os.path.join(self.datapath, 'sample_products.json')) as f:
         product = Product(json.loads(f.read())[0])
     self.assertEqual(0, len(Prod.by_domain(TEST_DOMAIN)))
     ilsgateway_product = sync_ilsgateway_product(TEST_DOMAIN, product)
     self.assertEqual(product.sms_code, ilsgateway_product.code.lower())
     self.assertEqual(product.name, ilsgateway_product.name)
     self.assertEqual(product.description, ilsgateway_product.description)
     self.assertEqual(product.units, str(ilsgateway_product.unit))
예제 #20
0
 def test_products_migration(self):
     checkpoint = MigrationCheckpoint(
         domain=TEST_DOMAIN, start_date=datetime.utcnow(), date=datetime.utcnow(), api="product", limit=100, offset=0
     )
     product_api = ApiSyncObject("product", self.endpoint.get_products, self.api_object.product_sync)
     synchronization(product_api, checkpoint, None, 100, 0)
     self.assertEqual("product", checkpoint.api)
     self.assertEqual(100, checkpoint.limit)
     self.assertEqual(0, checkpoint.offset)
     self.assertEqual(6, len(list(Prod.by_domain(TEST_DOMAIN))))
    def testCreateProgram(self):
        with open(os.path.join(self.datapath, 'sample_program.json')) as f:
            lmis_program = Program.from_json(json.loads(f.read()))

        # program sync
        self.assertEqual(0, len(Product.by_domain(TEST_DOMAIN)))
        commtrack_program = sync_openlmis_program(TEST_DOMAIN, lmis_program)
        self.assertEqual(lmis_program.name, commtrack_program.name)
        self.assertEqual(lmis_program.code, commtrack_program.code)

        # product sync
        self.assertEqual(len(lmis_program.products), len(Product.by_domain(TEST_DOMAIN)))
        lmis_product = lmis_program.products[0]
        product = Product.get_by_code(TEST_DOMAIN, lmis_product.code)
        self.assertEqual(product.code, lmis_product.code)
        self.assertEqual(product.name, lmis_product.name)
        self.assertEqual(product.description, lmis_product.description)
        self.assertEqual(product.unit, str(lmis_product.unit))
        self.assertEqual(product.category, str(lmis_product.category))
예제 #22
0
 def __init__(self, domain, *args, **kwargs):
     self.domain = domain
     super(ConsumptionForm, self).__init__(*args, **kwargs)
     products = Product.by_domain(domain)
     for p in products:
         field_name = "default_%s" % p._id
         display = _("Default %(product_name)s") % {"product_name": p.name}
         self.fields[field_name] = forms.DecimalField(
             label=display, required=False, initial=get_default_monthly_consumption(self.domain, p._id, None, None)
         )
예제 #23
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)))
예제 #24
0
 def setUp(self):
     self.backend = test.bootstrap(TEST_BACKEND, to_console=True)
     self.domain = bootstrap_domain()
     self.user = bootstrap_user()
     self.verified_number = self.user.get_verified_number()
     self.loc = make_loc('loc1')
     self.sp = make_supply_point(self.domain.name, self.loc)
     self.products = Product.by_domain(self.domain.name)
     self.assertEqual(3, len(self.products))
     self.spps = {}
     for p in self.products:
         self.spps[p.code] = make_supply_point_product(self.sp, p._id)
예제 #25
0
def charts(request, domain, template="commtrack/charts.html"):
    products = Product.by_domain(domain)
    prod_codes = [p.code for p in products]
    prod_codes.extend(range(20))

    from random import randint
    num_facilities = randint(44, 444)


    ### gen fake data
    def vals():
        tot = 0
        l = []
        for i in range(4):
            v = randint(0, num_facilities - tot)
            l.append(v)
            tot += v
        l.append(num_facilities - tot)
        return l

    statuses = [
        {"key": "stocked out", "color": "#e00707"},
        {"key": "under stock", "color": "#ffb100"},
        {"key": "adequate stock", "color": "#4ac925"},
        {"key": "overstocked", "color": "#b536da"},
        {"key": "unknown", "color": "#ABABAB"}
    ]

    for s in statuses:
        s["values"] = []

    for i, p in enumerate(prod_codes):
        vs = vals()
        for j in range(5):
            statuses[j]["values"].append({"x": p, "y": vs[j]})

    # colors don't actually work correctly for pie charts
    resp_values = [
        {"label": "Submitted on Time", "color": "#4ac925", "value": randint(0, 40)},
        {"label": "Didn't respond", "color": "#ABABAB", "value": randint(0, 20)},
        {"label": "Submitted Late", "color": "#e00707", "value": randint(0, 8)},
    ]
    response_data = [{
        "key": "Current Late Report",
        "values": resp_values
    }]

    ctxt = {
        "domain": domain,
        "stock_data": statuses,
        "response_data": response_data,
    }
    return render(request, template, ctxt)
예제 #26
0
 def setUp(self):
     self.datapath = os.path.join(os.path.dirname(__file__), 'data')
     initial_bootstrap(TEST_DOMAIN)
     config = ILSGatewayConfig()
     config.domain = TEST_DOMAIN
     config.enabled = True
     config.password = '******'
     config.username = '******'
     config.url = 'http://test-api.com/'
     config.save()
     for product in Product.by_domain(TEST_DOMAIN):
         product.delete()
예제 #27
0
 def consumption(self):
     consumptions = []
     for product in Product.by_domain(self.domain):
         consumption = get_default_consumption(
             self.domain,
             product._id,
             self.location.location_type,
             self.supply_point._id if self.supply_point else None,
         )
         if consumption:
             consumptions.append((product.name, consumption))
     return consumptions
예제 #28
0
    def setUpClass(cls):
        cls.datapath = os.path.join(os.path.dirname(__file__), 'data')
        cls.sms_backend, cls.sms_backend_mapping = setup_default_sms_test_backend()
        initial_bootstrap(TEST_DOMAIN)

        config = ILSGatewayConfig()
        config.domain = TEST_DOMAIN
        config.enabled = True
        config.password = '******'
        config.username = '******'
        config.url = 'http://test-api.com/'
        config.save()
        for product in Product.by_domain(TEST_DOMAIN):
            product.delete()
예제 #29
0
    def tearDown(self):
        for product in Product.by_domain(TEST_DOMAIN):
            product.delete()

        for location in Location.by_domain(TEST_DOMAIN):
            location.delete()

        for user in CommCareUser.by_domain(TEST_DOMAIN):
            user.delete()

        for web_user in WebUser.by_domain(TEST_DOMAIN):
            web_user.delete()

        ILSMigrationStats.objects.all().delete()
        ILSMigrationProblem.objects.all().delete()
예제 #30
0
    def product_data(self):
        data = []
        products = Product.by_domain(domain=self.domain, limit=self.limit, skip=self.skip())
        for p in products:
            if p.program_id:
                program = Program.get(p.program_id)
            else:
                program = get_or_make_def_program(self.domain)
                p.program_id = program.get_id
                p.save()

            info = p._doc
            info['program'] = program.name
            info['edit_url'] = reverse('commtrack_product_edit', kwargs={'domain': self.domain, 'prod_id': p._id})
            data.append(info)
        return data
예제 #31
0
    def product_data(self):
        data = []
        products = Product.by_domain(domain=self.domain, limit=self.limit, skip=self.skip())
        for p in products:
            if p.program_id:
                program = Program.get(p.program_id)
            else:
                program = get_or_make_def_program(self.domain)
                p.program_id = program.get_id
                p.save()

            info = p._doc
            info['program'] = program.name
            info['edit_url'] = reverse('commtrack_product_edit', kwargs={'domain': self.domain, 'prod_id': p._id})
            data.append(info)
        return data
예제 #32
0
 def __init__(self, domain, *args, **kwargs):
     self.domain = domain
     super(ConsumptionForm, self).__init__(*args, **kwargs)
     products = Product.by_domain(domain)
     for p in products:
         field_name = 'default_%s' % p.code
         display = _('Default %(product_name)s') % {'product_name': p.name}
         self.fields[field_name] = forms.DecimalField(
             label=display,
             required=False,
             initial=get_default_consumption(
                 self.domain,
                 p._id,
                 None,
                 None
             )
         )
예제 #33
0
    def setUp(self):
        self.datapath = os.path.join(os.path.dirname(__file__), 'data')
        initial_bootstrap(TEST_DOMAIN)
        sms_backend = TestSMSBackend(name="MOBILE_BACKEND_TEST",
                                     is_global=True)
        sms_backend._id = sms_backend.name
        sms_backend.save()

        config = ILSGatewayConfig()
        config.domain = TEST_DOMAIN
        config.enabled = True
        config.password = '******'
        config.username = '******'
        config.url = 'http://test-api.com/'
        config.save()
        for product in Product.by_domain(TEST_DOMAIN):
            product.delete()
예제 #34
0
def get_default_column_data(domain, location_types):
    data = {
        'headers': {},
        'values': {}
    }

    if Domain.get_by_name(domain).commtrack_settings.individual_consumption_defaults:
        products = Product.by_domain(domain)

        supply_point_map = SupplyPointCase.get_location_map_by_domain(domain)

        consumption_dict = build_consumption_dict(domain)

        if not consumption_dict:
            return data

        for loc_type in location_types:
            loc = get_loc_config(domain)[loc_type]
            if not loc.administrative:
                data['headers'][loc_type] = [
                    'default_' +
                    p.code for p in products
                ]

                locations = Location.filter_by_type(domain, loc_type)
                for loc in locations:
                    if loc._id in supply_point_map:
                        sp_id = supply_point_map[loc._id]
                    else:
                        # this only happens if the supply point case did
                        # not already exist
                        sp_id = SupplyPointCase.get_or_create_by_location(loc)._id

                    data['values'][loc._id] = [
                        get_loaded_default_monthly_consumption(
                            consumption_dict,
                            domain,
                            p._id,
                            loc_type,
                            sp_id
                        ) or '' for p in products
                    ]
            else:
                data['headers'][loc_type] = []
    return data
예제 #35
0
def recalculate_domain_consumption(domain):
    """
    Given a domain, recalculate all saved consumption settings in that domain.
    """
    # note: might get slow as this gets huge
    found_doc_ids = DocDomainMapping.objects.filter(
        domain_name=domain,
        doc_type='CommCareCase',
    ).values_list('doc_id', flat=True)
    products = Product.by_domain(domain)
    for supply_point_id in found_doc_ids:
        for product in products:
            filtered_transactions = StockTransaction.objects.filter(
                case_id=supply_point_id,
                product_id=product._id,
                section_id=const.SECTION_TYPE_STOCK,
            ).order_by('-report__date')
            if filtered_transactions:
                update_stock_state_for_transaction(filtered_transactions[0])
예제 #36
0
 def test_products_migration(self):
     checkpoint = MigrationCheckpoint(
         domain=TEST_DOMAIN,
         start_date=datetime.utcnow(),
         date=datetime.utcnow(),
         api='product',
         limit=100,
         offset=0
     )
     product_api = ApiSyncObject(
         'product',
         self.endpoint.get_products,
         self.api_object.product_sync
     )
     synchronization(product_api, checkpoint, None, 100, 0)
     self.assertEqual('product', checkpoint.api)
     self.assertEqual(100, checkpoint.limit)
     self.assertEqual(0, checkpoint.offset)
     self.assertEqual(6, len(list(Prod.by_domain(TEST_DOMAIN))))
예제 #37
0
def product_fetch(request, domain):
    page = int(request.GET.get('page', 1))
    limit = int(request.GET.get('limit', DEFAULT_PRODUCT_LIST_LIMIT))
    skip = (page-1)*limit

    sort_by = request.GET.get('sortBy', 'abc')

    show_inactive = json.loads(request.GET.get('show_inactive', 'false'))

    products = Product.by_domain(domain) #limit=limit, skip=skip)
    def product_data(p):
        info = p._doc
        info['edit_url'] = reverse('commtrack_product_edit', kwargs={'domain': domain, 'prod_id': p._id})
        return info

    return HttpResponse(json.dumps(dict(
        success=True,
        current_page=page,
        product_list=[product_data(p) for p in products],
    )), 'text/json')
예제 #38
0
def product_list(request, domain, template="commtrack/manage/products.html"):
    page = request.GET.get('page', 1)
    limit = request.GET.get('limit', DEFAULT_PRODUCT_LIST_LIMIT)

    show_inactive = json.loads(request.GET.get('show_inactive', 'false'))

    total = len(Product.by_domain(domain))

    context = {
        'domain': domain,
    }
    context.update(product_list=dict(
        page=page,
        limit=limit,
        total=total,
    ),
                   show_inactive=show_inactive,
                   pagination_limit_options=range(DEFAULT_PRODUCT_LIST_LIMIT,
                                                  51,
                                                  DEFAULT_PRODUCT_LIST_LIMIT))
    return render(request, template, context)
예제 #39
0
    def headers(self):
        header = DataTablesHeader()
        columns = self.model.columns
        if self.model.have_groups:
            header.add_column(
                DataTablesColumnGroup('', columns[0].data_tables_column))
        else:
            header.add_column(columns[0].data_tables_column)

        self.groups = [group.name for group in Product.by_domain(self.domain)]
        for group in self.groups:
            if self.model.have_groups:
                header.add_column(
                    DataTablesColumnGroup(
                        group, *[
                            columns[j].data_tables_column
                            for j in xrange(1, len(columns))
                        ]))
            else:
                header.add_column(DataTablesColumn(group))

        return header
예제 #40
0
    def display_config(self):
        conf = {
            'name_column': 'name',
            'detail_columns': ['type'],
            'table_columns': ['type'],
            'column_titles': {
                'type': 'Supply Point Type',
            },
            'enum_captions': {},
            'numeric_format': {},
            'metrics': [
                {
                    'color': {
                        'column': 'type',
                    },
                },
            ],
        }

        titles = {
            'current_stock': 'Stock on Hand',
            'consumption': 'Monthly Consumption',
            'months_remaining': 'Months of Stock Remaining',
            'category': 'Current Stock Status',
        }

        products = sorted(Product.by_domain(
            self.domain,
            include_archived=self.request.GET.get('archived_products', False)),
                          key=lambda p: p.name)

        if self.program_id:
            products = filter(lambda c: c.program_id == self.program_id,
                              products)
        for p in products:
            col_id = lambda c: '%s-%s' % (p._id, c)

            product_cols = []
            for c in ('category', 'current_stock', 'months_remaining',
                      'consumption'):
                conf['column_titles'][col_id(c)] = titles[c]
                product_cols.append(col_id(c))
            conf['detail_columns'].extend(product_cols)

            product_metrics = [{
                'icon': {
                    'column': col_id('category'),
                    'categories': {
                        'stockout': '/static/commtrack/img/stockout.png',
                        'understock': '/static/commtrack/img/warning.png',
                        'adequate': '/static/commtrack/img/goodstock.png',
                        'overstock': '/static/commtrack/img/overstock.png',
                        #'nodata': '/static/commtrack/img/no_data.png',
                        '_null': '/static/commtrack/img/no_data.png',
                    },
                }
            }]
            conf['enum_captions'][col_id('category')] = {
                'stockout': 'Stocked out',
                'understock': 'Under-stock',
                'adequate': 'Adequate Stock',
                'overstock': 'Over-stock',
                '_null': 'No Data',
            }

            for c in ('current_stock', 'months_remaining', 'consumption'):
                metric = {
                    'title': conf['column_titles'][col_id(c)],
                    'size': {
                        'column': col_id(c),
                    },
                }
                if c not in ('consumption', ):
                    metric['color'] = {
                        'column': col_id('category'),
                        'categories': {
                            'stockout': 'rgba(255, 0, 0, .8)',
                            'understock': 'rgba(255, 120, 0, .8)',
                            'adequate': 'rgba(50, 200, 50, .8)',
                            'overstock': 'rgba(120, 0, 255, .8)',
                            '_null': 'rgba(128, 128, 128, .8)',
                        },
                    }
                else:
                    metric['color'] = 'rgba(120, 120, 255, .8)'
                product_metrics.append(metric)

                conf['numeric_format'][col_id(c)] = {
                    'current_stock':
                    "return x + ' %s'" % (p.unit or 'unit'),
                    'months_remaining':
                    "return (Math.round(10 * x) / 10) + (x == 1 ? ' month' : ' months')",
                    'consumption':
                    "return (Math.round(10 * x) / 10) + ' %s / month'" %
                    (p.unit or 'unit'),
                }[c]

            conf['metrics'].append({
                'title': p.name,
                'group': True,
                'children': product_metrics,
            })
            conf['table_columns'].append({
                'title': p.name,
                'subcolumns': product_cols,
            })

        conf['detail_template'] = render_to_string(
            'reports/partials/commtrack/stockstatus_mapdetail.html', {
                'products':
                products,
                'columns': [{
                    'id': c,
                    'title': titles[c]
                } for c in ('category', 'current_stock', 'consumption',
                            'months_remaining')],
            })

        conf['display'] = {
            'table': False,
        }
        return conf
예제 #41
0
    def test_product_fixture(self):
        user = bootstrap_user(self, phone_number="1234567890")
        user_id = user.user_id
        products = ''
        product_list = Product.by_domain(user.domain)
        self._initialize_product_names(len(product_list))
        for i, product in enumerate(product_list):
            product_id = product._id
            product_name = self.product_names.next()
            product_unit = self._random_string(20)
            product_code = self._random_string(20)
            product_description = self._random_string(20)
            product_category = self._random_string(20)
            product_program_id = self._random_string(20)
            product_cost = 0 if i == 0 else float('%g' %
                                                  random.uniform(1, 100))

            # only set this on one product, so we can also test that
            # this node doesn't get sent down on every product
            if i == 0:
                product_data = {'special_number': '555111'}

                custom_data_xml = '''
                    <product_data>
                        <special_number>555111</special_number>
                    </product_data>
                '''
            else:
                product_data = {}
                custom_data_xml = ''

            products += '''
                <product id="{id}">
                    <name>{name}</name>
                    <unit>{unit}</unit>
                    <code>{code}</code>
                    <description>{description}</description>
                    <category>{category}</category>
                    <program_id>{program_id}</program_id>
                    <cost>{cost}</cost>
                    {custom_data}
                </product>
            '''.format(id=product_id,
                       name=product_name,
                       unit=product_unit,
                       code=product_code,
                       description=product_description,
                       category=product_category,
                       program_id=product_program_id,
                       cost=product_cost,
                       custom_data=custom_data_xml)

            product.name = product_name
            product.unit = product_unit
            product.code = product_code
            product.description = product_description
            product.category = product_category
            product.program_id = product_program_id
            product.cost = product_cost
            product.product_data = product_data
            product.save()
        fixture = product_fixture_generator(user, V1, None)

        self.assertXmlEqual(
            '''<fixture id="commtrack:products" user_id="{user_id}">
                                    <products>
                                        {products}
                                    </products>
                                </fixture>'''.format(user_id=user_id,
                                                     products=products),
            ElementTree.tostring(fixture[0]))
예제 #42
0
 def obj_get_list(self, request, **kwargs):
     return Product.by_domain(kwargs['domain'])
예제 #43
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,
                    }
예제 #44
0
 def products(self):
     prods = Product.by_domain(self.domain, wrap=False)
     return sorted(prods, key=lambda p: p['name'])
 def setUp(self):
     self.datapath = os.path.join(os.path.dirname(__file__), 'data')
     initial_bootstrap(TEST_DOMAIN)
     bootstrap_domain(TEST_DOMAIN)
     for product in Product.by_domain(TEST_DOMAIN):
         product.delete()
예제 #46
0
 def headers(self):
     headers = DataTablesHeader(*[DataTablesColumn('Quantity')])
     for product in Product.by_domain(self.config['domain']):
         headers.add_column(DataTablesColumn(product.name))
     return headers
예제 #47
0
    def generate_product_xml(self, user, randomize_data=True):
        products = ''
        product_list = Product.by_domain(user.domain)
        self._initialize_product_names(len(product_list))
        for i, product in enumerate(product_list):
            product_id = product._id
            product_name = self.product_names.next()
            product_unit = self._random_string(20)
            product_code = self._random_string(20)
            product_description = self._random_string(20)
            product_category = self._random_string(20)
            product_program_id = self._random_string(20)
            product_cost = 0 if i == 0 else float('%g' % random.uniform(1, 100))

            # only set this on one product, so we can also test that
            # this node doesn't get sent down on every product
            if i == 0:
                product_data = {
                    'special_number': '555111'
                }

                custom_data_xml = '''
                    <product_data>
                        <special_number>555111</special_number>
                    </product_data>
                '''
            else:
                product_data = {}
                custom_data_xml = ''

            products += '''
                <product id="{id}">
                    <name>{name}</name>
                    <unit>{unit}</unit>
                    <code>{code}</code>
                    <description>{description}</description>
                    <category>{category}</category>
                    <program_id>{program_id}</program_id>
                    <cost>{cost}</cost>
                    {custom_data}
                </product>
            '''.format(
                id=product_id,
                name=product_name,
                unit=product_unit,
                code=product_code,
                description=product_description,
                category=product_category,
                program_id=product_program_id,
                cost=product_cost,
                custom_data=custom_data_xml
            )

            product.name = product_name
            product.unit = product_unit
            product.code = product_code
            product.description = product_description
            product.category = product_category
            product.program_id = product_program_id
            product.cost = product_cost
            product.product_data = product_data
            product.save()

        return products
예제 #48
0
def charts(request, domain, template="commtrack/charts.html"):
    products = Product.by_domain(domain)
    prod_codes = [p.code for p in products]
    prod_codes.extend(range(20))

    from random import randint
    num_facilities = randint(44, 444)

    ### gen fake data
    def vals():
        tot = 0
        l = []
        for i in range(4):
            v = randint(0, num_facilities - tot)
            l.append(v)
            tot += v
        l.append(num_facilities - tot)
        return l

    statuses = [{
        "key": "stocked out",
        "color": "#e00707"
    }, {
        "key": "under stock",
        "color": "#ffb100"
    }, {
        "key": "adequate stock",
        "color": "#4ac925"
    }, {
        "key": "overstocked",
        "color": "#b536da"
    }, {
        "key": "unknown",
        "color": "#ABABAB"
    }]

    for s in statuses:
        s["values"] = []

    for i, p in enumerate(prod_codes):
        vs = vals()
        for j in range(5):
            statuses[j]["values"].append({"x": p, "y": vs[j]})

    # colors don't actually work correctly for pie charts
    resp_values = [
        {
            "label": "Submitted on Time",
            "color": "#4ac925",
            "value": randint(0, 40)
        },
        {
            "label": "Didn't respond",
            "color": "#ABABAB",
            "value": randint(0, 20)
        },
        {
            "label": "Submitted Late",
            "color": "#e00707",
            "value": randint(0, 8)
        },
    ]
    response_data = [{"key": "Current Late Report", "values": resp_values}]

    ctxt = {
        "domain": domain,
        "stock_data": statuses,
        "response_data": response_data,
    }
    return render(request, template, ctxt)