"""
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"))
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"))
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"))
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,
)