Пример #1
0
    def create_submission(self, survey, user):
        session = object_session(survey)
        program = survey.program
        submission = model.Submission(program=program,
                                      organisation=user.organisation,
                                      survey=survey,
                                      title="First submission",
                                      approval='draft')
        session.add(submission)

        for m in program.measures:
            # Preload response type to avoid autoflush
            response_type = m.response_type
            qnode_measure = m.get_qnode_measure(survey)
            if not qnode_measure:
                continue
            response = model.Response(qnode_measure=qnode_measure,
                                      submission=submission,
                                      user=user)
            response.attachments = []
            response.not_relevant = False
            response.modified = datetime.datetime.utcnow()
            response.approval = 'final'
            response.comment = "Response for %s" % m.title
            session.add(response)
            if response_type.name == 'Yes / No':
                response.response_parts = [{'index': 1, 'note': "Yes"}]
            elif response_type.name in {
                    'Numerical', 'External Numerical', 'Planned', 'Actual'
            }:
                response.response_parts = [{'value': 1}]
            else:
                raise ValueError("Unknown response type")

            response.attachments.append(
                model.Attachment(file_name="File %s 1" % m.title,
                                 url="Bar",
                                 storage='external',
                                 organisation=user.organisation))
            response.attachments.append(
                model.Attachment(file_name="File %s 2" % m.title,
                                 url="Baz",
                                 storage='external',
                                 organisation=user.organisation))
            response.attachments.append(
                model.Attachment(file_name="File %s 3" % m.title,
                                 blob=b'A blob',
                                 storage='external',
                                 organisation=user.organisation))

        session.flush()

        calculator = Calculator.scoring(submission)
        calculator.mark_entire_survey_dirty(submission.survey)
        calculator.execute()
        submission.approval = 'final'
        session.flush()
        return submission
Пример #2
0
    def create_submission(self):
        # Respond to a survey
        with model.session_scope() as session:
            program = session.query(model.Program).one()
            user = (session.query(
                model.AppUser).filter_by(email='clerk').one())
            organisation = (session.query(
                model.Organisation).filter_by(name='Utility').one())
            survey = (session.query(
                model.Survey).filter_by(title='Survey 1').one())
            submission = model.Submission(program_id=program.id,
                                          organisation_id=organisation.id,
                                          survey_id=survey.id,
                                          title="Submission",
                                          approval='draft')
            session.add(submission)

            for m in program.measures:
                # Preload response type to avoid autoflush
                response_type = m.response_type
                qnode_measure = m.get_qnode_measure(survey)
                if not qnode_measure:
                    continue
                response = model.Response(submission=submission,
                                          qnode_measure=qnode_measure,
                                          user=user)
                response.attachments = []
                response.not_relevant = False
                response.modified = sa.func.now()
                response.approval = 'final'
                response.comment = "Response for %s" % m.title
                session.add(response)
                if response_type.name == 'Yes / No':
                    response.response_parts = [{'index': 1, 'note': "Yes"}]
                else:
                    response.response_parts = [{'value': 1}]

            calculator = Calculator.scoring(submission)
            calculator.mark_entire_survey_dirty(submission.survey)
            calculator.execute()

            functions = list(submission.rnodes)
            self.assertAlmostEqual(functions[0].score, 33)
            self.assertAlmostEqual(functions[1].score, 0)
            self.assertAlmostEqual(functions[0].qnode.total_weight, 33)
            self.assertAlmostEqual(functions[1].qnode.total_weight, 0)

            return submission.id
Пример #3
0
    def background_task(self, program_id, survey_id, organisation_id, title):

        with tempfile.NamedTemporaryFile() as fd:
            fileinfo = self.request.files['file'][0]
            fd.write(fileinfo['body'])
            all_rows = self.read_sheet(fd.name)

        with model.session_scope() as session:
            user_session = self.get_user_session(session)

            org = session.query(model.Organisation).get(organisation_id)
            if not org:
                raise errors.ModelError("No such organisation")

            survey = (session.query(model.Survey).get((survey_id, program_id)))
            if not survey:
                raise errors.ModelError("No such survey")

            submission = model.Submission()
            submission.program = survey.program
            submission.survey = survey
            submission.organisation = org
            submission.title = title
            submission.approval = 'draft'
            session.add(submission)
            session.flush()
            submission_id = submission.id

            policy = user_session.policy.derive({
                'org':
                org,
                'survey':
                survey,
                'surveygroups':
                submission.surveygroups,
            })
            policy.verify('surveygroup_interact')
            policy.verify('submission_add')

            self.process_submission_file(all_rows, session, submission,
                                         user_session.user)

        return submission_id
Пример #4
0
    def post(self, submission_id):
        '''Create new.'''
        if submission_id:
            raise errors.MethodError("Can't use POST for existing object")

        program_id = self.get_argument('programId', '')
        if not program_id:
            raise errors.ModelError("Program ID is required")

        survey_id = self.get_argument('surveyId', '')
        if not survey_id:
            raise errors.ModelError("Survey ID is required")

        organisation_id = self.get_argument('organisationId', '')
        if not organisation_id:
            raise errors.ModelError("Organisation ID is required")

        # Source submission ID
        duplicate_id = self.get_argument('duplicateId', '')

        with model.session_scope() as session:
            user_session = self.get_user_session(session)

            org = session.query(model.Organisation).get(organisation_id)
            if not org:
                raise errors.ModelError("No such organisation")

            survey = session.query(model.Survey).get((survey_id, program_id))
            if not survey:
                raise errors.ModelError("No such survey")

            if duplicate_id:
                source_submission = (session.query(
                    model.Submission).get(duplicate_id))
                if not source_submission:
                    raise errors.MissingDocError(
                        "Source submission (for duplication) not found")
                if source_submission.organisation != org:
                    raise errors.ModelError(
                        "Can't duplicate a submission across two "
                        "organisations: '%s' and '%s'" %
                        (source_submission.organisation.name, org.name))
            else:
                source_submission = None

            submission = model.Submission(program=survey.program,
                                          survey=survey,
                                          organisation=org,
                                          approval='draft')
            self._update(submission, self.request_son)
            session.add(submission)

            surveygroups = submission.surveygroups
            if source_submission:
                surveygroups &= source_submission.surveygroups

            policy = user_session.policy.derive({
                'org': org,
                'survey': survey,
                'surveygroups': surveygroups,
            })
            policy.verify('surveygroup_interact')
            policy.verify('submission_add')

            session.flush()
            submission_id = str(submission.id)

            if source_submission:
                yield SubmissionHandler.executor.submit(
                    self.duplicate, submission, source_submission, session)

            act = Activities(session)
            act.record(user_session.user, submission, ['create'])
            act.ensure_subscription(user_session.user, submission,
                                    submission.organisation, self.reason)

        self.get(submission_id)
Пример #5
0
    def test_extern(self):
        '''Check that variables can depend on each other'''
        with model.session_scope() as session:
            user = (session.query(
                model.AppUser).filter_by(email='clerk').one())
            survey = (session.query(
                model.Survey).filter_by(title='Survey 1').one())
            program = survey.program

            # Add a response type that has an extenal variable
            rt = next(rt for rt in TEST_RESPONSE_TYPES
                      if rt['id'] == 'external-var')
            ext_response_type = model.ResponseType(program=program,
                                                   name=rt['name'],
                                                   parts=rt['parts'],
                                                   formula=rt['formula'])
            session.add(ext_response_type)

            # Attach response type to a measure
            target_qm = survey.qnodes[0].children[0].qnode_measures[1]
            target_qm.measure.response_type = ext_response_type
            self.assertEqual(1, len(ext_response_type.measures))

            # Bind variable to link measures
            source_qm = survey.qnodes[0].children[0].qnode_measures[0]
            session.add(
                model.MeasureVariable(program=program,
                                      survey=survey,
                                      source_qnode_measure=source_qm,
                                      source_field='_score',
                                      target_qnode_measure=target_qm,
                                      target_field='ext'))

            submission = model.Submission(program=program,
                                          organisation=user.organisation,
                                          survey=survey,
                                          title="Intermeasure Variables Test",
                                          approval='draft')
            session.add(submission)
            session.flush()

            submission_id = str(submission.id)
            mid_111 = str(
                survey.qnodes[0].children[0].qnode_measures[0].measure_id)
            mid_112 = str(
                survey.qnodes[0].children[0].qnode_measures[1].measure_id)

        # Put dependant response with errors. Check that the error refers to
        # missing dependency.
        with base.mock_user('clerk'):
            response_son = {
                'notRelevant': False,
                'responseParts': [],
                'comment': "Incomplete dependant response",
                'approval': 'draft',
            }
            response_son = self.fetch("/submission/%s/response/%s.json" %
                                      (submission_id, mid_112),
                                      method='PUT',
                                      body=response_son,
                                      expected=200,
                                      decode=True)

        with model.session_scope() as session:
            response = (session.query(model.Response).get(
                (submission_id, mid_112)))
            self.assertIn('depends on', response.error)
            self.assertIn('measure has an error', response.parent.error)
            self.assertIn('sub-category has an error',
                          response.parent.parent.error)
            self.assertIn('category has an error', response.submission.error)

        # Put dependency, and check that error of dependant has changed.
        with base.mock_user('clerk'):
            response_son = {
                'notRelevant': False,
                'responseParts': [{
                    'note': 'Yes',
                    'index': 1
                }],
                'comment': "Dependency",
                'approval': 'draft',
            }
            response_son = self.fetch("/submission/%s/response/%s.json" %
                                      (submission_id, mid_111),
                                      method='PUT',
                                      body=response_son,
                                      expected=200,
                                      decode=True)

        with model.session_scope() as session:
            response = (session.query(model.Response).get(
                (submission_id, mid_111)))
            self.assertIs(response.error, None)
            # Parent still has an error due to sibling
            self.assertIn('measure has an error', response.parent.error)

            response = (session.query(model.Response).get(
                (submission_id, mid_112)))
            # Error has changed: dependency has been provided, but response
            # is still incomplete
            self.assertIn('undefined variable', response.error)

        # Fix dependant response and check that errors are resolved.
        with base.mock_user('clerk'):
            response_son = self.fetch("/submission/%s/response/%s.json" %
                                      (submission_id, mid_112),
                                      method='GET',
                                      expected=200,
                                      decode=True)
            response_son['response_parts'] = [{'value': 1}]
            response_son['comment'] = "Complete dependant response"
            response_son = self.fetch("/submission/%s/response/%s.json" %
                                      (submission_id, mid_112),
                                      method='PUT',
                                      body=response_son,
                                      expected=200,
                                      decode=True)

        with model.session_scope() as session:
            response = (session.query(model.Response).get(
                (submission_id, mid_112)))
            # Error has been resolved.
            self.assertIs(response.error, None)
            self.assertIs(response.error, response.parent.error)
            self.assertIs(response.error, response.parent.parent.error)
            self.assertIs(response.error, response.submission.error)