From 9312a66bb72c47f145779074c6e47355c6195b48 Mon Sep 17 00:00:00 2001 From: Landon Wark Date: Wed, 15 Nov 2023 14:12:16 -0600 Subject: [PATCH] Bugs squashed. --- src/submissions/__init__.py | 2 +- src/submissions/__main__.py | 6 ++- src/submissions/backend/db/models/kits.py | 15 +++++++ .../backend/db/models/submissions.py | 18 +++++++- src/submissions/backend/validators/pydant.py | 13 +++--- .../frontend/widgets/submission_table.py | 11 ++--- .../frontend/widgets/submission_widget.py | 41 +++++++------------ .../templates/submission_details.html | 2 +- 8 files changed, 66 insertions(+), 42 deletions(-) diff --git a/src/submissions/__init__.py b/src/submissions/__init__.py index 0ac2122..78398b8 100644 --- a/src/submissions/__init__.py +++ b/src/submissions/__init__.py @@ -4,7 +4,7 @@ from pathlib import Path # Version of the realpython-reader package __project__ = "submissions" -__version__ = "202311.2b" +__version__ = "202311.3b" __author__ = {"name":"Landon Wark", "email":"Landon.Wark@phac-aspc.gc.ca"} __copyright__ = "2022-2023, Government of Canada" diff --git a/src/submissions/__main__.py b/src/submissions/__main__.py index 3d1ef60..0e40426 100644 --- a/src/submissions/__main__.py +++ b/src/submissions/__main__.py @@ -1,9 +1,11 @@ import sys import os # environment variable must be set to enable qtwebengine in network path -if getattr(sys, 'frozen', False): +# if getattr(sys, 'frozen', False): +# os.environ['QTWEBENGINE_DISABLE_SANDBOX'] = "1" +from tools import get_config, setup_logger, check_if_app +if check_if_app(): os.environ['QTWEBENGINE_DISABLE_SANDBOX'] = "1" -from tools import get_config, setup_logger # setup custom logger logger = setup_logger(verbosity=3) # create settings object diff --git a/src/submissions/backend/db/models/kits.py b/src/submissions/backend/db/models/kits.py index 1264d40..a2a02d9 100644 --- a/src/submissions/backend/db/models/kits.py +++ b/src/submissions/backend/db/models/kits.py @@ -471,6 +471,21 @@ class Reagent(Base): pass return query_return(query=query, limit=limit) + def update_last_used(self, kit:KitType): + report = Report() + logger.debug(f"Attempting update of reagent type at intersection of ({self}), ({kit})") + rt = ReagentType.query(kit_type=kit, reagent=self, limit=1) + if rt != None: + logger.debug(f"got reagenttype {rt}") + assoc = KitTypeReagentTypeAssociation.query(kit_type=kit, reagent_type=rt) + if assoc != None: + if assoc.last_used != self.lot: + logger.debug(f"Updating {assoc} last used to {self.lot}") + assoc.last_used = self.lot + result = assoc.save() + return(report.add_result(result)) + return report.add_result(Result(msg=f"Updating last used {rt} was not performed.", status="Information")) + class Discount(Base): """ Relationship table for client labs for certain kits. diff --git a/src/submissions/backend/db/models/submissions.py b/src/submissions/backend/db/models/submissions.py index 95d2d8c..75be538 100644 --- a/src/submissions/backend/db/models/submissions.py +++ b/src/submissions/backend/db/models/submissions.py @@ -25,7 +25,6 @@ from dateutil.parser._parser import ParserError import yaml from sqlalchemy.exc import OperationalError as AlcOperationalError, IntegrityError as AlcIntegrityError, StatementError from sqlite3 import OperationalError as SQLOperationalError, IntegrityError as SQLIntegrityError -import sys logger = logging.getLogger(f"submissions.{__name__}") @@ -572,6 +571,17 @@ class BasicSubmission(Base): except AttributeError: logger.error(f"Could not set {self} attribute {key} to {value}") + def update_subsampassoc(self, sample:BasicSample, input_dict:dict): + assoc = SubmissionSampleAssociation.query(submission=self, sample=sample, limit=1) + for k,v in input_dict.items(): + try: + setattr(assoc, k, v) + except AttributeError: + logger.error(f"Can't set {k} to {v}") + # result = store_object(ctx=ctx, object=assoc) + result = assoc.save() + return result + # Below are the custom submission types class BacterialCulture(BasicSubmission): @@ -925,6 +935,8 @@ class WastewaterArtic(BasicSubmission): input_dict['csv'] = df return input_dict +# Sample Classes + class BasicSample(Base): """ Base of basic sample which polymorphs into BCSample and WWSample @@ -1115,6 +1127,8 @@ class BasicSample(Base): instance.sample_type = sample_type return instance +#Below are the custom sample types + class WastewaterSample(BasicSample): """ Derivative wastewater sample @@ -1199,6 +1213,8 @@ class BacterialCultureSample(BasicSample): sample['name'] = f"{self.submitter_id} - ({self.organism})" return sample +# Submission to Sample Associations + class SubmissionSampleAssociation(Base): """ table containing submission/sample associations diff --git a/src/submissions/backend/validators/pydant.py b/src/submissions/backend/validators/pydant.py index 9788936..61f5b8b 100644 --- a/src/submissions/backend/validators/pydant.py +++ b/src/submissions/backend/validators/pydant.py @@ -13,7 +13,7 @@ import re import logging from tools import check_not_nan, convert_nans_to_nones, jinja_template_loading, Report, Result from backend.db.models import * -from sqlalchemy.exc import StatementError +from sqlalchemy.exc import StatementError, IntegrityError from PyQt6.QtWidgets import QComboBox, QWidget from pprint import pformat from openpyxl import load_workbook @@ -172,7 +172,10 @@ class PydSample(BaseModel, extra='allow'): submission=submission, sample=instance, row=row, column=column) - instance.sample_submission_associations.append(association) + try: + instance.sample_submission_associations.append(association) + except IntegrityError: + instance.metadata.session.rollback() return instance, result class PydSubmission(BaseModel, extra='allow'): @@ -408,9 +411,9 @@ class PydSubmission(BaseModel, extra='allow'): extraction_kit = KitType.query(name=self.extraction_kit['value']) logger.debug(f"We have the extraction kit: {extraction_kit.name}") excel_map = extraction_kit.construct_xl_map_for_use(self.submission_type['value']) - logger.debug(f"Extraction kit map:\n\n{pformat(excel_map)}") - logger.debug(f"Missing reagents going into autofile: {pformat(reagents)}") - logger.debug(f"Missing info going into autofile: {pformat(info)}") + # logger.debug(f"Extraction kit map:\n\n{pformat(excel_map)}") + # logger.debug(f"Missing reagents going into autofile: {pformat(reagents)}") + # logger.debug(f"Missing info going into autofile: {pformat(info)}") new_reagents = [] for reagent in reagents: new_reagent = {} diff --git a/src/submissions/frontend/widgets/submission_table.py b/src/submissions/frontend/widgets/submission_table.py index bcea319..8aa169c 100644 --- a/src/submissions/frontend/widgets/submission_table.py +++ b/src/submissions/frontend/widgets/submission_table.py @@ -145,7 +145,7 @@ class SubmissionsSheet(QTableView): index = (self.selectionModel().currentIndex()) value = index.sibling(index.row(),1).data() logger.debug(f"Selected value: {value}") - dlg = SubmissionComment(ctx=self.ctx, rsl=value) + dlg = SubmissionComment(rsl=value) if dlg.exec(): dlg.add_comment() @@ -455,6 +455,8 @@ class SubmissionDetails(QDialog): super().__init__(parent) # self.ctx = ctx + self.app = parent.parent().parent().parent().parent().parent().parent + print(f"App: {self.app}") self.setWindowTitle("Submission Details") # create scrollable interior interior = QScrollArea() @@ -603,10 +605,10 @@ class SubmissionComment(QDialog): """ a window for adding comment text to a submission """ - def __init__(self, ctx:Settings, rsl:str) -> None: + def __init__(self, rsl:str) -> None: super().__init__() - self.ctx = ctx + # self.ctx = ctx self.rsl = rsl self.setWindowTitle(f"{self.rsl} Submission Comment") # create text field @@ -640,7 +642,6 @@ class SubmissionComment(QDialog): except AttributeError: sub.comment = [full_comment] logger.debug(sub.__dict__) - self.ctx.database_session.add(sub) - self.ctx.database_session.commit() + sub.save() \ No newline at end of file diff --git a/src/submissions/frontend/widgets/submission_widget.py b/src/submissions/frontend/widgets/submission_widget.py index c9fbdaf..ec29d71 100644 --- a/src/submissions/frontend/widgets/submission_widget.py +++ b/src/submissions/frontend/widgets/submission_widget.py @@ -11,7 +11,7 @@ from tools import Report, Result, check_not_nan from backend.excel.parser import SheetParser, PCRParser from backend.validators import PydSubmission, PydReagent from backend.db import ( - check_kit_integrity, update_last_used, KitType, Organization, SubmissionType, Reagent, + check_kit_integrity, KitType, Organization, SubmissionType, Reagent, ReagentType, KitTypeReagentTypeAssociation, BasicSubmission, update_subsampassoc_with_pcr ) from pprint import pformat @@ -22,7 +22,7 @@ import difflib from datetime import date import inspect import json - +import sys logger = logging.getLogger(f"submissions.{__name__}") @@ -80,27 +80,6 @@ class SubmissionFormContainer(QWidget): case _: self.app.result_reporter() - # def kit_reload_function(self): - # """ - # Reload the fields in the form - - # Args: - # obj (QMainWindow): original app window - - # Returns: - # Tuple[QMainWindow, dict]: Collection of new main app window and result dict - # """ - # report = Report() - # # for item in obj.table_widget.formlayout.parentWidget().findChildren(QWidget): - # logger.debug(f"Attempting to clear {obj.form.find_widgets()}") - # for item in self.form.find_widgets(): - # if isinstance(item, ReagentFormWidget): - # item.setParent(None) - # self.kit_integrity_completion_function() - # self.report.add_result(report) - - - def kit_integrity_completion(self): """ Performs check of imported reagents @@ -296,6 +275,8 @@ class SubmissionFormContainer(QWidget): self.report.add_result(report) return base_submission, result = self.pyd.toSQL() + # logger.debug(f"Base submission: {base_submission.to_dict()}") + # sys.exit() # check output message for issues match result.code: # code 0: everything is fine. @@ -303,7 +284,7 @@ class SubmissionFormContainer(QWidget): self.report.add_result(None) # code 1: ask for overwrite case 1: - dlg = QuestionAsker(title=f"Review {base_submission.rsl_plate_num}?", message=result['message']) + dlg = QuestionAsker(title=f"Review {base_submission.rsl_plate_num}?", message=result.msg) if dlg.exec(): # Do not add duplicate reagents. # base_submission.reagents = [] @@ -320,7 +301,10 @@ class SubmissionFormContainer(QWidget): pass # add reagents to submission object for reagent in base_submission.reagents: - update_last_used(reagent=reagent, kit=base_submission.extraction_kit) + # logger.debug(f"Updating: {reagent} with {reagent.lot}") + # update_last_used(reagent=reagent, kit=base_submission.extraction_kit) + reagent.update_last_used(kit=base_submission.extraction_kit) + # sys.exit() 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.") @@ -329,7 +313,7 @@ class SubmissionFormContainer(QWidget): self.app.table_widget.sub_wid.setData() # reset form self.form.setParent(None) - logger.debug(f"All attributes of obj: {pformat(self.__dict__)}") + # logger.debug(f"All attributes of obj: {pformat(self.__dict__)}") wkb = self.pyd.autofill_excel() if wkb != None: fname = select_save_file(obj=self, default_name=self.pyd.construct_filename(), extension="xlsx") @@ -352,6 +336,7 @@ class SubmissionFormContainer(QWidget): fname = select_save_file(obj=self, default_name=self.pyd.construct_filename(), extension="csv") try: self.pyd.csv.to_csv(fname.__str__(), index=False) + del self.pyd.csv except PermissionError: logger.debug(f"Could not get permissions to {fname}. Possibly the request was cancelled.") @@ -424,7 +409,8 @@ class SubmissionFormContainer(QWidget): sample_dict = [item for item in parser.samples if item['sample']==sample.rsl_number][0] except IndexError: continue - update_subsampassoc_with_pcr(submission=sub, sample=sample, input_dict=sample_dict) + # update_subsampassoc_with_pcr(submission=sub, sample=sample, input_dict=sample_dict) + sub.update_subsampassoc(sample=sample, input_dict=sample_dict) self.report.add_result(Result(msg=f"We added PCR info to {sub.rsl_plate_num}.", status='Information')) # return obj, result @@ -481,6 +467,7 @@ class SubmissionFormWidget(QWidget): info[field] = value logger.debug(f"Info: {pformat(info)}") logger.debug(f"Reagents: {pformat(reagents)}") + # sys.exit() # app = self.parent().parent().parent().parent().parent().parent().parent().parent submission = PydSubmission(filepath=self.filepath, reagents=reagents, samples=self.samples, **info) return submission diff --git a/src/submissions/templates/submission_details.html b/src/submissions/templates/submission_details.html index 223c16e..3e603b5 100644 --- a/src/submissions/templates/submission_details.html +++ b/src/submissions/templates/submission_details.html @@ -35,7 +35,7 @@ Submission Details for {{ sub['Plate Number'] }} - {% set excluded = ['reagents', 'samples', 'controls', 'ext_info', 'pcr_info', 'comments', 'barcode', 'platemap'] %} + {% set excluded = ['reagents', 'samples', 'controls', 'ext_info', 'pcr_info', 'comments', 'barcode', 'platemap', 'export_map'] %}

Submission Details for {{ sub['Plate Number'] }}

   {% if sub['barcode'] %}{% endif %}

{% for key, value in sub.items() if key not in excluded %}