Example #1
0
def export_contacts(account_key, contact_keys, include_extra=True):
    """
    Export a list of contacts as a CSV file and email to the account
    holders' email address.

    :param str account_key:
        The account holders account key
    :param str contact_keys:
        The keys of the contacts to export
    :param bool include_extra:
        Whether or not to include the extra data stored in the dynamic field.
    """

    api = VumiUserApi.from_config_sync(account_key, settings.VUMI_API_CONFIG)
    contact_store = api.contact_store

    contacts = contacts_by_key(contact_store, *contact_keys)
    data = contacts_to_csv(contacts, include_extra)
    file = zipped_file('contacts-export.csv', data)

    # Get the profile for this user so we can email them when the import
    # has been completed.
    user_profile = UserProfile.objects.get(user_account=account_key)

    email = EmailMessage(
        'Contacts export',
        'Please find the CSV data for %s contact(s)' % len(contacts),
        settings.DEFAULT_FROM_EMAIL, [user_profile.user.email])

    email.attach('contacts-export.zip', file, 'application/zip')
    email.send()
Example #2
0
def export_contacts(account_key, contact_keys, include_extra=True):
    """
    Export a list of contacts as a CSV file and email to the account
    holders' email address.

    :param str account_key:
        The account holders account key
    :param str contact_keys:
        The keys of the contacts to export
    :param bool include_extra:
        Whether or not to include the extra data stored in the dynamic field.
    """

    api = VumiUserApi.from_config_sync(account_key, settings.VUMI_API_CONFIG)
    contact_store = api.contact_store

    contacts = contacts_by_key(contact_store, *contact_keys)
    data = contacts_to_csv(contacts, include_extra)
    file = zipped_file('contacts-export.csv', data)

    # Get the profile for this user so we can email them when the import
    # has been completed.
    user_profile = UserProfile.objects.get(user_account=account_key)

    email = EmailMessage(
        'Contacts export',
        'Please find the CSV data for %s contact(s)' % len(contacts),
        settings.DEFAULT_FROM_EMAIL, [user_profile.user.email])

    email.attach('contacts-export.zip', file, 'application/zip')
    email.send()
Example #3
0
def _smart_group(request, contact_store, group):
    if request.method == 'POST':
        if '_save_group' in request.POST:
            smart_group_form = SmartGroupForm(request.POST)
            if smart_group_form.is_valid():
                group.name = smart_group_form.cleaned_data['name']
                group.query = smart_group_form.cleaned_data['query']
                group.save()
                return redirect(_group_url(group.key))
        elif '_export' in request.POST:
            tasks.export_group_contacts.delay(
                request.user_api.user_account_key, group.key, True)
            messages.info(
                request, 'The export is scheduled and should '
                'complete within a few minutes.')
            return redirect(_group_url(group.key))
        elif '_delete_group_contacts' in request.POST:
            tasks.delete_group_contacts.delay(
                request.user_api.user_account_key, group.key)
            messages.info(request,
                          "The group's contacts will be deleted shortly.")
            return redirect(_group_url(group.key))
        elif '_delete_group' in request.POST:
            tasks.delete_group.delay(request.user_api.user_account_key,
                                     group.key)
            messages.info(request, 'The group will be deleted shortly.')
            return redirect(reverse('contacts:index'))
        else:
            # We didn't get any useful POST variables, so just redirect back to
            # the group page without doing anything.
            return redirect(_group_url(group.key))
    else:
        smart_group_form = SmartGroupForm({
            'name': group.name,
            'query': group.query,
        })

    keys = contact_store.get_contacts_for_group(group)
    limit = min(int(request.GET.get('limit', 100)), len(keys))

    if keys:
        messages.info(
            request,
            "Showing %s of the group's %s contact(s)" % (limit, len(keys)))

    contacts = utils.contacts_by_key(contact_store, *keys[:limit])
    return render(
        request, 'contacts/smart_group_detail.html', {
            'group': group,
            'selected_contacts': contacts,
            'group_form': smart_group_form,
        })
Example #4
0
def _smart_group(request, contact_store, group):
    if request.method == 'POST':
        if '_save_group' in request.POST:
            smart_group_form = SmartGroupForm(request.POST)
            if smart_group_form.is_valid():
                group.name = smart_group_form.cleaned_data['name']
                group.query = smart_group_form.cleaned_data['query']
                group.save()
                return redirect(_group_url(group.key))
        elif '_export' in request.POST:
            tasks.export_group_contacts.delay(
                request.user_api.user_account_key, group.key, True)
            messages.info(request, 'The export is scheduled and should '
                                   'complete within a few minutes.')
            return redirect(_group_url(group.key))
        elif '_delete_group_contacts' in request.POST:
            tasks.delete_group_contacts.delay(
                request.user_api.user_account_key, group.key)
            messages.info(
                request, "The group's contacts will be deleted shortly.")
            return redirect(_group_url(group.key))
        elif '_delete_group' in request.POST:
            tasks.delete_group.delay(request.user_api.user_account_key,
                                     group.key)
            messages.info(request, 'The group will be deleted shortly.')
            return redirect(reverse('contacts:index'))
        else:
            # We didn't get any useful POST variables, so just redirect back to
            # the group page without doing anything.
            return redirect(_group_url(group.key))
    else:
        smart_group_form = SmartGroupForm({
            'name': group.name,
            'query': group.query,
        })

    keys = contact_store.get_contacts_for_group(group)
    limit = min(int(request.GET.get('limit', 100)), len(keys))

    if keys:
        messages.info(
            request,
            "Showing %s of the group's %s contact(s)" % (limit, len(keys)))

    contacts = utils.contacts_by_key(contact_store, *keys[:limit])
    return render(request, 'contacts/smart_group_detail.html', {
        'group': group,
        'selected_contacts': contacts,
        'group_form': smart_group_form,
    })
Example #5
0
def get_group_contacts(contact_store, *groups):
    contact_keys = []
    for group in groups:
        contact_keys.extend(contact_store.get_contacts_for_group(group))

    return contacts_by_key(contact_store, *contact_keys)
Example #6
0
def get_group_contacts(contact_store, *groups):
    contact_keys = []
    for group in groups:
        contact_keys.extend(contact_store.get_contacts_for_group(group))

    return contacts_by_key(contact_store, *contact_keys)
Example #7
0
def _people(request):
    contact_store = request.user_api.contact_store
    upload_contacts_form = None
    group = None

    if request.method == 'POST':
        if '_delete' in request.POST:
            contacts = request.POST.getlist('contact')
            for person_key in contacts:
                contact = contact_store.get_contact_by_key(person_key)
                contact.delete()
            messages.info(request, '%d Contacts deleted' % len(contacts))
        elif '_export' in request.POST:
            tasks.export_contacts.delay(
                request.user_api.user_account_key,
                request.POST.getlist('contact'))
            messages.info(request, 'The export is scheduled and should '
                                   'complete within a few minutes.')
        elif '_export_all' in request.POST:
            tasks.export_all_contacts.delay(
                request.user_api.user_account_key)
            messages.info(request, 'The export is scheduled and should '
                                   'complete within a few minutes.')
        else:
            # first parse the CSV file and create Contact instances
            # from them for attaching to a group later
            upload_contacts_form = UploadContactsForm(
                request.POST, request.FILES)
            if upload_contacts_form.is_valid():
                # We could be creating a new contact group.
                if request.POST.get('name'):
                    new_group_form = ContactGroupForm(request.POST)
                    if new_group_form.is_valid():
                        group = contact_store.new_group(
                            new_group_form.cleaned_data['name'])

                # We could be using an existing contact group.
                elif request.POST.get('contact_group'):
                    select_group_form = SelectContactGroupForm(
                        request.POST, groups=contact_store.list_groups())
                    if select_group_form.is_valid():
                        group = contact_store.get_group(
                            select_group_form.cleaned_data['contact_group'])

                if group is None:
                    messages.error(request, 'Please select a group or provide '
                                            'a new group name.')
                else:
                    file_object = upload_contacts_form.cleaned_data['file']
                    file_name, file_path = utils.store_temporarily(file_object)
                    utils.store_file_hints_in_session(
                        request, file_name, file_path)
                    return redirect(_group_url(group.key))
            else:
                messages.error(
                    request, 'Something went wrong with the upload.')

    select_contact_group_form = SelectContactGroupForm(
        groups=contact_store.list_groups())

    # TODO: A lot of this stuff is duplicated from the similar group search
    #       in the groups() view. We need a function that does that to avoid
    #       the duplication.
    user_query = request.GET.get('q', '')
    query = user_query
    if query:
        if not ':' in query:
            query = 'name:%s' % (query,)

        keys = contact_store.contacts.raw_search(query).get_keys()
    else:
        keys = contact_store.list_contacts()

    limit = min(int(request.GET.get('limit', 100)), len(keys))
    messages.info(request, "Showing %s of %s contact(s)" % (limit, len(keys)))

    smart_group_form = SmartGroupForm(initial={'query': query})
    contacts = utils.contacts_by_key(contact_store, *keys[:limit])

    return render(request, 'contacts/contact_list.html', {
        'query': user_query,
        'selected_contacts': contacts,
        'smart_group_form': smart_group_form,
        'upload_contacts_form': upload_contacts_form or UploadContactsForm(),
        'select_contact_group_form': select_contact_group_form,
    })
Example #8
0
def _static_group(request, contact_store, group):
    if group is None:
        raise Http404

    if request.method == 'POST':
        group_form = ContactGroupForm(request.POST)
        if '_save_group' in request.POST:
            if group_form.is_valid():
                group.name = group_form.cleaned_data['name']
                group.save()
            messages.info(request, 'The group name has been updated')
            return redirect(_group_url(group.key))
        elif '_export' in request.POST:
            tasks.export_group_contacts.delay(
                request.user_api.user_account_key,
                group.key)

            messages.info(request,
                          'The export is scheduled and should '
                          'complete within a few minutes.')
            return redirect(_group_url(group.key))
        elif '_remove' in request.POST:
            contacts = request.POST.getlist('contact')
            for person_key in contacts:
                contact = contact_store.get_contact_by_key(person_key)
                contact.groups.remove(group)
                contact.save()
            messages.info(
                request,
                '%d Contacts removed from group' % len(contacts))
            return redirect(_group_url(group.key))
        elif '_delete_group_contacts' in request.POST:
            tasks.delete_group_contacts.delay(
                request.user_api.user_account_key, group.key)
            messages.info(request,
                          "The group's contacts will be deleted shortly.")
            return redirect(_group_url(group.key))
        elif '_delete_group' in request.POST:
            tasks.delete_group.delay(request.user_api.user_account_key,
                                     group.key)
            messages.info(request, 'The group will be deleted shortly.')
            return redirect(reverse('contacts:index'))
        elif '_complete_contact_upload' in request.POST:
            try:
                import_rule = request.POST.get('import_rule')
                import_handler = {
                    'existing_is_truth': handle_import_existing_is_truth,
                    'upload_is_truth': handle_import_upload_is_truth,
                }.get(import_rule, handle_import_new_contacts)

                import_handler(request, group)
                messages.info(
                    request,
                    'The contacts are being imported. '
                    'We will notify you via email when the import '
                    'has been completed')

            except (ContactParserException,):
                messages.error(request, 'Something is wrong with the file')
                _, file_path = utils.get_file_hints_from_session(request)
                default_storage.delete(file_path)

            return redirect(_group_url(group.key))

        else:
            upload_contacts_form = UploadContactsForm(request.POST,
                                                      request.FILES)
            if upload_contacts_form.is_valid():
                file_object = upload_contacts_form.cleaned_data['file']
                file_name, file_path = utils.store_temporarily(file_object)
                utils.store_file_hints_in_session(
                    request, file_name, file_path)
                return redirect(_group_url(group.key))
            else:
                # We didn't get any useful POST variables, so just redirect
                # back to the group page without doing anything.
                return redirect(_group_url(group.key))

    else:
        group_form = ContactGroupForm({
            'name': group.name,
        })

    context = {
        'group': group,
        'group_form': group_form,
    }

    if 'clear-upload' in request.GET:
        # FIXME this is a debug statement
        utils.clear_file_hints_from_session(request)

    if utils.has_uncompleted_contact_import(request):
        try:
            file_name, file_path = utils.get_file_hints_from_session(request)
            file_type, parser = ContactFileParser.get_parser(file_name)
            has_header, headers, row = parser.guess_headers_and_row(file_path)
            context.update({
                'contact_data_headers': headers,
                'field_normalizer': FieldNormalizer(),
                'contact_data_row': row,
                # NOTE: Only if we have a key (contact UUID) value in the
                #       row we can look at updating contacts instead of
                #       only writing new ones.
                'can_update_contacts': 'key' in row,
            })
        except (ValueError, ContactParserException):
            messages.error(request, 'Something is wrong with the file')
            utils.clear_file_hints_from_session(request)
            default_storage.delete(file_path)

    query = request.GET.get('q', '')
    if query:
        if not ':' in query:
            query = 'name:%s' % (query,)
        keys = contact_store.contacts.raw_search(query).get_keys()
    else:
        keys = contact_store.get_contacts_for_group(group)

    limit = min(int(request.GET.get('limit', 100)), len(keys))
    if keys:
        messages.info(
            request,
            "Showing %s of the group's %s contact(s)" % (limit, len(keys)))

    contacts = utils.contacts_by_key(contact_store, *keys[:limit])
    context.update({
        'query': request.GET.get('q'),
        'selected_contacts': contacts,
        'member_count': contact_store.count_contacts_for_group(group),
    })

    return render(request, 'contacts/static_group_detail.html', context)
Example #9
0
def _people(request):
    contact_store = request.user_api.contact_store
    upload_contacts_form = None
    group = None

    if request.method == 'POST':
        if '_delete' in request.POST:
            contacts = request.POST.getlist('contact')
            for person_key in contacts:
                contact = contact_store.get_contact_by_key(person_key)
                contact.delete()
            messages.info(request, '%d Contacts deleted' % len(contacts))
        elif '_export' in request.POST:
            tasks.export_contacts.delay(request.user_api.user_account_key,
                                        request.POST.getlist('contact'))
            messages.info(
                request, 'The export is scheduled and should '
                'complete within a few minutes.')
        elif '_export_all' in request.POST:
            tasks.export_all_contacts.delay(request.user_api.user_account_key)
            messages.info(
                request, 'The export is scheduled and should '
                'complete within a few minutes.')
        else:
            # first parse the CSV file and create Contact instances
            # from them for attaching to a group later
            upload_contacts_form = UploadContactsForm(request.POST,
                                                      request.FILES)
            if upload_contacts_form.is_valid():
                # We could be creating a new contact group.
                if request.POST.get('name'):
                    new_group_form = ContactGroupForm(request.POST)
                    if new_group_form.is_valid():
                        group = contact_store.new_group(
                            new_group_form.cleaned_data['name'])

                # We could be using an existing contact group.
                elif request.POST.get('contact_group'):
                    select_group_form = SelectContactGroupForm(
                        request.POST, groups=contact_store.list_groups())
                    if select_group_form.is_valid():
                        group = contact_store.get_group(
                            select_group_form.cleaned_data['contact_group'])

                if group is None:
                    messages.error(
                        request, 'Please select a group or provide '
                        'a new group name.')
                else:
                    file_object = upload_contacts_form.cleaned_data['file']
                    file_name, file_path = utils.store_temporarily(file_object)
                    utils.store_file_hints_in_session(request, file_name,
                                                      file_path)
                    return redirect(_group_url(group.key))
            else:
                messages.error(request,
                               'Something went wrong with the upload.')

    select_contact_group_form = SelectContactGroupForm(
        groups=contact_store.list_groups())

    # TODO: A lot of this stuff is duplicated from the similar group search
    #       in the groups() view. We need a function that does that to avoid
    #       the duplication.
    user_query = request.GET.get('q', '')
    query = user_query
    if query:
        if not ':' in query:
            query = 'name:%s' % (query, )

        keys = contact_store.contacts.raw_search(query).get_keys()
    else:
        keys = contact_store.list_contacts()

    limit = min(int(request.GET.get('limit', 100)), len(keys))
    messages.info(request, "Showing %s of %s contact(s)" % (limit, len(keys)))

    smart_group_form = SmartGroupForm(initial={'query': query})
    contacts = utils.contacts_by_key(contact_store, *keys[:limit])

    return render(
        request, 'contacts/contact_list.html', {
            'query': user_query,
            'selected_contacts': contacts,
            'smart_group_form': smart_group_form,
            'upload_contacts_form': upload_contacts_form
            or UploadContactsForm(),
            'select_contact_group_form': select_contact_group_form,
        })
Example #10
0
def _static_group(request, contact_store, group):
    if group is None:
        raise Http404

    if request.method == 'POST':
        group_form = ContactGroupForm(request.POST)
        if '_save_group' in request.POST:
            if group_form.is_valid():
                group.name = group_form.cleaned_data['name']
                group.save()
            messages.info(request, 'The group name has been updated')
            return redirect(_group_url(group.key))
        elif '_export' in request.POST:
            tasks.export_group_contacts.delay(
                request.user_api.user_account_key, group.key)

            messages.info(
                request, 'The export is scheduled and should '
                'complete within a few minutes.')
            return redirect(_group_url(group.key))
        elif '_remove' in request.POST:
            contacts = request.POST.getlist('contact')
            for person_key in contacts:
                contact = contact_store.get_contact_by_key(person_key)
                contact.groups.remove(group)
                contact.save()
            messages.info(request,
                          '%d Contacts removed from group' % len(contacts))
            return redirect(_group_url(group.key))
        elif '_delete_group_contacts' in request.POST:
            tasks.delete_group_contacts.delay(
                request.user_api.user_account_key, group.key)
            messages.info(request,
                          "The group's contacts will be deleted shortly.")
            return redirect(_group_url(group.key))
        elif '_delete_group' in request.POST:
            tasks.delete_group.delay(request.user_api.user_account_key,
                                     group.key)
            messages.info(request, 'The group will be deleted shortly.')
            return redirect(reverse('contacts:index'))
        elif '_complete_contact_upload' in request.POST:
            try:
                import_rule = request.POST.get('import_rule')
                import_handler = {
                    'existing_is_truth': handle_import_existing_is_truth,
                    'upload_is_truth': handle_import_upload_is_truth,
                }.get(import_rule, handle_import_new_contacts)

                import_handler(request, group)
                messages.info(
                    request, 'The contacts are being imported. '
                    'We will notify you via email when the import '
                    'has been completed')

            except (ContactParserException, ):
                messages.error(request, 'Something is wrong with the file')
                _, file_path = utils.get_file_hints_from_session(request)
                default_storage.delete(file_path)

            return redirect(_group_url(group.key))

        else:
            upload_contacts_form = UploadContactsForm(request.POST,
                                                      request.FILES)
            if upload_contacts_form.is_valid():
                file_object = upload_contacts_form.cleaned_data['file']
                file_name, file_path = utils.store_temporarily(file_object)
                utils.store_file_hints_in_session(request, file_name,
                                                  file_path)
                return redirect(_group_url(group.key))
            else:
                # We didn't get any useful POST variables, so just redirect
                # back to the group page without doing anything.
                return redirect(_group_url(group.key))

    else:
        group_form = ContactGroupForm({
            'name': group.name,
        })

    context = {
        'group': group,
        'group_form': group_form,
    }

    if 'clear-upload' in request.GET:
        # FIXME this is a debug statement
        utils.clear_file_hints_from_session(request)

    if utils.has_uncompleted_contact_import(request):
        try:
            file_name, file_path = utils.get_file_hints_from_session(request)
            file_type, parser = ContactFileParser.get_parser(file_name)
            has_header, headers, row = parser.guess_headers_and_row(file_path)
            context.update({
                'contact_data_headers': headers,
                'field_normalizer': FieldNormalizer(),
                'contact_data_row': row,
                # NOTE: Only if we have a key (contact UUID) value in the
                #       row we can look at updating contacts instead of
                #       only writing new ones.
                'can_update_contacts': 'key' in row,
            })
        except (ValueError, ContactParserException):
            messages.error(request, 'Something is wrong with the file')
            utils.clear_file_hints_from_session(request)
            default_storage.delete(file_path)

    query = request.GET.get('q', '')
    if query:
        if not ':' in query:
            query = 'name:%s' % (query, )
        keys = contact_store.contacts.raw_search(query).get_keys()
    else:
        keys = contact_store.get_contacts_for_group(group)

    limit = min(int(request.GET.get('limit', 100)), len(keys))
    if keys:
        messages.info(
            request,
            "Showing %s of the group's %s contact(s)" % (limit, len(keys)))

    contacts = utils.contacts_by_key(contact_store, *keys[:limit])
    context.update({
        'query':
        request.GET.get('q'),
        'selected_contacts':
        contacts,
        'member_count':
        contact_store.count_contacts_for_group(group),
    })

    return render(request, 'contacts/static_group_detail.html', context)