示例#1
0
    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)),
        }
示例#2
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]
     )
示例#3
0
    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
示例#4
0
    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
示例#5
0
 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)
示例#6
0
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]
    })
示例#7
0
    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
示例#8
0
    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
示例#9
0
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.'))
示例#10
0
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
示例#11
0
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
示例#12
0
    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.'),
            )
示例#13
0
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
示例#14
0
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
示例#15
0
 def by_domain(cls, domain):
     return get_report_configs_for_domain(domain)
示例#16
0
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
示例#17
0
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
示例#18
0
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
示例#19
0
 def by_domain(cls, domain):
     return get_report_configs_for_domain(domain)
示例#20
0
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])