示例#1
0
 def test_get_document_or_404_not_found(self):
     """
     get_document_or_404 should raise 404 on ResourceNotFound
     """
     with mock_get_context():
         with self.assertRaises(Http404):
             get_document_or_404(MockModel, 'ham', '123')
示例#2
0
 def test_get_document_or_404_wrapping_error(self):
     """
     get_document_or_404 should raise 404 on WrappingAttributeError
     """
     with mock_wrap_context():
         with self.assertRaises(Http404):
             get_document_or_404(MockModel, 'ham', '123')
示例#3
0
def get_ledgers(request, domain):
    """
    Returns ledgers associated with a case in the format:
    {
        "section_id": {
            "product_id": amount,
            "product_id": amount,
            ...
        },
        ...
    }
    """
    case_id = request.REQUEST.get('case_id')
    if not case_id:
        return json_response(
            {'message': 'You must specify a case id to make this query.'},
            status_code=400)
    case = get_document_or_404(CommCareCase, domain, case_id)
    ledger_map = get_current_ledger_transactions(case._id)

    def custom_json_handler(obj):
        if isinstance(obj, StockTransaction):
            return obj.stock_on_hand
        return json_handler(obj)

    return json_response(
        {
            'entity_id': case_id,
            'ledger': ledger_map,
        },
        default=custom_json_handler,
    )
示例#4
0
    def rows(self):
        base_link_url = '{}?q={{id}}'.format(reverse('global_quick_find'))

        user_id = self.request.GET.get('individual')
        if not user_id:
            return []

        # security check
        get_document_or_404(CommCareUser, self.domain, user_id)

        sync_log_ids = [row['id'] for row in SyncLog.view(
            "phone/sync_logs_by_user",
            startkey=[user_id, {}],
            endkey=[user_id],
            descending=True,
            reduce=False,
            limit=10
        )]

        def _sync_log_to_row(sync_log):
            def _fmt_duration(duration):
                if isinstance(duration, int):
                    return format_datatables_data(
                        '<span class="{cls}">{text}</span>'.format(
                            cls=_bootstrap_class(duration or 0, 60, 20),
                            text=_('{} seconds').format(duration),
                        ),
                        duration
                    )
                else:
                    return format_datatables_data(
                        '<span class="label">{text}</span>'.format(
                            text=_("Unknown"),
                        ),
                        -1,
                    )

            def _fmt_id(sync_log_id):
                href = base_link_url.format(id=sync_log_id)
                return '<a href="{href}" target="_blank">{id:.5}...</a>'.format(
                    href=href,
                    id=sync_log_id
                )

            num_cases = len(sync_log.cases_on_phone)
            columns = [
                _fmt_date(sync_log.date),
                format_datatables_data(num_cases, num_cases),
                _fmt_duration(sync_log.duration),
            ]
            if self.show_extra_columns:
                columns.append(_fmt_id(sync_log.get_id))

            return columns

        return [
            _sync_log_to_row(SyncLog.wrap(sync_log_json))
            for sync_log_json in iter_docs(SyncLog.get_db(), sync_log_ids)
        ]
示例#5
0
def delete_report(request, domain, report_id):
    if not (toggle_enabled(request, toggles.USER_CONFIGURABLE_REPORTS)
            or toggle_enabled(request, toggles.REPORT_BUILDER)
            or toggle_enabled(request, toggles.REPORT_BUILDER_BETA_GROUP)
            or has_report_builder_add_on_privilege(request)):
        raise Http404()

    config = get_document_or_404(ReportConfiguration, domain, report_id)

    # Delete the data source too if it's not being used by any other reports.
    try:
        data_source, __ = get_datasource_config(config.config_id, domain)
    except DataSourceConfigurationNotFoundError:
        # It's possible the data source has already been deleted, but that's fine with us.
        pass
    else:
        if data_source.get_report_count() <= 1:
            # No other reports reference this data source.
            data_source.deactivate()

    config.delete()
    did_purge_something = purge_report_from_mobile_ucr(config)

    messages.success(request, _(u'Report "{}" deleted!').format(config.title))
    if did_purge_something:
        messages.warning(
            request,
            _(u"This report was used in one or more applications. "
              "It has been removed from there too.")
        )
    redirect = request.GET.get("redirect", None)
    if not redirect:
        redirect = reverse('configurable_reports_home', args=[domain])
    return HttpResponseRedirect(redirect)
示例#6
0
    def post(self, request, *args, **kwargs):
        if self.new_commcare_user_form.is_valid() and self.custom_data.is_valid():
            username = self.new_commcare_user_form.cleaned_data['username']
            password = self.new_commcare_user_form.cleaned_data['password']
            phone_number = self.new_commcare_user_form.cleaned_data['phone_number']

            if 'location_id' in request.GET:
                loc = get_document_or_404(Location, self.domain,
                                          request.GET.get('location_id'))

            user = CommCareUser.create(
                self.domain,
                username,
                password,
                phone_number=phone_number,
                device_id="Generated from HQ",
                user_data=self.custom_data.get_data_to_save(),
            )

            if 'location_id' in request.GET:
                user.set_location(loc)

            if phone_number:
                initiate_sms_verification_workflow(user, phone_number)

            user_json = {'user_id': user._id, 'text': user.username_in_report}
            return self.render_json_response({"status": "success",
                                              "user": user_json})
        return self.render_form("failure")
示例#7
0
    def post(self, request, *args, **kwargs):
        if self.new_commcare_user_form.is_valid(
        ) and self.custom_data.is_valid():
            username = self.new_commcare_user_form.cleaned_data['username']
            password = self.new_commcare_user_form.cleaned_data['password']
            phone_number = self.new_commcare_user_form.cleaned_data[
                'phone_number']

            if 'location_id' in request.GET:
                loc = get_document_or_404(Location, self.domain,
                                          request.GET.get('location_id'))

            couch_user = CommCareUser.create(
                self.domain,
                username,
                password,
                phone_number=phone_number,
                device_id="Generated from HQ",
                user_data=self.custom_data.get_data_to_save(),
            )

            if 'location_id' in request.GET:
                couch_user.set_location(loc)

            return HttpResponseRedirect(
                reverse(EditCommCareUserView.urlname,
                        args=[self.domain, couch_user.userID]))
        return self.get(request, *args, **kwargs)
示例#8
0
    def saved_report_context_data(self):
        def _get_context_for_saved_report(report_config):
            if report_config:
                report_config_data = report_config.to_json()
                report_config_data['filters'].update(
                    report_config.get_date_range())
                return report_config_data
            else:
                return ReportConfig.default()

        saved_report_config_id = self.request.GET.get('config_id')
        saved_report_config = get_document_or_404(ReportConfig, self.domain, saved_report_config_id) \
            if saved_report_config_id else None

        return {
            'report_configs': [
                _get_context_for_saved_report(saved_report) for saved_report in
                ReportConfig.by_domain_and_owner(self.domain,
                                                 self.request.couch_user._id,
                                                 report_slug=self.slug)
            ],
            'default_config':
            _get_context_for_saved_report(saved_report_config),
            'datespan_filters':
            ReportConfig.datespan_filter_choices(self.datespan_filters,
                                                 self.lang),
        }
示例#9
0
    def post(self, request, *args, **kwargs):
        if self.new_commcare_user_form.is_valid(
        ) and self.custom_data.is_valid():
            username = self.new_commcare_user_form.cleaned_data['username']
            password = self.new_commcare_user_form.cleaned_data['password']
            phone_number = self.new_commcare_user_form.cleaned_data[
                'phone_number']

            if 'location_id' in request.GET:
                loc = get_document_or_404(Location, self.domain,
                                          request.GET.get('location_id'))

            user = CommCareUser.create(
                self.domain,
                username,
                password,
                phone_number=phone_number,
                device_id="Generated from HQ",
                user_data=self.custom_data.get_data_to_save(),
            )

            if 'location_id' in request.GET:
                user.set_location(loc)

            if phone_number:
                initiate_sms_verification_workflow(user, phone_number)

            user_json = {'user_id': user._id, 'text': user.username_in_report}
            return self.render_json_response({
                "status": "success",
                "user": user_json
            })
        return self.render_form("failure")
示例#10
0
def choice_list_api(request, domain, report_id, filter_id):
    report = get_document_or_404(ReportConfiguration, domain, report_id)
    filter = report.get_ui_filter(filter_id)
    if filter is None:
        raise Http404(_(u'Filter {} not found!').format(filter_id))

    def get_choices(data_source, filter, search_term=None, limit=20, page=0):
        # todo: we may want to log this as soon as mobile UCR stops hitting this
        # for misconfigured filters
        if not isinstance(filter, DynamicChoiceListFilter):
            return []

        table = get_indicator_table(data_source)
        sql_column = table.c[filter.field]
        query = Session.query(sql_column)
        if search_term:
            query = query.filter(sql_column.contains(search_term))

        offset = page * limit
        try:
            return [
                v[0] for v in query.distinct().order_by(sql_column).limit(
                    limit).offset(offset)
            ]
        except ProgrammingError:
            return []

    return json_response(
        get_choices(report.config,
                    filter,
                    request.GET.get('q', None),
                    limit=int(request.GET.get('limit', 20)),
                    page=int(request.GET.get('page', 1)) - 1))
示例#11
0
def delete_report(request, domain, report_id):
    if not (toggle_enabled(request, toggles.USER_CONFIGURABLE_REPORTS)
            or toggle_enabled(request, toggles.REPORT_BUILDER)
            or toggle_enabled(request, toggles.REPORT_BUILDER_BETA_GROUP)
            or has_report_builder_add_on_privilege(request)):
        raise Http404()

    config = get_document_or_404(ReportConfiguration, domain, report_id)

    # Delete the data source too if it's not being used by any other reports.
    try:
        data_source, __ = get_datasource_config(config.config_id, domain)
    except DataSourceConfigurationNotFoundError:
        # It's possible the data source has already been deleted, but that's fine with us.
        pass
    else:
        if data_source.get_report_count() <= 1:
            # No other reports reference this data source.
            data_source.deactivate()

    config.delete()
    did_purge_something = purge_report_from_mobile_ucr(config)

    messages.success(request, _(u'Report "{}" deleted!').format(config.title))
    if did_purge_something:
        messages.warning(
            request,
            _(u"This report was used in one or more applications. "
              "It has been removed from there too."))
    redirect = request.GET.get("redirect", None)
    if not redirect:
        redirect = reverse('configurable_reports_home', args=[domain])
    return HttpResponseRedirect(redirect)
示例#12
0
def export_data_source(request, domain, config_id):
    config = get_document_or_404(DataSourceConfiguration, domain, config_id)
    adapter = IndicatorSqlAdapter(config)
    q = adapter.get_query_object()
    table = adapter.get_table()

    try:
        params = process_url_params(request.GET, table.columns)
    except UserQueryError as e:
        return HttpResponse(e.message, status=400)

    q = q.filter_by(**params.keyword_filters)
    for sql_filter in params.sql_filters:
        q = q.filter(sql_filter)

    # build export
    def get_table(q):
        yield table.columns.keys()
        for row in q:
            yield row

    fd, path = tempfile.mkstemp()
    with os.fdopen(fd, 'wb') as tmpfile:
        try:
            tables = [[config.table_id, get_table(q)]]
            export_from_tables(tables, tmpfile, params.format)
        except exc.DataError:
            msg = _("There was a problem executing your query, please make "
                    "sure your parameters are valid.")
            return HttpResponse(msg, status=400)
        return export_response(Temp(path), params.format, config.display_name)
示例#13
0
    def saved_report_context_data(self):
        def _get_context_for_saved_report(report_config):
            if report_config:
                report_config_data = report_config.to_json()
                report_config_data['filters'].update(report_config.get_date_range())
                return report_config_data
            else:
                return ReportConfig.default()

        saved_report_config_id = self.request.GET.get('config_id')
        saved_report_config = get_document_or_404(ReportConfig, self.domain, saved_report_config_id) \
            if saved_report_config_id else None

        datespan_filters = []
        for f in self.datespan_filters:
            copy = dict(f)
            copy['display'] = localize(copy['display'], self.lang)
            datespan_filters.append(copy)

        return {
            'report_configs': [
                _get_context_for_saved_report(saved_report)
                for saved_report in ReportConfig.by_domain_and_owner(
                    self.domain, self.request.couch_user._id, report_slug=self.slug
                )
            ],
            'default_config': _get_context_for_saved_report(saved_report_config),
            'datespan_filters': [{
                'display': _('Choose a date filter...'),
                'slug': None,
            }] + datespan_filters,
        }
示例#14
0
def export_data_source(request, domain, config_id):
    config = get_document_or_404(DataSourceConfiguration, domain, config_id)
    adapter = IndicatorSqlAdapter(config)
    q = adapter.get_query_object()
    table = adapter.get_table()

    try:
        params = process_url_params(request.GET, table.columns)
    except UserQueryError as e:
        return HttpResponse(e.message, status=400)

    q = q.filter_by(**params.keyword_filters)
    for sql_filter in params.sql_filters:
        q = q.filter(sql_filter)

    # build export
    def get_table(q):
        yield table.columns.keys()
        for row in q:
            yield row

    fd, path = tempfile.mkstemp()
    with os.fdopen(fd, 'wb') as tmpfile:
        try:
            tables = [[config.table_id, get_table(q)]]
            export_from_tables(tables, tmpfile, params.format)
        except exc.DataError:
            msg = _("There was a problem executing your query, please make "
                    "sure your parameters are valid.")
            return HttpResponse(msg, status=400)
        return export_response(Temp(path), params.format, config.display_name)
示例#15
0
def get_ledgers(request, domain):
    """
    Returns ledgers associated with a case in the format:
    {
        "section_id": {
            "product_id": amount,
            "product_id": amount,
            ...
        },
        ...
    }
    """
    case_id = request.REQUEST.get('case_id')
    if not case_id:
        return json_response(
            {'message': 'You must specify a case id to make this query.'},
            status_code=400
        )
    case = get_document_or_404(CommCareCase, domain, case_id)
    ledger_map = get_current_ledger_transactions(case._id)
    def custom_json_handler(obj):
        if isinstance(obj, StockTransaction):
            return obj.stock_on_hand
        return json_handler(obj)

    return json_response(
        {
            'entity_id': case_id,
            'ledger': ledger_map,
        },
        default=custom_json_handler,
    )
示例#16
0
def _delete_data_source_shared(request, domain, config_id):
    config = get_document_or_404(DataSourceConfiguration, domain, config_id)
    adapter = IndicatorSqlAdapter(get_engine(), config)
    adapter.drop_table()
    config.delete()
    messages.success(request,
                     _(u'Data source "{}" has been deleted.'.format(config.display_name)))
示例#17
0
def choice_list_api(request, domain, report_id, filter_id):
    report = get_document_or_404(ReportConfiguration, domain, report_id)
    filter = report.get_ui_filter(filter_id)
    if filter is None:
        raise Http404(_(u'Filter {} not found!').format(filter_id))

    def get_choices(data_source, filter, search_term=None, limit=20, page=0):
        # todo: we may want to log this as soon as mobile UCR stops hitting this
        # for misconfigured filters
        if not isinstance(filter, DynamicChoiceListFilter):
            return []

        table = get_indicator_table(data_source)
        sql_column = table.c[filter.field]
        query = Session.query(sql_column)
        if search_term:
            query = query.filter(sql_column.contains(search_term))

        offset = page * limit
        try:
            return [v[0] for v in query.distinct().order_by(sql_column).limit(limit).offset(offset)]
        except ProgrammingError:
            return []

    return json_response(get_choices(
        report.config,
        filter,
        request.GET.get('q', None),
        limit=int(request.GET.get('limit', 20)),
        page=int(request.GET.get('page', 1)) - 1
    ))
示例#18
0
def delete_data_source(request, domain, config_id):
    config = get_document_or_404(DataSourceConfiguration, domain, config_id)
    adapter = IndicatorSqlAdapter(get_engine(), config)
    adapter.drop_table()
    config.delete()
    messages.success(request,
                     _(u'Data source "{}" has been deleted.'.format(config.display_name)))
    return HttpResponseRedirect(reverse('configurable_reports_home', args=[domain]))
示例#19
0
    def rows(self):
        user_id = self.request.GET.get('individual')
        if not user_id:
            return []

        # security check
        get_document_or_404(CommCareUser, self.domain, user_id)

        sync_log_ids = [row['id'] for row in SyncLog.view(
            "phone/sync_logs_by_user",
            startkey=[user_id, {}],
            endkey=[user_id],
            descending=True,
            reduce=False,
        )]

        def _sync_log_to_row(sync_log):
            def _fmt_duration(duration):
                if isinstance(duration, int):
                    return format_datatables_data(
                        '<span class="{cls}">{text}</span>'.format(
                            cls=_bootstrap_class(duration or 0, 20, 60),
                            text=_('{} seconds').format(duration),
                        ),
                        duration
                    )
                else:
                    return format_datatables_data(
                        '<span class="label">{text}</span>'.format(
                            text=_("Unknown"),
                        ),
                        -1,
                    )

            num_cases = len(sync_log.cases_on_phone)
            return [
                _fmt_date(sync_log.date),
                format_datatables_data(num_cases, num_cases),
                _fmt_duration(sync_log.duration),
            ]

        return [
            _sync_log_to_row(SyncLog.wrap(sync_log_json))
            for sync_log_json in iter_docs(SyncLog.get_db(), sync_log_ids)
        ]
示例#20
0
def get_datasource_config_or_404(config_id, domain):
    is_static = config_id.startswith(CustomDataSourceConfiguration._datasource_id_prefix)
    if is_static:
        config = CustomDataSourceConfiguration.by_id(config_id)
        if not config or config.domain != domain:
            raise Http404()
    else:
        config = get_document_or_404(DataSourceConfiguration, domain, config_id)
    return config, is_static
示例#21
0
def delete_data_source_shared(domain, config_id, request=None):
    config = get_document_or_404(DataSourceConfiguration, domain, config_id)
    adapter = get_indicator_adapter(config)
    adapter.drop_table()
    config.delete()
    if request:
        messages.success(
            request,
            _(u'Data source "{}" has been deleted.'.format(
                config.display_name)))
示例#22
0
def delete_data_source_shared(domain, config_id, request=None):
    config = get_document_or_404(DataSourceConfiguration, domain, config_id)
    adapter = get_indicator_adapter(config)
    adapter.drop_table()
    config.delete()
    if request:
        messages.success(
            request,
            _(u'Data source "{}" has been deleted.'.format(config.display_name))
        )
示例#23
0
def rebuild_data_source(request, domain, config_id):
    config = get_document_or_404(DataSourceConfiguration, domain, config_id)
    messages.success(
        request,
        _('Table "{}" is now being rebuilt. Data should start showing up soon').format(
            config.display_name
        )
    )
    rebuild_indicators.delay(config_id)
    return HttpResponseRedirect(reverse('edit_configurable_data_source', args=[domain, config._id]))
示例#24
0
def undo_close_case_view(request, domain, case_id):
    case = get_document_or_404(CommCareCase, domain, case_id)
    if not case.closed:
        messages.info(request, u'Case {} is not closed.'.format(case.name))
    else:
        closing_form_id = request.POST['closing_form']
        assert closing_form_id in case.xform_ids
        form = XFormInstance.get(closing_form_id)
        form.archive(user=request.couch_user._id)
        messages.success(request, u'Case {} has been reopened.'.format(case.name))
    return HttpResponseRedirect(reverse('case_details', args=[domain, case_id]))
示例#25
0
def get_datasource_config_or_404(config_id, domain):
    is_static = config_id.startswith(
        CustomDataSourceConfiguration._datasource_id_prefix)
    if is_static:
        config = CustomDataSourceConfiguration.by_id(config_id)
        if not config or config.domain != domain:
            raise Http404()
    else:
        config = get_document_or_404(DataSourceConfiguration, domain,
                                     config_id)
    return config, is_static
示例#26
0
def preview_data_source(request, domain, config_id):
    config = get_document_or_404(DataSourceConfiguration, domain, config_id)
    table = get_indicator_table(config)

    q = Session.query(table)
    context = _shared_context(domain)
    context.update({
        'data_source': config,
        'columns': q.column_descriptions,
        'data': q[:20],
    })
    return render(request, "userreports/preview_data.html", context)
示例#27
0
 def dispatch(self, request, *args, **kwargs):
     report_id = kwargs['report_id']
     report = get_document_or_404(ReportConfiguration, request.domain, report_id)
     if report.report_meta.created_by_builder:
         view_class = {
             'chart': ConfigureChartReport,
             'list': ConfigureListReport,
             'worker': ConfigureWorkerReport,
             'table': ConfigureTableReport
         }[report.report_meta.builder_report_type]
         return view_class.as_view(existing_report=report)(request, *args, **kwargs)
     raise Http404("Report was not created by the report builder")
示例#28
0
def choice_list_api(request, domain, report_id, filter_id):
    report = get_document_or_404(ReportConfiguration, domain, report_id)
    filter = report.get_ui_filter(filter_id)

    def get_choices(data_source, filter, search_term=None, limit=20):
        table = get_indicator_table(data_source)
        sql_column = table.c[filter.name]
        query = Session.query(sql_column)
        if search_term:
            query = query.filter(sql_column.contains(search_term))

        return [v[0] for v in query.distinct().limit(limit)]

    return json_response(get_choices(report.config, filter, request.GET.get('q', None)))
示例#29
0
 def dispatch(self, request, *args, **kwargs):
     report_id = kwargs['report_id']
     report = get_document_or_404(ReportConfiguration, request.domain, report_id)
     if report.report_meta.created_by_builder:
         view_class = {
             'chart': ConfigureChartReport,
             'list': ConfigureListReport,
             'worker': ConfigureWorkerReport,
             'table': ConfigureTableReport
         }[report.report_meta.builder_report_type]
         try:
             return view_class.as_view(existing_report=report)(request, *args, **kwargs)
         except BadBuilderConfigError as e:
             messages.error(request, e.message)
             return HttpResponseRedirect(reverse(ConfigurableReport.slug, args=[request.domain, report_id]))
     raise Http404("Report was not created by the report builder")
示例#30
0
def case_details(request, domain, case_id):
    timezone = util.get_timezone(request.couch_user, domain)

    try:
        case = get_document_or_404(CommCareCase, domain, case_id)
    except Http404:
        messages.info(
            request, "Sorry, we couldn't find that case. If you think this is a mistake please report an issue."
        )
        return HttpResponseRedirect(CaseListReport.get_url(domain=domain))

    try:
        owner_name = CommCareUser.get_by_user_id(case.owner_id, domain).raw_username
    except Exception:
        try:
            owning_group = Group.get(case.owner_id)
            owner_name = owning_group.display_name if owning_group.domain == domain else ""
        except Exception:
            owner_name = None

    try:
        username = CommCareUser.get_by_user_id(case.user_id, domain).raw_username
    except Exception:
        username = None

    return render(
        request,
        "reports/reportdata/case_details.html",
        {
            "domain": domain,
            "case_id": case_id,
            "case": case,
            "username": username,
            "owner_name": owner_name,
            "slug": CaseListReport.slug,
            "report": dict(name=case_inline_display(case), slug=CaseListReport.slug, is_async=False),
            "layout_flush_content": True,
            "timezone": timezone,
            "case_display_options": {
                "display": request.project.get_case_display(case),
                "timezone": timezone,
                "get_case_url": lambda case_id: reverse(case_details, args=[domain, case_id]),
            },
            "show_case_rebuild": toggles.CASE_REBUILD.enabled(request.user.username),
        },
    )
示例#31
0
def close_case_view(request, domain, case_id):
    case = get_document_or_404(CommCareCase, domain, case_id)
    if case.closed:
        messages.info(request, u'Case {} is already closed.'.format(case.name))
    else:
        form_id = close_case(case_id, domain, request.couch_user)
        msg = _(u'''Case {name} has been closed.
            <a href="javascript:document.getElementById('{html_form_id}').submit();">Undo</a>.
            You can also reopen the case in the future by archiving the last form in the case history.
            <form id="{html_form_id}" action="{url}" method="POST">
                <input type="hidden" name="closing_form" value="{xform_id}" />
            </form>
        '''.format(
            name=case.name,
            html_form_id='undo-close-case',
            xform_id=form_id,
            url=reverse('undo_close_case', args=[domain, case_id]),
        ))
        messages.success(request, mark_safe(msg), extra_tags='html')
    return HttpResponseRedirect(reverse('case_details', args=[domain, case_id]))
示例#32
0
def delete_report(request, domain, report_id):
    config = get_document_or_404(ReportConfiguration, domain, report_id)

    # Delete the data source too if it's not being used by any other reports.
    data_source, __ = get_datasource_config_or_404(config.config_id, domain)
    if data_source.get_report_count() <= 1:
        # No other reports reference this data source.
        try:
            delete_data_source_shared(domain, data_source._id, request)
        except Http404:
            # It's possible the data source has already been deleted, but
            # that's fine with us.
            pass

    config.delete()
    messages.success(request, _(u'Report "{}" deleted!').format(config.title))
    redirect = request.GET.get("redirect", None)
    if not redirect:
        redirect = reverse('configurable_reports_home', args=[domain])
    return HttpResponseRedirect(redirect)
示例#33
0
def delete_report(request, domain, report_id):
    config = get_document_or_404(ReportConfiguration, domain, report_id)

    # Delete the data source too if it's not being used by any other reports.
    data_source, __ = get_datasource_config_or_404(config.config_id, domain)
    if data_source.get_report_count() <= 1:
        # No other reports reference this data source.
        try:
            data_source.deactivate()
        except Http404:
            # It's possible the data source has already been deleted, but
            # that's fine with us.
            pass

    config.delete()
    messages.success(request, _(u'Report "{}" deleted!').format(config.title))
    redirect = request.GET.get("redirect", None)
    if not redirect:
        redirect = reverse('configurable_reports_home', args=[domain])
    return HttpResponseRedirect(redirect)
示例#34
0
def export_case_transactions(request, domain, case_id):
    case = get_document_or_404(CommCareCase, domain, case_id)
    products_by_id = dict(SQLProduct.objects.filter(domain=domain).values_list('product_id', 'name'))

    headers = [
        _('case id'),
        _('case name'),
        _('section'),
        _('date'),
        _('product_id'),
        _('product_name'),
        _('transaction amount'),
        _('type'),
        _('ending balance'),
    ]

    def _make_row(transaction):
        return [
            transaction.case_id,
            case.name,
            transaction.section_id,
            transaction.report.date if transaction.report_id else '',
            transaction.product_id,
            products_by_id.get(transaction.product_id, _('unknown product')),
            transaction.quantity,
            transaction.type,
            transaction.stock_on_hand,
        ]

    query_set = StockTransaction.objects.select_related('report')\
        .filter(case_id=case_id).order_by('section_id', 'report__date')

    formatted_table = [
        [
            'stock transactions',
            [headers] + [_make_row(txn) for txn in query_set]
        ]
    ]
    tmp = StringIO()
    export_from_tables(formatted_table, tmp, 'xlsx')
    return export_response(tmp, 'xlsx', '{}-stock-transactions'.format(case.name))
示例#35
0
 def dispatch(self, request, *args, **kwargs):
     report_id = kwargs['report_id']
     report = get_document_or_404(ReportConfiguration, request.domain,
                                  report_id)
     if report.report_meta.created_by_builder:
         view_class = {
             'chart': ConfigureChartReport,
             'list': ConfigureListReport,
             'worker': ConfigureWorkerReport,
             'table': ConfigureTableReport
         }[report.report_meta.builder_report_type]
         try:
             return view_class.as_view(existing_report=report)(request,
                                                               *args,
                                                               **kwargs)
         except BadBuilderConfigError as e:
             messages.error(request, e.message)
             return HttpResponseRedirect(
                 reverse(ConfigurableReport.slug,
                         args=[request.domain, report_id]))
     raise Http404("Report was not created by the report builder")
示例#36
0
    def post(self, request, *args, **kwargs):
        if self.new_commcare_user_form.is_valid() and self.custom_data.is_valid():
            username = self.new_commcare_user_form.cleaned_data["username"]
            password = self.new_commcare_user_form.cleaned_data["password"]
            phone_number = self.new_commcare_user_form.cleaned_data["phone_number"]

            if "location_id" in request.GET:
                loc = get_document_or_404(Location, self.domain, request.GET.get("location_id"))

            couch_user = CommCareUser.create(
                self.domain,
                username,
                password,
                phone_number=phone_number,
                device_id="Generated from HQ",
                user_data=self.custom_data.get_data_to_save(),
            )

            if "location_id" in request.GET:
                couch_user.set_location(loc)

            return HttpResponseRedirect(reverse(EditCommCareUserView.urlname, args=[self.domain, couch_user.userID]))
        return self.get(request, *args, **kwargs)
示例#37
0
    def saved_report_context_data(self):
        def _get_context_for_saved_report(report_config):
            if report_config:
                report_config_data = report_config.to_json()
                report_config_data['filters'].update(report_config.get_date_range())
                return report_config_data
            else:
                return ReportConfig.default()

        saved_report_config_id = self.request.GET.get('config_id')
        saved_report_config = get_document_or_404(ReportConfig, self.domain, saved_report_config_id) \
            if saved_report_config_id else None

        return {
            'report_configs': [
                _get_context_for_saved_report(saved_report)
                for saved_report in ReportConfig.by_domain_and_owner(
                    self.domain, self.request.couch_user._id, report_slug=self.slug
                )
            ],
            'default_config': _get_context_for_saved_report(saved_report_config),
            'datespan_filters': ReportConfig.datespan_filter_choices(self.datespan_filters, self.lang),
        }
示例#38
0
def export_data_source(request, domain, config_id):
    format = request.GET.get('format', Format.UNZIPPED_CSV)
    config = get_document_or_404(DataSourceConfiguration, domain, config_id)
    table = get_indicator_table(config)
    q = Session.query(table)
    column_headers = [col['name'] for col in q.column_descriptions]

    # apply filtering if any
    filter_values = {key: value for key, value in request.GET.items() if key != 'format'}
    for key in filter_values:
        if key not in column_headers:
            return HttpResponse('Invalid filter parameter: {}'.format(key), status=400)
    q = q.filter_by(**filter_values)

    # build export
    def get_table(q):
        yield column_headers
        for row in q:
            yield row

    fd, path = tempfile.mkstemp()
    with os.fdopen(fd, 'wb') as temp:
        export_from_tables([[config.table_id, get_table(q)]], temp, format)
        return export_response(Temp(path), format, config.display_name)
示例#39
0
def choice_list_api(request, domain, report_id, filter_id):
    report = get_document_or_404(ReportConfiguration, domain, report_id)
    filter = report.get_ui_filter(filter_id)

    def get_choices(data_source, filter, search_term=None, limit=20, page=0):
        table = get_indicator_table(data_source)
        sql_column = table.c[filter.field]
        query = Session.query(sql_column)
        if search_term:
            query = query.filter(sql_column.contains(search_term))

        offset = page * limit
        try:
            return [v[0] for v in query.distinct().order_by(sql_column).limit(limit).offset(offset)]
        except ProgrammingError:
            return []

    return json_response(get_choices(
        report.config,
        filter,
        request.GET.get('q', None),
        limit=int(request.GET.get('limit', 20)),
        page=int(request.GET.get('page', 1)) - 1
    ))
示例#40
0
def delete_report(request, domain, report_id):
    config = get_document_or_404(ReportConfiguration, domain, report_id)

    # Delete the data source too if it's not being used by any other reports.
    data_source_id = config.config_id

    report_count = ReportConfiguration.view(
        'userreports/report_configs_by_data_source',
        reduce=True,
        key=[domain, data_source_id]
    ).one()['value']

    if report_count <= 1:
        # No other reports reference this data source.
        try:
            _delete_data_source_shared(request, domain, data_source_id)
        except Http404:
            # It's possible the data source has already been deleted, but
            # that's fine with us.
            pass

    config.delete()
    messages.success(request, _(u'Report "{}" deleted!').format(config.title))
    return HttpResponseRedirect(reverse('configurable_reports_home', args=[domain]))
示例#41
0
def report_source_json(request, domain, report_id):
    config = get_document_or_404(ReportConfiguration, domain, report_id)
    del config._doc['_rev']
    return json_response(config)
示例#42
0
def data_source_status(request, domain, config_id):
    config = get_document_or_404(DataSourceConfiguration, domain, config_id)
    return json_response({'isBuilt': config.meta.build.finished})
示例#43
0
 def editable_user(self):
     try:
         return get_document_or_404(WebUser, self.domain,
                                    self.editable_user_id)
     except (ResourceNotFound, CouchUser.AccountTypeError):
         raise Http404()
示例#44
0
def edit_report(request, domain, report_id):
    config = get_document_or_404(ReportConfiguration, domain, report_id)
    return _edit_report_shared(request, domain, config)
示例#45
0
def get_query_results(export_instance, domain, id):
    export = get_document_or_404(export_instance, domain, id)
    query = get_case_export_base_query(domain, export.case_type)
    results = query.run()
    return results
示例#46
0
    def rows(self):
        base_link_url = '{}?q={{id}}'.format(reverse('global_quick_find'))

        user_id = self.request.GET.get('individual')
        if not user_id:
            return []

        # security check
        get_document_or_404(CommCareUser, self.domain, user_id)

        sync_log_ids = [
            row['id'] for row in SyncLog.view(
                "phone/sync_logs_by_user",
                startkey=[user_id, {}],
                endkey=[user_id],
                descending=True,
                reduce=False,
                limit=self.limit,
            )
        ]

        def _sync_log_to_row(sync_log):
            def _fmt_duration(duration):
                if isinstance(duration, int):
                    return format_datatables_data(
                        '<span class="{cls}">{text}</span>'.format(
                            cls=_bootstrap_class(duration or 0, 60, 20),
                            text=_('{} seconds').format(duration),
                        ), duration)
                else:
                    return format_datatables_data(
                        '<span class="label">{text}</span>'.format(
                            text=_("Unknown"), ),
                        -1,
                    )

            def _fmt_id(sync_log_id):
                href = base_link_url.format(id=sync_log_id)
                return '<a href="{href}" target="_blank">{id:.5}...</a>'.format(
                    href=href, id=sync_log_id)

            def _fmt_error_info(sync_log):
                if not sync_log.had_state_error:
                    return u'<span class="label label-success">&#10003;</span>'
                else:
                    return (
                        u'<span class="label label-important">X</span>'
                        u'State error {}<br>Expected hash: {:.10}...').format(
                            _naturaltime_with_hover(sync_log.error_date),
                            sync_log.error_hash,
                        )

            num_cases = sync_log.case_count()
            columns = [
                _fmt_date(sync_log.date),
                format_datatables_data(num_cases, num_cases),
                _fmt_duration(sync_log.duration),
            ]
            if self.show_extra_columns:
                columns.append(_fmt_id(sync_log.get_id))
                columns.append(sync_log.log_format)
                columns.append(
                    _fmt_id(sync_log.previous_log_id) if sync_log.
                    previous_log_id else '---')
                columns.append(_fmt_error_info(sync_log))
                columns.append('{:.10}...'.format(sync_log.get_state_hash()))
                columns.append(_naturaltime_with_hover(
                    sync_log.last_submitted))
                columns.append(u'{}<br>{:.10}'.format(
                    _naturaltime_with_hover(sync_log.last_cached),
                    sync_log.hash_at_last_cached))

            return columns

        return [
            _sync_log_to_row(properly_wrap_sync_log(sync_log_json))
            for sync_log_json in iter_docs(SyncLog.get_db(), sync_log_ids)
        ]
示例#47
0
                request.project.get_case_display(case),
                "timezone":
                timezone,
                "get_case_url":
                lambda case_id: reverse(case_details, args=[domain, case_id])
            },
            "show_case_rebuild":
            toggles.CASE_REBUILD.enabled(request.user.username),
        })


@require_case_view_permission
@login_and_domain_required
@require_GET
def case_xml(request, domain, case_id):
    case = get_document_or_404(CommCareCase, domain, case_id)
    version = request.GET.get('version', V2)
    return HttpResponse(case.to_xml(version), content_type='text/xml')


@require_case_view_permission
@require_permission(Permissions.edit_data)
@require_POST
def rebuild_case_view(request, domain, case_id):
    case = get_document_or_404(CommCareCase, domain, case_id)
    rebuild_case(case_id)
    messages.success(request,
                     _(u'Case %s was rebuilt from its forms.' % case.name))
    return HttpResponseRedirect(reverse('case_details', args=[domain,
                                                              case_id]))
示例#48
0
def case_details(request, domain, case_id):
    timezone = util.get_timezone(request.couch_user, domain)

    try:
        case = get_document_or_404(CommCareCase, domain, case_id)
示例#49
0
 def saved_report_config(self):
     config_id = self.request.GET.get('config_id')
     return get_document_or_404(ReportConfig, self.domain,
                                config_id) if config_id else None
示例#50
0
 def editable_user(self):
     try:
         return get_document_or_404(WebUser, self.domain, self.editable_user_id)
     except (ResourceNotFound, CouchUser.AccountTypeError):
         raise Http404()
示例#51
0
    def rows(self):
        base_link_url = '{}?id={{id}}'.format(reverse('raw_couch'))

        user_id = self.request.GET.get('individual')
        if not user_id:
            return []

        # security check
        get_document_or_404(CommCareUser, self.domain, user_id)

        def _sync_log_to_row(sync_log):
            def _fmt_duration(duration):
                if isinstance(duration, int):
                    return format_datatables_data(
                        '<span class="{cls}">{text}</span>'.format(
                            cls=_bootstrap_class(duration or 0, 60, 20),
                            text=_('{} seconds').format(duration),
                        ),
                        duration
                    )
                else:
                    return format_datatables_data(
                        '<span class="label label-default">{text}</span>'.format(
                            text=_("Unknown"),
                        ),
                        -1,
                    )

            def _fmt_id(sync_log_id):
                href = base_link_url.format(id=sync_log_id)
                return '<a href="{href}" target="_blank">{id:.5}...</a>'.format(
                    href=href,
                    id=sync_log_id
                )

            def _fmt_error_info(sync_log):
                if not sync_log.had_state_error:
                    return u'<span class="label label-success">&#10003;</span>'
                else:
                    return (u'<span class="label label-danger">X</span>'
                            u'State error {}<br>Expected hash: {:.10}...').format(
                        _naturaltime_with_hover(sync_log.error_date),
                        sync_log.error_hash,
                    )

            def _get_state_hash_display(sync_log):
                try:
                    return u'{:.10}...'.format(sync_log.get_state_hash())
                except SyncLogAssertionError as e:
                    return _(u'Error computing hash! {}').format(e)

            num_cases = sync_log.case_count()
            columns = [
                _fmt_date(sync_log.date),
                format_datatables_data(num_cases, num_cases),
                _fmt_duration(sync_log.duration),
            ]
            if self.show_extra_columns:
                columns.append(_fmt_id(sync_log.get_id))
                columns.append(sync_log.log_format)
                columns.append(_fmt_id(sync_log.previous_log_id) if sync_log.previous_log_id else '---')
                columns.append(_fmt_error_info(sync_log))
                columns.append(_get_state_hash_display(sync_log))
                columns.append(_naturaltime_with_hover(sync_log.last_submitted))
                columns.append(u'{}<br>{:.10}'.format(_naturaltime_with_hover(sync_log.last_cached),
                                                      sync_log.hash_at_last_cached))

            return columns

        return [_sync_log_to_row(sync_log)
                for sync_log in get_sync_logs_for_user(user_id, self.limit)]