Example #1
0
def prepare_form_multimedia(request, domain):
    """Gets the download_id for the multimedia zip and sends it to the
    exportDownloadService in download_export.ng.js to begin polling for the
    zip file download.
    """
    form_or_case = request.POST.get('form_or_case')
    sms_export = json.loads(request.POST.get('sms_export'))
    permissions = ExportsPermissionsManager(form_or_case, domain, request.couch_user)
    permissions.access_download_export_or_404()

    view_helper = DownloadExportViewHelper.get(request, domain, form_or_case, sms_export)
    filter_form_data = json.loads(request.POST.get('form_data'))
    export_specs = json.loads(request.POST.get('exports'))
    try:
        filter_form = view_helper.get_filter_form(filter_form_data)
    except ExportFormValidationException:
        return json_response({
            'error': _("Please check that you've submitted all required filters."),
        })

    download = DownloadBase()
    export_object = view_helper.get_export(export_specs[0]['export_id'])
    task_kwargs = filter_form.get_multimedia_task_kwargs(export_object, download.download_id, filter_form_data)
    from corehq.apps.reports.tasks import build_form_multimedia_zip
    download.set_task(build_form_multimedia_zip.delay(**task_kwargs))

    return json_response({
        'success': True,
        'download_id': download.download_id,
    })
Example #2
0
def prepare_form_multimedia(request, domain):
    """Gets the download_id for the multimedia zip and sends it to the
    exportDownloadService in download_export.ng.js to begin polling for the
    zip file download.
    """
    form_or_case = request.POST.get('form_or_case')
    sms_export = json.loads(request.POST.get('sms_export'))
    permissions = ExportsPermissionsManager(form_or_case, domain,
                                            request.couch_user)
    permissions.access_download_export_or_404()

    view_helper = DownloadExportViewHelper.get(request, domain, form_or_case,
                                               sms_export)
    filter_form_data = json.loads(request.POST.get('form_data'))
    export_specs = json.loads(request.POST.get('exports'))
    try:
        filter_form = view_helper.get_filter_form(filter_form_data)
    except ExportFormValidationException:
        return JsonResponse({
            'error':
            _("Please check that you've submitted all required filters."),
        })

    download = DownloadBase()
    export_object = view_helper.get_export(export_specs[0]['export_id'])
    task_kwargs = filter_form.get_multimedia_task_kwargs(
        export_object, download.download_id, filter_form_data)
    from corehq.apps.reports.tasks import build_form_multimedia_zip
    download.set_task(build_form_multimedia_zip.delay(**task_kwargs))

    return JsonResponse({
        'success': True,
        'download_id': download.download_id,
    })
Example #3
0
def prepare_custom_export(request, domain):
    """Uses the current exports download framework (with some nasty filters)
    to return the current download id to POLL for the download status.
    :return: {
        'success': True,
        'download_id': '<some uuid>',
    }
    """
    form_or_case = request.POST.get('form_or_case')
    sms_export = json.loads(request.POST.get('sms_export'))
    permissions = ExportsPermissionsManager(form_or_case, domain, request.couch_user)
    permissions.access_download_export_or_404()

    view_helper = DownloadExportViewHelper.get(request, domain, form_or_case, sms_export)

    filter_form_data = json.loads(request.POST.get('form_data'))
    try:
        filter_form = view_helper.get_filter_form(filter_form_data)
    except ExportFormValidationException:
        return json_response({
            'error': _("Form did not validate."),
        })
    export_filters = filter_form.get_export_filters(request, filter_form_data)
    export_es_filters = [f.to_es_filter() for f in export_filters]

    export_specs = json.loads(request.POST.get('exports'))
    export_ids = [spec['export_id'] for spec in export_specs]
    export_instances = [view_helper.get_export(export_id) for export_id in export_ids]

    try:
        _check_deid_permissions(permissions, export_instances)
        _check_export_size(domain, export_instances, export_filters)
    except ExportAsyncException as e:
        return json_response({
            'error': str(e),
        })

    # Generate filename
    if len(export_instances) > 1:
        filename = "{}_custom_bulk_export_{}".format(domain, date.today().isoformat())
    else:
        filename = "{} {}".format(export_instances[0].name, date.today().isoformat())

    download = get_export_download(
        domain,
        export_ids,
        view_helper.model,
        request.couch_user.username,
        es_filters=export_es_filters,
        owner_id=request.couch_user.get_id,
        filename=filename,
    )

    view_helper.send_preparation_analytics(export_instances, export_filters)

    return json_response({
        'success': True,
        'download_id': download.download_id,
    })
Example #4
0
def prepare_custom_export(request, domain):
    """Uses the current exports download framework (with some nasty filters)
    to return the current download id to POLL for the download status.
    :return: {
        'success': True,
        'download_id': '<some uuid>',
    }
    """
    form_or_case = request.POST.get('form_or_case')
    sms_export = json.loads(request.POST.get('sms_export'))
    permissions = ExportsPermissionsManager(form_or_case, domain, request.couch_user)
    permissions.access_download_export_or_404()

    view_helper = DownloadExportViewHelper.get(request, domain, form_or_case, sms_export)

    filter_form_data = json.loads(request.POST.get('form_data'))
    try:
        filter_form = view_helper.get_filter_form(filter_form_data)
    except ExportFormValidationException:
        return json_response({
            'error': _("Form did not validate."),
        })
    export_filters = filter_form.get_export_filters(request, filter_form_data)

    export_specs = json.loads(request.POST.get('exports'))
    export_ids = [spec['export_id'] for spec in export_specs]
    export_instances = [view_helper.get_export(export_id) for export_id in export_ids]

    try:
        _check_deid_permissions(permissions, export_instances)
        _check_export_size(domain, export_instances, export_filters)
    except ExportAsyncException as e:
        return json_response({
            'error': six.text_type(e),
        })

    # Generate filename
    if len(export_instances) > 1:
        filename = "{}_custom_bulk_export_{}".format(domain, date.today().isoformat())
    else:
        filename = "{} {}".format(export_instances[0].name, date.today().isoformat())

    download = get_export_download(
        domain,
        export_ids,
        view_helper.model,
        request.couch_user.username,
        filters=export_filters,
        filename=filename,
    )

    view_helper.send_preparation_analytics(export_instances, export_filters)

    return json_response({
        'success': True,
        'download_id': download.download_id,
    })
Example #5
0
def prepare_form_multimedia(request, domain):
    """Gets the download_id for the multimedia zip and sends it to the
    exportDownloadService in download_export.ng.js to begin polling for the
    zip file download.
    """
    form_or_case = request.POST.get('form_or_case')
    sms_export = json.loads(request.POST.get('sms_export'))
    permissions = ExportsPermissionsManager(form_or_case, domain,
                                            request.couch_user)
    permissions.access_download_export_or_404()

    view_helper = DownloadExportViewHelper.get(request, domain, form_or_case,
                                               sms_export)
    filter_form_data = json.loads(request.POST.get('form_data'))
    export_specs = json.loads(request.POST.get('exports'))
    try:
        filter_form = view_helper.get_filter_form(filter_form_data)
    except ExportFormValidationException:
        return json_response({
            'error':
            _("Please check that you've submitted all required filters."),
        })

    export = view_helper.get_export(export_specs[0]['export_id'])
    datespan = filter_form.cleaned_data['date_range']
    user_types = filter_form.get_es_user_types(filter_form_data)

    if media_export_is_too_big(domain, export.app_id, export.xmlns, datespan,
                               user_types):
        return json_response({
            'success':
            False,
            'error':
            _("This is too many files to export at once.  "
              "Please modify your filters to select fewer forms."),
        })

    download = DownloadBase()
    download.set_task(
        build_form_multimedia_zip.delay(
            domain=domain,
            export_id=export.get_id,
            datespan=datespan,
            user_types=user_types,
            download_id=download.download_id,
            owner_id=request.couch_user.get_id,
        ))

    return json_response({
        'success': True,
        'download_id': download.download_id,
    })
Example #6
0
def has_multimedia(request, domain):
    """Checks to see if this form export has multimedia available to export
    """
    form_or_case = request.GET.get('form_or_case')
    if form_or_case != 'form':
        raise ValueError("has_multimedia is only available for form exports")
    permissions = ExportsPermissionsManager(form_or_case, domain, request.couch_user)
    permissions.access_download_export_or_404()
    export_object = FormExportInstance.get(request.GET.get('export_id'))
    return json_response({
        'success': True,
        'hasMultimedia': export_object.has_multimedia,
    })
Example #7
0
def poll_custom_export_download(request, domain):
    """Polls celery to see how the export download task is going.
    :return: final response: {
        'success': True,
        'dropbox_url': '<url>',
        'download_url: '<url>',
        <task info>
    }
    """
    form_or_case = request.GET.get('form_or_case')
    permissions = ExportsPermissionsManager(form_or_case, domain,
                                            request.couch_user)
    permissions.access_download_export_or_404()
    download_id = request.GET.get('download_id')
    try:
        context = get_download_context(download_id)
    except TaskFailedError as e:
        if e.exception_name == 'XlsLengthException':
            return JsonResponse({
                'error':
                _('This file has more than 256 columns, which is not supported by xls. '
                  'Please change the output type to csv or xlsx to export this file.'
                  )
            })
        else:
            notify_exception(request,
                             "Export download failed",
                             details={
                                 'download_id': download_id,
                                 'errors': e.errors,
                                 'exception_name': e.exception_name
                             })

            return JsonResponse({
                'error': _("Download task failed to start."),
            })

    if context.get('is_ready', False):
        context.update({
            'dropbox_url':
            reverse('dropbox_upload', args=(download_id, )),
            'download_url':
            "{}?get_file".format(
                reverse('retrieve_download', args=(download_id, ))),
        })
    context['is_poll_successful'] = True
    return json_response(context)
Example #8
0
def has_multimedia(request, domain):
    """Checks to see if this form export has multimedia available to export
    """
    form_or_case = request.GET.get('form_or_case')
    if form_or_case != 'form':
        raise ValueError("has_multimedia is only available for form exports")
    permissions = ExportsPermissionsManager(form_or_case, domain,
                                            request.couch_user)
    permissions.access_download_export_or_404()
    export_object = FormExportInstance.get(request.GET.get('export_id'))
    if isinstance(export_object, ExportInstance):
        has_multimedia = export_object.has_multimedia
    else:
        has_multimedia = forms_have_multimedia(
            domain, export_object.app_id, getattr(export_object, 'xmlns', ''))
    return JsonResponse({
        'success': True,
        'hasMultimedia': has_multimedia,
    })
Example #9
0
def poll_custom_export_download(request, domain):
    """Polls celery to see how the export download task is going.
    :return: final response: {
        'success': True,
        'dropbox_url': '<url>',
        'download_url: '<url>',
        <task info>
    }
    """
    form_or_case = request.GET.get('form_or_case')
    permissions = ExportsPermissionsManager(form_or_case, domain, request.couch_user)
    permissions.access_download_export_or_404()
    download_id = request.GET.get('download_id')
    try:
        context = get_download_context(download_id)
    except TaskFailedError as e:
        if e.exception_name == 'XlsLengthException':
            return JsonResponse({
                'error': _(
                    'This file has more than 256 columns, which is not supported by xls. '
                    'Please change the output type to csv or xlsx to export this file.')
            })
        else:
            notify_exception(
                request, "Export download failed",
                details={'download_id': download_id, 'errors': e.errors,
                         'exception_name': e.exception_name})

            return JsonResponse({
                'error': _("Download task failed to start."),
            })

    if context.get('is_ready', False):
        context.update({
            'dropbox_url': reverse('dropbox_upload', args=(download_id,)),
            'download_url': "{}?get_file".format(
                reverse('retrieve_download', args=(download_id,))
            ),
        })
    context['is_poll_successful'] = True
    return json_response(context)
Example #10
0
def has_multimedia(request, domain):
    """Checks to see if this form export has multimedia available to export
    """
    form_or_case = request.GET.get('form_or_case')
    if form_or_case != 'form':
        raise ValueError("has_multimedia is only available for form exports")
    permissions = ExportsPermissionsManager(form_or_case, domain, request.couch_user)
    permissions.access_download_export_or_404()
    export_object = FormExportInstance.get(request.GET.get('export_id'))
    if isinstance(export_object, ExportInstance):
        has_multimedia = export_object.has_multimedia
    else:
        has_multimedia = forms_have_multimedia(
            domain,
            export_object.app_id,
            getattr(export_object, 'xmlns', '')
        )
    return json_response({
        'success': True,
        'hasMultimedia': has_multimedia,
    })
Example #11
0
def poll_custom_export_download(request, domain):
    """Polls celery to see how the export download task is going.
    :return: final response: {
        'success': True,
        'dropbox_url': '<url>',
        'download_url: '<url>',
        <task info>
    }
    """
    form_or_case = request.GET.get('form_or_case')
    permissions = ExportsPermissionsManager(form_or_case, domain,
                                            request.couch_user)
    permissions.access_download_export_or_404()
    download_id = request.GET.get('download_id')
    try:
        context = get_download_context(download_id)
    except TaskFailedError as e:
        notify_exception(request,
                         "Export download failed",
                         details={
                             'download_id': download_id,
                             'errors': e.errors
                         })
        return JsonResponse({
            'error': _("Download task failed to start."),
        })
    if context.get('is_ready', False):
        context.update({
            'dropbox_url':
            reverse('dropbox_upload', args=(download_id, )),
            'download_url':
            "{}?get_file".format(
                reverse('retrieve_download', args=(download_id, ))),
        })
    context['is_poll_successful'] = True
    return JsonResponse(context)
Example #12
0
def prepare_custom_export(request, domain):
    """Uses the current exports download framework (with some nasty filters)
    to return the current download id to POLL for the download status.
    :return: {
        'success': True,
        'download_id': '<some uuid>',
    }
    """
    form_or_case = request.POST.get('form_or_case')
    sms_export = json.loads(request.POST.get('sms_export'))
    permissions = ExportsPermissionsManager(form_or_case, domain,
                                            request.couch_user)
    permissions.access_download_export_or_404()

    view_helper = DownloadExportViewHelper.get(request, domain, form_or_case,
                                               sms_export)

    filter_form_data = json.loads(request.POST.get('form_data'))
    try:
        filter_form = view_helper.get_filter_form(filter_form_data)
    except ExportFormValidationException:
        return JsonResponse({
            'error': _("Form did not validate."),
        })
    export_filters = filter_form.get_export_filters(request, filter_form_data)

    export_specs = json.loads(request.POST.get('exports'))
    export_ids = [spec['export_id'] for spec in export_specs]
    export_instances = [
        view_helper.get_export(export_id) for export_id in export_ids
    ]

    try:
        _check_deid_permissions(permissions, export_instances)
        _check_export_size(domain, export_instances, export_filters)
    except ExportAsyncException as e:
        return JsonResponse({
            'error': six.text_type(e),
        })

    # Generate filename
    if len(export_instances) > 1:
        filename = "{}_custom_bulk_export_{}".format(domain,
                                                     date.today().isoformat())
    else:
        filename = "{} {}".format(export_instances[0].name,
                                  date.today().isoformat())

    try:
        download = get_export_download(
            domain,
            export_ids,
            view_helper.model,
            request.couch_user.username,
            filters=export_filters,
            filename=filename,
        )
    except XlsLengthException:
        return JsonResponse({
            'error':
            _('This file has more than 256 columns, which is not supported by xls. '
              'Please change the output type to csv or xlsx to export this file.'
              )
        })

    view_helper.send_preparation_analytics(export_instances, export_filters)

    return JsonResponse({
        'success': True,
        'download_id': download.download_id,
    })
Example #13
0
class BaseDownloadExportView(HQJSONResponseMixin, BaseProjectDataView):
    template_name = 'export/download_export.html'
    http_method_names = ['get', 'post']
    show_date_range = False
    check_for_multimedia = False
    sms_export = False
    # To serve filters for export from mobile_user_and_group_slugs
    export_filter_class = None

    @use_daterangepicker
    @use_select2
    @method_decorator(login_and_domain_required)
    def dispatch(self, request, *args, **kwargs):
        self.permissions = ExportsPermissionsManager(self.form_or_case,
                                                     request.domain,
                                                     request.couch_user)
        self.permissions.access_download_export_or_404()

        return super(BaseDownloadExportView,
                     self).dispatch(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        if not request.is_ajax():
            context = self.get_context_data(**kwargs)
            return self.render_to_response(context)
        return super(BaseDownloadExportView,
                     self).post(request, *args, **kwargs)

    @property
    @memoized
    def view_helper(self):
        return DownloadExportViewHelper.get(self.request, self.domain,
                                            self.form_or_case, self.sms_export)

    @property
    @memoized
    def timezone(self):
        return get_timezone(self.domain, self.request.couch_user)

    @property
    @memoized
    def default_datespan(self):
        return datespan_from_beginning(self.domain_object, self.timezone)

    @property
    def page_context(self):
        context = {
            'download_export_form': self.download_export_form,
            'export_list': self.export_list,
            'form_or_case': self.form_or_case,
            'max_column_size': self.max_column_size,
            'show_date_range': self.show_date_range,
            'check_for_multimedia': self.check_for_multimedia,
            'sms_export': self.sms_export,
            'user_types': HQUserType.human_readable
        }
        if (self.default_datespan.startdate is not None
                and self.default_datespan.enddate is not None):
            context.update({
                'default_date_range':
                '{startdate}{separator}{enddate}'.format(
                    startdate=self.default_datespan.startdate.strftime(
                        '%Y-%m-%d'),
                    enddate=self.default_datespan.enddate.strftime('%Y-%m-%d'),
                    separator=DateRangePickerWidget.separator,
                ),
            })
        else:
            context.update({
                'default_date_range':
                _("You have no submissions in this project."),
                'show_no_submissions_warning':
                True,
            })
        if self.export_filter_class:
            context['dynamic_filters'] = self.export_filter_class(
                self.request, self.request.domain).render()
        return context

    @property
    @memoized
    def download_export_form(self):
        return self.view_helper.filter_form_class(self.domain_object,
                                                  timezone=self.timezone)

    @property
    def export_id(self):
        return self.kwargs.get('export_id')

    @property
    def page_url(self):
        if self.export_id:
            return reverse(self.urlname, args=(self.domain, self.export_id))
        return reverse(self.urlname, args=(self.domain, ))

    @property
    def export_list(self):
        exports = []
        if (self.request.method == 'POST'
                and 'export_list' in self.request.POST
                and not self.request.is_ajax()):
            raw_export_list = json.loads(self.request.POST['export_list'])
            exports = [
                self.view_helper.get_export(e['id']) for e in raw_export_list
            ]
        elif self.export_id or self.sms_export:
            exports = [self.view_helper.get_export(self.export_id)]

        if not self.permissions.has_view_permissions:
            if self.permissions.has_deid_view_permissions:
                exports = [x for x in exports if x.is_safe]
            else:
                raise Http404()

        # if there are no exports, this page doesn't exist
        if not exports:
            raise Http404()

        exports = [
            self.download_export_form.format_export_data(e) for e in exports
        ]
        return exports

    @property
    def max_column_size(self):
        try:
            return int(self.request.GET.get('max_column_size', 2000))
        except TypeError:
            return 2000
Example #14
0
class BaseDownloadExportView(HQJSONResponseMixin, BaseProjectDataView):
    template_name = 'export/download_export.html'
    http_method_names = ['get', 'post']
    show_date_range = False
    check_for_multimedia = False
    sms_export = False
    # To serve filters for export from mobile_user_and_group_slugs
    export_filter_class = None

    @use_daterangepicker
    @use_select2
    @method_decorator(login_and_domain_required)
    def dispatch(self, request, *args, **kwargs):
        self.permissions = ExportsPermissionsManager(self.form_or_case, request.domain, request.couch_user)
        self.permissions.access_download_export_or_404()

        return super(BaseDownloadExportView, self).dispatch(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        if not request.is_ajax():
            context = self.get_context_data(**kwargs)
            return self.render_to_response(context)
        return super(BaseDownloadExportView, self).post(request, *args, **kwargs)

    @property
    @memoized
    def view_helper(self):
        return DownloadExportViewHelper.get(self.request, self.domain, self.form_or_case, self.sms_export)

    @property
    @memoized
    def timezone(self):
        return get_timezone(self.domain, self.request.couch_user)

    @property
    @memoized
    def default_datespan(self):
        return datespan_from_beginning(self.domain_object, self.timezone)

    @property
    def page_context(self):
        context = {
            'download_export_form': self.download_export_form,
            'export_list': self.export_list,
            'form_or_case': self.form_or_case,
            'max_column_size': self.max_column_size,
            'show_date_range': self.show_date_range,
            'check_for_multimedia': self.check_for_multimedia,
            'sms_export': self.sms_export,
            'user_types': HQUserType.human_readable
        }
        if (
            self.default_datespan.startdate is not None
            and self.default_datespan.enddate is not None
        ):
            context.update({
                'default_date_range': '{startdate}{separator}{enddate}'.format(
                    startdate=self.default_datespan.startdate.strftime('%Y-%m-%d'),
                    enddate=self.default_datespan.enddate.strftime('%Y-%m-%d'),
                    separator=DateRangePickerWidget.separator,
                ),
            })
        else:
            context.update({
                'default_date_range': _(
                    "You have no submissions in this project."
                ),
                'show_no_submissions_warning': True,
            })
        if self.export_filter_class:
            context['dynamic_filters'] = self.export_filter_class(
                self.request, self.request.domain
            ).render()
        return context

    @property
    @memoized
    def download_export_form(self):
        return self.view_helper.filter_form_class(self.domain_object, timezone=self.timezone)

    @property
    def export_id(self):
        return self.kwargs.get('export_id')

    @property
    def page_url(self):
        if self.export_id:
            return reverse(self.urlname, args=(self.domain, self.export_id))
        return reverse(self.urlname, args=(self.domain,))

    @property
    def export_list(self):
        exports = []
        if (
            self.request.method == 'POST'
            and 'export_list' in self.request.POST
            and not self.request.is_ajax()
        ):
            raw_export_list = json.loads(self.request.POST['export_list'])
            exports = [self.view_helper.get_export(e['id']) for e in raw_export_list]
        elif self.export_id or self.sms_export:
            exports = [self.view_helper.get_export(self.export_id)]

        if not self.permissions.has_view_permissions:
            if self.permissions.has_deid_view_permissions:
                exports = [x for x in exports if x.is_safe]
            else:
                raise Http404()

        # if there are no exports, this page doesn't exist
        if not exports:
            raise Http404()

        exports = [self.download_export_form.format_export_data(e) for e in exports]
        return exports

    @property
    def max_column_size(self):
        try:
            return int(self.request.GET.get('max_column_size', 2000))
        except TypeError:
            return 2000