Пример #1
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),
        }
Пример #2
0
def add_config(request, domain=None):
    # todo: refactor this into a django form
    from datetime import datetime
    user_id = request.couch_user._id

    POST = json.loads(request.raw_post_data)
    if 'name' not in POST or not POST['name']:
        return HttpResponseBadRequest()

    user_configs = ReportConfig.by_domain_and_owner(domain, user_id)
    if not POST.get('_id') and POST['name'] in [c.name for c in user_configs]:
        return HttpResponseBadRequest()

    to_date = lambda s: datetime.strptime(s, '%Y-%m-%d').date() if s else s
    try:
        POST['start_date'] = to_date(POST['start_date'])
        POST['end_date'] = to_date(POST['end_date'])
    except ValueError:
        # invalidly formatted date input
        return HttpResponseBadRequest()

    date_range = POST.get('date_range')
    if date_range == 'last7':
        POST['days'] = 7
    elif date_range == 'last30':
        POST['days'] = 30
    elif POST.get('days'):
        POST['days'] = int(POST['days'])

    exclude_filters = ['startdate', 'enddate']
    for field in exclude_filters:
        POST['filters'].pop(field, None)

    config = ReportConfig.get_or_create(POST.get('_id', None))

    if config.owner_id:
        # in case a user maliciously tries to edit another user's config
        assert config.owner_id == user_id
    else:
        config.domain = domain
        config.owner_id = user_id

    for field in config.properties().keys():
        if field in POST:
            setattr(config, field, POST[field])

    if POST.get(
            'days'
    ) or date_range == 'lastmonth':  # remove start and end date if the date range is "last xx days"
        if "start_date" in config:
            delattr(config, "start_date")
        if "end_date" in config:
            delattr(config, "end_date")

    config.save()

    touch_saved_reports_views(request.couch_user, domain)

    return json_response(config)
Пример #3
0
def add_config(request, domain=None):
    # todo: refactor this into a django form
    from datetime import datetime

    user_id = request.couch_user._id

    POST = json.loads(request.raw_post_data)
    if "name" not in POST or not POST["name"]:
        return HttpResponseBadRequest()

    user_configs = ReportConfig.by_domain_and_owner(domain, user_id)
    if not POST.get("_id") and POST["name"] in [c.name for c in user_configs]:
        return HttpResponseBadRequest()

    to_date = lambda s: datetime.strptime(s, "%Y-%m-%d").date() if s else s
    try:
        POST["start_date"] = to_date(POST["start_date"])
        POST["end_date"] = to_date(POST["end_date"])
    except ValueError:
        # invalidly formatted date input
        return HttpResponseBadRequest()

    date_range = POST.get("date_range")
    if date_range == "last7":
        POST["days"] = 7
    elif date_range == "last30":
        POST["days"] = 30
    elif POST.get("days"):
        POST["days"] = int(POST["days"])

    exclude_filters = ["startdate", "enddate"]
    for field in exclude_filters:
        POST["filters"].pop(field, None)

    config = ReportConfig.get_or_create(POST.get("_id", None))

    if config.owner_id:
        # in case a user maliciously tries to edit another user's config
        assert config.owner_id == user_id
    else:
        config.domain = domain
        config.owner_id = user_id

    for field in config.properties().keys():
        if field in POST:
            setattr(config, field, POST[field])

    if POST.get("days") or date_range == "lastmonth":  # remove start and end date if the date range is "last xx days"
        if "start_date" in config:
            delattr(config, "start_date")
        if "end_date" in config:
            delattr(config, "end_date")

    config.save()

    touch_saved_reports_views(request.couch_user, domain)

    return json_response(config)
Пример #4
0
def touch_saved_reports_views(user, domain):
    """
    Hit the saved reports views so stale=update_after doesn't cause the user to
    see old or deleted data after a change when they next load the reports
    homepage.

    """
    ReportConfig.by_domain_and_owner(domain, user._id, limit=1, stale=False)
    ReportNotification.by_domain_and_owner(domain, user._id, limit=1, stale=False)
Пример #5
0
def touch_saved_reports_views(user, domain):
    """
    Hit the saved reports views so stale=update_after doesn't cause the user to
    see old or deleted data after a change when they next load the reports
    homepage.

    """
    ReportConfig.by_domain_and_owner(domain, user._id, limit=1).all()
    ReportNotification.by_domain_and_owner(domain, user._id, limit=1).all()
Пример #6
0
    def _update_initial_context(self):
        """
            Intention: Don't override.
        """
        report_configs = ReportConfig.by_domain_and_owner(self.domain,
            self.request.couch_user._id, report_slug=self.slug)
        current_config_id = self.request.GET.get('config_id', '')
        default_config = ReportConfig.default()

        def is_editable_datespan(field):
            field_fn = to_function(field) if isinstance(field, six.string_types) else field
            return issubclass(field_fn, DatespanFilter) and field_fn.is_editable

        has_datespan = any([is_editable_datespan(field) for field in self.fields])

        self.context.update(
            report=dict(
                title=self.rendered_report_title,
                description=self.description,
                section_name=self.section_name,
                slug=self.slug,
                sub_slug=None,
                type=self.dispatcher.prefix,
                url_root=self.url_root,
                is_async=self.asynchronous,
                is_exportable=self.exportable,
                dispatcher=self.dispatcher,
                filter_set=self.filter_set,
                needs_filters=self.needs_filters,
                has_datespan=has_datespan,
                show=(
                    self.override_permissions_check
                    or self.request.couch_user.can_view_some_reports(self.domain)
                ),
                is_emailable=self.emailable,
                is_export_all = self.exportable_all,
                is_printable=self.printable,
                is_admin=self.is_admin_report,
                special_notice=self.special_notice,
                report_title=self.report_title or self.rendered_report_title,
                report_subtitles=self.report_subtitles,
                export_target=self.export_target,
                js_scripts=self.js_scripts,
                js_options=self.js_options,
                custom_filter_action_template=(
                    self.custom_filter_action_template
                    if hasattr(self, 'custom_filter_action_template')
                    else False
                ),
            ),
            current_config_id=current_config_id,
            default_config=default_config,
            report_configs=report_configs,
            show_time_notice=self.show_time_notice,
            domain=self.domain,
            layout_flush_content=self.flush_layout
        )
Пример #7
0
    def _update_initial_context(self):
        """
            Intention: Don't override.
        """
        report_configs = ReportConfig.by_domain_and_owner(self.domain,
            self.request.couch_user._id, report_slug=self.slug)
        current_config_id = self.request.GET.get('config_id', '')
        default_config = ReportConfig.default()

        def is_editable_datespan(field):
            field_fn = to_function(field) if isinstance(field, six.string_types) else field
            return issubclass(field_fn, DatespanFilter) and field_fn.is_editable

        has_datespan = any([is_editable_datespan(field) for field in self.fields])

        self.context.update(
            report=dict(
                title=self.rendered_report_title,
                description=self.description,
                section_name=self.section_name,
                slug=self.slug,
                sub_slug=None,
                type=self.dispatcher.prefix,
                url_root=self.url_root,
                is_async=self.asynchronous,
                is_exportable=self.exportable,
                dispatcher=self.dispatcher,
                filter_set=self.filter_set,
                needs_filters=self.needs_filters,
                has_datespan=has_datespan,
                show=(
                    self.override_permissions_check
                    or self.request.couch_user.can_view_some_reports(self.domain)
                ),
                is_emailable=self.emailable,
                is_export_all = self.exportable_all,
                is_printable=self.printable,
                is_admin=self.is_admin_report,
                special_notice=self.special_notice,
                report_title=self.report_title or self.rendered_report_title,
                report_subtitles=self.report_subtitles,
                export_target=self.export_target,
                js_options=self.js_options,
                custom_filter_action_template=(
                    self.custom_filter_action_template
                    if hasattr(self, 'custom_filter_action_template')
                    else False
                ),
            ),
            current_config_id=current_config_id,
            default_config=default_config,
            report_configs=report_configs,
            show_time_notice=self.show_time_notice,
            domain=self.domain,
            layout_flush_content=self.flush_layout
        )
Пример #8
0
 def saved_report_context_data(self):
     current_config_id = self.request.GET.get('config_id')
     return {
         'report_configs': ReportConfig.by_domain_and_owner(
             self.domain, self.request.couch_user._id, report_slug=self.slug
         ),
         'default_config': (
             ReportConfig.get(current_config_id)
             if current_config_id
             else ReportConfig.default()
         ),
     }
Пример #9
0
    def _update_initial_context(self):
        """
            Intention: Don't override.
        """
        report_configs = ReportConfig.by_domain_and_owner(
            self.domain, self.request.couch_user._id, report_slug=self.slug
        )
        current_config_id = self.request.GET.get("config_id", "")
        default_config = ReportConfig.default()

        def is_datespan(field):
            field_fn = to_function(field) if isinstance(field, basestring) else field
            return issubclass(field_fn, DatespanFilter)

        has_datespan = any([is_datespan(field) for field in self.fields])

        self.context.update(
            report=dict(
                title=self.rendered_report_title,
                description=self.description,
                section_name=self.section_name,
                slug=self.slug,
                sub_slug=None,
                type=self.dispatcher.prefix,
                url_root=self.url_root,
                is_async=self.asynchronous,
                is_exportable=self.exportable,
                dispatcher=self.dispatcher,
                filter_set=self.filter_set,
                needs_filters=self.needs_filters,
                has_datespan=has_datespan,
                show=(
                    self.override_permissions_check
                    or self.request.couch_user.can_view_reports()
                    or self.request.couch_user.get_viewable_reports()
                ),
                is_emailable=self.emailable,
                is_export_all=self.exportable_all,
                is_printable=self.printable,
                is_admin=self.is_admin_report,  # todo is this necessary???
                special_notice=self.special_notice,
                report_title=self.report_title or self.rendered_report_title,
                report_subtitles=self.report_subtitles,
            ),
            current_config_id=current_config_id,
            default_config=default_config,
            report_configs=report_configs,
            show_time_notice=self.show_time_notice,
            domain=self.domain,
            layout_flush_content=self.flush_layout,
        )
Пример #10
0
def add_config(request, domain=None):
    # todo: refactor this into a django form
    from datetime import datetime
    user_id = request.couch_user._id

    POST = json.loads(request.raw_post_data)
    if 'name' not in POST or not POST['name']:
        return HttpResponseBadRequest()
    
    user_configs = ReportConfig.by_domain_and_owner(domain, user_id).all()
    if not POST.get('_id') and POST['name'] in [c.name for c in user_configs]:
        return HttpResponseBadRequest()

    to_date = lambda s: datetime.strptime(s, '%Y-%m-%d').date() if s else s
    try:
        POST['start_date'] = to_date(POST['start_date'])
        POST['end_date'] = to_date(POST['end_date'])
    except ValueError:
        # invalidly formatted date input
        return HttpResponseBadRequest()

    date_range = POST.get('date_range')
    if date_range == 'last7':
        POST['days'] = 7
    elif date_range == 'last30':
        POST['days'] = 30
    elif POST.get('days'):
        POST['days'] = int(POST['days'])
  
    exclude_filters = ['startdate', 'enddate']
    for field in exclude_filters:
        POST['filters'].pop(field, None)
    
    config = ReportConfig.get_or_create(POST.get('_id', None))

    if config.owner_id:
        # in case a user maliciously tries to edit another user's config
        assert config.owner_id == user_id
    else:
        config.domain = domain
        config.owner_id = user_id

    for field in config.properties().keys():
        if field in POST:
            setattr(config, field, POST[field])
    
    config.save()

    touch_saved_reports_views(request.couch_user, domain)

    return json_response(config)
Пример #11
0
def email_report(request, domain, report_slug, report_type=ProjectReportDispatcher.prefix):
    from dimagi.utils.django.email import send_HTML_email
    from forms import EmailReportForm
    user_id = request.couch_user._id

    form = EmailReportForm(request.GET)
    if not form.is_valid():
        return HttpResponseBadRequest()

    config = ReportConfig()
    # see ReportConfig.query_string()
    object.__setattr__(config, '_id', 'dummy')
    config.name = _("Emailed report")
    config.report_type = report_type

    config.report_slug = report_slug
    config.owner_id = user_id
    config.domain = domain

    config.date_range = 'range'
    config.start_date = request.datespan.computed_startdate.date()
    config.end_date = request.datespan.computed_enddate.date()

    GET = dict(request.GET.iterlists())
    exclude = ['startdate', 'enddate', 'subject', 'send_to_owner', 'notes', 'recipient_emails']
    filters = {}
    for field in GET:
        if not field in exclude:
            filters[field] = GET.get(field)

    config.filters = filters

    body = _render_report_configs(request, [config],
                                  domain,
                                  user_id, request.couch_user,
                                  True,
                                  notes=form.cleaned_data['notes'])[0].content

    subject = form.cleaned_data['subject'] or _("Email report from CommCare HQ")

    if form.cleaned_data['send_to_owner']:
        send_HTML_email(subject, request.couch_user.get_email(), body,
                        email_from=settings.DEFAULT_FROM_EMAIL)

    if form.cleaned_data['recipient_emails']:
        for recipient in form.cleaned_data['recipient_emails']:
            send_HTML_email(subject, recipient, body, email_from=settings.DEFAULT_FROM_EMAIL)

    return HttpResponse()
Пример #12
0
    def _update_initial_context(self):
        """
            Intention: Don't override.
        """
        report_configs = ReportConfig.by_domain_and_owner(
            self.domain, self.request.couch_user._id, report_slug=self.slug)
        current_config_id = self.request.GET.get('config_id', '')
        default_config = ReportConfig.default()

        def is_datespan(field):
            field_fn = to_function(field) if isinstance(field,
                                                        basestring) else field
            return issubclass(field_fn, DatespanFilter)

        has_datespan = any([is_datespan(field) for field in self.fields])

        self.context.update(
            report=dict(
                title=self.rendered_report_title,
                description=self.description,
                section_name=self.section_name,
                slug=self.slug,
                sub_slug=None,
                type=self.dispatcher.prefix,
                url_root=self.url_root,
                is_async=self.asynchronous,
                is_exportable=self.exportable,
                dispatcher=self.dispatcher,
                filter_set=self.filter_set,
                needs_filters=self.needs_filters,
                has_datespan=has_datespan,
                show=self.override_permissions_check or \
                   self.request.couch_user.can_view_reports() or self.request.couch_user.get_viewable_reports(),
                is_emailable=self.emailable,
                is_export_all = self.exportable_all,
                is_printable=self.printable,
                is_admin=self.is_admin_report,   # todo is this necessary???
                special_notice=self.special_notice,
                report_title=self.report_title or self.rendered_report_title,
                report_subtitles=self.report_subtitles,
            ),
            current_config_id=current_config_id,
            default_config=default_config,
            report_configs=report_configs,
            show_time_notice=self.show_time_notice,
            domain=self.domain,
            layout_flush_content=self.flush_layout
        )
Пример #13
0
 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()
Пример #14
0
def saved_reports(request, domain, template="reports/reports_home.html"):
    user = request.couch_user
    if not (request.couch_user.can_view_reports() or request.couch_user.get_viewable_reports()):
        raise Http404

    configs = ReportConfig.by_domain_and_owner(domain, user._id)

    def _is_valid(rn):
        # the _id check is for weird bugs we've seen in the wild that look like
        # oddities in couch.
        return hasattr(rn, "_id") and rn._id and (not hasattr(rn, 'report_slug') or rn.report_slug != 'admin_domains')

    scheduled_reports = [rn for rn in ReportNotification.by_domain_and_owner(domain, user._id) if _is_valid(rn)]
    scheduled_reports = sorted(scheduled_reports, key=lambda rn: rn.configs[0].name)

    context = dict(
        couch_user=request.couch_user,
        domain=domain,
        configs=configs,
        scheduled_reports=scheduled_reports,
        report=dict(
            title=_("My Saved Reports"),
            show=user.can_view_reports() or user.get_viewable_reports(),
            slug=None,
            is_async=True,
            section_name=ProjectReport.section_name,
        ),
    )

    if request.couch_user:
        util.set_report_announcements_for_user(request, user)

    return render(request, template, context)
Пример #15
0
 def test_get_scheduled_report_response(self):
     domain = self.domain
     user = WebUser.create(
         domain=domain,
         username='******',
         password='******',
     )
     report_config = ReportConfig.wrap({
         "date_range": "last30",
         "days": 30,
         "domain": domain,
         "report_slug": "worker_activity",
         "report_type": "project_report",
         "owner_id": user._id,
     })
     report_config.save()
     report = ReportNotification(hour=12,
                                 minute=None,
                                 day=30,
                                 interval='monthly',
                                 config_ids=[report_config._id])
     report.save()
     response = get_scheduled_report_response(
         couch_user=user, domain=domain, scheduled_report_id=report._id)[0]
     self.assertTrue(user.username in response)
Пример #16
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,
        }
Пример #17
0
 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()
Пример #18
0
    def balance_email_reports(self):
        EWSMigrationProblem.objects.filter(domain=self.domain).delete()
        reports = set()
        reports_count = 0
        for web_user in WebUser.by_domain(self.domain):
            notifications = ReportNotification.by_domain_and_owner(self.domain, web_user.get_id)
            for notification in notifications:
                config_id = notification.config_ids[0] if notification.config_ids else None

                if not config_id:
                    continue

                config = ReportConfig.get(config_id)
                location_id = config.filters.get('location_id')
                if not location_id:
                    # report is not migrated from ews
                    continue
                reports_count += 1
                report_slug = config.report_slug
                code = SQLLocation.objects.get(location_id=location_id).site_code
                report_tuple = (
                    web_user.username, notification.day, notification.hour,
                    code, report_slug, notification.interval
                )
                external_id = '{}-{}-{}-{}-{}-{}'.format(*report_tuple)
                if not notification.send_to_owner and not notification.recipient_emails:
                    migration_problem, _ = EWSMigrationProblem.objects.get_or_create(
                        domain=self.domain,
                        object_id=web_user.username,
                        object_type='email_report_send_to_owner',
                        external_id=external_id
                    )
                    migration_problem.description = 'send_to_owner not set to true'
                    migration_problem.save()

                reports.add(report_tuple)

        total_count = 0

        for report in self.endpoint.get_daily_reports(limit=1000)[1]:
            if self._check_report(report, reports, 1, 'daily'):
                total_count += 1

        for report in self.endpoint.get_weekly_reports(limit=1000)[1]:
            if self._check_report(report, reports, report.day_of_week, 'weekly'):
                total_count += 1

        for report in self.endpoint.get_monthly_reports(limit=1000)[1]:
            if self._check_report(report, reports, report.day_of_month, 'monthly'):
                total_count += 1

        if total_count != reports_count:
            migration_problem, _ = EWSMigrationProblem.objects.get_or_create(
                domain=self.domain,
                object_id=None,
                object_type='email_report',
                external_id='email-report-count'
            )
            migration_problem.description = '{} / {}'.format(reports_count, total_count)
            migration_problem.save()
Пример #19
0
def saved_reports(request, domain, template="reports/reports_home.html"):
    user = request.couch_user
    if not (request.couch_user.can_view_reports() or request.couch_user.get_viewable_reports()):
        raise Http404

    configs = ReportConfig.by_domain_and_owner(domain, user._id)

    def _is_valid(rn):
        # the _id check is for weird bugs we've seen in the wild that look like
        # oddities in couch.
        return hasattr(rn, "_id") and rn._id and (not hasattr(rn, "report_slug") or rn.report_slug != "admin_domains")

    scheduled_reports = [rn for rn in ReportNotification.by_domain_and_owner(domain, user._id) if _is_valid(rn)]
    scheduled_reports = sorted(scheduled_reports, key=lambda rn: rn.configs[0].name)

    context = dict(
        couch_user=request.couch_user,
        domain=domain,
        configs=configs,
        scheduled_reports=scheduled_reports,
        report=dict(
            title=_("My Saved Reports"),
            show=user.can_view_reports() or user.get_viewable_reports(),
            slug=None,
            is_async=True,
            section_name=ProjectReport.section_name,
        ),
    )

    if request.couch_user:
        util.set_report_announcements_for_user(request, user)

    return render(request, template, context)
Пример #20
0
 def test_get_scheduled_report_response(self):
     domain = 'test-scheduled-reports'
     user = WebUser.create(
         domain=domain,
         username='******',
         password='******',
     )
     report_config = ReportConfig.wrap({
         "date_range": "last30",
         "days": 30,
         "domain": domain,
         "report_slug": "worker_activity",
         "report_type": "project_report",
         "owner_id": user._id,
     })
     report_config.save()
     report = ReportNotification(
         hour=12, minute=None, day=30, interval='monthly', config_ids=[report_config._id]
     )
     report.save()
     response = get_scheduled_report_response(
         couch_user=user, domain=domain, scheduled_report_id=report._id
     )[0]
     self.assertEqual(200, response.status_code)
     self.assertTrue(user.username in response.serialize())
Пример #21
0
def saved_reports(request, domain, template="reports/reports_home.html"):
    user = request.couch_user
    if not (request.couch_user.can_view_reports() or request.couch_user.get_viewable_reports()):
        raise Http404

    configs = ReportConfig.by_domain_and_owner(domain, user._id).all()
    scheduled_reports = [s for s in ReportNotification.by_domain_and_owner(domain, user._id).all()
                         if not hasattr(s, 'report_slug') or s.report_slug != 'admin_domains']

    context = dict(
        couch_user=request.couch_user,
        domain=domain,
        configs=configs,
        scheduled_reports=scheduled_reports,
        report=dict(
            title="Select a Report to View",
            show=user.can_view_reports() or user.get_viewable_reports(),
            slug=None,
            is_async=True,
            section_name=ProjectReport.section_name,
        ),
    )

    if request.couch_user:
        util.set_report_announcements_for_user(request, user)

    return render(request, template, context)
Пример #22
0
def delete_config(request, domain, config_id):
    try:
        config = ReportConfig.get(config_id)
    except ResourceNotFound:
        raise Http404()

    config.delete()
    return HttpResponse()
Пример #23
0
def delete_config(request, domain, config_id):
    try:
        config = ReportConfig.get(config_id)
    except ResourceNotFound:
        raise Http404()

    config.delete()

    touch_saved_reports_views(request.couch_user, domain)
    return HttpResponse()
Пример #24
0
 def total(self):
     key = ["name", self.request.domain, self.request.couch_user._id]
     results = ReportConfig.get_db().view(
         'reportconfig/configs_by_domain',
         include_docs=False,
         startkey=key,
         endkey=key+[{}],
         reduce=True,
     ).all()
     return results[0]['value'] if results else 0
Пример #25
0
def delete_config(request, domain, config_id):
    try:
        config = ReportConfig.get(config_id)
    except ResourceNotFound:
        raise Http404()

    config.delete()

    touch_saved_reports_views(request.couch_user, domain)
    return HttpResponse()
Пример #26
0
 def total(self):
     key = ["name", self.request.domain, self.request.couch_user._id]
     results = ReportConfig.get_db().view(
         'reportconfig/configs_by_domain',
         include_docs=False,
         startkey=key,
         endkey=key+[{}],
         reduce=True,
     ).all()
     return results[0]['value'] if results else 0
Пример #27
0
    def _report_notfication_sync(self, report, interval, day):
        if not report.users or report.report not in self.REPORT_MAP:
            return
        user_id = report.users[0]
        recipients = report.users[1:]
        location_code = report.view_args.split()[1][1:-2]

        user = WebUser.get_by_username(user_id)
        if not user:
            return

        try:
            location = SQLLocation.active_objects.get(site_code=location_code, domain=self.domain)
        except SQLLocation.DoesNotExist:
            return

        notifications = ReportNotification.by_domain_and_owner(self.domain, user.get_id)
        for n in notifications:
            if len(n.config_ids) == 1:
                # Migrated reports have only one config
                config = ReportConfig.get(n.config_ids[0])
                location_id = config.filters.get('location_id')
                slug = self.REPORT_MAP[report.report]
                report_slug = config.report_slug
                if (n.day, location_id, report_slug, n.interval) == (day, location.location_id, slug, interval):
                    if not n.send_to_owner and not n.recipient_emails:
                        n.send_to_owner = True
                        n.save()
                    return

        saved_config = ReportConfig(
            report_type='custom_project_report', name=report.report, owner_id=user.get_id,
            report_slug=self.REPORT_MAP[report.report], domain=self.domain,
            filters={'filter_by_program': 'all', 'location_id': location.location_id}
        )
        saved_config.save()
        saved_notification = ReportNotification(
            hour=report.hours, day=day, interval=interval, owner_id=user.get_id, domain=self.domain,
            recipient_emails=recipients, config_ids=[saved_config.get_id], send_to_owner=True
        )
        saved_notification.save()
        return saved_notification
Пример #28
0
    def _update_initial_context(self):
        """
            Intention: Don't override.
        """
        report_configs = ReportConfig.by_domain_and_owner(
            self.domain, self.request.couch_user._id,
            report_slug=self.slug).all()
        current_config_id = self.request.GET.get('config_id', '')
        default_config = ReportConfig.default()

        has_datespan = ('corehq.apps.reports.fields.DatespanField'
                        in self.fields)

        self.context.update(
            report=dict(
                title=self.name,
                description=self.description,
                section_name=self.section_name,
                slug=self.slug,
                sub_slug=None,
                type=self.dispatcher.prefix,
                url_root=self.url_root,
                is_async=self.asynchronous,
                is_exportable=self.exportable,
                dispatcher=self.dispatcher,
                filter_set=self.filter_set,
                needs_filters=self.needs_filters,
                has_datespan=has_datespan,
                show=self.override_permissions_check or \
                   self.request.couch_user.can_view_reports() or self.request.couch_user.get_viewable_reports(),
                is_emailable=self.emailable,
                is_admin=self.is_admin_report,   # todo is this necessary???
                special_notice=self.special_notice,
            ),
            current_config_id=current_config_id,
            default_config=default_config,
            report_configs=report_configs,
            show_time_notice=self.show_time_notice,
            domain=self.domain,
            layout_flush_content=self.flush_layout
        )
Пример #29
0
    def _update_initial_context(self):
        """
            Intention: Don't override.
        """
        report_configs = ReportConfig.by_domain_and_owner(self.domain,
            self.request.couch_user._id, report_slug=self.slug).all()
        current_config_id = self.request.GET.get('config_id', '')
        default_config = ReportConfig.default()

        has_datespan = ('corehq.apps.reports.fields.DatespanField' in self.fields)

        self.context.update(
            report=dict(
                title=self.rendered_report_title,
                description=self.description,
                section_name=self.section_name,
                slug=self.slug,
                sub_slug=None,
                type=self.dispatcher.prefix,
                url_root=self.url_root,
                is_async=self.asynchronous,
                is_exportable=self.exportable,
                dispatcher=self.dispatcher,
                filter_set=self.filter_set,
                needs_filters=self.needs_filters,
                has_datespan=has_datespan,
                show=self.override_permissions_check or \
                   self.request.couch_user.can_view_reports() or self.request.couch_user.get_viewable_reports(),
                is_emailable=self.emailable,
                is_printable=self.printable,
                is_admin=self.is_admin_report,   # todo is this necessary???
                special_notice=self.special_notice,
            ),
            current_config_id=current_config_id,
            default_config=default_config,
            report_configs=report_configs,
            show_time_notice=self.show_time_notice,
            domain=self.domain,
            layout_flush_content=self.flush_layout
        )
Пример #30
0
    def _report_notfication_sync(self, report, interval, day):
        if not report.users:
            return
        user_id = report.users[0]
        recipients = report.users[1:]
        location_code = report.view_args.split()[1][1:-2]

        user = WebUser.get_by_username(user_id)
        if not user:
            return

        try:
            location = SQLLocation.objects.get(site_code=location_code, domain=self.domain)
        except SQLLocation.DoesNotExist:
            return

        notifications = ReportNotification.by_domain_and_owner(self.domain, user.get_id)
        reports = []
        for n in notifications:
            for config_id in n.config_ids:
                config = ReportConfig.get(config_id)
                reports.append((config.filters.get('location_id'), config.report_slug, interval))

        if report.report not in self.REPORT_MAP or (location.location_id, self.REPORT_MAP[report.report],
                                                    interval) in reports:
            return

        saved_config = ReportConfig(
            report_type='custom_project_report', name=report.report, owner_id=user.get_id,
            report_slug=self.REPORT_MAP[report.report], domain=self.domain,
            filters={'filter_by_program': 'all', 'location_id': location.location_id}
        )
        saved_config.save()
        saved_notification = ReportNotification(
            hour=report.hours, day=day, interval=interval, owner_id=user.get_id, domain=self.domain,
            recipient_emails=recipients, config_ids=[saved_config.get_id]
        )
        saved_notification.save()
        return saved_notification
Пример #31
0
 def _paginated_items(self, items_per_page, skip):
     reports = ReportConfig.by_domain_and_owner(self.request.domain,
                                                self.request.couch_user._id,
                                                limit=items_per_page,
                                                skip=skip)
     for report in reports:
         yield self._fmt_item(report.name,
                              report.url,
                              description="%(desc)s (%(date)s)" % {
                                  'desc': report.description,
                                  'date': report.date_description,
                              },
                              full_name=report.full_name)
 def handle(self, report_slug, *args, **options):
     kwargs = {'stale': settings.COUCH_STALE_QUERY}
     key = ["name slug"]
     result = cache_core.cached_view(ReportConfig.get_db(),
                                     "reportconfig/configs_by_domain",
                                     reduce=False,
                                     include_docs=False,
                                     startkey=key,
                                     endkey=key + [{}],
                                     **kwargs)
     for report_config in result:
         domain, owner_id, slug = report_config['key'][1:4]
         if slug == report_slug:
             print("%s, %s, %s" % (domain, owner_id, slug))
Пример #33
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),
        }
Пример #34
0
 def paginated_items(self):
     reports = ReportConfig.by_domain_and_owner(
         self.request.domain, self.request.couch_user._id,
         limit=self.limit, skip=self.skip
     )
     for report in reports:
         yield self._fmt_item(
             report.name,
             report.url,
             description="%(desc)s (%(date)s)" % {
                 'desc': report.description,
                 'date': report.date_description,
             },
             full_name=report.full_name
         )
Пример #35
0
    def handle(self, *args, **options):
        db = ReportConfig.get_db()
        results = db.view('reportconfig/configs_by_domain',
            startkey=["name"], endkey=["name", {}],
            reduce=False,
            include_docs=False,
        ).all()

        configs_to_save = []
        for config in iter_docs(db, [r['id'] for r in results]):
            if migrate(config, db):
                configs_to_save.append(config)

            if len(configs_to_save) > 100:
                db.bulk_save(configs_to_save)
                configs_to_save = []
        db.bulk_save(configs_to_save)
Пример #36
0
def saved_reports(request, domain, template="reports/reports_home.html"):
    user = request.couch_user
    if not (request.couch_user.can_view_reports()
            or request.couch_user.get_viewable_reports()):
        raise Http404

    configs = ReportConfig.by_domain_and_owner(domain, user._id)

    def _is_valid(rn):
        # the _id check is for weird bugs we've seen in the wild that look like
        # oddities in couch.
        return hasattr(rn, "_id") and rn._id and (not hasattr(rn, 'report_slug') or rn.report_slug != 'admin_domains')

    scheduled_reports = [rn for rn in ReportNotification.by_domain_and_owner(domain, user._id) if _is_valid(rn)]
    scheduled_reports = sorted(scheduled_reports, key=lambda rn: rn.configs[0].name)
    for report in scheduled_reports:
        time_difference = get_timezone_difference(domain)
        (report.hour, day_change) = recalculate_hour(report.hour, int(time_difference[:3]), int(time_difference[3:]))
        report.minute = 0
        if day_change:
            report.day = calculate_day(report.interval, report.day, day_change)

    context = dict(
        couch_user=request.couch_user,
        domain=domain,
        configs=configs,
        scheduled_reports=scheduled_reports,
        report=dict(
            title=_("My Saved Reports"),
            show=user.can_view_reports() or user.get_viewable_reports(),
            slug=None,
            is_async=True,
            section_name=ProjectReport.section_name,
        ),
    )

    if request.couch_user:
        util.set_report_announcements_for_user(request, user)

    return render(request, template, context)
 def test_get_scheduled_report_response(self):
     domain = self.domain
     report_config = ReportConfig.wrap({
         "date_range": "last30",
         "days": 30,
         "domain": domain,
         "report_slug": "worker_activity",
         "report_type": "project_report",
         "owner_id": self.user._id,
     })
     report_config.save()
     report = ReportNotification(hour=12,
                                 minute=None,
                                 day=30,
                                 interval='monthly',
                                 config_ids=[report_config._id])
     report.save()
     response = get_scheduled_report_response(
         couch_user=self.user,
         domain=domain,
         scheduled_report_id=report._id)[0]
     self.assertTrue(self.user.username in response.decode('utf-8'))
Пример #38
0
def edit_scheduled_report(request, domain, scheduled_report_id=None,
                          template="reports/edit_scheduled_report.html"):
    from corehq.apps.users.models import WebUser
    from corehq.apps.reports.forms import ScheduledReportForm

    context = {
        'form': None,
        'domain': domain,
        'report': {
            'show': request.couch_user.can_view_reports() or request.couch_user.get_viewable_reports(),
            'slug': None,
            'default_url': reverse('reports_home', args=(domain,)),
            'is_async': False,
            'section_name': ProjectReport.section_name,
        }
    }

    user_id = request.couch_user._id

    configs = ReportConfig.by_domain_and_owner(domain, user_id)
    config_choices = [(c._id, c.full_name) for c in configs if c.report and c.report.emailable]

    if not config_choices:
        return render(request, template, context)

    web_users = WebUser.view('users/web_users_by_domain', reduce=False,
                               key=domain, include_docs=True).all()
    web_user_emails = [u.get_email() for u in web_users]

    if scheduled_report_id:
        instance = ReportNotification.get(scheduled_report_id)
        time_difference = get_timezone_difference(domain)
        (instance.hour, day_change) = recalculate_hour(instance.hour, int(time_difference[:3]), int(time_difference[3:]))
        instance.minute = 0
        if day_change:
            instance.day = calculate_day(instance.interval, instance.day, day_change)

        if instance.owner_id != user_id or instance.domain != domain:
            raise HttpResponseBadRequest()
    else:
        instance = ReportNotification(owner_id=user_id, domain=domain,
                                      config_ids=[], hour=8, minute=0,
                                      send_to_owner=True, recipient_emails=[])

    is_new = instance.new_document
    initial = instance.to_json()
    initial['recipient_emails'] = ', '.join(initial['recipient_emails'])

    kwargs = {'initial': initial}
    args = (request.POST,) if request.method == "POST" else ()
    form = ScheduledReportForm(*args, **kwargs)

    form.fields['config_ids'].choices = config_choices
    form.fields['recipient_emails'].choices = web_user_emails

    form.fields['hour'].help_text = "This scheduled report's timezone is %s (%s GMT)"  % \
                                    (Domain._get_by_name(domain)['default_timezone'],
                                    get_timezone_difference(domain)[:3] + ':' + get_timezone_difference(domain)[3:])


    if request.method == "POST" and form.is_valid():
        for k, v in form.cleaned_data.items():
            setattr(instance, k, v)

        time_difference = get_timezone_difference(domain)
        (instance.hour, day_change) = calculate_hour(instance.hour, int(time_difference[:3]), int(time_difference[3:]))
        instance.minute = int(time_difference[3:])
        if day_change:
            instance.day = calculate_day(instance.interval, instance.day, day_change)

        instance.save()
        if is_new:
            messages.success(request, "Scheduled report added!")
        else:
            messages.success(request, "Scheduled report updated!")

        touch_saved_reports_views(request.couch_user, domain)
        return HttpResponseRedirect(reverse('reports_home', args=(domain,)))

    context['form'] = form
    context['day_value'] = getattr(instance, "day", 1)
    context['weekly_day_options'] = ReportNotification.day_choices()
    context['monthly_day_options'] = [(i, i) for i in range(1, 32)]
    if is_new:
        context['form_action'] = "Create a new"
        context['report']['title'] = "New Scheduled Report"
    else:
        context['form_action'] = "Edit"
        context['report']['title'] = "Edit Scheduled Report"

    return render(request, template, context)
Пример #39
0
def edit_scheduled_report(request, domain, scheduled_report_id=None, template="reports/edit_scheduled_report.html"):
    from corehq.apps.users.models import WebUser
    from corehq.apps.reports.forms import ScheduledReportForm

    context = {
        "form": None,
        "domain": domain,
        "report": {
            "show": request.couch_user.can_view_reports() or request.couch_user.get_viewable_reports(),
            "slug": None,
            "default_url": reverse("reports_home", args=(domain,)),
            "is_async": False,
            "section_name": ProjectReport.section_name,
        },
    }

    user_id = request.couch_user._id

    configs = ReportConfig.by_domain_and_owner(domain, user_id)
    config_choices = [(c._id, c.full_name) for c in configs if c.report and c.report.emailable]

    if not config_choices:
        return render(request, template, context)

    web_users = WebUser.view("users/web_users_by_domain", reduce=False, key=domain, include_docs=True).all()
    web_user_emails = [u.get_email() for u in web_users]

    if scheduled_report_id:
        instance = ReportNotification.get(scheduled_report_id)
        if instance.owner_id != user_id or instance.domain != domain:
            raise HttpResponseBadRequest()
    else:
        instance = ReportNotification(
            owner_id=user_id, domain=domain, config_ids=[], hour=8, send_to_owner=True, recipient_emails=[]
        )

    is_new = instance.new_document
    initial = instance.to_json()
    initial["recipient_emails"] = ", ".join(initial["recipient_emails"])

    kwargs = {"initial": initial}
    args = (request.POST,) if request.method == "POST" else ()
    form = ScheduledReportForm(*args, **kwargs)

    form.fields["config_ids"].choices = config_choices
    form.fields["recipient_emails"].choices = web_user_emails

    if request.method == "POST" and form.is_valid():
        for k, v in form.cleaned_data.items():
            setattr(instance, k, v)
        instance.save()
        if is_new:
            messages.success(request, "Scheduled report added!")
        else:
            messages.success(request, "Scheduled report updated!")

        touch_saved_reports_views(request.couch_user, domain)
        return HttpResponseRedirect(reverse("reports_home", args=(domain,)))

    context["form"] = form
    context["day_value"] = getattr(instance, "day", 1)
    context["weekly_day_options"] = ReportNotification.day_choices()
    context["monthly_day_options"] = [(i, i) for i in range(1, 32)]
    if is_new:
        context["form_action"] = "Create a new"
        context["report"]["title"] = "New Scheduled Report"
    else:
        context["form_action"] = "Edit"
        context["report"]["title"] = "Edit Scheduled Report"

    return render(request, template, context)
Пример #40
0
def edit_scheduled_report(request, domain, scheduled_report_id=None, 
                          template="reports/edit_scheduled_report.html"):
    from corehq.apps.users.models import WebUser
    from corehq.apps.reports.forms import ScheduledReportForm

    context = {
        'form': None,
        'domain': domain,
        'report': {
            'show': request.couch_user.can_view_reports() or request.couch_user.get_viewable_reports(),
            'slug': None,
            'default_url': reverse('reports_home', args=(domain,)),
            'is_async': False,
            'section_name': ProjectReport.section_name,
        }
    }
    
    user_id = request.couch_user._id

    configs = ReportConfig.by_domain_and_owner(domain, user_id).all()
    config_choices = [(c._id, c.full_name) for c in configs if c.report and c.report.emailable]

    if not config_choices:
        return render(request, template, context)

    web_users = WebUser.view('users/web_users_by_domain', reduce=False,
                               key=domain, include_docs=True).all()
    web_user_emails = [u.get_email() for u in web_users]

    if scheduled_report_id:
        instance = ReportNotification.get(scheduled_report_id)
        if instance.owner_id != user_id or instance.domain != domain:
            raise HttpResponseBadRequest()
    else:
        instance = ReportNotification(owner_id=user_id, domain=domain,
                                      config_ids=[], day_of_week=-1, hours=8,
                                      send_to_owner=True, recipient_emails=[])

    is_new = instance.new_document
    initial = instance.to_json()
    initial['recipient_emails'] = ', '.join(initial['recipient_emails'])

    kwargs = {'initial': initial}
    args = (request.POST,) if request.method == "POST" else ()
    form = ScheduledReportForm(*args, **kwargs)
    
    form.fields['config_ids'].choices = config_choices
    form.fields['recipient_emails'].choices = web_user_emails

    if request.method == "POST" and form.is_valid():
        for k, v in form.cleaned_data.items():
            setattr(instance, k, v)
        instance.save()

        if is_new:
            messages.success(request, "Scheduled report added!")
        else:
            messages.success(request, "Scheduled report updated!")

        return HttpResponseRedirect(reverse('reports_home', args=(domain,)))

    context['form'] = form
    if is_new:
        context['form_action'] = "Create a new"
        context['report']['title'] = "New Scheduled Report"
    else:
        context['form_action'] = "Edit"
        context['report']['title'] = "Edit Scheduled Report"

    return render(request, template, context)
Пример #41
0
def email_report(request,
                 domain,
                 report_slug,
                 report_type=ProjectReportDispatcher.prefix):
    from dimagi.utils.django.email import send_HTML_email
    from forms import EmailReportForm
    user_id = request.couch_user._id

    form = EmailReportForm(request.GET)
    if not form.is_valid():
        return HttpResponseBadRequest()

    config = ReportConfig()
    # see ReportConfig.query_string()
    object.__setattr__(config, '_id', 'dummy')
    config.name = _("Emailed report")
    config.report_type = report_type

    config.report_slug = report_slug
    config.owner_id = user_id
    config.domain = domain

    config.date_range = 'range'
    config.start_date = request.datespan.computed_startdate.date()
    config.end_date = request.datespan.computed_enddate.date()

    GET = dict(request.GET.iterlists())
    exclude = [
        'startdate', 'enddate', 'subject', 'send_to_owner', 'notes',
        'recipient_emails'
    ]
    filters = {}
    for field in GET:
        if not field in exclude:
            filters[field] = GET.get(field)

    config.filters = filters

    body = _render_report_configs(request, [config],
                                  domain,
                                  user_id,
                                  request.couch_user,
                                  True,
                                  notes=form.cleaned_data['notes'])[0].content

    subject = form.cleaned_data['subject'] or _(
        "Email report from CommCare HQ")

    if form.cleaned_data['send_to_owner']:
        send_HTML_email(subject,
                        request.couch_user.get_email(),
                        body,
                        email_from=settings.DEFAULT_FROM_EMAIL)

    if form.cleaned_data['recipient_emails']:
        for recipient in form.cleaned_data['recipient_emails']:
            send_HTML_email(subject,
                            recipient,
                            body,
                            email_from=settings.DEFAULT_FROM_EMAIL)

    return HttpResponse()
Пример #42
0
def edit_scheduled_report(request,
                          domain,
                          scheduled_report_id=None,
                          template="reports/edit_scheduled_report.html"):
    from corehq.apps.users.models import WebUser
    from corehq.apps.reports.forms import ScheduledReportForm

    context = {
        'form': None,
        'domain': domain,
        'report': {
            'show':
            request.couch_user.can_view_reports()
            or request.couch_user.get_viewable_reports(),
            'slug':
            None,
            'default_url':
            reverse('reports_home', args=(domain, )),
            'is_async':
            False,
            'section_name':
            ProjectReport.section_name,
        }
    }

    user_id = request.couch_user._id

    configs = ReportConfig.by_domain_and_owner(domain, user_id)
    config_choices = [(c._id, c.full_name) for c in configs
                      if c.report and c.report.emailable]

    if not config_choices:
        return render(request, template, context)

    web_users = WebUser.view('users/web_users_by_domain',
                             reduce=False,
                             key=domain,
                             include_docs=True).all()
    web_user_emails = [u.get_email() for u in web_users]

    if scheduled_report_id:
        instance = ReportNotification.get(scheduled_report_id)
        if instance.owner_id != user_id or instance.domain != domain:
            raise HttpResponseBadRequest()
    else:
        instance = ReportNotification(owner_id=user_id,
                                      domain=domain,
                                      config_ids=[],
                                      hour=8,
                                      send_to_owner=True,
                                      recipient_emails=[])

    is_new = instance.new_document
    initial = instance.to_json()
    initial['recipient_emails'] = ', '.join(initial['recipient_emails'])

    kwargs = {'initial': initial}
    args = (request.POST, ) if request.method == "POST" else ()
    form = ScheduledReportForm(*args, **kwargs)

    form.fields['config_ids'].choices = config_choices
    form.fields['recipient_emails'].choices = web_user_emails

    if request.method == "POST" and form.is_valid():
        for k, v in form.cleaned_data.items():
            setattr(instance, k, v)
        instance.save()
        if is_new:
            messages.success(request, "Scheduled report added!")
        else:
            messages.success(request, "Scheduled report updated!")

        touch_saved_reports_views(request.couch_user, domain)
        return HttpResponseRedirect(reverse('reports_home', args=(domain, )))

    context['form'] = form
    context['day_value'] = getattr(instance, "day", 1)
    context['weekly_day_options'] = ReportNotification.day_choices()
    context['monthly_day_options'] = [(i, i) for i in range(1, 32)]
    if is_new:
        context['form_action'] = "Create a new"
        context['report']['title'] = "New Scheduled Report"
    else:
        context['form_action'] = "Edit"
        context['report']['title'] = "Edit Scheduled Report"

    return render(request, template, context)