Exemplo n.º 1
0
            def create_surveys(hsons):
                surveys = []
                for hson in hsons:
                    survey = model.Survey(program=program,
                                          title=hson['title'],
                                          description=hson['description'],
                                          deleted=hson.get('deleted', False))
                    survey.structure = hson['structure']
                    session.add(survey)

                    # Explicitly add to collection because backref is one-way.
                    if not hson.get('deleted', False):
                        program.surveys.append(survey)

                    survey.qnodes = create_qnodes(hson['qnodes'], survey)
                    survey.qnodes.reorder()

                    if 'dependencies' in hson:
                        link_measures(survey, hson['dependencies'])

                    calculator = Calculator.structural()
                    calculator.mark_entire_survey_dirty(survey)
                    calculator.execute()
                    # print_survey(survey)
                return surveys
Exemplo n.º 2
0
    def put(self, response_type_id):
        '''Update existing'''

        program_id = self.get_argument('programId', '')

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

            response_type = (session.query(model.ResponseType).get(
                (response_type_id, program_id)))
            if not response_type:
                raise errors.MissingDocError("No such response type")

            policy = user_session.policy.derive({
                'program':
                response_type.program,
                'surveygroups':
                response_type.program.surveygroups,
            })
            policy.verify('surveygroup_interact')
            policy.verify('response_type_edit')

            if 'name' in self.request_son:
                rt_by_name = (session.query(model.ResponseType).filter(
                    model.ResponseType.program_id == program_id).filter(
                        model.ResponseType.name ==
                        self.request_son.name).first())
                if rt_by_name and rt_by_name != response_type:
                    raise errors.ModelError(
                        "'" + self.request_son.name +
                        "' as a response type of that name already exists")

            try:
                self._update(response_type, self.request_son)
            except ResponseTypeError as e:
                raise errors.ModelError(str(e))
            except voluptuous.error.Error as e:
                raise errors.ModelError(str(e))
            except Exception as e:
                raise errors.ModelError(str(e))

            verbs = []
            # Check if modified now to avoid problems with autoflush later
            if session.is_modified(response_type):
                verbs.append('update')
                calculator = Calculator.structural()
                for measure in response_type.measures:
                    for qnode_measure in measure.qnode_measures:
                        calculator.mark_measure_dirty(qnode_measure)
                calculator.execute()

            act = Activities(session)
            act.record(user_session.user, response_type, verbs)
            act.ensure_subscription(user_session.user, response_type,
                                    response_type.program, self.reason)

        self.get(response_type_id)
Exemplo n.º 3
0
    def delete(self, qnode_id):
        '''Delete existing.'''

        if not qnode_id:
            raise errors.MethodError("Question node ID required")

        program_id = self.get_argument('programId', '')

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

            qnode = (
                session.query(model.QuestionNode)
                .options(joinedload('program'))
                .options(joinedload('program.surveygroups'))
                .get((qnode_id, program_id)))
            if not qnode:
                raise errors.MissingDocError("No such question node")
            log.debug("deleting: %s", qnode)

            program = qnode.program
            survey = qnode.survey
            parent = qnode.parent

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

            act = Activities(session)
            if not qnode.deleted:
                act.record(user_session.user, qnode, ['delete'])
            act.ensure_subscription(
                user_session.user, qnode, qnode.program, self.reason)

            qnode.deleted = True

            calculator = Calculator.structural()
            if parent:
                parent.children.reorder()
                calculator.mark_qnode_dirty(parent)
            else:
                survey.qnodes.reorder()
                calculator.mark_survey_dirty(survey)
            calculator.execute()

        self.finish()
Exemplo n.º 4
0
    def put(self, program_id):
        '''
        Update an existing program.
        '''
        if program_id == '':
            raise errors.MethodError("Can't use PUT for new program (no ID).")

        editable = self.get_argument('editable', '')
        if editable != '':
            self._update_state(program_id, truthy(editable))
            return

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

            program = session.query(model.Program).get(program_id)
            if not program:
                raise errors.MissingDocError("No such program")

            try:
                groups_changed = assign_surveygroups(user_session, program,
                                                     self.request_son)
            except ValueError as e:
                raise errors.ModelError(str(e))

            policy = user_session.policy.derive({
                'program':
                program,
                'surveygroups':
                program.surveygroups,
            })
            policy.verify('surveygroup_interact')
            policy.verify('program_edit')

            if not program.is_editable:
                raise errors.MethodError("This program is closed for editing")

            calculator = Calculator.structural()
            if self.request_son['has_quality'] != program.has_quality:
                # Recalculate stats for surveys. This will trigger the
                # recalculation of the submissions in the recalculation
                # daemon.
                for survey in program.surveys:
                    calculator.mark_survey_dirty(survey)

            self._update(program, self.request_son)

            calculator.execute()

            verbs = []
            if session.is_modified(program) or groups_changed:
                verbs.append('update')

            if program.deleted:
                program.deleted = False
                verbs.append('undelete')

            act = Activities(session)
            act.record(user_session.user, program, verbs)
            act.ensure_subscription(user_session.user, program, program,
                                    self.reason)
        self.get(program_id)
Exemplo n.º 5
0
    def put(self, qnode_id):
        '''Update existing.'''

        if not qnode_id:
            self.ordering()
            return

        program_id = self.get_argument('programId', '')
        parent_id = self.get_argument('parentId', '')

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

            qnode = (
                session.query(model.QuestionNode)
                .options(joinedload('program'))
                .options(joinedload('program.surveygroups'))
                .get((qnode_id, program_id)))
            if not qnode:
                raise errors.MissingDocError("No such question node")

            policy = user_session.policy.derive({
                'program': qnode.program,
                'survey': qnode.survey,
                'surveygroups': qnode.program.surveygroups,
            })
            policy.verify('surveygroup_interact')
            policy.verify('qnode_edit')

            self._update(session, qnode, self.request_son)

            verbs = []
            if session.is_modified(qnode):
                verbs.append('update')

            calculator = Calculator.structural()
            if parent_id and str(qnode.parent_id) != parent_id:
                # Change parent
                old_parent = qnode.parent
                new_parent = (
                    session.query(model.QuestionNode)
                    .get((parent_id, program_id)))
                if new_parent.survey != qnode.survey:
                    raise errors.ModelError("Can't move to different survey")
                if not new_parent:
                    raise errors.ModelError("No such question node")
                old_parent.children.remove(qnode)
                old_parent.children.reorder()
                new_parent.children.append(qnode)
                new_parent.children.reorder()
                calculator.mark_qnode_dirty(old_parent)
                calculator.mark_qnode_dirty(qnode)
                self.reason("Moved from %s to %s" % (
                    old_parent.title, new_parent.title))
                verbs.append('relation')

            if qnode.deleted:
                # Get a reference to the collection before changing the
                # deleted flag - otherwise, if a query is needed to
                # instantiate the collection, it will seem as if the object
                # is already in the collection and insert will not work as
                # expected.
                if qnode.parent:
                    collection = qnode.parent.children
                else:
                    collection = qnode.survey.qnodes
                qnode.deleted = False
                collection.insert(qnode.seq, qnode)
                collection.reorder()
                calculator.mark_qnode_dirty(qnode)
                verbs.append('undelete')

            calculator.execute()

            act = Activities(session)
            act.record(user_session.user, qnode, verbs)
            act.ensure_subscription(
                user_session.user, qnode, qnode.program, self.reason)

        self.get(qnode_id)
Exemplo n.º 6
0
    def post(self, qnode_id):
        '''Create new.'''

        if qnode_id:
            raise errors.MethodError("Can't use POST for existing object")

        program_id = self.get_argument('programId', '')
        survey_id = self.get_argument('surveyId', '')
        parent_id = self.get_argument('parentId', '')

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

            program = (
                session.query(model.Program)
                .options(joinedload('surveygroups'))
                .get(program_id))
            if not program:
                raise errors.ModelError("No such program")

            qnode = model.QuestionNode(program=program)
            self._update(session, qnode, self.request_son)
            log.debug("new: %s", qnode)

            if survey_id:
                survey = (
                    session.query(model.Survey)
                    .get((survey_id, program_id)))
                if not survey:
                    raise errors.ModelError("No such survey")
            else:
                survey = None
            log.debug("survey: %s", survey)

            if parent_id:
                parent = (
                    session.query(model.QuestionNode)
                    .get((parent_id, program_id)))
                if not parent:
                    raise errors.ModelError("Parent does not exist")
                if not survey:
                    survey = parent.survey
                elif parent.survey != survey:
                    raise errors.ModelError(
                        "Parent does not belong to that survey")
            else:
                parent = None

            qnode.survey = survey

            if parent:
                log.debug("Appending to parent")
                parent.children.append(qnode)
                parent.children.reorder()
                log.debug("committing: %s", parent.children)
            elif survey:
                log.debug("Appending to survey")
                survey.qnodes.append(qnode)
                survey.qnodes.reorder()
                log.debug("committing: %s", survey.qnodes)
            else:
                raise errors.ModelError("Parent or survey ID required")

            # Need to flush so object has an ID to record action against.
            session.flush()

            policy = user_session.policy.derive({
                'program': qnode.program,
                'survey': qnode.survey,
                'surveygroups': qnode.program.surveygroups,
            })
            policy.verify('surveygroup_interact')
            policy.verify('qnode_add')

            calculator = Calculator.structural()
            calculator.mark_qnode_dirty(qnode)
            calculator.execute()

            qnode_id = str(qnode.id)

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

        self.get(qnode_id)
Exemplo n.º 7
0
    def process_structure_file(self, all_rows, session, program):
        response_types = self.create_response_types(session, program)

        survey = model.Survey()
        survey.program = program
        survey.title = "Imported Survey"
        survey.description = None
        with open(
                os.path.join(os.path.dirname(os.path.abspath(__file__)),
                             'aquamark_hierarchy.json')) as data_file:
            survey.structure = json.load(data_file)
        session.add(survey)
        session.flush()

        log.info("survey: %s" % survey.id)

        function_title_row = [{
            "title": row[col2num("J")],
            "order": row[col2num("C")],
            "row_num": all_rows.index(row)
        } for row in all_rows if str(row[col2num("S")]) == "Function Header"]

        process_title_row = [{
            "title": row[col2num("J")],
            "order": row[col2num("D")],
            "row_num": all_rows.index(row)
        } for row in all_rows if str(row[col2num("S")]) == "Process Header"]

        subprocess_title_row = [{
            "title": row[col2num("J")],
            "order": row[col2num("E")],
            "row_num": all_rows.index(row)
        } for row in all_rows if str(row[col2num("S")]) == "SubProcess Header"]

        for function in function_title_row:
            function_order = int(function['order'])
            function_title = function['title'].replace(
                "{} - ".format(function_order), "")
            function_description = self.parse_description(
                all_rows, function['row_num'])

            qnode_function = model.QuestionNode()
            qnode_function.program = program
            qnode_function.survey = survey
            qnode_function.seq = function_order - 1
            qnode_function.title = function_title
            qnode_function.description = bleach.clean(function_description,
                                                      strip=True)

            session.add(qnode_function)
            session.flush()

            process_row = [
                row for row in process_title_row
                if "{}.".format(function_order) in row['title']
            ]

            for process in process_row:
                process_order = int(process['order'])
                process_title = process['title'].replace(
                    "{}.{} - ".format(function_order, process_order), "")

                # print("process order:", process_order)
                # print("process title:", process_title)
                process_description = self.parse_description(
                    all_rows, process['row_num'], "")

                qnode_process = model.QuestionNode()
                qnode_process.program = program
                qnode_process.survey = survey
                qnode_process.parent = qnode_function
                qnode_process.seq = process_order - 1
                qnode_process.title = process_title
                qnode_process.description = bleach.clean(process_description,
                                                         strip=True)
                # log.info("qnode_process: %s" % qnode_process)
                session.add(qnode_process)
                session.flush()

                subprocess_row = [
                    row for row in subprocess_title_row if "{}.{}.".format(
                        function_order, process_order) in row['title']
                ]
                for subprocess in subprocess_row:
                    subprocess_order = int(subprocess['order'])
                    subprocess_title = subprocess['title'].replace(
                        "{}.{}.{} - ".format(function_order, process_order,
                                             subprocess_order), "")

                    # print("subprocess order:", subprocess_order)
                    # print("subprocess title:", subprocess_title)
                    subprocess_description = self.parse_description(
                        all_rows, subprocess['row_num'], "")

                    qnode_subprocess = model.QuestionNode()
                    qnode_subprocess.program = program
                    qnode_subprocess.survey = survey
                    qnode_subprocess.parent = qnode_process
                    qnode_subprocess.seq = subprocess_order - 1
                    qnode_subprocess.title = subprocess_title
                    qnode_subprocess.description = bleach.clean(
                        subprocess_description, strip=True)

                    session.add(qnode_subprocess)
                    session.flush()

                    measure_title_row = [
                        {
                            "title": row[col2num("k")],
                            "row_num": all_rows.index(row),
                            "order": row[col2num("F")],
                            "weight": row[col2num("L")],
                            "resp_num": row[col2num("F")]
                        } for row in all_rows
                        if function_order == row[col2num("C")]
                        and process_order == row[col2num("D")]
                        and subprocess_order == row[col2num("E")]
                        and row[col2num("F")] != 0 and row[col2num("G")] == 1
                    ]

                    for measure in measure_title_row:
                        measure_order = int(measure["order"])
                        measure_title = measure['title'].replace(
                            "{}.{}.{}.{} - ".format(function_order,
                                                    process_order,
                                                    subprocess_order,
                                                    measure_order), "")

                        measure_description = self.parse_description(
                            all_rows, measure['row_num'], "Description")
                        # Comments are part of the response, so ignore that
                        # row
                        measure_weight = measure['weight']

                        m = model.Measure()
                        m.program = program
                        m.title = measure_title
                        m.weight = measure_weight
                        m.description = bleach.clean(measure_description,
                                                     strip=True)
                        rt_id = "standard"
                        if function_order == 7:
                            rt_id = "business-support-%s" % int(
                                measure['resp_num'])
                        # log.info("response_type: %s", rt_id)
                        m.response_type = response_types[rt_id]
                        session.add(m)
                        session.flush()
                        qnode_measure = model.QnodeMeasure(
                            program=program,
                            survey=survey,
                            qnode=qnode_subprocess,
                            measure=m)
                        qnode_subprocess.qnode_measures.reorder()
                        session.add(qnode_measure)
                        session.flush()

        calculator = Calculator.structural()
        calculator.mark_entire_survey_dirty(survey)
        calculator.execute()