def setUpClass(cls): FormModelDocument.registered_functions = [] cls.db_name = uniq('mangrove-test') cls.manager = get_db_manager('http://localhost:5984/', cls.db_name) initializer._create_views(cls.manager) create_views(cls.manager) question1 = UniqueIdField(unique_id_type='clinic', name="entity_question", code="ID", label="What is associated entity") question2 = TextField(name="question1_Name", code="Q1", label="What is your name", defaultValue="some default value", constraints=[TextLengthConstraint(5, 10)]) cls.project1 = Project(dbm=cls.manager, name=project1_name, goals="Testing", devices=['web'], form_code="abc", fields=[question1, question2]) cls.project1_id = cls.project1.save() cls.project2 = Project(dbm=cls.manager, name=project2_name, goals="Testing", devices=['web'], form_code="def", fields=[question1, question2]) cls.project2_id = cls.project2.save()
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_delete_datasender_from_project(self): self.project1 = Project.get(self.manager, self.project1_id) self.project1.data_senders = ['rep1', 'rep2'] datasender_to_be_deleted = 'rep1' self.project1.delete_datasender(self.manager, datasender_to_be_deleted) self.project1 = Project.get(self.manager, self.project1_id) expected_data_senders = ['rep2'] self.assertEqual(self.project1.data_senders, expected_data_senders)
def test_should_throw_unsupported_xform_edit_exception(self): new_questionnaire = Project.new_from_doc(DatabaseManagerStub(), ProjectDocument()) old_questionnaire = Project.new_from_doc(DatabaseManagerStub(), ProjectDocument()) validator = Mock(Validator) validator.valid.return_value = False self.assertRaises(UnsupportedXformEditException, XFormEditor(Mock(Submission), validator, Mock(Questionnaire)).edit, new_questionnaire, old_questionnaire, {})
def test_should_save_questionnaire_and_update_submission_when_valid_change(self): new_questionnaire = Project.new_from_doc(DatabaseManagerStub(), ProjectDocument()) old_questionnaire = Project.new_from_doc(DatabaseManagerStub(), ProjectDocument()) submission = Mock(Submission) validator = Mock(Validator) questionnaire = Mock(Questionnaire) validator.valid.return_value = True XFormEditor(submission, validator, questionnaire).edit(new_questionnaire, old_questionnaire, {}) questionnaire.save.assert_called_once_with(new_questionnaire) submission.update_all.assert_called_once_with(new_questionnaire.id)
def test_should_update_project(self): self.project1 = Project.get(self.manager, self.project1_id) self.project1.update( dict(name=project1_name, devices=['web', 'sms'], goals="New goals")) project1_id = self.project1.save() project = Project.get(self.manager, project1_id) self.assertEquals(project.name, project1_name) self.assertEquals(project.goals, 'New goals') self.assertEquals(project.devices, ['web', 'sms'])
def test_get_deadline_day(self): reminder_and_deadline_for_month = { "reminders_enabled": "True", "deadline_month": "5", "deadline_type": "current", "frequency_enabled": "True", "has_deadline": "True", "frequency_period": "month" } project_reminders = Project(self.manager, name="ReminderProject") project_reminders.reminder_and_deadline = reminder_and_deadline_for_month self.assertEquals(5, project_reminders.get_deadline_day())
def test_project_name_should_be_case_insensitively_unique(self): questionnaire = Project(self.manager, name=project2_name.upper(), goals="Testing", devices=['web']) with self.assertRaises(Exception) as cm: questionnaire.save() the_exception = cm.exception self.assertEqual( the_exception.message, "Questionnaire with Name = '%s' already exists." % project2_name.upper())
def test_project_name_should_be_unique(self): questionnaire = Project(dbm=self.manager, name=project2_name, goals="Testing", devices=['web'], form_code="name_form", fields=[]) with self.assertRaises(Exception) as cm: questionnaire.save() the_exception = cm.exception self.assertEqual( the_exception.message, "Questionnaire with Name = '%s' already exists." % project2_name)
def process(self, form_code, submission_values): form_model = get_form_model_by_code(self.dbm, form_code) project = Project.from_form_model(form_model=form_model) reporter_entity = self.request.get('reporter_entity') if project.is_open_survey or (reporter_entity.short_code == "test" or \ isinstance(form_model, EntityFormModel) or \ reporter_entity.short_code in Project.from_form_model(form_model).data_senders): self.check_answers_numbers() return None self.check_answers_numbers(linked_datasender=False) return self._get_response(form_code)
def setUp(self): MangroveTestCase.setUp(self) initializer.run(self.manager) self.ds1 = self.create_datasender() self.ds2 = self.create_datasender() self.project = Project(self.manager, name="Test reminders", form_code="abc", fields=[], goals="This project is for automation", devices=["sms", "web", "smartPhone"], sender_group="close") self.manager._save_document( SurveyResponseDocument(channel="transport", destination=12345, form_model_id=self.project.id, values={ 'Q1': 'ans1', 'Q2': 'ans2' }, status=False, error_message="", data_record_id='2345678', owner_uid=self.ds1.id, event_time=datetime.datetime(2011, 9, 1))) self.manager._save_document( SurveyResponseDocument(channel="transport", destination=12345, form_model_id=self.project.id, values={ 'Q1': 'ans12', 'Q2': 'ans22' }, owner_uid=self.ds1.id, status=False, error_message="", data_record_id='1234567', event_time=datetime.datetime(2011, 3, 2))) self.manager._save_document( SurveyResponseDocument(channel="transport", destination=12345, form_model_id=self.project.id, values={ 'Q1': 'ans123', 'Q2': 'ans222' }, owner_uid=self.ds2.id, status=False, error_message="", data_record_id='1234567', event_time=datetime.datetime(2011, 3, 3)))
def get_customized_message_for_questionnaire(dbm, request, message_code, form_code, placeholder_dict=None, form_model=None): if form_model is None: try: form_model = get_form_model_by_code(dbm, form_code) except: pass if form_model is None or isinstance( form_model, EntityFormModel): #For UniqueId registration message = _get_customized_message_for_language( dbm, request.get('organization').language, message_code) else: # For questionnaire submission project = Project.from_form_model(form_model) message = _get_customized_message_for_language(dbm, project.language, message_code) request[ 'is_outgoing_reply_sms_enabled'] = project.is_outgoing_sms_replies_enabled if placeholder_dict: message = _replace_placeholders_in_message(message, placeholder_dict) return message
def remove_deleted_ds_from_project(db_name): logger = logging.getLogger(db_name) try: dbm = get_db_manager(db_name) logger.info("starting data fix for " + db_name) all_data_senders = set(get_all_active_data_senders(dbm)) for project_doc in dbm.database.view("project_names/project_names", include_docs=True): try: project_data_senders = set(project_doc["doc"]["data_senders"]) invalid_ds = project_data_senders.difference(all_data_senders) project_doc = Project._wrap_row(project_doc) for ds in invalid_ds: logger.info("Found invalid data senders in project : " + str(project_doc) + " " + str(invalid_ds)) project_doc.data_senders.remove(ds) project_doc.save() except Exception as e: print "Error : " + db_name + " : " + str( project_doc) + e.message traceback.print_exc(file=sys.stdout) logger.info("done:" + db_name) mark_as_completed(db_name) except Exception as e: logger.exception(e.message)
def update_submission_search_for_subject_edition(dbm, unique_id_type, short_code, last_name): projects = [] for row in dbm.load_all_rows_in_view('projects_by_subject_type', key=unique_id_type[0], include_docs=True): projects.append( Project.new_from_doc(dbm, ProjectDocument.wrap(row['doc']))) for project in projects: entity_field_code = None for field in project.entity_questions: if [field.unique_id_type] == unique_id_type: entity_field_code = field.code if entity_field_code: unique_id_field_name = es_questionnaire_field_name( entity_field_code, project.id) fields_mapping = {unique_id_field_name: last_name} args = { es_unique_id_code_field_name(unique_id_field_name): short_code } query = _get_submissions_for_unique_id_entry(args, dbm, project) for survey_response in query.values_dict('void'): SubmissionIndexUpdateHandler( dbm.database_name, project.id).update_field_in_submission_index( survey_response._id, fields_mapping)
def edit_xform_submission_post(request, survey_response_id): manager = get_database_manager(request.user) survey_response = get_survey_response_by_id(manager, survey_response_id) activity_log = UserActivityLog() questionnaire = Project.get(manager, survey_response.form_model_id) old_data = survey_response._doc.values try: response = XFormWebSubmissionHandler(request=request). \ update_submission_response(survey_response_id) new_survey_response = get_survey_response_by_id( manager, survey_response_id) new_data = new_survey_response._doc.values edit_details = _details_for_activity_log(new_data, old_data, questionnaire) activity_log.log(request, action=EDITED_DATA_SUBMISSION_ADV_QUEST, project=questionnaire.name, detail=json.dumps(edit_details)) return response except Exception as e: logger.exception("Exception in submission : \n%s" % e) send_email_on_exception(request.user, "Edit Web Submission", traceback.format_exc(), additional_details={ 'survey_response_id': survey_response_id, 'submitted-data': request.POST['form_data'] }) return HttpResponseBadRequest()
def post(self, request, project_id): data = request.POST['data'] file_type = request.POST['file_type'] is_draft = request.POST['is_draft'] try: excel_as_dict = json.loads(data, object_pairs_hook=OrderedDict) if is_draft and is_draft.lower().strip() == 'true': manager = get_database_manager(request.user) questionnaire = Project.get(manager, project_id) _save_questionnaire_as_dict_for_builder( questionnaire, excel_as_dict=excel_as_dict) return HttpResponse(json.dumps({ "status": "success", "project_id": project_id, 'reason': 'Successfully updated', 'details': '' }), content_type='application/json') excel_raw_stream = convert_json_to_excel(excel_as_dict, file_type) excel_file = _temp_file(request, excel_raw_stream, file_type) return _edit_questionnaire(request, project_id, excel_file, excel_as_dict) except Exception as e: logger.exception('Unable to save questionnaire from builder') return HttpResponse( json.dumps({ "status": "error", "project_id": project_id, 'reason': 'Unable to save', # TODO: i18n translation 'details': e.message }), content_type='application/json')
def my_poll_recipients_count(request, project_id): dbm = get_database_manager(request.user) questionnaire = Project.get(dbm, project_id) contact_dict = _get_poll_recipients(dbm, questionnaire) return HttpResponse(content_type='application/json', content=json.dumps( {'my_poll_recipients': contact_dict}))
def geo_json_for_project(request, project_id, entity_type=None): dbm = get_database_manager(request.user) location_list = [] try: if entity_type: first_geocode_field = _get_first_geocode_field_for_entity_type( dbm, entity_type) if first_geocode_field: unique_ids = get_all_entities(dbm, [entity_type], limit=1000) location_list.extend( get_location_list_for_entities(first_geocode_field, unique_ids)) else: questionnaire = Project.get(dbm, project_id) unique_ids = by_short_codes(dbm, questionnaire.data_senders, ["reporter"], limit=1000) location_list.extend(get_location_list_for_datasenders(unique_ids)) except DataObjectNotFound: pass location_geojson = {"type": "FeatureCollection", "features": location_list} return HttpResponse(json.dumps(location_geojson))
def _associate_datasender_to_poll_questionnaire(self, current_project_id, dbm, short_codes): questionnaire = Project.get(dbm, current_project_id) questionnaire.associate_data_sender_to_project(dbm, short_codes) questionnaire.save() for short_code in short_codes: update_datasender_index_by_id(short_code, dbm)
def send_reminders_for_an_organization(org, on_date, sms_client, from_number, dbm, charged_sms=False): """ Sends out all reminders for an organization, scheduled for the given date. """ reminders_grouped_by_proj = _get_reminders_grouped_by_project_for_organization( org.org_id) logger.info("Projects with reminders:- %d" % len(reminders_grouped_by_proj)) for project_id, reminders in reminders_grouped_by_proj.items(): try: project = Project.get(dbm, project_id) if not project.has_deadline(): continue #send reminders to next projects in the queue if their is any error while sending reminders to previous project _, total_sms_sent = send_reminders_on(project, reminders, on_date, sms_client, from_number, dbm) increment_dict = {'sent_reminders_count': total_sms_sent} if charged_sms: increment_dict.update( {'sent_reminders_charged_count': total_sms_sent}) org.increment_message_count_for(**increment_dict) except Exception: logger.exception( "Exception while sending reminders for this project")
def get_submission_breakup(request, project_id): dbm = get_database_manager(request.user) questionnaire = Project.get(dbm, project_id) submission_success, submission_errors = submission_stats( dbm, questionnaire.id) response = json.dumps([submission_success, submission_errors]) return HttpResponse(response)
def analysis_results(request, project_id=None, questionnaire_code=None): manager = get_database_manager(request.user) org_id = helper.get_org_id_by_user(request.user) if request.method == 'GET': questionnaire = Project.get(manager, project_id) dashboard_page = settings.HOME_PAGE + "?deleted=true" if questionnaire.is_void(): return HttpResponseRedirect(dashboard_page) filterable_fields = get_filterable_fields(questionnaire.fields, []) first_filterable_fields = filterable_fields.pop( 0) if filterable_fields else None result_dict = { "xform": questionnaire.xform, "user_email": request.user.email, "is_quota_reached": is_quota_reached(request, org_id=org_id), "first_filterable_field": first_filterable_fields, "filterable_fields": filterable_fields, 'is_pro_sms': get_organization(request).is_pro_sms, "is_media_field_present": questionnaire.is_media_type_fields_present # first 3 columns are additional submission data fields (ds_is, ds_name and submission_status } result_dict.update( project_info(request, questionnaire, questionnaire_code)) return render_to_response('project/analysis_results.html', result_dict, context_instance=RequestContext(request))
def test_get_correct_web_submission_link(self): request = Mock() request.user = Mock(spec=User) manager = Mock(spec=DatabaseManager) manager.database = dict() raw_project = dict( value=dict(_id="pid", devices=["sms", "web"], name="Project Name", created="2012-05-23T02:57:09.788294+00:00")) project = Project(dbm=manager, name="Project Name") profile = Mock(spec=NGOUserProfile) questionnaire = Mock() questionnaire.form_code = "q01" with patch("datawinners.project.models.Project.get") as get_project: get_project.return_value = project with patch.object(DatabaseManager, "get") as db_manager: db_manager.return_value = questionnaire with patch("django.contrib.auth.models.User.get_profile" ) as get_profile: get_profile.return_value = profile profile.reporter = False project_info = get_project_info(manager, raw_project) self.assertEqual(project_info["web_submission_link"], "/project/testquestionnaire/pid/")
def _get_cascade_questionnaire(self, cascades): fields = [] for cascade in cascades: fields.append( SelectField(cascade, cascade, "Please select", cascades[cascade], is_cascade=True)) doc = ProjectDocument() doc.xform = self._build_xform(fields=fields, field_type="cascade", cascades=cascades) questionnaire = Project.new_from_doc(DatabaseManagerStub(), doc) questionnaire.name = "q1" questionnaire.form_code = "007" questionnaire.fields.append( FieldSet(code="group_outer", name="group_outer", label="Enter the outer group details", field_set=[ FieldSet(code="repeat_outer", name="repeat_outer", label="Enter the details you wanna repeat", field_set=fields) ])) return questionnaire
def post(self, request): project_name = request.GET['pname'].strip() manager = get_database_manager(request.user) try: xls_parser_response = _try_parse_xls(manager, request, project_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, project_name) questionnaire_code = generate_questionnaire_code(manager) excel_file = _temp_file(request) mangrove_service = MangroveService( request, questionnaire_code=questionnaire_code, project_name=project_name, xls_form=excel_file, xls_parser_response=xls_parser_response) questionnaire_id, form_code = mangrove_service.create_project() if not questionnaire_id: logger.info("User: %s. Upload Error: %s", request.user.username, "Questionnaire must be unique") 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.") })) questionnaire = Project.get(manager, questionnaire_id) _save_questionnaire_as_dict_for_builder(questionnaire, excel_file=excel_file) except QuestionAlreadyExistsException as e: return HttpResponse(content_type='application/json', content=json.dumps({ 'success': False, 'error_msg': [_(e.message)] })) return HttpResponse(json.dumps({ "success": True, "project_name": project_name, "project_id": questionnaire_id, "form_code": form_code }), content_type='application/json')
def make_user_data_sender_with_project(manager, reporter_id, project_id): questionnaire = Project.get(manager, project_id) reporters_to_associate = [reporter_id] questionnaire.associate_data_sender_to_project(manager, reporters_to_associate) for data_senders_code in reporters_to_associate: update_datasender_index_by_id(data_senders_code, manager)
def test_should_validate_xform_change(self): rule1 = Mock(Rule) rule2 = Mock(Rule) new_questionnaire = Project.new_from_doc(DatabaseManagerStub(), ProjectDocument()) old_questionnaire = Project.new_from_doc(DatabaseManagerStub(), ProjectDocument()) old_questionnaire.xform_model = Mock(Xform) new_questionnaire.xform_model = Mock(Xform) old_questionnaire.xform_model.equals.return_value = True activity_log_detail = {} self.assertTrue(Validator([rule1, rule2]).valid(new_questionnaire, old_questionnaire, activity_log_detail)) rule1.update_xform.assert_called_once_with(old_questionnaire, new_questionnaire, activity_log_detail) old_questionnaire.xform_model.equals.return_value = False self.assertFalse(Validator([rule1, rule2]).valid(new_questionnaire, old_questionnaire, activity_log_detail))
def test_should_not_show_change_setting_option(self): self.registered_datasenders_page = self._create_project_and_go_to_registered_datasenders( ) self.assertFalse(self.registered_datasenders_page. is_change_setting_option_displayed()) form_model = get_form_model_by_code(self.dbm, self.questionnaire_code) project = Project.from_form_model(form_model) self.assertFalse(project.is_open_survey)
def _get_projects(self, manager, request): project_ids = request.POST.get('project_id').split(';') questionnaires = [] for project_id in project_ids: questionnaire = Project.get(manager, project_id) if questionnaire is not None: questionnaires.append(questionnaire) return questionnaires
def get_projects_by_unique_id_type(dbm, unique_id_type): projects = [] for row in dbm.load_all_rows_in_view('projects_by_subject_type', key=unique_id_type[0], include_docs=True): projects.append( Project.new_from_doc(dbm, ProjectDocument.wrap(row['doc']))) return projects