def get(self): args = self.get_req_parser.parse_args() user_id = g.current_user['id'] event_id = args['event_id'] page_number = args['page_number'] limit = args['limit'] sort_column = args['sort_column'] reviewer = user_repository.get_by_id(user_id).is_reviewer(event_id) if not reviewer: return FORBIDDEN reviews = review_repository.get_review_history(user_id, event_id) if sort_column == 'review_response_id': reviews = reviews.order_by(ReviewResponse.id) if sort_column == 'submitted_timestamp': reviews = reviews.order_by(ReviewResponse.submitted_timestamp) reviews = reviews.slice(page_number * limit, page_number * limit + limit).all() num_entries = review_repository.get_review_history_count( user_id, event_id) total_pages = ceil(float(num_entries) / limit) reviews = [ReviewHistoryModel(review) for review in reviews] return { 'reviews': reviews, 'num_entries': num_entries, 'current_pagenumber': page_number, 'total_pages': total_pages }
def put(self): args = self.post_req_parser.parse_args() validation_result = self.validate_scores(args['scores']) if validation_result is not None: return validation_result response_id = args['response_id'] review_form_id = args['review_form_id'] reviewer_user_id = g.current_user['id'] scores = args['scores'] is_submitted = args['is_submitted'] response_reviewer = review_repository.get_response_reviewer( response_id, reviewer_user_id) if response_reviewer is None: return FORBIDDEN review_response = review_repository.get_review_response( review_form_id, response_id, reviewer_user_id) if review_response is None: return REVIEW_RESPONSE_NOT_FOUND review_repository.delete_review(review_response) review_response.review_scores = self.get_review_scores(scores) if is_submitted: review_response.submit() db.session.commit() return review_response, 200
def put(self): args = self.post_req_parser.parse_args() validation_result = self.validate_scores(args['scores']) if validation_result is not None: return validation_result response_id = args['response_id'] review_form_id = args['review_form_id'] reviewer_user_id = g.current_user['id'] scores = args['scores'] response_reviewer = review_repository.get_response_reviewer( response_id, reviewer_user_id) if response_reviewer is None: return FORBIDDEN review_response = review_repository.get_review_response( review_form_id, response_id, reviewer_user_id) if review_response is None: return REVIEW_RESPONSE_NOT_FOUND db.session.query(ReviewScore).filter( ReviewScore.review_response_id == review_response.id).delete() review_response.review_scores = self.get_review_scores(scores) db.session.commit() return {}, 200
def get(self): parser = reqparse.RequestParser() parser.add_argument('response_id', type=int, required=True) parser.add_argument('event_id', type=int, required=True) parser.add_argument('language', type=str, required=True) args = parser.parse_args() response_id = args['response_id'] event_id = args['event_id'] review_form = review_repository.get_review_form(event_id) if review_form is None: return REVIEW_FORM_NOT_FOUND response = review_repository.get_response_by_reviewer( response_id, g.current_user['id']) if response is None: return RESPONSE_NOT_FOUND review_response = review_repository.get_review_response( review_form.id, response_id, g.current_user['id']) return ReviewResponseUser(review_form, response, 0, args['language'], review_response=review_response)
def post(self): args = self.post_req_parser.parse_args() validation_result = self.validate_scores(args['scores']) if validation_result is not None: return validation_result response_id = args['response_id'] review_form_id = args['review_form_id'] reviewer_user_id = g.current_user['id'] scores = args['scores'] language = args['language'] is_submitted = args['is_submitted'] response_reviewer = review_repository.get_response_reviewer( response_id, reviewer_user_id) if response_reviewer is None: return FORBIDDEN review_response = ReviewResponse(review_form_id, reviewer_user_id, response_id, language) review_response.review_scores = self.get_review_scores(scores) if is_submitted: review_response.submit() review_repository.add_model(review_response) return review_response, 201
def get(self, event_id): req_parser = reqparse.RequestParser() req_parser.add_argument('include_unsubmitted', type=inputs.boolean, required=True) # Note: Including [] in the question_ids parameter because that gets added by Axios on the front-end req_parser.add_argument('question_ids[]', type=int, required=False, action='append') req_parser.add_argument('language', type=str, required=True) args = req_parser.parse_args() include_unsubmitted = args['include_unsubmitted'] question_ids = args['question_ids[]'] language = args['language'] print('Include unsubmitted:', include_unsubmitted) responses = response_repository.get_all_for_event(event_id, not include_unsubmitted) review_config = review_configuration_repository.get_configuration_for_event(event_id) required_reviewers = 1 if review_config is None else review_config.num_reviews_required + review_config.num_optional_reviews response_reviewers = review_repository.get_response_reviewers_for_event(event_id) response_to_reviewers = { k: list(g) for k, g in itertools.groupby(response_reviewers, lambda r: r.response_id) } review_responses = review_repository.get_review_responses_for_event(event_id) reviewer_to_review_response = { r.reviewer_user_id: r for r in review_responses } serialized_responses = [] for response in responses: reviewers = [_serialize_reviewer(r, reviewer_to_review_response.get(r.reviewer_user_id, None)) for r in response_to_reviewers.get(response.id, [])] reviewers = _pad_list(reviewers, required_reviewers) if question_ids: answers = [_serialize_answer(answer, language) for answer in response.answers if answer.question_id in question_ids] else: answers = [] serialized = { 'response_id': response.id, 'user_title': response.user.user_title, 'firstname': response.user.firstname, 'lastname': response.user.lastname, 'start_date': response.started_timestamp.isoformat(), 'is_submitted': response.is_submitted, 'is_withdrawn': response.is_withdrawn, 'submitted_date': None if response.submitted_timestamp is None else response.submitted_timestamp.isoformat(), 'language': response.language, 'answers': answers, 'reviewers': reviewers, 'tags': [_serialize_tag(rt.tag, language) for rt in response.response_tags] } serialized_responses.append(serialized) return serialized_responses
def get_eligible_response_ids(self, event_id, reviewer_user_id, num_reviews, reviews_required): candidate_responses = review_repository.get_candidate_response_ids( event_id, reviewer_user_id, reviews_required) candidate_response_ids = set([r.id for r in candidate_responses]) # Now remove any responses that the reviewer is already assigned to already_assigned = review_repository.get_already_assigned( reviewer_user_id) already_assigned_ids = set([r.response_id for r in already_assigned]) responses = list(candidate_response_ids - already_assigned_ids) return random.sample(responses, min(len(responses), num_reviews))
def get(self): args = self.get_req_parser.parse_args() id = args['id'] reviewer_user_id = g.current_user['id'] review_form_response = review_repository.get_review_response_with_form( id, reviewer_user_id) if review_form_response is None: return REVIEW_RESPONSE_NOT_FOUND review_form, review_response = review_form_response response = review_repository.get_response_by_review_response( id, reviewer_user_id, review_form.application_form_id) return ReviewResponseUser(review_form, response, 0, review_response)
def get(self): args = self.req_parser.parse_args() event_id = args['event_id'] review_form = review_repository.get_review_form(event_id) if review_form is None: return EVENT_NOT_FOUND reviews_remaining_count = review_repository.get_remaining_reviews_count( g.current_user['id'], review_form.application_form_id) skip = self.sanitise_skip(args['skip'], reviews_remaining_count) response = review_repository.get_response_to_review( skip, g.current_user['id'], review_form.application_form_id) return ReviewResponseUser(review_form, response, reviews_remaining_count)
def _validate_user_admin_or_reviewer(user_id, event_id, response_id): user = user_repository.get_by_id(user_id) # Check if the user is an event admin permitted = user.is_event_admin(event_id) # If they're not an event admin, check if they're a reviewer for the relevant response if not permitted and user.is_reviewer(event_id): response_reviewer = review_repository.get_response_reviewer(response_id, user.id) if response_reviewer is not None: permitted = True return permitted
def get(self, event_id): parser = reqparse.RequestParser() parser.add_argument('language', type=str, required=True) args = parser.parse_args() review_responses = review_repository.get_all_review_responses_by_event( event_id) return [ ReviewResponseDetailListAPI._serialise_review_response( review_response, args['language']) for review_response in review_responses ], 200
def get(self): args = self.get_req_parser.parse_args() event_id = args['event_id'] user_id = g.current_user['id'] current_user = user_repository.get_by_id(user_id) if not current_user.is_event_admin(event_id): return FORBIDDEN counts = review_repository.count_reviews_allocated_and_completed_per_reviewer( event_id) views = [ReviewCountView(count) for count in counts] return views
def get(self): args = self.req_parser.parse_args() event_id = args['event_id'] review_form = review_repository.get_review_form(event_id) if review_form is None: return EVENT_NOT_FOUND reviews_remaining_count = review_repository.get_remaining_reviews_count( g.current_user['id'], review_form.application_form_id) skip = self.sanitise_skip(args['skip'], reviews_remaining_count) response = review_repository.get_response_to_review( skip, g.current_user['id'], review_form.application_form_id) references = [] if response is not None: reference_requests = reference_repository.get_all_by_response_id( response.id) for r in reference_requests: reference = reference_repository.get_reference_by_reference_request_id( r.id) if reference is not None: references.append( ReviewResponseReference(r.title, r.firstname, r.lastname, r.relation, reference.uploaded_document)) review_response = None if response is None else review_repository.get_review_response( review_form.id, response.id, g.current_user['id']) references = None if len(references) == 0 else references return ReviewResponseUser(review_form, response, reviews_remaining_count, args['language'], reference_responses=references, review_response=review_response)
def delete(self, event_id): parser = reqparse.RequestParser() parser.add_argument('response_id', type=int, required=True) parser.add_argument('reviewer_user_id', type=int, required=True) args = parser.parse_args() response_id = args['response_id'] reviewer_user_id = args['reviewer_user_id'] review_form = review_repository.get_review_form(event_id) if not review_form: return REVIEW_FORM_NOT_FOUND # If the reviewer has already completed the review, action can't be completed review_response = review_repository.get_review_response( review_form.id, response_id, reviewer_user_id) if review_response: return REVIEW_ALREADY_COMPLETED review_repository.delete_response_reviewer(response_id, reviewer_user_id) return {}, 200
def get(self): args = self.get_req_parser.parse_args() event_id = args['event_id'] user_id = g.current_user['id'] current_user = user_repository.get_by_id(user_id) if not current_user.is_event_admin(event_id): return FORBIDDEN return { 'reviews_unallocated': review_repository.count_unassigned_reviews(event_id, REVIEWS_PER_SUBMISSION) }
def _serialize_reviewer(response_reviewer, review_form_id): if review_form_id is None: completed = False else: review_response = review_repository.get_review_response(review_form_id, response_reviewer.response_id, response_reviewer.reviewer_user_id) completed = review_response is not None return { 'reviewer_user_id': response_reviewer.user.id, 'user_title': response_reviewer.user.user_title, 'firstname': response_reviewer.user.firstname, 'lastname': response_reviewer.user.lastname, 'completed': completed }
def get(self, event_id): req_parser = reqparse.RequestParser() req_parser.add_argument('stage', type=int, required=False) args = req_parser.parse_args() stage = args['stage'] review_form = review_repository.get_review_form(event_id, stage=stage) if not review_form: return REVIEW_FORM_FOR_STAGE_NOT_FOUND review_form.event_id = event_id return review_form
def _serialise_response(response: Response, review_form: ReviewForm, language: str): scores = [] for review_section in review_form.review_sections: for review_question in review_section.review_questions: if review_question.weight > 0: review_question_translation = review_question.get_translation( language) if not review_question_translation: review_question_translation = review_question.get_translation( 'en') LOGGER.warn( 'Could not find {} translation for review question id {}' .format(language, review_score.review_question.id)) average_score = review_repository.get_average_score_for_review_question( response.id, review_question.id) score = { "review_question_id": review_question.id, "headline": review_question_translation.headline, "description": review_question_translation.description, "type": review_question.type, "score": average_score, "weight": review_question.weight } scores.append(score) response_summary = { "response_id": response.id, "response_user_title": response.user.user_title, "response_user_firstname": response.user.firstname, "response_user_lastname": response.user.lastname, "identifiers": [ ReviewResponseDetailListAPI._serialise_identifier( answer, response.language) for answer in response.answers if answer.question.is_review_identifier() ], "scores": scores, "total": sum(score['score'] * score['weight'] for score in scores) } return response_summary
def get(self): args = self.get_req_parser.parse_args() event_id = args['event_id'] user_id = g.current_user['id'] current_user = user_repository.get_by_id(user_id) if not current_user.is_event_admin(event_id): return FORBIDDEN config = review_configuration_repository.get_configuration_for_event( event_id) return { 'reviews_unallocated': review_repository.count_unassigned_reviews( event_id, config.num_reviews_required) }
def get(self, event_id): req_parser = reqparse.RequestParser() req_parser.add_argument('response_id', type=int, required=True) req_parser.add_argument('language', type=str, required=True) args = req_parser.parse_args() response_id = args['response_id'] language = args['language'] response = response_repository.get_by_id(response_id) review_form = review_repository.get_review_form(event_id) review_form_id = None if review_form is None else review_form.id review_config = review_configuration_repository.get_configuration_for_event(event_id) num_reviewers = review_config.num_reviews_required + review_config.num_optional_reviews if review_config is not None else 1 return ResponseDetailAPI._serialize_response(response, language, review_form_id, num_reviewers)
def get(self): parser = reqparse.RequestParser() parser.add_argument('event_id', type=int, required=True) args = parser.parse_args() event_id = args['event_id'] review_forms = review_repository.get_all_review_forms_for_event( event_id) current_form = [r for r in review_forms if r.active] if not current_form: return NO_ACTIVE_REVIEW_FORM current_form = current_form[0] return { 'current_stage': current_form.stage, 'total_stages': len(review_forms) }
def get(self): parser = reqparse.RequestParser() parser.add_argument('event_id', type=int, required=True) parser.add_argument('language', type=str, required=True) args = parser.parse_args() event_id = args['event_id'] user_id = g.current_user['id'] language = args['language'] if not user_repository.get_by_id(user_id).is_reviewer(event_id): return FORBIDDEN responses_to_review = review_repository.get_review_list( user_id, event_id) return [ ReviewListAPI._serialize_response(response, review_response, language) for response, review_response in responses_to_review ]
def post(self, event_id): parser = reqparse.RequestParser() parser.add_argument('stage', type=int, required=True) args = parser.parse_args() stage = args['stage'] review_forms = review_repository.get_all_review_forms_for_event( event_id) selected_form = [r for r in review_forms if r.stage == stage] if not selected_form: return REVIEW_FORM_FOR_STAGE_NOT_FOUND selected_form = selected_form[0] for form in review_forms: form.deactivate() selected_form.activate() db.session.commit() return {}, 201
def put(self, event_id): dt_format = lambda x: datetime.strptime(x, '%Y-%m-%dT%H:%M:%S') req_parser = reqparse.RequestParser() req_parser.add_argument('id', type=int, required=True) req_parser.add_argument('application_form_id', type=int, required=True) req_parser.add_argument('stage', type=int, required=True) req_parser.add_argument('is_open', type=bool, required=True) req_parser.add_argument('deadline', type=dt_format, required=True) req_parser.add_argument('sections', type=dict, required=True, action='append') args = req_parser.parse_args() id = args['id'] application_form_id = args['application_form_id'] stage = args['stage'] is_open = args['is_open'] deadline = args['deadline'] sections_data = args['sections'] review_form = review_repository.get_review_form_by_id(id) if not review_form: return REVIEW_FORM_NOT_FOUND if application_form_id != review_form.application_form_id: return UPDATE_CONFLICT if event_id != review_form.application_form.event_id: return UPDATE_CONFLICT review_form.stage = stage review_form.is_open = is_open review_form.deadline = deadline # Note: we don't update the active property which is controlled by # the ReviewStageAPI # Delete questions in the review form that no longer exist all_question_ids = [ q["id"] for s in sections_data for q in s["questions"] if "id" in q ] for section in review_form.review_sections: for question in section.review_questions: if question.id not in all_question_ids: review_repository.delete_review_question(question) all_section_ids = [s["id"] for s in sections_data if "id" in s] for section in review_form.review_sections: if section.id not in all_section_ids: review_repository.delete_review_section(section) for section_data in sections_data: if 'id' in section_data: # If ID is populated, then update the existing section section = next((s for s in review_form.review_sections if s.id == section_data['id']), None) # type: ReviewSection if not section: return SECTION_NOT_FOUND current_translations = section.translations # type: Sequence[ReviewSectionTranslation] for current_translation in current_translations: current_translation.description = section_data[ 'description'][current_translation.language] current_translation.headline = section_data['name'][ current_translation.language] section.order = section_data["order"] else: # if not populated, then add new section section = ReviewSection(review_form.id, section_data["order"]) review_repository.add_model(section) languages = section_data['name'].keys() for language in languages: section_translation = ReviewSectionTranslation( section.id, language, section_data['name'][language], section_data['description'][language]) review_repository.add_model(section_translation) for question_data in section_data["questions"]: if "id" in question_data: current_question = next((q for q in section.review_questions if q.id == question_data['id']), None) # type: ReviewQuestion if not current_question: return QUESTION_NOT_FOUND current_question.question_id = question_data[ "question_id"] or None current_question.type = question_data["type"] current_question.order = question_data["order"] current_question.is_required = question_data["is_required"] current_question.weight = question_data["weight"] current_translations = current_question.translations # type: Sequence[ReviewQuestionTranslation] for current_translation in current_translations: current_translation.description = question_data[ 'description'][current_translation.language] current_translation.headline = question_data[ 'headline'][current_translation.language] current_translation.options = question_data['options'][ current_translation.language] current_translation.placeholder = question_data[ 'placeholder'][current_translation.language] current_translation.validation_regex = question_data[ 'validation_regex'][current_translation.language] current_translation.validation_text = question_data[ 'validation_text'][current_translation.language] else: question = ReviewQuestion( review_section_id=section.id, question_id=question_data["question_id"] or None, type=question_data["type"], is_required=question_data["is_required"], order=question_data["order"], weight=question_data["weight"]) review_repository.add_model(question) for language in question_data['headline'].keys(): translation = ReviewQuestionTranslation( review_question_id=question.id, language=language, description=question_data["description"][language], headline=question_data["headline"][language], placeholder=question_data["placeholder"][language], options=question_data["options"][language], validation_regex=question_data["validation_regex"] [language], validation_text=question_data["validation_text"] [language]) review_repository.add_model(translation) db.session.commit() review_form = review_repository.get_review_form_by_id(id) review_form.event_id = event_id return review_form, 200
def get(self, event_id): event = event_repository.get_by_id(event_id) if not event: return EVENT_NOT_FOUND num_responses = response_repository.get_total_count_by_event(event_id) num_submitted_respones = response_repository.get_submitted_count_by_event( event_id) num_withdrawn_responses = response_repository.get_withdrawn_count_by_event( event_id) submitted_response_timeseries = _process_timeseries( response_repository.get_submitted_timeseries_by_event(event_id)) review_config = review_config_repository.get_configuration_for_event( event_id) required_reviews = 1 if review_config is None else review_config.num_reviews_required reviews_completed = review_repository.get_count_reviews_completed_for_event( event_id) reviews_incomplete = review_repository.get_count_reviews_incomplete_for_event( event_id) reviews_unallocated = review_repository.count_unassigned_reviews( event_id, required_reviews) reviews_timeseries = _process_timeseries( review_repository.get_review_complete_timeseries_by_event( event_id)) offers_allocated = offer_repository.count_offers_allocated(event_id) offers_accepted = offer_repository.count_offers_accepted(event_id) offers_rejected = offer_repository.count_offers_rejected(event_id) offers_timeseries = _process_timeseries( offer_repository.timeseries_offers_accepted(event_id)) num_registrations = registration_repository.count_registrations( event_id) num_guests = guest_registration_repository.count_guests(event_id) num_registered_guests = guest_registration_repository.count_registered_guests( event_id) registration_timeseries = _process_timeseries( registration_repository.timeseries_registrations(event_id)) guest_registration_timeseries = _process_timeseries( guest_registration_repository.timeseries_guest_registrations( event_id)) registration_timeseries = _combine_timeseries( registration_timeseries, guest_registration_timeseries) return { 'num_responses': num_responses, 'num_submitted_responses': num_submitted_respones, 'num_withdrawn_responses': num_withdrawn_responses, 'submitted_timeseries': submitted_response_timeseries, 'reviews_completed': reviews_completed, 'review_incomplete': reviews_incomplete, 'reviews_unallocated': reviews_unallocated, 'reviews_complete_timeseries': reviews_timeseries, 'offers_allocated': offers_allocated, 'offers_accepted': offers_accepted, 'offers_rejected': offers_rejected, 'offers_accepted_timeseries': offers_timeseries, 'num_registrations': num_registrations, 'num_guests': num_guests, 'num_registered_guests': num_registered_guests, 'registration_timeseries': registration_timeseries }, 200
def post(self, event_id): dt_format = lambda x: datetime.strptime(x, '%Y-%m-%dT%H:%M:%S') req_parser = reqparse.RequestParser() req_parser.add_argument('application_form_id', type=int, required=True) req_parser.add_argument('stage', type=int, required=True) req_parser.add_argument('is_open', type=bool, required=True) req_parser.add_argument('deadline', type=dt_format, required=True) req_parser.add_argument('active', type=bool, required=True) req_parser.add_argument('sections', type=dict, required=True, action='append') args = req_parser.parse_args() application_form_id = args['application_form_id'] stage = args['stage'] is_open = args['is_open'] deadline = args['deadline'] active = args['active'] sections_data = args['sections'] review_form = review_repository.get_review_form(event_id, stage) if review_form is not None: return REVIEW_FORM_EXISTS other_review_forms = review_repository.get_review_forms(event_id) review_form = ReviewForm( application_form_id, deadline, stage, # Only make this stage active if there is no other active stage. active=not any(o.active for o in other_review_forms)) review_repository.add_model(review_form) for section_data in sections_data: section = ReviewSection(review_form.id, section_data['order']) review_repository.add_model(section) languages = section_data['name'].keys() for language in languages: section_translation = ReviewSectionTranslation( review_section_id=section.id, language=language, headline=section_data['name'][language], description=section_data['description'][language]) review_repository.add_model(section_translation) for question_data in section_data['questions']: question = ReviewQuestion( review_section_id=section.id, question_id=question_data['question_id'] or None, type=question_data['type'], is_required=question_data['is_required'], order=question_data['order'], weight=question_data['weight']) review_repository.add_model(question) languages = question_data['headline'].keys() for language in languages: question_translation = ReviewQuestionTranslation( review_question_id=question.id, language=language, description=question_data["description"][language], headline=question_data["headline"][language], placeholder=question_data["placeholder"][language], options=question_data["options"][language], validation_regex=question_data["validation_regex"] [language], validation_text=question_data["validation_text"] [language]) review_repository.add_model(question_translation) new_review_form = review_repository.get_review_form_by_id( review_form.id) new_review_form.event_id = event_id return new_review_form, 201