예제 #1
0
 def product_from_code(self, prod_code):
     """return the product doc referenced by prod_code"""
     prod_code = prod_code.lower()
     p = Product.get_by_code(self.domain.name, prod_code)
     if p is None:
         raise SMSError('invalid product code "%s"' % prod_code)
     return p
예제 #2
0
def sync_requisition_from_openlmis(domain, requisition_id, openlmis_endpoint):
    cases = []
    send_notification = False
    lmis_requisition_details = openlmis_endpoint.get_requisition_details(requisition_id)
    if lmis_requisition_details:
        rec_cases = [c for c in RequisitionCase.get_by_external_id(domain, str(lmis_requisition_details.id)) if c.type == const.REQUISITION_CASE_TYPE]

        if len(rec_cases) == 0:
            products = [product for product in lmis_requisition_details.products if product.skipped == False]
            for product in products:
                pdt = Product.get_by_code(domain, product.code.lower())
                if pdt:
                    case = lmis_requisition_details.to_requisition_case(pdt._id)
                    case.save()
                    if case.requisition_status == 'AUTHORIZED':
                        send_notification = True
                    cases.append(case)
        else:
            for case in rec_cases:
                before_status = case.requisition_status
                if apply_updates(case, lmis_requisition_details.to_dict(case.product_id)):
                    after_status = case.requisition_status
                    case.save()
                    if before_status in ['INITIATED', 'SUBMITTED'] and after_status == 'AUTHORIZED':
                        send_notification = True
                cases.append(case)
        return cases, send_notification
    else:
        return None, False
예제 #3
0
 def wrap_from_json(cls, obj, domain, location_id):
     product = Product.get_by_code(domain, obj['product'])
     obj['product'] = product._id
     obj['supply_point'] = location_id
     obj['external_id'] = obj['id']
     del obj['id']
     return cls(**obj)
예제 #4
0
파일: sms.py 프로젝트: tsinkala/commcare-hq
 def product_from_code(self, prod_code):
     """return the product doc referenced by prod_code"""
     prod_code = prod_code.lower()
     p = Product.get_by_code(self.domain.name, prod_code)
     if p is None:
         raise SMSError('invalid product code "%s"' % prod_code)
     return p
예제 #5
0
def submit_form(domain, parent, form_data, properties, existing, location_type, consumption):
    # don't save if there is nothing to save
    if no_changes_needed(domain, existing, properties, form_data, consumption):
        return {
            'id': existing._id,
            'message': 'no changes for %s %s' % (location_type, existing.name)
        }

    form_data.update(properties)

    form = make_form(domain, parent, form_data, existing)
    form.strict = False  # optimization hack to turn off strict validation
    if form.is_valid():
        loc = form.save()

        sp = SupplyPointCase.get_by_location(loc) if consumption else None

        if consumption and sp:
            for product_code, value in consumption:
                try:
                    amount = Decimal(value)

                    # only set it if there is a non-negative/non-null value
                    if amount and amount >= 0:
                        set_default_consumption_for_supply_point(
                            domain,
                            Product.get_by_code(domain, product_code)._id,
                            sp._id,
                            amount
                        )
                except (TypeError, InvalidOperation):
                    # should inform user, but failing hard due to non numbers
                    # being used on consumption is strange since the
                    # locations would be in a very inconsistent state
                    continue

        if existing:
            message = 'updated %s %s' % (location_type, loc.name)
        else:
            message = 'created %s %s' % (location_type, loc.name)

        return {
            'id': loc._id,
            'message': message
        }
    else:
        message = 'Form errors when submitting: '
        # TODO move this to LocationForm somehow
        forms = filter(None, [form, form.sub_forms.get(location_type)])
        for k, v in itertools.chain(*(f.errors.iteritems() for f in forms)):
            if k != '__all__':
                message += u'{0} {1}; {2}: {3}. '.format(
                    location_type, form_data.get('name', 'unknown'), k, v[0]
                )

        return {
            'id': None,
            'message': message
        }
예제 #6
0
def submit_form(domain, parent, form_data, properties, existing, location_type, consumption):
    # don't save if there is nothing to save
    if no_changes_needed(domain, existing, properties, form_data, consumption):
        return {
            'id': existing._id,
            'message': 'no changes for %s %s' % (location_type, existing.name)
        }

    form_data.update(properties)

    form = make_form(domain, parent, form_data, existing)
    form.strict = False  # optimization hack to turn off strict validation
    if form.is_valid():
        loc = form.save()

        sp = SupplyPointCase.get_by_location(loc) if consumption else None

        if consumption and sp:
            for product_code, value in consumption:
                try:
                    amount = Decimal(value)

                    # only set it if there is a non-negative/non-null value
                    if amount and amount >= 0:
                        set_default_consumption_for_supply_point(
                            domain,
                            Product.get_by_code(domain, product_code)._id,
                            sp._id,
                            amount
                        )
                except (TypeError, InvalidOperation):
                    # should inform user, but failing hard due to non numbers
                    # being used on consumption is strange since the
                    # locations would be in a very inconsistent state
                    continue

        if existing:
            message = 'updated %s %s' % (location_type, loc.name)
        else:
            message = 'created %s %s' % (location_type, loc.name)

        return {
            'id': loc._id,
            'message': message
        }
    else:
        message = 'Form errors when submitting: '
        # TODO move this to LocationForm somehow
        forms = filter(None, [form, form.sub_forms.get(location_type)])
        for k, v in itertools.chain(*(f.errors.iteritems() for f in forms)):
            if k != '__all__':
                message += u'{0} {1}; {2}: {3}. '.format(
                    location_type, form_data.get('name', 'unknown'), k, v[0]
                )

        return {
            'id': None,
            'message': message
        }
예제 #7
0
 def save(self):
     for field in self.fields:
         val = self.cleaned_data[field]
         set_default_consumption_for_product(
             self.domain,
             Product.get_by_code(
                 self.domain,
                 field.split('_')[1]
             )._id,
             val
         )
예제 #8
0
    def test_should_import_consumption(self):
        existing = make_loc('existingloc', type='state')
        sp = make_supply_point(self.loc.domain, existing)

        data = {'id': existing._id, 'name': 'existingloc', 'default_pp': 77}

        import_location(self.domain.name, 'state', data)

        self.assertEqual(
            get_default_consumption(
                self.domain.name,
                Product.get_by_code(self.domain.name, 'pp')._id,
                'state',
                sp._id,
            ), 77)
예제 #9
0
def submit_form(domain, parent, form_data, properties, existing, location_type, consumption):
    # don't save if there is nothing to save
    if no_changes_needed(domain, existing, properties, form_data, consumption):
        return {
            'id': existing._id,
            'message': 'no changes for %s %s' % (location_type, existing.name)
        }

    form_data.update(properties)

    form = make_form(domain, parent, form_data, existing)
    form.strict = False  # optimization hack to turn off strict validation
    if form.is_valid():
        loc = form.save()

        sp = SupplyPointCase.get_by_location(loc) if consumption else None

        if consumption and sp:
            for product_code, amount in consumption:
                set_default_consumption_for_supply_point(
                    domain,
                    Product.get_by_code(domain, product_code)._id,
                    sp._id,
                    amount
                )
        if existing:
            message = 'updated %s %s' % (location_type, loc.name)
        else:
            message = 'created %s %s' % (location_type, loc.name)

        return {
            'id': loc._id,
            'message': message
        }
    else:
        message = 'Form errors when submitting: '
        # TODO move this to LocationForm somehow
        forms = filter(None, [form, form.sub_forms.get(location_type)])
        for k, v in itertools.chain(*(f.errors.iteritems() for f in forms)):
            if k != '__all__':
                message += u'{0} {1}; {2}: {3}. '.format(
                    location_type, form_data.get('name', 'unknown'), k, v[0]
                )

        return {
            'id': None,
            'message': message
        }
예제 #10
0
def sync_ilsgateway_product(domain, ilsgateway_product):
    product = Product.get_by_code(domain, ilsgateway_product.sms_code)
    product_dict = {
        'domain': domain,
        'name': ilsgateway_product.name,
        'code': ilsgateway_product.sms_code,
        'unit': str(ilsgateway_product.units),
        'description': ilsgateway_product.description,
    }
    if product is None:
        product = Product(**product_dict)
        product.save()
    else:
        if apply_updates(product, product_dict):
            product.save()
    return product
예제 #11
0
def sync_ilsgateway_product(domain, ilsgateway_product):
    product = Product.get_by_code(domain, ilsgateway_product.sms_code)
    product_dict = {
        'domain': domain,
        'name': ilsgateway_product.name,
        'code': ilsgateway_product.sms_code,
        'unit': str(ilsgateway_product.units),
        'description': ilsgateway_product.description,
    }
    if product is None:
        product = Product(**product_dict)
        product.save()
    else:
        if apply_updates(product, product_dict):
            product.save()
    return product
예제 #12
0
def sync_requisition_from_openlmis(domain, requisition_id, openlmis_endpoint):
    cases = []
    send_notification = False
    lmis_requisition_details = openlmis_endpoint.get_requisition_details(requisition_id)
    if lmis_requisition_details:
        rec_cases = [c for c in RequisitionCase.get_by_external_id(domain, str(lmis_requisition_details.id)) if c.type == const.REQUISITION_CASE_TYPE]

        if len(rec_cases) == 0:
            products = [product for product in lmis_requisition_details.products if product.skipped == False]
            for product in products:
                pdt = Product.get_by_code(domain, product.code.lower())
                if pdt:
                    case = lmis_requisition_details.to_requisition_case(pdt._id)
                    case.save()
                    if case.requisition_status == 'AUTHORIZED':
                        send_notification = True
                    cases.append(case)
예제 #13
0
def get_stock_transaction(domain, endpoint):
    # Faking xform
    try:
        xform = XFormInstance.get(docid='ilsgateway-xform')
    except ResourceNotFound:
        xform = XFormInstance(_id='ilsgateway-xform')
        xform.save()

    for facility in FACILITIES:
        has_next = True
        next_url = ""

        while has_next:
            meta, stocktransactions = endpoint.get_stocktransactions(next_url_params=next_url,
                                                                     filters=(dict(supply_point=facility,
                                                                                   order_by='date')))
            for stocktransaction in stocktransactions:
                case = SupplyPointCase.view('hqcase/by_domain_external_id',
                                            key=[domain, str(stocktransaction.supply_point_id)],
                                            reduce=False,
                                            include_docs=True,
                                            limit=1).first()
                product = Product.get_by_code(domain, stocktransaction.product_code)
                try:
                    StockTransaction.objects.get(case_id=case._id,
                                                 product_id=product._id,
                                                 report__date=force_to_datetime(stocktransaction.date),
                                                 stock_on_hand=Decimal(stocktransaction.ending_balance),
                                                 type='stockonhand', report__domain=domain)
                except StockTransaction.DoesNotExist:
                    r = StockReport.objects.create(form_id=xform._id,
                                                   date=force_to_datetime(stocktransaction.date),
                                                   type='balance',
                                                   domain=domain)
                    StockTransaction.objects.create(report=r,
                                                    section_id='stock',
                                                    case_id=case._id,
                                                    product_id=product._id,
                                                    type='stockonhand',
                                                    stock_on_hand=Decimal(stocktransaction.ending_balance))
            if not meta.get('next', False):
                has_next = False
            else:
                next_url = meta['next'].split('?')[1]
    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))
    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.lower(), 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.lower())
        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))
예제 #16
0
def no_changes_needed(domain, existing, properties, form_data, consumption, sp=None):
    if not existing:
        return False
    for prop, val in properties.iteritems():
        if getattr(existing, prop[1], None) != val:
            return False
    for key, val in form_data.iteritems():
        if getattr(existing, key, None) != val:
            return False
    for product_code, val in consumption:
        product = Product.get_by_code(domain, product_code)
        if get_default_consumption(
            domain,
            product._id,
            existing.location_type,
            existing._id
        ) != val:
            return False

    return True
예제 #17
0
def no_changes_needed(domain, existing, properties, form_data, consumption, sp=None):
    if not existing:
        return False
    for prop, val in properties.iteritems():
        if getattr(existing, prop[1], None) != val:
            return False
    for key, val in form_data.iteritems():
        if getattr(existing, key, None) != val:
            return False
    for product_code, val in consumption:
        product = Product.get_by_code(domain, product_code)
        if get_default_consumption(
            domain,
            product._id,
            existing.location_type,
            existing._id
        ) != val:
            return False

    return True
예제 #18
0
    def test_should_import_consumption(self):
        existing = make_loc('existingloc', type='state')
        sp = make_supply_point(self.loc.domain, existing)

        data = {
            'id': existing._id,
            'name': 'existingloc',
            'default_pp': 77
        }

        import_location(self.domain.name, 'state', data)

        self.assertEqual(
            get_default_consumption(
                self.domain.name,
                Product.get_by_code(self.domain.name, 'pp')._id,
                'state',
                sp._id,
            ),
            77 / DAYS_IN_MONTH
        )
예제 #19
0
def get_product_stock(domain, endpoint, facilities):
    for facility in facilities:
        has_next = True
        next_url = ""
        while has_next:
            meta, product_stocks = endpoint.get_productstocks(next_url_params=next_url,
                                                              filters=dict(supply_point=facility))
            for product_stock in product_stocks:
                case = SupplyPointCase.view('hqcase/by_domain_external_id',
                                            key=[domain, str(product_stock.supply_point)],
                                            reduce=False,
                                            include_docs=True,
                                            limit=1).first()
                product = Product.get_by_code(domain, product_stock.product)
                try:
                    stock_state = StockState.objects.get(section_id='stock',
                                                         case_id=case._id,
                                                         product_id=product._id)
                except StockState.DoesNotExist:
                    stock_state = StockState(section_id='stock',
                                             case_id=case._id,
                                             product_id=product._id,
                                             stock_on_hand=product_stock.quantity or 0,
                                             last_modified_date=product_stock.last_modified,
                                             sql_product=SQLProduct.objects.get(product_id=product._id))

                if product_stock.auto_monthly_consumption:
                    stock_state.daily_consumption = product_stock.auto_monthly_consumption / DAYS_IN_MONTH
                elif product_stock.use_auto_consumption is False:
                    stock_state.daily_consumption = product_stock.manual_monthly_consumption / DAYS_IN_MONTH
                else:
                    stock_state.daily_consumption = None

                stock_state.save()

            if not meta.get('next', False):
                has_next = False
            else:
                next_url = meta['next'].split('?')[1]
예제 #20
0
def sync_requisition_from_openlmis(domain, requisition_id, openlmis_endpoint):
    cases = []
    send_notification = False
    lmis_requisition_details = openlmis_endpoint.get_requisition_details(requisition_id)
    rec_cases = [RequisitionCase.wrap(c._doc) for c in RequisitionCase.get_by_external_id(domain, lmis_requisition_details.id) if c.type == const.REQUISITION_CASE_TYPE]
    if rec_cases is None:
        for product in lmis_requisition_details.products:
            pdt = Product.get_by_code(domain, product.code)
            case = lmis_requisition_details.to_requisition_case(pdt._id)
            case.save()
            if case.requisition_status is 'AUTHORIZED':
                send_notification = True
            cases.append(case)
    else:
        for case in rec_cases:
            before_status = case.requisition_status
            if _apply_updates(case, lmis_requisition_details.to_requisition_case(case.product_id)):
                after_status = case.requisition_status
                case.save()
                if before_status in ['INITIATED', 'SUBMITTED'] and after_status is 'AUTHORIZED':
                    send_notification = True
            cases.append(case)
    return cases, send_notification
예제 #21
0
def get_product(domain, lmis_product):
    return Product.get_by_code(domain, lmis_product.code)