Beispiel #1
0
 def add_step(self, questionnaireName):
     if not self.has_step(questionnaireName):
         class_name = ExportService.camel_case_it(questionnaireName)
         cls = ExportService.get_class(class_name)
         q = cls()
         step = Step(questionnaireName, q.__question_type__, q.__label__)
         self.steps.append(step)
 def get(self, name, participant_id):
     class_ref = ExportService.get_class(name)
     schema = ExportService.get_schema(name, many=True)
     questionnaires = db.session.query(class_ref)\
         .filter(class_ref.participant_id == participant_id)\
         .all()
     return schema.dump(questionnaires)
    def put(self, name, id):
        """
        Modifies an existing questionnaire record.

        Parameters:
            name (str):
                Snake-cased name of the questionnaire class (should also match the table name),
                found in app.model.questionnaires.
                E.g., clinical_diagnoses_questionnaire -> ClinicalDiagnosesQuestionnaire

            id (int): ID of the questionnaire record to retrieve

        Returns: The updated questionnaire record.
        """
        name = ExportService.camel_case_it(name)
        class_ref = ExportService.get_class(name)
        instance = db.session.query(class_ref).filter(
            class_ref.id == id).first()
        schema = ExportService.get_schema(name, session=db.session)
        request_data = request.get_json()
        if "_links" in request_data:
            request_data.pop("_links")

        try:
            updated = schema.load(request_data, instance=instance)
        except Exception as errors:
            raise RestException(RestException.INVALID_OBJECT, details=errors)

        updated.last_updated = datetime.datetime.utcnow()
        db.session.add(updated)
        db.session.commit()
        return schema.dump(updated)
    def get(self, name):
        """
        Retrieves metadata about the given questionnaire name. Includes JSON Formly field definition.
        Used for data export to get meta without specifying flow and relationship.

        Returns:
            A dict object containing the metadata about the questionnaire. Example:
            {
                table: {
                    question_type: "sensitive",
                    label: "Clinical Diagnosis"
                },
                fields: [
                    {
                    name: "id",
                    key: "id",
                    display_order: 0
                    },
                    ...
                ]
            }
        """
        name = ExportService.camel_case_it(name)
        class_ref = ExportService.get_class(name)
        questionnaire = class_ref()
        meta = {"table": {}}
        try:
            meta["table"]['question_type'] = questionnaire.__question_type__
            meta["table"]["label"] = questionnaire.__label__
        except:
            pass  # If these fields don't exist, just keep going.
        meta["fields"] = []

        # This will move fields referenced by the field groups into the group, but will otherwise add them
        # the base meta object if they are not contained within a group.
        for c in questionnaire.__table__.columns:
            if c.info:
                c.info['name'] = c.name
                c.info['key'] = c.name
                meta['fields'].append(c.info)
            elif c.type.python_type == datetime.datetime:
                meta['fields'].append({
                    'name': c.name,
                    'key': c.name,
                    'display_order': 0,
                    'type': 'DATETIME'
                })
            else:
                meta['fields'].append({
                    'name': c.name,
                    'key': c.name,
                    'display_order': 0
                })

        # Sort the fields
        meta['fields'] = sorted(meta['fields'],
                                key=lambda field: field['display_order'])

        return meta
Beispiel #5
0
 def get(self, flow, questionnaire_name):
     questionnaire_name = ExportService.camel_case_it(questionnaire_name)
     flow = Flows.get_flow_by_name(flow)
     if flow is None:
         raise RestException(RestException.NOT_FOUND)
     class_ref = ExportService.get_class(questionnaire_name)
     questionnaire = class_ref()
     return ExportService.get_meta(questionnaire, flow.relationship)
    def load_data(self, export_info, log):
        if len(export_info.json_data) < 1:
            return  # Nothing to do here.
        schema = ExportService.get_schema(export_info.class_name,
                                          many=False,
                                          is_import=True)
        model_class = ExportService.get_class(export_info.class_name)
        log_detail = DataTransferLogDetail(class_name=export_info.class_name,
                                           date_started=log.date_started,
                                           successful=True,
                                           success_count=0,
                                           failure_count=0)
        log.details.append(log_detail)
        for item in export_info.json_data:
            item_copy = dict(item)
            if "_links" in item_copy:
                links = item_copy.pop("_links")
            existing_model = self.db.session.query(model_class).filter_by(
                id=item['id']).first()
            try:
                if existing_model:
                    model = schema.load(data=item_copy,
                                        session=self.db.session,
                                        instance=existing_model)
                else:
                    model = schema.load(data=item_copy,
                                        session=self.db.session)

                try:
                    self.db.session.add(model)
                    self.db.session.commit()
                    log_detail.handle_success()
                    self.db.session.add(log_detail)
                    if hasattr(
                            model, '__question_type__'
                    ) and model.__question_type__ == ExportService.TYPE_SENSITIVE:
                        print("Sensitive Data.  Calling Delete.")
                        self.delete_record(item)
                except Exception as e:
                    self.db.session.rollback()
                    self.logger.error("Error processing " +
                                      export_info.class_name + " with id of " +
                                      str(item["id"]) + ".  Error: " + str(e))
                    log_detail.handle_failure(e)
                    self.db.session.add(log)
                    self.db.session.add(log_detail)
                    raise e

            except Exception as e:
                e = Exception("Failed to parse model " +
                              export_info.class_name + ". " + str(e))
                log_detail.handle_failure(e)
                self.db.session.add(log)
                self.db.session.add(log_detail)
                raise e

        self.db.session.commit()
 def get(self, name, id):
     name = ExportService.camel_case_it(name)
     class_ref = ExportService.get_class(name)
     instance = db.session.query(class_ref).filter(
         class_ref.id == id).first()
     if instance is None:
         raise RestException(RestException.NOT_FOUND)
     schema = ExportService.get_schema(name)
     return schema.dump(instance)
 def delete(self, name, id):
     try:
         name = ExportService.camel_case_it(name)
         class_ref = ExportService.get_class(name)
         instance = db.session.query(class_ref).filter(
             class_ref.id == id).first()
         db.session.delete(instance)
         #            db.session.query(class_ref).filter(class_ref.id == id).delete()
         db.session.commit()
     except IntegrityError as error:
         raise RestException(RestException.CAN_NOT_DELETE)
     return
    def put(self, name, id):
        name = ExportService.camel_case_it(name)
        class_ref = ExportService.get_class(name)
        instance = db.session.query(class_ref).filter(
            class_ref.id == id).first()
        schema = ExportService.get_schema(name, session=db.session)
        request_data = request.get_json()
        if "_links" in request_data:
            request_data.pop("_links")
        updated, errors = schema.load(request_data, instance=instance)

        if errors:
            raise RestException(RestException.INVALID_OBJECT, details=errors)
        updated.last_updated = datetime.datetime.utcnow()
        db.session.add(updated)
        db.session.commit()
        return schema.dump(updated)
    def get(self, name, id):
        """
        Returns a single questionnaire record.

        Parameters:
            name (str):
                Snake-cased name of the questionnaire class (should also match the table name),
                found in app.model.questionnaires.
                E.g., clinical_diagnoses_questionnaire -> ClinicalDiagnosesQuestionnaire

            id (int): ID of the questionnaire record to retrieve

        Returns: A single questionnaire record.
        """
        name = ExportService.camel_case_it(name)
        class_ref = ExportService.get_class(name)
        instance = db.session.query(class_ref).filter(
            class_ref.id == id).first()
        if instance is None:
            raise RestException(RestException.NOT_FOUND)
        schema = ExportService.get_schema(name)
        return schema.dump(instance)
    def get(self, name):
        name = ExportService.camel_case_it(name)
        class_ref = ExportService.get_class(name)
        questionnaire = class_ref()
        meta = {"table": {}}
        try:
            meta["table"]['question_type'] = questionnaire.__question_type__
            meta["table"]["label"] = questionnaire.__label__
        except:
            pass  # If these fields don't exist, just keep going.
        meta["fields"] = []

        # This will move fields referenced by the field groups into the group, but will otherwise add them
        # the base meta object if they are not contained within a group.
        for c in questionnaire.__table__.columns:
            if c.info:
                c.info['name'] = c.name
                c.info['key'] = c.name
                meta['fields'].append(c.info)
            elif c.type.python_type == datetime.datetime:
                meta['fields'].append({
                    'name': c.name,
                    'key': c.name,
                    'display_order': 0,
                    'type': 'DATETIME'
                })
            else:
                meta['fields'].append({
                    'name': c.name,
                    'key': c.name,
                    'display_order': 0
                })

        # Sort the fields
        meta['fields'] = sorted(meta['fields'],
                                key=lambda field: field['display_order'])

        return meta
    def delete(self, name, id):
        """
        Deletes a single questionnaire record.

        Parameters:
            name (str):
                Snake-cased name of the questionnaire class (should also match the table name),
                found in app.model.questionnaires.
                E.g., clinical_diagnoses_questionnaire -> ClinicalDiagnosesQuestionnaire

            id (int): ID of the questionnaire record to delete
        """
        try:
            name = ExportService.camel_case_it(name)
            class_ref = ExportService.get_class(name)
            instance = db.session.query(class_ref).filter(
                class_ref.id == id).first()
            db.session.delete(instance)
            #            db.session.query(class_ref).filter(class_ref.id == id).delete()
            db.session.commit()
        except IntegrityError as error:
            raise RestException(RestException.CAN_NOT_DELETE)
        return
    def export_xls(name, app, user_id=None):
        # Flask response
        response = Response()
        response.status_code = 200

        # Create an in-memory output file for the new workbook.
        output = io.BytesIO()

        if name.lower() == 'all':
            # Get Questionnaire Names
            questionnaire_names = ExportXlsService.get_questionnaire_names(app)
        else:
            cl = ExportService.get_class(name)
            info = ExportService.get_single_table_info(cl, None)
            questionnaire_names = [name]
            for sub_table in info.sub_tables:
                questionnaire_names.append(sub_table.class_name)

        # Create workbook
        workbook = xlsxwriter.Workbook(output, {'in_memory': True})

        # Add a bold format to use to highlight cells.
        bold = workbook.add_format({'bold': True})

        for qname in questionnaire_names:
            worksheet = workbook.add_worksheet(
                ExportXlsService.pretty_title_from_snakecase(qname))
            # Some data we want to write to the worksheet.
            # Get header fields from the schema in case the first record is missing fields
            schema = ExportService.get_schema(qname, many=True)
            header_fields = schema.fields
            if user_id:
                questionnaires = schema.dump(ExportService().get_data(
                    name=qname, user_id=user_id),
                                             many=True)
            else:
                questionnaires = schema.dump(
                    ExportService().get_data(name=qname), many=True)

            # Start from the first cell. Rows and columns are zero indexed.
            row = 0
            col = 0

            # Write the column headers.
            for (key, value) in header_fields.items():
                if key != "_links":
                    worksheet.write(row, col, key, bold)
                    col += 1
            row += 1

            # Iterate over the data and write it out row by row.
            for questionnaire in questionnaires:
                # Start from the first cell. Rows and columns are zero indexed.
                col = 0
                for (key, value) in questionnaire.items():
                    if key == "_links":
                        continue  # Don't export _links
                    if isinstance(value, dict):
                        continue
                    if isinstance(value,
                                  list) and len(value) > 0 and isinstance(
                                      value[0], dict):
                        continue  # Don't try to represent sub-table data.
                    if isinstance(value, list):
                        list_string = ''
                        for list_value in value:
                            list_string = list_string + str(list_value) + ', '
                        worksheet.write(row, col, list_string)
                    else:
                        worksheet.write(row, col, value)
                    col += 1
                row += 1

        # Close the workbook before streaming the data.
        workbook.close()

        # Rewind the buffer.
        output.seek(0)

        # Add output to response
        response.data = output.read()

        # Set filename
        file_name = 'export_{}_{}.xlsx'.format(name, datetime.utcnow())

        # HTTP headers for forcing file download
        response_headers = Headers({
            'Pragma':
            "public",  # required,
            'Expires':
            '0',
            'Cache-Control':
            'must-revalidate, private',  # required for certain browsers
            'Content-Type':
            'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
            'Content-Disposition':
            'attachment; filename=\"%s\";' % file_name,
            'Content-Transfer-Encoding':
            'binary',
            'Access-Control-Expose-Headers':
            'x-filename',
            'x-filename':
            file_name,
            'Content-Length':
            len(response.data)
        })

        # Add headers
        response.headers = response_headers

        # jquery.fileDownload.js requirements
        response.set_cookie('fileDownload', 'true', path='/')

        # Return the response
        return response
 def get(self, name):
     name = ExportService.camel_case_it(name)
     class_ref = ExportService.get_class(name)
     schema = ExportService.get_schema(name, many=True)
     questionnaires = db.session.query(class_ref).all()
     return schema.dump(questionnaires)