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
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
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)
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 }
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 )
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)
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 }
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
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)
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))
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
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 )
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]
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
def get_product(domain, lmis_product): return Product.get_by_code(domain, lmis_product.code)