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), }
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)
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)
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)
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()
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 )
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 )
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() ), }
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, )
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)
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()
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 )
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()
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)
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)
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, }
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()
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)
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())
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)
def delete_config(request, domain, config_id): try: config = ReportConfig.get(config_id) except ResourceNotFound: raise Http404() config.delete() return HttpResponse()
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()
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
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
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 )
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 )
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
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))
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), }
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 )
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)
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'))
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)
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)
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)
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()
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)