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)
示例#9
0
    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)
示例#10
0
    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)