def test_should_not_save_snapshots_when_questionnaires_field_not_changed( self): self._create_form_model() form_model = get_form_model_by_code(self.manager, FORM_CODE_1) post = [{ "title": "What is associated entity", "options": { "ddtype": self.default_ddtype.to_json() }, "type": "text", "is_entity_question": True, "code": "ID", "name": "entity_question" }, { "title": "What is your name", "options": { "ddtype": self.default_ddtype.to_json() }, "type": "text", "is_entity_question": False, "code": "Q1", "range_min": 5, "range_max": 10 }] QuestionnaireBuilder( form_model, self.manager).update_questionnaire_with_questions(post) form_model.save() form_model = get_form_model_by_code(self.manager, FORM_CODE_1) self.assertEqual(0, len(form_model.snapshots))
def create_questionnaire(post, manager, name, language, reporter_id, question_set_json=None, xform=None, is_open_survey=False): questionnaire_code = post['questionnaire-code'].lower() datasenders = json.loads(post.get('datasenders', "[]")) question_set = question_set_json if question_set_json else json.loads(post['question-set']) questionnaire = Project(manager, name=name, fields=[], form_code=questionnaire_code, language=language, devices=[u'sms', u'web', u'smartPhone']) questionnaire.xform = xform if is_open_survey: questionnaire.is_open_survey = post.get('is_open_survey') if reporter_id is not None: questionnaire.data_senders.append(reporter_id) if datasenders: questionnaire.data_senders.extend(filter(lambda ds: ds != reporter_id, datasenders)) outgoing_sms_enabled = not xform and post.get('is_outgoing_sms_enabled', 'true') QuestionnaireBuilder(questionnaire, manager)\ .update_questionnaire_with_questions(question_set)\ .update_reminder(json.loads(post.get('reminder_and_deadline', '{}')))\ .update_outgoing_sms_enabled_flag(outgoing_sms_enabled) return questionnaire
def test_should_save_snapshots_when_questionnaires_field_modified(self): self._create_form_model() form_model = get_form_model_by_code(self.manager, FORM_CODE_1) original_fields = form_model._doc.json_fields revision = form_model._doc['_rev'] post = [{ "title": "q1", "type": "text", "choices": [], "is_entity_question": False, "code": "q1", "min_length": 1, "max_length": "" }, { "title": "q2", "type": "integer", "choices": [], "is_entity_question": False, "code": "q2", "range_min": 0, "range_max": 100 }] QuestionnaireBuilder( form_model, self.manager).update_questionnaire_with_questions(post) form_model.save() form_model = get_form_model_by_code(self.manager, FORM_CODE_1) self.assertEqual(1, len(form_model.snapshots)) self.assertEqual(revision, form_model.snapshots.keys()[-1]) expect = [(each['code'], each['label']) for each in original_fields] self.assertListEqual(expect, [(each.code, each.label) for each in form_model.snapshots[revision]])
def save_questionnaire(request): manager = get_database_manager(request.user) if request.method == 'POST': questionnaire_code = request.POST['questionnaire-code'] json_string = request.POST['question-set'] question_set = json.loads(json_string) pid = request.POST['pid'] project = Project.load(manager.database, pid) form_model = FormModel.get(manager, project.qid) old_fields = form_model.fields try: QuestionnaireBuilder(form_model, manager).update_questionnaire_with_questions(question_set) except QuestionCodeAlreadyExistsException as e: return HttpResponseServerError(e) except QuestionAlreadyExistsException as e: return HttpResponseServerError(e) except EntityQuestionAlreadyExistsException as e: return HttpResponseServerError(e.message) else: try: form_model.form_code = questionnaire_code.lower() except DataObjectAlreadyExists as e: if e.message.find("Form") >= 0: return HttpResponseServerError("Questionnaire with this code already exists") return HttpResponseServerError(e.message) form_model.name = project.name form_model.entity_id = project.entity_type detail = utils.get_changed_questions(old_fields, form_model.fields, subject=False) form_model.save() UserActivityLog().log(request, project=project.name, action=EDITED_PROJECT, detail=json.dumps(detail)) return HttpResponse(json.dumps({"response": "ok"}))
def update_questionnaire(questionnaire, post, manager): questionnaire.form_code = post['questionnaire-code'].lower() json_string = post['question-set'] question_set = json.loads(json_string) QuestionnaireBuilder( questionnaire, manager).update_questionnaire_with_questions(question_set) return questionnaire
def create_questionnaire(post, manager, entity_type, name, language): entity_type = [entity_type] if is_string(entity_type) else entity_type questionnaire_code = post['questionnaire-code'].lower() json_string = post['question-set'] question_set = json.loads(json_string) form_model = FormModel(manager, entity_type=entity_type, name=name, type='survey', state=post['project_state'], fields=[], form_code=questionnaire_code, language=language) QuestionnaireBuilder(form_model, manager).update_questionnaire_with_questions(question_set) return form_model
def update_questionnaire(questionnaire, post, entity_type, name, manager, language): questionnaire.name = name questionnaire.activeLanguages = [language] questionnaire.entity_type = [entity_type] if is_string(entity_type) else entity_type questionnaire.form_code = post['questionnaire-code'].lower() json_string = post['question-set'] question_set = json.loads(json_string) QuestionnaireBuilder(questionnaire, manager).update_questionnaire_with_questions(question_set) questionnaire.deactivate() if post['project_state'] == ProjectState.INACTIVE else questionnaire.set_test_mode() return questionnaire
def test_should_remove_unique_id_validator_if_unique_id_field_is_not_present( self): dbm = Mock(spec=DatabaseManager) form_model = MagicMock(spec=FormModel) form_model.fields = [TextField('name', 'code', 'label')] form_model.entity_questions = [] QuestionnaireBuilder(form_model, dbm)._update_unique_id_validator() form_model.remove_validator.assert_called_once_with( UniqueIdExistsValidator)
def test_should_add_unique_id_validator_to_form_model_if_unique_id_field_is_present( self): dbm = Mock(spec=DatabaseManager) form_model = MagicMock(spec=FormModel) form_model.fields = [UniqueIdField('clinic', 'name', 'code', 'label')] QuestionnaireBuilder(form_model, dbm)._update_unique_id_validator() form_model.add_validator.assert_called_once_with( UniqueIdExistsValidator)
def _create_questionnaire(manager, questionnaire, question): question_set = [{ 'title': question, 'type': 'text', "is_entity_question": False, "code": 'q1', "name": question, 'required': True, "parent_field_code": '', "instruction": "Answer must be a text", 'label': question }] QuestionnaireBuilder( questionnaire, manager).update_questionnaire_with_questions(question_set)
def test_should_update_questionnaire_when_entity_type_is_not_reporter( self): self._create_form_model() form_model = self.manager.get(self.form_model__id, FormModel) post = [{ "title": "What is your age", "code": "age", "type": "integer", "choices": [], "is_entity_question": False, "range_min": 0, "range_max": 100 }] QuestionnaireBuilder( form_model, self.manager).update_questionnaire_with_questions(post) self.assertEquals(1, len(form_model.fields))
def test_should_update_questionnaire_when_entity_type_is_reporter(self): self._create_summary_form_model() post = [{ "title": "q1", "type": "text", "choices": [], "is_entity_question": False, "code": "q1", "min_length": 1, "max_length": "" }, { "title": "q2", "type": "integer", "choices": [], "is_entity_question": False, "code": "code", "range_min": 0, "range_max": 100 }, { "title": "q3", "type": "select", "code": "code", "choices": [{ "value": "c1" }, { "value": "c2" }], "is_entity_question": False }] summary_form_model = self.manager.get(self.summary_form_model__id, FormModel) QuestionnaireBuilder( summary_form_model, self.manager).update_questionnaire_with_questions(post) self.assertEqual(4, len(summary_form_model.fields)) self.assertEqual('eid', summary_form_model.fields[0].code) self.assertEqual('q1', summary_form_model.fields[1].code) self.assertEqual('q2', summary_form_model.fields[2].code) self.assertEqual('q3', summary_form_model.fields[3].code) entity_id_question = summary_form_model.entity_question self.assertEqual('eid', entity_id_question.code) self.assertEqual('I am submitting this data on behalf of', entity_id_question.name) self.assertEqual("Choose Data Sender from this list.", entity_id_question.instruction)
def save_questionnaire(request): manager = get_database_manager(request.user) if request.method == 'POST': new_short_code = request.POST['questionnaire-code'].lower() saved_short_code = request.POST['saved-questionnaire-code'].lower() form_model = get_form_model_by_code(manager, saved_short_code) detail_dict = dict() if new_short_code != saved_short_code: try: form_model.old_form_code = form_model.form_code form_model.form_code = new_short_code form_model.save() detail_dict.update({"form_code": new_short_code}) except DataObjectAlreadyExists as e: if e.message.find("Form") >= 0: return HttpResponse(json.dumps({'success': False, "code_has_error": True, 'error_message': ugettext( "Questionnaire with same code already exists.")})) return HttpResponseServerError(e.message) json_string = request.POST['question-set'] question_set = json.loads(json_string) try: saved_fields = form_model.fields QuestionnaireBuilder(form_model, manager).update_questionnaire_with_questions(question_set) form_model.save() changed = get_changed_questions(saved_fields, form_model.fields) changed.update(dict(entity_type=form_model.entity_type[0].capitalize())) detail_dict.update(changed) kwargs = dict() if request.POST.get("project-name") is not None: kwargs.update(dict(project=request.POST.get("project-name").capitalize())) UserActivityLog().log(request, action=EDITED_REGISTRATION_FORM, detail=json.dumps(detail_dict), **kwargs) return HttpResponse(json.dumps({'success': True, 'form_code': form_model.form_code})) except QuestionCodeAlreadyExistsException as e: return HttpResponse(json.dumps({'success': False, 'error_message': _(e.message)})) except QuestionAlreadyExistsException as e: return HttpResponse(json.dumps({'success': False, 'error_message': _(e.message)})) except EntityQuestionAlreadyExistsException as e: return HttpResponse(json.dumps({'success': False, 'error_message': _(e.message)}))
def create_questionnaire(post, manager, name, language, reporter_id): questionnaire_code = post['questionnaire-code'].lower() datasenders = json.loads(post.get('datasenders', "[]")) json_string = post['question-set'] question_set = json.loads(json_string) questionnaire = Project(manager, name=name, fields=[], form_code=questionnaire_code, language=language, devices=[u'sms', u'web', u'smartPhone']) if reporter_id is not None: questionnaire.data_senders.append(reporter_id) if datasenders: questionnaire.data_senders.extend( filter(lambda ds: ds != reporter_id, datasenders)) QuestionnaireBuilder(questionnaire, manager)\ .update_questionnaire_with_questions(question_set)\ .update_reminder(json.loads(post.get('reminder_and_deadline', '{}'))) return questionnaire
def post(self, request, project_id): manager = get_database_manager(request.user) questionnaire = Project.get(manager, project_id) file_content = None tmp_file = None try: file_content = request.raw_post_data file_errors, file_extension = _perform_file_validations(request) tmp_file = NamedTemporaryFile(delete=True, suffix=file_extension) if file_errors: logger.info( "User: %s. Edit upload File validation failed: %s. File name: %s, size: %d", request.user.username, json.dumps(file_errors), request.GET.get("qqfile"), int(request.META.get('CONTENT_LENGTH'))) return HttpResponse(content_type='application/json', content=json.dumps({ 'success': False, 'error_msg': file_errors })) tmp_file.write(file_content) tmp_file.seek(0) xls_parser_response = XlsFormParser(tmp_file, questionnaire.name, manager).parse() send_email_if_unique_id_type_question_has_no_registered_unique_ids( xls_parser_response, request, questionnaire.name) profile = request.user.get_profile() organization = Organization.objects.get(org_id=profile.org_id) if xls_parser_response.is_multiple_languages: logger.info( "Edit Questionnaire %s with Multi Language support for organization : %s(%s) and email: %s", questionnaire.name, organization.name, profile.org_id, profile.user.email) if xls_parser_response.errors: info_list = list(xls_parser_response.errors) logger.info("User: %s. Edit upload Errors: %s", request.user.username, json.dumps(info_list)) return HttpResponse( content_type='application/json', content=json.dumps({ 'success': False, 'error_msg': info_list, 'message_prefix': _("Sorry! Current version of DataWinners does not support" ), 'message_suffix': _("Update your XLSForm and upload again.") })) mangrove_service = MangroveService( request, questionnaire_code=questionnaire.form_code, project_name=questionnaire.name, xls_parser_response=xls_parser_response) questionnaire.xform = mangrove_service.xform_with_form_code QuestionnaireBuilder(questionnaire, manager).update_questionnaire_with_questions( xls_parser_response.json_xform_data) tmp_file.seek(0) questionnaire.update_media_field_flag() questionnaire.save(process_post_update=False) base_name, extension = os.path.splitext(tmp_file.name) questionnaire.update_attachments(tmp_file, 'questionnaire%s' % extension) self._purge_submissions(manager, questionnaire) self._purge_feed_documents(questionnaire, request) self._purge_media_details_documents(manager, questionnaire) self.recreate_submissions_mapping(manager, questionnaire) if xls_parser_response.info: info_list = list(xls_parser_response.info) logger.info("User: %s. Edit upload Errors: %s", request.user.username, json.dumps(info_list)) return HttpResponse(content_type='application/json', content=json.dumps({ 'success': True, 'information': info_list, })) except PyXFormError as e: logger.info("User: %s. Upload Error: %s", request.user.username, e.message) message = transform_error_message(e.message) if 'name_type_error' in message or 'choice_name_type_error' in message: if 'choice_name_type_error' in message: message_prefix = _( "On your \"choices\" sheet the first and second column must be \"list_name\" and \"name\". Possible errors:" ) else: message_prefix = _( "On your \"survey\" sheet the first and second column must be \"type\" and \"name\". Possible errors:" ) return HttpResponse( content_type='application/json', content=json.dumps({ 'success': False, 'error_msg': [ _("Columns are missing"), _("Column name is misspelled"), _("Additional space in column name") ], 'message_prefix': message_prefix, 'message_suffix': _("Update your XLSForm and upload again.") })) else: return HttpResponse( content_type='application/json', content=json.dumps({ 'success': False, 'error_msg': [ message if message else ugettext( "all XLSForm features. Please check the list of unsupported features." ) ] })) except QuestionAlreadyExistsException as e: logger.info("User: %s. Upload Error: %s", request.user.username, e.message) return HttpResponse( content_type='application/json', content=json.dumps({ 'success': False, 'error_msg': [ _("Duplicate labels. All questions (labels) must be unique." ) ], 'message_prefix': _("Sorry! Current version of DataWinners does not support" ), 'message_suffix': _("Update your XLSForm and upload again.") })) except UnicodeDecodeError as e: logger.info("User: %s. Upload Error: %s", request.user.username, e.message) return HttpResponse( content_type='application/json', content=json.dumps({ 'success': False, 'error_msg': [ _("Check your columns for errors.<br>There are missing symbols (like $ for relevant or calculate) or incorrect characters<br>" ) + _("Update your XLSForm and upload again.") ], })) except Exception as e: logger.info("User: %s. Edit Upload Exception message: %s", request.user.username, e.message) message = e.message if e.message else _("Some error in excel") odk_message = '' if not 'ODK Validate Errors:' in e.message: send_email_on_exception( request.user, "Questionnaire Edit", traceback.format_exc(), additional_details={'file_contents': file_content}) else: odk_message = translate_odk_message(e.message) message = odk_message if odk_message else message return HttpResponse(content_type='application/json', content=json.dumps({ 'error_msg': [message], 'success': False, })) finally: if tmp_file: tmp_file.close() return HttpResponse( json.dumps({ "success": True, "project_name": questionnaire.name, "project_id": questionnaire.id, "file_name": "%s%s" % (slugify(questionnaire.name), extension), # "xls_dict": XlsProjectParser().parse(file_content) }), content_type='application/json')
def _edit_questionnaire(request, project_id, excel_file=None, excel_as_dict=None): manager = get_database_manager(request.user) questionnaire = Project.get(manager, project_id) try: xls_parser_response = _try_parse_xls(manager, request, questionnaire.name, excel_file) if isinstance(xls_parser_response, HttpResponse): return xls_parser_response doc = deepcopy(questionnaire._doc) doc.xform = MangroveService( request, questionnaire_code=questionnaire.form_code, xls_parser_response=xls_parser_response).xform_with_form_code new_questionnaire = Project.new_from_doc(manager, doc) QuestionnaireBuilder(new_questionnaire, manager).update_questionnaire_with_questions( xls_parser_response.json_xform_data) xform_rules = get_all_rules() if excel_file is None: excel_file = _temp_file(request) else: excel_file.seek(0) questionnaire_wrapper = Questionnaire(excel_file) activity_log_detail = {} XFormEditor( Submission(manager, get_database_name(request.user), xform_rules), Validator(xform_rules), questionnaire_wrapper).edit(new_questionnaire, questionnaire, activity_log_detail) questionnaire = Project.get(manager, project_id) _save_questionnaire_as_dict_for_builder(questionnaire, excel_as_dict, excel_file) UserActivityLog().log(request, action=EDITED_QUESTIONNAIRE, project=questionnaire.name, detail=json.dumps(activity_log_detail)) except UnsupportedXformEditException as e: return HttpResponse( content_type='application/json', content=json.dumps({ 'success': False, 'unsupported': True, 'error_msg': [_("Unsupported edit operation")], "status": "error", 'reason': "Unsupported edit operation", # TODO: i18n translation 'details': e.message })) except QuestionAlreadyExistsException as e: return HttpResponse( content_type='application/json', content=json.dumps({ 'success': False, 'error_msg': [_(e.message)], "status": "error", 'reason': "Save Failed", # TODO: i18n translation 'details': _(e.message) })) return HttpResponse( json.dumps({ "success": True, "status": "success", 'reason': 'Successfully updated' # TODO: i18n translation }), content_type='application/json')
def _overwrite(self, project_id, request): try: manager = get_database_manager(request.user) questionnaire = Project.get(manager, project_id) xls_parser_response = _try_parse_xls(manager, request, questionnaire.name) if isinstance(xls_parser_response, HttpResponse): return xls_parser_response send_email_if_unique_id_type_question_has_no_registered_unique_ids( xls_parser_response, request, questionnaire.name) mangrove_service = MangroveService( request, questionnaire_code=questionnaire.form_code, project_name=questionnaire.name, xls_parser_response=xls_parser_response) questionnaire.xform = mangrove_service.xform_with_form_code QuestionnaireBuilder(questionnaire, manager).update_questionnaire_with_questions( xls_parser_response.json_xform_data) questionnaire.update_media_field_flag() questionnaire.save(process_post_update=False) UserActivityLog().log(self.request, action=EDITED_QUESTIONNAIRE, project=questionnaire.name, detail=questionnaire.name) tmp_file = _temp_file(request) base_name, extension = os.path.splitext(tmp_file.name) questionnaire.update_attachments(tmp_file, 'questionnaire%s' % extension) questionnaire.update_external_itemset( mangrove_service.itemsets_csv) self._purge_submissions(manager, questionnaire) self._purge_feed_documents(questionnaire, request) self._purge_media_details_documents(manager, questionnaire) self.recreate_submissions_mapping(manager, questionnaire) excel_file = _temp_file(request) excel_file.seek(0) _save_questionnaire_as_dict_for_builder(questionnaire, excel_file=excel_file) if xls_parser_response.info: info_list = list(xls_parser_response.info) logger.info("User: %s. Edit upload Errors: %s", request.user.username, json.dumps(info_list)) return HttpResponse(content_type='application/json', content=json.dumps({ 'success': True, 'information': info_list, })) except QuestionAlreadyExistsException as e: return HttpResponse( content_type='application/json', content=json.dumps({ 'success': False, 'error_msg': [_(e.message)], "status": "error", 'reason': "Save Failed", # TODO: i18n translation 'details': _(e.message) })) return HttpResponse( json.dumps({ "success": True, "project_name": questionnaire.name, "project_id": questionnaire.id, "file_name": "%s%s" % (slugify(questionnaire.name), extension), # "xls_dict": XlsProjectParser().parse(file_content) }), content_type='application/json')