Updating AddEdit to hopefully include ReagentAdd
This commit is contained in:
@@ -1,3 +1,11 @@
|
|||||||
|
# 202501.02
|
||||||
|
|
||||||
|
- Fixed bug where Wastewater ENs were not receiving rsl_number and therefore not getting PCR data.
|
||||||
|
|
||||||
|
# 202501.01
|
||||||
|
|
||||||
|
- Created Client Manager to be run by super users.
|
||||||
|
|
||||||
# 202412.06
|
# 202412.06
|
||||||
|
|
||||||
- Switched startup/teardown scripts to importlib/getattr addition to ctx.
|
- Switched startup/teardown scripts to importlib/getattr addition to ctx.
|
||||||
|
|||||||
1
TODO.md
1
TODO.md
@@ -1,3 +1,4 @@
|
|||||||
|
- [ ] Find a way to merge AddEdit with ReagentAdder
|
||||||
- [x] Find a way to merge omni_search and sample_search
|
- [x] Find a way to merge omni_search and sample_search
|
||||||
- [x] Allow parsing of custom fields to a json 'custom' field in _basicsubmissions
|
- [x] Allow parsing of custom fields to a json 'custom' field in _basicsubmissions
|
||||||
- [x] Upgrade to generators when returning lists.
|
- [x] Upgrade to generators when returning lists.
|
||||||
|
|||||||
@@ -608,7 +608,7 @@ class Reagent(BaseClass, LogMixin):
|
|||||||
if isinstance(value, str):
|
if isinstance(value, str):
|
||||||
field_value = datetime.strptime(value, "%Y-%m-%d")
|
field_value = datetime.strptime(value, "%Y-%m-%d")
|
||||||
elif isinstance(value, date):
|
elif isinstance(value, date):
|
||||||
field_value = datetime.combine(value, datetime.min.time())
|
field_value = datetime.combine(value, datetime.max.time())
|
||||||
else:
|
else:
|
||||||
field_value = value
|
field_value = value
|
||||||
field_value.replace(tzinfo=timezone)
|
field_value.replace(tzinfo=timezone)
|
||||||
|
|||||||
@@ -1502,6 +1502,25 @@ class Wastewater(BasicSubmission):
|
|||||||
logger.error(f"Error handling couldn't get csv due to: {e}")
|
logger.error(f"Error handling couldn't get csv due to: {e}")
|
||||||
return input_dict
|
return input_dict
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def parse_samples(cls, input_dict: dict) -> dict:
|
||||||
|
"""
|
||||||
|
Update sample dictionary with type specific information. Extends parent
|
||||||
|
|
||||||
|
Args:
|
||||||
|
input_dict (dict): Input sample dictionary
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
dict: Updated sample dictionary
|
||||||
|
"""
|
||||||
|
input_dict = super().parse_samples(input_dict=input_dict)
|
||||||
|
# NOTE: Had to put in this section due to ENs not having rsl_number and therefore not getting PCR results.
|
||||||
|
check = check_key_or_attr("rsl_number", input_dict)
|
||||||
|
if not check:
|
||||||
|
input_dict['rsl_number'] = input_dict['submitter_id']
|
||||||
|
# logger.debug(pformat(input_dict, indent=4))
|
||||||
|
return input_dict
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def parse_pcr(cls, xl: Workbook, rsl_plate_num: str) -> Generator[dict, None, None]:
|
def parse_pcr(cls, xl: Workbook, rsl_plate_num: str) -> Generator[dict, None, None]:
|
||||||
"""
|
"""
|
||||||
@@ -1633,6 +1652,7 @@ class Wastewater(BasicSubmission):
|
|||||||
self.save(original=False)
|
self.save(original=False)
|
||||||
for sample in self.samples:
|
for sample in self.samples:
|
||||||
try:
|
try:
|
||||||
|
# NOTE: Fix for ENs which have no rsl_number...
|
||||||
sample_dict = next(item for item in pcr_samples if item['sample'] == sample.rsl_number)
|
sample_dict = next(item for item in pcr_samples if item['sample'] == sample.rsl_number)
|
||||||
except StopIteration:
|
except StopIteration:
|
||||||
continue
|
continue
|
||||||
@@ -2539,7 +2559,7 @@ class WastewaterSample(BasicSample):
|
|||||||
Custom sample parser. Extends parent
|
Custom sample parser. Extends parent
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
input_dict (dict): Basic parser results.
|
input_dict (dict): Basic parser results for this sample.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
dict: Updated parser results.
|
dict: Updated parser results.
|
||||||
@@ -2554,6 +2574,8 @@ class WastewaterSample(BasicSample):
|
|||||||
output_dict['rsl_number'] = "RSL-WW-" + output_dict['ww_processing_num']
|
output_dict['rsl_number'] = "RSL-WW-" + output_dict['ww_processing_num']
|
||||||
if output_dict['ww_full_sample_id'] is not None and output_dict["submitter_id"] in disallowed:
|
if output_dict['ww_full_sample_id'] is not None and output_dict["submitter_id"] in disallowed:
|
||||||
output_dict["submitter_id"] = output_dict['ww_full_sample_id']
|
output_dict["submitter_id"] = output_dict['ww_full_sample_id']
|
||||||
|
check = check_key_or_attr("rsl_number", output_dict, check_none=True)
|
||||||
|
# logger.debug(pformat(output_dict, indent=4))
|
||||||
return output_dict
|
return output_dict
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|||||||
@@ -144,7 +144,9 @@ class PydReagent(BaseModel):
|
|||||||
case "expiry":
|
case "expiry":
|
||||||
if isinstance(value, str):
|
if isinstance(value, str):
|
||||||
value = date(year=1970, month=1, day=1)
|
value = date(year=1970, month=1, day=1)
|
||||||
value = datetime.combine(value, datetime.min.time())
|
# NOTE: if min time is used, any reagent set to expire today (Bac postive control, eg) will have expired at midnight and therefore be flagged.
|
||||||
|
# NOTE: Make expiry at date given, plus now time + 1 hour
|
||||||
|
value = datetime.combine(value, datetime.max.time())
|
||||||
reagent.expiry = value.replace(tzinfo=timezone)
|
reagent.expiry = value.replace(tzinfo=timezone)
|
||||||
case _:
|
case _:
|
||||||
try:
|
try:
|
||||||
@@ -826,7 +828,7 @@ class PydSubmission(BaseModel, extra='allow'):
|
|||||||
case item if item in instance.timestamps():
|
case item if item in instance.timestamps():
|
||||||
logger.warning(f"Incoming timestamp key: {item}, with value: {value}")
|
logger.warning(f"Incoming timestamp key: {item}, with value: {value}")
|
||||||
if isinstance(value, date):
|
if isinstance(value, date):
|
||||||
value = datetime.combine(value, datetime.min.time())
|
value = datetime.combine(value, datetime.max.time())
|
||||||
value = value.replace(tzinfo=timezone)
|
value = value.replace(tzinfo=timezone)
|
||||||
elif isinstance(value, str):
|
elif isinstance(value, str):
|
||||||
value: datetime = datetime.strptime(value, "%Y-%m-%d")
|
value: datetime = datetime.strptime(value, "%Y-%m-%d")
|
||||||
@@ -961,7 +963,7 @@ class PydSubmission(BaseModel, extra='allow'):
|
|||||||
if reagent not in exempt:
|
if reagent not in exempt:
|
||||||
role_expiry = ReagentRole.query(name=reagent.role).eol_ext
|
role_expiry = ReagentRole.query(name=reagent.role).eol_ext
|
||||||
try:
|
try:
|
||||||
dt = datetime.combine(reagent.expiry, datetime.min.time())
|
dt = datetime.combine(reagent.expiry, datetime.max.time())
|
||||||
except TypeError:
|
except TypeError:
|
||||||
continue
|
continue
|
||||||
if datetime.now() > dt + role_expiry:
|
if datetime.now() > dt + role_expiry:
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ class App(QMainWindow):
|
|||||||
connect menu and tool bar item to functions
|
connect menu and tool bar item to functions
|
||||||
"""
|
"""
|
||||||
self.importAction.triggered.connect(self.table_widget.formwidget.importSubmission)
|
self.importAction.triggered.connect(self.table_widget.formwidget.importSubmission)
|
||||||
self.addReagentAction.triggered.connect(self.table_widget.formwidget.add_reagent)
|
self.addReagentAction.triggered.connect(self.table_widget.formwidget.new_add_reagent)
|
||||||
self.joinExtractionAction.triggered.connect(self.table_widget.sub_wid.link_extractions)
|
self.joinExtractionAction.triggered.connect(self.table_widget.sub_wid.link_extractions)
|
||||||
self.joinPCRAction.triggered.connect(self.table_widget.sub_wid.link_pcr)
|
self.joinPCRAction.triggered.connect(self.table_widget.sub_wid.link_pcr)
|
||||||
self.helpAction.triggered.connect(self.showAbout)
|
self.helpAction.triggered.connect(self.showAbout)
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
from datetime import date
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from PyQt6.QtWidgets import (
|
from PyQt6.QtWidgets import (
|
||||||
@@ -12,7 +13,7 @@ logger = logging.getLogger(f"submissions.{__name__}")
|
|||||||
|
|
||||||
class AddEdit(QDialog):
|
class AddEdit(QDialog):
|
||||||
|
|
||||||
def __init__(self, parent, instance: Any):
|
def __init__(self, parent, instance: Any|None=None):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
self.instance = instance
|
self.instance = instance
|
||||||
self.object_type = instance.__class__
|
self.object_type = instance.__class__
|
||||||
@@ -22,13 +23,16 @@ class AddEdit(QDialog):
|
|||||||
self.buttonBox = QDialogButtonBox(QBtn)
|
self.buttonBox = QDialogButtonBox(QBtn)
|
||||||
self.buttonBox.accepted.connect(self.accept)
|
self.buttonBox.accepted.connect(self.accept)
|
||||||
self.buttonBox.rejected.connect(self.reject)
|
self.buttonBox.rejected.connect(self.reject)
|
||||||
fields = {k: v for k, v in self.object_type.__dict__.items() if
|
# fields = {k: v for k, v in self.object_type.__dict__.items() if
|
||||||
isinstance(v, InstrumentedAttribute) and k != "id"}
|
# isinstance(v, InstrumentedAttribute) and k != "id"}
|
||||||
|
fields = {k: v for k, v in self.object_type.__dict__.items() if k != "id"}
|
||||||
for key, field in fields.items():
|
for key, field in fields.items():
|
||||||
|
logger.debug(f"")
|
||||||
try:
|
try:
|
||||||
widget = EditProperty(self, key=key, column_type=field.property.expression.type,
|
widget = EditProperty(self, key=key, column_type=field.property.expression.type,
|
||||||
value=getattr(self.instance, key))
|
value=getattr(self.instance, key))
|
||||||
except AttributeError:
|
except AttributeError as e:
|
||||||
|
logger.error(f"Problem setting widget {key}: {e}")
|
||||||
continue
|
continue
|
||||||
self.layout.addWidget(widget, self.layout.rowCount(), 0)
|
self.layout.addWidget(widget, self.layout.rowCount(), 0)
|
||||||
self.layout.addWidget(self.buttonBox)
|
self.layout.addWidget(self.buttonBox)
|
||||||
@@ -62,14 +66,19 @@ class EditProperty(QWidget):
|
|||||||
self.setObjectName(key)
|
self.setObjectName(key)
|
||||||
match column_type:
|
match column_type:
|
||||||
case String():
|
case String():
|
||||||
|
if not value:
|
||||||
|
value = ""
|
||||||
self.widget = QLineEdit(self)
|
self.widget = QLineEdit(self)
|
||||||
self.widget.setText(value)
|
self.widget.setText(value)
|
||||||
case TIMESTAMP():
|
case TIMESTAMP():
|
||||||
self.widget = QDateEdit(self)
|
self.widget = QDateEdit(self, calendarPopup=True)
|
||||||
|
if not value:
|
||||||
|
value = date.today()
|
||||||
self.widget.setDate(value)
|
self.widget.setDate(value)
|
||||||
case _:
|
case _:
|
||||||
logger.error(f"{column_type} not a supported type.")
|
logger.error(f"{column_type} not a supported type.")
|
||||||
self.widget = None
|
self.widget = None
|
||||||
|
return
|
||||||
self.layout.addWidget(self.widget, 0, 1, 1, 3)
|
self.layout.addWidget(self.widget, 0, 1, 1, 3)
|
||||||
self.setLayout(self.layout)
|
self.setLayout(self.layout)
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ from backend.db import (
|
|||||||
from pprint import pformat
|
from pprint import pformat
|
||||||
from .pop_ups import QuestionAsker, AlertPop
|
from .pop_ups import QuestionAsker, AlertPop
|
||||||
from .misc import AddReagentForm
|
from .misc import AddReagentForm
|
||||||
|
from .omni_add_edit import AddEdit
|
||||||
from typing import List, Tuple
|
from typing import List, Tuple
|
||||||
from datetime import date
|
from datetime import date
|
||||||
|
|
||||||
@@ -139,6 +140,15 @@ class SubmissionFormContainer(QWidget):
|
|||||||
self.layout().addWidget(self.form)
|
self.layout().addWidget(self.form)
|
||||||
return report
|
return report
|
||||||
|
|
||||||
|
|
||||||
|
def new_add_reagent(self):
|
||||||
|
instance = Reagent()
|
||||||
|
dlg = AddEdit(parent=self, instance=instance)
|
||||||
|
if dlg.exec():
|
||||||
|
obj = dlg.parse_form()
|
||||||
|
print(obj)
|
||||||
|
|
||||||
|
|
||||||
@report_result
|
@report_result
|
||||||
def add_reagent(self, reagent_lot: str | None = None, reagent_role: 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, kit: str | KitType | None = None) -> Tuple[PydReagent, Report]:
|
name: str | None = None, kit: str | KitType | None = None) -> Tuple[PydReagent, Report]:
|
||||||
|
|||||||
@@ -449,7 +449,10 @@ class Settings(BaseSettings, extra="allow"):
|
|||||||
|
|
||||||
def set_from_db(self):
|
def set_from_db(self):
|
||||||
if 'pytest' in sys.modules:
|
if 'pytest' in sys.modules:
|
||||||
output = dict(power_users=['lwark', 'styson', 'ruwang'])
|
output = dict(power_users=['lwark', 'styson', 'ruwang'],
|
||||||
|
startup_scripts=dict(hello=None),
|
||||||
|
teardown_scripts=dict(goodbye=None)
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
# print(f"Hello from database settings getter.")
|
# print(f"Hello from database settings getter.")
|
||||||
# print(self.__dict__)
|
# print(self.__dict__)
|
||||||
|
|||||||
Reference in New Issue
Block a user