Source code for ResearchNotes.database.ess_ppm_report

"""
Every databse scheme for ESS including the templates
"""

from dataclasses import dataclass
from datetime import datetime

from typing import List, Set, Any  # Needs to be here for compatibility with python 3.8

# from ResearchNotes.search import add_to_index, remove_from_index, query_index, delete_index

from ResearchNotes.database import db
from ResearchNotes.database.mixins import SearchableMixin


# =============================================================================
# Samples database scheme
# =============================================================================


[docs]@dataclass(init=False, eq=False) class Samples(SearchableMixin, db.Model): # type: ignore """ Defines the Sample database scheme. A sample has an id, identifier, origin, short description, long description and creator (Name or combination of names). We note creation date and update name. Update date should be also updated, if measurement or report are updated. One-to-many relation: - creator (user, how makes he record) as user id. - Group-id - Location Backref: - Measurements - Reports Many-to-many relation: -SharedSamples """ # id: int = field(init=False) # identifier: str # origin: str # short_dis: str # long_dis: str # creator: str # created: datetime = field(init=False) # updated: datetime = field(init=False) # creator_id: int # group_id: int # location_id: int __tablename__ = "samples" __searchable__ = ["short_dis", "long_dis", "origin", "identifier", "creator"] id: int = db.Column(db.Integer, primary_key=True) identifier: str = db.Column(db.String(80), nullable=False) origin: str = db.Column(db.String(80), nullable=False) short_dis: str = db.Column(db.String(80), nullable=False) long_dis: str = db.Column(db.Text, nullable=False) creator: str = db.Column(db.String(80), nullable=False) created: datetime = db.Column(db.DateTime, nullable=False, index=True, default=datetime.utcnow) updated: datetime = db.Column( db.DateTime, nullable=False, index=True, default=datetime.utcnow, onupdate=datetime.utcnow, ) # One to many # Creator of record creator_id: int = db.Column(db.Integer, db.ForeignKey("users.id")) # Group, which owns sample group_id: int = db.Column(db.Integer, db.ForeignKey("groups.id")) # Sample storing place location_id: int = db.Column(db.Integer, db.ForeignKey("locations.id"), default=1) # Backref # # Measurements related to sample # Creates Measurements.measurement_sample # measurements = db.relationship( "Measurements", backref="measurement_sample", lazy="dynamic", order_by="desc(Measurements.updated)", ) # Reports related to sample # Creates Reports.reports_sample (used heavily for identification and information # in report module) # reports = db.relationship( "Reports", backref="reports_sample", lazy="dynamic", order_by="desc(Reports.updated)" ) # # Many-to-many relation for shared sample # # Backref is wrong, issue #20 sharedsamples = db.relationship("User", secondary="sharedsamples", back_populates="sharedsamples") def __repr__(self) -> str: """ Return a representation string of the sample database scheme. Returns ------- str Representation string. """ return f"Sample ID:{self.id}-Sample identifier: {self.identifier}" @property def sharedsamplelist(self) -> List[int]: """ Give a list of ids in samples.sharedsamples. This should be the ids of the user the sample is shared to. Returns ------- list List of user IDs to whom sample is shared. """ return [u.id for u in self.sharedsamples] @property def is_shared(self) -> bool: """ Return true, if the sample is shared to someone. Returns ------- Bool True if there is an entry in the sharedsamplelist, i.e. exits user. """ return len(self.sharedsamplelist) > 0
# ============================================================================= # Measurement Type database scheme # =============================================================================
[docs]@dataclass(init=False, eq=False) class MeasurementType(db.Model): # type: ignore """ Defines the MeasurementType database scheme. Type has an ID and a name. It relates to its group and the measurements attached to it. """ # id: int = field(init=False) # name: str # group_id: int __tablename__ = "measurementstype" id: int = db.Column(db.Integer, primary_key=True) name: str = db.Column(db.String(50), nullable=False) # One to many # Group the measurement type is registered for group_id: int = db.Column(db.Integer, db.ForeignKey("groups.id")) # Backref # Measurements of this type # Creates Measurements.measurement_type # measurements = db.relationship("Measurements", backref="measurement_type", lazy="dynamic") def __repr__(self) -> str: """ Representation string of the MeasurementType database scheme. Returns ------- str Representation of the class. """ return f"MeasurementType ID:{self.id}, MeasurementType name: {self.name}"
# ============================================================================= # Measurements database scheme # =============================================================================
[docs]@dataclass(init=False, eq=False) class Measurements(SearchableMixin, db.Model): # type: ignore """ Measurement database scheme. Measurements have an id, short description, long description, creator, a creation date and an update date One-to-many - Measurement type (mtype) - Sample ID - User ID of person who made measurement report (might not be the creator) Backref - Reports """ # id: int = field(init=False) # short_dis: str # long_dis: str # creator: str # created: datetime = field(init=False) # updated: datetime = field(init=False) # # mtype_id: int # sample_id: int # creator_id: int __tablename__ = "measurements" __searchable__ = ["short_dis", "long_dis", "creator"] id: int = db.Column(db.Integer, primary_key=True) short_dis: str = db.Column(db.String(80), nullable=False) long_dis: str = db.Column(db.Text, nullable=False) creator: str = db.Column(db.String(80), nullable=False) created: datetime = db.Column(db.DateTime, nullable=False, index=True, default=datetime.utcnow) updated: datetime = db.Column( db.DateTime, nullable=False, index=True, default=datetime.utcnow, onupdate=datetime.utcnow, ) # One to many # Measurement type mtype_id: int = db.Column(db.Integer, db.ForeignKey("measurementstype.id")) # Sample id of measured sample sample_id: int = db.Column(db.Integer, db.ForeignKey("samples.id")) # User making the record creator_id: int = db.Column(db.Integer, db.ForeignKey("users.id")) # Instrument used in the PPM instrument_id: int = db.Column(db.Integer, db.ForeignKey("instrument.id")) # Backref # reports for this measurement # Creates Reports.report_measurement # reports = db.relationship("Reports", backref="report_measurement", lazy="dynamic") def __repr__(self) -> str: """ Representation string of the measurement database scheme. Returns ------- str DESCRIPTION. """ return ( f"Measurement ID:{self.id}, Measurement: {self.short_dis}, " + f" Sample related {self.sample_id}" )
# ============================================================================= # Reports database scheme # =============================================================================
[docs]@dataclass(init=False, eq=False) class Reports(SearchableMixin, db.Model): # type: ignore """ Defines the Report database scheme. A report has an ID, title and a long description. We note creator (free name), creation date and updated date. One-to-many relations: - Sample - User submitting report (User ID) - Measurement report is about """ # id: int = field(init=False) # title: str # long_dis: str # creator: str # created: datetime = field(init=False) # updated: datetime = field(init=False) # # sample_id: int # creator_id: int # measurement_id: int __tablename__ = "report" __searchable__ = ["title", "long_dis", "creator"] id: int = db.Column(db.Integer, primary_key=True) title: str = db.Column(db.String(80), nullable=False) long_dis: str = db.Column(db.Text, nullable=False) creator: str = db.Column(db.String(80), nullable=False) created: datetime = db.Column(db.DateTime, nullable=False, index=True, default=datetime.utcnow) updated: datetime = db.Column( db.DateTime, nullable=False, index=True, default=datetime.utcnow, onupdate=datetime.utcnow, ) # One-to-many relations: # Sample the report is about sample_id: int = db.Column(db.Integer, db.ForeignKey("samples.id")) # User submitting the report creator_id: int = db.Column(db.Integer, db.ForeignKey("users.id")) # Measurement the report is about measurement_id: int = db.Column(db.Integer, db.ForeignKey("measurements.id")) def __repr__(self) -> str: """ Return a representation string of the Report's database scheme. Returns ------- str Database scheme representation. """ return f"Report ID:{self.id}, Report title: {self.title}"
# ============================================================================= # Defines the table for the many-to-many relation of the shared samples. # ============================================================================= ShareSamples = db.Table( "sharedsamples", db.Column("sample_id", db.Integer, db.ForeignKey("samples.id")), db.Column("user_id", db.Integer, db.ForeignKey("users.id")), ) # ============================================================================= # Sample Templates database scheme # =============================================================================
[docs]@dataclass(init=False, eq=False) class TemplateSamples(db.Model): # type: ignore """ ESS template database structure. The class is used for all templates related to create E/S/S entries. They can either be created from scratch or from existing samples. """ # id: int = field(init=False) # tname: str # identifier: str # origin: str # short_dis: str # long_dis: str # # creator_id: int # group_id: int # # created: datetime = field(init=False) # updated: datetime = field(init=False) __tablename__ = "templatesamples" id: int = db.Column(db.Integer, primary_key=True) tname: str = db.Column(db.String(80), nullable=False) identifier: str = db.Column(db.String(80), nullable=False) origin: str = db.Column(db.String(80), nullable=False) short_dis: str = db.Column(db.String(80), nullable=False) long_dis: str = db.Column(db.Text, nullable=False) creator_id: int = db.Column(db.Integer, db.ForeignKey("users.id")) group_id: int = db.Column(db.Integer, db.ForeignKey("groups.id")) group_share: bool = db.Column(db.Boolean, nullable=False, default=False) created: datetime = db.Column(db.DateTime, nullable=False, index=True, default=datetime.utcnow) updated: datetime = db.Column( db.DateTime, nullable=False, index=True, default=datetime.utcnow, onupdate=datetime.utcnow, ) instruments_default = db.relationship( "Instrument", backref="default_ess_template", lazy="dynamic", order_by="desc(Instrument.updated)", )
# ============================================================================= # Measurement templates database scheme # =============================================================================
[docs]@dataclass(init=False, eq=False) class TemplateMeasurements(db.Model): # type: ignore """ PPM database structure. Class for all PMM templates to come from exiting PMM or created from scratch. """ # id: int = field(init=False) # tname: str # short_dis: str # long_dis: str # # creator_id: int # # created: datetime = field(init=False) # updated: datetime = field(init=False) __tablename__ = "templatemeasurements" id: int = db.Column(db.Integer, primary_key=True) tname: str = db.Column(db.String(80), nullable=False) short_dis: str = db.Column(db.String(80), nullable=False) long_dis: str = db.Column(db.Text, nullable=False) creator_id: int = db.Column(db.Integer, db.ForeignKey("users.id")) group_id: int = db.Column(db.Integer, db.ForeignKey("groups.id")) group_share: bool = db.Column(db.Boolean, nullable=False, default=False) created: datetime = db.Column(db.DateTime, nullable=False, index=True, default=datetime.utcnow) updated: datetime = db.Column( db.DateTime, nullable=False, index=True, default=datetime.utcnow, onupdate=datetime.utcnow, ) mtype_id: int = db.Column(db.Integer, default=1) creator: str = db.Column(db.String(80), nullable=True) instruments_default = db.relationship( "Instrument", backref="default_ppm_template", lazy="dynamic", order_by="desc(Instrument.updated)", )
# ============================================================================= # Report templates database scheme # =============================================================================
[docs]@dataclass class TemplateReports(db.Model): # type: ignore """ Report template database structure (unused). This guy is currently not used as we have no report templates. """ # id: int = field(init=False) # tname: str # title: str # long_dis: str # # creator_id: int # # created: datetime = field(init=False) # updated: datetime = field(init=False) __tablename__ = "templatereport" id: int = db.Column(db.Integer, primary_key=True) tname: str = db.Column(db.String(80), nullable=False) title: str = db.Column(db.String(80), nullable=False) long_dis: str = db.Column(db.Text, nullable=False) creator_id: int = db.Column(db.Integer, db.ForeignKey("users.id")) group_id: int = db.Column(db.Integer, db.ForeignKey("groups.id")) group_share: bool = db.Column(db.Boolean, nullable=False, default=False) created: datetime = db.Column(db.DateTime, nullable=False, index=True, default=datetime.utcnow) updated: datetime = db.Column( db.DateTime, nullable=False, index=True, default=datetime.utcnow, onupdate=datetime.utcnow, )