diff --git a/alembic.ini b/alembic.ini
index 0cddafa..bbda290 100644
--- a/alembic.ini
+++ b/alembic.ini
@@ -56,9 +56,9 @@ version_path_separator = os # Use os.pathsep. Default configuration used for ne
# output_encoding = utf-8
; sqlalchemy.url = sqlite:///L:\Robotics Laboratory Support\Submissions\submissions.db
-; sqlalchemy.url = sqlite:///C:\Users\lwark\Documents\Archives\Submissions_app_backups\DB_backups\submissions-demo.db
+sqlalchemy.url = sqlite:///C:\Users\lwark\Documents\Archives\Submissions_app_backups\DB_backups\submissions-demo.db
;sqlalchemy.url = sqlite:///C:\Users\lwark\Documents\Archives\Submissions_app_backups\DB_backups\submissions-prototypes.db
-sqlalchemy.url = sqlite:///C:\Users\lwark\Documents\python\submissions\mytests\test_assets\submissions-test.db
+; sqlalchemy.url = sqlite:///C:\Users\lwark\Documents\python\submissions\mytests\test_assets\submissions-test.db
[post_write_hooks]
diff --git a/src/submissions/backend/db/models/kits.py b/src/submissions/backend/db/models/kits.py
index 9a1b4de..0b08803 100644
--- a/src/submissions/backend/db/models/kits.py
+++ b/src/submissions/backend/db/models/kits.py
@@ -19,11 +19,11 @@ from io import BytesIO
logger = logging.getLogger(f'submissions.{__name__}')
# logger.debug("Table for ReagentType/Reagent relations")
-reagenttypes_reagents = Table(
- "_reagenttypes_reagents",
+reagentroles_reagents = Table(
+ "_reagentroles_reagents",
Base.metadata,
Column("reagent_id", INTEGER, ForeignKey("_reagent.id")),
- Column("reagenttype_id", INTEGER, ForeignKey("_reagenttype.id")),
+ Column("reagentrole_id", INTEGER, ForeignKey("_reagentrole.id")),
extend_existing=True
)
@@ -84,16 +84,16 @@ class KitType(BaseClass):
processes = relationship("Process", back_populates="kit_types",
secondary=kittypes_processes) #: equipment processes used by this kit
- kit_reagenttype_associations = relationship(
- "KitTypeReagentTypeAssociation",
+ kit_reagentrole_associations = relationship(
+ "KitTypeReagentRoleAssociation",
back_populates="kit_type",
cascade="all, delete-orphan",
)
# creator function: https://stackoverflow.com/questions/11091491/keyerror-when-adding-objects-to-sqlalchemy-association-object/11116291#11116291
- reagent_types = association_proxy("kit_reagenttype_associations", "reagent_type",
- creator=lambda RT: KitTypeReagentTypeAssociation(
- reagent_type=RT)) #: Association proxy to KitTypeReagentTypeAssociation
+ reagent_roles = association_proxy("kit_reagentrole_associations", "reagent_role",
+ creator=lambda RT: KitTypeReagentRoleAssociation(
+ reagent_role=RT)) #: Association proxy to KitTypeReagentRoleAssociation
kit_submissiontype_associations = relationship(
"SubmissionTypeKitTypeAssociation",
@@ -111,7 +111,7 @@ class KitType(BaseClass):
"""
return f""
- def get_reagents(self, required: bool = False, submission_type: str | SubmissionType | None = None) -> List[ReagentType]:
+ def get_reagents(self, required: bool = False, submission_type: str | SubmissionType | None = None) -> List[ReagentRole]:
"""
Return ReagentTypes linked to kit through KitTypeReagentTypeAssociation.
@@ -120,25 +120,25 @@ class KitType(BaseClass):
submission_type (str | Submissiontype | None, optional): Submission type to narrow results. Defaults to None.
Returns:
- List[ReagentType]: List of reagents linked to this kit.
+ List[ReagentRole]: List of reagents linked to this kit.
"""
match submission_type:
case SubmissionType():
# logger.debug(f"Getting reagents by SubmissionType {submission_type}")
- relevant_associations = [item for item in self.kit_reagenttype_associations if
+ relevant_associations = [item for item in self.kit_reagentrole_associations if
item.submission_type == submission_type]
case str():
# logger.debug(f"Getting reagents by str {submission_type}")
- relevant_associations = [item for item in self.kit_reagenttype_associations if
+ relevant_associations = [item for item in self.kit_reagentrole_associations if
item.submission_type.name == submission_type]
case _:
# logger.debug(f"Getting reagents")
- relevant_associations = [item for item in self.kit_reagenttype_associations]
+ relevant_associations = [item for item in self.kit_reagentrole_associations]
if required:
# logger.debug(f"Filtering by required.")
- return [item.reagent_type for item in relevant_associations if item.required == 1]
+ return [item.reagent_role for item in relevant_associations if item.required == 1]
else:
- return [item.reagent_type for item in relevant_associations]
+ return [item.reagent_role for item in relevant_associations]
# TODO: Move to BasicSubmission?
def construct_xl_map_for_use(self, submission_type: str | SubmissionType) -> dict:
@@ -156,17 +156,17 @@ class KitType(BaseClass):
match submission_type:
case str():
# logger.debug(f"Constructing xl map with str {submission_type}")
- assocs = [item for item in self.kit_reagenttype_associations if
+ assocs = [item for item in self.kit_reagentrole_associations if
item.submission_type.name == submission_type]
case SubmissionType():
# logger.debug(f"Constructing xl map with SubmissionType {submission_type}")
- assocs = [item for item in self.kit_reagenttype_associations if item.submission_type == submission_type]
+ assocs = [item for item in self.kit_reagentrole_associations if item.submission_type == submission_type]
case _:
raise ValueError(f"Wrong variable type: {type(submission_type)} used!")
# logger.debug("Get all KitTypeReagentTypeAssociation for SubmissionType")
for assoc in assocs:
try:
- info_map[assoc.reagent_type.name] = assoc.uses
+ info_map[assoc.reagent_role.name] = assoc.uses
except TypeError:
continue
return info_map
@@ -226,34 +226,34 @@ class KitType(BaseClass):
super().save()
-class ReagentType(BaseClass):
+class ReagentRole(BaseClass):
"""
Base of reagent type abstract
"""
id = Column(INTEGER, primary_key=True) #: primary key
name = Column(String(64)) #: name of reagent type
- instances = relationship("Reagent", back_populates="type",
- secondary=reagenttypes_reagents) #: concrete instances of this reagent type
+ instances = relationship("Reagent", back_populates="role",
+ secondary=reagentroles_reagents) #: concrete instances of this reagent type
eol_ext = Column(Interval()) #: extension of life interval
- reagenttype_kit_associations = relationship(
- "KitTypeReagentTypeAssociation",
- back_populates="reagent_type",
+ reagentrole_kit_associations = relationship(
+ "KitTypeReagentRoleAssociation",
+ back_populates="reagent_role",
cascade="all, delete-orphan",
) #: Relation to KitTypeReagentTypeAssociation
# creator function: https://stackoverflow.com/questions/11091491/keyerror-when-adding-objects-to-sqlalchemy-association-object/11116291#11116291
- kit_types = association_proxy("reagenttype_kit_associations", "kit_type",
- creator=lambda kit: KitTypeReagentTypeAssociation(
- kit_type=kit)) #: Association proxy to KitTypeReagentTypeAssociation
+ kit_types = association_proxy("reagentrole_kit_associations", "kit_type",
+ creator=lambda kit: KitTypeReagentRoleAssociation(
+ kit_type=kit)) #: Association proxy to KitTypeReagentRoleAssociation
def __repr__(self) -> str:
"""
Returns:
str: Representation of object
"""
- return f""
+ return f""
@classmethod
@setup_lookup
@@ -262,7 +262,7 @@ class ReagentType(BaseClass):
kit_type: KitType | str | None = None,
reagent: Reagent | str | None = None,
limit: int = 0,
- ) -> ReagentType | List[ReagentType]:
+ ) -> ReagentRole | List[ReagentRole]:
"""
Lookup reagent types in the database.
@@ -276,7 +276,7 @@ class ReagentType(BaseClass):
ValueError: Raised if only kit_type or reagent, not both, given.
Returns:
- ReagentType|List[ReagentType]: ReagentType or list of ReagentTypes matching filter.
+ ReagentRole|List[ReagentRole]: ReagentRole or list of ReagentRoles matching filter.
"""
query: Query = cls.__database_session__.query(cls)
if (kit_type is not None and reagent is None) or (reagent is not None and kit_type is None):
@@ -296,10 +296,10 @@ class ReagentType(BaseClass):
reagent = Reagent.query(lot_number=reagent)
case _:
pass
- assert reagent.type
+ assert reagent.role
# logger.debug(f"Looking up reagent type for {type(kit_type)} {kit_type} and {type(reagent)} {reagent}")
# logger.debug(f"Kit reagent types: {kit_type.reagent_types}")
- result = list(set(kit_type.reagent_types).intersection(reagent.type))
+ result = list(set(kit_type.reagent_roles).intersection(reagent.role))
# logger.debug(f"Result: {result}")
try:
return result[0]
@@ -322,7 +322,7 @@ class ReagentType(BaseClass):
PydReagent: PydReagent representation of this object.
"""
from backend.validators.pydant import PydReagent
- return PydReagent(lot=None, type=self.name, name=self.name, expiry=date.today())
+ return PydReagent(lot=None, role=self.name, name=self.name, expiry=date.today())
@check_authorization
def save(self):
@@ -335,10 +335,10 @@ class Reagent(BaseClass):
"""
id = Column(INTEGER, primary_key=True) #: primary key
- type = relationship("ReagentType", back_populates="instances",
- secondary=reagenttypes_reagents) #: joined parent reagent type
- type_id = Column(INTEGER, ForeignKey("_reagenttype.id", ondelete='SET NULL',
- name="fk_reagent_type_id")) #: id of parent reagent type
+ role = relationship("ReagentRole", back_populates="instances",
+ secondary=reagentroles_reagents) #: joined parent reagent type
+ role_id = Column(INTEGER, ForeignKey("_reagentrole.id", ondelete='SET NULL',
+ name="fk_reagent_role_id")) #: id of parent reagent type
name = Column(String(64)) #: reagent name
lot = Column(String(64)) #: lot number of reagent
expiry = Column(TIMESTAMP) #: expiry date - extended by eol_ext of parent programmatically
@@ -356,7 +356,7 @@ class Reagent(BaseClass):
if self.name is not None:
return f""
else:
- return f""
+ return f""
def to_sub_dict(self, extraction_kit: KitType = None) -> dict:
"""
@@ -371,12 +371,12 @@ class Reagent(BaseClass):
if extraction_kit is not None:
# NOTE: Get the intersection of this reagent's ReagentType and all ReagentTypes in KitType
try:
- reagent_role = list(set(self.type).intersection(extraction_kit.reagent_types))[0]
+ reagent_role = list(set(self.role).intersection(extraction_kit.reagent_roles))[0]
# NOTE: Most will be able to fall back to first ReagentType in itself because most will only have 1.
except:
- reagent_role = self.type[0]
+ reagent_role = self.role[0]
else:
- reagent_role = self.type[0]
+ reagent_role = self.role[0]
try:
rtype = reagent_role.name.replace("_", " ")
except AttributeError:
@@ -393,7 +393,7 @@ class Reagent(BaseClass):
place_holder = place_holder.strftime("%Y-%m-%d")
return dict(
name=self.name,
- type=rtype,
+ role=rtype,
lot=self.lot,
expiry=place_holder,
missing=False
@@ -411,10 +411,10 @@ class Reagent(BaseClass):
"""
report = Report()
# logger.debug(f"Attempting update of last used reagent type at intersection of ({self}), ({kit})")
- rt = ReagentType.query(kit_type=kit, reagent=self, limit=1)
+ rt = ReagentRole.query(kit_type=kit, reagent=self, limit=1)
if rt is not None:
# logger.debug(f"got reagenttype {rt}")
- assoc = KitTypeReagentTypeAssociation.query(kit_type=kit, reagent_type=rt)
+ assoc = KitTypeReagentRoleAssociation.query(kit_type=kit, reagent_role=rt)
if assoc is not None:
if assoc.last_used != self.lot:
# logger.debug(f"Updating {assoc} last used to {self.lot}")
@@ -429,7 +429,7 @@ class Reagent(BaseClass):
@setup_lookup
def query(cls,
id: int | None = None,
- reagent_type: str | ReagentType | None = None,
+ reagent_role: str | ReagentRole | None = None,
lot_number: str | None = None,
name: str | None = None,
limit: int = 0
@@ -438,7 +438,7 @@ class Reagent(BaseClass):
Lookup a list of reagents from the database.
Args:
- reagent_type (str | models.ReagentType | None, optional): Reagent type. Defaults to None.
+ reagent_role (str | models.ReagentType | None, optional): Reagent type. Defaults to None.
lot_number (str | None, optional): Reagent lot number. Defaults to None.
name (str | None, optional): Reagent name. Defaults to None.
limit (int, optional): limit of results returned. Defaults to 0.
@@ -453,13 +453,13 @@ class Reagent(BaseClass):
limit = 1
case _:
pass
- match reagent_type:
+ match reagent_role:
case str():
# logger.debug(f"Looking up reagents by reagent type str: {reagent_type}")
- query = query.join(cls.type).filter(ReagentType.name == reagent_type)
- case ReagentType():
+ query = query.join(cls.role).filter(ReagentRole.name == reagent_role)
+ case ReagentRole():
# logger.debug(f"Looking up reagents by reagent type ReagentType: {reagent_type}")
- query = query.filter(cls.type.contains(reagent_type))
+ query = query.filter(cls.role.contains(reagent_role))
case _:
pass
match name:
@@ -582,7 +582,7 @@ class SubmissionType(BaseClass):
"equipment_role") #: Proxy of equipmentrole associations
submissiontype_kit_rt_associations = relationship(
- "KitTypeReagentTypeAssociation",
+ "KitTypeReagentRoleAssociation",
back_populates="submission_type",
cascade="all, delete-orphan"
) #: triple association of KitTypes, ReagentTypes, SubmissionTypes
@@ -617,7 +617,7 @@ class SubmissionType(BaseClass):
if isinstance(filepath, str):
filepath = Path(filepath)
try:
- xl = ExcelFile(filepath)
+ ExcelFile(filepath)
except ValueError:
raise ValueError(f"File {filepath} is not of appropriate type.")
with open(filepath, "rb") as f:
@@ -836,13 +836,13 @@ class SubmissionTypeKitTypeAssociation(BaseClass):
return cls.execute_query(query=query, limit=limit)
-class KitTypeReagentTypeAssociation(BaseClass):
+class KitTypeReagentRoleAssociation(BaseClass):
"""
table containing reagenttype/kittype associations
DOC: https://docs.sqlalchemy.org/en/14/orm/extensions/associationproxy.html
"""
- reagent_types_id = Column(INTEGER, ForeignKey("_reagenttype.id"),
+ reagent_roles_id = Column(INTEGER, ForeignKey("_reagentrole.id"),
primary_key=True) #: id of associated reagent type
kits_id = Column(INTEGER, ForeignKey("_kittype.id"), primary_key=True) #: id of associated reagent type
submission_type_id = Column(INTEGER, ForeignKey("_submissiontype.id"), primary_key=True)
@@ -851,23 +851,23 @@ class KitTypeReagentTypeAssociation(BaseClass):
last_used = Column(String(32)) #: last used lot number of this type of reagent
kit_type = relationship(KitType,
- back_populates="kit_reagenttype_associations") #: relationship to associated KitType
+ back_populates="kit_reagentrole_associations") #: relationship to associated KitType
# reference to the "ReagentType" object
- reagent_type = relationship(ReagentType,
- back_populates="reagenttype_kit_associations") #: relationship to associated ReagentType
+ reagent_role = relationship(ReagentRole,
+ back_populates="reagentrole_kit_associations") #: relationship to associated ReagentType
submission_type = relationship(SubmissionType,
back_populates="submissiontype_kit_rt_associations") #: relationship to associated SubmissionType
- def __init__(self, kit_type=None, reagent_type=None, uses=None, required=1):
+ def __init__(self, kit_type=None, reagent_role=None, uses=None, required=1):
self.kit_type = kit_type
- self.reagent_type = reagent_type
+ self.reagent_role = reagent_role
self.uses = uses
self.required = required
def __repr__(self) -> str:
- return f""
+ return f""
@validates('required')
def validate_age(self, key, value):
@@ -888,8 +888,8 @@ class KitTypeReagentTypeAssociation(BaseClass):
raise ValueError(f'Invalid required value {value}. Must be 0 or 1.')
return value
- @validates('reagenttype')
- def validate_reagenttype(self, key, value):
+ @validates('reagentrole')
+ def validate_reagentrole(self, key, value):
"""
Ensures reagenttype is an actual ReagentType
@@ -903,23 +903,23 @@ class KitTypeReagentTypeAssociation(BaseClass):
Returns:
_type_: ReagentType
"""
- if not isinstance(value, ReagentType):
- raise ValueError(f'{value} is not a reagenttype')
+ if not isinstance(value, ReagentRole):
+ raise ValueError(f'{value} is not a reagentrole')
return value
@classmethod
@setup_lookup
def query(cls,
kit_type: KitType | str | None = None,
- reagent_type: ReagentType | str | None = None,
+ reagent_role: ReagentRole | str | None = None,
limit: int = 0
- ) -> KitTypeReagentTypeAssociation | List[KitTypeReagentTypeAssociation]:
+ ) -> KitTypeReagentRoleAssociation | List[KitTypeReagentRoleAssociation]:
"""
Lookup junction of ReagentType and KitType
Args:
kit_type (models.KitType | str | None): KitType of interest.
- reagent_type (models.ReagentType | str | None): ReagentType of interest.
+ reagent_role (models.ReagentType | str | None): ReagentType of interest.
limit (int, optional): Maximum number of results to return (0 = all). Defaults to 0.
Returns:
@@ -935,16 +935,16 @@ class KitTypeReagentTypeAssociation(BaseClass):
query = query.join(KitType).filter(KitType.name == kit_type)
case _:
pass
- match reagent_type:
- case ReagentType():
+ match reagent_role:
+ case ReagentRole():
# logger.debug(f"Lookup KitTypeReagentTypeAssociation by reagent_type ReagentType {reagent_type}")
- query = query.filter(cls.reagent_type == reagent_type)
+ query = query.filter(cls.reagent_role == reagent_role)
case str():
# logger.debug(f"Lookup KitTypeReagentTypeAssociation by reagent_type ReagentType {reagent_type}")
- query = query.join(ReagentType).filter(ReagentType.name == reagent_type)
+ query = query.join(ReagentRole).filter(ReagentRole.name == reagent_role)
case _:
pass
- if kit_type != None and reagent_type != None:
+ if kit_type != None and reagent_role != None:
limit = 1
return cls.execute_query(query=query, limit=limit)
@@ -1478,4 +1478,45 @@ class Process(BaseClass):
return cls.execute_query(query=query, limit=limit)
-# class Tips(Reagent):
\ No newline at end of file
+# class TipRole(BaseClass):
+#
+# id = Column(INTEGER, primary_key=True) #: primary key
+# name = Column(String(64)) #: name of reagent type
+# instances = relationship("Tips", back_populates="role",
+# secondary=reagenttypes_reagents) #: concrete instances of this reagent type
+#
+# tiprole_kit_associations = relationship(
+# "KitTypeTipRoleAssociation",
+# back_populates="tip_role",
+# cascade="all, delete-orphan",
+# ) #: Relation to KitTypeReagentTypeAssociation
+#
+# # creator function: https://stackoverflow.com/questions/11091491/keyerror-when-adding-objects-to-sqlalchemy-association-object/11116291#11116291
+# kit_types = association_proxy("tiprole_kit_associations", "kit_type",
+# creator=lambda kit: KitTypeReagentTypeAssociation(
+# kit_type=kit)) #: Association proxy to KitTypeReagentTypeAssociation
+#
+# def __repr__(self):
+# return f""
+#
+# class Tips(BaseClass):
+#
+# id = Column(INTEGER, primary_key=True) #: primary key
+# role = relationship("TipRole", back_populates="instances",
+# secondary=reagenttypes_reagents) #: joined parent reagent type
+# role_id = Column(INTEGER, ForeignKey("_tiprole.id", ondelete='SET NULL',
+# name="fk_tip_role_id")) #: id of parent reagent type
+# name = Column(String(64)) #: tip common name
+# lot = Column(String(64)) #: lot number of tips
+#
+# tips_submission_associations = relationship(
+# "SubmissionTipsAssociation",
+# back_populates="tips",
+# cascade="all, delete-orphan",
+# ) #: Relation to SubmissionSampleAssociation
+#
+# submissions = association_proxy("tips_submission_associations",
+# "submission") #: Association proxy to SubmissionSampleAssociation.samples
+#
+# def __repr__(self):
+# return f""
diff --git a/src/submissions/backend/db/models/submissions.py b/src/submissions/backend/db/models/submissions.py
index d369af7..63095cf 100644
--- a/src/submissions/backend/db/models/submissions.py
+++ b/src/submissions/backend/db/models/submissions.py
@@ -266,9 +266,9 @@ class BasicSubmission(BaseClass):
for k in self.extraction_kit.construct_xl_map_for_use(self.submission_type):
if k == 'info':
continue
- if not any([item['type'] == k for item in reagents]):
+ if not any([item['role'] == k for item in reagents]):
reagents.append(
- dict(type=k, name="Not Applicable", lot="NA", expiry=date(year=1970, month=1, day=1),
+ dict(role=k, name="Not Applicable", lot="NA", expiry=date(year=1970, month=1, day=1),
missing=True))
except Exception as e:
logger.error(f"We got an error retrieving reagents: {e}")
diff --git a/src/submissions/backend/excel/parser.py b/src/submissions/backend/excel/parser.py
index acfa67f..fa2a126 100644
--- a/src/submissions/backend/excel/parser.py
+++ b/src/submissions/backend/excel/parser.py
@@ -139,6 +139,7 @@ class SheetParser(object):
# logger.debug(f"Submission dictionary coming into 'to_pydantic':\n{pformat(self.sub)}")
pyd_dict = copy(self.sub)
pyd_dict['samples'] = [PydSample(**sample) for sample in self.sub['samples']]
+ logger.debug(f"Reagents: {pformat(self.sub['reagents'])}")
pyd_dict['reagents'] = [PydReagent(**reagent) for reagent in self.sub['reagents']]
# logger.debug(f"Equipment: {self.sub['equipment']}")
try:
@@ -307,7 +308,7 @@ class ReagentParser(object):
comment = ""
except (KeyError, IndexError):
listo.append(
- PydReagent(type=item.strip(), lot=None, expiry=None, name=None, comment="", missing=True))
+ PydReagent(role=item.strip(), lot=None, expiry=None, name=None, comment="", missing=True))
continue
# NOTE: If the cell is blank tell the PydReagent
if check_not_nan(lot):
@@ -324,7 +325,7 @@ class ReagentParser(object):
logger.warning(f"name is not a string.")
check = True
if check:
- listo.append(dict(type=item.strip(), lot=lot, expiry=expiry, name=name, comment=comment,
+ listo.append(dict(role=item.strip(), lot=lot, expiry=expiry, name=name, comment=comment,
missing=missing))
return listo
diff --git a/src/submissions/backend/validators/__init__.py b/src/submissions/backend/validators/__init__.py
index b4c536c..f9cafb9 100644
--- a/src/submissions/backend/validators/__init__.py
+++ b/src/submissions/backend/validators/__init__.py
@@ -178,5 +178,5 @@ class RSLNamer(object):
return template.render(**kwargs)
-from .pydant import PydSubmission, PydKit, PydContact, PydOrganization, PydSample, PydReagent, PydReagentType, \
+from .pydant import PydSubmission, PydKit, PydContact, PydOrganization, PydSample, PydReagent, PydReagentRole, \
PydEquipment, PydEquipmentRole
diff --git a/src/submissions/backend/validators/pydant.py b/src/submissions/backend/validators/pydant.py
index 0a75902..228298c 100644
--- a/src/submissions/backend/validators/pydant.py
+++ b/src/submissions/backend/validators/pydant.py
@@ -25,7 +25,7 @@ logger = logging.getLogger(f"submissions.{__name__}")
class PydReagent(BaseModel):
lot: str | None
- type: str | None
+ role: str | None
expiry: date | Literal['NA'] | None
name: str | None
missing: bool = Field(default=True)
@@ -38,7 +38,7 @@ class PydReagent(BaseModel):
return ""
return value
- @field_validator("type", mode='before')
+ @field_validator("role", mode='before')
@classmethod
def remove_undesired_types(cls, value):
match value:
@@ -47,7 +47,7 @@ class PydReagent(BaseModel):
case _:
return value
- @field_validator("type")
+ @field_validator("role")
@classmethod
def rescue_type_with_lookup(cls, value, values):
if value == None and values.data['lot'] != None:
@@ -147,10 +147,10 @@ class PydReagent(BaseModel):
match key:
case "lot":
reagent.lot = value.upper()
- case "type":
- reagent_type = ReagentType.query(name=value)
- if reagent_type != None:
- reagent.type.append(reagent_type)
+ case "role":
+ reagent_role = ReagentRole.query(name=value)
+ if reagent_role is not None:
+ reagent.role.append(reagent_role)
case "comment":
continue
case "expiry":
@@ -792,11 +792,11 @@ class PydSubmission(BaseModel, extra='allow'):
# logger.debug(f"Kit reagents: {ext_kit_rtypes}")
# logger.debug(f"Submission reagents: {self.reagents}")
# Exclude any reagenttype found in this pyd not expected in kit.
- expected_check = [item.type for item in ext_kit_rtypes]
- output_reagents = [rt for rt in self.reagents if rt.type in expected_check]
+ expected_check = [item.role for item in ext_kit_rtypes]
+ output_reagents = [rt for rt in self.reagents if rt.role in expected_check]
# logger.debug(f"Already have these reagent types: {output_reagents}")
- missing_check = [item.type for item in output_reagents]
- missing_reagents = [rt for rt in ext_kit_rtypes if rt.type not in missing_check]
+ missing_check = [item.role for item in output_reagents]
+ missing_reagents = [rt for rt in ext_kit_rtypes if rt.role not in missing_check]
missing_reagents += [rt for rt in output_reagents if rt.missing]
output_reagents += [rt for rt in missing_reagents if rt not in output_reagents]
# logger.debug(f"Missing reagents types: {missing_reagents}")
@@ -805,7 +805,7 @@ class PydSubmission(BaseModel, extra='allow'):
result = None
else:
result = Result(
- msg=f"The excel sheet you are importing is missing some reagents expected by the kit.\n\nIt looks like you are missing: {[item.type.upper() for item in missing_reagents]}\n\nAlternatively, you may have set the wrong extraction kit.\n\nThe program will populate lists using existing reagents.\n\nPlease make sure you check the lots carefully!",
+ msg=f"The excel sheet you are importing is missing some reagents expected by the kit.\n\nIt looks like you are missing: {[item.role.upper() for item in missing_reagents]}\n\nAlternatively, you may have set the wrong extraction kit.\n\nThe program will populate lists using existing reagents.\n\nPlease make sure you check the lots carefully!",
status="Warning")
report.add_result(result)
return output_reagents, report
@@ -850,7 +850,7 @@ class PydOrganization(BaseModel):
return instance
-class PydReagentType(BaseModel):
+class PydReagentRole(BaseModel):
name: str
eol_ext: timedelta | int | None
uses: dict | None
@@ -863,33 +863,33 @@ class PydReagentType(BaseModel):
return timedelta(days=value)
return value
- def toSQL(self, kit: KitType) -> ReagentType:
+ def toSQL(self, kit: KitType) -> ReagentRole:
"""
Converts this instance into a backend.db.models.ReagentType instance
Args:
- kit (KitType): KitType joined to the reagenttype
+ kit (KitType): KitType joined to the reagentrole
Returns:
- ReagentType: ReagentType instance
+ ReagentRole: ReagentType instance
"""
- instance: ReagentType = ReagentType.query(name=self.name)
+ instance: ReagentRole = ReagentRole.query(name=self.name)
if instance == None:
- instance = ReagentType(name=self.name, eol_ext=self.eol_ext)
+ instance = ReagentRole(name=self.name, eol_ext=self.eol_ext)
# logger.debug(f"This is the reagent type instance: {instance.__dict__}")
try:
- assoc = KitTypeReagentTypeAssociation.query(reagent_type=instance, kit_type=kit)
+ assoc = KitTypeReagentRoleAssociation.query(reagent_role=instance, kit_type=kit)
except StatementError:
assoc = None
if assoc == None:
- assoc = KitTypeReagentTypeAssociation(kit_type=kit, reagent_type=instance, uses=self.uses,
+ assoc = KitTypeReagentRoleAssociation(kit_type=kit, reagent_role=instance, uses=self.uses,
required=self.required)
return instance
class PydKit(BaseModel):
name: str
- reagent_types: List[PydReagentType] = []
+ reagent_roles: List[PydReagentRole] = []
def toSQL(self) -> Tuple[KitType, Report]:
"""
@@ -902,7 +902,7 @@ class PydKit(BaseModel):
instance = KitType.query(name=self.name)
if instance == None:
instance = KitType(name=self.name)
- [item.toSQL(instance) for item in self.reagent_types]
+ [item.toSQL(instance) for item in self.reagent_roles]
return instance, report
diff --git a/src/submissions/frontend/widgets/kit_creator.py b/src/submissions/frontend/widgets/kit_creator.py
index 8f43444..4e23455 100644
--- a/src/submissions/frontend/widgets/kit_creator.py
+++ b/src/submissions/frontend/widgets/kit_creator.py
@@ -5,8 +5,8 @@ from PyQt6.QtWidgets import (
QSpinBox, QDateEdit
)
from sqlalchemy import FLOAT, INTEGER
-from backend.db import SubmissionTypeKitTypeAssociation, SubmissionType, ReagentType
-from backend.validators import PydReagentType, PydKit
+from backend.db import SubmissionTypeKitTypeAssociation, SubmissionType, ReagentRole
+from backend.validators import PydReagentRole, PydKit
import logging
from pprint import pformat
from tools import Report
@@ -81,7 +81,7 @@ class KitAdder(QWidget):
"""
# get bottommost row
maxrow = self.grid.rowCount()
- reg_form = ReagentTypeForm(parent=self)
+ reg_form = ReagentRoleForm(parent=self)
reg_form.setObjectName(f"ReagentForm_{maxrow}")
self.grid.addWidget(reg_form, maxrow,0,1,4)
@@ -95,11 +95,11 @@ class KitAdder(QWidget):
info = {k:v for k,v in info.items() if k in [column.name for column in self.columns] + ['kit_name', 'used_for']}
# logger.debug(f"kit info: {pformat(info)}")
# logger.debug(f"kit reagents: {pformat(reagents)}")
- info['reagent_types'] = reagents
+ info['reagent_roles'] = reagents
# logger.debug(pformat(info))
# send to kit constructor
kit = PydKit(name=info['kit_name'])
- for reagent in info['reagent_types']:
+ for reagent in info['reagent_roles']:
uses = {
info['used_for']:
{'sheet':reagent['sheet'],
@@ -107,7 +107,7 @@ class KitAdder(QWidget):
'lot':reagent['lot'],
'expiry':reagent['expiry']
}}
- kit.reagent_types.append(PydReagentType(name=reagent['rtname'], eol_ext=reagent['eol'], uses=uses))
+ kit.reagent_roles.append(PydReagentRole(name=reagent['rtname'], eol_ext=reagent['eol'], uses=uses))
# logger.debug(f"Output pyd object: {kit.__dict__}")
sqlobj, result = kit.toSQL(self.ctx)
report.add_result(result=result)
@@ -125,11 +125,11 @@ class KitAdder(QWidget):
# logger.debug(f"Hello from {self.__class__} parser!")
info = {}
reagents = []
- widgets = [widget for widget in self.findChildren(QWidget) if widget.objectName() not in self.ignore and not isinstance(widget.parent(), ReagentTypeForm)]
+ widgets = [widget for widget in self.findChildren(QWidget) if widget.objectName() not in self.ignore and not isinstance(widget.parent(), ReagentRoleForm)]
for widget in widgets:
# logger.debug(f"Parsed widget: {widget.objectName()} of type {type(widget)} with parent {widget.parent()}")
match widget:
- case ReagentTypeForm():
+ case ReagentRoleForm():
reagents.append(widget.parse_form())
case QLineEdit():
info[widget.objectName()] = widget.text()
@@ -139,7 +139,7 @@ class KitAdder(QWidget):
info[widget.objectName()] = widget.date().toPyDate()
return info, reagents
-class ReagentTypeForm(QWidget):
+class ReagentRoleForm(QWidget):
"""
custom widget to add information about a new reagenttype
"""
@@ -152,13 +152,13 @@ class ReagentTypeForm(QWidget):
self.reagent_getter = QComboBox()
self.reagent_getter.setObjectName("rtname")
# lookup all reagent type names from db
- lookup = ReagentType.query()
+ lookup = ReagentRole.query()
# logger.debug(f"Looked up ReagentType names: {lookup}")
self.reagent_getter.addItems([item.name for item in lookup])
self.reagent_getter.setEditable(True)
grid.addWidget(self.reagent_getter,0,1)
grid.addWidget(QLabel("Extension of Life (months):"),0,2)
- # widget to get extension of life
+ # NOTE: widget to get extension of life
self.eol = QSpinBox()
self.eol.setObjectName('eol')
self.eol.setMinimum(0)
diff --git a/src/submissions/frontend/widgets/misc.py b/src/submissions/frontend/widgets/misc.py
index 3d6ae79..e0e84b2 100644
--- a/src/submissions/frontend/widgets/misc.py
+++ b/src/submissions/frontend/widgets/misc.py
@@ -23,10 +23,10 @@ class AddReagentForm(QDialog):
"""
dialog to add gather info about new reagent
"""
- def __init__(self, reagent_lot:str|None=None, reagent_type:str|None=None, expiry:date|None=None, reagent_name:str|None=None) -> None:
+ def __init__(self, reagent_lot:str|None=None, reagent_role: str | None=None, expiry: date | None=None, reagent_name: str | None=None) -> None:
super().__init__()
if reagent_lot == None:
- reagent_lot = reagent_type
+ reagent_lot = reagent_role
self.setWindowTitle("Add Reagent")
@@ -57,15 +57,15 @@ class AddReagentForm(QDialog):
# widget to get reagent type info
self.type_input = QComboBox()
self.type_input.setObjectName('type')
- self.type_input.addItems([item.name for item in ReagentType.query()])
+ self.type_input.addItems([item.name for item in ReagentRole.query()])
# logger.debug(f"Trying to find index of {reagent_type}")
# convert input to user friendly string?
try:
- reagent_type = reagent_type.replace("_", " ").title()
+ reagent_role = reagent_role.replace("_", " ").title()
except AttributeError:
- reagent_type = None
+ reagent_role = None
# set parsed reagent type to top of list
- index = self.type_input.findText(reagent_type, Qt.MatchFlag.MatchEndsWith)
+ index = self.type_input.findText(reagent_role, Qt.MatchFlag.MatchEndsWith)
if index >= 0:
self.type_input.setCurrentIndex(index)
self.layout = QVBoxLayout()
@@ -91,7 +91,7 @@ class AddReagentForm(QDialog):
return dict(name=self.name_input.currentText().strip(),
lot=self.lot_input.text().strip(),
expiry=self.exp_input.date().toPyDate(),
- type=self.type_input.currentText().strip())
+ role=self.type_input.currentText().strip())
def update_names(self):
"""
@@ -99,7 +99,7 @@ class AddReagentForm(QDialog):
"""
# logger.debug(self.type_input.currentText())
self.name_input.clear()
- lookup = Reagent.query(reagent_type=self.type_input.currentText())
+ lookup = Reagent.query(reagent_role=self.type_input.currentText())
self.name_input.addItems(list(set([item.name for item in lookup])))
class ReportDatePicker(QDialog):
diff --git a/src/submissions/frontend/widgets/submission_widget.py b/src/submissions/frontend/widgets/submission_widget.py
index a5ba527..07b2966 100644
--- a/src/submissions/frontend/widgets/submission_widget.py
+++ b/src/submissions/frontend/widgets/submission_widget.py
@@ -14,7 +14,7 @@ from backend.excel.parser import SheetParser
from backend.validators import PydSubmission, PydReagent
from backend.db import (
KitType, Organization, SubmissionType, Reagent,
- ReagentType, KitTypeReagentTypeAssociation
+ ReagentRole, KitTypeReagentRoleAssociation
)
from pprint import pformat
from .pop_ups import QuestionAsker, AlertPop
@@ -112,14 +112,14 @@ class SubmissionFormContainer(QWidget):
# logger.debug(f"Outgoing report: {self.report.results}")
# logger.debug(f"All attributes of submission container:\n{pformat(self.__dict__)}")
- def add_reagent(self, reagent_lot: str | None = None, reagent_type: str | None = None, expiry: date | None = None,
+ def add_reagent(self, reagent_lot: str | None = None, reagent_role: str | None = None, expiry: date | None = None,
name: str | None = None):
"""
Action to create new reagent in DB.
Args:
reagent_lot (str | None, optional): Parsed reagent from import form. Defaults to None.
- reagent_type (str | None, optional): Parsed reagent type from import form. Defaults to None.
+ reagent_role (str | None, optional): Parsed reagent type from import form. Defaults to None.
expiry (date | None, optional): Parsed reagent expiry data. Defaults to None.
name (str | None, optional): Parsed reagent name. Defaults to None.
@@ -130,7 +130,7 @@ class SubmissionFormContainer(QWidget):
if isinstance(reagent_lot, bool):
reagent_lot = ""
# NOTE: create form
- dlg = AddReagentForm(reagent_lot=reagent_lot, reagent_type=reagent_type, expiry=expiry, reagent_name=name)
+ dlg = AddReagentForm(reagent_lot=reagent_lot, reagent_role=reagent_role, expiry=expiry, reagent_name=name)
if dlg.exec():
# extract form info
info = dlg.parse_form()
@@ -581,13 +581,13 @@ class SubmissionFormWidget(QWidget):
"""
lot = self.lot.currentText()
# logger.debug(f"Using this lot for the reagent {self.reagent}: {lot}")
- wanted_reagent = Reagent.query(lot_number=lot, reagent_type=self.reagent.type)
+ wanted_reagent = Reagent.query(lot_number=lot, reagent_role=self.reagent.role)
# NOTE: if reagent doesn't exist in database, offer to add it (uses App.add_reagent)
if wanted_reagent == None:
dlg = QuestionAsker(title=f"Add {lot}?",
message=f"Couldn't find reagent type {self.reagent.type}: {lot} in the database.\n\nWould you like to add it?")
if dlg.exec():
- wanted_reagent = self.parent().parent().add_reagent(reagent_lot=lot, reagent_type=self.reagent.type,
+ wanted_reagent = self.parent().parent().add_reagent(reagent_lot=lot, reagent_role=self.reagent.role,
expiry=self.reagent.expiry,
name=self.reagent.name)
return wanted_reagent, None
@@ -598,10 +598,10 @@ class SubmissionFormWidget(QWidget):
else:
# NOTE: Since this now gets passed in directly from the parser -> pyd -> form and the parser gets the name
# from the db, it should no longer be necessary to query the db with reagent/kit, but with rt name directly.
- rt = ReagentType.query(name=self.reagent.type)
+ rt = ReagentRole.query(name=self.reagent.role)
if rt == None:
- rt = ReagentType.query(kit_type=self.extraction_kit, reagent=wanted_reagent)
- return PydReagent(name=wanted_reagent.name, lot=wanted_reagent.lot, type=rt.name,
+ rt = ReagentRole.query(kit_type=self.extraction_kit, reagent=wanted_reagent)
+ return PydReagent(name=wanted_reagent.name, lot=wanted_reagent.lot, role=rt.name,
expiry=wanted_reagent.expiry, missing=False), None
def updated(self):
@@ -619,20 +619,20 @@ class SubmissionFormWidget(QWidget):
check = not reagent.missing
except:
check = False
- self.setObjectName(f"{reagent.type}_label")
+ self.setObjectName(f"{reagent.role}_label")
if check:
- self.setText(f"Parsed {reagent.type}")
+ self.setText(f"Parsed {reagent.role}")
else:
- self.setText(f"MISSING {reagent.type}")
+ self.setText(f"MISSING {reagent.role}")
- def updated(self, reagent_type: str):
+ def updated(self, reagent_role: str):
"""
Marks widget as updated
Args:
- reagent_type (str): _description_
+ reagent_role (str): _description_
"""
- self.setText(f"UPDATED {reagent_type}")
+ self.setText(f"UPDATED {reagent_role}")
class ReagentLot(QComboBox):
@@ -641,7 +641,7 @@ class SubmissionFormWidget(QWidget):
self.setEditable(True)
# logger.debug(f"Attempting lookup of reagents by type: {reagent.type}")
# NOTE: below was lookup_reagent_by_type_name_and_kit_name, but I couldn't get it to work.
- lookup = Reagent.query(reagent_type=reagent.type)
+ lookup = Reagent.query(reagent_role=reagent.role)
relevant_reagents = [str(item.lot) for item in lookup]
output_reg = []
for rel_reagent in relevant_reagents:
@@ -658,7 +658,7 @@ class SubmissionFormWidget(QWidget):
if check_not_nan(reagent.lot):
relevant_reagents.insert(0, str(reagent.lot))
else:
- looked_up_rt = KitTypeReagentTypeAssociation.query(reagent_type=reagent.type,
+ looked_up_rt = KitTypeReagentRoleAssociation.query(reagent_role=reagent.role,
kit_type=extraction_kit)
try:
looked_up_reg = Reagent.query(lot_number=looked_up_rt.last_used)
@@ -684,5 +684,5 @@ class SubmissionFormWidget(QWidget):
# logger.debug(f"Found {reagent.lot} in relevant reagents: {relevant_reagents}. But no need to move due to short list.")
pass
# logger.debug(f"New relevant reagents: {relevant_reagents}")
- self.setObjectName(f"lot_{reagent.type}")
+ self.setObjectName(f"lot_{reagent.role}")
self.addItems(relevant_reagents)
diff --git a/src/submissions/templates/basicsubmission_details.html b/src/submissions/templates/basicsubmission_details.html
index 1633875..cc87dfb 100644
--- a/src/submissions/templates/basicsubmission_details.html
+++ b/src/submissions/templates/basicsubmission_details.html
@@ -47,7 +47,7 @@
{% endfor %}
Reagents:
{% for item in sub['reagents'] %}
- {{ item['type'] }}: {{ item['lot'] }} (EXP: {{ item['expiry'] }})
+ {{ item['role'] }}: {{ item['lot'] }} (EXP: {{ item['expiry'] }})
{% endfor %}
{% if sub['equipment'] %}
Equipment: