Exemplo n.º 1
0
class Academic(AuditMixin, CommonMixin, db.Model):

    id = db.Column(db.Integer(), primary_key=True)
    google_scholar_id = db.Column(db.String(255))
    name = db.Column(db.String(500))
    affiliation = db.Column(db.String(500))
    cited_by = db.Column(db.Integer)
    h_index = db.Column(db.Integer)
    i10_index = db.Column(db.Integer)
    is_updating = db.Column(db.Boolean)

    @property
    def pubmed_name(self):
        firstname, *_, lastname = self.name.split()
        return f'{lastname} {firstname[0]}'
Exemplo n.º 2
0
class ParticipantIdentifierSource(db.Model):
    __tablename__ = 'participant_identifier_source'

    id = db.Column(db.Integer, primary_key=True)
    linked_minimum_patient_identifier_source_id = db.Column(
        db.Integer,
        db.ForeignKey("participant_identifier_source.id"),
        nullable=True)
    type = db.Column(db.String(100), nullable=False)
    study_id = db.Column(db.Integer, db.ForeignKey(Study.id), nullable=True)
    study = db.relationship(
        Study, backref=db.backref("participant_identifier_sources"))

    __mapper_args__ = {
        'polymorphic_identity': 'participant_identifier_source',
        'polymorphic_on': type,
    }

    last_updated_datetime = db.Column(db.DateTime,
                                      nullable=False,
                                      default=datetime.utcnow)
    last_updated_by_user_id = db.Column(db.Integer, db.ForeignKey(User.id))
    last_updated_by_user = db.relationship(User)

    identifiers = db.relationship(
        "ParticipantIdentifier",
        secondary=participant_identifiers__participant_identifier_sources,
        back_populates="sources",
        collection_class=set)

    def __str__(self):
        return f"{self.type.name}: {self.identifier}"
Exemplo n.º 3
0
class DemographicsRequestColumn(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    demographics_request_id = db.Column(db.Integer,
                                        db.ForeignKey(DemographicsRequest.id))
    demographics_request = db.relationship(
        DemographicsRequest,
        foreign_keys=[demographics_request_id],
        backref=db.backref("columns"))
    name = db.Column(db.String(500))
    last_updated_datetime = db.Column(db.DateTime,
                                      nullable=False,
                                      default=datetime.utcnow)
    last_updated_by_user_id = db.Column(db.Integer, db.ForeignKey(User.id))
    last_updated_by_user = db.relationship(
        User, foreign_keys=[last_updated_by_user_id])

    def __lt__(self, other):
        return self.name < other.name

    def __repr__(self):
        fields = '; '.join([
            f'{key}="{value}"' for key, value in self.__dict__.items()
            if key[0] != '_'
        ])
        return f'[{type(self).__name__}({fields})]'
Exemplo n.º 4
0
class Organisation(db.Model, CommonMixin):

    CARDIOVASCULAR = 'BRC Cardiovascular Theme'
    LIFESTYLE = 'BRC Lifestyle Theme'
    PRECICION = 'BRC Precision Medicine Theme'
    RESPIRATORY = 'BRC Respiratory Theme'
    LDC = 'Leicester Diabetes Centre'
    PRC = 'Patient Recruitment Centre'
    RandI = 'R&I'
    OTHER = 'Other - please specify'

    all_organisations = [
        CARDIOVASCULAR, LIFESTYLE, PRECICION, RESPIRATORY, LDC, PRC, RandI,
        OTHER
    ]

    id = db.Column(db.Integer(), primary_key=True)
    name = db.Column(db.String(255))

    @classmethod
    def get_organisation(cls, name):
        return Organisation.query.filter_by(name=name).one()

    @classmethod
    def get_other(cls):

        return cls.get_organisation(Organisation.OTHER)
Exemplo n.º 5
0
class Blinding(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    unblind_id = db.Column(db.String(100), nullable=False)
    blinding_type_id = db.Column(db.Integer,
                                 db.ForeignKey(BlindingType.id),
                                 nullable=False)
    blinding_type = db.relationship(BlindingType,
                                    backref=db.backref("blindings"))
    pseudo_random_id_id = db.Column(db.Integer,
                                    db.ForeignKey(PseudoRandomId.id),
                                    nullable=False)
    pseudo_random_id = db.relationship(PseudoRandomId)
    last_updated_datetime = db.Column(db.DateTime,
                                      nullable=False,
                                      default=datetime.utcnow)
    last_updated_by_user_id = db.Column(db.Integer, db.ForeignKey(User.id))
    last_updated_by_user = db.relationship(User)

    def __repr__(self):
        return '; '.join([
            self.blinding_type.name,
            self.unblind_id,
            self.pseudo_random_id.full_code,
        ])

    def __lt__(self, other):
        return self.name < other.name
Exemplo n.º 6
0
class BlindingSet(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(100), nullable=False)
    study_id = db.Column(db.Integer, db.ForeignKey(Study.id), nullable=False)
    study = db.relationship(Study, backref=db.backref("blinding_sets"))

    def __repr__(self):
        return self.name

    def __lt__(self, other):
        return self.name < other.name

    def get_blind_ids(self, unblind_id, user):
        result = []

        for bt in self.blinding_types:
            blind_id = bt.get_blind_id(unblind_id, user)
            if blind_id:
                result.append(blind_id)

        return result

    def get_unblind_id(self, blind_id):
        for bt in self.blinding_types:
            unblind_id = bt.get_unblind_id(blind_id)
            if unblind_id:
                return unblind_id
Exemplo n.º 7
0
class BioresourceId(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    bioresource_id_provider_id = db.Column(
        db.Integer, db.ForeignKey(BioresourceIdProvider.id))
    bioresource_id_provider = db.relationship(BioresourceIdProvider)
    number = db.Column(db.Integer, nullable=False)
    check_character = db.Column(db.String(1), nullable=False)
    legacy_number = db.Column(db.Integer)
    last_updated_datetime = db.Column(db.DateTime,
                                      nullable=False,
                                      default=datetime.utcnow)
    last_updated_by_user_id = db.Column(db.Integer, db.ForeignKey(User.id))
    last_updated_by_user = db.relationship(User)

    def __repr__(self):
        return str(self.__class__) + ": " + str(self.__dict__)

    def __str__(self):
        return self.full_code

    @property
    def full_code(self):
        return self.bioresource_id_provider.prefix + str(
            self.number) + self.check_character

    @property
    def barcode(self):
        return self.full_code
Exemplo n.º 8
0
class Study(db.Model):

    id = db.Column(db.Integer(), primary_key=True)
    name = db.Column(db.String(100))
    date_created = db.Column(db.DateTime,
                             nullable=False,
                             default=datetime.utcnow)
    allow_duplicate_study_number = db.Column(db.Boolean,
                                             nullable=False,
                                             default=False)
    allow_empty_study_number = db.Column(db.Boolean,
                                         nullable=False,
                                         default=False)
    study_number_format = db.Column(db.String(50))
    study_number_name = db.Column(db.String(100))
    field_group_id = db.Column(db.Integer(), db.ForeignKey(FieldGroup.id))
    field_group = db.relationship(FieldGroup, backref=db.backref("study"))

    owners = db.relationship(
        User,
        secondary=studies_owners,
        backref=db.backref("owned_studies", lazy="dynamic"),
    )
    collaborators = db.relationship(
        User,
        secondary=studies_collaborators,
        backref=db.backref("collaborator_studies", lazy="dynamic"),
    )

    def __str__(self):
        return self.name

    @property
    def upload_count(self):
        return len([u for u in self.uploads if not u.deleted])

    def upload_count_for_user(self, user):
        return len(
            [u for u in self.uploads if not u.deleted and u.uploader == user])

    @property
    def outstanding_upload_count(self):
        return len(
            [u for u in self.uploads if not u.deleted and not u.completed])

    def get_study_number_name(self):
        return self.study_number_name or 'Study Number'
Exemplo n.º 9
0
class TaskAssignedUser(AuditMixin, CommonMixin, db.Model):

    id = db.Column(db.Integer(), primary_key=True)
    task_id = db.Column(db.Integer, db.ForeignKey(Task.id), nullable=False)
    task = db.relationship(Task, backref="assigned_user_history")
    user_id = db.Column(db.Integer, db.ForeignKey(User.id), nullable=False)
    user = db.relationship(User)
    notes = db.Column(db.String(255))
Exemplo n.º 10
0
class PseudoRandomId(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    pseudo_random_id_provider_id = db.Column(
        db.Integer, db.ForeignKey(PseudoRandomIdProvider.id))
    pseudo_random_id_provider = db.relationship(PseudoRandomIdProvider)
    ordinal = db.Column(db.Integer, nullable=False)
    unique_code = db.Column(db.Integer, nullable=False)
    check_character = db.Column(db.String(1), nullable=False)
    full_code = db.Column(db.String(20), nullable=False)
    last_updated_datetime = db.Column(db.DateTime,
                                      nullable=False,
                                      default=datetime.utcnow)
    last_updated_by_user_id = db.Column(db.Integer, db.ForeignKey(User.id))
    last_updated_by_user = db.relationship(User)

    @property
    def barcode(self):
        return self.full_code
Exemplo n.º 11
0
class AbstractSection(AuditMixin, CommonMixin, db.Model):

    id = db.Column(db.Integer(), primary_key=True)
    publication_id = db.Column(db.Integer(), db.ForeignKey(Publication.id))
    publication = db.relationship(Publication,
                                  lazy="joined",
                                  backref='abstracts')
    label = db.Column(db.String(200))
    text = db.Column(db.UnicodeText())
Exemplo n.º 12
0
class LabelPack(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    type = db.Column(db.String(100), nullable=False)
    study_id = db.Column(db.Integer, db.ForeignKey(Study.id))
    study = db.relationship(Study, backref=db.backref("label_packs"))

    __mapper_args__ = {
        "polymorphic_identity": "Pack",
        "polymorphic_on": type,
    }

    def user_defined_participant_id(self):
        return False

    def allow_batch_printing(self):
        return True

    @property
    def name(self):
        return re.sub('([a-z])([A-Z])', r'\1 \2', self.__class__.__name__)

    def print(self, count):
        for _ in range(count):
            current_app.logger.info(
                f'Printing label for study {self.study.name}')

            self._do_print()

            db.session.commit()

            time.sleep(current_app.config['PRINTING_SET_SLEEP'])

    def save_participant_id(self, participant_id):
        pit = ParticipantIdentifierType.get_study_participant_id()

        pi = ParticipantIdentifier.query.filter_by(
            participant_identifier_type_id=pit.id,
            identifier=participant_id,
        ).one_or_none()

        if pi is None:
            db.session.add(
                ParticipantIdentifier(
                    participant_identifier_type_id=pit.id,
                    identifier=participant_id,
                    last_updated_by_user_id=current_user.id,
                ))

    def _do_print(self, participant_id=None):
        pass

    def __repr__(self):
        return self.name

    def __lt__(self, other):
        return self.name < other.name
Exemplo n.º 13
0
class LegacyIdProvider(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(100), nullable=False)
    prefix = db.Column(db.String(10), nullable=False)
    number_fixed_length = db.Column(db.Integer, nullable=False)
    last_updated_datetime = db.Column(db.DateTime,
                                      nullable=False,
                                      default=datetime.utcnow)
    last_updated_by_user_id = db.Column(db.Integer, db.ForeignKey(User.id))
    last_updated_by_user = db.relationship(User)

    def allocate_id(self, user):
        found = 1
        tries = 0
        prospective_id = 0

        while found > 0:
            prospective_id = random.randint(1, 900000)
            tries = tries + 1

            found = LegacyId.query.filter(
                LegacyId.legacy_id_provider_id == self.id).filter(
                    LegacyId.number == prospective_id).count()

        actual_id = LegacyId(
            legacy_id_provider=self,
            number=prospective_id,
            last_updated_by_user=user,
        )

        db.session.add(actual_id)

        return actual_id

    def allocate_ids(self, count, user):
        result = []
        for _ in range(count):
            result.append(self.allocate_id(user))

        return result

    def __repr__(self):
        return str(self.__class__) + ": " + str(self.__dict__)
Exemplo n.º 14
0
class TaskStatus(AuditMixin, CommonMixin, db.Model):

    id = db.Column(db.Integer(), primary_key=True)
    task_id = db.Column(db.Integer, db.ForeignKey(Task.id), nullable=False)
    task = db.relationship(Task, backref="status_history")
    notes = db.Column(db.String(255))
    task_status_type_id = db.Column(db.Integer,
                                    db.ForeignKey(TaskStatusType.id),
                                    nullable=False)
    task_status_type = db.relationship(TaskStatusType,
                                       backref="assigned_tasks")
Exemplo n.º 15
0
class Site(db.Model):

    LBRC = "Leicester Biomedical Research Centre"

    id = db.Column(db.Integer(), primary_key=True)
    name = db.Column(db.String(255))
    number = db.Column(db.String(20))
    date_created = db.Column(db.DateTime,
                             nullable=False,
                             default=datetime.utcnow)

    def __str__(self):
        return self.name

    @property
    def name_and_number(self):
        number_portion = ""
        if self.number:
            number_portion = " ({})".format(self.number)
        return self.name + number_portion
Exemplo n.º 16
0
class Upload(db.Model):

    id = db.Column(db.Integer(), primary_key=True)
    study_id = db.Column(db.Integer(), db.ForeignKey(Study.id))
    study_number = db.Column(db.String(20))
    uploader_id = db.Column(db.Integer(), db.ForeignKey(User.id))
    date_created = db.Column(db.DateTime,
                             nullable=False,
                             default=datetime.utcnow)
    study = db.relationship(Study, backref=db.backref("uploads"))
    uploader = db.relationship(User)
    completed = db.Column(db.Boolean, default=0)
    deleted = db.Column(db.Boolean, default=0)
Exemplo n.º 17
0
class Publication(AuditMixin, CommonMixin, db.Model):

    id = db.Column(db.Integer(), primary_key=True)
    pm_id = db.Column(db.Integer())
    journal = db.Column(db.String(200))
    published_date = db.Column(db.Date)
    title = db.Column(db.UnicodeText())

    academics = db.relationship("Academic",
                                secondary=academics_publications,
                                collection_class=set,
                                backref=db.backref("publications",
                                                   lazy="joined"))
Exemplo n.º 18
0
class Service(AuditMixin, CommonMixin, db.Model):

    id = db.Column(db.Integer(), primary_key=True)
    name = db.Column(db.String(255))
    generic_recipients = db.Column(db.String(255))
    suppress_owner_email = db.Column(db.Boolean)
    field_group_id = db.Column(db.Integer, db.ForeignKey(FieldGroup.id))
    field_group = db.relationship(FieldGroup)
    introduction = db.Column(db.UnicodeText())

    def __str__(self):
        return self.name

    def get_field_for_field_name(self, field_name):
        if self.field_group:
            return self.field_group.get_field_for_field_name(field_name)

    @property
    def notification_email_addresses(self):
        return list(
            filter(len, [
                r.email for r in self.owners if not self.suppress_owner_email
            ] + re.split(r'[;,\s]+', self.generic_recipients or '')))
Exemplo n.º 19
0
class SequentialIdProvider(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(100), nullable=False)
    prefix = db.Column(db.String(10))
    zero_fill_size = db.Column(db.Integer)
    last_number = db.Column(db.Integer, nullable=False, default=0)
    last_updated_datetime = db.Column(db.DateTime,
                                      nullable=False,
                                      default=datetime.utcnow)
    last_updated_by_user_id = db.Column(db.Integer, db.ForeignKey(User.id))
    last_updated_by_user = db.relationship(User)

    def allocate_ids(self, count, user):
        start = self.last_number + 1

        self.last_number = self.last_number + count
        self.last_updated_by_user = user
        self.last_updated_datetime = datetime.utcnow()

        format_string = self.prefix or ""

        if self.zero_fill_size:
            format_string += "{:0" + str(self.zero_fill_size) + "d}"
        else:
            format_string += "{}"

        return [
            SequentialId(format_string.format(i))
            for i in range(start, self.last_number + 1)
        ]

    def allocate_id(self, user):
        return self.allocate_ids(1, user)[0]

    def __repr__(self):
        return str(self.__class__) + ": " + str(self.__dict__)
Exemplo n.º 20
0
class Study(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    edge_id = db.Column(db.Integer, nullable=True)
    name = db.Column(db.String(50), nullable=False)

    def __str__(self):
        return self.name or ""

    def get_blind_ids(self, unblind_id, user):
        result = []

        for bs in self.blinding_sets:
            for bt in [t for t in bs.blinding_types if not t.deleted]:
                blind_id = bt.get_blind_id(unblind_id, user)
                if blind_id:
                    result.append(blind_id)

        return result
Exemplo n.º 21
0
class BlindingType(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(100), nullable=False)
    blinding_set_id = db.Column(db.Integer,
                                db.ForeignKey(BlindingSet.id),
                                nullable=False)
    blinding_set = db.relationship(BlindingSet,
                                   backref=db.backref("blinding_types"))
    pseudo_random_id_provider_id = db.Column(db.Integer,
                                             db.ForeignKey(
                                                 PseudoRandomIdProvider.id),
                                             nullable=False)
    pseudo_random_id_provider = db.relationship(PseudoRandomIdProvider)
    deleted = db.Column(db.Boolean, nullable=False, default=False)
    duplicate_number = db.Column(db.Integer, default=0, nullable=False)

    def __repr__(self):
        return self.name

    def __lt__(self, other):
        return self.name < other.name

    def get_blind_id(self, unblind_id, user):
        blinding = (Blinding.query.filter_by(
            blinding_type_id=self.id).filter_by(unblind_id=unblind_id).first())
        if not blinding:
            pseudo_random_id = self.pseudo_random_id_provider.allocate_id(user)

            blinding = Blinding(
                unblind_id=unblind_id,
                blinding_type=self,
                pseudo_random_id=pseudo_random_id,
                last_updated_by_user=user,
            )

        return blinding

    def get_unblind_id(self, blind_id):
        blinding = (Blinding.query.filter_by(
            blinding_type_id=self.id).join(PseudoRandomId).filter_by(
                full_code=blind_id).first())

        return blinding
Exemplo n.º 22
0
class ParticipantIdentifier(db.Model):
    __tablename__ = 'participant_identifier'

    id = db.Column(db.Integer, primary_key=True)
    identifier = db.Column(db.String(100), nullable=False)
    participant_identifier_type_id = db.Column(
        db.Integer, db.ForeignKey(ParticipantIdentifierType.id))
    participant_identifier_type = db.relationship(ParticipantIdentifierType)

    last_updated_datetime = db.Column(db.DateTime,
                                      nullable=False,
                                      default=datetime.utcnow)
    last_updated_by_user_id = db.Column(db.Integer, db.ForeignKey(User.id))
    last_updated_by_user = db.relationship(User)

    sources = db.relationship(
        "ParticipantIdentifierSource",
        secondary=participant_identifiers__participant_identifier_sources,
        back_populates="identifiers",
        collection_class=set)

    def __str__(self):
        return f"{self.type.name}: {self.identifier}"
Exemplo n.º 23
0
class ParticipantIdentifierType(db.Model):

    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(100), nullable=False)

    last_updated_datetime = db.Column(db.DateTime,
                                      nullable=False,
                                      default=datetime.utcnow)
    last_updated_by_user_id = db.Column(db.Integer, db.ForeignKey(User.id))
    last_updated_by_user = db.relationship(User)

    def __str__(self):
        return self.name

    @staticmethod
    def get_type(type_name):
        return ParticipantIdentifierType.query.filter_by(
            name=type_name, ).one_or_none()

    @staticmethod
    def get_study_participant_id():
        return ParticipantIdentifierType.get_type(
            ParticipantIdentifierTypeName.STUDY_PARTICIPANT_ID)
Exemplo n.º 24
0
class UploadFile(db.Model):

    id = db.Column(db.Integer(), primary_key=True)
    upload_id = db.Column(db.Integer(), db.ForeignKey(Upload.id))
    upload = db.relationship(Upload, backref=db.backref("files"))
    field_id = db.Column(db.Integer(), db.ForeignKey(Field.id))
    field = db.relationship(Field)
    filename = db.Column(db.String(500))

    def get_download_filename(self):
        if len(self.field.download_filename_format or '') == 0:
            return self.filename
        else:
            return self.field.download_filename_format.format(
                file=self) + os.path.splitext(self.filename)[-1]

    def filepath(self):
        return os.path.join(
            secure_filename("{}_{}".format(self.upload.study.id,
                                           self.upload.study.name)),
            secure_filename("{}_{}_{}".format(self.id,
                                              self.upload.study_number,
                                              self.filename)),
        )
Exemplo n.º 25
0
class DemographicsRequest(db.Model):

    id = db.Column(db.Integer, primary_key=True)
    created_datetime = db.Column(db.DateTime,
                                 nullable=False,
                                 default=datetime.utcnow)
    filename = db.Column(db.String(500))
    extension = db.Column(db.String(100), nullable=False)
    owner_user_id = db.Column(db.Integer, db.ForeignKey(User.id))
    owner = db.relationship(User,
                            foreign_keys=[owner_user_id],
                            backref=db.backref("demographic_requests"))
    submitted_datetime = db.Column(db.DateTime)
    deleted_datetime = db.Column(db.DateTime)
    paused_datetime = db.Column(db.DateTime)
    data_extracted_datetime = db.Column(db.DateTime)
    pmi_data_pre_completed_datetime = db.Column(db.DateTime)
    pmi_data_post_completed_datetime = db.Column(db.DateTime)
    lookup_completed_datetime = db.Column(db.DateTime)
    result_created_datetime = db.Column(db.DateTime)
    result_downloaded_datetime = db.Column(db.DateTime)
    error_datetime = db.Column(db.DateTime)
    error_message = db.Column(db.Text)
    last_updated_datetime = db.Column(db.DateTime,
                                      nullable=False,
                                      default=datetime.utcnow)
    last_updated_by_user_id = db.Column(db.Integer, db.ForeignKey(User.id))
    last_updated_by_user = db.relationship(
        User, foreign_keys=[last_updated_by_user_id])
    column_definition = db.relationship("DemographicsRequestColumnDefinition",
                                        uselist=False,
                                        back_populates="demographics_request")
    skip_pmi = db.Column(db.Boolean, default=False)

    __mapper_args__ = {
        "polymorphic_on": extension,
    }

    @property
    def filepath(self):
        return os.path.join(
            current_app.config["FILE_UPLOAD_DIRECTORY"],
            secure_filename(
                "{}_{}".format(self.last_updated_by_user.id,
                               self.last_updated_by_user.full_name)),
            secure_filename("{}_{}".format(self.id, self.filename)),
        )

    @property
    def result_filename(self):
        return secure_filename("{}_result_{}".format(self.id, self.filename))

    @property
    def result_filepath(self):
        return os.path.join(
            current_app.config["FILE_UPLOAD_DIRECTORY"],
            secure_filename(
                "{}_{}".format(self.last_updated_by_user.id,
                               self.last_updated_by_user.full_name)),
            self.result_filename,
        )

    def __lt__(self, other):
        return self.created_datetime < other.created_datetime

    @property
    def data_extracted(self):
        return self.data_extracted_datetime is not None

    @property
    def paused(self):
        return self.paused_datetime is not None

    @property
    def columns_defined(self):
        return self.column_definition and self.column_definition.is_valid

    @property
    def awaiting_submission(self):
        return self.columns_defined and self.submitted_datetime is None

    @property
    def submitted(self):
        return self.submitted_datetime is not None

    @property
    def deleted(self):
        return self.deleted_datetime is not None

    @property
    def result_created(self):
        return self.result_created_datetime is not None

    @property
    def pmi_data_pre_completed(self):
        return self.pmi_data_pre_completed_datetime is not None

    @property
    def pmi_data_post_completed(self):
        return self.pmi_data_post_completed_datetime is not None

    @property
    def result_downloaded(self):
        return self.result_downloaded_datetime is not None

    @property
    def lookup_completed(self):
        return self.lookup_completed_datetime is not None

    @property
    def in_error(self):
        return self.error_datetime is not None

    @property
    def requires_column_definition(self):
        return not self.deleted and not self.submitted and not self.in_error

    @property
    def requires_submission(self):
        return not self.deleted and self.awaiting_submission and not self.in_error

    @property
    def can_be_resubmitted(self):
        return not self.deleted and self.submitted and not self.result_created and not self.in_error

    @property
    def can_be_paused(self):
        return not self.deleted and self.submitted and not self.result_created and not self.paused and not self.in_error

    @property
    def can_be_downloaded(self):
        return not self.deleted and self.result_created and not self.in_error

    @property
    def can_be_deleted(self):
        return not self.deleted

    @property
    def status(self):
        if self.deleted:
            return 'Deleted'
        elif self.in_error:
            return 'Error'
        elif self.paused:
            return 'Paused'
        if not self.columns_defined:
            return 'Uploaded'
        elif not self.submitted:
            return 'Awaiting Submission'
        elif not self.data_extracted:
            return f'Extracting Data'
        elif not self.pmi_data_pre_completed and not self.skip_pmi:
            return f'Fetching PMI details {self.prepmi_count} of {self.data_count} before spine lookup'
        elif not self.lookup_completed:
            return f'Fetching Demographics {self.fetched_count} of {self.data_count}'
        elif not self.pmi_data_post_completed and not self.skip_pmi:
            return f'Fetching PMI details {self.postpmi_count} of {self.data_count} after spine lookup'
        elif not self.result_created:
            return 'Processing Demographics'
        elif not self.result_downloaded:
            return 'Ready to Download'
        else:
            return 'Downloaded'

    @property
    def data_count(self):
        return DemographicsRequestData.query.filter(
            DemographicsRequestData.demographics_request_id ==
            self.id).count()

    @property
    def fetched_count(self):
        return DemographicsRequestData.query.filter(
            DemographicsRequestData.demographics_request_id == self.id).filter(
                DemographicsRequestData.processed_datetime.isnot(
                    None)).count()

    @property
    def prepmi_count(self):
        return DemographicsRequestData.query.filter(
            DemographicsRequestData.demographics_request_id == self.id).filter(
                DemographicsRequestData.pmi_pre_processed_datetime.isnot(
                    None)).count()

    @property
    def postpmi_count(self):
        return DemographicsRequestData.query.filter(
            DemographicsRequestData.demographics_request_id == self.id).filter(
                DemographicsRequestData.pmi_post_processed_datetime.isnot(
                    None)).count()

    def get_most_likely_uhl_system_number_column_id(self):
        return self._get_most_likely_column_id('(uhl|\bs).*(number|no|)')

    def get_most_likely_nhs_number_column_id(self):
        return self._get_most_likely_column_id('nhs.*(number|no|)')

    def get_most_likely_family_name_column_id(self):
        return self._get_most_likely_column_id('(surname|(family|last).*name)')

    def get_most_likely_given_name_column_id(self):
        return self._get_most_likely_column_id('(first|given|fore).*name|name')

    def get_most_likely_gender_column_id(self):
        return self._get_most_likely_column_id('(gender|sex)')

    def get_most_likely_dob_column_id(self):
        return self._get_most_likely_column_id('(dob|date.*birth|birth.*date)')

    def get_most_likely_postcode_column_id(self):
        return self._get_most_likely_column_id('(post.*code)')

    def _get_most_likely_column_id(self, regular_expression):
        repat = re.compile(regular_expression, re.IGNORECASE)
        ids = (c.id for c in self.columns if re.search(repat, c.name))
        return next(ids, 0)

    def set_error(self, message):
        self.error_datetime = datetime.utcnow()
        self.error_message = message
Exemplo n.º 26
0
class PseudoRandomIdProvider(db.Model):
    # See http://preshing.com/20121224/how-to-generate-a-sequence-of-unique-random-integers/

    _PRIME = 999983  # PRIME MOD 4 must equal 3

    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(100), nullable=False)
    prefix = db.Column(db.String(10), nullable=False)
    last_updated_datetime = db.Column(db.DateTime,
                                      nullable=False,
                                      default=datetime.utcnow)
    last_updated_by_user_id = db.Column(db.Integer, db.ForeignKey(User.id))
    last_updated_by_user = db.relationship(User)

    def _permuteQPR(self, x):
        if x >= self._PRIME:
            return x  # The 5 integers out of range are mapped to themselves.
        residue = (x * x) % self._PRIME
        return residue if (x <= self._PRIME / 2) else self._PRIME - residue

    def _create_unique_id(self, x):
        first = (self._permuteQPR(x) +
                 sum([ord(x) for x in self.prefix])) % self._PRIME
        return self._permuteQPR(first)

    def _get_id(self, n):
        uniqueId = self._create_unique_id(n)
        formattedId = "{}{:0>7d}".format(self.prefix, uniqueId)
        checkDigit = self._get_checkdigit(formattedId)
        return "{}{}".format(formattedId, checkDigit)

    def validate(self, id):
        code = id[:-1]

        if id[:len(self.prefix)] != self.prefix:
            return False

        if id[-1:] != self._get_checkdigit(code):
            return False

        return True

    def _get_checkdigit(self, id):

        numerified = sum([ord(x) * i for i, x in enumerate(id)])

        return "ABCDEFGHJKLMNPQRSTVWXYZ"[numerified % 23]

    def _create_pseudo_id(self, ordinal, user):
        unique_code = self._create_unique_id(ordinal)
        formatted_code = "{}{:0>7d}".format(self.prefix, unique_code)
        check_character = self._get_checkdigit(formatted_code)
        full_code = formatted_code + check_character

        return PseudoRandomId(
            pseudo_random_id_provider_id=self.id,
            ordinal=ordinal,
            unique_code=unique_code,
            check_character=check_character,
            full_code=full_code,
            last_updated_by_user_id=user.id,
        )

    def allocate_id(self, user):
        previous_ordinal = db.session.query(db.func.max(
            PseudoRandomId.ordinal)).scalar() or 0
        result = self._create_pseudo_id(previous_ordinal + 1, user)
        db.session.add(result)

        return result

    def allocate_ids(self, count, user):
        # Bulk inserts objects for speed that does not populate
        # the object ID, so may cause problems if the object is
        # used later on.

        result = []
        previous_ordinal = db.session.query(db.func.max(
            PseudoRandomId.ordinal)).scalar() or 0

        for ordinal in range(previous_ordinal + 1,
                             previous_ordinal + count + 1):
            result.append(self._create_pseudo_id(ordinal, user))

        db.session.bulk_save_objects(result)
        db.session.commit()

        return result
Exemplo n.º 27
0
class BioresourceIdProvider(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(100), nullable=False)
    prefix = db.Column(db.String(10), nullable=False)
    last_updated_datetime = db.Column(db.DateTime,
                                      nullable=False,
                                      default=datetime.utcnow)
    last_updated_by_user_id = db.Column(db.Integer, db.ForeignKey(User.id))
    last_updated_by_user = db.relationship(User)

    def allocate_id(self, user):
        prospective_id = 0
        found = 1
        tries = 0

        while found > 0:
            prospective_id = random.randint(1000000, 9999999)
            tries = tries + 1

            found = BioresourceId.query.filter(
                BioresourceId.bioresource_id_provider_id == self.id).filter(
                    BioresourceId.number == prospective_id).count()

        actual_id = BioresourceId(
            bioresource_id_provider=self,
            number=prospective_id,
            check_character=self._get_checkdigit(prospective_id),
            last_updated_by_user=user,
        )

        db.session.add(actual_id)

        return actual_id

    def validate(self, id):
        if id[:len(self.prefix)] != self.prefix:
            return False

        number = id[len(self.prefix):-1]

        if len(number) != 7:
            return False

        if id[-1:] != self._get_checkdigit(int(number)):
            return False

        return True

    def _get_checkdigit(self, id):

        return "ZABCDEFGHJKLMNPQRSTVWXY"[id % 23]

    def allocate_ids(self, count, user):
        result = []
        for _ in range(count):
            result.append(self.allocate_id(user))

        return result

    def __repr__(self):
        return str(self.__class__) + ": " + str(self.__dict__)
Exemplo n.º 28
0
class TaskStatusType(db.Model, CommonMixin):

    CREATED = 'Created'
    IN_PROGRESS = 'In Progress'
    DONE = 'Done'
    AWAITING_INFORMATION = 'Awaiting Information'
    CANCELLED = 'Cancelled'
    DECLINED = 'Declined'
    DUPLICATE = 'Duplicate'

    all_details = {
        CREATED: {
            'is_complete': False,
            'is_active': False,
        },
        IN_PROGRESS: {
            'is_complete': False,
            'is_active': True,
        },
        DONE: {
            'is_complete': True,
            'is_active': False,
        },
        AWAITING_INFORMATION: {
            'is_complete': False,
            'is_active': False,
        },
        CANCELLED: {
            'is_complete': True,
            'is_active': False,
        },
        DECLINED: {
            'is_complete': True,
            'is_active': False,
        },
        DUPLICATE: {
            'is_complete': True,
            'is_active': False,
        },
    }

    @classmethod
    def get_task_status(cls, name):
        return TaskStatusType.query.filter_by(name=name).one()

    @classmethod
    def get_created(cls):
        return cls.get_task_status(TaskStatusType.CREATED)

    @classmethod
    def get_created_id(cls):
        return cls.get_created().id

    @classmethod
    def get_in_progress(cls):
        return cls.get_task_status(TaskStatusType.IN_PROGRESS)

    @classmethod
    def get_done(cls):
        return cls.get_task_status(TaskStatusType.DONE)

    @classmethod
    def get_awaiting_information(cls):
        return cls.get_task_status(TaskStatusType.AWAITING_INFORMATION)

    @classmethod
    def get_cancelled(cls):
        return cls.get_task_status(TaskStatusType.CANCELLED)

    @classmethod
    def get_declined(cls):
        return cls.get_task_status(TaskStatusType.DECLINED)

    @classmethod
    def get_duplicate(cls):
        return cls.get_task_status(TaskStatusType.DUPLICATE)

    id = db.Column(db.Integer(), primary_key=True)
    name = db.Column(db.String(255))
    is_complete = db.Column(db.Boolean)
    is_active = db.Column(db.Boolean)