ReagentLot add/edit updated.
This commit is contained in:
@@ -2,11 +2,12 @@
|
||||
Contains all models for sqlalchemy
|
||||
"""
|
||||
from __future__ import annotations
|
||||
import sys, logging, json
|
||||
import sys, logging, json, inspect
|
||||
from dateutil.parser import parse
|
||||
from jinja2 import TemplateNotFound
|
||||
from pandas import DataFrame
|
||||
from pydantic import BaseModel
|
||||
from sqlalchemy import Column, INTEGER, String, JSON
|
||||
from sqlalchemy import Column, INTEGER, String, JSON, DATETIME
|
||||
from sqlalchemy.ext.associationproxy import AssociationProxy
|
||||
from sqlalchemy.orm import DeclarativeMeta, declarative_base, Query, Session, InstrumentedAttribute, ColumnProperty
|
||||
from sqlalchemy.ext.declarative import declared_attr
|
||||
@@ -36,10 +37,6 @@ class BaseClass(Base):
|
||||
__table_args__ = {'extend_existing': True} #: NOTE Will only add new columns
|
||||
|
||||
singles = ['id']
|
||||
# omni_removes = ["id", 'run', "omnigui_class_dict", "omnigui_instance_dict"]
|
||||
# omni_sort = ["name"]
|
||||
# omni_inheritable = []
|
||||
searchables = []
|
||||
|
||||
_misc_info = Column(JSON)
|
||||
|
||||
@@ -155,6 +152,33 @@ class BaseClass(Base):
|
||||
except AttributeError:
|
||||
return []
|
||||
|
||||
@classmethod
|
||||
def get_omni_sort(cls):
|
||||
output = [item[0] for item in inspect.getmembers(cls, lambda a: not (inspect.isroutine(a)))
|
||||
if isinstance(item[1], InstrumentedAttribute)] # and not isinstance(item[1].property, _RelationshipDeclared)]
|
||||
output = [item for item in output if item not in ['_misc_info']]
|
||||
return output
|
||||
|
||||
@classmethod
|
||||
def get_searchables(cls):
|
||||
output = []
|
||||
for item in inspect.getmembers(cls, lambda a: not (inspect.isroutine(a))):
|
||||
if item[0] in ["_misc_info"]:
|
||||
continue
|
||||
if not isinstance(item[1], InstrumentedAttribute):
|
||||
continue
|
||||
if not isinstance(item[1].property, ColumnProperty):
|
||||
continue
|
||||
# if isinstance(item[1], _RelationshipDeclared):
|
||||
# if "association" in item[0]:
|
||||
# continue
|
||||
if len(item[1].foreign_keys) > 0:
|
||||
continue
|
||||
if item[1].type.__class__.__name__ not in ["String"]:
|
||||
continue
|
||||
output.append(item[0])
|
||||
return output
|
||||
|
||||
@classmethod
|
||||
def get_default_info(cls, *args) -> dict | list | str:
|
||||
"""
|
||||
@@ -296,7 +320,6 @@ class BaseClass(Base):
|
||||
except AttributeError:
|
||||
check = False
|
||||
if check:
|
||||
logger.debug("Got uselist")
|
||||
try:
|
||||
query = query.filter(attr.contains(v))
|
||||
except ArgumentError:
|
||||
@@ -358,16 +381,14 @@ class BaseClass(Base):
|
||||
dict: Dictionary of object minus _sa_instance_state with id at the front.
|
||||
"""
|
||||
dicto = {key: dict(class_attr=getattr(self.__class__, key), instance_attr=getattr(self, key))
|
||||
for key in dir(self.__class__) if
|
||||
isinstance(getattr(self.__class__, key), InstrumentedAttribute) and key not in self.omni_removes
|
||||
}
|
||||
for key in self.get_omni_sort()}
|
||||
for k, v in dicto.items():
|
||||
try:
|
||||
v['instance_attr'] = v['instance_attr'].name
|
||||
except AttributeError:
|
||||
continue
|
||||
try:
|
||||
dicto = list_sort_dict(input_dict=dicto, sort_list=self.__class__.omni_sort)
|
||||
dicto = list_sort_dict(input_dict=dicto, sort_list=self.__class__.get_omni_sort())
|
||||
except TypeError as e:
|
||||
logger.error(f"Could not sort {self.__class__.__name__} by list due to :{e}")
|
||||
try:
|
||||
@@ -418,7 +439,7 @@ class BaseClass(Base):
|
||||
try:
|
||||
template = env.get_template(temp_name)
|
||||
except TemplateNotFound as e:
|
||||
logger.error(f"Couldn't find template {e}")
|
||||
# logger.error(f"Couldn't find template {e}")
|
||||
template = env.get_template("details.html")
|
||||
return template
|
||||
|
||||
@@ -505,7 +526,6 @@ class BaseClass(Base):
|
||||
existing = self.__getattribute__(key)
|
||||
# NOTE: This is causing problems with removal of items from lists. Have to overhaul it.
|
||||
if existing is not None:
|
||||
logger.debug(f"{key} Existing: {existing}, incoming: {value}")
|
||||
if isinstance(value, list):
|
||||
value = value
|
||||
else:
|
||||
@@ -626,7 +646,7 @@ class BaseClass(Base):
|
||||
from backend.validators import pydant
|
||||
if not pyd_model_name:
|
||||
pyd_model_name = f"Pyd{self.__class__.__name__}"
|
||||
logger.debug(f"Looking for pydant model {pyd_model_name}")
|
||||
logger.info(f"Looking for pydant model {pyd_model_name}")
|
||||
try:
|
||||
pyd = getattr(pydant, pyd_model_name)
|
||||
except AttributeError:
|
||||
|
||||
@@ -194,6 +194,7 @@ class Reagent(BaseClass, LogMixin):
|
||||
Concrete reagent instance
|
||||
"""
|
||||
|
||||
skip_on_edit = False
|
||||
id = Column(INTEGER, primary_key=True) #: primary key
|
||||
reagentrole = relationship("ReagentRole", back_populates="reagent",
|
||||
secondary=reagentrole_reagent) #: joined parent ReagentRole
|
||||
@@ -319,15 +320,7 @@ class Reagent(BaseClass, LogMixin):
|
||||
except AttributeError as e:
|
||||
logger.error(f"Could not set {key} due to {e}")
|
||||
|
||||
@check_authorization
|
||||
def edit_from_search(self, obj, **kwargs):
|
||||
from frontend.widgets.omni_add_edit import AddEdit
|
||||
dlg = AddEdit(parent=None, instance=self)
|
||||
if dlg.exec():
|
||||
pyd = dlg.parse_form()
|
||||
for field in pyd.model_fields:
|
||||
self.set_attribute(field, pyd.__getattribute__(field))
|
||||
self.save()
|
||||
|
||||
|
||||
@classproperty
|
||||
def add_edit_tooltips(self):
|
||||
@@ -418,6 +411,15 @@ class ReagentLot(BaseClass):
|
||||
pass
|
||||
setattr(self, key, value)
|
||||
|
||||
@check_authorization
|
||||
def edit_from_search(self, obj, **kwargs):
|
||||
from frontend.widgets.omni_add_edit import AddEdit
|
||||
dlg = AddEdit(parent=None, instance=self, disabled=['reagent'])
|
||||
if dlg.exec():
|
||||
pyd = dlg.parse_form()
|
||||
for field in pyd.model_fields:
|
||||
self.set_attribute(field, pyd.__getattribute__(field))
|
||||
self.save()
|
||||
|
||||
class Discount(BaseClass):
|
||||
"""
|
||||
@@ -952,6 +954,7 @@ class Procedure(BaseClass):
|
||||
output['sample'] = active_samples + inactive_samples
|
||||
output['reagent'] = [reagent.details_dict() for reagent in output['procedurereagentlotassociation']]
|
||||
output['equipment'] = [equipment.details_dict() for equipment in output['procedureequipmentassociation']]
|
||||
logger.debug(f"equipment: {pformat([item for item in output['equipment']])}")
|
||||
output['repeat'] = self.repeat
|
||||
output['run'] = self.run.name
|
||||
output['excluded'] += self.get_default_info("details_ignore")
|
||||
@@ -963,14 +966,6 @@ class Procedure(BaseClass):
|
||||
def to_pydantic(self, **kwargs):
|
||||
from backend.validators.pydant import PydReagent
|
||||
output = super().to_pydantic()
|
||||
try:
|
||||
output.kittype = dict(value=output.kittype['name'], missing=False)
|
||||
except KeyError:
|
||||
try:
|
||||
output.kittype = dict(value=output.kittype['value'], missing=False)
|
||||
except KeyError as e:
|
||||
logger.error(f"Output.kittype: {output.kittype}")
|
||||
raise e
|
||||
output.sample = [item.to_pydantic() for item in output.proceduresampleassociation]
|
||||
reagents = []
|
||||
for reagent in output.reagent:
|
||||
@@ -985,6 +980,7 @@ class Procedure(BaseClass):
|
||||
output.result = [item.to_pydantic() for item in self.results]
|
||||
output.sample_results = flatten_list(
|
||||
[[result.to_pydantic() for result in item.results] for item in self.proceduresampleassociation])
|
||||
|
||||
return output
|
||||
|
||||
def create_proceduresampleassociations(self, sample):
|
||||
@@ -1607,7 +1603,7 @@ class Equipment(BaseClass, LogMixin):
|
||||
from backend.validators.pydant import PydEquipment
|
||||
creation_dict = self.details_dict()
|
||||
processes = self.get_processes(equipmentrole=equipmentrole)
|
||||
creation_dict['process'] = processes
|
||||
creation_dict['processes'] = processes
|
||||
creation_dict['equipmentrole'] = equipmentrole or creation_dict['equipmentrole']
|
||||
return PydEquipment(**creation_dict)
|
||||
|
||||
@@ -2187,6 +2183,7 @@ class ProcedureEquipmentAssociation(BaseClass):
|
||||
output.update(relevant)
|
||||
output['misc_info'] = misc
|
||||
output['equipment_role'] = self.equipmentrole
|
||||
output['processes'] = [item for item in self.equipment.get_processes(equipmentrole=output['equipment_role'])]
|
||||
try:
|
||||
output['processversion'] = self.processversion.details_dict()
|
||||
except AttributeError:
|
||||
|
||||
@@ -116,7 +116,6 @@ class ClientSubmission(BaseClass, LogMixin):
|
||||
if start_date is not None:
|
||||
start_date = cls.rectify_query_date(start_date)
|
||||
end_date = cls.rectify_query_date(end_date, eod=True)
|
||||
logger.debug(f"Start date: {start_date}, end date: {end_date}")
|
||||
query = query.filter(cls.submitted_date.between(start_date, end_date))
|
||||
# NOTE: by rsl number (returns only a single value)
|
||||
match submitter_plate_id:
|
||||
@@ -303,7 +302,6 @@ class ClientSubmission(BaseClass, LogMixin):
|
||||
return {item: self.__getattribute__(item.lower().replace(" ", "_")) for item in names}
|
||||
|
||||
def add_run(self, obj):
|
||||
logger.debug("Add Run")
|
||||
from frontend.widgets.sample_checker import SampleChecker
|
||||
samples = [sample.to_pydantic() for sample in self.clientsubmissionsampleassociation]
|
||||
checker = SampleChecker(parent=None, title="Create Run", samples=samples, clientsubmission=self)
|
||||
@@ -455,13 +453,14 @@ class Run(BaseClass, LogMixin):
|
||||
output = {k: v for k, v in dicto.items() if k in args}
|
||||
else:
|
||||
output = {k: v for k, v in dicto.items()}
|
||||
logger.debug(f"Submission type for get default info: {submissiontype}")
|
||||
# logger.debug(f"Submission type for get default info: {submissiontype}")
|
||||
if isinstance(submissiontype, SubmissionType):
|
||||
st = submissiontype
|
||||
else:
|
||||
st = cls.get_submission_type(submissiontype)
|
||||
if st is None:
|
||||
logger.error("No default info for Run.")
|
||||
# logger.error("No default info for Run.")
|
||||
pass
|
||||
else:
|
||||
output['submissiontype'] = st.name
|
||||
for k, v in st.defaults.items():
|
||||
|
||||
Reference in New Issue
Block a user