def page_context(self): def to_json(dataset_map): dataset_map = dataset_map.to_json() del (dataset_map['_id']) del (dataset_map['_rev']) del (dataset_map['doc_type']) del (dataset_map['domain']) for datavalue_map in dataset_map['datavalue_maps']: del (datavalue_map['doc_type']) return dataset_map dataset_maps = [ to_json(d) for d in get_dataset_maps(self.request.domain) ] return { 'dataset_maps': dataset_maps, 'connection_settings': ConnectionSettings.objects.filter(domain=self.domain).all(), 'ucrs': get_report_configs_for_domain(self.domain), 'send_data_url': reverse('send_dhis2_data', kwargs={'domain': self.domain}), 'is_json_ui': int(self.request.GET.get('json', 0)), }
def test_get_report_configs_for_domain(self): self.assertEqual( [o.to_json() for o in get_report_configs_for_domain(self.domain_1.name)], [report_config.to_json() for report_config in sorted(self.report_configs, key=lambda report: report.title) if report_config.domain == self.domain_1.name] )
def copy_ucr_reports(self, datasource_map): report_map = {} reports = get_report_configs_for_domain(self.existing_domain) for report in reports: old_datasource_id = report.config_id try: report.config_id = datasource_map[old_datasource_id] except KeyError: pass # datasource not found old_id, new_id = self.save_couch_copy(report, self.new_domain) report_map[old_id] = new_id for static_report in StaticReportConfiguration.by_domain(self.existing_domain): if static_report.get_id.startswith(STATIC_PREFIX): report_id = static_report.get_id.replace( STATIC_PREFIX + self.existing_domain + '-', '' ) is_custom_report = False else: report_id = static_report.get_id.replace( CUSTOM_REPORT_PREFIX + self.existing_domain + '-', '' ) is_custom_report = True new_id = StaticReportConfiguration.get_doc_id( self.new_domain, report_id, is_custom_report ) # check that new report is in new domain's list of static reports StaticReportConfiguration.by_id(new_id) report_map[static_report.get_id] = new_id return report_map
def copy_ucr_reports(self, datasource_map): report_map = {} reports = get_report_configs_for_domain(self.existing_domain) for report in reports: old_datasource_id = report.config_id try: report.config_id = datasource_map[old_datasource_id] except KeyError: pass # datasource not found old_id, new_id = self.save_couch_copy(report, self.new_domain) report_map[old_id] = new_id for static_report in StaticReportConfiguration.by_domain( self.existing_domain): if static_report.get_id.startswith(STATIC_PREFIX): report_id = static_report.get_id.replace( STATIC_PREFIX + self.existing_domain + '-', '') is_custom_report = False else: report_id = static_report.get_id.replace( CUSTOM_REPORT_PREFIX + self.existing_domain + '-', '') is_custom_report = True new_id = StaticReportConfiguration.get_doc_id( self.new_domain, report_id, is_custom_report) # check that new report is in new domain's list of static reports StaticReportConfiguration.by_id(new_id) report_map[static_report.get_id] = new_id return report_map
def _get_reports(self): master_list = {} linked_list = {} reports = get_report_configs_for_domain(self.domain) for report in reports: if report.report_meta.master_id: linked_list[report.get_id] = report else: master_list[report.get_id] = report return (master_list, linked_list)
def linkable_ucr(request, domain): """Returns a list of reports to be used by the downstream domain on a remote server to create linked reports by calling the `ucr_config` view below """ reports = get_report_configs_for_domain(domain) return JsonResponse({ "reports": [ {"id": report._id, "title": report.title} for report in reports] })
def copy_ucr_reports(self, datasource_map): report_map = {} reports = get_report_configs_for_domain(self.existing_domain) for report in reports: old_datasource_id = report.config_id try: report.config_id = datasource_map[old_datasource_id] except KeyError: pass # datasource not found old_id, new_id = self.save_couch_copy(report, self.new_domain) report_map[old_id] = new_id report_map.update(get_static_report_mapping(self.existing_domain, self.new_domain)) return report_map
def copy_ucr_reports(self, datasource_map): report_map = {} reports = get_report_configs_for_domain(self.existing_domain) for report in reports: old_datasource_id = report.config_id try: report.config_id = datasource_map[old_datasource_id] except KeyError: pass # datasource not found old_id, new_id = self.save_couch_copy(report, self.new_domain) report_map[old_id] = new_id report_map = get_static_report_mapping(self.existing_domain, self.new_domain, report_map) return report_map
def get_ucr_field(domain): from corehq.apps.userreports.views import UserConfigReportsHomeView ucrs = get_report_configs_for_domain(domain) url = reverse(UserConfigReportsHomeView.urlname, kwargs={'domain': domain}) return forms.ChoiceField( label=_("User Configurable Report"), choices=[(ucr.get_id, ucr.title) for ucr in ucrs], required=True, help_text= _('DataSet Maps map CommCare UCRs to DHIS2 DataSets. ' '<a href="https://github.com/dimagi/commcare-hq/blob/master/corehq/motech/dhis2/README.md#datasets" ' f'target="_new">More info</a>. ' f'Go to <a href="{url}">Configurable Reports</a> to define a UCR.'))
def migrate_linked_reports(upstream_domain=None): logger.setLevel(logging.INFO) if upstream_domain: domain_links = DomainLink.all_objects.filter( master_domain=upstream_domain) else: domain_links = DomainLink.all_objects.all() num_of_failed_attempts = 0 for domain_link in domain_links: reports = get_report_configs_for_domain(domain_link.linked_domain) for report in reports: if report.report_meta.master_id and not report.config.meta.build.app_id: upstream_report = ReportConfiguration.get( report.report_meta.master_id) upstream_datasource = DataSourceConfiguration.get( upstream_report.config_id) downstream_app_id = get_downstream_app_id( domain_link.linked_domain, upstream_datasource.meta.build.app_id, ) if not downstream_app_id: # just as a backup in case upstream_app_id is not set but family_id is downstream_app_id = get_downstream_app_id( domain_link.linked_domain, upstream_datasource.meta.build.app_id, use_upstream_app_id=False) if downstream_app_id: logger.info( f"Needed to use family_id to find downstream app {downstream_app_id}" ) if not downstream_app_id: logger.warning( f"Could not find downstream_app_id for upstream app" f" {upstream_datasource.meta.build.app_id} " f"in downstream domain {domain_link.linked_domain}") num_of_failed_attempts += 1 report.config.meta.build.app_id = downstream_app_id report.config.save() logger.info( f"Completed linked report migration with {num_of_failed_attempts} failed attempts" ) return num_of_failed_attempts
def _get_or_create_report_link(domain_link, report, datasource): domain_reports = get_report_configs_for_domain(domain_link.linked_domain) existing_linked_reports = [ r for r in domain_reports if r.report_meta.master_id == report.get_id ] if existing_linked_reports: return existing_linked_reports[0] report_json = report.to_json() report_json["report_meta"]["master_id"] = report.get_id report_json["domain"] = domain_link.linked_domain report_json["config_id"] = datasource.get_id report_json["_id"] = None report_json["_rev"] = None new_report = ReportConfiguration.wrap(report_json) new_report.save() return new_report
def _release_report(self, domain_link, model): report_id = model['detail']['report_id'] found = False for linked_report in get_report_configs_for_domain(domain_link.linked_domain): if linked_report.report_meta.master_id == report_id: found = True update_linked_ucr(domain_link, linked_report.get_id) if not found: report = ReportConfiguration.get(report_id) if report.report_meta.created_by_builder: view = 'edit_report_in_builder' else: view = 'edit_configurable_report' url = get_url_base() + reverse(view, args=[domain_link.master_domain, report_id]) return self._error_tuple( _('Could not find report. <a href="{}">Click here</a> and click "Link Report" to link this ' + 'report.').format(url), text=_('Could not find report. Please check that the report has been linked.'), )
def _convert_reports_permissions(domain_link, master_results): """Mutates the master result docs to convert dynamic report permissions. """ report_map = get_static_report_mapping(domain_link.master_domain, domain_link.linked_domain) report_map.update({ c.report_meta.master_id: c._id for c in get_report_configs_for_domain(domain_link.linked_domain) }) for role_def in master_results: new_report_perms = [ perm for perm in role_def['permissions']['view_report_list'] if 'DynamicReport' not in perm ] for master_id, linked_id in report_map.items(): master_report_perm = get_ucr_class_name(master_id) if master_report_perm in role_def['permissions']['view_report_list']: new_report_perms.append(get_ucr_class_name(linked_id)) role_def['permissions']['view_report_list'] = new_report_perms
def get_downstream_report(downstream_domain, upstream_report_id): for linked_report in get_report_configs_for_domain(downstream_domain): if linked_report.report_meta.master_id == upstream_report_id: return linked_report return None
def by_domain(cls, domain): return get_report_configs_for_domain(domain)
def update_linked_app(app, master_app_id_or_build, user_id): if not app.domain_link: raise AppLinkError( _('This project is not authorized to update from the master application. ' 'Please contact the maintainer of the master app if you believe this is a mistake. ' )) if isinstance(master_app_id_or_build, str): try: master_build = app.get_latest_master_release( master_app_id_or_build) except ActionNotPermitted: raise AppLinkError( _('This project is not authorized to update from the master application. ' 'Please contact the maintainer of the master app if you believe this is a mistake. ' )) except RemoteAuthError: raise AppLinkError( _('Authentication failure attempting to pull latest master from remote CommCare HQ.' 'Please verify your authentication details for the remote link are correct.' )) except RemoteRequestError: raise AppLinkError( _('Unable to pull latest master from remote CommCare HQ. Please try again later.' )) else: master_build = master_app_id_or_build master_app_id = master_build.origin_id previous = app.get_latest_build_from_upstream(master_app_id) if (previous is None or master_build.version > previous.upstream_version or toggles.MULTI_MASTER_LINKED_DOMAINS.enabled(app.domain)): old_multimedia_ids = set([ media_info.multimedia_id for path, media_info in app.multimedia_map.items() ]) report_map = get_static_report_mapping(master_build.domain, app['domain']) report_map.update({ c.report_meta.master_id: c._id for c in get_report_configs_for_domain(app.domain) if c.report_meta.master_id }) try: app = overwrite_app(app, master_build, report_map) except AppEditingError as e: raise AppLinkError( _('This application uses mobile UCRs ' 'which are not available in the linked domain: {ucr_id}. ' 'Try linking these reports first and try again.').format( ucr_id=str(e))) if app.master_is_remote: try: pull_missing_multimedia_for_app(app, old_multimedia_ids) except RemoteRequestError: raise AppLinkError( _('Error fetching multimedia from remote server. Please try again later.' )) # reapply linked application specific data app.reapply_overrides() app.save() app.domain_link.update_last_pull( 'app', user_id, model_detail=AppLinkDetail(app_id=app._id).to_json()) return app
def get_linked_reports_in_domain(domain): reports = get_report_configs_for_domain(domain) linked_reports = [report for report in reports if report.report_meta.master_id] return linked_reports
def get_linked_report_configs(domain, report_id): domain_reports = get_report_configs_for_domain(domain) existing_linked_reports = [r for r in domain_reports if r.report_meta.master_id == report_id] return existing_linked_reports
def push_models(master_domain, models, linked_domains, build_apps, username): domain_links_by_linked_domain = { link.linked_domain: link for link in get_linked_domains(master_domain) } user = CouchUser.get_by_username(username) errors_by_domain = defaultdict(list) successes_by_domain = defaultdict(list) for linked_domain in linked_domains: if linked_domain not in domain_links_by_linked_domain: errors_by_domain[linked_domain].append( _("Project space {} is no longer linked to {}. No content " "was released to it.").format(master_domain, linked_domain)) continue domain_link = domain_links_by_linked_domain[linked_domain] for model in models: try: found = False updated_app = False built_app = False if model['type'] == MODEL_APP: app_id = model['detail']['app_id'] for linked_app in get_apps_in_domain(linked_domain, include_remote=False): if is_linked_app( linked_app) and linked_app.family_id == app_id: found = True if toggles.MULTI_MASTER_LINKED_DOMAINS.enabled( linked_domain): errors_by_domain[linked_domain].append( textwrap.dedent( _(""" Could not update {} because multi master flag is in use """.strip()).format(model['name']))) continue app = update_linked_app(linked_app, app_id, user.user_id) updated_app = True if build_apps: build = app.make_build() build.is_released = True build.save(increment_version=False) built_app = True elif model['type'] == MODEL_REPORT: report_id = model['detail']['report_id'] for linked_report in get_report_configs_for_domain( linked_domain): if linked_report.report_meta.master_id == report_id: found = True update_linked_ucr(domain_link, linked_report.get_id) elif (model['type'] == MODEL_CASE_SEARCH and not toggles.SYNC_SEARCH_CASE_CLAIM.enabled(linked_domain) ): errors_by_domain[linked_domain].append( textwrap.dedent( _(""" Could not update {} because case claim flag is not on """.strip()).format(model['name']))) continue else: found = True update_model_type(domain_link, model['type'], model_detail=model['detail']) domain_link.update_last_pull(model['type'], user._id, model_details=model['detail']) if found: successes_by_domain[linked_domain].append( _("{} was updated").format(model['name'])) else: errors_by_domain[linked_domain].append( _("Could not find {}").format(model['name'])) except Exception as e: # intentionally broad if model[ 'type'] == MODEL_APP and updated_app and build_apps and not built_app: # Updating an app can be a 2-step process, make it clear which one failed errors_by_domain[linked_domain].append( textwrap.dedent( _(""" Updated {} but could not make and release build: {} """.strip()).format(model['name'], str(e)))) else: errors_by_domain[linked_domain].append( textwrap.dedent( _(""" Could not update {}: {} """.strip()).format(model['name'], str(e)))) notify_exception( None, "Exception pushing linked domains: {}".format(e)) subject = _("Linked project release complete.") if errors_by_domain: subject += _(" Errors occurred.") error_domain_count = len(errors_by_domain) success_domain_count = len(linked_domains) - error_domain_count message = _(""" Release complete. {} project(s) succeeded. {} The following content was released: {} The following linked project spaces received content: """).format( success_domain_count, _("{} project(s) encountered errors.").format(error_domain_count) if error_domain_count else "", "\n".join(["- " + m['name'] for m in models])) for linked_domain in linked_domains: if linked_domain not in errors_by_domain: message += _("\n- {} updated successfully").format(linked_domain) else: message += _("\n- {} encountered errors:").format(linked_domain) for msg in errors_by_domain[linked_domain] + successes_by_domain[ linked_domain]: message += "\n - " + msg send_mail_async.delay(subject, message, settings.DEFAULT_FROM_EMAIL, [user.email or user.username])