From 7fb5bb12f33adc4e4ac942ec8ed745fe5e9230e2 Mon Sep 17 00:00:00 2001 From: Landon Wark Date: Fri, 3 Feb 2023 14:18:29 -0600 Subject: [PATCH] Better xlsx reports --- requirements.txt | Bin 1096 -> 2262 bytes src/submissions/__init__.py | 2 +- src/submissions/backend/db/__init__.py | 19 +++++----- src/submissions/frontend/__init__.py | 35 ++++++++++++++++-- .../templates/submission_details.txt | 2 +- 5 files changed, 44 insertions(+), 14 deletions(-) diff --git a/requirements.txt b/requirements.txt index 544a26ee199e8c4bbc0a3c242d0efa6828ecf2a9..e017284da00777f44b0248c7a908928d41d2b28d 100644 GIT binary patch literal 2262 zcmZ{l%}yIZ5QOI(DUV`=*Zd@h9CC;hMIaGzh;oWxv9ZH?ZR{o3JbaS+x^_H9fL4pl zc1?G6bp-s>3w>ahJMo(6B}=9Cl^ziMJ&kO& z;u%4P;jLQ2pXC`&4cCq3WNbn)^oenoxp?=1HQ6QIqtb z^$+ULQF06u?5p4fm$9BUYFRB*HV!XLwVoQsdS{w1b@~$Q z(7}7~?aD9lZ?jpdn=X`Wr6T9>joz#Qon=Sv<2=`KoC>%UJkBX6g7ZH0k$m?0)XlMh zYK_%DXGa}QnZ*o0D*Kzb_cRgr)6-Na!@KTnPFcH7H=W(!)4S|C&zd;r5c9Q9il?|wV9PFU_Oknw up(_xa3-mnNsZ#aodq$69dL7++hUQ-!P&C>|U*AHNrkc+I?{)4ED*gw@IYcx7 delta 54 zcmV-60LlN>5y%LTMw7+?Xp>?B9+R2^f|EW2hLdgt5|da2c9Zx7+>`tTLX(CDM3dwO MCX+4)LX(aMB1y9phX4Qo diff --git a/src/submissions/__init__.py b/src/submissions/__init__.py index b48d6ab..e2a17e4 100644 --- a/src/submissions/__init__.py +++ b/src/submissions/__init__.py @@ -1,4 +1,4 @@ # __init__.py # Version of the realpython-reader package -__version__ = "1.1.2" +__version__ = "1.2.1" diff --git a/src/submissions/backend/db/__init__.py b/src/submissions/backend/db/__init__.py index d771baf..0ad9c48 100644 --- a/src/submissions/backend/db/__init__.py +++ b/src/submissions/backend/db/__init__.py @@ -2,16 +2,14 @@ from . import models import pandas as pd import sqlalchemy.exc import sqlite3 -# from sqlalchemy.exc import IntegrityError, OperationalError -# from sqlite3 import IntegrityError, OperationalError import logging from datetime import date, datetime, timedelta from sqlalchemy import and_ import uuid -import base64 +# import base64 from sqlalchemy import JSON import json -from dateutil.relativedelta import relativedelta +# from dateutil.relativedelta import relativedelta from getpass import getuser logger = logging.getLogger(f"submissions.{__name__}") @@ -94,11 +92,14 @@ def construct_submission_info(ctx:dict, info_dict:dict) -> models.BasicSubmissio instance = ctx['database_session'].query(models.BasicSubmission).filter(models.BasicSubmission.rsl_plate_num==info_dict['rsl_plate_num']).first() msg = "This submission already exists.\nWould you like to overwrite?" # get model based on submission type converted above + logger.debug(f"Looking at models for submission type: {query}") model = getattr(models, query) + logger.debug(f"We've got the model: {type(model)}") info_dict['submission_type'] = info_dict['submission_type'].replace(" ", "_").lower() # if query return nothing, ie doesn't already exist in db if instance == None: instance = model() + logger.debug(f"Submission doesn't exist yet, creating new instance: {instance}") msg = None for item in info_dict: logger.debug(f"Setting {item} to {info_dict[item]}") @@ -133,11 +134,11 @@ def construct_submission_info(ctx:dict, info_dict:dict) -> models.BasicSubmissio logger.debug(f"Could not set attribute: {item} to {info_dict[item]}") continue # calculate cost of the run: immutable cost + mutable times number of columns - try: - instance.run_cost = instance.extraction_kit.immutable_cost + (instance.extraction_kit.mutable_cost * ((instance.sample_count / 8)/12)) - except TypeError: - logger.debug(f"Looks like that kit doesn't have cost breakdown yet, using full plate cost.") - instance.run_cost = instance.extraction_kit.cost_per_run + try: + instance.run_cost = instance.extraction_kit.immutable_cost + (instance.extraction_kit.mutable_cost * ((instance.sample_count / 8)/12)) + except (TypeError, AttributeError): + logger.debug(f"Looks like that kit doesn't have cost breakdown yet, using full plate cost.") + instance.run_cost = instance.extraction_kit.cost_per_run logger.debug(f"Constructed instance: {instance.to_string()}") logger.debug(msg) return instance, {'message':msg} diff --git a/src/submissions/frontend/__init__.py b/src/submissions/frontend/__init__.py index 8dc1abe..9bbc141 100644 --- a/src/submissions/frontend/__init__.py +++ b/src/submissions/frontend/__init__.py @@ -15,9 +15,12 @@ from PyQt6.QtWebEngineWidgets import QWebEngineView from pathlib import Path import plotly import pandas as pd +from openpyxl.utils import get_column_letter +from openpyxl.styles import NamedStyle from xhtml2pdf import pisa # import plotly.express as px import yaml +import pprint from backend.excel.parser import SheetParser from backend.excel.reports import convert_control_by_mode, convert_data_list_to_df @@ -35,7 +38,7 @@ import difflib from datetime import date from frontend.visualizations.charts import create_charts -logger = logging.getLogger(__name__) +logger = logging.getLogger(f'submissions.{__name__}') logger.info("Hello, I am a logger") class App(QMainWindow): @@ -64,6 +67,7 @@ class App(QMainWindow): self._connectActions() self.controls_getter() self.show() + def _createMenuBar(self): """ @@ -261,10 +265,11 @@ class App(QMainWindow): logger.debug("Will not add reagent.") if wanted_reagent != None: parsed_reagents.append(wanted_reagent) - logger.debug(info) + # logger.debug(info) # move samples into preliminary submission dict info['samples'] = self.samples # construct submission object + logger.debug(f"Here is the info_dict: {pprint.pformat(info)}") base_submission, output = construct_submission_info(ctx=self.ctx, info_dict=info) # check output message for issues if output['message'] != None: @@ -376,7 +381,31 @@ class App(QMainWindow): # df.to_excel(fname, engine='openpyxl') with open(fname, "w+b") as f: pisa.CreatePDF(html, dest=f) - df.to_excel(fname.with_suffix(".xlsx"), engine='openpyxl') + writer = pd.ExcelWriter(fname.with_suffix(".xlsx"), engine='openpyxl') + df.to_excel(writer, sheet_name="Report") + worksheet = writer.sheets['Report'] + for idx, col in enumerate(df): # loop through all columns + series = df[col] + max_len = max(( + series.astype(str).map(len).max(), # len of largest item + len(str(series.name)) # len of column name/header + )) + 20 # adding a little extra space + try: + worksheet.column_dimensions[get_column_letter(idx)].width = max_len + except ValueError: + pass + # set_column(idx, idx, max_len) # set column width + # colu = worksheet.column_dimensions["C"] + # style = NamedStyle(name="custom_currency", number_format='Currency') + for cell in worksheet['C']: + # try: + # check = int(cell.row) + # except TypeError: + # continue + if cell.row > 3: + cell.style = 'Currency' + writer.close() + diff --git a/src/submissions/templates/submission_details.txt b/src/submissions/templates/submission_details.txt index 8a9e7d3..0d38f72 100644 --- a/src/submissions/templates/submission_details.txt +++ b/src/submissions/templates/submission_details.txt @@ -1,7 +1,7 @@ {# template for constructing submission details #} {% for key, value in sub.items() if key != 'reagents' and key != 'samples' %} -{{ key }}: {{ value }} +{% if key=='Cost' %} {{ key }}: {{ "${:,.2f}".format(value) }} {% else %} {{ key }}: {{ value }} {% endif %} {% endfor %} Reagents: {% for item in sub['reagents'] %}