def changes(request): hubApi = HubApiClient( api_url=request.session["user_tokens"]["HUB"]["url"], auth_token=request.session["user_tokens"]["HUB"]["token"]) if 'mother_id' in request.GET: form = ChangeFilterForm(request.GET) if form.is_valid(): change_filter = { "action": form.cleaned_data['action'], "validated": form.cleaned_data['validated'], settings.IDENTITY_FIELD: form.cleaned_data['mother_id'] } changes = hubApi.get_changes(params=change_filter)['results'] else: changes = [] else: form = ChangeFilterForm() changes = hubApi.get_changes()['results'] changes = utils.get_page_of_iterator(changes, settings.CHANGE_LIST_PAGE_SIZE, request.GET.get('page')) context = {"changes": changes, "form": form} return render(request, 'ci/changes.html', context)
def registrations(request): context = {} hubApi = HubApiClient( api_url=request.session["user_tokens"]["HUB"]["url"], # noqa auth_token=request.session["user_tokens"]["HUB"]["token"] # noqa ) if 'mother_id' in request.GET: form = RegistrationFilterForm(request.GET) if form.is_valid(): reg_filter = { settings.STAGE_FIELD: form.cleaned_data['stage'], "validated": form.cleaned_data['validated'], settings.IDENTITY_FIELD: form.cleaned_data['mother_id'] } registrations = hubApi.get_registrations( params=reg_filter)['results'] else: registrations = [] else: form = RegistrationFilterForm() registrations = hubApi.get_registrations()['results'] context['form'] = form context['registrations'] = utils.get_page_of_iterator( registrations, settings.REGISTRATION_LIST_PAGE_SIZE, request.GET.get('page')) return render(request, 'ci/registrations.html', context)
def handle(self, *args, **options): hub_url = options['hub_url'] hub_token = options['hub_token'] id_url = options['identity_url'] id_token = options['identity_token'] hub_id_field = options['hub_identity_field'] if not hub_url or not hub_token: self.warning("hub-url and hub-token is required.") return hubApi = HubApiClient(hub_token, hub_url) idApi = IdentityStoreApiClient(id_token, id_url) subscriptions = Subscription.objects.filter(process_status=5) reg_count = 0 id_count = 0 for subscription in subscriptions.iterator(): identity = subscription.identity # find and update linked registrations registrations = hubApi.get_registrations({hub_id_field: identity}) for registration in registrations['results']: if not registration['data'].get('exclude_report', False): registration['data']['exclude_report'] = True try: hubApi.update_registration( registration['id'], {'data': registration['data']}) reg_count += 1 except exceptions.ConnectionError as exc: self.warning( 'Connection error to Hub API: {}'.format(exc)) except HTTPServiceError as exc: self.warning('Invalid Hub API response({}): {}'.format( exc.response.status_code, exc.response.url)) # find and update linked identities identity = idApi.get_identity(identity) if not identity['details'].get('exclude_report', False): identity['details']['exclude_report'] = True try: idApi.update_identity(identity['id'], {'details': identity['details']}) id_count += 1 except exceptions.ConnectionError as exc: self.warning( 'Connection error to Identity API: {}'.format(exc)) except HTTPServiceError as exc: self.warning( 'Invalid Identity Store API response({}): {}'.format( exc.response.status_code, exc.response.url)) self.success('Updated %s identities and %s registrations.' % (id_count, reg_count))
def change(request, change): hubApi = HubApiClient( api_url=request.session["user_tokens"]["HUB"]["url"], auth_token=request.session["user_tokens"]["HUB"]["token"]) if request.method == "POST": pass else: results = hubApi.get_change(change) if results is None: return redirect('not_found') context = {"change": results} context.update(csrf(request)) return render(request, 'ci/changes_detail.html', context)
def registration(request, registration): hubApi = HubApiClient( api_url=request.session["user_tokens"]["HUB"]["url"], # noqa auth_token=request.session["user_tokens"]["HUB"]["token"] # noqa ) if request.method == "POST": pass else: results = hubApi.get_registration(registration) if results is None: return redirect('not_found') context = {"registration": results} context.update(csrf(request)) return render(request, 'ci/registrations_detail.html', context)
def report_generation(request): hubApi = HubApiClient(request.session["user_tokens"]["HUB"]["token"], api_url=request.session["user_tokens"]["HUB"]["url"]) if request.method == "POST": report_type = request.POST['report_type'] if report_type == 'registration': reg_form = ReportGenerationForm(request.POST, auto_id='registration_%s') posted_form = reg_form msisdn_form = MsisdnReportGenerationForm(auto_id='cohort_%s') elif report_type == 'cohort': msisdn_form = MsisdnReportGenerationForm(request.POST, request.FILES, auto_id='cohort_%s') posted_form = msisdn_form reg_form = ReportGenerationForm(auto_id='registration_%s') if posted_form.is_valid(): # Remove fields that weren't supplied if posted_form.cleaned_data.get('start_date') is None: del posted_form.cleaned_data['start_date'] if posted_form.cleaned_data.get('end_date') is None: del posted_form.cleaned_data['end_date'] if posted_form.cleaned_data.get('email_to') == []: del posted_form.cleaned_data['email_to'] if posted_form.cleaned_data.get('email_from') == "": del posted_form.cleaned_data['email_from'] if posted_form.cleaned_data.get('email_subject') == "": del posted_form.cleaned_data['email_subject'] try: results = hubApi.trigger_report_generation( posted_form.cleaned_data) except HTTPServiceError as e: logger.error('Report generation failed: %s' % e.details) messages.add_message(request, messages.ERROR, 'Could not start report generation') else: if 'report_generation_requested' in results: messages.add_message( request, messages.INFO, 'Successfully started report generation') else: messages.add_message(request, messages.ERROR, 'Could not start report generation') else: reg_form = ReportGenerationForm(auto_id='registration_%s') msisdn_form = MsisdnReportGenerationForm(auto_id='cohort_%s') report_type = "" report_tasks = hubApi.get_report_tasks() context = { "forms": { "registration_form": reg_form, "cohort_form": msisdn_form }, "report_tasks": report_tasks, "report_type": report_type } context.update(csrf(request)) return render(request, 'ci/reports.html', context)
def subscription(request, subscription): sbmApi = StageBasedMessagingApiClient( api_url=request.session["user_tokens"]["SEED_STAGE_BASED_MESSAGING"] ["url"], # noqa auth_token=request.session["user_tokens"]["SEED_STAGE_BASED_MESSAGING"] ["token"] # noqa ) messagesets_results = sbmApi.get_messagesets() messagesets = {} for messageset in messagesets_results["results"]: messagesets[messageset["id"]] = messageset["short_name"] results = sbmApi.get_subscription(subscription) if results is None: return redirect('not_found') if request.method == "POST": try: form = ChangeSubscriptionForm(request.POST) if form.is_valid(): lang = form.cleaned_data["language"] messageset = form.cleaned_data["messageset"] if (lang != results["lang"] or messageset != results["messageset"]): hubApi = HubApiClient( request.session["user_tokens"]["HUB"]["token"], api_url=request.session["user_tokens"]["HUB"] ["url"]) # noqa change = { settings.IDENTITY_FIELD: results["identity"], "subscription": subscription } if lang != results["lang"]: change["language"] = lang if messageset != results["messageset"]: change["messageset"] = messagesets[messageset] hubApi.create_change_admin(change) messages.add_message(request, messages.INFO, 'Successfully added change.', extra_tags='success') except: messages.add_message(request, messages.ERROR, 'Change failed.', extra_tags='danger') languages = sbmApi.get_messageset_languages() context = { "subscription": results, "messagesets": messagesets, "languages": json.dumps(languages) } context.update(csrf(request)) return render(request, 'ci/subscriptions_detail.html', context)
def identity(request, identity): idApi = IdentityStoreApiClient( api_url=request.session["user_tokens"]["SEED_IDENTITY_SERVICE"] ["url"], # noqa auth_token=request.session["user_tokens"]["SEED_IDENTITY_SERVICE"][ "token"] # noqa ) hubApi = HubApiClient( api_url=request.session["user_tokens"]["HUB"]["url"], # noqa auth_token=request.session["user_tokens"]["HUB"]["token"] # noqa ) sbmApi = StageBasedMessagingApiClient( api_url=request.session["user_tokens"]["SEED_STAGE_BASED_MESSAGING"] ["url"], # noqa auth_token=request.session["user_tokens"]["SEED_STAGE_BASED_MESSAGING"] ["token"] # noqa ) msApi = MessageSenderApiClient( api_url=request.session["user_tokens"]["SEED_MESSAGE_SENDER"] ["url"], # noqa auth_token=request.session["user_tokens"]["SEED_MESSAGE_SENDER"][ "token"] # noqa ) messagesets_results = sbmApi.get_messagesets() messagesets = {} schedules = {} choices = [] for messageset in messagesets_results["results"]: messagesets[messageset["id"]] = messageset["short_name"] schedules[messageset["id"]] = messageset["default_schedule"] choices.append((messageset["id"], messageset["short_name"])) results = idApi.get_identity(identity) sbm_filter = {"identity": identity} subscriptions = sbmApi.get_subscriptions(params=sbm_filter) if request.method == "POST": if 'add_subscription' in request.POST: form = AddSubscriptionForm(request.POST) language = results['details'].get(settings.LANGUAGE_FIELD) if language: if form.is_valid(): subscription = { "active": True, "identity": identity, "completed": False, "lang": language, "messageset": form.cleaned_data['messageset'], "next_sequence_number": 1, "schedule": schedules[form.cleaned_data['messageset']], "process_status": 0, } sbmApi.create_subscription(subscription) messages.add_message( request, messages.INFO, 'Successfully created a subscription.', extra_tags='success') else: messages.add_message( request, messages.ERROR, 'No language value in {} on the identity.'.format( settings.LANGUAGE_FIELD), extra_tags='danger') elif 'deactivate_subscription' in request.POST: form = DeactivateSubscriptionForm(request.POST) if form.is_valid(): data = {"active": False} sbmApi.update_subscription( form.cleaned_data['subscription_id'], data) messages.add_message( request, messages.INFO, 'Successfully deactivated the subscription.', extra_tags='success') elif 'optout_identity' in request.POST: try: details = results.get('details', {}) addresses = details.get('addresses', {}) for address_type, addresses in addresses.items(): for address, info in addresses.items(): idApi.create_optout({ "identity": identity, "optout_type": "stop", "address_type": address_type, "address": address, "request_source": "ci" }) hubApi.create_optout_admin({settings.IDENTITY_FIELD: identity}) messages.add_message(request, messages.INFO, 'Successfully opted out.', extra_tags='success') except: messages.add_message(request, messages.ERROR, 'Optout failed.', extra_tags='danger') hub_filter = {settings.IDENTITY_FIELD: identity} registrations = hubApi.get_registrations(params=hub_filter) changes = hubApi.get_changes(params=hub_filter) if results is None: return redirect('not_found') outbound_message_params = { 'to_identity': identity, 'ordering': '-created_at', } outbound_messages = msApi.get_outbounds(params=outbound_message_params) outbound_page = request.GET.get('outbound_page') outbound_paginator = Paginator(list(outbound_messages['results']), settings.IDENTITY_MESSAGES_PAGE_SIZE) try: outbound_messages = outbound_paginator.page(outbound_page) except PageNotAnInteger: outbound_messages = outbound_paginator.page(1) except EmptyPage: outbound_messages = outbound_paginator.page( outbound_paginator.num_pages) inbound_message_params = { 'from_identity': identity, 'ordering': '-created_at', } inbound_messages = msApi.get_inbounds(inbound_message_params) inbound_page = request.GET.get('inbound_page') inbound_paginator = Paginator(list(inbound_messages['results']), settings.IDENTITY_MESSAGES_PAGE_SIZE) try: inbound_messages = inbound_paginator.page(inbound_page) except PageNotAnInteger: inbound_messages = inbound_paginator.page(1) except EmptyPage: inbound_messages = inbound_paginator.page(inbound_paginator.num_pages) deactivate_subscription_form = DeactivateSubscriptionForm() add_subscription_form = AddSubscriptionForm() add_subscription_form.fields['messageset'] = forms.ChoiceField( choices=choices) optout_visible = False details = results.get('details', {}) addresses = details.get('addresses', {}) msisdns = addresses.get('msisdn', {}) optout_visible = any((not d.get('optedout') for _, d in msisdns.items())) context = { "identity": results, "registrations": registrations, "changes": changes, "messagesets": messagesets, "subscriptions": subscriptions, "outbound_messages": outbound_messages, "add_subscription_form": add_subscription_form, "deactivate_subscription_form": deactivate_subscription_form, "inbound_messages": inbound_messages, "optout_visible": optout_visible } context.update(csrf(request)) return render(request, 'ci/identities_detail.html', context)
def handle(self, *args, **options): identity_store_token = options['identity_store_token'] identity_store_url = options['identity_store_url'] hub_token = options['hub_token'] hub_url = options['hub_url'] file_name = options['csv'] start = options['start'] end = options['end'] no_is = options['no_is_lookup'] log = get_logger() if not file_name: raise CommandError('--csv is a required parameter') if not os.path.isfile(file_name): raise CommandError('--csv must be a valid path to a file') if not hub_url: raise CommandError('--hub-url is a required parameter') if not hub_token: raise CommandError('--hub-token is a required parameter') if not no_is: if not identity_store_url: raise CommandError('--identity-store-url is a required ' 'parameter') if not identity_store_token: raise CommandError('--identity-store-token is a required ' 'parameter') ids_client = IdentityStoreApiClient(identity_store_token, identity_store_url) hub_client = HubApiClient(hub_token, hub_url) with open(file_name) as csv_file: csv_reader = csv.reader(csv_file, delimiter=';') if start and end: rows = itertools.islice(csv_reader, start, end) row_count = start elif start and not end: rows = itertools.islice(csv_reader, start) row_count = start elif end and not start: raise CommandError('--start is a required parameter when ' 'specifying --end') else: rows = csv_reader row_count = 1 # skip the header row next(csv_reader) for idx, row in enumerate(rows, start=row_count): loop_log = log.bind(row=idx) msisdn = '+{0}'.format(row[1]) loop_log = loop_log.bind(msisdn=msisdn) if no_is: identity = row[3] if not identity: loop_log.error('Could not load identity for msisdn.') continue else: result = list(ids_client.get_identity_by_address( 'msisdn', msisdn)['result']) if len(result) < 1: loop_log.error('Could not load identity for msisdn.') continue if len(result) > 1: msg = 'Warning: Found {0} identities' msg = msg.format(len(result)) loop_log.warn(msg) identity = result[0]['id'] # Use this logger only for this iteration of the loop id_log = loop_log.bind(identity=identity) change = { 'registrant_id': identity, 'action': 'momconnect_nonloss_optout', 'data': { 'reason': 'sms_failure' } } try: result = hub_client.create_change(change) except exceptions.ConnectionError as exc: id_log.error('Connection error to Hub API: {}' .format(exc.message)) break except HTTPServiceError as exc: id_log.error('Invalid Hub API response', url=exc.response.url, status_code=exc.response.status_code) break if result: id_log.info('Successfully submitted changed.') else: id_log.error('Change failed', response=result)
def handle(self, *options, **kwargs): self.identity_cache = {} hub_token = kwargs['hub_token'] hub_url = kwargs['hub_url'] id_store_token = kwargs['identity_store_token'] id_store_url = kwargs['identity_store_url'] group = kwargs['group'] headers = ['risk', 'count'] if group == 'msisdn': if not id_store_token or not id_store_url: raise CommandError( 'Please make sure the --identity-store-url and ' '--identity-store-token is set.') ids_client = IdentityStoreApiClient(id_store_token, id_store_url) headers = ['msisdn', 'risk'] output = self.stdout if kwargs['output']: output = open(kwargs['output'], 'w') results = defaultdict(int) def add_to_result(risk, reg): if group == "msisdn": identity = self.get_identity(ids_client, reg) if identity: details = identity.get('details', {}) default_addr_type = details.get('default_addr_type') if default_addr_type: addresses = details.get('addresses', {}) msisdns = addresses.get(default_addr_type, {}).keys() else: msisdns = [] results[', '.join(msisdns)] = 1 if risk == "high" else 0 else: results[risk] += 1 if hub_token and hub_url: hub_client = HubApiClient(hub_token, hub_url) for source in (1, 3): registrations = hub_client.get_registrations({ "source": source, "validated": True })['results'] for registration in registrations: mom_dob = registration["data"].get("mom_dob") if not mom_dob: identity = self.get_identity( ids_client, registration["registrant_id"]) if not identity: continue mom_dob = identity["details"].get("mom_dob") risk = get_risk_status(registration["reg_type"], mom_dob, registration["data"].get("edd")) add_to_result(risk, registration['registrant_id']) else: registrations = Registration.objects.filter( Q(reg_type='pmtct_postbirth') | Q(reg_type='pmtct_prebirth') | Q(reg_type='whatsapp_pmtct_postbirth') | Q(reg_type='whatsapp_pmtct_prebirth'), validated=True) for registration in registrations.iterator(): add_personally_identifiable_fields(registration) risk = get_risk_status(registration.reg_type, registration.data["mom_dob"], registration.data.get("edd")) add_to_result(risk, registration.registrant_id) writer = csv.DictWriter(output, headers) writer.writeheader() for risk, count in results.items(): writer.writerow({headers[0]: risk, headers[1]: count})
def handle(self, *args, **kwargs): self.identity_cache = {} self.messageset_cache = {} hub_token = kwargs['hub_token'] hub_url = kwargs['hub_url'] id_store_token = kwargs['identity_store_token'] id_store_url = kwargs['identity_store_url'] sbm_token = kwargs['sbm_token'] sbm_url = kwargs['sbm_url'] ms_token = kwargs['ms_token'] ms_url = kwargs['ms_url'] start_date = kwargs['start'] end_date = kwargs['end'] output_file = kwargs['output_file'] email_recipients = kwargs['email_to'] email_sender = kwargs['email_from'] email_subject = kwargs['email_subject'] if not sbm_url: raise CommandError('Please make sure the --sbm-url is set.') if not sbm_token: raise CommandError('Please make sure the --sbm-token is set.') if not ms_url: raise CommandError('Please make sure the --ms-url is set.') if not ms_token: raise CommandError('Please make sure the --ms-token is set.') if not output_file: raise CommandError('Please specify --output-file.') if end_date is None: end_date = one_month_after(start_date) hub_client = HubApiClient(hub_token, hub_url) ids_client = IdentityStoreApiClient(id_store_token, id_store_url) sbm_client = StageBasedMessagingApiClient(sbm_token, sbm_url) ms_client = MessageSenderApiClient(ms_token, ms_url) workbook = self.workbook_class() sheet = workbook.add_sheet('Registrations by date', 0) self.handle_registrations(sheet, hub_client, ids_client, start_date, end_date) sheet = workbook.add_sheet('Health worker registrations', 1) self.handle_health_worker_registrations(sheet, hub_client, ids_client, start_date, end_date) sheet = workbook.add_sheet('Enrollments', 2) self.handle_enrollments(sheet, sbm_client, ids_client, start_date, end_date) sheet = workbook.add_sheet('SMS delivery per MSISDN', 3) self.handle_sms_delivery_msisdn(sheet, ms_client, start_date, end_date) sheet = workbook.add_sheet('OBD Delivery Failure', 4) self.handle_obd_delivery_failure(sheet, ms_client, start_date, end_date) sheet = workbook.add_sheet('Opt Outs by Subscription', 5) self.handle_optouts_by_subscription(sheet, sbm_client, ids_client, start_date, end_date) sheet = workbook.add_sheet('Opt Outs by Date', 6) self.handle_optouts_by_date(sheet, hub_client, sbm_client, ids_client, start_date, end_date) workbook.save(output_file) if email_recipients: file_name = 'report-%s-to-%s.xlsx' % ( start_date.strftime('%Y-%m-%d'), end_date.strftime('%Y-%m-%d')) self.send_email(email_subject, file_name, output_file, email_sender, email_recipients)