Ejemplo n.º 1
0
 def _save_to_case_root_node(self, form_unique_id, question):
     """Add an extra node with the root path of the save to case to attach case properties to
     """
     question_path = self._save_to_case_root_path(question)
     response = FormQuestionResponse({
         "label":
         question_path,
         "tag":
         question_path,
         "value":
         question_path,
         "repeat":
         question['repeat'],
         "group":
         question['group'],
         "type":
         'SaveToCase',
         "hashtagValue":
         question['hashtagValue'],
         "relevant":
         None,
         "required":
         False,
         "comment":
         None,
         "constraint":
         None,
     }).to_json()
     response['load_properties'] = self._case_meta.get_load_properties(
         form_unique_id, question_path)
     response['save_properties'] = self._case_meta.get_save_properties(
         form_unique_id, question_path)
     self._seen_save_to_case[form_unique_id].append(question_path)
     return response
Ejemplo n.º 2
0
    def test_repeat_empty(self):
        questions_json = [{
            'tag': 'repeat',
            'type': 'Repeat',
            'label': 'Repeat',
            'value': '/data/question12',
        }]
        form_data = {
            "@uiVersion": "1",
            "@xmlns":
            "http://openrosa.org/formdesigner/432B3A7F-6EEE-4033-8740-ACCB0804C4FC",
            "@name": "Untitled Form",
            "#type": "data",
            "question12": ["", ""],
            "meta": {
                "@xmlns": "http://openrosa.org/jr/xforms",
                "username": "******",
                "instanceID": "172981b6-5eeb-4be8-bbc7-ad52f808e803",
                "userID": "a07d4bd967a9c205287f767509600931",
                "timeEnd": "2014-04-28T18:27:05Z",
                "appVersion": {
                    "@xmlns":
                    "http://commcarehq.org/xforms",
                    "#text":
                    "CommCare ODK, version \"2.11.0\"(29272). App v8. CommCare Version 2.11. Build 29272, built on: February-14-2014"
                },
                "timeStart": "2014-04-28T18:26:38Z",
                "deviceID": "990004280784863"
            },
            "@version": "8"
        }

        expected = [{
            'tag': 'repeat',
            'type': 'Repeat',
            'label': 'Repeat',
            'value': '/data/question12',
            'response': None,
            'calculate': None,
            'children': [],
        }]
        actual = get_readable_form_data(
            form_data, [FormQuestionResponse(q) for q in questions_json])
        self.assertJSONEqual(
            json.dumps([q.to_json() for q in actual]),
            json.dumps([FormQuestionResponse(q).to_json() for q in expected]))
Ejemplo n.º 3
0
 def _serialized_question(self, form_unique_id, question):
     response = FormQuestionResponse(question).to_json()
     response['load_properties'] = self._case_meta.get_load_properties(
         form_unique_id, question['value'])
     response['save_properties'] = self._case_meta.get_save_properties(
         form_unique_id, question['value'])
     if self._is_save_to_case(question):
         response['type'] = 'SaveToCase'
     return response
Ejemplo n.º 4
0
    def test_get_readable_data_for_submission(self):
        formxml = FormSubmissionBuilder(form_id='123',
                                        form_properties={
                                            'dalmation_count': 'yes'
                                        }).as_xml_string()

        xform = submit_form_locally(formxml, self.domain).xform
        actual, _ = get_readable_data_for_submission(xform)

        expected = [{
            'value': '/data/dalmation_count',
            'label': 'dalmation_count',
            'response': 'yes'
        }]
        self.assertJSONEqual(
            json.dumps([q.to_json() for q in actual]),
            json.dumps([FormQuestionResponse(q).to_json() for q in expected]))
Ejemplo n.º 5
0
 def _get_form_row(self, form, language, case_meta):
     form_summary_rows = []
     for question in form.get_questions(self.app.langs,
                                        include_triggers=True,
                                        include_groups=True,
                                        include_translations=True):
         question_response = FormQuestionResponse(question)
         form_summary_rows.append(
             FormSummaryRow(
                 question_id=question_response.value,
                 label=_translate_name(question_response.translations,
                                       language),
                 translations=question_response.translations,
                 type=question_response.type,
                 repeat=question_response.repeat,
                 group=question_response.group,
                 option_labels="\n".join([
                     _translate_name(option.translations, language)
                     for option in question_response.options
                 ]),
                 option_values=", ".join([
                     option.value for option in question_response.options
                 ]),
                 calculate=question_response.calculate,
                 relevant=question_response.relevant,
                 constraint=question_response.constraint,
                 required="true" if question_response.required else "false",
                 comment=question_response.comment,
                 default_value=question_response.setvalue,
                 load_properties="\n".join([
                     "{} - {}".format(prop.case_type, prop.property)
                     for prop in case_meta.get_load_properties(
                         form.unique_id, question['value'])
                 ]),
                 save_properties="\n".join([
                     "{} - {}".format(prop.case_type, prop.property)
                     for prop in case_meta.get_save_properties(
                         form.unique_id, question['value'])
                 ]),
             ))
     return tuple(form_summary_rows)
Ejemplo n.º 6
0
def get_questions_from_xform_node(xform, langs):
    questions = xform.get_questions(langs,
                                    include_triggers=True,
                                    include_groups=True)
    return [FormQuestionResponse(q) for q in questions]
Ejemplo n.º 7
0
def zip_form_data_and_questions(relative_data,
                                questions,
                                path_context='',
                                output_context=None,
                                process_label=None,
                                absolute_data=None):
    """
    The strategy here is to loop through the questions, and at every point
    pull in the corresponding piece of data, removing it from data
    and adding it to the question. At the end, any remain piece of data are
    added to the end as unknown questions.

    Repeats are matched up with their entry node in the data,
    and then this function is applied recursively to each of the elements in
    the list, using the repeat's children as the question list.

    """
    assert path_context
    absolute_data = absolute_data or relative_data
    if not path_context.endswith('/'):
        path_context += '/'
    if not output_context:
        output_context = {
            '%s%s' % (path_context, '/'.join(map(str, key))): str(value)
            for key, value in _flatten_json(relative_data).items()
        }

    result = []
    for question in questions:
        path = path_relative_to_context(question.value, path_context)
        absolute_path = absolute_path_from_context(question.value,
                                                   path_context)
        node = pop_from_form_data(relative_data, absolute_data, path)
        # response=True on a question with children indicates that one or more
        # child has a response, i.e. that the entire group wasn't skipped
        question_data = dict(question)
        question_data.pop('response')
        if question.type in ('Group', 'FieldList'):
            children = question_data.pop('children')
            form_question = FormQuestionResponse(
                children=zip_form_data_and_questions(
                    node,
                    children,
                    path_context=absolute_path,
                    output_context=output_context,
                    process_label=process_label,
                    absolute_data=absolute_data,
                ),
                **question_data)
            if _group_question_has_response(form_question):
                form_question.response = True
        elif question.type == 'Repeat':
            if not isinstance(node, list):
                node = [node]
            children = question_data.pop('children')
            form_question = FormQuestionResponse(children=[
                FormQuestionResponse(children=zip_form_data_and_questions(
                    entry,
                    children,
                    path_context=absolute_path,
                    output_context=output_context,
                    process_label=process_label,
                    absolute_data=absolute_data,
                ), ) for entry in node
            ],
                                                 **question_data)
            for child in form_question.children:
                if _group_question_has_response(child):
                    child.response = True
            if _group_question_has_response(form_question):
                form_question.response = True
        else:
            if (question.type == 'DataBindOnly'
                    and question.label == question.value):
                question_data['label'] = '/'.join(
                    question.value.split('/')[2:])

            if process_label:
                question_data['label'] = process_label(question_data['label'],
                                                       output_context)

            form_question = FormQuestionResponse(response=node,
                                                 **question_data)
        result.append(form_question)

    if relative_data:
        for key, response in sorted(_flatten_json(relative_data).items()):
            joined_key = '/'.join(map(str, key))
            result.append(
                FormQuestionResponse(
                    label=joined_key,
                    value='%s%s' % (path_context, joined_key),
                    response=response,
                ))

    return result
Ejemplo n.º 8
0
    def test(self):

        questions_json = [{
            "tag": "input",
            "repeat": None,
            "group": None,
            "value": "/data/question4",
            "label": "Question 4",
            "type": "Text",
            'calculate': None,
            'required': False,
            'relevant': None,
            'setvalue': 'default',
        }]
        form_data = {
            "@uiVersion": "1",
            "@xmlns":
            "http://openrosa.org/formdesigner/D096EE34-DF37-466C-B6D9-950A36D570AD",
            "@name": "Untitled Form",
            "question4": "foo",
            "#type": "data",
            "case": {
                "@xmlns": "http://commcarehq.org/case/transaction/v2",
                "@date_modified": "2013-12-23T16:24:20Z",
                "create": {
                    "case_type": "case",
                    "case_name": "foo",
                    "owner_id": "9ee0367ad4051f0fb33c75eae67d750e"
                },
                "@user_id": "9ee0367ad4051f0fb33c75eae67d750e",
                "update": "",
                "@case_id": "6bc190f6-ddeb-4a42-b445-8fa348b50806"
            },
            "meta": {
                "@xmlns": "http://openrosa.org/jr/xforms",
                "username": "******",
                "instanceID": "0398f186-c35f-4437-8b6b-41800807e485",
                "userID": "9ee0367ad4051f0fb33c75eae67d750e",
                "timeEnd": "2013-12-23T16:24:20Z",
                "appVersion": {
                    "@xmlns": "http://commcarehq.org/xforms",
                    "#text": "2.0"
                },
                "timeStart": "2013-12-23T16:24:10Z",
                "deviceID": "cloudcare"
            },
            "@version": "10"
        }
        questions = [FormQuestionResponse(q) for q in questions_json]
        actual = get_readable_form_data(form_data, questions)
        self.assertJSONEqual(
            json.dumps([q.to_json() for q in actual]),
            json.dumps([{
                "tag": "input",
                "repeat": None,
                "group": None,
                "value": "/data/question4",
                "label": "Question 4",
                "response": "foo",
                "type": "Text",
                'calculate': None,
                'comment': None,
                'required': False,
                'relevant': None,
                'setvalue': 'default',
                "options": [],
                "children": [],
            }]))
Ejemplo n.º 9
0
    def test_repeat(self):
        questions_json = [{
            'tag': 'input',
            'type': 'Text',
            'label': 'Text',
            'value': '/data/question1',
        }, {
            'tag': 'input',
            'type': 'Int',
            'label': 'How many names?',
            'value': '/data/question18',
        }, {
            'tag': 'repeat',
            'type': 'Repeat',
            'label': 'Repeat',
            'value': '/data/question12',
        }, {
            'tag': 'input',
            'type': 'Text',
            'label': 'Name',
            'value': '/data/question12/name',
            'repeat': '/data/question12',
            'group': '/data/question12',
        }, {
            'tag': 'trigger',
            'type': 'Trigger',
            'label': 'Label',
            'value': '/data/question2',
        }, {
            'tag':
            'select1',
            'type':
            'Select',
            'label':
            'Single Answer',
            'value':
            '/data/question3',
            'options': [{
                'value': 'item1',
                'label': 'Item 1'
            }, {
                'value': 'item2',
                'label': 'Item 2'
            }]
        }]
        form_data = {
            "@uiVersion":
            "1",
            "@xmlns":
            "http://openrosa.org/formdesigner/432B3A7F-6EEE-4033-8740-ACCB0804C4FC",
            "@name":
            "Untitled Form",
            "question18":
            "3",
            "#type":
            "data",
            "question12": [{
                "name": "Jack"
            }, {
                "name": "Jill"
            }, {
                "name": "Up the hill"
            }],
            "meta": {
                "@xmlns": "http://openrosa.org/jr/xforms",
                "username": "******",
                "instanceID": "172981b6-5eeb-4be8-bbc7-ad52f808e803",
                "userID": "a07d4bd967a9c205287f767509600931",
                "timeEnd": "2014-04-28T18:27:05Z",
                "appVersion": {
                    "@xmlns":
                    "http://commcarehq.org/xforms",
                    "#text":
                    "CommCare ODK, version \"2.11.0\"(29272). App v8. CommCare Version 2.11. Build 29272, built on: February-14-2014"
                },
                "timeStart": "2014-04-28T18:26:38Z",
                "deviceID": "990004280784863"
            },
            "question1":
            "T",
            "question3":
            "item2",
            "question2":
            "OK",
            "@version":
            "8"
        }

        expected = [{
            'tag': 'input',
            'type': 'Text',
            'label': 'Text',
            'value': '/data/question1',
            'response': 'T',
            'calculate': None,
        }, {
            'tag': 'input',
            'type': 'Int',
            'label': 'How many names?',
            'value': '/data/question18',
            'response': '3',
            'calculate': None,
        }, {
            'tag':
            'repeat',
            'type':
            'Repeat',
            'label':
            'Repeat',
            'value':
            '/data/question12',
            'response':
            True,
            'calculate':
            None,
            'children': [{
                'children': [{
                    'tag': 'input',
                    'type': 'Text',
                    'label': 'Name',
                    'value': '/data/question12/name',
                    'repeat': '/data/question12',
                    'group': '/data/question12',
                    'response': 'Jack',
                    'calculate': None,
                }],
                'response':
                True,
            }, {
                'children': [{
                    'tag': 'input',
                    'type': 'Text',
                    'label': 'Name',
                    'value': '/data/question12/name',
                    'repeat': '/data/question12',
                    'group': '/data/question12',
                    'response': 'Jill',
                    'calculate': None,
                }],
                'response':
                True
            }, {
                'children': [{
                    'tag': 'input',
                    'type': 'Text',
                    'label': 'Name',
                    'value': '/data/question12/name',
                    'repeat': '/data/question12',
                    'group': '/data/question12',
                    'response': 'Up the hill',
                    'calculate': None,
                }],
                'response':
                True
            }],
        }, {
            'tag': 'trigger',
            'type': 'Trigger',
            'label': 'Label',
            'value': '/data/question2',
            'response': 'OK',
            'calculate': None,
        }, {
            'tag':
            'select1',
            'type':
            'Select',
            'label':
            'Single Answer',
            'value':
            '/data/question3',
            'options': [{
                'value': 'item1',
                'label': 'Item 1'
            }, {
                'value': 'item2',
                'label': 'Item 2'
            }],
            'response':
            'item2',
            'calculate':
            None,
        }]
        actual = get_readable_form_data(
            form_data, [FormQuestionResponse(q) for q in questions_json])
        self.assertJSONEqual(
            json.dumps([q.to_json() for q in actual]),
            json.dumps([FormQuestionResponse(q).to_json() for q in expected]))
Ejemplo n.º 10
0
def zip_form_data_and_questions(relative_data, questions, path_context='',
                                output_context=None, process_label=None,
                                absolute_data=None):
    """
    The strategy here is to loop through the questions, and at every point
    pull in the corresponding piece of data, removing it from data
    and adding it to the question. At the end, any remain piece of data are
    added to the end as unknown questions.

    Repeats are matched up with their entry node in the data,
    and then this function is applied recursively to each of the elements in
    the list, using the repeat's children as the question list.

    """
    assert path_context
    absolute_data = absolute_data or relative_data
    if not path_context.endswith('/'):
        path_context += '/'
    if not output_context:
        output_context = {
            '%s%s' % (path_context, '/'.join(map(six.text_type, key))): six.text_type(value)
            for key, value in _flatten_json(relative_data).items()
        }

    result = []
    for question in questions:
        path = path_relative_to_context(question.value, path_context)
        absolute_path = absolute_path_from_context(question.value, path_context)
        node = pop_from_form_data(relative_data, absolute_data, path)
        # response=True on a question with children indicates that one or more
        # child has a response, i.e. that the entire group wasn't skipped
        question_data = dict(question)
        question_data.pop('response')
        if question.type in ('Group', 'FieldList'):
            children = question_data.pop('children')
            form_question = FormQuestionResponse(
                children=zip_form_data_and_questions(
                    node,
                    children,
                    path_context=absolute_path,
                    output_context=output_context,
                    process_label=process_label,
                    absolute_data=absolute_data,
                ),
                **question_data
            )
            if _group_question_has_response(form_question):
                form_question.response = True
        elif question.type == 'Repeat':
            if not isinstance(node, list):
                node = [node]
            children = question_data.pop('children')
            form_question = FormQuestionResponse(
                children=[
                    FormQuestionResponse(
                        children=zip_form_data_and_questions(
                            entry,
                            children,
                            path_context=absolute_path,
                            output_context=output_context,
                            process_label=process_label,
                            absolute_data=absolute_data,
                        ),
                    )
                    for entry in node
                ],
                **question_data
            )
            for child in form_question.children:
                if _group_question_has_response(child):
                    child.response = True
            if _group_question_has_response(form_question):
                form_question.response = True
        else:
            if (question.type == 'DataBindOnly'
                    and question.label == question.value):
                question_data['label'] = '/'.join(
                    question.value.split('/')[2:])

            if process_label:
                question_data['label'] = process_label(question_data['label'],
                                                       output_context)

            form_question = FormQuestionResponse(response=node,
                                                 **question_data)
        result.append(form_question)

    if relative_data:
        for key, response in sorted(_flatten_json(relative_data).items()):
            joined_key = '/'.join(map(six.text_type, key))
            result.append(
                FormQuestionResponse(
                    label=joined_key,
                    value='%s%s' % (path_context, joined_key),
                    response=response,
                )
            )

    return result