Пример #1
0
    def delete(self):
        args = self.del_req_parser.parse_args()
        current_user_id = g.current_user['id']

        response = response_repository.get_by_id(args['id'])
        if not response:
            return errors.RESPONSE_NOT_FOUND

        if response.user_id != current_user_id:
            return errors.UNAUTHORIZED

        response.withdraw()
        response_repository.save(response)      

        try:
            user = user_repository.get_by_id(current_user_id)
            event = response.application_form.event
            organisation = event.organisation

            emailer.email_user(
                'withdrawal',
                template_parameters=dict(
                    organisation_name=organisation.name
                ),
                event=event,
                user=user
            )

        except:                
            LOGGER.error('Failed to send withdrawal confirmation email for response with ID : {id}, but the response was withdrawn succesfully'.format(id=args['id']))

        return {}, 204
Пример #2
0
    def get(self):
        args = self.req_parser.parse_args()
        event_id = args['event_id']
        user_id = g.current_user['id']

        try:
            offer = db.session.query(Offer).filter(Offer.event_id == event_id).filter(Offer.user_id == user_id).first()
            response = response_repository.get_submitted_by_user_id_for_event(user_id, event_id)
            if not response:
                return errors.RESPONSE_NOT_FOUND
            request_travel = response_repository.get_answer_by_question_key_and_response_id('travel_grant', response.id)
            
            if not offer:
                return errors.OFFER_NOT_FOUND
            elif offer.is_expired():
                return errors.OFFER_EXPIRED
            else:
                return offer_info(offer, request_travel), 200

        except SQLAlchemyError as e:
            LOGGER.error("Database error encountered: {}".format(e))
            return errors.DB_NOT_AVAILABLE
        except:
            LOGGER.error("Encountered unknown error: {}".format(
                traceback.format_exc()))
            return errors.DB_NOT_AVAILABLE
Пример #3
0
def _get_candidate_nominator(response):
    nominating_capacity = response_repository.get_answer_by_question_key_and_response_id(
        'nominating_capacity', response.id)
    if not nominating_capacity:
        raise ValueError('Missing nominating capacity answer')
    is_nomination = nominating_capacity.value == 'other'

    if is_nomination:
        question_answers = response_repository.get_question_answers_by_section_key_and_response_id(
            'nominee_section', response.id)

        nomination_info = {
            qa.Question.key: qa.Answer.value
            for qa in question_answers
        }
        candidate = '{nomination_title} {nomination_firstname} {nomination_lastname}'.format(
            **nomination_info)
        candidate_firstname = nomination_info['nomination_firstname']
        nominator = '{} {} {}'.format(response.user.user_title,
                                      response.user.firstname,
                                      response.user.lastname)
    else:
        candidate = '{} {} {}'.format(response.user.user_title,
                                      response.user.firstname,
                                      response.user.lastname)
        candidate_firstname = response.user.firstname
        nominator = None

    return candidate, candidate_firstname, nominator
Пример #4
0
    def delete(self):
        args = self.req_parser.parse_args()

        event_id = args['event_id']
        tag_id = args['tag_id']
        response_id = args['response_id']

        if not _validate_user_admin_or_reviewer(g.current_user['id'], event_id, response_id):
            return errors.FORBIDDEN

        response_repository.remove_tag_from_response(response_id, tag_id)

        return {}
Пример #5
0
    def get(self):
        args = self.req_parser.parse_args()
        response = response_repository.get_by_id_and_user_id(
            args['response_id'], g.current_user['id'])
        if not response:
            return RESPONSE_NOT_FOUND

        return reference_request_repository.get_all_by_response_id(
            response.id), 200
Пример #6
0
    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
Пример #7
0
    def test_build_response_html_app_info(self):

        self._seed_static_data()

        response = response_repository.get_by_id(self.response_id)

        html_info_string = build_response_html_app_info(response, 'en')

        self.assertIsNotNone(html_info_string)
Пример #8
0
    def post(self):
        args = self.post_req_parser.parse_args()
        response_id = args['response_id']
        title = args['title']
        firstname = args['firstname']
        lastname = args['lastname']
        relation = args['relation']
        email = args['email']
        user = user_repository.get_by_id(g.current_user['id'])

        if not user:
            return USER_NOT_FOUND

        event = event_repository.get_event_by_response_id(response_id)
        if not event:
            return EVENT_NOT_FOUND

        response = response_repository.get_by_id(response_id)
        if not response:
            return RESPONSE_NOT_FOUND

        reference_request = ReferenceRequest(response_id=response_id,
                                             title=title,
                                             firstname=firstname,
                                             lastname=lastname,
                                             relation=relation,
                                             email=email)
        reference_request_repository.create(reference_request)

        link = "{host}/reference/{token}".format(host=misc.get_baobab_host(),
                                                 token=reference_request.token)

        candidate, candidate_firstname, nominator = _get_candidate_nominator(
            response)
        if nominator is None:
            nomination_text = "has nominated themself"
        else:
            nomination_text = "has been nominated by {}".format(nominator)

        subject = 'REFERENCE REQUEST - {}'.format(event.name)
        body = REFERENCE_REQUEST_EMAIL_BODY.format(
            title=title,
            firstname=firstname,
            lastname=lastname,
            candidate=candidate,
            candidate_firstname=candidate_firstname,
            nomination_text=nomination_text,
            event_name=event.name,
            event_url=event.url,
            application_close_date=event.application_close,
            link=link)
        send_mail(recipient=email, subject=subject, body_text=body)

        reference_request.set_email_sent(datetime.now())
        reference_request_repository.add(reference_request)
        return reference_request, 201
Пример #9
0
    def test_repo_get_response(self):
        """Test for when retrieving a response from the repository and not via the api directly"""
        self._seed_data()

        response = response_repository.get_by_id_and_user_id(
            self.test_response.id, self.other_user_data['id'])
        self.assertEqual(response.application_form_id, self.test_form.id)
        self.assertEqual(response.user_id, self.other_user_data['id'])
        self.assertIsNone(response.submitted_timestamp)
        self.assertFalse(response.is_withdrawn)
        self.assertTrue(response.answers)

        same_response = response_repository.get_by_id(self.test_response.id)
        self.assertEqual(response, same_response)

        all_user_responses = response_repository.get_by_user_id(
            self.other_user_data['id'])
        self.assertEqual(len(all_user_responses), 2)
        self.assertEqual(response, all_user_responses[0])
Пример #10
0
    def test_repo_get_answers(self):
        self._seed_data()

        # retrieve using response_id
        #   first answer should have correct response_id and question_id
        answers_by_response = response_repository.get_answers_by_response_id(
            self.test_response.id)
        self.assertEqual(answers_by_response[0].response_id,
                         self.test_response.id)
        self.assertEqual(answers_by_response[0].question_id,
                         self.test_question.id)

        # retrieve using question_id
        #   test the first answer here is the same as first answer above
        #   test_question completed by dummy users and other_user
        answers_by_question = response_repository.get_answers_by_question_id(
            self.test_question.id)
        self.assertEqual(answers_by_question[0], answers_by_response[0])
        self.assertEqual(
            len(self.test_users) + 1,
            len(answers_by_question))  # including other_user response

        # retrieve using response_id and question_id
        #   use same question_id and response_id as previous test --> can test object is the same
        answer_by_qid_rid = response_repository.get_answer_by_question_id_and_response_id(
            self.test_question.id, self.test_response.id)
        self.assertEqual(answer_by_qid_rid, answers_by_response[0])
        #   use different ids. Check expected ids are in the returned answer
        answer_by_qid_rid_q2 = response_repository.get_answer_by_question_id_and_response_id(
            self.test_question2.id, self.responses[0].id)
        self.assertEqual(answer_by_qid_rid_q2.response_id,
                         self.responses[0].id)
        self.assertEqual(answer_by_qid_rid_q2.question_id,
                         self.test_question2.id)

        # retrieve all (Question, Answer) tuples using section_id and response_id
        qa_by_sid_rid = response_repository.get_question_answers_by_section_key_and_response_id(
            self.test_section.key, self.test_response.id)
        self.assertTupleEqual(qa_by_sid_rid[0],
                              (self.test_question, self.test_answer1))
        other_response = self.responses[0]
        qa_by_sid_rid_dummy = response_repository.get_question_answers_by_section_key_and_response_id(
            self.test_section.key, other_response.id)
        answer1 = response_repository.get_answer_by_question_id_and_response_id(
            self.test_question.id, other_response.id)
        answer2 = response_repository.get_answer_by_question_id_and_response_id(
            self.test_question2.id, other_response.id)
        self.assertEqual(len(qa_by_sid_rid_dummy), 2)  # answered 2 questions
        self.assertTupleEqual(qa_by_sid_rid_dummy[0],
                              (self.test_question, answer1))
        self.assertTupleEqual(qa_by_sid_rid_dummy[1],
                              (self.test_question2, answer2))
Пример #11
0
    def test_build_response_html_answers(self):
        self._seed_static_data()

        application_form = application_form_repository.get_by_id(
            self.application_form_id)
        answers = response_repository.get_by_id(self.response_id).answers

        html_answer_string = build_response_html_answers(
            answers, 'en', application_form)

        self.assertIsNotNone(html_answer_string)
Пример #12
0
    def post(self):
        args = self.post_req_parser.parse_args()
        response_id = args['response_id']
        title = args['title']
        firstname = args['firstname']
        lastname = args['lastname']
        relation = args['relation']
        email = args['email']
        user = user_repository.get_by_id(g.current_user['id'])

        if not user:
            return USER_NOT_FOUND

        event = event_repository.get_event_by_response_id(response_id)
        if not event:
            return EVENT_NOT_FOUND

        response = response_repository.get_by_id(response_id)
        if not response:
            return RESPONSE_NOT_FOUND

        reference_request = ReferenceRequest(response_id=response_id,
                                             title=title,
                                             firstname=firstname,
                                             lastname=lastname,
                                             relation=relation,
                                             email=email)
        reference_request_repository.create(reference_request)

        link = "{host}/reference/{token}".format(host=misc.get_baobab_host(),
                                                 token=reference_request.token)

        try:
            candidate, candidate_firstname, nominator = _get_candidate_nominator(
                response)
        except ValueError as e:
            LOGGER.error(e)
            return BAD_CONFIGURATION

        email_user('reference-request-self-nomination'
                   if nominator is None else 'reference-request',
                   template_parameters=dict(
                       candidate=candidate,
                       candidate_firstname=candidate_firstname,
                       nominator=nominator,
                       event_url=event.url,
                       application_close_date=event.application_close,
                       link=link),
                   event=event,
                   user=user)

        reference_request.set_email_sent(datetime.now())
        reference_request_repository.add(reference_request)
        return reference_request, 201
Пример #13
0
    def get(self, event_id):
        parser = reqparse.RequestParser()
        parser.add_argument('language', type=str, required=True)
        args = parser.parse_args()

        responses = response_repository.get_all_for_event(event_id)
        review_form = review_repository.get_review_form(event_id)

        return [
            ReviewResponseSummaryListAPI._serialise_response(
                response, review_form, args['language'])
            for response in responses
        ], 200
Пример #14
0
    def get(self):
        args = self.post_req_parser.parse_args()
        token = args['token']

        reference_request = reference_request_repository.get_by_token(
            token)  # type: ReferenceRequest
        if not reference_request:
            return REFRERENCE_REQUEST_WITH_TOKEN_NOT_FOUND

        response_id = reference_request.response_id
        response = response_repository.get_by_id(response_id)  # type: Response
        if not response:
            return RESPONSE_NOT_FOUND

        event = event_repository.get_event_by_response_id(
            response_id)  # type: Event

        if not event:
            return EVENT_NOT_FOUND

        reference = reference_repository.get_by_reference_request_id(
            reference_request.id)
        app_form = event.get_application_form()  # type: ApplicationForm

        # Determine whether the response is a nomination
        try:
            candidate, _, nominator = _get_candidate_nominator(response)
        except ValueError as e:
            LOGGER.error(e)
            return BAD_CONFIGURATION

        return_object = {
            'candidate':
            candidate,
            'nominator':
            nominator,
            'relation':
            reference_request.relation,
            'name':
            event.get_name('en'),
            'description':
            event.get_description('en'),
            'is_application_open':
            event.is_application_open,
            'email_from':
            event.email_from,
            'reference_submitted_timestamp':
            reference.timestamp if reference is not None else None
        }

        return return_object, 200
Пример #15
0
    def get(self):
        LOGGER.debug('Received get request for reference-request')
        user = user_repository.get_by_id(g.current_user['id'])
        if not user:
            return USER_NOT_FOUND

        args = self.req_parser.parse_args()
        response = response_repository.get_by_id_and_user_id(
            args['response_id'], user.id)
        if not response:
            return RESPONSE_NOT_FOUND

        return reference_request_repository.get_all_by_response_id(
            response.id), 200
Пример #16
0
    def get(self):
        args = self.get_req_parser.parse_args()
        event_id = args['event_id']
        current_user_id = g.current_user['id']

        event = event_repository.get_by_id(event_id)
        if not event:
            return errors.EVENT_NOT_FOUND

        if not event.has_application_form():
            return errors.FORM_NOT_FOUND

        form = event.get_application_form()
        responses = response_repository.get_all_for_user_application(current_user_id, form.id)
        return responses
Пример #17
0
    def test_build_response_html_answers_with_answers_missing(self):
        """
        Tests that the builder doesn't break when a question is submitted without an answer
        """

        self._seed_static_data()

        application_form = application_form_repository.get_by_id(
            self.application_form_id)
        answers = response_repository.get_by_id(self.response_id2).answers

        html_string = build_response_html_answers(answers, 'en',
                                                  application_form)

        self.assertIsNotNone(html_string)
Пример #18
0
    def post(self, event_id):
        parser = reqparse.RequestParser()
        parser.add_argument('response_ids',
                            type=int,
                            required=True,
                            action='append')
        parser.add_argument('reviewer_email', type=str, required=True)
        args = parser.parse_args()

        response_ids = args['response_ids']
        reviewer_email = args['reviewer_email']

        filtered_response_ids = response_repository.filter_ids_to_event(
            response_ids, event_id)

        print('response_ids:', response_ids)
        print('filtered_response_ids:', filtered_response_ids)

        if set(filtered_response_ids) != set(response_ids):
            return FORBIDDEN

        event = event_repository.get_by_id(event_id)

        reviewer_user = user_repository.get_by_email(reviewer_email,
                                                     g.organisation.id)
        if reviewer_user is None:
            return USER_NOT_FOUND

        if not reviewer_user.is_reviewer(event_id):
            _add_reviewer_role(reviewer_user.id, event_id)

        response_reviewers = [
            ResponseReviewer(response_id, reviewer_user.id)
            for response_id in response_ids
        ]
        db.session.add_all(response_reviewers)
        db.session.commit()

        if len(response_ids) > 0:
            email_user('reviews-assigned',
                       template_parameters=dict(
                           num_reviews=len(response_ids),
                           baobab_host=misc.get_baobab_host(),
                           system_name=g.organisation.system_name,
                           event_key=event.key),
                       event=event,
                       user=reviewer_user)
        return {}, 201
Пример #19
0
def get_event_status(event_id, user_id):
    invited_guest = invited_guest_repository.get_for_event_and_user(
        event_id, user_id)
    if invited_guest:
        registration = invited_guest_repository.get_registration_for_event_and_user(
            event_id, user_id)
        # If they're an invited guest, we don't bother with whether they applied or not
        return EventStatus(
            invited_guest=invited_guest.role,
            registration_status=_get_registration_status(registration))

    response = response_repository.get_by_user_id_for_event(user_id, event_id)
    if response is None:
        application_status = None
    elif response.is_submitted:
        application_status = 'Submitted'
    elif response.is_withdrawn:
        application_status = 'Withdrawn'
    else:
        application_status = 'Not Submitted'

    outcome = outcome_repository.get_latest_by_user_for_event(
        user_id, event_id)
    if outcome is None:
        outcome_status = None
    else:
        outcome_status = outcome.status.name

    offer = offer_repository.get_by_user_id_for_event(user_id, event_id)
    if offer is None:
        offer_status = None
    elif offer.candidate_response:
        offer_status = 'Accepted'
    elif offer.candidate_response == False:
        offer_status = 'Rejected'
    elif offer.is_expired():
        offer_status = 'Expired'
    else:
        offer_status = 'Pending'

    registration = registration_repository.get_by_user_id(user_id, event_id)
    registration_status = _get_registration_status(registration)

    return EventStatus(application_status=application_status,
                       outcome_status=outcome_status,
                       offer_status=offer_status,
                       registration_status=registration_status)
Пример #20
0
    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)
Пример #21
0
    def get(self):
        args = self.get_req_parser.parse_args()
        user = user_repository.get_by_id(g.current_user['id'])
        response = response_repository.get_by_id(args['response_id'])
        if not response:
            return RESPONSE_NOT_FOUND

        event = event_repository.get_event_by_response_id(response.id)

        if not user.is_event_admin(event.id):
            return FORBIDDEN
        reference_responses = reference_request_repository.get_references_by_response_id(
            response.id)
        return [
            reference_response.Reference
            for reference_response in reference_responses
        ], 200
Пример #22
0
    def put(self):
        args = self.put_req_parser.parse_args()
        user_id = g.current_user['id']
        is_submitted = args['is_submitted']
        language = args['language']

        response = response_repository.get_by_id(args['id'])
        if not response:
            return errors.RESPONSE_NOT_FOUND
        if response.user_id != user_id:
            return errors.UNAUTHORIZED
        if response.application_form_id != args['application_form_id']:
            return errors.UPDATE_CONFLICT

        response.is_submitted = is_submitted
        response.language = language
        if is_submitted:
            response.submit()
        response_repository.save(response)

        answers = []
        for answer_args in args['answers']:
            answer = response_repository.get_answer_by_question_id_and_response_id(
                answer_args['question_id'], response.id)
            if answer:
                answer.update(answer_args['value'])
            else:
                answer = Answer(response.id, answer_args['question_id'],
                                answer_args['value'])
            answers.append(answer)
        response_repository.save_answers(answers)

        try:
            if response.is_submitted:
                LOGGER.info(
                    'Sending confirmation email for response with ID : {id}'.
                    format(id=response.id))
                user = user_repository.get_by_id(user_id)
                response = response_repository.get_by_id_and_user_id(
                    response.id, user_id)
                self.send_confirmation(user, response)
        except:
            LOGGER.warn(
                'Failed to send confirmation email for response with ID : {id}, but the response was submitted succesfully'
                .format(id=response.id))
        finally:
            return response, 200
Пример #23
0
    def post(self):
        args = self.post_req_parser.parse_args()
        user_id = g.current_user['id']
        is_submitted = args['is_submitted']
        application_form_id = args['application_form_id']
        language = args['language']
        if len(language) != 2:
            language = 'en'  # Fallback to English if language doesn't look like an ISO 639-1 code

        application_form = application_form_repository.get_by_id(
            application_form_id)
        if application_form is None:
            return errors.FORM_NOT_FOUND_BY_ID

        user = user_repository.get_by_id(user_id)
        responses = response_repository.get_all_for_user_application(
            user_id, application_form_id)

        if not application_form.nominations and len(responses) > 0:
            return errors.RESPONSE_ALREADY_SUBMITTED

        response = Response(application_form_id, user_id, language)
        if is_submitted:
            response.submit()

        response_repository.save(response)

        answers = []
        for answer_args in args['answers']:
            answer = Answer(response.id, answer_args['question_id'],
                            answer_args['value'])
            answers.append(answer)
        response_repository.save_answers(answers)

        try:
            if response.is_submitted:
                LOGGER.info(
                    'Sending confirmation email for response with ID : {id}'.
                    format(id=response.id))
                user = user_repository.get_by_id(user_id)
                response = response_repository.get_by_id_and_user_id(
                    response.id, user_id)
                self.send_confirmation(user, response)
        except:
            LOGGER.warn(
                'Failed to send confirmation email for response with ID : {id}, but the response was submitted succesfully'
                .format(id=response.id))
        finally:
            return response, 201
Пример #24
0
    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
Пример #25
0
    def get(self):
        def _get_answer(question_id, answers):
            # Get the answer for a question
            for a in answers:
                if a.question_id == question_id:
                    return a

            return None

        def _get_files(application_form, answers):
            # Get the response files that should be exported in the ZIP file

            file_names = []

            for section in application_form.sections:
                for question in section.questions:
                    answer = _get_answer(question.id, answers)
                    if answer is not None:
                        # We are only interested in the files,
                        # the text answers will be in the main PDF file
                        if question.type == 'multi-file':
                            file_names.extend(json.loads(answer.value))
                        if question.type == 'file':
                            file_names.append(json.loads(answer.value))

            return file_names

        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)
        application_form = application_form_repository.get_by_id(response_id)

        # Build the HTML string
        response_string = strings.build_response_html_app_info(response, language) + \
        strings.build_response_html_answers(response.answers, language, application_form)

        # Convert to PDF
        files_to_compress = [('response.pdf',
                              pdfconvertor.html_to_pdf(response.id,
                                                       response_string))]

        # The files that were uploaded as part of the response
        files_to_get = _get_files(application_form, response.answers)
        bucket = storage.get_storage_bucket()

        # Download and name the files
        files_to_compress.extend([
            (f['rename'] or f['filename'],
             io.BytesIO(bucket.blob(f['filename']).download_as_bytes()))
            for f in files_to_get
        ])

        # Zip files
        zipped_files = zip_in_memory(files_to_compress)

        with tempfile.NamedTemporaryFile() as temp:
            temp.write(zipped_files.getvalue())
            return send_file(temp.name,
                             as_attachment=True,
                             attachment_filename=f"response_{response.id}.zip")