Exemple #1
0
def get_form_data_schema(request, domain, form_unique_id):
    """Get data schema

    One of `app_id` or `form_unique_id` is required. `app_id` is ignored
    if `form_unique_id` is provided.

    :returns: A list of data source schema definitions. A data source schema
    definition is a dictionary. For details on the content of the dictionary,
    see https://github.com/dimagi/Vellum/blob/master/src/datasources.js
    """
    data = []

    try:
        form, app = Form.get_form(form_unique_id, and_app=True)
    except ResourceConflict:
        raise Http404()

    if app.domain != domain:
        raise Http404()

    try:
        data.append(get_session_schema(form))
        if form.requires_case() or is_usercase_in_use(domain):
            data.append(get_casedb_schema(form))
    except Exception:
        logger.exception("schema error")
        return HttpResponseBadRequest("schema error, see log for details")

    data.extend(
        sorted(item_lists_by_domain(domain), key=lambda x: x['name'].lower())
    )
    kw = {}
    if "pretty" in request.GET:
        kw["indent"] = 2
    return HttpResponse(json.dumps(data, **kw))
Exemple #2
0
def edit_form_actions(request, domain, app_id, form_unique_id):
    app = get_app(domain, app_id)
    form = app.get_form(form_unique_id)
    module = form.get_module()
    old_load_from_form = form.actions.load_from_form
    form.actions = FormActions.wrap(json.loads(request.POST['actions']))
    add_properties_to_data_dictionary(domain, module.case_type, list(form.actions.update_case.update.keys()))
    if old_load_from_form:
        form.actions.load_from_form = old_load_from_form

    for condition in (form.actions.open_case.condition, form.actions.close_case.condition):
        if isinstance(condition.answer, six.string_types):
            soft_assert_type_text(condition.answer)
            condition.answer = condition.answer.strip('"\'')
    form.requires = request.POST.get('requires', form.requires)
    if actions_use_usercase(form.actions):
        if not is_usercase_in_use(domain):
            enable_usercase(domain)
        add_properties_to_data_dictionary(domain, USERCASE_TYPE, list(form.actions.usercase_update.update.keys()))

    response_json = {}
    app.save(response_json)
    response_json['propertiesMap'] = get_all_case_properties(app)
    response_json['usercasePropertiesMap'] = get_usercase_properties(app)
    return json_response(response_json)
Exemple #3
0
def edit_form_actions(request, domain, app_id, form_unique_id):
    app = get_app(domain, app_id)
    form = app.get_form(form_unique_id)
    module = form.get_module()
    old_load_from_form = form.actions.load_from_form
    form.actions = FormActions.wrap(json.loads(request.POST['actions']))
    add_properties_to_data_dictionary(
        domain, module.case_type, list(form.actions.update_case.update.keys()))
    if old_load_from_form:
        form.actions.load_from_form = old_load_from_form

    for condition in (form.actions.open_case.condition,
                      form.actions.close_case.condition):
        if isinstance(condition.answer, six.string_types):
            soft_assert_type_text(condition.answer)
            condition.answer = condition.answer.strip('"\'')
    form.requires = request.POST.get('requires', form.requires)
    if actions_use_usercase(form.actions):
        if not is_usercase_in_use(domain):
            enable_usercase(domain)
        add_properties_to_data_dictionary(
            domain, USERCASE_TYPE,
            list(form.actions.usercase_update.update.keys()))

    response_json = {}
    app.save(response_json)
    response_json['propertiesMap'] = get_all_case_properties(app)
    response_json['usercasePropertiesMap'] = get_usercase_properties(app)
    return json_response(response_json)
Exemple #4
0
def get_form_data_schema(request, domain, app_id, form_unique_id):
    """Get data schema

    :returns: A list of data source schema definitions. A data source schema
    definition is a dictionary. For details on the content of the dictionary,
    see https://github.com/dimagi/Vellum/blob/master/src/datasources.js
    """
    data = []

    app = get_app(domain, app_id)
    form = app.get_form(form_unique_id)

    try:
        data.append(get_session_schema(form))
        if form.requires_case() or is_usercase_in_use(domain):
            data.append(get_casedb_schema(form))
    except AppManagerException as e:
        notify_exception(request, message=str(e))
        return HttpResponseBadRequest(
            str(e) or
            _("There is an error in the case management of your application. "
              "Please fix the error to see case properties in this tree"))
    except Exception as e:
        notify_exception(request, message=str(e))
        return HttpResponseBadRequest("schema error, see log for details")

    data.extend(item_lists_by_domain(domain))
    kw = {}
    if "pretty" in request.GET:
        kw["indent"] = 2
    return HttpResponse(json.dumps(data, **kw))
Exemple #5
0
        def get_commands():
            for form in module.get_suite_forms():
                command = Command(id=id_strings.form_command(form, module))

                if form.requires_case():
                    form_datums = self.entries_helper.get_datums_meta_for_form_generic(form, module)
                    var_name = next(
                        meta.datum.id for meta in reversed(form_datums) if meta.action and meta.requires_selection
                    )
                    case = CaseIDXPath(session_var(var_name)).case()
                else:
                    case = None

                if (
                    getattr(form, "form_filter", None)
                    and not module.put_in_root
                    and (module.all_forms_require_a_case() or is_usercase_in_use(self.app.domain))
                ):
                    fixture_xpath = (
                        session_var(id_strings.fixture_session_var(module)) if module.fixture_select.active else None
                    )
                    command.relevant = interpolate_xpath(form.form_filter, case, fixture_xpath)

                if getattr(module, "has_schedule", False) and module.all_forms_require_a_case():
                    # If there is a schedule and another filter condition, disregard it...
                    # Other forms of filtering are disabled in the UI

                    schedule_filter_condition = MenuContributor._schedule_filter_conditions(form, module, case)
                    if schedule_filter_condition is not None:
                        command.relevant = schedule_filter_condition

                yield command

            if hasattr(module, "case_list") and module.case_list.show:
                yield Command(id=id_strings.case_list_command(module))
def get_usercase_properties(app):
    if is_usercase_in_use(app.domain):
        # TODO: add name here once it is fixed to concatenate first and last in form builder
        default_properties = {'first_name', 'last_name', 'phone_number', 'username'}
        case_properties = get_case_properties(app, [USERCASE_TYPE])
        case_properties[USERCASE_TYPE] = list(set(case_properties[USERCASE_TYPE]) | default_properties)
        return case_properties
    return {USERCASE_TYPE: []}
def get_usercase_properties(app):
    if is_usercase_in_use(app.domain):
        # TODO: add name here once it is fixed to concatenate first and last in form builder
        default_properties = {'first_name', 'last_name', 'phone_number', 'username'}
        case_properties = get_case_properties(app, [USERCASE_TYPE])
        case_properties[USERCASE_TYPE] = list(set(case_properties[USERCASE_TYPE]) | default_properties)
        return case_properties
    return {USERCASE_TYPE: []}
Exemple #8
0
def _setup_case_property_builder(app):
    defaults = ('name', 'date-opened', 'status', 'last_modified')
    if app.case_sharing:
        defaults += ('#owner_name',)
    per_type_defaults = None
    if is_usercase_in_use(app.domain):
        per_type_defaults = get_per_type_defaults(app.domain, [USERCASE_TYPE])
    builder = ParentCasePropertyBuilder(app, defaults=defaults,
                                        per_type_defaults=per_type_defaults)
    return builder
Exemple #9
0
def _setup_case_property_builder(app):
    defaults = ('name', 'date-opened', 'status')
    if app.case_sharing:
        defaults += ('#owner_name',)
    per_type_defaults = None
    if is_usercase_in_use(app.domain):
        per_type_defaults = get_per_type_defaults(app.domain, [USERCASE_TYPE])
    builder = ParentCasePropertyBuilder(app, defaults=defaults,
                                        per_type_defaults=per_type_defaults)
    return builder
Exemple #10
0
def filter_cases(request, domain, app_id, module_id, parent_id=None):
    app = Application.get(app_id)
    module = app.get_module(module_id)
    auth_cookie = request.COOKIES.get('sessionid')

    suite_gen = SuiteGenerator(app, is_usercase_in_use(domain))
    xpath = suite_gen.get_filter_xpath(module)
    extra_instances = [{'id': inst.id, 'src': inst.src}
                       for inst in suite_gen.get_instances_for_module(module, additional_xpaths=[xpath])]

    # touchforms doesn't like this to be escaped
    xpath = HTMLParser.HTMLParser().unescape(xpath)
    case_type = module.case_type

    if xpath:
        # if we need to do a custom filter, send it to touchforms for processing
        additional_filters = {
            "properties/case_type": case_type,
            "footprint": True
        }

        helper = SessionDataHelper(domain, request.couch_user)
        result = helper.filter_cases(xpath, additional_filters, DjangoAuth(auth_cookie),
                                     extra_instances=extra_instances)
        if result.get('status', None) == 'error':
            code = result.get('code', 500)
            message = result.get('message', _("Something went wrong filtering your cases."))
            if code == 500:
                notify_exception(None, message=message)
            return json_response(message, status_code=code)

        case_ids = result.get("cases", [])
    else:
        # otherwise just use our built in api with the defaults
        case_ids = [res.id for res in get_filtered_cases(
            domain,
            status=CASE_STATUS_OPEN,
            case_type=case_type,
            user_id=request.couch_user._id,
            footprint=True,
            ids_only=True,
        )]

    cases = [CommCareCase.wrap(doc) for doc in iter_docs(CommCareCase.get_db(), case_ids)]

    if parent_id:
        cases = filter(lambda c: c.parent and c.parent.case_id == parent_id, cases)

    # refilter these because we might have accidentally included footprint cases
    # in the results from touchforms. this is a little hacky but the easiest
    # (quick) workaround. should be revisted when we optimize the case list.
    cases = filter(lambda c: c.type == case_type, cases)
    cases = [c.get_json(lite=True) for c in cases if c]

    return json_response(cases)
Exemple #11
0
def edit_advanced_form_actions(request, domain, app_id, module_id, form_id):
    app = get_app(domain, app_id)
    form = app.get_module(module_id).get_form(form_id)
    json_loads = json.loads(request.POST.get('actions'))
    actions = AdvancedFormActions.wrap(json_loads)
    form.actions = actions
    if advanced_actions_use_usercase(form.actions) and not is_usercase_in_use(domain):
        enable_usercase(domain)
    response_json = {}
    app.save(response_json)
    response_json['propertiesMap'] = get_all_case_properties(app)
    return json_response(response_json)
Exemple #12
0
def edit_advanced_form_actions(request, domain, app_id, module_id, form_id):
    app = get_app(domain, app_id)
    form = app.get_module(module_id).get_form(form_id)
    json_loads = json.loads(request.POST.get('actions'))
    actions = AdvancedFormActions.wrap(json_loads)
    form.actions = actions
    if advanced_actions_use_usercase(form.actions) and not is_usercase_in_use(domain):
        enable_usercase(domain)
    response_json = {}
    app.save(response_json)
    response_json['propertiesMap'] = get_all_case_properties(app)
    return json_response(response_json)
Exemple #13
0
def get_session_schema(form):
    """Get form session schema definition
    """
    from corehq.apps.app_manager.suite_xml.sections.entries import EntriesHelper
    app = form.get_app()
    structure = {}
    datums = EntriesHelper(app).get_datums_meta_for_form_generic(form)
    datums = [
        d for d in datums
        if not d.is_new_case_id and d.case_type and d.requires_selection
    ]
    if len(datums):
        session_var = datums[-1].datum.id
        structure["data"] = {
            "merge": True,
            "structure": {
                session_var: {
                    "reference": {
                        "hashtag": "#case",
                        "source": "casedb",
                        "subset": "case",
                        "key": "@case_id",
                    },
                },
            },
        }
    if is_usercase_in_use(
            app.domain) and toggles.USER_PROPERTY_EASY_REFS.enabled(
                app.domain):
        structure["context"] = {
            "merge": True,
            "structure": {
                "userid": {
                    "reference": {
                        "hashtag": "#user",
                        "source": "casedb",
                        "subset": USERCASE_TYPE,
                        "subset_key": "@case_type",
                        "subset_filter": True,
                        "key": "hq_user_id",
                    },
                },
            },
        }
    return {
        "id": "commcaresession",
        "uri": "jr://instance/session",
        "name": "Session",
        "path": "/session",
        "structure": structure,
    }
def get_per_type_defaults(domain, case_types=None):
    from corehq.apps.callcenter.utils import get_call_center_case_type_if_enabled

    per_type_defaults = {}
    if (not case_types and is_usercase_in_use(domain)) or USERCASE_TYPE in case_types:
        per_type_defaults = {
            USERCASE_TYPE: get_usercase_default_properties(domain)
        }

    callcenter_case_type = get_call_center_case_type_if_enabled(domain)
    if callcenter_case_type and (not case_types or callcenter_case_type in case_types):
        per_type_defaults[callcenter_case_type] = get_usercase_default_properties(domain)

    return per_type_defaults
Exemple #15
0
def edit_advanced_form_actions(request, domain, app_id, module_id, form_id):
    app = get_app(domain, app_id)
    form = app.get_module(module_id).get_form(form_id)
    json_loads = json.loads(request.POST.get('actions'))
    actions = AdvancedFormActions.wrap(json_loads)
    form.actions = actions
    for action in actions.load_update_cases:
        add_properties_to_data_dictionary(domain, action.case_type, action.case_properties.keys())
    if advanced_actions_use_usercase(form.actions) and not is_usercase_in_use(domain):
        enable_usercase(domain)
    response_json = {}
    app.save(response_json)
    response_json['propertiesMap'] = get_all_case_properties(app)
    return json_response(response_json)
Exemple #16
0
def edit_advanced_form_actions(request, domain, app_id, module_id, form_id):
    app = get_app(domain, app_id)
    form = app.get_module(module_id).get_form(form_id)
    json_loads = json.loads(request.POST.get('actions'))
    actions = AdvancedFormActions.wrap(json_loads)
    form.actions = actions
    for action in actions.load_update_cases:
        add_properties_to_data_dictionary(domain, action.case_type, action.case_properties.keys())
    if advanced_actions_use_usercase(form.actions) and not is_usercase_in_use(domain):
        enable_usercase(domain)
    response_json = {}
    app.save(response_json)
    response_json['propertiesMap'] = get_all_case_properties(app)
    return json_response(response_json)
def get_per_type_defaults(domain):
    """Get default properties for callcenter and usercases"""
    from corehq.apps.callcenter.utils import get_call_center_case_type_if_enabled

    per_type_defaults = {}
    if is_usercase_in_use(domain):
        per_type_defaults = {
            USERCASE_TYPE: _get_usercase_default_properties(domain)
        }

    callcenter_case_type = get_call_center_case_type_if_enabled(domain)
    if callcenter_case_type:
        per_type_defaults[callcenter_case_type] = _get_usercase_default_properties(domain)

    return per_type_defaults
Exemple #18
0
def get_per_type_defaults(domain):
    """Get default properties for callcenter and usercases"""
    from corehq.apps.callcenter.utils import get_call_center_case_type_if_enabled

    per_type_defaults = {}
    if is_usercase_in_use(domain):
        per_type_defaults = {
            USERCASE_TYPE: _get_usercase_default_properties(domain)
        }

    callcenter_case_type = get_call_center_case_type_if_enabled(domain)
    if callcenter_case_type:
        per_type_defaults[callcenter_case_type] = _get_usercase_default_properties(domain)

    return per_type_defaults
Exemple #19
0
def edit_form_actions(request, domain, app_id, module_id, form_id):
    app = get_app(domain, app_id)
    form = app.get_module(module_id).get_form(form_id)
    form.actions = FormActions.wrap(json.loads(request.POST['actions']))
    for condition in (form.actions.open_case.condition, form.actions.close_case.condition):
        if isinstance(condition.answer, basestring):
            condition.answer = condition.answer.strip('"\'')
    form.requires = request.POST.get('requires', form.requires)
    if actions_use_usercase(form.actions) and not is_usercase_in_use(domain):
        enable_usercase(domain)
    response_json = {}
    app.save(response_json)
    response_json['propertiesMap'] = get_all_case_properties(app)
    response_json['usercasePropertiesMap'] = get_usercase_properties(app)
    return json_response(response_json)
Exemple #20
0
def _get_module_details_context(app, module, case_property_builder,
                                case_type_):
    subcase_types = list(app.get_subcase_types(module.case_type))
    item = {
        'label': gettext_lazy('Case List'),
        'detail_label': gettext_lazy('Case Detail'),
        'type': 'case',
        'model': 'case',
        'subcase_types': subcase_types,
        'sort_elements': module.case_details.short.sort_elements,
        'short': module.case_details.short,
        'long': module.case_details.long,
    }
    case_properties = case_property_builder.get_properties(case_type_)
    if is_usercase_in_use(app.domain) and case_type_ != USERCASE_TYPE:
        usercase_properties = prefix_usercase_properties(
            case_property_builder.get_properties(USERCASE_TYPE))
        case_properties |= usercase_properties

    item['properties'] = sorted(case_properties)
    item['fixture_select'] = module.fixture_select

    if isinstance(module, AdvancedModule):
        details = [item]
        if app.commtrack_enabled:
            details.append({
                'label':
                gettext_lazy('Product List'),
                'detail_label':
                gettext_lazy('Product Detail'),
                'type':
                'product',
                'model':
                'product',
                'properties': ['name'] +
                commtrack_ledger_sections(app.commtrack_requisition_mode),
                'sort_elements':
                module.product_details.short.sort_elements,
                'short':
                module.product_details.short,
                'subcase_types':
                subcase_types,
            })
    else:
        item['parent_select'] = module.parent_select
        details = [item]

    return details
Exemple #21
0
def edit_advanced_form_actions(request, domain, app_id, form_unique_id):
    app = get_app(domain, app_id)
    form = app.get_form(form_unique_id)
    json_loads = json.loads(request.POST.get('actions'))
    actions = AdvancedFormActions.wrap(json_loads)
    if form.form_type == "shadow_form":
        form.extra_actions = actions
    else:
        form.actions = actions
    for action in actions.load_update_cases:
        add_properties_to_data_dictionary(domain, action.case_type, list(action.case_properties.keys()))
    if advanced_actions_use_usercase(actions) and not is_usercase_in_use(domain):
        enable_usercase(domain)
    response_json = {}
    app.save(response_json)
    response_json['propertiesMap'] = get_all_case_properties(app)
    return JsonResponse(response_json)
def _get_vellum_plugins(domain, form, module):
    """
    Returns a list of enabled vellum plugins based on the domain's
    privileges.
    """
    vellum_plugins = ["modeliteration", "itemset", "atwho"]
    if toggles.COMMTRACK.enabled(domain):
        vellum_plugins.append("commtrack")
    if toggles.VELLUM_SAVE_TO_CASE.enabled(domain):
        vellum_plugins.append("saveToCase")

    form_uses_case = ((module and module.case_type and form.requires_case())
                      or is_usercase_in_use(domain))
    form_is_basic = form.doc_type == 'Form'
    if form_uses_case and form_is_basic:
        vellum_plugins.append("databrowser")

    return vellum_plugins
Exemple #23
0
def edit_form_actions(request, domain, app_id, module_id, form_id):
    app = get_app(domain, app_id)
    form = app.get_module(module_id).get_form(form_id)
    old_load_from_form = form.actions.load_from_form
    form.actions = FormActions.wrap(json.loads(request.POST['actions']))
    if old_load_from_form:
        form.actions.load_from_form = old_load_from_form

    for condition in (form.actions.open_case.condition, form.actions.close_case.condition):
        if isinstance(condition.answer, basestring):
            condition.answer = condition.answer.strip('"\'')
    form.requires = request.POST.get('requires', form.requires)
    if actions_use_usercase(form.actions) and not is_usercase_in_use(domain):
        enable_usercase(domain)
    response_json = {}
    app.save(response_json)
    response_json['propertiesMap'] = get_all_case_properties(app)
    response_json['usercasePropertiesMap'] = get_usercase_properties(app)
    return json_response(response_json)
Exemple #24
0
def form_context(request, domain, app_id, module_id, form_id):
    app = Application.get(app_id)
    form_url = "%s%s" % (get_url_base(), reverse('download_xform', args=[domain, app_id, module_id, form_id]))
    case_id = request.GET.get('case_id')
    instance_id = request.GET.get('instance_id')
    try:
        form = app.get_module(module_id).get_form(form_id)
    except (FormNotFoundException, ModuleNotFoundException):
        raise Http404()

    form_name = form.name.values()[0]

    # make the name for the session we will use with the case and form
    session_name = u'{app} > {form}'.format(
        app=app.name,
        form=form_name,
    )
    if case_id:
        session_name = u'{0} - {1}'.format(session_name, CommCareCase.get(case_id).name)

    root_context = {
        'form_url': form_url,
    }
    if instance_id:
        try:
            root_context['instance_xml'] = XFormInstance.get_db().fetch_attachment(
                instance_id, ATTACHMENT_NAME
            )
        except ResourceNotFound:
            raise Http404()


    session_extras = {'session_name': session_name, 'app_id': app._id}
    suite_gen = SuiteGenerator(app, is_usercase_in_use(domain))
    session_extras.update(get_cloudcare_session_data(suite_gen, domain, form, request.couch_user))

    delegation = request.GET.get('task-list') == 'true'
    offline = request.GET.get('offline') == 'true'
    session_helper = SessionDataHelper(domain, request.couch_user, case_id, delegation=delegation, offline=offline)
    return json_response(session_helper.get_full_context(
        root_context,
        session_extras
    ))
Exemple #25
0
def get_form_data_schema(request, domain, form_unique_id):
    """Get data schema

    One of `app_id` or `form_unique_id` is required. `app_id` is ignored
    if `form_unique_id` is provided.

    :returns: A list of data source schema definitions. A data source schema
    definition is a dictionary. For details on the content of the dictionary,
    see https://github.com/dimagi/Vellum/blob/master/src/datasources.js
    """
    data = []

    try:
        form, app = Form.get_form(form_unique_id, and_app=True)
    except ResourceConflict:
        raise Http404()

    if app.domain != domain:
        raise Http404()

    try:
        data.append(get_session_schema(form))
        if form.requires_case() or is_usercase_in_use(domain):
            data.append(get_casedb_schema(form))
    except AppManagerException as e:
        notify_exception(request, message=str(e))
        return HttpResponseBadRequest(
            str(e) or _("There is an error in the case management of your application. "
            "Please fix the error to see case properties in this tree")
        )
    except Exception as e:
        notify_exception(request, message=six.text_type(e))
        return HttpResponseBadRequest("schema error, see log for details")

    data.extend(
        sorted(item_lists_by_domain(domain), key=lambda x: x['name'].lower())
    )
    kw = {}
    if "pretty" in request.GET:
        kw["indent"] = 2
    return HttpResponse(json.dumps(data, **kw))
Exemple #26
0
def _get_vellum_plugins(domain, form, module):
    """
    Returns a list of enabled vellum plugins based on the domain's
    privileges.
    """
    vellum_plugins = ["modeliteration", "itemset", "atwho"]
    if (toggles.COMMTRACK.enabled(domain)
            or toggles.NON_COMMTRACK_LEDGERS.enabled(domain)):
        vellum_plugins.append("commtrack")
    if toggles.VELLUM_SAVE_TO_CASE.enabled(domain):
        vellum_plugins.append("saveToCase")

    form_uses_case = (
        (module and module.case_type and form.requires_case()) or
        is_usercase_in_use(domain)
    )
    form_is_basic = form.doc_type == 'Form'
    if form_uses_case and form_is_basic:
        vellum_plugins.append("databrowser")

    return vellum_plugins
Exemple #27
0
def _get_module_details_context(app, module, case_property_builder, case_type_):
    subcase_types = list(app.get_subcase_types(module.case_type))
    item = {
        'label': gettext_lazy('Case List'),
        'detail_label': gettext_lazy('Case Detail'),
        'type': 'case',
        'model': 'case',
        'subcase_types': subcase_types,
        'sort_elements': module.case_details.short.sort_elements,
        'short': module.case_details.short,
        'long': module.case_details.long,
    }
    case_properties = case_property_builder.get_properties(case_type_)
    if is_usercase_in_use(app.domain) and case_type_ != USERCASE_TYPE:
        usercase_properties = prefix_usercase_properties(case_property_builder.get_properties(USERCASE_TYPE))
        case_properties |= usercase_properties

    item['properties'] = sorted(case_properties)
    item['fixture_select'] = module.fixture_select

    if isinstance(module, AdvancedModule):
        details = [item]
        if app.commtrack_enabled:
            details.append({
                'label': gettext_lazy('Product List'),
                'detail_label': gettext_lazy('Product Detail'),
                'type': 'product',
                'model': 'product',
                'properties': ['name'] + commtrack_ledger_sections(app.commtrack_requisition_mode),
                'sort_elements': module.product_details.short.sort_elements,
                'short': module.product_details.short,
                'subcase_types': subcase_types,
            })
    else:
        item['parent_select'] = module.parent_select
        details = [item]

    return details
Exemple #28
0
def get_casedb_schema(form):
    """Get case database schema definition for vellum to display as an external data source.

    This lists all case types and their properties for the given app.
    """
    app = form.get_app()

    subsets = []
    if form.requires_case() and not form.get_module().search_config.data_registry:
        subsets.extend(_get_case_schema_subsets(app, form.get_module().case_type))

    parent_select = getattr(form.get_module(), 'parent_select', None)
    if parent_select and parent_select.active and parent_select.relationship is None:
        # for child modules that use parent select where the parent is not a 'related' case
        # See toggles.NON_PARENT_MENU_SELECTION
        parent_module = app.get_module_by_unique_id(parent_select.module_id)
        source = clean_trans(parent_module.name, app.langs)
        subsets.extend(_get_case_schema_subsets(app, parent_module.case_type, source=source))


    if is_usercase_in_use(app.domain):
        subsets.append({
            "id": USERCASE_TYPE,
            "name": "user",
            "key": "@case_type",
            "structure": {p: {} for p in get_usercase_properties(app)[USERCASE_TYPE]},
        })

    return {
        "id": "casedb",
        "uri": "jr://instance/casedb",
        "name": "case",
        "path": "/casedb/case",
        "structure": {},
        "subsets": subsets,
    }
Exemple #29
0
def get_form_view_context_and_template(request, domain, form, langs, current_lang, messages=messages):
    xform_questions = []
    xform = None
    form_errors = []
    xform_validation_errored = False
    xform_validation_missing = False

    try:
        xform = form.wrapped_xform()
    except XFormException as e:
        form_errors.append("Error in form: %s" % e)
    except Exception as e:
        logging.exception(e)
        form_errors.append("Unexpected error in form: %s" % e)

    has_case_error = False
    if xform and xform.exists():
        if xform.already_has_meta():
            messages.warning(
                request,
                "This form has a meta block already! "
                "It may be replaced by CommCare HQ's standard meta block."
            )

        try:
            xform_questions = xform.get_questions(langs, include_triggers=True)
            form.validate_form()
        except etree.XMLSyntaxError as e:
            form_errors.append("Syntax Error: %s" % e)
        except AppEditingError as e:
            form_errors.append("Error in application: %s" % e)
        except XFormValidationError:
            xform_validation_errored = True
            # showing these messages is handled by validate_form_for_build ajax
        except XFormValidationFailed:
            xform_validation_missing = True
            messages.warning(request, _("Unable to validate form due to server error."))
        except XFormException as e:
            form_errors.append("Error in form: %s" % e)
        # any other kind of error should fail hard,
        # but for now there are too many for that to be practical
        except Exception as e:
            if settings.DEBUG:
                raise
            notify_exception(request, 'Unexpected Build Error')
            form_errors.append("Unexpected System Error: %s" % e)
        else:
            # remove upload questions (attachments) until MM Case Properties
            # are released to general public
            is_previewer = toggles.MM_CASE_PROPERTIES.enabled_for_request(request)
            xform_questions = [q for q in xform_questions
                               if q["tag"] != "upload" or is_previewer]

        if not form_errors and not xform_validation_missing and not xform_validation_errored:
            try:
                form_action_errors = form.validate_for_build()
                if not form_action_errors:
                    form.add_stuff_to_xform(xform)
            except CaseError as e:
                has_case_error = True
                messages.error(request, "Error in Case Management: %s" % e)
            except XFormException as e:
                messages.error(request, str(e))
            except Exception as e:
                if settings.DEBUG:
                    raise
                logging.exception(str(e))
                messages.error(request, "Unexpected Error: %s" % e)

    try:
        languages = xform.get_languages()
    except Exception:
        languages = []

    for err in form_errors:
        messages.error(request, err)

    module_case_types = []
    app = form.get_app()
    all_modules = list(app.get_modules())
    for module in all_modules:
        for case_type in module.get_case_types():
            module_case_types.append({
                'id': module.unique_id,
                'module_name': trans(module.name, langs),
                'case_type': case_type,
                'module_type': module.doc_type
            })
    module = form.get_module()

    if not form.unique_id:
        form.get_unique_id()
        app.save()

    allow_usercase = domain_has_privilege(request.domain, privileges.USERCASE)
    valid_index_names = list(DEFAULT_CASE_INDEX_IDENTIFIERS.values())
    if allow_usercase:
        valid_index_names.append(USERCASE_PREFIX[0:-1])     # strip trailing slash

    form_has_schedule = isinstance(form, AdvancedForm) and module.has_schedule

    try:
        case_properties_map = get_all_case_properties(app)
        usercase_properties_map = get_usercase_properties(app)
    except CaseError as e:
        case_properties_map = {}
        usercase_properties_map = {}
        if not has_case_error:
            messages.error(request, "Error in Case Management: %s" % e)

    case_config_options = {
        'caseType': form.get_case_type(),
        'moduleCaseTypes': module_case_types,
        'propertiesMap': case_properties_map,
        'propertyDescriptions': get_case_property_description_dict(domain),
        'questions': xform_questions,
        'reserved_words': load_case_reserved_words(),
        'usercasePropertiesMap': usercase_properties_map,
    }
    context = {
        'nav_form': form,
        'xform_languages': languages,
        'form_errors': form_errors,
        'xform_validation_errored': xform_validation_errored,
        'xform_validation_missing': xform_validation_missing,
        'allow_form_copy': isinstance(form, (Form, AdvancedForm)),
        'allow_form_filtering': not form_has_schedule,
        'uses_form_workflow': form.post_form_workflow == WORKFLOW_FORM,
        'allow_usercase': allow_usercase,
        'is_usercase_in_use': is_usercase_in_use(request.domain),
        'is_module_filter_enabled': app.enable_module_filtering,
        'is_training_module': module.is_training_module,
        'is_allowed_to_be_release_notes_form': form.is_allowed_to_be_release_notes_form,
        'root_requires_same_case': module.root_requires_same_case(),
        'is_case_list_form': form.is_case_list_form,
        'edit_name_url': reverse('edit_form_attr', args=[app.domain, app.id, form.unique_id, 'name']),
        'form_filter_patterns': {
            'case_substring': CASE_XPATH_SUBSTRING_MATCHES,
            'usercase_substring': USERCASE_XPATH_SUBSTRING_MATCHES,
        },
        'custom_instances': [
            {'instanceId': instance.instance_id, 'instancePath': instance.instance_path}
            for instance in form.custom_instances
        ],
        'custom_assertions': [
            {'test': assertion.test, 'text': assertion.text.get(current_lang)}
            for assertion in form.custom_assertions
        ],
        'form_icon': None,
        'session_endpoints_enabled': toggles.SESSION_ENDPOINTS.enabled(domain),
        'module_is_multi_select': module.is_multi_select(),
        'module_loads_registry_case': module_loads_registry_case(module),
    }

    if toggles.CUSTOM_ICON_BADGES.enabled(domain):
        context['form_icon'] = form.custom_icon if form.custom_icon else CustomIcon()

    if toggles.COPY_FORM_TO_APP.enabled_for_request(request):
        context['apps_modules'] = get_apps_modules(domain, app.id, module.unique_id)

    if toggles.FORM_LINK_WORKFLOW.enabled(domain):
        context.update(_get_form_link_context(module, langs))

    if isinstance(form, AdvancedForm):
        def commtrack_programs():
            if app.commtrack_enabled:
                programs = Program.by_domain(app.domain)
                return [{'value': program.get_id, 'label': program.name} for program in programs]
            else:
                return []

        all_programs = [{'value': '', 'label': _('All Programs')}]
        case_config_options.update({
            'commtrack_enabled': app.commtrack_enabled,
            'commtrack_programs': all_programs + commtrack_programs(),
            'module_id': module.unique_id,
            'save_url': reverse("edit_advanced_form_actions", args=[app.domain, app.id, form.unique_id]),
            'arbitrary_datums': form.arbitrary_datums,
        })
        if form.form_type == "shadow_form":
            case_config_options.update({
                'actions': form.extra_actions,
                'isShadowForm': True,
            })
        else:
            case_config_options.update({
                'actions': form.actions,
                'isShadowForm': False,
            })
        if getattr(module, 'has_schedule', False):
            schedule_options = get_schedule_context(form)
            schedule_options.update({
                'phase': schedule_options['schedule_phase'],
                'questions': xform_questions,
                'save_url': reverse("edit_visit_schedule", args=[app.domain, app.id, form.unique_id]),
                'schedule': form.schedule,
            })
            context.update({
                'schedule_options': schedule_options,
            })
    else:
        context.update({
            'show_custom_ref': toggles.APP_BUILDER_CUSTOM_PARENT_REF.enabled_for_request(request),
        })
        case_config_options.update({
            'actions': form.actions,
            'allowUsercase': allow_usercase,
            'save_url': reverse("edit_form_actions", args=[app.domain, app.id, form.unique_id]),
            'valid_index_names': valid_index_names,
        })

    context.update({'case_config_options': case_config_options})
    return "app_manager/form_view.html", context
Exemple #30
0
def get_usercase_properties(app):
    if is_usercase_in_use(app.domain):
        return get_case_properties(app, [USERCASE_TYPE])
    return {USERCASE_TYPE: []}
Exemple #31
0
def get_form_view_context_and_template(request,
                                       domain,
                                       form,
                                       langs,
                                       messages=messages):
    xform_questions = []
    xform = None
    form_errors = []
    xform_validation_errored = False
    xform_validation_missing = False

    try:
        xform = form.wrapped_xform()
    except XFormException as e:
        form_errors.append(u"Error in form: %s" % e)
    except Exception as e:
        logging.exception(e)
        form_errors.append(u"Unexpected error in form: %s" % e)

    if xform and xform.exists():
        if xform.already_has_meta():
            messages.warning(
                request, "This form has a meta block already! "
                "It may be replaced by CommCare HQ's standard meta block.")

        try:
            xform_questions = xform.get_questions(langs, include_triggers=True)
            form.validate_form()
        except etree.XMLSyntaxError as e:
            form_errors.append(u"Syntax Error: %s" % e)
        except AppEditingError as e:
            form_errors.append(u"Error in application: %s" % e)
        except XFormValidationError:
            xform_validation_errored = True
            # showing these messages is handled by validate_form_for_build ajax
            pass
        except XFormValidationFailed:
            xform_validation_missing = True
            messages.warning(request,
                             _("Unable to validate form due to server error."))
        except XFormException as e:
            form_errors.append(u"Error in form: %s" % e)
        # any other kind of error should fail hard,
        # but for now there are too many for that to be practical
        except Exception as e:
            if settings.DEBUG:
                raise
            notify_exception(request, 'Unexpected Build Error')
            form_errors.append(u"Unexpected System Error: %s" % e)
        else:
            # remove upload questions (attachemnts) until MM Case Properties
            # are released to general public
            is_previewer = toggles.MM_CASE_PROPERTIES.enabled(
                request.user.username)
            xform_questions = [
                q for q in xform_questions
                if q["tag"] != "upload" or is_previewer
            ]

        if not form_errors and not xform_validation_missing and not xform_validation_errored:
            try:
                form_action_errors = form.validate_for_build()
                if not form_action_errors:
                    form.add_stuff_to_xform(xform)
            except CaseError as e:
                messages.error(request, u"Error in Case Management: %s" % e)
            except XFormException as e:
                messages.error(request, unicode(e))
            except Exception as e:
                if settings.DEBUG:
                    raise
                logging.exception(unicode(e))
                messages.error(request, u"Unexpected Error: %s" % e)

    try:
        languages = xform.get_languages()
    except Exception:
        languages = []

    for err in form_errors:
        messages.error(request, err)

    module_case_types = []
    app = form.get_app()
    all_modules = list(app.get_modules())
    for module in all_modules:
        for case_type in module.get_case_types():
            module_case_types.append({
                'id': module.unique_id,
                'module_name': trans(module.name, langs),
                'case_type': case_type,
                'module_type': module.doc_type
            })

    if not form.unique_id:
        form.get_unique_id()
        app.save()

    allow_usercase = domain_has_privilege(request.domain, privileges.USER_CASE)
    valid_index_names = DEFAULT_CASE_INDEX_IDENTIFIERS.values()
    if allow_usercase:
        valid_index_names.append(USERCASE_PREFIX[0:-1])  # strip trailing slash

    form_has_schedule = isinstance(
        form, AdvancedForm) and form.get_module().has_schedule
    case_config_options = {
        'caseType': form.get_case_type(),
        'moduleCaseTypes': module_case_types,
        'propertiesMap': get_all_case_properties(app),
        'questions': xform_questions,
        'reserved_words': load_case_reserved_words(),
    }
    context = {
        'nav_form':
        form,
        'xform_languages':
        languages,
        "xform_questions":
        xform_questions,
        'form_errors':
        form_errors,
        'xform_validation_errored':
        xform_validation_errored,
        'xform_validation_missing':
        xform_validation_missing,
        'allow_cloudcare':
        isinstance(form, Form),
        'allow_form_copy':
        isinstance(form, (Form, AdvancedForm)),
        'allow_form_filtering':
        not isinstance(form, CareplanForm) and not form_has_schedule,
        'allow_form_workflow':
        not isinstance(form, CareplanForm),
        'uses_form_workflow':
        form.post_form_workflow == WORKFLOW_FORM,
        'allow_usercase':
        allow_usercase,
        'is_usercase_in_use':
        is_usercase_in_use(request.domain),
        'is_module_filter_enabled':
        app.enable_module_filtering,
        'is_case_list_form':
        form.is_case_list_form,
        'edit_name_url':
        reverse('edit_form_attr',
                args=[app.domain, app.id, form.unique_id, 'name']),
        'case_xpath_pattern_matches':
        CASE_XPATH_PATTERN_MATCHES,
        'case_xpath_substring_matches':
        CASE_XPATH_SUBSTRING_MATCHES,
        'user_case_xpath_pattern_matches':
        USER_CASE_XPATH_PATTERN_MATCHES,
        'user_case_xpath_substring_matches':
        USER_CASE_XPATH_SUBSTRING_MATCHES,
        'custom_instances': [{
            'instanceId': instance.instance_id,
            'instancePath': instance.instance_path
        } for instance in form.custom_instances],
        'can_preview_form':
        request.couch_user.has_permission(domain, 'edit_data')
    }

    if tours.NEW_APP.is_enabled(
            request.user) and not toggles.APP_MANAGER_V2.enabled(
                request.user.username):
        request.guided_tour = tours.NEW_APP.get_tour_data()

    if context['allow_form_workflow'] and toggles.FORM_LINK_WORKFLOW.enabled(
            domain):
        module = form.get_module()

        def qualified_form_name(form, auto_link):
            module_name = trans(form.get_module().name, langs)
            form_name = trans(form.name, langs)
            star = '* ' if auto_link else '  '
            return u"{}{} -> {}".format(star, module_name, form_name)

        modules = filter(lambda m: m.case_type == module.case_type,
                         all_modules)
        if getattr(module, 'root_module_id',
                   None) and module.root_module not in modules:
            modules.append(module.root_module)
        auto_linkable_forms = list(
            itertools.chain.from_iterable(
                list(m.get_forms()) for m in modules))

        def linkable_form(candidate_form):
            auto_link = candidate_form in auto_linkable_forms
            return {
                'unique_id': candidate_form.unique_id,
                'name': qualified_form_name(candidate_form, auto_link),
                'auto_link': auto_link
            }

        context['linkable_forms'] = [
            linkable_form(candidate_form) for candidate_module in all_modules
            for candidate_form in candidate_module.get_forms()
        ]

    if isinstance(form, CareplanForm):
        case_config_options.update({
            'save_url':
            reverse("edit_careplan_form_actions",
                    args=[app.domain, app.id, module.id, form.id]),
            'case_preload': [{
                'key': key,
                'path': path
            } for key, path in form.case_preload.items()],
            'customCaseUpdates': [{
                'key': key,
                'path': path
            } for key, path in form.custom_case_updates.items()],
            'fixedQuestions':
            form.get_fixed_questions(),
            'mode':
            form.mode,
        })
    elif isinstance(form, AdvancedForm):

        def commtrack_programs():
            if app.commtrack_enabled:
                programs = Program.by_domain(app.domain)
                return [{
                    'value': program.get_id,
                    'label': program.name
                } for program in programs]
            else:
                return []

        all_programs = [{'value': '', 'label': _('All Programs')}]
        case_config_options.update({
            'save_url':
            reverse("edit_advanced_form_actions",
                    args=[app.domain, app.id, module.id, form.id]),
            'commtrack_enabled':
            app.commtrack_enabled,
            'commtrack_programs':
            all_programs + commtrack_programs(),
            'module_id':
            module.unique_id,
            'propertyDescriptions':
            get_case_property_description_dict(domain),
        })
        if form.form_type == "shadow_form":
            case_config_options.update({
                'actions': form.extra_actions,
                'isShadowForm': True,
            })
        else:
            case_config_options.update({
                'actions': form.actions,
                'isShadowForm': False,
            })

        if module.has_schedule:
            visit_scheduler_options = get_schedule_context(form)
            visit_scheduler_options.update({
                'questions':
                xform_questions,
                'save_url':
                reverse("edit_visit_schedule",
                        args=[app.domain, app.id, module.id, form.id]),
                'schedule':
                form.schedule,
                'phase':
                visit_scheduler_options['schedule_phase'],
            })
            context.update(
                {'visit_scheduler_options': visit_scheduler_options})
    else:
        case_config_options.update({
            'actions':
            form.actions,
            'allowUsercase':
            allow_usercase,
            'valid_index_names':
            valid_index_names,
            'usercasePropertiesMap':
            get_usercase_properties(app),
            'propertyDescriptions':
            get_case_property_description_dict(domain),
            'save_url':
            reverse("edit_form_actions",
                    args=[app.domain, app.id, module.id, form.id]),
        })
        context.update({
            'show_custom_ref':
            toggles.APP_BUILDER_CUSTOM_PARENT_REF.enabled_for_request(request),
        })
    context.update({'case_config_options': case_config_options})
    template = get_app_manager_template(
        request.user,
        "app_manager/v1/form_view.html",
        "app_manager/v2/form_view.html",
    )
    return template, context
Exemple #32
0
 def domain_uses_usercase():
     return is_usercase_in_use(self.app.domain)
Exemple #33
0
 def domain_uses_usercase():
     return is_usercase_in_use(self.app.domain)
Exemple #34
0
def get_session_schema(form):
    """Get form session schema definition
    """
    from corehq.apps.app_manager.suite_xml.sections.entries import EntriesHelper
    app = form.get_app()
    structure = {}
    datums = EntriesHelper(app).get_datums_meta_for_form_generic(form)
    datums = [
        d for d in datums
        if d.requires_selection and d.case_type and not d.is_new_case_id
    ]

    def _get_structure(datum, data_registry, source=None):
        id_source = f":{slugify(source)}" if source else ""
        return {
            "reference": {
                "hashtag": f'#registry_case{id_source}'
                if data_registry else f"#case{id_source}",
                "source": "registry" if data_registry else "casedb",
                "subset": f"case{id_source}",
                "key": "@case_id",
            },
        }

    unrelated_parents = set()
    for datum in datums:
        if not datum.module_id:
            continue
        module = app.get_module_by_unique_id(datum.module_id)
        parent_select_active = hasattr(
            module, 'parent_select') and module.parent_select.active
        if parent_select_active and module.parent_select.relationship is None:
            # for child modules that use parent select where the parent is not a 'related' case
            # See toggles.NON_PARENT_MENU_SELECTION
            unrelated_parents.add(module.parent_select.module_id)

    data_structure = {}
    for i, datum in enumerate(reversed(datums)):
        if isinstance(datum.datum, InstanceDatum):
            continue
        module_id = datum.module_id
        module = app.get_module_by_unique_id(module_id) if module_id else None
        data_registry = module.search_config.data_registry if module else None
        if i == 0:
            # always add the datum for this module
            data_structure[datum.datum.id] = _get_structure(
                datum, data_registry)
        else:
            if module and module_id in unrelated_parents:
                source = clean_trans(
                    module.name, app.langs
                )  # ensure that this structure reference is unique
                data_structure[datum.datum.id] = _get_structure(
                    datum, data_registry, source)

    if data_structure:
        structure["data"] = {
            "merge": True,
            "structure": data_structure,
        }

    if is_usercase_in_use(app.domain):
        structure["context"] = {
            "merge": True,
            "structure": {
                "userid": {
                    "reference": {
                        "hashtag": "#user",
                        "source": "casedb",
                        "subset": USERCASE_TYPE,
                        "subset_key": "@case_type",
                        "subset_filter": True,
                        "key": "hq_user_id",
                    },
                },
            },
        }
    return {
        "id": "commcaresession",
        "uri": "jr://instance/session",
        "name": "Session",
        "path": "/session",
        "structure": structure,
    }
Exemple #35
0
 def _form_uses_case(module, form):
     return ((module and module.case_type and form.requires_case())
             or is_usercase_in_use(domain))
Exemple #36
0
def get_form_view_context_and_template(request, domain, form, langs, messages=messages):
    xform_questions = []
    xform = None
    form_errors = []
    xform_validation_errored = False
    xform_validation_missing = False

    try:
        xform = form.wrapped_xform()
    except XFormException as e:
        form_errors.append(u"Error in form: %s" % e)
    except Exception as e:
        logging.exception(e)
        form_errors.append(u"Unexpected error in form: %s" % e)

    if xform and xform.exists():
        if xform.already_has_meta():
            messages.warning(
                request,
                "This form has a meta block already! "
                "It may be replaced by CommCare HQ's standard meta block."
            )

        try:
            xform_questions = xform.get_questions(langs, include_triggers=True)
            form.validate_form()
        except etree.XMLSyntaxError as e:
            form_errors.append(u"Syntax Error: %s" % e)
        except AppEditingError as e:
            form_errors.append(u"Error in application: %s" % e)
        except XFormValidationError:
            xform_validation_errored = True
            # showing these messages is handled by validate_form_for_build ajax
            pass
        except XFormValidationFailed:
            xform_validation_missing = True
            messages.warning(request, _("Unable to validate form due to server error."))
        except XFormException as e:
            form_errors.append(u"Error in form: %s" % e)
        # any other kind of error should fail hard,
        # but for now there are too many for that to be practical
        except Exception as e:
            if settings.DEBUG:
                raise
            notify_exception(request, 'Unexpected Build Error')
            form_errors.append(u"Unexpected System Error: %s" % e)
        else:
            # remove upload questions (attachemnts) until MM Case Properties
            # are released to general public
            is_previewer = toggles.MM_CASE_PROPERTIES.enabled(request.user.username)
            xform_questions = [q for q in xform_questions
                               if q["tag"] != "upload" or is_previewer]

        if not form_errors and not xform_validation_missing and not xform_validation_errored:
            try:
                form_action_errors = form.validate_for_build()
                if not form_action_errors:
                    form.add_stuff_to_xform(xform)
            except CaseError as e:
                messages.error(request, u"Error in Case Management: %s" % e)
            except XFormException as e:
                messages.error(request, unicode(e))
            except Exception as e:
                if settings.DEBUG:
                    raise
                logging.exception(unicode(e))
                messages.error(request, u"Unexpected Error: %s" % e)

    try:
        languages = xform.get_languages()
    except Exception:
        languages = []

    for err in form_errors:
        messages.error(request, err)

    module_case_types = []
    app = form.get_app()
    all_modules = list(app.get_modules())
    for module in all_modules:
        for case_type in module.get_case_types():
            module_case_types.append({
                'id': module.unique_id,
                'module_name': trans(module.name, langs),
                'case_type': case_type,
                'module_type': module.doc_type
            })

    if not form.unique_id:
        form.get_unique_id()
        app.save()

    form_has_schedule = isinstance(form, AdvancedForm) and form.get_module().has_schedule
    context = {
        'nav_form': form,
        'xform_languages': languages,
        "xform_questions": xform_questions,
        'case_reserved_words_json': load_case_reserved_words(),
        'module_case_types': module_case_types,
        'form_errors': form_errors,
        'xform_validation_errored': xform_validation_errored,
        'xform_validation_missing': xform_validation_missing,
        'allow_cloudcare': isinstance(form, Form),
        'allow_form_copy': isinstance(form, (Form, AdvancedForm)),
        'allow_form_filtering': not isinstance(form, CareplanForm) and not form_has_schedule,
        'allow_form_workflow': not isinstance(form, CareplanForm),
        'uses_form_workflow': form.post_form_workflow == WORKFLOW_FORM,
        'allow_usercase': domain_has_privilege(request.domain, privileges.USER_CASE),
        'is_usercase_in_use': is_usercase_in_use(request.domain),
        'is_module_filter_enabled': app.enable_module_filtering,
        'edit_name_url': reverse('edit_form_attr', args=[app.domain, app.id, form.unique_id, 'name']),
        'case_xpath_pattern_matches': CASE_XPATH_PATTERN_MATCHES,
        'case_xpath_substring_matches': CASE_XPATH_SUBSTRING_MATCHES,
        'user_case_xpath_pattern_matches': USER_CASE_XPATH_PATTERN_MATCHES,
        'user_case_xpath_substring_matches': USER_CASE_XPATH_SUBSTRING_MATCHES,
        'custom_instances': [
            {'instanceId': instance.instance_id, 'instancePath': instance.instance_path}
            for instance in form.custom_instances
        ],
    }

    if tours.NEW_APP.is_enabled(request.user):
        request.guided_tour = tours.NEW_APP.get_tour_data()

    if context['allow_form_workflow'] and toggles.FORM_LINK_WORKFLOW.enabled(domain):
        module = form.get_module()

        def qualified_form_name(form, auto_link):
            module_name = trans(form.get_module().name, langs)
            form_name = trans(form.name, langs)
            star = '* ' if auto_link else '  '
            return u"{}{} -> {}".format(star, module_name, form_name)

        modules = filter(lambda m: m.case_type == module.case_type, all_modules)
        if getattr(module, 'root_module_id', None) and module.root_module not in modules:
            modules.append(module.root_module)
        auto_linkable_forms = list(itertools.chain.from_iterable(list(m.get_forms()) for m in modules))

        def linkable_form(candidate_form):
            auto_link = candidate_form in auto_linkable_forms
            return {
                'unique_id': candidate_form.unique_id,
                'name': qualified_form_name(candidate_form, auto_link),
                'auto_link': auto_link
            }

        context['linkable_forms'] = [
            linkable_form(candidate_form) for candidate_module in all_modules
            for candidate_form in candidate_module.get_forms()
        ]

    if isinstance(form, CareplanForm):
        context.update({
            'mode': form.mode,
            'fixed_questions': form.get_fixed_questions(),
            'custom_case_properties': [
                {'key': key, 'path': path} for key, path in form.custom_case_updates.items()
            ],
            'case_preload': [
                {'key': key, 'path': path} for key, path in form.case_preload.items()
            ],
        })
        return "app_manager/v1/form_view_careplan.html", context
    elif isinstance(form, AdvancedForm):
        def commtrack_programs():
            if app.commtrack_enabled:
                programs = Program.by_domain(app.domain)
                return [{'value': program.get_id, 'label': program.name} for program in programs]
            else:
                return []

        all_programs = [{'value': '', 'label': _('All Programs')}]
        context.update({
            'show_custom_ref': toggles.APP_BUILDER_CUSTOM_PARENT_REF.enabled(request.user.username),
            'commtrack_programs': all_programs + commtrack_programs(),
        })
        context.update(get_schedule_context(form))
        return "app_manager/v1/form_view_advanced.html", context
    else:
        context.update({
            'show_custom_ref': toggles.APP_BUILDER_CUSTOM_PARENT_REF.enabled(request.user.username),
        })
        return "app_manager/v1/form_view.html", context
Exemple #37
0
def get_casedb_schema(form):
    """Get case database schema definition for vellum to display as an external data source.

    This lists all case types and their properties for the given app.
    """
    app = form.get_app()
    base_case_type = form.get_module().case_type if form.requires_case(
    ) else None
    case_types = app.get_case_types() | get_shared_case_types(app)
    per_type_defaults = get_per_type_defaults(app.domain, case_types)
    builder = ParentCasePropertyBuilder(app, ['case_name'],
                                        per_type_defaults,
                                        include_parent_properties=False)
    related = builder.get_parent_type_map(case_types)
    map = builder.get_case_property_map(case_types)
    descriptions_dict = get_case_property_description_dict(app.domain)

    if base_case_type:
        # Generate hierarchy of case types, represented as a list of lists of strings:
        # [[base_case_type], [parent_type1, parent_type2...], [grandparent_type1, grandparent_type2...]]
        # Vellum case management only supports three levels
        generation_names = ['case', 'parent', 'grandparent']
        generations = [[] for g in generation_names]

        def _add_ancestors(ctype, generation):
            if generation < len(generation_names):
                generations[generation].append(ctype)
                for parent in related.get(ctype, {}).get('parent', []):
                    _add_ancestors(parent, generation + 1)

        _add_ancestors(base_case_type, 0)

        # Remove any duplicate types or empty generations
        generations = [set(g) for g in generations if len(g)]
    else:
        generations = []

    subsets = [{
        "id":
        generation_names[i],
        "name":
        "{} ({})".format(generation_names[i], " or ".join(ctypes))
        if i > 0 else base_case_type,
        "structure": {
            p: {
                "description": descriptions_dict.get(t, {}).get(p, '')
            }
            for t in ctypes for p in map[t]
        },
        "related": {
            "parent": {
                "hashtag": "#case/" + generation_names[i + 1],
                "subset": generation_names[i + 1],
                "key": "@case_id",
            }
        } if i < len(generations) - 1 else None,
    } for i, ctypes in enumerate(generations)]

    if is_usercase_in_use(app.domain):
        subsets.append({
            "id": USERCASE_TYPE,
            "name": "user",
            "key": "@case_type",
            "structure":
            {p: {}
             for p in get_usercase_properties(app)[USERCASE_TYPE]},
        })

    return {
        "id": "casedb",
        "uri": "jr://instance/casedb",
        "name": "case",
        "path": "/casedb/case",
        "structure": {},
        "subsets": subsets,
    }
Exemple #38
0
def get_form_view_context_and_template(request, domain, form, langs, messages=messages):
    xform_questions = []
    xform = None
    form_errors = []
    xform_validation_errored = False

    try:
        xform = form.wrapped_xform()
    except XFormException as e:
        form_errors.append(u"Error in form: %s" % e)
    except Exception as e:
        logging.exception(e)
        form_errors.append(u"Unexpected error in form: %s" % e)

    if xform and xform.exists():
        if xform.already_has_meta():
            messages.warning(
                request,
                "This form has a meta block already! "
                "It may be replaced by CommCare HQ's standard meta block."
            )

        try:
            form.validate_form()
            xform_questions = xform.get_questions(langs, include_triggers=True, form=form)
        except etree.XMLSyntaxError as e:
            form_errors.append(u"Syntax Error: %s" % e)
        except AppEditingError as e:
            form_errors.append(u"Error in application: %s" % e)
        except XFormValidationError:
            xform_validation_errored = True
            # showing these messages is handled by validate_form_for_build ajax
            pass
        except XFormException as e:
            form_errors.append(u"Error in form: %s" % e)
        # any other kind of error should fail hard,
        # but for now there are too many for that to be practical
        except Exception as e:
            if settings.DEBUG:
                raise
            notify_exception(request, 'Unexpected Build Error')
            form_errors.append(u"Unexpected System Error: %s" % e)
        else:
            # remove upload questions (attachemnts) until MM Case Properties
            # are released to general public
            is_previewer = toggles.MM_CASE_PROPERTIES.enabled(request.user.username)
            xform_questions = [q for q in xform_questions
                               if q["tag"] != "upload" or is_previewer]

        try:
            form_action_errors = form.validate_for_build()
            if not form_action_errors:
                form.add_stuff_to_xform(xform)
        except CaseError as e:
            messages.error(request, u"Error in Case Management: %s" % e)
        except XFormException as e:
            messages.error(request, unicode(e))
        except Exception as e:
            if settings.DEBUG:
                raise
            logging.exception(unicode(e))
            messages.error(request, u"Unexpected Error: %s" % e)

    try:
        languages = xform.get_languages()
    except Exception:
        languages = []

    for err in form_errors:
        messages.error(request, err)

    module_case_types = []
    app = form.get_app()
    all_modules = list(app.get_modules())
    for module in all_modules:
        for case_type in module.get_case_types():
            module_case_types.append({
                'id': module.unique_id,
                'module_name': trans(module.name, langs),
                'case_type': case_type,
                'module_type': module.doc_type
            })

    if not form.unique_id:
        form.get_unique_id()
        app.save()

    form_has_schedule = isinstance(form, AdvancedForm) and form.get_module().has_schedule
    module_filter_preview = feature_previews.MODULE_FILTER.enabled(request.domain)
    context = {
        'nav_form': form,
        'xform_languages': languages,
        "xform_questions": xform_questions,
        'case_reserved_words_json': load_case_reserved_words(),
        'module_case_types': module_case_types,
        'form_errors': form_errors,
        'xform_validation_errored': xform_validation_errored,
        'allow_cloudcare': isinstance(form, Form),
        'allow_form_copy': isinstance(form, (Form, AdvancedForm)),
        'allow_form_filtering': (module_filter_preview or
            (not isinstance(form, CareplanForm) and not form_has_schedule)),
        'allow_form_workflow': not isinstance(form, CareplanForm),
        'allow_usercase': domain_has_privilege(request.domain, privileges.USER_CASE),
        'is_usercase_in_use': is_usercase_in_use(request.domain),
        'is_module_filter_enabled': (feature_previews.MODULE_FILTER.enabled(request.domain) and
                                     app.enable_module_filtering),
        'edit_name_url': reverse('edit_form_attr', args=[app.domain, app.id, form.unique_id, 'name']),
        'case_xpath_pattern_matches': CASE_XPATH_PATTERN_MATCHES,
        'case_xpath_substring_matches': CASE_XPATH_SUBSTRING_MATCHES,
        'user_case_xpath_pattern_matches': USER_CASE_XPATH_PATTERN_MATCHES,
        'user_case_xpath_substring_matches': USER_CASE_XPATH_SUBSTRING_MATCHES,
    }

    if tours.NEW_APP.is_enabled(request.user):
        request.guided_tour = tours.NEW_APP.get_tour_data()

    if context['allow_form_workflow'] and toggles.FORM_LINK_WORKFLOW.enabled(domain):
        module = form.get_module()

        def qualified_form_name(form, auto_link):
            module_name = trans(form.get_module().name, langs)
            form_name = trans(form.name, langs)
            star = '* ' if auto_link else '  '
            return u"{}{} -> {}".format(star, module_name, form_name)

        modules = filter(lambda m: m.case_type == module.case_type, all_modules)
        if getattr(module, 'root_module_id', None) and module.root_module not in modules:
            modules.append(module.root_module)
        auto_linkable_forms = list(itertools.chain.from_iterable(list(m.get_forms()) for m in modules))

        def linkable_form(candidate_form):
            auto_link = candidate_form in auto_linkable_forms
            return {
                'unique_id': candidate_form.unique_id,
                'name': qualified_form_name(candidate_form, auto_link),
                'auto_link': auto_link
            }

        context['linkable_forms'] = [
            linkable_form(candidate_form) for candidate_module in all_modules
            for candidate_form in candidate_module.get_forms()
        ]

    if isinstance(form, CareplanForm):
        context.update({
            'mode': form.mode,
            'fixed_questions': form.get_fixed_questions(),
            'custom_case_properties': [
                {'key': key, 'path': path} for key, path in form.custom_case_updates.items()
            ],
            'case_preload': [
                {'key': key, 'path': path} for key, path in form.case_preload.items()
            ],
        })
        return "app_manager/form_view_careplan.html", context
    elif isinstance(form, AdvancedForm):
        def commtrack_programs():
            if app.commtrack_enabled:
                programs = Program.by_domain(app.domain)
                return [{'value': program.get_id, 'label': program.name} for program in programs]
            else:
                return []

        all_programs = [{'value': '', 'label': _('All Programs')}]
        context.update({
            'show_custom_ref': toggles.APP_BUILDER_CUSTOM_PARENT_REF.enabled(request.user.username),
            'commtrack_programs': all_programs + commtrack_programs(),
        })
        context.update(get_schedule_context(form))
        return "app_manager/form_view_advanced.html", context
    else:
        context.update({
            'show_custom_ref': toggles.APP_BUILDER_CUSTOM_PARENT_REF.enabled(request.user.username),
        })
        return "app_manager/form_view.html", context