def get_supply_point(domain, site_code=None, loc=None): if loc is None: loc = Location.view('commtrack/locations_by_code', key=[domain, site_code.lower()], include_docs=True).first() if loc: case = SupplyPointCase.get_by_location(loc)
def handle(self, *args, **options): for retailer_location in Location.filter_by_type( "colalifezambia", "retailer"): retailer_case = SupplyPointCase.get_by_location(retailer_location) wholesaler_location = retailer_location.parent wholesaler_case = SupplyPointCase.get_by_location( wholesaler_location) retailer_case.wholesaler_case_id = wholesaler_case._id retailer_case.save()
def handle(self, *args, **options): for retailer_location in Location.filter_by_type( "colalifezambia", "retailer"): retailer_case = SupplyPointCase.get_by_location(retailer_location) wholesaler_location = retailer_location.parent wholesaler_case = SupplyPointCase.get_by_location( wholesaler_location ) retailer_case.wholesaler_case_id = wholesaler_case._id retailer_case.save()
def sync_ilsgateway_location(domain, endpoint, ilsgateway_location): location = Location.view('commtrack/locations_by_code', key=[domain, ilsgateway_location.code.lower()], include_docs=True).first() if not location: if ilsgateway_location.parent: loc_parent = SupplyPointCase.view('hqcase/by_domain_external_id', key=[domain, str(ilsgateway_location.parent)], reduce=False, include_docs=True).first() if not loc_parent: parent = endpoint.get_location(ilsgateway_location.parent) loc_parent = sync_ilsgateway_location(domain, endpoint, Loc.from_json(parent)) else: loc_parent = loc_parent.location location = Location(parent=loc_parent) else: location = Location() location.lineage = [] location.domain = domain location.name = ilsgateway_location.name if ilsgateway_location.groups: location.metadata = {'groups': ilsgateway_location.groups} if ilsgateway_location.latitude: location.latitude = float(ilsgateway_location.latitude) if ilsgateway_location.longitude: location.longitude = float(ilsgateway_location.longitude) location.location_type = ilsgateway_location.type location.site_code = ilsgateway_location.code location.external_id = str(ilsgateway_location.id) location.save() if not SupplyPointCase.get_by_location(location): SupplyPointCase.create_from_location(domain, location) else: location_dict = { 'name': ilsgateway_location.name, 'latitude': float(ilsgateway_location.latitude) if ilsgateway_location.latitude else None, 'longitude': float(ilsgateway_location.longitude) if ilsgateway_location.longitude else None, 'type': ilsgateway_location.type, 'site_code': ilsgateway_location.code.lower(), 'external_id': str(ilsgateway_location.id), } case = SupplyPointCase.get_by_location(location) if apply_updates(location, location_dict): location.save() if case: case.update_from_location(location) else: SupplyPointCase.create_from_location(domain, location) return location
def sync_ilsgateway_location(domain, endpoint, ilsgateway_location): location = Location.view('commtrack/locations_by_code', key=[domain, ilsgateway_location.code.lower()], include_docs=True).first() if not location: if ilsgateway_location.parent: loc_parent = SupplyPointCase.view('hqcase/by_domain_external_id', key=[domain, str(ilsgateway_location.parent)], reduce=False, include_docs=True).first() if not loc_parent: parent = endpoint.get_location(ilsgateway_location.parent) loc_parent = sync_ilsgateway_location(domain, endpoint, Loc.from_json(parent)) else: loc_parent = loc_parent.location location = Location(parent=loc_parent) else: location = Location() location.lineage = [] location.domain = domain location.name = ilsgateway_location.name if ilsgateway_location.groups: location.metadata = {'groups': ilsgateway_location.groups} if ilsgateway_location.latitude: location.latitude = float(ilsgateway_location.latitude) if ilsgateway_location.longitude: location.longitude = float(ilsgateway_location.longitude) location.location_type = ilsgateway_location.type location.site_code = ilsgateway_location.code location.external_id = str(ilsgateway_location.id) location.save() if not SupplyPointCase.get_by_location(location): SupplyPointCase.create_from_location(domain, location) else: location_dict = { 'name': ilsgateway_location.name, 'latitude': float(ilsgateway_location.latitude) if ilsgateway_location.latitude else None, 'longitude': float(ilsgateway_location.longitude) if ilsgateway_location.longitude else None, 'type': ilsgateway_location.type, 'site_code': ilsgateway_location.code.lower(), 'external_id': str(ilsgateway_location.id), } case = SupplyPointCase.get_by_location(location) if apply_updates(location, location_dict): location.save() if case: case.update_from_location(location) else: SupplyPointCase.create_from_location(domain, location)
def bootstrap_user( username=TEST_USER, domain=TEST_DOMAIN, phone_number=TEST_NUMBER, password=TEST_PASSWORD, backend=TEST_BACKEND, first_name='', last_name='', home_loc=None, user_data=None, ): from corehq.apps.commtrack.helpers import make_supply_point user_data = user_data or {} user = CommCareUser.create(domain, username, password, phone_numbers=[TEST_NUMBER], user_data=user_data, first_name=first_name, last_name=last_name) if not SupplyPointCase.get_by_location(home_loc): make_supply_point(domain, home_loc) home_loc.save() user.set_location(home_loc) user.save_verified_number(domain, phone_number, verified=True, backend_id=backend) return CommCareUser.wrap(user.to_json())
def handle(self, *args, **options): for location_type in ["wholesaler", "retailer"]: for location in Location.filter_by_type("colalifezambia", location_type): supply_point_case = SupplyPointCase.get_by_location(location) supply_point_case.location_type = location_type supply_point_case.save()
def bootstrap_user(username=TEST_USER, domain=TEST_DOMAIN, phone_number=TEST_NUMBER, password=TEST_PASSWORD, backend=TEST_BACKEND, first_name='', last_name='', home_loc=None, user_data=None, ): from corehq.apps.commtrack.helpers import make_supply_point user_data = user_data or {} user = CommCareUser.create( domain, username, password, phone_numbers=[TEST_NUMBER], user_data=user_data, first_name=first_name, last_name=last_name ) if not SupplyPointCase.get_by_location(home_loc): make_supply_point(domain, home_loc) home_loc.save() user.set_location(home_loc) user.save_verified_number(domain, phone_number, verified=True, backend_id=backend) return CommCareUser.wrap(user.to_json())
def bootstrap_user( setup, username=TEST_USER, domain=TEST_DOMAIN, phone_number=TEST_NUMBER, password=TEST_PASSWORD, backend=TEST_BACKEND, first_name='', last_name='', home_loc=None, user_data=None, ): user_data = user_data or {} user = CommTrackUser.create(domain, username, password, phone_numbers=[TEST_NUMBER], user_data=user_data, first_name=first_name, last_name=last_name) if home_loc == setup.loc.site_code: if not SupplyPointCase.get_by_location(setup.loc): make_supply_point(domain, setup.loc) user.add_location(setup.loc) user.save() user.save_verified_number(domain, phone_number, verified=True, backend_id=backend) return CommTrackUser.wrap(user.to_json())
def report_reminder_process_user(user, test=False): now = datetime.datetime.utcnow() date = now - datetime.timedelta(days=7) if not user.location or user.location.location_type.administrative: return sp = SupplyPointCase.get_by_location(user.location) if not sp: return transaction_exists = StockTransaction.objects.filter( case_id=sp._id, type="stockonhand", report__date__gte=date ).exists() if sp and not transaction_exists and user.get_verified_number(): message = REPORT_REMINDER % (user.name, user.location.name) verified_number = user.get_verified_number() if not test: send_sms_to_verified_number(verified_number, message) else: send_test_message(verified_number, message) if can_receive_email(user, verified_number): email = str(user.email) send_mail('REPORT REMINDER', message, '*****@*****.**', [email])
def stockout_process_user(user, test=False): if user_has_reporting_location(user): location = user.location supply_point = SupplyPointCase.get_by_location(location) if supply_point and user.get_verified_number(): products = [ SQLProduct.objects.get(product_id=state.product_id).name for state in StockState.objects.filter( case_id=supply_point._id, stock_on_hand=0, product_id__in=[product.product_id for product in location.sql_location.products] ) ] if products: if not test: send_sms_to_verified_number( user.get_verified_number(), STOCKOUT_REPORT % { 'name': user.name, 'facility': supply_point.name, 'date': datetime.datetime.utcnow().strftime('%b %d'), 'products': ", ".join(products) } ) else: send_test_message( user.get_verified_number(), STOCKOUT_REPORT % { 'name': user.name, 'facility': supply_point.name, 'date': datetime.datetime.utcnow().strftime('%b %d'), 'products': ", ".join(products) } )
def stockout_process_user(user, test=False): if user_has_reporting_location(user): location = user.location supply_point = SupplyPointCase.get_by_location(location) if supply_point and user.get_verified_number(): products = [ SQLProduct.objects.get(product_id=state.product_id).name for state in StockState.objects.filter( case_id=supply_point._id, stock_on_hand=0, product_id__in=[ product.product_id for product in location.sql_location.products ]) ] if products: if not test: send_sms_to_verified_number( user.get_verified_number(), STOCKOUT_REPORT % { 'name': user.name, 'facility': supply_point.name, 'date': datetime.datetime.utcnow().strftime('%b %d'), 'products': ", ".join(products) }) else: send_test_message( user.get_verified_number(), STOCKOUT_REPORT % { 'name': user.name, 'facility': supply_point.name, 'date': datetime.datetime.utcnow().strftime('%b %d'), 'products': ", ".join(products) })
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 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 get_supply_point(domain, site_code=None, loc=None): if loc is None: loc = Location.view("commtrack/locations_by_code", key=[domain, site_code.lower()], include_docs=True).first() if loc: case = SupplyPointCase.get_by_location(loc) else: case = None return {"case": case, "location": loc}
def send_soh_reminder(domain, date): sp_ids = set() for user in CommTrackUser.by_domain(domain): if user.is_active and user.location and user.location.location_type == 'FACILITY': sp = SupplyPointCase.get_by_location(user.location) if sp and not StockTransaction.objects.filter(case_id=sp._id, report__date__gte=date, type='stockonhand').exists(): if user.get_verified_number(): send_sms_to_verified_number(user.get_verified_number(), REMINDER_STOCKONHAND) sp_ids.add(sp._id) update_statuses(sp_ids, SupplyPointStatusTypes.SOH_FACILITY, SupplyPointStatusValues.REMINDER_SENT)
def send_soh_reminder(domain, date): sp_ids = set() for user in CommTrackUser.by_domain(domain): if user.is_active and user.location and user.location.location_type == 'FACILITY': sp = SupplyPointCase.get_by_location(user.location) if sp and not StockTransaction.objects.filter(case_id=sp._id, report__date__gte=date, type='stockonhand').exists(): if user.get_verified_number(): send_sms_to_verified_number(user.get_verified_number(), REMINDER_STOCKONHAND) sp_ids.add(sp._id) update_statuses(sp_ids, SupplyPointStatusTypes.SOH_FACILITY, SupplyPointStatusValues.REMINDER_SENT)
def send_soh_reminder(domain, date, test_list=None): sp_ids = set() users = CommCareUser.by_domain(domain) if not test_list else test_list for user in users: if user.is_active and user.location and user.location.location_type == 'FACILITY': sp = SupplyPointCase.get_by_location(user.location) if sp and not StockTransaction.objects.filter(case_id=sp._id, report__date__gte=date, type='stockonhand').exists(): result = send_translated_message(user, REMINDER_STOCKONHAND) if not test_list and result: sp_ids.add(sp._id) update_statuses(sp_ids, SupplyPointStatusTypes.SOH_FACILITY, SupplyPointStatusValues.REMINDER_SENT)
def send_supervision_reminder(domain, date): sp_ids = set() for user in CommTrackUser.by_domain(domain): if user.is_active and user.location and user.location.location_type == 'FACILITY': sp = SupplyPointCase.get_by_location(user.location) if sp and not SupplyPointStatus.objects.filter(supply_point=sp._id, status_type=SupplyPointStatusTypes.SUPERVISION_FACILITY, status_date__gte=date).exists(): if user.get_verified_number(): send_sms_to_verified_number(user.get_verified_number(), REMINDER_SUPERVISION) sp_ids.add(sp._id) update_statuses(sp_ids, SupplyPointStatusTypes.SUPERVISION_FACILITY, SupplyPointStatusValues.REMINDER_SENT)
def _create_supply_point_from_location(self, supply_point, location): if not SupplyPointCase.get_by_location(location): if supply_point.supervised_by: location.metadata['supervised_by'] = supply_point.supervised_by location.save() sql_loc = location.sql_location sql_loc.products = SQLProduct.objects.filter(domain=self.domain, code__in=supply_point.products) sql_loc.save() return SupplyPointCase.get_or_create_by_location(Loc(_id=location._id, name=supply_point.name, external_id=str(supply_point.id), domain=self.domain))
def save(self, user): commtrack_user = CommTrackUser.wrap(user.to_json()) location_id = self.cleaned_data['supply_point'] if location_id: loc = Location.get(location_id) commtrack_user.clear_locations() commtrack_user.add_location(loc, create_sp_if_missing=True) # add the supply point case id to user data fields # so that the phone can auto select supply_point = SupplyPointCase.get_by_location(loc) user.user_data['commtrack-supply-point'] = supply_point._id
def save(self, user): commtrack_user = CommTrackUser.wrap(user.to_json()) location_id = self.cleaned_data['supply_point'] if location_id: loc = Location.get(location_id) commtrack_user.clear_locations() commtrack_user.add_location(loc, create_sp_if_missing=True) # add the supply point case id to user data fields # so that the phone can auto select supply_point = SupplyPointCase.get_by_location(loc) user.user_data['commtrack-supply-point'] = supply_point._id
def _create_supply_point_from_location(self, supply_point, location): if not SupplyPointCase.get_by_location(location): if supply_point.supervised_by: location.metadata['supervised_by'] = supply_point.supervised_by location.save() sql_loc = location.sql_location sql_loc.products = SQLProduct.objects.filter( domain=self.domain, code__in=supply_point.products) sql_loc.save() return SupplyPointCase.get_or_create_by_location( Loc(_id=location._id, name=supply_point.name, external_id=str(supply_point.id), domain=self.domain))
def send_soh_reminder(domain, date, test_list=None): sp_ids = set() users = CommCareUser.by_domain(domain) if not test_list else test_list for user in users: if user.is_active and user.location and user.location.location_type == 'FACILITY': sp = SupplyPointCase.get_by_location(user.location) if sp and not StockTransaction.objects.filter( case_id=sp._id, report__date__gte=date, type='stockonhand').exists(): result = send_translated_message(user, REMINDER_STOCKONHAND) if not test_list and result: sp_ids.add(sp._id) update_statuses(sp_ids, SupplyPointStatusTypes.SOH_FACILITY, SupplyPointStatusValues.REMINDER_SENT)
def send_supervision_reminder(domain, date): sp_ids = set() for user in CommTrackUser.by_domain(domain): if user.is_active and user.location and user.location.location_type == 'FACILITY': sp = SupplyPointCase.get_by_location(user.location) if sp and not SupplyPointStatus.objects.filter( supply_point=sp._id, status_type=SupplyPointStatusTypes.SUPERVISION_FACILITY, status_date__gte=date).exists(): if user.get_verified_number(): send_sms_to_verified_number(user.get_verified_number(), REMINDER_SUPERVISION) sp_ids.add(sp._id) update_statuses(sp_ids, SupplyPointStatusTypes.SUPERVISION_FACILITY, SupplyPointStatusValues.REMINDER_SENT)
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 second_soh_process_user(user, test=False): now = datetime.datetime.utcnow() date = now - datetime.timedelta(days=DAYS_UNTIL_LATE) supply_point = SupplyPointCase.get_by_location(user.location) if not supply_point: return stock_states = StockState.objects.filter( case_id=supply_point._id, last_modified_date__gte=date ) products = user.sql_location.products location_products_ids = [product.product_id for product in products] reported_products_ids = [stock_state.product_id for stock_state in stock_states] missing_products_ids = set(location_products_ids) - set(reported_products_ids) if not user_has_reporting_location(user) or not user.get_verified_number(): return if not stock_states: if not test: send_sms_to_verified_number( user.get_verified_number(), SECOND_STOCK_ON_HAND_REMINDER % {'name': user.name} ) else: send_test_message( user.get_verified_number(), SECOND_STOCK_ON_HAND_REMINDER % {'name': user.name} ) elif missing_products_ids: products_names = [ product.name for product in products if product.product_id in missing_products_ids ] if not test: send_sms_to_verified_number( user.get_verified_number(), SECOND_INCOMPLETE_SOH_REMINDER % {'name': user.name, 'products': ", ".join(products_names)} ) else: send_test_message( user.get_verified_number(), SECOND_INCOMPLETE_SOH_REMINDER % {'name': user.name, 'products': ", ".join(products_names)} )
def second_soh_process_user(user, test=False): now = datetime.datetime.utcnow() date = now - datetime.timedelta(days=DAYS_UNTIL_LATE) supply_point = SupplyPointCase.get_by_location(user.location) if not supply_point: return stock_states = StockState.objects.filter(case_id=supply_point._id, last_modified_date__gte=date) products = user.sql_location.products location_products_ids = [product.product_id for product in products] reported_products_ids = [ stock_state.product_id for stock_state in stock_states ] missing_products_ids = set(location_products_ids) - set( reported_products_ids) if not user_has_reporting_location(user) or not user.get_verified_number(): return if not stock_states: if not test: send_sms_to_verified_number( user.get_verified_number(), SECOND_STOCK_ON_HAND_REMINDER % {'name': user.name}) else: send_test_message( user.get_verified_number(), SECOND_STOCK_ON_HAND_REMINDER % {'name': user.name}) elif missing_products_ids: products_names = [ product.name for product in products if product.product_id in missing_products_ids ] if not test: send_sms_to_verified_number( user.get_verified_number(), SECOND_INCOMPLETE_SOH_REMINDER % { 'name': user.name, 'products': ", ".join(products_names) }) else: send_test_message( user.get_verified_number(), SECOND_INCOMPLETE_SOH_REMINDER % { 'name': user.name, 'products': ", ".join(products_names) })
def report_reminder(): sp_ids = set() now = datetime.datetime.utcnow() date = now - datetime.timedelta(days=7) domains = EWSGhanaConfig.get_all_enabled_domains() for domain in domains: for user in CommCareUser.by_domain(domain): if user.location: sp = SupplyPointCase.get_by_location(user.location) if sp and not StockTransaction.objects.filter( case_id=sp._id, type="stockonhand", report__date__gte=date).exists()\ and user.get_verified_number(): sp_ids.add(sp._id) message = REPORT_REMINDER % (user.name, user.location.name) send_sms_to_verified_number(user.get_verified_number(), message) if user.email: email = str(user.email) send_mail('REPORT REMINDER', message, '*****@*****.**', [email])
def get_message_for_location(self, location): supply_point = SupplyPointCase.get_by_location(location) if not supply_point: return on_time_products, missing_products = report_status(location.sql_location, days_until_late=DAYS_UNTIL_LATE) if not on_time_products: return SECOND_STOCK_ON_HAND_REMINDER, {} elif missing_products: products_names = ', '.join([ product.name for product in missing_products ]) return SECOND_INCOMPLETE_SOH_REMINDER, {'products': products_names} return None, {}
def first_soh_process_user(user, test=False): if user_has_reporting_location(user) and user_has_role(user, IN_CHARGE_ROLE): supply_point = SupplyPointCase.get_by_location(user.location) transaction_exists = StockTransaction.objects.filter( case_id=supply_point._id, type='stockonhand' ).exists() if supply_point and not transaction_exists and user.get_verified_number(): message = STOCK_ON_HAND_REMINDER % {'name': user.name} if not test: send_sms_to_verified_number( user.get_verified_number(), message ) else: send_test_message( user.get_verified_number(), message )
def send_ror_reminder(domain, date, loc_type='FACILITY'): if loc_type == 'FACILITY': status_type = SupplyPointStatusTypes.R_AND_R_FACILITY sms_text = REMINDER_R_AND_R_FACILITY elif loc_type == 'DISTRICT': status_type = SupplyPointStatusTypes.R_AND_R_DISTRICT sms_text = REMINDER_R_AND_R_DISTRICT else: return current_group = get_current_group() sp_ids = set() for user in CommTrackUser.by_domain(domain): if user.is_active and user.location and user.location.location_type == loc_type: sp = SupplyPointCase.get_by_location(user.location) if current_group in get_groups(sp.location.metadata.get('groups', None)) \ and not SupplyPointStatus.objects.filter(supply_point=sp._id, status_type=status_type, status_date__gte=date).exists(): if user.get_verified_number(): send_sms_to_verified_number(user.get_verified_number(), sms_text) sp_ids.add(sp._id) update_statuses(sp_ids, status_type, SupplyPointStatusValues.REMINDER_SENT)
def send_ror_reminder(domain, date, loc_type='FACILITY'): if loc_type == 'FACILITY': status_type = SupplyPointStatusTypes.R_AND_R_FACILITY sms_text = REMINDER_R_AND_R_FACILITY elif loc_type == 'DISTRICT': status_type = SupplyPointStatusTypes.R_AND_R_DISTRICT sms_text = REMINDER_R_AND_R_DISTRICT else: return current_group = DeliveryGroups().current_submitting_group(date.month) sp_ids = set() for user in CommTrackUser.by_domain(domain): if user.is_active and user.location and user.location.location_type == loc_type: sp = SupplyPointCase.get_by_location(user.location) if current_group in get_groups(sp.location.metadata.get('groups', None)) \ and not SupplyPointStatus.objects.filter(supply_point=sp._id, status_type=status_type, status_date__gte=date).exists(): if user.get_verified_number(): send_sms_to_verified_number(user.get_verified_number(), sms_text) sp_ids.add(sp._id) update_statuses(sp_ids, status_type, SupplyPointStatusValues.REMINDER_SENT)
def second_soh_process_user(user, date, test=False): supply_point = SupplyPointCase.get_by_location(user.location) if not supply_point: return stock_states = StockState.objects.filter( case_id=supply_point._id, last_modified_date__gte=date ) location_products = [product.product_id for product in user.location.sql_location.products] reported_products = [stock_state.product_id for stock_state in stock_states] missing_products = set(location_products) - set(reported_products) if user_has_reporting_location(user) and user_has_role(user, IN_CHARGE_ROLE): if user.get_verified_number(): if not stock_states: if not test: send_sms_to_verified_number( user.get_verified_number(), SECOND_STOCK_ON_HAND_REMINDER % {'name': user.name} ) else: send_test_message( user.get_verified_number(), SECOND_STOCK_ON_HAND_REMINDER % {'name': user.name} ) elif missing_products: if not test: send_sms_to_verified_number( user.get_verified_number(), SECOND_INCOMPLETE_SOH_REMINDER % {'name': user.name, 'products': ", ".join(missing_products)} ) else: send_test_message( user.get_verified_number(), SECOND_INCOMPLETE_SOH_REMINDER % {'name': user.name, 'products': ", ".join(missing_products)} )
def stock_alerts(transactions, user): products_without_receipts = set() products_above = set() products_below = set() sp = SupplyPointCase.get_by_location(user.location) for i in range(0, len(transactions), 2): if StockState.objects.filter(case_id=sp._id, product_id=transactions[i + 1].product_id).exists(): receipt = int(transactions[i].quantity) stock = int(transactions[i + 1].quantity) product = SQLProduct.objects.get(product_id=transactions[i].product_id).name last_stock = StockState.objects.get( case_id=sp._id, product_id=transactions[i].product_id).stock_on_hand stock_levels_config = CommtrackConfig.for_domain(user.domain).stock_levels_config over_stock_threshold = stock_levels_config.overstock_threshold under_stock_threshold = stock_levels_config.understock_threshold if stock > over_stock_threshold: products_above.add(product) elif stock < under_stock_threshold: products_below.add(product) if stock > last_stock and receipt == 0: products_without_receipts.add(product) if products_below: message = BELOW_REORDER_LEVELS % (user.name, user.location, ", ".join(sorted([str(prod) for prod in products_below]))) send_sms_to_verified_number(user.get_verified_number(), message) elif products_above: message = ABOVE_THRESHOLD % ( user.name, ", ".join(sorted([str(prod) for prod in products_above]))) send_sms_to_verified_number(user.get_verified_number(), message) elif products_without_receipts: message = WITHOUT_RECEIPTS % ( ', '.join(sorted([str(prod) for prod in products_without_receipts]))) send_sms_to_verified_number(user.get_verified_number(), message) else: return False
def bootstrap_user(setup, username=TEST_USER, domain=TEST_DOMAIN, phone_number=TEST_NUMBER, password=TEST_PASSWORD, backend=TEST_BACKEND, first_name='', last_name='', home_loc=None, user_data=None, ): user_data = user_data or {} user = CommCareUser.create( domain, username, password, phone_numbers=[TEST_NUMBER], user_data=user_data, first_name=first_name, last_name=last_name ) if home_loc == setup.loc.site_code: if not SupplyPointCase.get_by_location(setup.loc): make_supply_point(domain, setup.loc) user.set_location(setup.loc) user.save_verified_number(domain, phone_number, verified=True, backend_id=backend) return CommCareUser.wrap(user.to_json())
def report_reminder_process_user(user, test=False): now = datetime.datetime.utcnow() date = now - datetime.timedelta(days=7) if not user.location or user.location.location_type.administrative: return sp = SupplyPointCase.get_by_location(user.location) if not sp: return transaction_exists = StockTransaction.objects.filter( case_id=sp._id, type="stockonhand", report__date__gte=date).exists() if sp and not transaction_exists and user.get_verified_number(): message = REPORT_REMINDER % (user.name, user.location.name) verified_number = user.get_verified_number() if not test: send_sms_to_verified_number(verified_number, message) else: send_test_message(verified_number, message) if can_receive_email(user, verified_number): email = str(user.email) send_mail('REPORT REMINDER', message, '*****@*****.**', [email])
def linked_supply_point(self): from corehq.apps.commtrack.models import SupplyPointCase return SupplyPointCase.get_by_location(self)
def _create_supply_point_from_location(self, supply_point, location): if not SupplyPointCase.get_by_location(location): return SupplyPointCase.get_or_create_by_location(Loc(_id=location.get_id, name=supply_point.name, external_id=str(supply_point.id), domain=self.domain))
def location_sync(self, ilsgateway_location): def get_or_create_msd_zone(region): msd_name = _get_msd_name(region.name) msd_code = MSDZONE_MAP[msd_name][0] try: sql_msd_loc = SQLLocation.objects.get(domain=self.domain, site_code=msd_code) msd_location = Loc.get(sql_msd_loc.location_id) except SQLLocation.DoesNotExist: msd_location = Loc(parent=loc_parent) msd_location.domain = self.domain msd_location.name = msd_name msd_location.location_type = 'MSDZONE' msd_location.site_code = MSDZONE_MAP[msd_name][0] msd_location.save() return msd_location try: sql_loc = SQLLocation.objects.get(domain=self.domain, external_id=int( ilsgateway_location.id)) location = Loc.get(sql_loc.location_id) except SQLLocation.DoesNotExist: location = None except SQLLocation.MultipleObjectsReturned: return if not location: if ilsgateway_location.id in EXCLUDED_REGIONS: return if ilsgateway_location.parent_id: try: sql_loc_parent = SQLLocation.objects.get( domain=self.domain, external_id=ilsgateway_location.parent_id) loc_parent = sql_loc_parent.couch_location except SQLLocation.DoesNotExist: parent = self.endpoint.get_location( ilsgateway_location.parent_id) loc_parent = self.location_sync(Location(parent)) if not loc_parent: return if ilsgateway_location.type == 'REGION': location = Loc( parent=get_or_create_msd_zone(ilsgateway_location)) else: location = Loc(parent=loc_parent) else: location = Loc() location.lineage = [] location.domain = self.domain location.name = ilsgateway_location.name if ilsgateway_location.groups: location.metadata = {'group': ilsgateway_location.groups[0]} if ilsgateway_location.latitude: location.latitude = float(ilsgateway_location.latitude) if ilsgateway_location.longitude: location.longitude = float(ilsgateway_location.longitude) location.location_type = ilsgateway_location.type location.site_code = ilsgateway_location.code location.external_id = unicode(ilsgateway_location.id) location.save() if ilsgateway_location.type == 'FACILITY' and not SupplyPointCase.get_by_location( location): SupplyPointCase.create_from_location(self.domain, location) location.save() else: location_dict = { 'name': ilsgateway_location.name, 'latitude': float(ilsgateway_location.latitude) if ilsgateway_location.latitude else None, 'longitude': float(ilsgateway_location.longitude) if ilsgateway_location.longitude else None, 'location_type': ilsgateway_location.type, 'site_code': ilsgateway_location.code.lower(), 'external_id': str(ilsgateway_location.id), 'metadata': {} } if ilsgateway_location.groups: location_dict['metadata'][ 'group'] = ilsgateway_location.groups[0] case = SupplyPointCase.get_by_location(location) if apply_updates(location, location_dict): location.save() if case: case.update_from_location(location) else: SupplyPointCase.create_from_location(self.domain, location)
def set_commtrack_location(user, location): user.commtrack_location = location._id supply_point_case = SupplyPointCase.get_by_location(location) reconcile_ownership(supply_point_case, user) user.save()
def handle(self, *args, **options): for location_type in ["wholesaler", "retailer"]: for location in Location.filter_by_type("colalifezambia", location_type): supply_point_case = SupplyPointCase.get_by_location(location) supply_point_case.location_type = location_type supply_point_case.save()
def linked_supply_point(self): from corehq.apps.commtrack.models import SupplyPointCase return SupplyPointCase.get_by_location(self)
def submit_form(self, parent, form_data, existing, location_type, consumption): location = existing or Location(domain=self.domain, parent=parent) form = LocationForm(location, form_data) form.strict = False # optimization hack to turn off strict validation if form.is_valid(): # don't save if there is nothing to save if self.no_changes_needed(existing, form_data, consumption): return { 'id': existing._id, 'message': 'no changes for %s %s' % (location_type, existing.name) } loc = form.save() sp = SupplyPointCase.get_by_location(loc) if consumption else None if consumption and sp: for product_code, value in consumption: product = self.get_product(product_code) if not product: # skip any consumption column that doesn't match # to a real product. currently there is no easy # way to alert here, though. continue 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( self.domain, product._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: ' for k, v in form.errors.iteritems(): 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 location_sync(self, ilsgateway_location): def get_or_create_msd_zone(region): msd_name = _get_msd_name(region.name) msd_code = MSDZONE_MAP[msd_name][0] try: sql_msd_loc = SQLLocation.objects.get(domain=self.domain, site_code=msd_code) msd_location = Loc.get(sql_msd_loc.location_id) except SQLLocation.DoesNotExist: msd_location = Loc(parent=loc_parent) msd_location.domain = self.domain msd_location.name = msd_name msd_location.location_type = "MSDZONE" msd_location.site_code = MSDZONE_MAP[msd_name][0] msd_location.save() return msd_location try: sql_loc = SQLLocation.objects.get(domain=self.domain, external_id=int(ilsgateway_location.id)) location = Loc.get(sql_loc.location_id) except SQLLocation.DoesNotExist: location = None except SQLLocation.MultipleObjectsReturned: return if not location: if ilsgateway_location.id in EXCLUDED_REGIONS: return if ilsgateway_location.parent_id: try: sql_loc_parent = SQLLocation.objects.get( domain=self.domain, external_id=ilsgateway_location.parent_id ) loc_parent = sql_loc_parent.couch_location except SQLLocation.DoesNotExist: parent = self.endpoint.get_location(ilsgateway_location.parent_id) loc_parent = self.location_sync(Location(parent)) if not loc_parent: return if ilsgateway_location.type == "REGION": location = Loc(parent=get_or_create_msd_zone(ilsgateway_location)) else: location = Loc(parent=loc_parent) else: location = Loc() location.lineage = [] location.domain = self.domain location.name = ilsgateway_location.name if ilsgateway_location.groups: location.metadata = {"group": ilsgateway_location.groups[0]} if ilsgateway_location.latitude: location.latitude = float(ilsgateway_location.latitude) if ilsgateway_location.longitude: location.longitude = float(ilsgateway_location.longitude) location.location_type = ilsgateway_location.type location.site_code = ilsgateway_location.code location.external_id = unicode(ilsgateway_location.id) location.save() if ilsgateway_location.type == "FACILITY" and not SupplyPointCase.get_by_location(location): SupplyPointCase.create_from_location(self.domain, location) location.save() else: location_dict = { "name": ilsgateway_location.name, "latitude": float(ilsgateway_location.latitude) if ilsgateway_location.latitude else None, "longitude": float(ilsgateway_location.longitude) if ilsgateway_location.longitude else None, "location_type": ilsgateway_location.type, "site_code": ilsgateway_location.code.lower(), "external_id": str(ilsgateway_location.id), "metadata": {}, } if ilsgateway_location.groups: location_dict["metadata"]["group"] = ilsgateway_location.groups[0] case = SupplyPointCase.get_by_location(location) if apply_updates(location, location_dict): location.save() if case: case.update_from_location(location) else: SupplyPointCase.create_from_location(self.domain, location) return location
def supply_point(self): return SupplyPointCase.get_by_location(self.location)
def supply_point(self): try: return SupplyPointCase.get_by_location(self.location) except MultipleResultsFound: raise MultipleSupplyPointException
def location_sync(self, ilsgateway_location): def get_or_create_msd_zone(region): msd_name = _get_msd_name(region.name) msd_code = MSDZONE_MAP[msd_name][0] try: sql_msd_loc = SQLLocation.objects.get( domain=self.domain, site_code=msd_code ) msd_location = Loc.get(sql_msd_loc.location_id) except SQLLocation.DoesNotExist: msd_location = Loc(parent=loc_parent) msd_location.domain = self.domain msd_location.name = msd_name msd_location.location_type = 'MSDZONE' msd_location.site_code = MSDZONE_MAP[msd_name][0] msd_location.save() return msd_location try: sql_loc = SQLLocation.objects.get( domain=self.domain, external_id=int(ilsgateway_location.id) ) location = Loc.get(sql_loc.location_id) except SQLLocation.DoesNotExist: location = None except SQLLocation.MultipleObjectsReturned: return if not location: if ilsgateway_location.parent_id: try: sql_loc_parent = SQLLocation.objects.get( domain=self.domain, external_id=ilsgateway_location.parent_id ) loc_parent = sql_loc_parent.couch_location except SQLLocation.DoesNotExist: parent = self.endpoint.get_location(ilsgateway_location.parent_id) loc_parent = self.location_sync(Location(parent)) if ilsgateway_location.type == 'REGION': location = Loc(parent=get_or_create_msd_zone(ilsgateway_location)) else: location = Loc(parent=loc_parent) else: location = Loc() location.lineage = [] location.domain = self.domain location.name = ilsgateway_location.name if ilsgateway_location.groups: location.metadata = {'group': ilsgateway_location.groups[0]} if ilsgateway_location.latitude: location.latitude = float(ilsgateway_location.latitude) if ilsgateway_location.longitude: location.longitude = float(ilsgateway_location.longitude) location.location_type = ilsgateway_location.type location.site_code = ilsgateway_location.code location.external_id = unicode(ilsgateway_location.id) location.save() if ilsgateway_location.type == 'FACILITY' and not SupplyPointCase.get_by_location(location): SupplyPointCase.create_from_location(self.domain, location) location.save() else: location_dict = { 'name': ilsgateway_location.name, 'latitude': float(ilsgateway_location.latitude) if ilsgateway_location.latitude else None, 'longitude': float(ilsgateway_location.longitude) if ilsgateway_location.longitude else None, 'location_type': ilsgateway_location.type, 'site_code': ilsgateway_location.code.lower(), 'external_id': str(ilsgateway_location.id), 'metadata': {} } if ilsgateway_location.groups: location_dict['metadata']['group'] = ilsgateway_location.groups[0] case = SupplyPointCase.get_by_location(location) if apply_updates(location, location_dict): location.save() if case: case.update_from_location(location) else: SupplyPointCase.create_from_location(self.domain, location) return location
def supply_point(self): return SupplyPointCase.get_by_location(self.location)