from ILE_MainWindow import Ui_MainWindow from defLocs_Window2 import Ui_defaultLocationDiag import sys import os import pandas as pd import json from PyQt5 import QtWidgets from PyQt5.QtWidgets import QApplication, QDialog, QMainWindow, QPushButton from datetime import datetime as dt import ILExtract as ilx print("Starting GUI... will anything else print?") class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow): def __init__(self, *args, obj=None, **kwargs): super(MainWindow, self).__init__(*args, **kwargs) self.setupUi(self) self.setAcceptDrops(True) self.inputFile = "" self.outputFile = "" self.inputCustomized = False with open("settings.json") as s: self.settings = json.loads(s.read()) self.curReportType = "ach" self.extract_function = ilx.ach cbs = self.copyButton.objectName() self.report_type_change() # Actions self.inputFileButton.clicked.connect(self.getfile) self.outputFileButton.clicked.connect(self.setOutput) self.processReportButton.clicked.connect(self.process_selection) self.copyButton.clicked.connect(self.to_clipboard) self.reportTypeCB.currentTextChanged.connect(self.report_type_change) self.openFolderButton.clicked.connect(lambda: self.openWithDefaultApp(self.outputFile.removesuffix(self.outputFile.split('/')[-1]))) self.openExcelButton.clicked.connect(lambda: self.openWithDefaultApp(self.outputFile)) self.action_Default_Locations.triggered.connect(self.df) self.inputFilePreview.setText("Drag & Drop Input file here!") def set_input(self, ifile): with open(ifile, errors="replace") as inF: txt = inF.read() self.inputFilePreview.setText(txt) self.inputFileLE.setText(ifile) self.inputFile = ifile # This gets the actual file name inFileEnd = ifile.split('/')[-1] # Takes just the root of the input file outputRoot = self.inputFile.removesuffix(inFileEnd) # Automatically sets output to be in the same file as input, with a naming scheme # The report type selected in the combo box will dictate the naming if self.reportTypeCB.currentText() == "Minv_C": self.outputFile = f"{outputRoot}{self.reportTypeCB.currentText()}_{dt.now().strftime('%Y%m%d_%H%M')}.txt" else: self.outputFile = f"{outputRoot}{self.reportTypeCB.currentText().replace('/','')}_{dt.now().strftime('%Y%m%d_%H%M')}.xlsx" self.outputFileLE.setText(self.outputFile) self.inputCustomized = True self.openExcelButton.setEnabled(False) self.copyButton.setEnabled(False) self.openFolderButton.setEnabled(True) # Enables the process button self.check_ready_to_process() def getfile(self): inFile = QtWidgets.QFileDialog.getOpenFileName(self, 'Open file') if inFile[0] == '': return 1 else: self.set_input(inFile[0]) def df(self): dlg = defLocWindow(self) dlg.exec() with open("settings.json") as s: self.settings = json.loads(s.read()) def dragEnterEvent(self, event): if event.mimeData().hasUrls(): event.accept() else: event.ignore() def dropEvent(self, event): file = [u.toLocalFile() for u in event.mimeData().urls()][0] print(file) self.set_input(file) def setOutput(self): # This allows the user to change the automatic naming and location outFile = QtWidgets.QFileDialog.getSaveFileName(self, "Output file name") if outFile[0] == '': return '' if self.reportTypeCB.currentText() == "Minv_C": self.outputFileLE.setText(f"{outFile[0]}__{dt.now().strftime('%Y%m%d_%H_%M')}.txt") else: self.outputFileLE.setText(f"{outFile[0]}__{dt.now().strftime('%Y%m%d_%H_%M')}.xlsx") print(f"Output: {outFile}") self.outputFile = f"{outFile[0]}__{dt.now().strftime('%Y%m%d_%H_%M')}.xlsx" self.check_ready_to_process() def check_ready_to_process(self): # Makes sure there is an input and output selected before allowing processing rtp = True if ((self.inputFile != "") & (self.outputFile != "")) else False if rtp : self.processReportButton.setEnabled(True) if self.outputFile == "": self.openFolderButton.setEnabled(False) def process_selection(self): print("Processing selection...") self.inputFilePreview.setText("Processing file...") # If only this was python 3.10 and we could use switch statments # but this should get the job done #try: # This is where the actual processing happens # We create an ILReport object and pass in the nessecary information print(self.inputFile) print(self.outputFile) dataframe = ilx.ILReport( location= self.inputFile, extraction_function=self.extract_function, output_location=self.outputFile, ).process() # The text preview box can have trouble loading the larger dataframes so # they are trimmed to 500 so that the users can see if anything got messed up smallDF = dataframe.iloc[0:500,:] self.inputFilePreview.setText(smallDF.to_html(index=False)) #except: # error = QtWidgets.QMessageBox() # error.setWindowTitle('Error Processing File!') # error.setText(f"Unable to process {self.inputFile}!\nPlease check input file!") self.openExcelButton.setEnabled(True) self.copyButton.setEnabled(True) self.checked_for_saved() self.openFolderButton.setEnabled(True) self.inputCustomized = False def preview_report(self): df = pd.read_excel(self.outputFile) self.inputFilePreview.setText(df.to_html()) def to_clipboard(self): df = pd.read_excel(self.outputFile) df.to_clipboard(excel=True) def openFolder(self): outputRoot = self.outputFile.removesuffix(self.outputFile.split('/')[-1]) os.startfile(outputRoot) def openWithDefaultApp(self, item): print(item) outputRoot = self.outputFile.removesuffix(self.outputFile.split('/')[-1]) os.startfile(item) def checked_for_saved(self): if self.settings["defaultLocations"][self.curReportType]["dir"] == '': self.settings["defaultLocations"][self.curReportType]["dir"] = ('/').join(self.inputFile.split('/')[:-1]) with open('settings.json', 'w') as s: json.dump(self.settings, s) def report_type_change(self): # Adjust the report type according to the combo box # This will be used in settings the the extract function and determining file locations self.processReportButton.setEnabled(False) if self.reportTypeCB.currentText() == "ACH": self.curReportType = "ach" self.extract_function = ilx.ach elif self.reportTypeCB.currentText() == "Disposition": self.curReportType = "disp" self.extract_function = ilx.disposition elif self.reportTypeCB.currentText() == "Gain Loss": self.curReportType = "gl" self.extract_function = ilx.gainloss elif self.reportTypeCB.currentText() == "Lock Box": self.curReportType = "lb" self.extract_function = ilx.lockbox elif self.reportTypeCB.currentText() == "Minv_C": self.curReportType = "minv" self.extract_function = ilx.minv elif self.reportTypeCB.currentText() == "Net Inv. Loans": self.curReportType = "niv" self.extract_function = ilx.net_invest_trial_balance elif self.reportTypeCB.currentText() == "NI Renewal": self.curReportType = "ren" self.extract_function = ilx.renewal_net_invest_trial_balance elif self.reportTypeCB.currentText() == "NIV After": self.curReportType = "niv" self.extract_function = ilx.net_invest_trial_balance elif self.reportTypeCB.currentText() == "PBP / Epay": self.curReportType = "pymt" self.extract_function = ilx.payment_transactions elif self.reportTypeCB.currentText() == "Unapplied": self.curReportType = "uap" self.extract_function = ilx.unapplied elif self.reportTypeCB.currentText() == "Past Due": self.curReportType = "pastdue" self.extract_function = ilx.pastdue elif self.reportTypeCB.currentText() == "VMCC": self.curReportType = "pymt" self.extract_function = ilx.payment_transactions elif self.reportTypeCB.currentText() == "Wires": self.curReportType = "pymt" self.extract_function = ilx.payment_transactions elif self.reportTypeCB.currentText() == "Returned Check": self.curReportType = "pymt" self.extract_function = ilx.payment_transactions inputRoot = self.settings["defaultLocations"][self.curReportType]["dir"]\ .replace("{dd}",dt.now().strftime('%d'))\ .replace("{mm}",dt.now().strftime('%m'))\ .replace("{yyyy}",dt.now().strftime('%Y')).replace("{yy}",dt.now().strftime('%y')) inputFile = self.settings["defaultLocations"][self.curReportType]["fn"]\ .replace("{dd}",dt.now().strftime('%d'))\ .replace("{mm}",dt.now().strftime('%m'))\ .replace("{yyyy}",dt.now().strftime('%Y')).replace("{yy}",dt.now().strftime('%y')) self.inputFile = f"{inputRoot}/{inputFile}" if (inputFile != '') else inputRoot self.inputFileLE.setText(self.inputFile) # Automatically sets output to be in the same file as input, with a naming scheme # The report type selected in the combo box will dictate the naming if self.inputFile == "": outputroot = ('/').join(self.inputFileLE.text().split('/')[:-1]) else: outputroot = inputRoot + '/' if self.curReportType == "minv": self.outputFile = f"{outputroot}{self.reportTypeCB.currentText()}_{dt.now().strftime('%Y%m%d_%H%M')}.txt" else: self.outputFile = f"{outputroot}{self.reportTypeCB.currentText().replace('/','')}_{dt.now().strftime('%Y%m%d_%H%M')}.xlsx" self.outputFileLE.setText(self.outputFile) self.openExcelButton.setEnabled(False) self.copyButton.setEnabled(False) self.openFolderButton.setEnabled(True) print(self.inputFile) print(self.outputFile) self.check_ready_to_process() class defLocWindow(QtWidgets.QDialog): def __init__(self, parent=None): super().__init__(parent) # Create an instance of the GUI self.ui = Ui_defaultLocationDiag() # Run the .setupUi() method to show the GUI self.ui.setupUi(self) with open("settings.json") as s: self.settings = json.loads(s.read()) self.load_user_settings() # Add dest folder buttons # Lambdas are used to create anon functions to that they don't execute at init self.ui.ach_B.clicked.connect(lambda : self.add_defloc(self.ui.ach_B.objectName(), True)) self.ui.disp_B.clicked.connect(lambda : self.add_defloc(self.ui.disp_B.objectName(), True)) self.ui.gl_B.clicked.connect(lambda : self.add_defloc(self.ui.gl_B.objectName(), True)) self.ui.lb_B.clicked.connect(lambda : self.add_defloc(self.ui.lb_B.objectName(), True)) self.ui.minv_B.clicked.connect(lambda : self.add_defloc(self.ui.minv_B.objectName(), True)) self.ui.niv_B.clicked.connect(lambda : self.add_defloc(self.ui.niv_B.objectName(), True)) self.ui.ren_B.clicked.connect(lambda : self.add_defloc(self.ui.ren_B.objectName(), True)) self.ui.pymt_B.clicked.connect(lambda : self.add_defloc(self.ui.pymt_B.objectName(), True)) self.ui.uap_B.clicked.connect(lambda : self.add_defloc(self.ui.uap_B.objectName(), True)) # Text Changes self.ui.ach_LE.textChanged.connect(lambda : self.add_defloc(self.ui.ach_B.objectName(), False)) self.ui.disp_LE.textChanged.connect(lambda : self.add_defloc(self.ui.disp_B.objectName(), False)) self.ui.gl_LE.textChanged.connect(lambda : self.add_defloc(self.ui.gl_B.objectName(), False)) self.ui.lb_LE.textChanged.connect(lambda : self.add_defloc(self.ui.lb_B.objectName(), False)) self.ui.minv_LE.textChanged.connect(lambda : self.add_defloc(self.ui.minv_B.objectName(), False)) self.ui.niv_LE.textChanged.connect(lambda : self.add_defloc(self.ui.niv_B.objectName(), False)) self.ui.ren_LE.textChanged.connect(lambda : self.add_defloc(self.ui.ren_B.objectName(), False)) self.ui.pymt_LE.textChanged.connect(lambda : self.add_defloc(self.ui.pymt_B.objectName(), False)) self.ui.uap_LE.textChanged.connect(lambda : self.add_defloc(self.ui.uap_B.objectName(), False)) self.ui.ach_FN.textChanged.connect(lambda : self.add_fn(self.ui.ach_FN.objectName())) self.ui.disp_FN.textChanged.connect(lambda : self.add_fn(self.ui.disp_FN.objectName())) self.ui.gl_FN.textChanged.connect(lambda : self.add_fn(self.ui.gl_FN.objectName())) self.ui.lb_FN.textChanged.connect(lambda : self.add_fn(self.ui.lb_FN.objectName())) self.ui.minv_FN.textChanged.connect(lambda : self.add_fn(self.ui.minv_FN.objectName())) self.ui.niv_FN.textChanged.connect(lambda : self.add_fn(self.ui.niv_FN.objectName())) self.ui.ren_FN.textChanged.connect(lambda : self.add_fn(self.ui.ren_FN.objectName())) self.ui.pymt_FN.textChanged.connect(lambda : self.add_fn(self.ui.pymt_FN.objectName())) self.ui.uap_FN.textChanged.connect(lambda : self.add_fn(self.ui.uap_FN.objectName())) self.ui.optionBBox.accepted.connect(self.save_changes) def add_defloc(self, button_name, use_filebrowser: bool): folder = QtWidgets.QFileDialog.getExistingDirectory() if use_filebrowser else None if folder == '': use_filebrowser = False report_type = button_name.split('_')[0] if report_type == "ach": if use_filebrowser: self.ui.ach_LE.setText(folder) else: folder = self.ui.ach_LE.text() elif report_type == "disp": if use_filebrowser: self.ui.disp_LE.setText(folder) else: folder = self.ui.disp_LE.text() elif report_type == "gl": if use_filebrowser: self.ui.gl_LE.setText(folder) else: folder = self.ui.gl_LE.text() elif report_type == "lb": if use_filebrowser: self.ui.lb_LE.setText(folder) else: folder = self.ui.lb_LE.text() elif report_type == "minv": if use_filebrowser: self.ui.minv_LE.setText(folder) else: folder = self.ui.minv_LE.text() elif report_type == "niv": if use_filebrowser: self.ui.niv_LE.setText(folder) else: folder = self.ui.niv_LE.text() elif report_type == "ren": if use_filebrowser: self.ui.ren_LE.setText(folder) else: folder = self.ui.ren_LE.text() elif report_type == "pymt": if use_filebrowser: self.ui.pymt_LE.setText(folder) else: folder = self.ui.pymt_LE.text() elif report_type == "uap": if use_filebrowser: self.ui.uap_LE.setText(folder) else: folder = self.ui.uap_LE.text() if folder != "": self.settings["defaultLocations"][report_type]["dir"] = folder def chg_folder(self, button_name): report_type = button_name.split('_')[0] if report_type == "ach": self.settings["defaultLocations"][report_type]["fn"] = self.ui.ach_FN.text() elif report_type == "disp": self.settings["defaultLocations"][report_type]["fn"] = self.ui.disp_FN.text() elif report_type == "gl": self.settings["defaultLocations"][report_type]["fn"] = self.ui.gl_FN.text() elif report_type == "lb": self.settings["defaultLocations"][report_type]["fn"] = self.ui.lb_FN.text() elif report_type == "minv": self.settings["defaultLocations"][report_type]["fn"] = self.ui.minv_FN.text() elif report_type == "niv": self.settings["defaultLocations"][report_type]["fn"] = self.ui.niv_FN.text() elif report_type == "ren": self.settings["defaultLocations"][report_type]["fn"] = self.ui.ren_FN.text() elif report_type == "pymt": self.settings["defaultLocations"][report_type]["fn"] = self.ui.pymt_FN.text() elif report_type == "uap": self.settings["defaultLocations"][report_type]["fn"] = self.ui.uap_FN.text() def add_fn(self, button_name): report_type = button_name.split('_')[0] if report_type == "ach": self.settings["defaultLocations"][report_type]["fn"] = self.ui.ach_FN.text() elif report_type == "disp": self.settings["defaultLocations"][report_type]["fn"] = self.ui.disp_FN.text() elif report_type == "gl": self.settings["defaultLocations"][report_type]["fn"] = self.ui.gl_FN.text() elif report_type == "lb": self.settings["defaultLocations"][report_type]["fn"] = self.ui.lb_FN.text() elif report_type == "minv": self.settings["defaultLocations"][report_type]["fn"] = self.ui.minv_FN.text() elif report_type == "niv": self.settings["defaultLocations"][report_type]["fn"] = self.ui.niv_FN.text() elif report_type == "ren": self.settings["defaultLocations"][report_type]["fn"] = self.ui.ren_FN.text() elif report_type == "pymt": self.settings["defaultLocations"][report_type]["fn"] = self.ui.pymt_FN.text() elif report_type == "uap": self.settings["defaultLocations"][report_type]["fn"] = self.ui.uap_FN.text() def load_user_settings(self): self.ui.ach_LE.setText(self.settings["defaultLocations"]["ach"]["dir"]) self.ui.ach_FN.setText(self.settings["defaultLocations"]["ach"]["fn"]) self.ui.disp_LE.setText(self.settings["defaultLocations"]["disp"]["dir"]) self.ui.disp_FN.setText(self.settings["defaultLocations"]["disp"]["fn"]) self.ui.gl_LE.setText(self.settings["defaultLocations"]["gl"]["dir"]) self.ui.gl_FN.setText(self.settings["defaultLocations"]["gl"]["fn"]) self.ui.lb_LE.setText(self.settings["defaultLocations"]["lb"]["dir"]) self.ui.lb_FN.setText(self.settings["defaultLocations"]["lb"]["fn"]) self.ui.minv_LE.setText(self.settings["defaultLocations"]["minv"]["dir"]) self.ui.minv_FN.setText(self.settings["defaultLocations"]["minv"]["fn"]) self.ui.niv_LE.setText(self.settings["defaultLocations"]["niv"]["dir"]) self.ui.niv_FN.setText(self.settings["defaultLocations"]["niv"]["fn"]) self.ui.ren_LE.setText(self.settings["defaultLocations"]["ren"]["dir"]) self.ui.ren_FN.setText(self.settings["defaultLocations"]["ren"]["fn"]) self.ui.pymt_LE.setText(self.settings["defaultLocations"]["pymt"]["dir"]) self.ui.pymt_FN.setText(self.settings["defaultLocations"]["pymt"]["fn"]) self.ui.uap_LE.setText(self.settings["defaultLocations"]["uap"]["dir"]) self.ui.uap_FN.setText(self.settings["defaultLocations"]["uap"]["fn"]) def save_changes(self): print(self.settings) with open('settings.json', 'w') as s: json.dump(self.settings, s) print(self.settings) app = QtWidgets.QApplication(sys.argv) app.setStyle("Fusion") window = MainWindow() window.setWindowTitle("IL Extract") window.show() app.exec()