Source code for ResearchNotes.database.instrument_journal

"""
All databases schemes for instrumentation and instrumentation journal entries (including templates) go here.
"""

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

# =============================================================================
# Many-to-many table for instruments
# =============================================================================

SharedInstrumentsToGuestUsers = db.Table(
    "shared_instruments_to_guest_users",
    db.Column("intrument_id", db.Integer, db.ForeignKey("instrument.id")),
    db.Column("user_id", db.Integer, db.ForeignKey("users.id")),
)

# =============================================================================
# Instrument database scheme
# =============================================================================


[docs]@dataclass(init=False, eq=False) class Instrument(SearchableMixin, db.Model): # type: ignore """ Define the Instrument database scheme. An instrument has an id, an identifier, a description, and a creator. It also stores creation and update date. One-to-many relations: - user_id - group_id - location_id Backref: - InstrumentationJournalEntry Many-to-many relation: - InstrumentSharedWithGroups """ __tablename__ = "instrument" __searchable__ = ["identifier", "description"] id: int = db.Column(db.Integer, primary_key=True) identifier: str = db.Column(db.String(80), nullable=False) description: str = db.Column(db.Text, nullable=False) active: bool = db.Column(db.Boolean, nullable=False, default=True) 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 instrument group_id: int = db.Column(db.Integer, db.ForeignKey("groups.id")) # Storage location location_id: int = db.Column(db.Integer, db.ForeignKey("locations.id"), default=1) # Default template for E/S/S default_ess_template_id: int = db.Column(db.Integer, db.ForeignKey("templatesamples.id")) # Default template for P/P/M default_ppm_template_id: int = db.Column(db.Integer, db.ForeignKey("templatemeasurements.id")) # Default template for instrumentation journal entries default_entry_template_id: int = db.Column(db.Integer, db.ForeignKey("templateentry.id")) # Backref # # Instrumentation Journal entries related to Instrument # Creates InstrumentationJournalEntry.instrument # journal_entries = db.relationship( "InstrumentationJournalEntry", backref="instrument", lazy="dynamic", order_by="desc(InstrumentationJournalEntry.created)", ) # PPM that were made using this instrument # measurements = db.relationship( "Measurements", backref="instrument", lazy="dynamic", order_by="desc(Measurements.updated)", ) # Instrumentation journal entry types associated with this instrument etypes = db.relationship( "EntryType", backref="instrument", lazy="dynamic", ) # Many-to-many relationship for shared Instrument # guest_users = db.relationship( "User", secondary="shared_instruments_to_guest_users", back_populates="shared_instruments", ) def __repr__(self) -> str: """ Return a representation string of the Instrument database scheme. Returns ------- str Representation string. """ return f"Instrument ID:{self.id}-Instrument identifier: {self.identifier}" @property def guest_users_list(self) -> list[int]: """ Return a list with the IDs of all guest users Returns ------- List[int] The IDs of the users this instrument is shared with """ return [user.id for user in self.guest_users] @property def is_shared(self) -> bool: """ Return true, if the instrument is shared with some group. Returns ------- Bool True if there is an entry in the shared_with_groups_list. """ return len(self.guest_users_list) > 0
# ============================================================================= # Instrument template database scheme # =============================================================================
[docs]@dataclass(init=False, eq=False) class TemplateInstrument(db.Model): # type: ignore """ Instrument template database scheme. Class for instrument templates, that can be created from exiting instruments or made from scratch. """ __tablename__ = "templateinstrument" id: int = db.Column(db.Integer, primary_key=True) creator_id: int = db.Column(db.Integer, db.ForeignKey("users.id")) group_id: int = db.Column(db.Integer, db.ForeignKey("groups.id")) tname: str = db.Column(db.String(80), nullable=False) location_id: int = db.Column(db.Integer, default=1) identifier: str = db.Column(db.String(80), nullable=False) description: str = db.Column(db.Text, 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, )
# ============================================================================= # Instrumentation journal entry type database scheme # ============================================================================= #
[docs]@dataclass(init=False, eq=False) class EntryType(db.Model): # type: ignore """ Defines the EntryType database scheme. Type has an ID and a name. It relates to its instrument. """ # id: int = field(init=False) # name: str # group_id: int __tablename__ = "entrytype" id: int = db.Column(db.Integer, primary_key=True) name: str = db.Column(db.String(50), nullable=False) # One to many # Instrument that the instrumentation journal entry type is associated with instrument_id: int = db.Column(db.Integer, db.ForeignKey("instrument.id")) # Backref # Instrumentation journal entries of this type # Creates InstrumentationJournalEntry.etype entries = db.relationship("InstrumentationJournalEntry", backref="etype", lazy="dynamic") def __repr__(self) -> str: """ Representation string of the EntryType database scheme. Returns ------- str Representation of the class. """ return f"EntryType ID:{self.id}, EntryType name: {self.name}"
# ============================================================================= # Instrument Journal Entry database scheme # =============================================================================
[docs]@dataclass(init=False, eq=False) class InstrumentationJournalEntry(SearchableMixin, db.Model): # type: ignore """ Define the Instrumentation Journal Entry database scheme. An entry has an id, an identifier, a description, and a creator. It also stores creation and update date. One-to-many relations: - user_id - group_id - location_id """ __tablename__ = "instrumentation_journal_entry" __searchable__ = ["identifier", "description"] id: int = db.Column(db.Integer, primary_key=True) identifier: str = db.Column(db.String(80), nullable=False) description: str = db.Column(db.Text, 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 # Entry type etype_id: int = db.Column(db.Integer, db.ForeignKey("entrytype.id")) # Creator of record creator_id: int = db.Column(db.Integer, db.ForeignKey("users.id")) # ID of instrument being journaled about instrument_id: int = db.Column(db.Integer, db.ForeignKey("instrument.id")) # ID of owner group group_id: int = db.Column(db.Integer, db.ForeignKey("groups.id")) def __repr__(self) -> str: """ Return a representation string of the InstrumentationJournalEntry database scheme. Returns ------- str Representation string. """ return f"InstrumentationJournalEntry ID:{self.id}, Identifier: {self.identifier}, "
# ============================================================================= # InstrumentationJournalEntry template database scheme # =============================================================================
[docs]@dataclass(init=False, eq=False) class TemplateInstrumentationJournalEntry(db.Model): # type: ignore """ Instrumentation journal entry template database scheme. Class for instrumentation journal entry templates, that can be created from exiting entries or made from scratch. """ __tablename__ = "templateentry" id: int = db.Column(db.Integer, primary_key=True) creator_id: int = db.Column(db.Integer, db.ForeignKey("users.id")) group_id: int = db.Column(db.Integer, db.ForeignKey("groups.id")) tname: str = db.Column(db.String(80), nullable=False) identifier: str = db.Column(db.String(80), nullable=False) description: str = db.Column(db.Text, 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, ) etype_id: int = db.Column(db.Integer, default=0) instruments_default = db.relationship( "Instrument", backref="default_entry_template", lazy="dynamic", order_by="desc(Instrument.updated)", )