Added submission editting functionality.

This commit is contained in:
Landon Wark
2024-03-11 11:16:34 -05:00
parent 17572b4a55
commit 08988a14a0
3 changed files with 511 additions and 324 deletions

View File

@@ -1,3 +1,8 @@
## 202403.02
- Moved functions out of submission container to submission form
- Added submission editting functionality.
## 202403.01 ## 202403.01
- Added navigation in submission details to sample details. - Added navigation in submission details to sample details.

View File

@@ -426,9 +426,10 @@ class BasicSubmission(BaseClass):
dicto = self.to_dict(full_data=True, backup=backup) dicto = self.to_dict(full_data=True, backup=backup)
new_dict = {} new_dict = {}
for key, value in dicto.items(): for key, value in dicto.items():
missing = value is None or value == ""
match key: match key:
case "reagents": case "reagents":
new_dict[key] = [PydReagent(**reagent) for reagent in value] new_dict[key] = [PydReagent(**reagent, missing=False) for reagent in value]
case "samples": case "samples":
# samples = {k.lower().replace(" ", "_"):v for k,v in dicto['samples'].items()} # samples = {k.lower().replace(" ", "_"):v for k,v in dicto['samples'].items()}
new_dict[key] = [PydSample(**{k.lower().replace(" ", "_"):v for k,v in sample.items()}) for sample in dicto['samples']] new_dict[key] = [PydSample(**{k.lower().replace(" ", "_"):v for k,v in sample.items()}) for sample in dicto['samples']]
@@ -438,12 +439,12 @@ class BasicSubmission(BaseClass):
except TypeError as e: except TypeError as e:
logger.error(f"Possible no equipment error: {e}") logger.error(f"Possible no equipment error: {e}")
case "Plate Number": case "Plate Number":
new_dict['rsl_plate_num'] = dict(value=value, missing=True) new_dict['rsl_plate_num'] = dict(value=value, missing=missing)
case "Submitter Plate Number": case "Submitter Plate Number":
new_dict['submitter_plate_num'] = dict(value=value, missing=True) new_dict['submitter_plate_num'] = dict(value=value, missing=missing)
case _: case _:
logger.debug(f"Setting dict {key} to {value}") logger.debug(f"Setting dict {key} to {value}")
new_dict[key.lower().replace(" ", "_")] = dict(value=value, missing=True) new_dict[key.lower().replace(" ", "_")] = dict(value=value, missing=missing)
new_dict['filepath'] = Path(tempfile.TemporaryFile().name) new_dict['filepath'] = Path(tempfile.TemporaryFile().name)
return PydSubmission(**new_dict) return PydSubmission(**new_dict)

View File

@@ -65,48 +65,48 @@ class SubmissionFormContainer(QWidget):
self.report = Report() self.report = Report()
self.app.result_reporter() self.app.result_reporter()
def scrape_reagents(self, *args, **kwargs): # def scrape_reagents(self, *args, **kwargs):
""" # """
Called when a reagent is changed. # Called when a reagent is changed.
""" # """
caller = inspect.stack()[1].function.__repr__().replace("'", "") # caller = inspect.stack()[1].function.__repr__().replace("'", "")
logger.debug(f"Args: {args}, kwargs: {kwargs}") # logger.debug(f"Args: {args}, kwargs: {kwargs}")
self.scrape_reagents_function(args[0], caller=caller) # self.scrape_reagents_function(args[0], caller=caller)
self.kit_integrity_completion() # self.kit_integrity_completion()
self.app.report.add_result(self.report) # self.app.report.add_result(self.report)
self.report = Report() # self.report = Report()
match inspect.stack()[1].function.__repr__(): # match inspect.stack()[1].function.__repr__():
case "import_submission_function": # case "import_submission_function":
pass # pass
case _: # case _:
self.app.result_reporter() # self.app.result_reporter()
def kit_integrity_completion(self): # def kit_integrity_completion(self):
""" # """
Performs check of imported reagents # Performs check of imported reagents
NOTE: this will not change self.reagents which should be fine # NOTE: this will not change self.reagents which should be fine
since it's only used when looking up # since it's only used when looking up
""" # """
self.kit_integrity_completion_function() # self.kit_integrity_completion_function()
self.app.report.add_result(self.report) # self.app.report.add_result(self.report)
self.report = Report() # self.report = Report()
match inspect.stack()[1].function.__repr__(): # match inspect.stack()[1].function.__repr__():
case "import_submission_function": # case "import_submission_function":
pass # pass
case _: # case _:
self.app.result_reporter() # self.app.result_reporter()
def submit_new_sample(self): # def submit_new_sample(self):
""" # """
Attempt to add sample to database when 'submit' button clicked # Attempt to add sample to database when 'submit' button clicked
""" # """
self.submit_new_sample_function() # self.submit_new_sample_function()
self.app.report.add_result(self.report) # self.app.report.add_result(self.report)
self.report = Report() # self.report = Report()
self.app.result_reporter() # self.app.result_reporter()
def export_csv(self, fname:Path|None=None): # def export_csv(self, fname:Path|None=None):
self.export_csv_function(fname) # self.export_csv_function(fname)
def import_submission_function(self, fname:Path|None=None): def import_submission_function(self, fname:Path|None=None):
""" """
@@ -159,168 +159,168 @@ class SubmissionFormContainer(QWidget):
logger.debug(f"Outgoing report: {self.report.results}") logger.debug(f"Outgoing report: {self.report.results}")
logger.debug(f"All attributes of submission container:\n{pformat(self.__dict__)}") logger.debug(f"All attributes of submission container:\n{pformat(self.__dict__)}")
def scrape_reagents_function(self, extraction_kit:str, caller:str|None=None): # def scrape_reagents_function(self, extraction_kit:str, caller:str|None=None):
""" # """
Extracted scrape reagents function that will run when # Extracted scrape reagents function that will run when
form 'extraction_kit' widget is updated. # form 'extraction_kit' widget is updated.
Args: # Args:
obj (QMainWindow): updated main application # obj (QMainWindow): updated main application
extraction_kit (str): name of extraction kit (in 'extraction_kit' widget) # extraction_kit (str): name of extraction kit (in 'extraction_kit' widget)
Returns: # Returns:
Tuple[QMainWindow, dict]: Updated application and result # Tuple[QMainWindow, dict]: Updated application and result
""" # """
self.form.reagents = [] # self.form.reagents = []
logger.debug(f"\n\n{caller}\n\n") # logger.debug(f"\n\n{caller}\n\n")
report = Report() # report = Report()
logger.debug(f"Extraction kit: {extraction_kit}") # logger.debug(f"Extraction kit: {extraction_kit}")
# Remove previous reagent widgets # # Remove previous reagent widgets
try: # try:
old_reagents = self.form.find_widgets() # old_reagents = self.form.find_widgets()
except AttributeError: # except AttributeError:
logger.error(f"Couldn't find old reagents.") # logger.error(f"Couldn't find old reagents.")
old_reagents = [] # old_reagents = []
# logger.debug(f"\n\nAttempting to clear: {old_reagents}\n\n") # # logger.debug(f"\n\nAttempting to clear: {old_reagents}\n\n")
for reagent in old_reagents: # for reagent in old_reagents:
if isinstance(reagent, ReagentFormWidget) or isinstance(reagent, QPushButton): # if isinstance(reagent, ReagentFormWidget) or isinstance(reagent, QPushButton):
reagent.setParent(None) # reagent.setParent(None)
match caller: # match caller:
case "import_submission_function": # case "import_submission_function":
self.form.reagents = self.prsr.sub['reagents'] # self.form.reagents = self.prsr.sub['reagents']
case _: # case _:
already_have = [reagent for reagent in self.prsr.sub['reagents'] if not reagent.missing] # already_have = [reagent for reagent in self.prsr.sub['reagents'] if not reagent.missing]
names = list(set([item.type for item in already_have])) # names = list(set([item.type for item in already_have]))
logger.debug(f"reagents: {already_have}") # logger.debug(f"reagents: {already_have}")
reagents = [item.to_pydantic() for item in KitType.query(name=extraction_kit).get_reagents(submission_type=self.pyd.submission_type) if item.name not in names] # reagents = [item.to_pydantic() for item in KitType.query(name=extraction_kit).get_reagents(submission_type=self.pyd.submission_type) if item.name not in names]
self.form.reagents = already_have + reagents # self.form.reagents = already_have + reagents
# logger.debug(f"Imported reagents: {obj.reagents}") # # logger.debug(f"Imported reagents: {obj.reagents}")
# logger.debug(f"Missing reagents: {obj.missing_reagents}") # # logger.debug(f"Missing reagents: {obj.missing_reagents}")
self.report.add_result(report) # self.report.add_result(report)
logger.debug(f"Outgoing report: {self.report.results}") # logger.debug(f"Outgoing report: {self.report.results}")
def kit_integrity_completion_function(self): # def kit_integrity_completion_function(self):
""" # """
Compare kit contents to parsed contents # Compare kit contents to parsed contents
Args: # Args:
obj (QMainWindow): The original app window # obj (QMainWindow): The original app window
Returns: # Returns:
Tuple[QMainWindow, dict]: Collection of new main app window and result dict # Tuple[QMainWindow, dict]: Collection of new main app window and result dict
""" # """
report = Report() # report = Report()
missing_reagents = [] # missing_reagents = []
# logger.debug(inspect.currentframe().f_back.f_code.co_name) # # logger.debug(inspect.currentframe().f_back.f_code.co_name)
# find the widget that contains kit info # # find the widget that contains kit info
kit_widget = self.form.find_widgets(object_name="extraction_kit")[0].input # kit_widget = self.form.find_widgets(object_name="extraction_kit")[0].input
logger.debug(f"Kit selector: {kit_widget}") # logger.debug(f"Kit selector: {kit_widget}")
# get current kit being used # # get current kit being used
self.ext_kit = kit_widget.currentText() # self.ext_kit = kit_widget.currentText()
for reagent in self.form.reagents: # for reagent in self.form.reagents:
logger.debug(f"Creating widget for {reagent}") # logger.debug(f"Creating widget for {reagent}")
add_widget = ReagentFormWidget(parent=self, reagent=reagent, extraction_kit=self.ext_kit) # add_widget = ReagentFormWidget(parent=self, reagent=reagent, extraction_kit=self.ext_kit)
# self.form.layout().addWidget(add_widget) # # self.form.layout().addWidget(add_widget)
self.form.layout.addWidget(add_widget) # self.form.layout.addWidget(add_widget)
if reagent.missing: # if reagent.missing:
missing_reagents.append(reagent) # missing_reagents.append(reagent)
logger.debug(f"Checking integrity of {self.ext_kit}") # logger.debug(f"Checking integrity of {self.ext_kit}")
# TODO: put check_kit_integrity here instead of what's here? # # TODO: put check_kit_integrity here instead of what's here?
# see if there are any missing reagents # # see if there are any missing reagents
if len(missing_reagents) > 0: # if len(missing_reagents) > 0:
result = Result(msg=f"""The submission you are importing is missing some reagents expected by the kit.\n\n # result = Result(msg=f"""The submission you are importing is missing some reagents expected by the kit.\n\n
It looks like you are missing: {[item.type.upper() for item in missing_reagents]}\n\n # It looks like you are missing: {[item.type.upper() for item in missing_reagents]}\n\n
Alternatively, you may have set the wrong extraction kit.\n\nThe program will populate lists using existing reagents. # Alternatively, 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!""".replace(" ", ""), status="Warning") # \n\nPlease make sure you check the lots carefully!""".replace(" ", ""), status="Warning")
report.add_result(result) # report.add_result(result)
if hasattr(self.pyd, "csv"): # if hasattr(self.pyd, "csv"):
export_csv_btn = QPushButton("Export CSV") # export_csv_btn = QPushButton("Export CSV")
export_csv_btn.setObjectName("export_csv_btn") # export_csv_btn.setObjectName("export_csv_btn")
self.form.layout().addWidget(export_csv_btn) # self.form.layout().addWidget(export_csv_btn)
export_csv_btn.clicked.connect(self.export_csv) # export_csv_btn.clicked.connect(self.export_csv)
submit_btn = QPushButton("Submit") # submit_btn = QPushButton("Submit")
submit_btn.setObjectName("submit_btn") # submit_btn.setObjectName("submit_btn")
self.form.layout().addWidget(submit_btn) # self.form.layout().addWidget(submit_btn)
submit_btn.clicked.connect(self.submit_new_sample) # submit_btn.clicked.connect(self.submit_new_sample)
self.report.add_result(report) # self.report.add_result(report)
logger.debug(f"Outgoing report: {self.report.results}") # logger.debug(f"Outgoing report: {self.report.results}")
def submit_new_sample_function(self) -> QWidget: # def submit_new_sample_function(self) -> QWidget:
""" # """
Parse forms and add sample to the database. # Parse forms and add sample to the database.
Args: # Args:
obj (QMainWindow): original app window # obj (QMainWindow): original app window
Returns: # Returns:
Tuple[QMainWindow, dict]: Collection of new main app window and result dict # Tuple[QMainWindow, dict]: Collection of new main app window and result dict
""" # """
logger.debug(f"\n\nBeginning Submission\n\n") # logger.debug(f"\n\nBeginning Submission\n\n")
report = Report() # report = Report()
self.pyd: PydSubmission = self.form.parse_form() # self.pyd: PydSubmission = self.form.parse_form()
logger.debug(f"Submission: {pformat(self.pyd)}") # logger.debug(f"Submission: {pformat(self.pyd)}")
logger.debug("Checking kit integrity...") # logger.debug("Checking kit integrity...")
result = self.pyd.check_kit_integrity() # result = self.pyd.check_kit_integrity()
report.add_result(result) # report.add_result(result)
if len(result.results) > 0: # if len(result.results) > 0:
self.report.add_result(report) # self.report.add_result(report)
return # return
base_submission, result = self.pyd.toSQL() # base_submission, result = self.pyd.toSQL()
# logger.debug(f"Base submission: {base_submission.to_dict()}") # # logger.debug(f"Base submission: {base_submission.to_dict()}")
# check output message for issues # # check output message for issues
match result.code: # match result.code:
# code 0: everything is fine. # # code 0: everything is fine.
case 0: # case 0:
self.report.add_result(None) # self.report.add_result(None)
# code 1: ask for overwrite # # code 1: ask for overwrite
case 1: # case 1:
dlg = QuestionAsker(title=f"Review {base_submission.rsl_plate_num}?", message=result.msg) # dlg = QuestionAsker(title=f"Review {base_submission.rsl_plate_num}?", message=result.msg)
if dlg.exec(): # if dlg.exec():
# Do not add duplicate reagents. # # Do not add duplicate reagents.
# base_submission.reagents = [] # # base_submission.reagents = []
result = None # result = None
else: # else:
self.app.ctx.database_session.rollback() # self.app.ctx.database_session.rollback()
self.report.add_result(Result(msg="Overwrite cancelled", status="Information")) # self.report.add_result(Result(msg="Overwrite cancelled", status="Information"))
return # return
# code 2: No RSL plate number given # # code 2: No RSL plate number given
case 2: # case 2:
self.report.add_result(result) # self.report.add_result(result)
return # return
case _: # case _:
pass # pass
# add reagents to submission object # # add reagents to submission object
for reagent in base_submission.reagents: # for reagent in base_submission.reagents:
# logger.debug(f"Updating: {reagent} with {reagent.lot}") # # logger.debug(f"Updating: {reagent} with {reagent.lot}")
reagent.update_last_used(kit=base_submission.extraction_kit) # reagent.update_last_used(kit=base_submission.extraction_kit)
# logger.debug(f"Here is the final submission: {pformat(base_submission.__dict__)}") # # logger.debug(f"Here is the final submission: {pformat(base_submission.__dict__)}")
# logger.debug(f"Parsed reagents: {pformat(base_submission.reagents)}") # # logger.debug(f"Parsed reagents: {pformat(base_submission.reagents)}")
# logger.debug(f"Sending submission: {base_submission.rsl_plate_num} to database.") # # logger.debug(f"Sending submission: {base_submission.rsl_plate_num} to database.")
# logger.debug(f"Samples from pyd: {pformat(self.pyd.samples)}") # # logger.debug(f"Samples from pyd: {pformat(self.pyd.samples)}")
# logger.debug(f"Samples SQL: {pformat([item.__dict__ for item in base_submission.samples])}") # # logger.debug(f"Samples SQL: {pformat([item.__dict__ for item in base_submission.samples])}")
# logger.debug(f"") # # logger.debug(f"")
base_submission.save() # base_submission.save()
# update summary sheet # # update summary sheet
self.app.table_widget.sub_wid.setData() # self.app.table_widget.sub_wid.setData()
# reset form # # reset form
self.form.setParent(None) # self.form.setParent(None)
# logger.debug(f"All attributes of obj: {pformat(self.__dict__)}") # # logger.debug(f"All attributes of obj: {pformat(self.__dict__)}")
self.report.add_result(report) # self.report.add_result(report)
def export_csv_function(self, fname:Path|None=None): # def export_csv_function(self, fname:Path|None=None):
""" # """
Save the submission's csv file. # Save the submission's csv file.
Args: # Args:
fname (Path | None, optional): Input filename. Defaults to None. # fname (Path | None, optional): Input filename. Defaults to None.
""" # """
if isinstance(fname, bool) or fname == None: # if isinstance(fname, bool) or fname == None:
fname = select_save_file(obj=self, default_name=self.pyd.construct_filename(), extension="csv") # fname = select_save_file(obj=self, default_name=self.pyd.construct_filename(), extension="csv")
try: # try:
self.pyd.csv.to_csv(fname.__str__(), index=False) # self.pyd.csv.to_csv(fname.__str__(), index=False)
del self.pyd.csv # del self.pyd.csv
except PermissionError: # except PermissionError:
logger.debug(f"Could not get permissions to {fname}. Possibly the request was cancelled.") # logger.debug(f"Could not get permissions to {fname}. Possibly the request was cancelled.")
def import_pcr_results(self): def import_pcr_results(self):
""" """
@@ -396,7 +396,14 @@ class SubmissionFormWidget(QWidget):
def __init__(self, parent: QWidget, **kwargs) -> None: def __init__(self, parent: QWidget, **kwargs) -> None:
super().__init__(parent) super().__init__(parent)
self.ignore = ['filepath', 'samples', 'reagents', 'csv', 'ctx', 'comment', 'equipment', 'source_plates'] self.report = Report()
self.app = parent.app
# self.input = [{k:v} for k,v in kwargs.items()]
self.samples = []
self.missing_info = []
self.ignore = ['filepath', 'samples', 'reagents', 'csv', 'ctx', 'comment',
'equipment', 'source_plates', 'id', 'cost', 'extraction_info',
'controls', 'pcr_info', 'gel_info', 'gel_image']
self.recover = ['filepath', 'samples', 'csv', 'comment', 'equipment'] self.recover = ['filepath', 'samples', 'csv', 'comment', 'equipment']
self.layout = QVBoxLayout() self.layout = QVBoxLayout()
for k, v in kwargs.items(): for k, v in kwargs.items():
@@ -404,9 +411,25 @@ class SubmissionFormWidget(QWidget):
add_widget = self.create_widget(key=k, value=v, submission_type=kwargs['submission_type']) add_widget = self.create_widget(key=k, value=v, submission_type=kwargs['submission_type'])
if add_widget != None: if add_widget != None:
self.layout.addWidget(add_widget) self.layout.addWidget(add_widget)
else: if k == "extraction_kit":
setattr(self, k, v) add_widget.input.currentTextChanged.connect(self.scrape_reagents)
# else:
self.__setattr__(k, v)
self.scrape_reagents(self.extraction_kit['value'])
# extraction kit must be added last so widget order makes sense.
# self.layout.addWidget(self.create_widget(key="extraction_kit", value=self.extraction_kit, submission_type=self.submission_type))
if hasattr(self, "csv"):
export_csv_btn = QPushButton("Export CSV")
export_csv_btn.setObjectName("export_csv_btn")
self.layout.addWidget(export_csv_btn)
export_csv_btn.clicked.connect(self.export_csv_function)
submit_btn = QPushButton("Submit")
submit_btn.setObjectName("submit_btn")
self.layout.addWidget(submit_btn)
submit_btn.clicked.connect(self.submit_new_sample_function)
self.setLayout(self.layout) self.setLayout(self.layout)
self.app.report.add_result(self.report)
self.app.result_reporter()
def create_widget(self, key:str, value:dict, submission_type:str|None=None) -> "self.InfoItem": def create_widget(self, key:str, value:dict, submission_type:str|None=None) -> "self.InfoItem":
""" """
@@ -422,16 +445,97 @@ class SubmissionFormWidget(QWidget):
""" """
if key not in self.ignore: if key not in self.ignore:
widget = self.InfoItem(self, key=key, value=value, submission_type=submission_type) widget = self.InfoItem(self, key=key, value=value, submission_type=submission_type)
# match key:
# case "extraction_kit":
# # compare obj.reagents with expected reagents in kit
# self.scrape_reagents(widget.currentText())
# widget.currentTextChanged.connect(self.scrape_reagents)
# case _:
# pass
return widget return widget
return None return None
def scrape_reagents(self, *args, **kwargs):#extraction_kit:str, caller:str|None=None):
"""
Extracted scrape reagents function that will run when
form 'extraction_kit' widget is updated.
Args:
obj (QMainWindow): updated main application
extraction_kit (str): name of extraction kit (in 'extraction_kit' widget)
Returns:
Tuple[QMainWindow, dict]: Updated application and result
"""
extraction_kit = args[0]
caller = inspect.stack()[1].function.__repr__().replace("'", "")
# self.reagents = []
# logger.debug(f"Self.reagents: {self.reagents}")
# logger.debug(f"\n\n{caller}\n\n")
# logger.debug(f"SubmissionType: {self.submission_type}")
report = Report()
logger.debug(f"Extraction kit: {extraction_kit}")
# Remove previous reagent widgets
try:
old_reagents = self.find_widgets()
except AttributeError:
logger.error(f"Couldn't find old reagents.")
old_reagents = []
# logger.debug(f"\n\nAttempting to clear: {old_reagents}\n\n")
for reagent in old_reagents:
if isinstance(reagent, self.ReagentFormWidget) or isinstance(reagent, QPushButton):
reagent.setParent(None)
# match caller:
# case "import_submission_function":
# self.reagents = self.prsr.sub['reagents']
# case _:
# already_have = [reagent for reagent in self.prsr.sub['reagents'] if not reagent.missing]
already_have = [reagent for reagent in self.reagents if not reagent.missing]
names = list(set([item.type for item in already_have]))
# logger.debug(f"Already have: {already_have}")
reagents = [item.to_pydantic() for item in KitType.query(name=extraction_kit).get_reagents(submission_type=self.submission_type['value']) if item.name not in names]
# logger.debug(f"Missing: {reagents}")
self.reagents = already_have + reagents
# logger.debug(f"Reagents: {self.reagents}")
self.kit_integrity_completion_function(extraction_kit=extraction_kit)
# logger.debug(f"Missing reagents: {obj.missing_reagents}")
self.report.add_result(report)
logger.debug(f"Outgoing report: {self.report.results}")
def kit_integrity_completion_function(self, extraction_kit:str|None=None):
"""
Compare kit contents to parsed contents and creates widgets.
Args:
obj (QMainWindow): The original app window
Returns:
Tuple[QMainWindow, dict]: Collection of new main app window and result dict
"""
report = Report()
missing_reagents = []
# logger.debug(inspect.currentframe().f_back.f_code.co_name)
# find the widget that contains kit info
if extraction_kit is None:
kit_widget = self.find_widgets(object_name="extraction_kit")[0].input
logger.debug(f"Kit selector: {kit_widget}")
# get current kit being used
self.ext_kit = kit_widget.currentText()
else:
self.ext_kit = extraction_kit
for reagent in self.reagents:
logger.debug(f"Creating widget for {reagent}")
add_widget = self.ReagentFormWidget(parent=self, reagent=reagent, extraction_kit=self.ext_kit)
# self.form.layout().addWidget(add_widget)
self.layout.addWidget(add_widget)
if reagent.missing:
missing_reagents.append(reagent)
logger.debug(f"Checking integrity of {self.ext_kit}")
# TODO: put check_kit_integrity here instead of what's here?
# see if there are any missing reagents
if len(missing_reagents) > 0:
result = Result(msg=f"""The submission you are importing is missing some reagents expected by the kit.\n\n
It looks like you are missing: {[item.type.upper() for item in missing_reagents]}\n\n
Alternatively, 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!""".replace(" ", ""), status="Warning")
report.add_result(result)
self.report.add_result(report)
logger.debug(f"Outgoing report: {self.report.results}")
def clear_form(self): def clear_form(self):
""" """
Removes all form widgets Removes all form widgets
@@ -454,6 +558,83 @@ class SubmissionFormWidget(QWidget):
query = [widget for widget in query if widget.objectName()==object_name] query = [widget for widget in query if widget.objectName()==object_name]
return query return query
def submit_new_sample_function(self) -> QWidget:
"""
Parse forms and add sample to the database.
Args:
obj (QMainWindow): original app window
Returns:
Tuple[QMainWindow, dict]: Collection of new main app window and result dict
"""
logger.debug(f"\n\nBeginning Submission\n\n")
report = Report()
self.pyd: PydSubmission = self.parse_form()
logger.debug(f"Submission: {pformat(self.pyd)}")
logger.debug("Checking kit integrity...")
result = self.pyd.check_kit_integrity()
report.add_result(result)
if len(result.results) > 0:
self.report.add_result(report)
return
base_submission, result = self.pyd.toSQL()
# logger.debug(f"Base submission: {base_submission.to_dict()}")
# check output message for issues
match result.code:
# code 0: everything is fine.
case 0:
self.report.add_result(None)
# code 1: ask for overwrite
case 1:
dlg = QuestionAsker(title=f"Review {base_submission.rsl_plate_num}?", message=result.msg)
if dlg.exec():
# Do not add duplicate reagents.
# base_submission.reagents = []
result = None
else:
self.app.ctx.database_session.rollback()
self.report.add_result(Result(msg="Overwrite cancelled", status="Information"))
return
# code 2: No RSL plate number given
case 2:
self.report.add_result(result)
return
case _:
pass
# add reagents to submission object
for reagent in base_submission.reagents:
# logger.debug(f"Updating: {reagent} with {reagent.lot}")
reagent.update_last_used(kit=base_submission.extraction_kit)
# logger.debug(f"Here is the final submission: {pformat(base_submission.__dict__)}")
# logger.debug(f"Parsed reagents: {pformat(base_submission.reagents)}")
# logger.debug(f"Sending submission: {base_submission.rsl_plate_num} to database.")
# logger.debug(f"Samples from pyd: {pformat(self.pyd.samples)}")
# logger.debug(f"Samples SQL: {pformat([item.__dict__ for item in base_submission.samples])}")
# logger.debug(f"")
base_submission.save()
# update summary sheet
self.app.table_widget.sub_wid.setData()
# reset form
self.setParent(None)
# logger.debug(f"All attributes of obj: {pformat(self.__dict__)}")
self.report.add_result(report)
def export_csv_function(self, fname:Path|None=None):
"""
Save the submission's csv file.
Args:
fname (Path | None, optional): Input filename. Defaults to None.
"""
pyd = self.parse_form()
if isinstance(fname, bool) or fname == None:
fname = select_save_file(obj=self, default_name=pyd.construct_filename(), extension="csv")
try:
pyd.csv.to_csv(fname.__str__(), index=False)
except PermissionError:
logger.debug(f"Could not get permissions to {fname}. Possibly the request was cancelled.")
def parse_form(self) -> PydSubmission: def parse_form(self) -> PydSubmission:
""" """
Transforms form info into PydSubmission Transforms form info into PydSubmission
@@ -467,7 +648,7 @@ class SubmissionFormWidget(QWidget):
for widget in self.findChildren(QWidget): for widget in self.findChildren(QWidget):
# logger.debug(f"Parsed widget of type {type(widget)}") # logger.debug(f"Parsed widget of type {type(widget)}")
match widget: match widget:
case ReagentFormWidget(): case self.ReagentFormWidget():
reagent, _ = widget.parse_form() reagent, _ = widget.parse_form()
if reagent != None: if reagent != None:
reagents.append(reagent) reagents.append(reagent)
@@ -581,7 +762,7 @@ class SubmissionFormWidget(QWidget):
logger.error(f"Couldn't find {obj.prsr.sub['extraction_kit']}") logger.error(f"Couldn't find {obj.prsr.sub['extraction_kit']}")
obj.ext_kit = uses[0] obj.ext_kit = uses[0]
add_widget.addItems(uses) add_widget.addItems(uses)
# Run reagent scraper whenever extraction kit is changed.
case 'submitted_date': case 'submitted_date':
# uses base calendar # uses base calendar
add_widget = QDateEdit(calendarPopup=True) add_widget = QDateEdit(calendarPopup=True)