You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
216 lines
9.1 KiB
216 lines
9.1 KiB
from ui import Ui_MainWindow
|
|
from errorDialog import ErrorDialog
|
|
import ILParser
|
|
from PyQt5 import QtWidgets
|
|
from logging import debug, info, warning, exception as logException, error,DEBUG, INFO, WARNING, ERROR, basicConfig, getLogger
|
|
from sys import argv
|
|
from typing import Literal, Optional
|
|
from pandas import DataFrame, ExcelWriter
|
|
from datetime import datetime as dt
|
|
from os import startfile
|
|
from json import load, dump
|
|
from time import sleep
|
|
|
|
# Open the config file, create a dict, and set up logging
|
|
with open("config.json") as configFile:
|
|
config: dict[Literal["loggingLevel"], Literal["ERROR", "WARNING", "INFO", "DEBUG"]] = load(configFile)
|
|
basicConfig(filename='ILFormatter.log', encoding='utf-8', level=config["loggingLevel"], filemode='w', force=True)
|
|
info(f"Starting with log level: {getLogger().level}")
|
|
|
|
# Change the current log level and save the change to config.json
|
|
def change_log_level(newLevel: Literal["ERROR", "WARNING", "INFO", "DEBUG"]):
|
|
config["loggingLevel"] = newLevel
|
|
with open("config.json", 'w') as configFile:
|
|
dump(config, configFile)
|
|
getLogger().setLevel(newLevel)
|
|
print(f"{now()} | New logging level: {getLogger().level}\n")
|
|
|
|
# Creates an error dialog pop up
|
|
# Based on the ui from errorDialog.py
|
|
def open_error_dialog(errorLabel: str, errorDescription: str, errorText: str):
|
|
dialog = QtWidgets.QDialog()
|
|
dialog.ui = ErrorDialog()
|
|
dialog.ui.setupUi(dialog)
|
|
dialog.ui.setFields(errorLabel, errorDescription, errorText)
|
|
dialog.exec_()
|
|
|
|
# Used to easily record uniform timestamps
|
|
now = lambda : dt.now().strftime("%H:%M-%S.%f")
|
|
|
|
# This class is responable for managing the UI of the application
|
|
# and connection it to the functionality of ILParser.py
|
|
class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
|
|
def __init__(self, *args, obj=None, **kwargs):
|
|
debug("MainWindow class init..")
|
|
super(MainWindow, self).__init__(*args, **kwargs)
|
|
self.setupUi(self)
|
|
self.processButton.setEnabled(False)
|
|
self.openButton.setEnabled(False)
|
|
|
|
# Fix log level action buttons
|
|
level: QtWidgets.QAction
|
|
for level in [self.actionError, self.warnAction, self.infoAction, self.debugAction]:
|
|
inUse = level.text().upper() == config["loggingLevel"]
|
|
level.setEnabled(not inUse)
|
|
level.setChecked(inUse)
|
|
if inUse: self.logLevel = level
|
|
debug(f"Logging Level: {self.logLevel}")
|
|
|
|
# File Locations
|
|
self.assetFile = None
|
|
self.custFile = None
|
|
self.dobFile = None
|
|
self.finFile = None
|
|
self.outputLocation = None
|
|
|
|
# Button Hooks
|
|
self.assetButton.clicked.connect(lambda: self._set_file(lineEdit= self.assetLE, selfFile="ASSET"))
|
|
self.custButton.clicked.connect(lambda: self._set_file(lineEdit= self.custLe, selfFile="CUST"))
|
|
self.dobButton.clicked.connect(lambda: self._set_file(lineEdit= self.dobLE, selfFile="DOB"))
|
|
self.finButton.clicked.connect(lambda: self._set_file(lineEdit= self.finLE, selfFile="FIN"))
|
|
self.outputButton.clicked.connect(lambda: self._set_output())
|
|
self.processButton.clicked.connect(lambda: self._process())
|
|
self.openButton.clicked.connect(lambda: self._open_with_default_app(self.outputLocation))
|
|
|
|
# Action Hooks
|
|
self.actionError.triggered.connect(lambda: self._switch_log_levels(self.actionError))
|
|
self.warnAction.triggered.connect(lambda: self._switch_log_levels(self.warnAction))
|
|
self.infoAction.triggered.connect(lambda: self._switch_log_levels(self.infoAction))
|
|
self.debugAction.triggered.connect(lambda: self._switch_log_levels(self.debugAction))
|
|
|
|
def _check_files(self):
|
|
debug(self.assetFile)
|
|
debug(self.custFile)
|
|
debug(self.dobFile)
|
|
debug(self.finFile)
|
|
self.openButton.setEnabled(False)
|
|
ready = (
|
|
self.assetFile != None and
|
|
self.custFile != None and
|
|
self.dobFile != None and
|
|
self.finFile != None and
|
|
self.outputLocation != None
|
|
)
|
|
self.processButton.setEnabled(ready)
|
|
|
|
def _set_file(self, lineEdit: QtWidgets.QLineEdit, selfFile: Literal["ASSET", "CUST", "DOB", "FIN"]) -> Optional[str] :
|
|
selectedFile: list[str] = QtWidgets.QFileDialog.getOpenFileName(self, "OpenFile")
|
|
debug(f"Selected file: {selectedFile}")
|
|
lineEdit.setText(selectedFile[0])
|
|
file = selectedFile[0] if selectedFile[0] != '' else None
|
|
if file != None and self.outputLocation == None:
|
|
self._auto_output_set(fileRoot='/'.join(file.split('/')[:-1]))
|
|
if selfFile == "ASSET":
|
|
self.assetFile = file
|
|
elif selfFile == "CUST":
|
|
self.custFile = file
|
|
elif selfFile == "DOB":
|
|
self.dobFile = file
|
|
elif selfFile == "FIN":
|
|
self.finFile = file
|
|
self._check_files()
|
|
|
|
def _set_output(self):
|
|
self.outputLocation = QtWidgets.QFileDialog.getSaveFileName(self, "Output file name") if QtWidgets.QFileDialog.getSaveFileName(self, "Output file name") != '' else None
|
|
self.outputLE.setText(self.outputLocation if self.outputLocation != None else '')
|
|
debug(f"Output Location: {self.outputLocation}")
|
|
|
|
def _auto_output_set(self, fileRoot):
|
|
self.outputLocation = fileRoot + f"/Portfolio Contracts - {dt.now().strftime('%Y-%m-%d')}.xlsx"
|
|
self.outputLE.setText(self.outputLocation if self.outputLocation != None else '')
|
|
debug(f"Auto set output: {self.outputLocation}")
|
|
|
|
def _open_with_default_app(self, item):
|
|
"""
|
|
Opens the linked item with it's default application (excel)
|
|
"""
|
|
debug(f"_open_with_default_app: {item}")
|
|
startfile(item)
|
|
|
|
|
|
def _switch_log_levels(self, newLevel: QtWidgets.QAction):
|
|
oldLevel: QtWidgets.QAction = self.logLevel
|
|
print(f"{now()} | Log Level Changed: {oldLevel.text()} -> {newLevel.text()}")
|
|
newLevel.setChecked(True)
|
|
oldLevel.setChecked(False)
|
|
newLevel.setEnabled(False)
|
|
oldLevel.setEnabled(True)
|
|
self.logLevel = newLevel
|
|
change_log_level(newLevel.text().upper())
|
|
|
|
|
|
def _parse_file(self, filePath: str, parseColumns: list[ILParser.Column]) -> Optional[DataFrame]:
|
|
with open(filePath) as file:
|
|
report = file.read()
|
|
debug(f"Report: {report}")
|
|
debug(f"Parse Columns:\n{parseColumns}")
|
|
try:
|
|
data: DataFrame = ILParser.parse(report, parseColumns)
|
|
except Exception as e:
|
|
logException(f"Failed to parse file-> {filePath} :\n{e}")
|
|
open_error_dialog("Parsing Error:",f"Failed to parse file-> {filePath}",repr(e))
|
|
return None
|
|
debug(f"Data: {data}")
|
|
if data.empty:
|
|
error(f"Dataframe empty -> {filePath} | Returning none")
|
|
open_error_dialog("Data Processing Error:",f"Dataframe empty!",filePath)
|
|
return None
|
|
else: return data
|
|
|
|
def _process(self):
|
|
assetDf: Optional[DataFrame] = self._parse_file(filePath= self.assetFile, parseColumns= ILParser.ASSET_COLS)
|
|
debug(f"AssetDF: {assetDf} | {type(assetDf)} ")
|
|
if type(assetDf) != DataFrame:
|
|
debug(f"Parse Columns: {ILParser.ASSET_COLS}")
|
|
self.assetLE.setText("")
|
|
self.assetFile = None
|
|
|
|
return None
|
|
custDf: DataFrame = self._parse_file(self.custFile, ILParser.CUST_COLS)
|
|
debug(custDf)
|
|
if type(custDf) != DataFrame:
|
|
debug(f"Parse Columns: {ILParser.CUST_COLS}")
|
|
self.custLe.setText("")
|
|
self.custFile = None
|
|
|
|
return None
|
|
dobDf: DataFrame = self._parse_file(self.dobFile, ILParser.DOB_COL)
|
|
debug(dobDf)
|
|
if type(dobDf) != DataFrame:
|
|
debug(f"Parse Columns: {ILParser.DOB_COL}")
|
|
self.dobLE.setText("")
|
|
self.dobFile = None
|
|
|
|
return None
|
|
finDf: DataFrame = self._parse_file(self.finFile, ILParser.FIN_COLUMNS)
|
|
debug(finDf)
|
|
if type(finDf) != DataFrame:
|
|
debug(f"Parse Columns: {ILParser.FIN_COLUMNS}")
|
|
self.finLE.setText("")
|
|
self.finFile = None
|
|
|
|
return None
|
|
try:
|
|
with ExcelWriter(self.outputLocation) as writer:
|
|
assetDf.to_excel(writer, sheet_name="ASSET")
|
|
custDf.to_excel(writer, sheet_name="CUST")
|
|
dobDf.to_excel(writer, sheet_name="DOB")
|
|
finDf.to_excel(writer, sheet_name="FIN")
|
|
except Exception as e:
|
|
logException(f"{now()} | Failed to write to excel -> {self.outputLocation} :\n{e}")
|
|
open_error_dialog("Failed to Create Excel", f"Failed to write to excel -> {self.outputLocation}", repr(e))
|
|
return None
|
|
debug("Finished writing to excel.")
|
|
self.openButton.setEnabled(True)
|
|
|
|
|
|
# Defines the app
|
|
app = QtWidgets.QApplication(argv)
|
|
# Sets the style
|
|
app.setStyle("Fusion")
|
|
# Builds the main window
|
|
window = MainWindow()
|
|
window.setWindowTitle("IL Extract")
|
|
window.show()
|
|
# Starts the app
|
|
app.exec() |