recomming to make sure up to date before upload

v3.1
Griffiths Lott 3 years ago
parent 7549e84d96
commit fa7162cd43
  1. 192
      ILE_MainWindow.py
  2. 289
      ILExtract.py
  3. 42
      MINV/2022.06.09_MINV_C
  4. 51
      MINV/2022.06.10_MINV_C
  5. 33
      MINV/2022.06.13_MINV_C
  6. 40
      MINV/2022.06.14_MINV_C
  7. 32
      MINV/2022.06.15_MINV_C
  8. 44
      assets/checkedCircle.svg
  9. 60
      assets/copy.svg
  10. 6
      assets/excel.svg
  11. BIN
      assets/extract.ico
  12. 1
      assets/extract.svg
  13. 4
      assets/fileSearch.svg
  14. 2
      assets/folder.svg
  15. 24
      assets/maximize.svg
  16. 1
      assets/process.svg
  17. 62
      assets/settings.svg
  18. 1
      compile_gui
  19. 196
      defLocs_Window.py
  20. 196
      defLocs_Window2.py
  21. 377
      main.py
  22. 2
      package.sh
  23. 1
      settings.json

@ -0,0 +1,192 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'ILE_MainWindow.ui'
#
# Created by: PyQt5 UI code generator 5.15.7
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(889, 634)
icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap("assets/extract.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
MainWindow.setWindowIcon(icon)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.gridLayout_2 = QtWidgets.QGridLayout(self.centralwidget)
self.gridLayout_2.setObjectName("gridLayout_2")
self.gridLayout = QtWidgets.QGridLayout()
self.gridLayout.setObjectName("gridLayout")
self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.reportTypeL = QtWidgets.QLabel(self.centralwidget)
font = QtGui.QFont()
font.setPointSize(14)
font.setBold(True)
font.setWeight(75)
self.reportTypeL.setFont(font)
self.reportTypeL.setObjectName("reportTypeL")
self.horizontalLayout_2.addWidget(self.reportTypeL, 0, QtCore.Qt.AlignLeft)
self.reportTypeCB = QtWidgets.QComboBox(self.centralwidget)
self.reportTypeCB.setObjectName("reportTypeCB")
self.reportTypeCB.addItem("")
self.reportTypeCB.addItem("")
self.reportTypeCB.addItem("")
self.reportTypeCB.addItem("")
self.reportTypeCB.addItem("")
self.reportTypeCB.addItem("")
self.reportTypeCB.addItem("")
self.reportTypeCB.addItem("")
self.reportTypeCB.addItem("")
self.reportTypeCB.addItem("")
self.reportTypeCB.addItem("")
self.reportTypeCB.addItem("")
self.reportTypeCB.addItem("")
self.horizontalLayout_2.addWidget(self.reportTypeCB)
self.gridLayout.addLayout(self.horizontalLayout_2, 0, 0, 1, 1)
self.fileSettingsBox = QtWidgets.QVBoxLayout()
self.fileSettingsBox.setObjectName("fileSettingsBox")
self.inputFileBox = QtWidgets.QHBoxLayout()
self.inputFileBox.setObjectName("inputFileBox")
self.inputFileButton = QtWidgets.QPushButton(self.centralwidget)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Maximum)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.inputFileButton.sizePolicy().hasHeightForWidth())
self.inputFileButton.setSizePolicy(sizePolicy)
self.inputFileButton.setMinimumSize(QtCore.QSize(250, 0))
self.inputFileButton.setMaximumSize(QtCore.QSize(250, 55))
icon1 = QtGui.QIcon()
icon1.addPixmap(QtGui.QPixmap("assets/folder.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.inputFileButton.setIcon(icon1)
self.inputFileButton.setObjectName("inputFileButton")
self.inputFileBox.addWidget(self.inputFileButton)
self.inputFileLE = QtWidgets.QLineEdit(self.centralwidget)
self.inputFileLE.setReadOnly(True)
self.inputFileLE.setObjectName("inputFileLE")
self.inputFileBox.addWidget(self.inputFileLE)
self.fileSettingsBox.addLayout(self.inputFileBox)
self.outFileLocation = QtWidgets.QHBoxLayout()
self.outFileLocation.setObjectName("outFileLocation")
self.outputFileButton = QtWidgets.QPushButton(self.centralwidget)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Maximum)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.outputFileButton.sizePolicy().hasHeightForWidth())
self.outputFileButton.setSizePolicy(sizePolicy)
self.outputFileButton.setMinimumSize(QtCore.QSize(250, 0))
self.outputFileButton.setMaximumSize(QtCore.QSize(250, 55))
self.outputFileButton.setIcon(icon1)
self.outputFileButton.setObjectName("outputFileButton")
self.outFileLocation.addWidget(self.outputFileButton)
self.outputFileLE = QtWidgets.QLineEdit(self.centralwidget)
self.outputFileLE.setReadOnly(True)
self.outputFileLE.setObjectName("outputFileLE")
self.outFileLocation.addWidget(self.outputFileLE)
self.fileSettingsBox.addLayout(self.outFileLocation)
self.gridLayout.addLayout(self.fileSettingsBox, 1, 0, 1, 1)
self.horizontalLayout = QtWidgets.QHBoxLayout()
self.horizontalLayout.setObjectName("horizontalLayout")
self.processReportButton = QtWidgets.QPushButton(self.centralwidget)
self.processReportButton.setEnabled(False)
icon2 = QtGui.QIcon()
icon2.addPixmap(QtGui.QPixmap("assets/process.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.processReportButton.setIcon(icon2)
self.processReportButton.setObjectName("processReportButton")
self.horizontalLayout.addWidget(self.processReportButton)
self.copyButton = QtWidgets.QPushButton(self.centralwidget)
self.copyButton.setEnabled(False)
icon3 = QtGui.QIcon()
icon3.addPixmap(QtGui.QPixmap("assets/copy.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.copyButton.setIcon(icon3)
self.copyButton.setObjectName("copyButton")
self.horizontalLayout.addWidget(self.copyButton)
self.openFolderButton = QtWidgets.QPushButton(self.centralwidget)
self.openFolderButton.setEnabled(False)
self.openFolderButton.setIcon(icon1)
self.openFolderButton.setObjectName("openFolderButton")
self.horizontalLayout.addWidget(self.openFolderButton)
self.openExcelButton = QtWidgets.QPushButton(self.centralwidget)
self.openExcelButton.setEnabled(False)
icon4 = QtGui.QIcon()
icon4.addPixmap(QtGui.QPixmap("assets/excel.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.openExcelButton.setIcon(icon4)
self.openExcelButton.setObjectName("openExcelButton")
self.horizontalLayout.addWidget(self.openExcelButton)
self.gridLayout.addLayout(self.horizontalLayout, 2, 0, 1, 1)
self.inputFilePreview = QtWidgets.QTextBrowser(self.centralwidget)
self.inputFilePreview.setObjectName("inputFilePreview")
self.gridLayout.addWidget(self.inputFilePreview, 3, 0, 1, 1)
self.gridLayout_2.addLayout(self.gridLayout, 0, 0, 1, 1)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 889, 24))
self.menubar.setObjectName("menubar")
self.menu_Settings = QtWidgets.QMenu(self.menubar)
icon5 = QtGui.QIcon()
icon5.addPixmap(QtGui.QPixmap("assets/settings.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.menu_Settings.setIcon(icon5)
self.menu_Settings.setObjectName("menu_Settings")
self.menuStart_Maximized = QtWidgets.QMenu(self.menu_Settings)
icon6 = QtGui.QIcon()
icon6.addPixmap(QtGui.QPixmap("assets/maximize.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.menuStart_Maximized.setIcon(icon6)
self.menuStart_Maximized.setObjectName("menuStart_Maximized")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.action_Default_Locations = QtWidgets.QAction(MainWindow)
icon7 = QtGui.QIcon()
icon7.addPixmap(QtGui.QPixmap("assets/fileSearch.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.action_Default_Locations.setIcon(icon7)
self.action_Default_Locations.setObjectName("action_Default_Locations")
self.menu_Settings.addAction(self.action_Default_Locations)
self.menubar.addAction(self.menu_Settings.menuAction())
self.reportTypeL.setBuddy(self.reportTypeCB)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
MainWindow.setTabOrder(self.reportTypeCB, self.inputFileButton)
MainWindow.setTabOrder(self.inputFileButton, self.outputFileButton)
MainWindow.setTabOrder(self.outputFileButton, self.processReportButton)
MainWindow.setTabOrder(self.processReportButton, self.copyButton)
MainWindow.setTabOrder(self.copyButton, self.inputFileLE)
MainWindow.setTabOrder(self.inputFileLE, self.outputFileLE)
MainWindow.setTabOrder(self.outputFileLE, self.inputFilePreview)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "IL Extract"))
self.reportTypeL.setText(_translate("MainWindow", "Infolease Report Type:"))
self.reportTypeCB.setItemText(0, _translate("MainWindow", "ACH"))
self.reportTypeCB.setItemText(1, _translate("MainWindow", "Disposition"))
self.reportTypeCB.setItemText(2, _translate("MainWindow", "Gain Loss"))
self.reportTypeCB.setItemText(3, _translate("MainWindow", "Lock Box"))
self.reportTypeCB.setItemText(4, _translate("MainWindow", "Minv_C"))
self.reportTypeCB.setItemText(5, _translate("MainWindow", "Net Inv. Loans"))
self.reportTypeCB.setItemText(6, _translate("MainWindow", "NI Renewal"))
self.reportTypeCB.setItemText(7, _translate("MainWindow", "NIV After"))
self.reportTypeCB.setItemText(8, _translate("MainWindow", "PBP / Epay"))
self.reportTypeCB.setItemText(9, _translate("MainWindow", "Returned Check"))
self.reportTypeCB.setItemText(10, _translate("MainWindow", "Unapplied"))
self.reportTypeCB.setItemText(11, _translate("MainWindow", "VMCC"))
self.reportTypeCB.setItemText(12, _translate("MainWindow", "Wires"))
self.inputFileButton.setText(_translate("MainWindow", "Select &InfoLease Report"))
self.inputFileLE.setPlaceholderText(_translate("MainWindow", "No file selected"))
self.outputFileButton.setText(_translate("MainWindow", "Select &Report Output Location"))
self.outputFileLE.setPlaceholderText(_translate("MainWindow", "No location selected"))
self.processReportButton.setText(_translate("MainWindow", "&Process Report"))
self.copyButton.setText(_translate("MainWindow", "&Copy to Clipboard"))
self.openFolderButton.setText(_translate("MainWindow", "&Open Folder"))
self.openExcelButton.setText(_translate("MainWindow", "&Open File"))
self.menu_Settings.setTitle(_translate("MainWindow", "&Settings"))
self.action_Default_Locations.setText(_translate("MainWindow", "&Default Locations"))

@ -32,6 +32,7 @@ class ILReport:
def process(self):
print("Processing file")
try:
# Open the file and read it to a string | errors = 'replace' deals with non UTF-8 characters (no affect on output)
with open(self.location, errors="replace") as ifile:
@ -234,7 +235,6 @@ def gainloss(report: str, save_name: str):
'RCV OFFSET' : [],
'GAIN/LOSS' : [],
'DISPOSITION CODE' : [],
'DISPOSITION DESC'
'UNEARNED IDC' : [],
'UNPAID INT' : [],
'PENALTY FEE' : [],
@ -293,6 +293,52 @@ def gainloss(report: str, save_name: str):
disp_descriptoin.append(" ".join(disp_split[1:]))
df["DISPOSITION CODE"] = disp_code
df["DISPOSITION DESC"] = disp_descriptoin
df["Fund"] = df["CONTRACT NUMBER"].apply(
lambda con_num: con_num[0:3])
df = df[['Fund',
'CONTRACT NUMBER',
'CUSTOMER NAME',
'DISPOSITION CODE',
'DISPOSITION DESC',
'CASH RECEIVED',
'GAIN/LOSS',
'NET RESERVE',
'REM RENT RCVB',
'RESIDUAL',
'UNAMORT RES',
'UNEARNED FIN',
'BLENDED INC',
'END/SEC DEP',
'UNEARNED IDC',
'UNPAID INT',
'MISC',
'ASSET VAL',
'CTD OPER DEPR'
'CURR INT RCVB',
'CURR RENT RCVB',
'DEF REN INC',
'DEF REN INT',
'DISPOSITION DESCUNEARNED IDC',
'EARNED IDC',
'EQUITY ADDON',
'GST BOOK G/L',
'GUAR RESIDUAL',
'INT EARNED',
'INVENT CHANGE',
'LATE CHGS',
'MISC G/L',
'MISC TAX',
'OPER BASIS',
'OPER RCVB',
'OVER/SHORT',
'PENALTY FEE',
'RCV OFFSET',
'RENEWAL RCVBL',
'SALES TAX',
'UNPAID ACCRD',
'UNRECOG GST',
'REM RENT RCVB',
]]
df.to_excel(save_name, index=False)
return df
@ -324,14 +370,13 @@ def net_invest_trial_balance(report: str, save_name: str):
'UNPAID INT': [],
'NET INV': [],
'UNEARNED IDC': [],
"LESSOR": []
}
lessors = []
columns = list(extracted_data_dict.keys())
line0 = list(zip(columns[0:4], [0, 3, 4, 5]))
line1 = list(zip(columns[4:12], [i for i in range(0, 8)]))
line2 = list(zip(columns[12:19], [i for i in range(0, 7)]))
line3 = list(zip(columns[19:-1], [i for i in range(1,6)]))
line3 = list(zip(columns[19:], [i for i in range(1, 6)]))
for l in [line0, line1, line2, line3]:
print(f"\n{l}")
@ -339,7 +384,8 @@ def net_invest_trial_balance(report: str, save_name: str):
data_extractor = create_line_divider([18, 32, 50, 66, 84, 100, 117])
for line in enumerate(lines):
slot1 = data_extractor(0, line[1], False)
if type(slot1) != str : continue
if type(slot1) != str:
continue
if re.search(contract_number_regex, slot1) != None:
data_section = lines[line[0]-1:line[0]+3]
# There were issues were the IL Report would have random blank lines so that needs to be checked
@ -361,40 +407,127 @@ def net_invest_trial_balance(report: str, save_name: str):
else:
data_section[3] = lines[line[0]+3]
# Now that the datasection is sorted we can extract the data
[extracted_data_dict[c[0]].append(data_extractor(c[1], data_section[0], False)) for c in line0]
[extracted_data_dict[c[0]].append(data_extractor(c[1], data_section[1], False)) for c in line1]
[extracted_data_dict[c[0]].append(data_extractor(c[1], data_section[2], False)) for c in line2]
[extracted_data_dict[c[0]].append(data_extractor(c[1], data_section[3], False)) for c in line3]
extracted_data_dict["LESSOR"].append(extracted_data_dict["LEASE NUMBER"][-1][0:3])
# We keep track of when we see new lessors for a summary tab
if extracted_data_dict["LESSOR"][-1] not in lessors:
lessors.append(extracted_data_dict["LESSOR"][-1])
[extracted_data_dict[c[0]].append(data_extractor(
c[1], data_section[0], False)) for c in line0]
[extracted_data_dict[c[0]].append(data_extractor(
c[1], data_section[1], False)) for c in line1]
[extracted_data_dict[c[0]].append(data_extractor(
c[1], data_section[2], False)) for c in line2]
[extracted_data_dict[c[0]].append(data_extractor(
c[1], data_section[3], False)) for c in line3]
dataframe = pd.DataFrame(extracted_data_dict)
dataframe["LESSOR"] = dataframe["LEASE NUMBER"].apply(lambda con: con[0:3])
dataframe = dataframe.replace("REVOLV", np.NaN)
dataframe = dataframe.replace("ING ACCOUNT", np.NaN)
dataframe = dataframe.replace("", np.NaN)
prt(dataframe)
summary = pd.pivot_table(dataframe,
values=['CUSTOMER NAME',
'RESIDUAL',
'UNEARN FIN',
'UNEARNED BLENDED',
'UNEARN RESID',
'SEC DEPOSIT',
'UNEARNED IDC',
'NET RESERVE',
'UNPAID INT',
'NET INV',
'BLEND NET INV',
'GROSS CONTRACT',
'PAYMENTS RCVD',
'REM RENT RCVB',
'LEASE PYMTS',
'UNEARN INC',
'TOTAL',
'CURR INT RCVB',
'PROV LOSS',
'CURR RENT RCVB',
'END DEPOSIT',
],
aggfunc={
'CUSTOMER NAME': np.size,
'RESIDUAL': np.sum,
'UNEARN FIN': np.sum,
'UNEARNED BLENDED': np.sum,
'UNEARN RESID': np.sum,
'SEC DEPOSIT': np.sum,
'UNEARNED IDC': np.sum,
'NET RESERVE': np.sum,
'UNPAID INT': np.sum,
'NET INV': np.sum,
'BLEND NET INV': np.sum,
'GROSS CONTRACT': np.sum,
'PAYMENTS RCVD': np.sum,
'REM RENT RCVB': np.sum,
'LEASE PYMTS': np.sum,
'UNEARN INC': np.sum,
'TOTAL': np.sum,
'CURR INT RCVB': np.sum,
'PROV LOSS': np.sum,
'CURR RENT RCVB': np.sum,
'END DEPOSIT': np.sum,
},
index="LESSOR")
summary.rename(columns={"CUSTOMER NAME": "Contract Count"}, inplace=True)
summary = summary[['Contract Count',
'REM RENT RCVB',
'RESIDUAL',
'UNEARN FIN',
'UNEARNED BLENDED',
'UNEARN RESID',
'SEC DEPOSIT',
'UNEARNED IDC',
'NET RESERVE',
'UNPAID INT',
'NET INV',
'BLEND NET INV',
'GROSS CONTRACT',
'PAYMENTS RCVD',
'REM RENT RCVB',
'LEASE PYMTS',
'UNEARN INC',
'TOTAL',
'CURR INT RCVB',
'PROV LOSS',
'CURR RENT RCVB',
'END DEPOSIT',
]]
dataframe = dataframe[['LESSOR',
'LEASE NUMBER',
'REM RENT RCVB',
'RESIDUAL',
'UNEARN FIN',
'UNEARNED BLENDED',
'UNEARN RESID',
'SEC DEPOSIT',
'NET RESERVE',
'UNEARNED IDC',
'CURR INT RCVB',
'BLEND NET INV',
'NET INV',
'CUSTOMER NAME',
'GROSS CONTRACT',
'CURR RENT RCVB',
'END DEPOSIT',
'LEASE PYMTS',
'TOTAL',
'CONTRACT STAT',
'PAYMENTS RCVD',
'PROV LOSS',
'UNEARN INC',
'BAL REMAINING',
'UNPAID INT',
]]
summary_series = []
for lessor in lessors:
reduced_df = dataframe.loc[dataframe["LESSOR"] == lessor]
# Delete columns that are strings as we don't need to sum them
del reduced_df["CUSTOMER NAME"]
del reduced_df["LEASE NUMBER"]
del reduced_df["CONTRACT STAT"]
reduced_df = reduced_df.replace("", np.NaN)
# There can sometimes be REVOLVING ACCOUNT over part of the data
# Just get rid of it
reduced_df = reduced_df.replace("REVOLV", np.NaN)
reduced_df = reduced_df.replace("ING ACCOUNT", np.NaN)
summation = reduced_df.sum(skipna=True, axis=0)
summation["LESSOR"] = lessor
summation["CONTRACT COUNT"] = len(reduced_df.index)
summary_series.append(summation)
summary_df = pd.concat(summary_series, axis=1).transpose().set_index("LESSOR")
with pd.ExcelWriter(save_name) as writer:
dataframe.to_excel(writer, index=False, sheet_name="data")
pd.DataFrame(summary_df).to_excel(writer, index=True, sheet_name="Summary")
pd.DataFrame(summary_df).to_excel(
writer, index=True, sheet_name="Summary")
return dataframe
def lockbox(report: str, save_name: str):
lines = report.splitlines()
extracted_data_dict = {
@ -447,6 +580,7 @@ def lockbox(report: str, save_name: str):
def minv(report: str, save_name: str):
print("Started minv process")
lines = report.splitlines()
data_extractor = create_line_divider([15,32,52,71,83,107,116,128])
extracted_data_dict = {
@ -464,15 +598,18 @@ def minv(report: str, save_name: str):
for line in enumerate(lines):
if re.search(contract_number_regex, line[1]) != None:
[extracted_data_dict[columns[c]].append(data_extractor(c,line[1],debug=False)) for c in range(0,len(columns))]
#All the list lengths need to be the same so if anything was missed it will fail to build
dataframe = pd.DataFrame(extracted_data_dict)
filtered = dataframe[
((dataframe["BookingDate"] != '04/26/2022') & (dataframe["RentalDue"] > 0)) |\
((dataframe["BookingDate"] != '04/26/2022') & (dataframe["RentalDue"] == 0) & (dataframe["OutstandBalance"] > 100))]
#filtered.to_excel(save_name, index=False)
filtered = dataframe[(dataframe["BookingDate"] != dt.today().strftime("%m/%d/%Y")) &
((dataframe["RentalDue"] > 0) | ((dataframe["RentalDue"] == 0) & (dataframe["OutstandBalance"] > 100)))]
with open(save_name, 'w') as output:
[output.write(f"{contract}\n") for contract in filtered['ContractNumber'].to_list()]
add_contracts = []
for contract in filtered['ContractNumber'].to_list():
output.write(f"{contract}\n") if contract not in add_contracts else None
add_contracts.append(contract)
return filtered
# Good for PUB_WIRES, VMCC, PBP_EPAY, returned check
def payment_transactions(report: str, save_name: str):
lines = report.splitlines()
@ -543,7 +680,8 @@ def renewal_net_invest_trial_balance(report: str, save_name: str):
for line in enumerate(lines):
slot1 = data_extractor(0, line[1], False)
if type(slot1) != str : continue
if type(slot1) != str:
continue
if re.search(contract_number_regex, slot1) != None:
data_section = lines[line[0]-1:line[0]+2]
# SEE net_invest_trial_balance FOR EXPLAINATION
@ -558,11 +696,80 @@ def renewal_net_invest_trial_balance(report: str, save_name: str):
else:
data_section[2] = lines[line[0]+2]
[extracted_data_dict[c[0]].append(data_extractor(c[1], data_section[0])) for c in line0]
[extracted_data_dict[c[0]].append(data_extractor(c[1], data_section[1])) for c in line1]
[extracted_data_dict[c[0]].append(data_extractor(c[1], data_section[2])) for c in line2]
[extracted_data_dict[c[0]].append(
data_extractor(c[1], data_section[0])) for c in line0]
[extracted_data_dict[c[0]].append(
data_extractor(c[1], data_section[1])) for c in line1]
[extracted_data_dict[c[0]].append(
data_extractor(c[1], data_section[2])) for c in line2]
dataframe = pd.DataFrame(extracted_data_dict)
dataframe.to_excel(save_name, index=False)
dataframe["Fund"] = dataframe["CONTRACT NUMBER"].apply(
lambda con_num: con_num[0:3])
summary = pd.pivot_table(dataframe,
values=['CUSTOMER NAME',
"UNPAID RES", "REMAINING RES", "SECURITY DEP", 'GROSS RENEWAL',
"FINANCED RES", "LEASE PYMTS", "PAYMENTS RCVD", "NET INVEST", "TOTAL",
"CUR RENT RCVB", "UNEARNED RIN", "UNEARN INCOME", "REM RENT RCVB"],
aggfunc={
'CUSTOMER NAME': np.size,
"UNPAID RES": np.sum,
"REMAINING RES": np.sum,
"SECURITY DEP": np.sum,
'GROSS RENEWAL': np.sum,
"FINANCED RES": np.sum,
"LEASE PYMTS": np.sum,
"PAYMENTS RCVD": np.sum,
"NET INVEST": np.sum,
"TOTAL": np.sum,
"CUR RENT RCVB": np.sum,
"UNEARNED RIN": np.sum,
"UNEARN INCOME": np.sum,
"REM RENT RCVB": np.sum
},
index="Fund")
summary.rename(columns={"CUSTOMER NAME": "Renewal Count"}, inplace=True)
summary = summary[['LESSOR',
'RENEWAL COUNT'
'UNPAID RES'
'REMAINING RES',
'SECURITY DEP',
'GROSS RENEWAL',
'REMAINING RES',
'FINANCED RES',
'LEASE PYMTS',
'PAYMENTS RCVD',
'NET INVEST',
'TOTAL',
'CUR RENT RCVB',
'UNEARNED RIN',
'UNEARN INCOME',
'REM RENT RCVB',
]]
dataframe = dataframe[['Fund',
'CONTRACT NUMBER',
'TYPE',
'RENEWAL',
'UNPAID RES'
'REMAINING RES',
'SECURITY DEP',
'GROSS RENEWAL',
'FINANCED RES',
'PAYMENTS RCVD',
'NET INVEST',
'REMAINING BAL',
'CUSTOMER NAME',
'LEASE PYMTS',
'CUR RENT RCVB',
'UNEARNED RIN',
'UNEARN INCOME',
'TOTAL',
'REM RENT RCVB',
]]
with pd.ExcelWriter(save_name) as writer:
dataframe.to_excel(writer, index=False, sheet_name="data")
pd.DataFrame(summary).to_excel(
writer, index=True, sheet_name="Summary")
return dataframe

@ -0,0 +1,42 @@
DAILY.MANUAL.INVOICE
CONTRACTS THAT WERE NOT INVOICED
PAGE 06-09-22 1
CHRG BUSINESS
CONTRACT.NO........ UATB.OIC.DUE RENTAL DUE......... UATB.IDS.OIC.PAYME TYPEM..... OUTSTANDING BALANCE.... SEGMENT. BOOKING.DATE BRANCH
100-0553300-001 04/01/2022 413.81 0.00 RENT 413.81 001.000 11/01/2020 4.3
047-4725409-001 04/14/2022 351.30 0.00 MISC 380.28 001.000 01/14/2019 3
100-1864627-002 05/14/2022 146.71 156.07 MISC 9.36 001.000 07/14/2017 9
100-6651721-001 07/14/2021 0.00 761.00 MISC 53.27 001.000 07/14/2021 9
100-0553300-001 05/01/2022 413.81 0.00 RENT 413.81 001.000 11/01/2020 4.3
100-6651721-002 07/25/2021 0.00 761.00 MISC 53.27 001.000 07/27/2021 9
100-0553300-001 01/01/2022 413.81 319.43 RENT 94.38 001.000 11/01/2020 4.3
047-4725409-001 05/14/2022 351.30 31.54 MISC 348.74 001.000 01/14/2019 3
100-5047921-001 06/15/2022 94.69 0.00 RENT 94.69 001.000 04/11/2019 3
100-3285968-004 05/25/2022 2,027.75 0.00 MISC 2,139.28 001.000 02/27/2019 9
100-0553300-001 06/01/2022 413.81 0.00 RENT 413.81 001.000 11/01/2020 4.3
100-0553300-001 02/01/2022 413.81 0.00 RENT 413.81 001.000 11/01/2020 4.3
100-7218171-001 05/19/2022 0.00 157.00 MISC 10.60 001.000 05/19/2022 3
047-4725409-001 06/14/2022 351.30 0.00 MISC 380.28 001.000 01/14/2019 3
100-5189011-002 07/01/2022 130.58 275.67 RENT 130.58 001.000 07/16/2019 12
100-2772548-003 06/25/2022 -830.51 0.00 MISC 601.48 001.000 05/30/2017 9
100-3285968-004 06/25/2022 2,027.75 0.00 MISC 2,139.28 001.000 02/27/2019 9
047-2903398-005 05/25/2022 0.00 0.00 MISC 58.25 001.000 04/25/2017 9
100-2911448-002 05/25/2022 0.00 1,895.04 RENT 30.43 001.000 04/29/2022 9
100-0553300-001 07/01/2022 413.81 0.00 RENT 413.81 001.000 11/01/2020 4.3
100-0553300-001 03/01/2022 413.81 0.00 RENT 413.81 001.000 11/01/2020 4.3
100-7220451-001 06/06/2022 0.00 171.00 RENT 19.45 001.000 06/06/2022 3
100-7268381-001 06/06/2022 0.00 151.00 RENT 11.33 001.000 06/06/2022 3
100-7314881-001 06/06/2022 0.00 119.00 RENT 9.88 001.000 06/06/2022 3
100-7317551-001 06/25/2022 2,916.00 0.00 RENT 2,916.00 001.000 05/27/2022 12
100-7289411-001 07/03/2022 556.33 0.00 RENT 556.33 001.000 06/03/2022 3
100-7304881-002 07/01/2022 60.90 0.00 MISC 66.27 001.000 06/08/2022 9
100-6943321-002 06/15/2022 8,012.77 0.03 RENT 8,012.77 001.000 04/12/2022 9
100-1477460-002 07/08/2022 34,915.99 0.00 RENT 34,915.99 001.000 06/08/2022 12
100-1516251-002 06/20/2022 1,485.99 0.00 RENT 1,485.99 001.000 09/24/2019 10
100-7352541-001 06/09/2022 1,422.30 0.00 RENT 711.15 001.000 06/09/2022 3
100-7352541-001 06/09/2022 1,422.30 0.00 RENT 711.15 001.000 06/09/2022 3
100-9677665-001 06/25/2022 242.11 0.00 RENT 242.11 001.000 08/30/2021 10
33 records listed

@ -0,0 +1,51 @@
DAILY.MANUAL.INVOICE
CONTRACTS THAT WERE NOT INVOICED
PAGE 06-10-22 1
CHRG BUSINESS
CONTRACT.NO........ UATB.OIC.DUE RENTAL DUE......... UATB.IDS.OIC.PAYME TYPEM..... OUTSTANDING BALANCE.... SEGMENT. BOOKING.DATE BRANCH
100-1049364-003 03/15/2022 79.56 0.00 RENT 79.56 001.000 10/01/2021 4.3
100-1049364-003 04/15/2022 79.56 0.00 RENT 79.56 001.000 10/01/2021 4.3
100-6651721-001 07/14/2021 0.00 761.00 MISC 53.27 001.000 07/14/2021 9
100-1049364-003 12/15/2021 79.56 68.40 RENT 11.16 001.000 10/01/2021 4.3
100-6651721-002 07/25/2021 0.00 761.00 MISC 53.27 001.000 07/27/2021 9
100-1049364-003 05/15/2022 79.56 0.00 RENT 79.56 001.000 10/01/2021 4.3
100-1049364-003 01/15/2022 79.56 0.00 RENT 79.56 001.000 10/01/2021 4.3
100-2170587-001 05/21/2022 484.62 0.00 RENT 484.62 001.000 03/26/2013 9
100-7218171-001 05/19/2022 0.00 157.00 MISC 10.60 001.000 05/19/2022 3
100-1049364-003 06/15/2022 79.56 0.00 RENT 79.56 001.000 10/01/2021 4.3
100-1049364-003 02/15/2022 79.56 0.00 RENT 79.56 001.000 10/01/2021 4.3
100-2170587-001 06/21/2022 484.62 0.00 RENT 484.62 001.000 03/26/2013 9
100-2772548-003 06/25/2022 -830.51 0.00 MISC 601.48 001.000 05/30/2017 9
047-2903398-005 05/25/2022 0.00 0.00 MISC 58.25 001.000 04/25/2017 9
100-2911448-002 05/25/2022 0.00 1,895.04 RENT 30.43 001.000 04/29/2022 9
100-7220451-001 06/06/2022 0.00 171.00 RENT 19.45 001.000 06/06/2022 3
100-7268381-001 06/06/2022 0.00 151.00 RENT 11.33 001.000 06/06/2022 3
100-7314881-001 06/06/2022 0.00 119.00 RENT 9.88 001.000 06/06/2022 3
100-7352541-001 06/09/2022 0.00 0.00 RENT 711.15 001.000 06/09/2022 3
100-7352541-001 06/09/2022 0.00 0.00 RENT 711.15 001.000 06/09/2022 3
100-9678164-001 06/25/2022 242.11 0.00 RENT 242.11 001.000 08/31/2021 10
100-1570785-001 06/24/2022 765.50 0.00 RENT 765.50 001.000 02/24/2020 10
100-4693949-001 06/17/2022 326.11 0.00 RENT 326.11 001.000 10/17/2018 3
100-1500564-011 07/04/2022 1,239.97 0.00 RENT 1,239.97 001.000 06/09/2022 12
100-9704497-001 06/16/2022 2,127.68 0.00 RENT 2,127.68 001.000 02/16/2022 10
100-7318371-001 07/01/2022 257.76 0.00 RENT 257.76 001.000 06/09/2022 9
100-1697447-005 06/20/2022 184.11 0.00 RENT 184.11 001.000 08/23/2019 3
100-1697447-004 06/20/2022 287.93 0.00 RENT 287.93 001.000 07/30/2019 3
100-4714407-008 07/01/2022 671.57 0.00 MISC 714.21 001.000 06/09/2022 9
100-6051107-001 06/20/2022 30.15 39.99 RENT 30.15 001.000 09/08/2020 9
100-3240348-006 06/14/2022 227.52 0.00 MISC 241.17 001.000 04/14/2022 9
100-6795737-003 07/10/2022 0.00 0.00 RENT 30,000.00 001.000 06/10/2022 12
100-9729335-001 06/10/2022 1,841.70 0.00 RENT 920.85 001.000 06/10/2022 10
100-9729335-001 06/10/2022 1,841.70 0.00 RENT 920.85 001.000 06/10/2022 10
100-7252451-001 06/10/2022 15.63 169.00 RENT 15.63 001.000 06/10/2022 3
100-6238218-001 06/19/2022 74.99 0.00 RENT 74.99 001.000 11/19/2021 9
100-7337851-001 06/10/2022 216.36 0.00 RENT 108.18 001.000 06/10/2022 3
100-7337851-001 06/10/2022 216.36 0.00 RENT 108.18 001.000 06/10/2022 3
100-7275051-001 06/10/2022 0.00 843.27 MISC 0.01 001.000 06/10/2022 3
100-1017678-003 07/01/2022 718.61 0.00 MISC 777.89 001.000 05/16/2019 12
100-4266879-003 07/03/2022 339.42 0.00 MISC 368.95 001.000 06/10/2022 9
41 records listed

@ -0,0 +1,33 @@
DAILY.MANUAL.INVOICE
CONTRACTS THAT WERE NOT INVOICED
PAGE 06-13-22 1
CHRG BUSINESS
CONTRACT.NO........ UATB.OIC.DUE RENTAL DUE......... UATB.IDS.OIC.PAYME TYPEM..... OUTSTANDING BALANCE.... SEGMENT. BOOKING.DATE BRANCH
100-6651721-001 07/14/2021 0.00 761.00 MISC 53.27 001.000 07/14/2021 9
100-6550098-001 05/20/2022 619.26 108.80 RENT 510.46 001.000 05/25/2021 3
100-6651721-002 07/25/2021 0.00 761.00 MISC 53.27 001.000 07/27/2021 9
100-7218171-001 05/19/2022 0.00 157.00 MISC 10.60 001.000 05/19/2022 3
100-2772548-003 06/25/2022 -830.51 0.00 MISC 601.48 001.000 05/30/2017 9
047-2903398-005 05/25/2022 0.00 0.00 MISC 58.25 001.000 04/25/2017 9
100-2911448-002 05/25/2022 0.00 1,895.04 RENT 30.43 001.000 04/29/2022 9
100-6795737-003 07/10/2022 30,000.00 0.00 RENT 30,000.00 001.000 06/10/2022 12
100-7252451-001 06/10/2022 0.00 169.00 RENT 15.63 001.000 06/10/2022 3
100-6238218-001 06/19/2022 74.99 0.00 RENT 74.99 001.000 11/19/2021 9
100-7337851-001 06/10/2022 0.00 0.00 RENT 108.18 001.000 06/10/2022 3
100-7337851-001 06/10/2022 0.00 0.00 RENT 108.18 001.000 06/10/2022 3
100-7275051-001 06/10/2022 0.00 843.27 MISC 0.01 001.000 06/10/2022 3
100-4266879-003 07/03/2022 339.42 0.00 MISC 368.95 001.000 06/10/2022 9
100-7203501-002 07/01/2022 40.00 0.00 MISC 42.50 001.000 06/10/2022 9
100-7282331-001 06/10/2022 0.00 0.00 RENT 1,432.54 001.000 06/10/2022 3
100-9735444-001 06/10/2022 0.00 0.00 RENT 214.90 001.000 06/10/2022 10
100-9735444-001 06/10/2022 0.00 0.00 RENT 214.90 001.000 06/10/2022 10
100-6930421-001 06/10/2022 0.00 0.00 RENT 1,982.24 001.000 06/10/2022 3
100-6930421-001 06/10/2022 0.00 0.00 RENT 1,982.24 001.000 06/10/2022 3
100-6721551-003 06/20/2022 1,210.36 0.00 RENT 1,210.36 001.000 09/24/2021 3
100-6721551-002 06/20/2022 613.92 0.00 RENT 613.92 001.000 09/23/2021 3
100-7136271-001 07/20/2022 176.54 0.00 RENT 176.54 001.000 03/22/2022 3
100-7171001-001 06/17/2022 68.92 0.00 RENT 68.92 001.000 03/17/2022 9
24 records listed

@ -0,0 +1,40 @@
DAILY.MANUAL.INVOICE
CONTRACTS THAT WERE NOT INVOICED
PAGE 06-14-22 1
CHRG BUSINESS
CONTRACT.NO........ UATB.OIC.DUE RENTAL DUE......... UATB.IDS.OIC.PAYME TYPEM..... OUTSTANDING BALANCE.... SEGMENT. BOOKING.DATE BRANCH
100-7269201-001 06/14/2022 17.11 172.00 RENT 17.11 001.000 06/14/2022 3
100-3654949-003 06/24/2022 1,086.99 0.00 RENT 1,086.99 001.000 09/24/2019 9
100-3654949-002 06/20/2022 1,789.52 0.00 RENT 1,789.52 001.000 09/19/2019 9
100-7199137-001 06/20/2022 1,068.97 0.00 RENT 1,068.97 001.000 04/29/2022 3
100-7284391-001 07/08/2022 91.25 0.00 RENT 91.25 001.000 06/08/2022 9
100-7209951-001 06/14/2022 0.00 160.00 MISC 11.20 001.000 06/14/2022 3
100-7334181-001 07/01/2022 338.41 0.00 MISC 366.32 001.000 06/14/2022 9
100-9570778-001 06/24/2022 637.91 0.00 RENT 637.91 001.000 02/24/2020 10
100-7234311-001 06/14/2022 15.81 204.00 RENT 15.81 001.000 06/14/2022 3
100-7294191-001 06/14/2022 14.80 160.00 RENT 14.80 001.000 06/14/2022 3
100-0849508-002 04/15/2022 2,392.50 0.00 RENT 2,392.50 001.000 10/01/2021 4.3
100-6651721-001 07/14/2021 0.00 761.00 MISC 53.27 001.000 07/14/2021 9
100-6651721-002 07/25/2021 0.00 761.00 MISC 53.27 001.000 07/27/2021 9
100-0849508-002 05/15/2022 2,392.50 0.00 RENT 2,392.50 001.000 10/01/2021 4.3
100-0849508-002 06/15/2022 2,392.50 0.00 RENT 2,392.50 001.000 10/01/2021 4.3
100-2772548-003 06/25/2022 -830.51 0.00 MISC 601.48 001.000 05/30/2017 9
100-3618019-001 06/25/2022 428.34 0.00 MISC 466.36 001.000 09/28/2016 9
047-2903398-005 05/25/2022 0.00 0.00 MISC 58.25 001.000 04/25/2017 9
100-2911448-002 05/25/2022 0.00 1,895.04 RENT 30.43 001.000 04/29/2022 9
100-7252451-001 06/10/2022 0.00 169.00 RENT 15.63 001.000 06/10/2022 3
100-7275051-001 06/10/2022 0.00 843.27 MISC 0.01 001.000 06/10/2022 3
100-7113121-001 07/13/2022 2,500.39 0.00 RENT 2,500.39 001.000 06/13/2022 3
100-7342981-001 07/08/2022 103.56 0.00 MISC 109.77 001.000 06/08/2022 9
100-7113391-002 07/01/2022 2,275.30 0.00 RENT 2,275.30 001.000 06/13/2022 3
100-5398561-002 07/01/2022 786.33 0.00 MISC 847.27 001.000 06/13/2022 9
100-4457819-001 06/20/2022 5,785.12 0.00 RENT 5,785.12 001.000 05/31/2018 3
100-3744149-012 07/08/2022 50.00 0.00 MISC 53.00 001.000 06/13/2022 9
100-3154768-008 07/01/2022 897.26 0.00 MISC 980.27 001.000 06/13/2022 9
100-7318021-001 07/03/2022 295.00 0.00 MISC 320.08 001.000 06/13/2022 9
100-2146226-002 07/01/2022 558.96 0.00 RENT 558.96 001.000 06/13/2022 9
30 records listed

@ -0,0 +1,32 @@
DAILY.MANUAL.INVOICE
CONTRACTS THAT WERE NOT INVOICED
PAGE 06-15-22 1
CHRG BUSINESS
CONTRACT.NO........ UATB.OIC.DUE RENTAL DUE......... UATB.IDS.OIC.PAYME TYPEM..... OUTSTANDING BALANCE.... SEGMENT. BOOKING.DATE BRANCH
100-7269201-001 06/14/2022 0.00 172.00 RENT 17.11 001.000 06/14/2022 3
100-7209951-001 06/14/2022 0.00 160.00 MISC 11.20 001.000 06/14/2022 3
100-7334181-001 07/01/2022 338.41 0.00 MISC 366.32 001.000 06/14/2022 9
100-7234311-001 06/14/2022 0.00 204.00 RENT 15.81 001.000 06/14/2022 3
100-7294191-001 06/14/2022 0.00 160.00 RENT 14.80 001.000 06/14/2022 3
100-9570729-001 06/24/2022 637.91 0.00 RENT 637.91 001.000 02/24/2020 10
100-7080901-001 06/14/2022 0.00 0.00 MISC 177.62 001.000 06/14/2022 3
100-7313341-001 07/09/2022 217.00 0.00 RENT 217.00 001.000 06/14/2022 9
100-7363251-001 06/14/2022 0.00 0.00 RENT 13,168.80 001.000 06/14/2022 3
100-1564449-001 07/03/2022 430.01 0.00 RENT 430.01 001.000 02/03/2020 10
100-7233611-001 06/15/2022 17.36 179.00 RENT 17.36 001.000 06/15/2022 3
100-7151111-001 06/15/2022 480.40 0.00 RENT 480.40 001.000 06/15/2022 9
100-9737145-001 06/15/2022 590.20 0.00 RENT 295.10 001.000 06/15/2022 10
100-9737145-001 06/15/2022 590.20 0.00 RENT 295.10 001.000 06/15/2022 10
100-7303761-001 08/14/2022 0.00 0.00 RENT 240,632.43 001.000 06/14/2022 12
100-6651721-001 07/14/2021 0.00 761.00 MISC 53.27 001.000 07/14/2021 9
100-6651721-002 07/25/2021 0.00 761.00 MISC 53.27 001.000 07/27/2021 9
100-6726271-001 06/15/2022 1,588.04 0.00 RENT 1,588.04 001.000 08/31/2021 12
100-2772548-003 06/25/2022 -830.51 0.00 MISC 601.48 001.000 05/30/2017 9
047-2903398-005 05/25/2022 0.00 0.00 MISC 58.25 001.000 04/25/2017 9
100-2911448-002 05/25/2022 0.00 1,895.04 RENT 30.43 001.000 04/29/2022 9
100-5864201-501 07/07/2022 143.00 0.00 MISC 153.01 001.000 09/01/2020 9
22 records listed

@ -0,0 +1,44 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 18.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 330 330" style="enable-background:new 0 0 330 330;" xml:space="preserve">
<g>
<path d="M165,0C74.019,0,0,74.019,0,165s74.019,165,165,165s165-74.019,165-165S255.981,0,165,0z M165,300
c-74.44,0-135-60.561-135-135S90.56,30,165,30s135,60.561,135,135S239.439,300,165,300z"/>
<path d="M226.872,106.664l-84.854,84.853l-38.89-38.891c-5.857-5.857-15.355-5.858-21.213-0.001
c-5.858,5.858-5.858,15.355,0,21.213l49.496,49.498c2.813,2.813,6.628,4.394,10.606,4.394c0.001,0,0,0,0.001,0
c3.978,0,7.793-1.581,10.606-4.393l95.461-95.459c5.858-5.858,5.858-15.355,0-21.213
C242.227,100.807,232.73,100.806,226.872,106.664z"/>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

@ -0,0 +1,60 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 19.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 64 64" enable-background="new 0 0 64 64" xml:space="preserve">
<g id="Text-files">
<path d="M53.9791489,9.1429005H50.010849c-0.0826988,0-0.1562004,0.0283995-0.2331009,0.0469999V5.0228
C49.7777481,2.253,47.4731483,0,44.6398468,0h-34.422596C7.3839517,0,5.0793519,2.253,5.0793519,5.0228v46.8432999
c0,2.7697983,2.3045998,5.0228004,5.1378999,5.0228004h6.0367002v2.2678986C16.253952,61.8274002,18.4702511,64,21.1954517,64
h32.783699c2.7252007,0,4.9414978-2.1725998,4.9414978-4.8432007V13.9861002
C58.9206467,11.3155003,56.7043495,9.1429005,53.9791489,9.1429005z M7.1110516,51.8661003V5.0228
c0-1.6487999,1.3938999-2.9909999,3.1062002-2.9909999h34.422596c1.7123032,0,3.1062012,1.3422,3.1062012,2.9909999v46.8432999
c0,1.6487999-1.393898,2.9911003-3.1062012,2.9911003h-34.422596C8.5049515,54.8572006,7.1110516,53.5149002,7.1110516,51.8661003z
M56.8888474,59.1567993c0,1.550602-1.3055,2.8115005-2.9096985,2.8115005h-32.783699
c-1.6042004,0-2.9097996-1.2608986-2.9097996-2.8115005v-2.2678986h26.3541946
c2.8333015,0,5.1379013-2.2530022,5.1379013-5.0228004V11.1275997c0.0769005,0.0186005,0.1504021,0.0469999,0.2331009,0.0469999
h3.9682999c1.6041985,0,2.9096985,1.2609005,2.9096985,2.8115005V59.1567993z"/>
<path d="M38.6031494,13.2063999H16.253952c-0.5615005,0-1.0159006,0.4542999-1.0159006,1.0158005
c0,0.5615997,0.4544001,1.0158997,1.0159006,1.0158997h22.3491974c0.5615005,0,1.0158997-0.4542999,1.0158997-1.0158997
C39.6190491,13.6606998,39.16465,13.2063999,38.6031494,13.2063999z"/>
<path d="M38.6031494,21.3334007H16.253952c-0.5615005,0-1.0159006,0.4542999-1.0159006,1.0157986
c0,0.5615005,0.4544001,1.0159016,1.0159006,1.0159016h22.3491974c0.5615005,0,1.0158997-0.454401,1.0158997-1.0159016
C39.6190491,21.7877007,39.16465,21.3334007,38.6031494,21.3334007z"/>
<path d="M38.6031494,29.4603004H16.253952c-0.5615005,0-1.0159006,0.4543991-1.0159006,1.0158997
s0.4544001,1.0158997,1.0159006,1.0158997h22.3491974c0.5615005,0,1.0158997-0.4543991,1.0158997-1.0158997
S39.16465,29.4603004,38.6031494,29.4603004z"/>
<path d="M28.4444485,37.5872993H16.253952c-0.5615005,0-1.0159006,0.4543991-1.0159006,1.0158997
s0.4544001,1.0158997,1.0159006,1.0158997h12.1904964c0.5615025,0,1.0158005-0.4543991,1.0158005-1.0158997
S29.0059509,37.5872993,28.4444485,37.5872993z"/>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

@ -0,0 +1,6 @@
<svg width="24px" height="24px" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<g>
<path fill="none" d="M0 0h24v24H0z"/>
<path d="M2.859 2.877l12.57-1.795a.5.5 0 0 1 .571.495v20.846a.5.5 0 0 1-.57.495L2.858 21.123a1 1 0 0 1-.859-.99V3.867a1 1 0 0 1 .859-.99zM4 4.735v14.53l10 1.429V3.306L4 4.735zM17 19h3V5h-3V3h4a1 1 0 0 1 1 1v16a1 1 0 0 1-1 1h-4v-2zm-6.8-7l2.8 4h-2.4L9 13.714 7.4 16H5l2.8-4L5 8h2.4L9 10.286 10.6 8H13l-2.8 4z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 477 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 18 KiB

@ -0,0 +1,4 @@
<?xml version="1.0" standalone="no"?>
<svg width="1024px" height="1024px" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" class="icon">
<path d="M688 312v-48c0-4.4-3.6-8-8-8H296c-4.4 0-8 3.6-8 8v48c0 4.4 3.6 8 8 8h384c4.4 0 8-3.6 8-8zm-392 88c-4.4 0-8 3.6-8 8v48c0 4.4 3.6 8 8 8h184c4.4 0 8-3.6 8-8v-48c0-4.4-3.6-8-8-8H296zm144 452H208V148h560v344c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V108c0-17.7-14.3-32-32-32H168c-17.7 0-32 14.3-32 32v784c0 17.7 14.3 32 32 32h272c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm445.7 51.5l-93.3-93.3C814.7 780.7 828 743.9 828 704c0-97.2-78.8-176-176-176s-176 78.8-176 176 78.8 176 176 176c35.8 0 69-10.7 96.8-29l94.7 94.7c1.6 1.6 3.6 2.3 5.6 2.3s4.1-.8 5.6-2.3l31-31a7.9 7.9 0 0 0 0-11.2zM652 816c-61.9 0-112-50.1-112-112s50.1-112 112-112 112 50.1 112 112-50.1 112-112 112z"/>
</svg>

After

Width:  |  Height:  |  Size: 819 B

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" id="Outline" viewBox="0 0 24 24" width="512" height="512"><path d="M19,3H12.472a1.019,1.019,0,0,1-.447-.1L8.869,1.316A3.014,3.014,0,0,0,7.528,1H5A5.006,5.006,0,0,0,0,6V18a5.006,5.006,0,0,0,5,5H19a5.006,5.006,0,0,0,5-5V8A5.006,5.006,0,0,0,19,3ZM5,3H7.528a1.019,1.019,0,0,1,.447.1l3.156,1.579A3.014,3.014,0,0,0,12.472,5H19a3,3,0,0,1,2.779,1.882L2,6.994V6A3,3,0,0,1,5,3ZM19,21H5a3,3,0,0,1-3-3V8.994l20-.113V18A3,3,0,0,1,19,21Z"/></svg>

After

Width:  |  Height:  |  Size: 512 B

@ -0,0 +1,24 @@
<svg
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M3 3H9V5H6.46173L11.3047 9.84298L9.8905 11.2572L5 6.3667V9H3V3Z"
fill="currentColor"
/>
<path
d="M3 21H9V19H6.3764L11.3046 14.0718L9.89038 12.6576L5 17.548V15H3V21Z"
fill="currentColor"
/>
<path
d="M15 21H21V15H19V17.5244L14.1332 12.6576L12.719 14.0718L17.6472 19H15V21Z"
fill="currentColor"
/>
<path
d="M21 3H15V5H17.5619L12.7189 9.84301L14.1331 11.2572L19 6.39032V9H21V3Z"
fill="currentColor"
/>
</svg>

After

Width:  |  Height:  |  Size: 568 B

@ -0,0 +1 @@
<svg width="16px" height="16px" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" fill="currentColor"><path fill-rule="evenodd" clip-rule="evenodd" d="M1.5 2h13l.5.5V9h-1V6H2v7h7v1H1.5l-.5-.5v-11l.5-.5zM2 5h12V3H2v2zm5 7v-1.094a1.633 1.633 0 0 1-.469-.265l-.945.539-.5-.86.937-.547a1.57 1.57 0 0 1 0-.547l-.937-.546.5-.86.945.54c.151-.12.308-.209.469-.266V7h1v1.094a1.48 1.48 0 0 1 .469.265l.945-.539.5.86-.937.547a1.57 1.57 0 0 1 0 .546l.937.547-.5.86-.945-.54a1.807 1.807 0 0 1-.469.266V12H7zm-.25-2.5c0 .208.073.385.219.531a.723.723 0 0 0 .531.219.723.723 0 0 0 .531-.219.723.723 0 0 0 .219-.531.723.723 0 0 0-.219-.531.723.723 0 0 0-.531-.219.723.723 0 0 0-.531.219.723.723 0 0 0-.219.531zm5.334 5.5v-1.094a1.634 1.634 0 0 1-.469-.265l-.945.539-.5-.86.938-.547a1.572 1.572 0 0 1 0-.547l-.938-.546.5-.86.945.54c.151-.12.308-.209.47-.266V10h1v1.094a1.486 1.486 0 0 1 .468.265l.945-.539.5.86-.937.547a1.562 1.562 0 0 1 0 .546l.937.547-.5.86-.945-.54a1.806 1.806 0 0 1-.469.266V15h-1zm-.25-2.5c0 .208.073.385.219.531a.723.723 0 0 0 .531.219.723.723 0 0 0 .531-.219.723.723 0 0 0 .22-.531.723.723 0 0 0-.22-.531.723.723 0 0 0-.53-.219.723.723 0 0 0-.532.219.723.723 0 0 0-.219.531z"/></svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

@ -0,0 +1,62 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 19.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 478.703 478.703" style="enable-background:new 0 0 478.703 478.703;" xml:space="preserve">
<g>
<g>
<path d="M454.2,189.101l-33.6-5.7c-3.5-11.3-8-22.2-13.5-32.6l19.8-27.7c8.4-11.8,7.1-27.9-3.2-38.1l-29.8-29.8
c-5.6-5.6-13-8.7-20.9-8.7c-6.2,0-12.1,1.9-17.1,5.5l-27.8,19.8c-10.8-5.7-22.1-10.4-33.8-13.9l-5.6-33.2
c-2.4-14.3-14.7-24.7-29.2-24.7h-42.1c-14.5,0-26.8,10.4-29.2,24.7l-5.8,34c-11.2,3.5-22.1,8.1-32.5,13.7l-27.5-19.8
c-5-3.6-11-5.5-17.2-5.5c-7.9,0-15.4,3.1-20.9,8.7l-29.9,29.8c-10.2,10.2-11.6,26.3-3.2,38.1l20,28.1
c-5.5,10.5-9.9,21.4-13.3,32.7l-33.2,5.6c-14.3,2.4-24.7,14.7-24.7,29.2v42.1c0,14.5,10.4,26.8,24.7,29.2l34,5.8
c3.5,11.2,8.1,22.1,13.7,32.5l-19.7,27.4c-8.4,11.8-7.1,27.9,3.2,38.1l29.8,29.8c5.6,5.6,13,8.7,20.9,8.7c6.2,0,12.1-1.9,17.1-5.5
l28.1-20c10.1,5.3,20.7,9.6,31.6,13l5.6,33.6c2.4,14.3,14.7,24.7,29.2,24.7h42.2c14.5,0,26.8-10.4,29.2-24.7l5.7-33.6
c11.3-3.5,22.2-8,32.6-13.5l27.7,19.8c5,3.6,11,5.5,17.2,5.5l0,0c7.9,0,15.3-3.1,20.9-8.7l29.8-29.8c10.2-10.2,11.6-26.3,3.2-38.1
l-19.8-27.8c5.5-10.5,10.1-21.4,13.5-32.6l33.6-5.6c14.3-2.4,24.7-14.7,24.7-29.2v-42.1
C478.9,203.801,468.5,191.501,454.2,189.101z M451.9,260.401c0,1.3-0.9,2.4-2.2,2.6l-42,7c-5.3,0.9-9.5,4.8-10.8,9.9
c-3.8,14.7-9.6,28.8-17.4,41.9c-2.7,4.6-2.5,10.3,0.6,14.7l24.7,34.8c0.7,1,0.6,2.5-0.3,3.4l-29.8,29.8c-0.7,0.7-1.4,0.8-1.9,0.8
c-0.6,0-1.1-0.2-1.5-0.5l-34.7-24.7c-4.3-3.1-10.1-3.3-14.7-0.6c-13.1,7.8-27.2,13.6-41.9,17.4c-5.2,1.3-9.1,5.6-9.9,10.8l-7.1,42
c-0.2,1.3-1.3,2.2-2.6,2.2h-42.1c-1.3,0-2.4-0.9-2.6-2.2l-7-42c-0.9-5.3-4.8-9.5-9.9-10.8c-14.3-3.7-28.1-9.4-41-16.8
c-2.1-1.2-4.5-1.8-6.8-1.8c-2.7,0-5.5,0.8-7.8,2.5l-35,24.9c-0.5,0.3-1,0.5-1.5,0.5c-0.4,0-1.2-0.1-1.9-0.8l-29.8-29.8
c-0.9-0.9-1-2.3-0.3-3.4l24.6-34.5c3.1-4.4,3.3-10.2,0.6-14.8c-7.8-13-13.8-27.1-17.6-41.8c-1.4-5.1-5.6-9-10.8-9.9l-42.3-7.2
c-1.3-0.2-2.2-1.3-2.2-2.6v-42.1c0-1.3,0.9-2.4,2.2-2.6l41.7-7c5.3-0.9,9.6-4.8,10.9-10c3.7-14.7,9.4-28.9,17.1-42
c2.7-4.6,2.4-10.3-0.7-14.6l-24.9-35c-0.7-1-0.6-2.5,0.3-3.4l29.8-29.8c0.7-0.7,1.4-0.8,1.9-0.8c0.6,0,1.1,0.2,1.5,0.5l34.5,24.6
c4.4,3.1,10.2,3.3,14.8,0.6c13-7.8,27.1-13.8,41.8-17.6c5.1-1.4,9-5.6,9.9-10.8l7.2-42.3c0.2-1.3,1.3-2.2,2.6-2.2h42.1
c1.3,0,2.4,0.9,2.6,2.2l7,41.7c0.9,5.3,4.8,9.6,10,10.9c15.1,3.8,29.5,9.7,42.9,17.6c4.6,2.7,10.3,2.5,14.7-0.6l34.5-24.8
c0.5-0.3,1-0.5,1.5-0.5c0.4,0,1.2,0.1,1.9,0.8l29.8,29.8c0.9,0.9,1,2.3,0.3,3.4l-24.7,34.7c-3.1,4.3-3.3,10.1-0.6,14.7
c7.8,13.1,13.6,27.2,17.4,41.9c1.3,5.2,5.6,9.1,10.8,9.9l42,7.1c1.3,0.2,2.2,1.3,2.2,2.6v42.1H451.9z"/>
<path d="M239.4,136.001c-57,0-103.3,46.3-103.3,103.3s46.3,103.3,103.3,103.3s103.3-46.3,103.3-103.3S296.4,136.001,239.4,136.001
z M239.4,315.601c-42.1,0-76.3-34.2-76.3-76.3s34.2-76.3,76.3-76.3s76.3,34.2,76.3,76.3S281.5,315.601,239.4,315.601z"/>
</g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.2 KiB

@ -1 +1,2 @@
pyinstaller -w --add-data "extract.svg;." --add-data "process.svg;." --add-data "folder.svg;." --add-data "copy.svg;." -i .\extract.ico -n "IL Extract" .\main.py

@ -0,0 +1,196 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'ui/default_locations.ui'
#
# Created by: PyQt5 UI code generator 5.15.7
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_defaultLocationDiag(object):
def setupUi(self, defaultLocationDiag):
defaultLocationDiag.setObjectName("defaultLocationDiag")
defaultLocationDiag.setWindowModality(QtCore.Qt.NonModal)
defaultLocationDiag.resize(954, 525)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(defaultLocationDiag.sizePolicy().hasHeightForWidth())
defaultLocationDiag.setSizePolicy(sizePolicy)
icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap("ui/extract.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
defaultLocationDiag.setWindowIcon(icon)
self.gridLayout_2 = QtWidgets.QGridLayout(defaultLocationDiag)
self.gridLayout_2.setObjectName("gridLayout_2")
self.gridLayout = QtWidgets.QGridLayout()
self.gridLayout.setObjectName("gridLayout")
self.label = QtWidgets.QLabel(defaultLocationDiag)
font = QtGui.QFont()
font.setPointSize(14)
font.setBold(True)
font.setWeight(75)
self.label.setFont(font)
self.label.setObjectName("label")
self.gridLayout.addWidget(self.label, 0, 0, 1, 2)
self.label_2 = QtWidgets.QLabel(defaultLocationDiag)
self.label_2.setWordWrap(True)
self.label_2.setObjectName("label_2")
self.gridLayout.addWidget(self.label_2, 1, 0, 1, 4)
self.label_3 = QtWidgets.QLabel(defaultLocationDiag)
self.label_3.setWordWrap(True)
self.label_3.setObjectName("label_3")
self.gridLayout.addWidget(self.label_3, 2, 0, 1, 4)
self.label_4 = QtWidgets.QLabel(defaultLocationDiag)
font = QtGui.QFont()
font.setItalic(True)
self.label_4.setFont(font)
self.label_4.setWordWrap(True)
self.label_4.setObjectName("label_4")
self.gridLayout.addWidget(self.label_4, 3, 0, 1, 4)
self.label_5 = QtWidgets.QLabel(defaultLocationDiag)
font = QtGui.QFont()
font.setBold(True)
font.setWeight(75)
self.label_5.setFont(font)
self.label_5.setObjectName("label_5")
self.gridLayout.addWidget(self.label_5, 4, 0, 1, 1)
spacerItem = QtWidgets.QSpacerItem(588, 13, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
self.gridLayout.addItem(spacerItem, 4, 1, 1, 2)
self.label_6 = QtWidgets.QLabel(defaultLocationDiag)
font = QtGui.QFont()
font.setBold(True)
font.setWeight(75)
self.label_6.setFont(font)
self.label_6.setObjectName("label_6")
self.gridLayout.addWidget(self.label_6, 4, 3, 1, 1)
self.ach_B = QtWidgets.QPushButton(defaultLocationDiag)
self.ach_B.setObjectName("ach_B")
self.gridLayout.addWidget(self.ach_B, 5, 0, 1, 1)
self.ach_LE = QtWidgets.QLineEdit(defaultLocationDiag)
self.ach_LE.setMinimumSize(QtCore.QSize(581, 0))
self.ach_LE.setObjectName("ach_LE")
self.gridLayout.addWidget(self.ach_LE, 5, 1, 1, 1)
self.ach_FN = QtWidgets.QLineEdit(defaultLocationDiag)
self.ach_FN.setObjectName("ach_FN")
self.gridLayout.addWidget(self.ach_FN, 5, 2, 1, 2)
self.disp_B = QtWidgets.QPushButton(defaultLocationDiag)
self.disp_B.setObjectName("disp_B")
self.gridLayout.addWidget(self.disp_B, 6, 0, 1, 1)
self.disp_LE = QtWidgets.QLineEdit(defaultLocationDiag)
self.disp_LE.setMinimumSize(QtCore.QSize(581, 0))
self.disp_LE.setObjectName("disp_LE")
self.gridLayout.addWidget(self.disp_LE, 6, 1, 1, 1)
self.disp_FN = QtWidgets.QLineEdit(defaultLocationDiag)
self.disp_FN.setObjectName("disp_FN")
self.gridLayout.addWidget(self.disp_FN, 6, 2, 1, 2)
self.gl_B = QtWidgets.QPushButton(defaultLocationDiag)
self.gl_B.setObjectName("gl_B")
self.gridLayout.addWidget(self.gl_B, 7, 0, 1, 1)
self.gl_LE = QtWidgets.QLineEdit(defaultLocationDiag)
self.gl_LE.setMinimumSize(QtCore.QSize(581, 0))
self.gl_LE.setObjectName("gl_LE")
self.gridLayout.addWidget(self.gl_LE, 7, 1, 1, 1)
self.gl_FN = QtWidgets.QLineEdit(defaultLocationDiag)
self.gl_FN.setObjectName("gl_FN")
self.gridLayout.addWidget(self.gl_FN, 7, 2, 1, 2)
self.lb_B = QtWidgets.QPushButton(defaultLocationDiag)
self.lb_B.setObjectName("lb_B")
self.gridLayout.addWidget(self.lb_B, 8, 0, 1, 1)
self.lb_LE = QtWidgets.QLineEdit(defaultLocationDiag)
self.lb_LE.setMinimumSize(QtCore.QSize(581, 0))
self.lb_LE.setObjectName("lb_LE")
self.gridLayout.addWidget(self.lb_LE, 8, 1, 1, 1)
self.lb_FN = QtWidgets.QLineEdit(defaultLocationDiag)
self.lb_FN.setObjectName("lb_FN")
self.gridLayout.addWidget(self.lb_FN, 8, 2, 1, 2)
self.minv_B = QtWidgets.QPushButton(defaultLocationDiag)
self.minv_B.setObjectName("minv_B")
self.gridLayout.addWidget(self.minv_B, 9, 0, 1, 1)
self.minv_LE = QtWidgets.QLineEdit(defaultLocationDiag)
self.minv_LE.setMinimumSize(QtCore.QSize(581, 0))
self.minv_LE.setObjectName("minv_LE")
self.gridLayout.addWidget(self.minv_LE, 9, 1, 1, 1)
self.minv_FN = QtWidgets.QLineEdit(defaultLocationDiag)
self.minv_FN.setObjectName("minv_FN")
self.gridLayout.addWidget(self.minv_FN, 9, 2, 1, 2)
self.niv_B = QtWidgets.QPushButton(defaultLocationDiag)
self.niv_B.setObjectName("niv_B")
self.gridLayout.addWidget(self.niv_B, 10, 0, 1, 1)
self.niv_LE = QtWidgets.QLineEdit(defaultLocationDiag)
self.niv_LE.setMinimumSize(QtCore.QSize(581, 0))
self.niv_LE.setObjectName("niv_LE")
self.gridLayout.addWidget(self.niv_LE, 10, 1, 1, 1)
self.niv_FN = QtWidgets.QLineEdit(defaultLocationDiag)
self.niv_FN.setObjectName("niv_FN")
self.gridLayout.addWidget(self.niv_FN, 10, 2, 1, 2)
self.ren_B = QtWidgets.QPushButton(defaultLocationDiag)
self.ren_B.setObjectName("ren_B")
self.gridLayout.addWidget(self.ren_B, 11, 0, 1, 1)
self.ren_LE = QtWidgets.QLineEdit(defaultLocationDiag)
self.ren_LE.setMinimumSize(QtCore.QSize(581, 0))
self.ren_LE.setObjectName("ren_LE")
self.gridLayout.addWidget(self.ren_LE, 11, 1, 1, 1)
self.ren_FN = QtWidgets.QLineEdit(defaultLocationDiag)
self.ren_FN.setObjectName("ren_FN")
self.gridLayout.addWidget(self.ren_FN, 11, 2, 1, 2)
self.pymt_B = QtWidgets.QPushButton(defaultLocationDiag)
self.pymt_B.setObjectName("pymt_B")
self.gridLayout.addWidget(self.pymt_B, 12, 0, 1, 1)
self.pymt_LE = QtWidgets.QLineEdit(defaultLocationDiag)
self.pymt_LE.setMinimumSize(QtCore.QSize(581, 0))
self.pymt_LE.setObjectName("pymt_LE")
self.gridLayout.addWidget(self.pymt_LE, 12, 1, 1, 1)
self.pymt_FN = QtWidgets.QLineEdit(defaultLocationDiag)
self.pymt_FN.setObjectName("pymt_FN")
self.gridLayout.addWidget(self.pymt_FN, 12, 2, 1, 2)
self.uap_B = QtWidgets.QPushButton(defaultLocationDiag)
self.uap_B.setObjectName("uap_B")
self.gridLayout.addWidget(self.uap_B, 13, 0, 1, 1)
self.uap_LE = QtWidgets.QLineEdit(defaultLocationDiag)
self.uap_LE.setMinimumSize(QtCore.QSize(581, 0))
self.uap_LE.setObjectName("uap_LE")
self.gridLayout.addWidget(self.uap_LE, 13, 1, 1, 1)
self.uap_FN = QtWidgets.QLineEdit(defaultLocationDiag)
self.uap_FN.setObjectName("uap_FN")
self.gridLayout.addWidget(self.uap_FN, 13, 2, 1, 2)
self.optionBBox = QtWidgets.QDialogButtonBox(defaultLocationDiag)
self.optionBBox.setOrientation(QtCore.Qt.Horizontal)
self.optionBBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Save)
self.optionBBox.setObjectName("optionBBox")
self.gridLayout.addWidget(self.optionBBox, 14, 3, 1, 1)
self.gridLayout_2.addLayout(self.gridLayout, 0, 0, 1, 1)
self.retranslateUi(defaultLocationDiag)
self.optionBBox.accepted.connect(defaultLocationDiag.accept) # type: ignore
self.optionBBox.rejected.connect(defaultLocationDiag.reject) # type: ignore
QtCore.QMetaObject.connectSlotsByName(defaultLocationDiag)
def retranslateUi(self, defaultLocationDiag):
_translate = QtCore.QCoreApplication.translate
defaultLocationDiag.setWindowTitle(_translate("defaultLocationDiag", "Default locations"))
self.label.setText(_translate("defaultLocationDiag", "Default File Locations:"))
self.label_2.setText(_translate("defaultLocationDiag", "Here you can determine which folders will be automatically be opened for each report type. You can even specify which file should be defaulted to."))
self.label_3.setText(_translate("defaultLocationDiag", "Use the following inline formaters to specify dates that will be automatically filled with the current date when running the program:"))
self.label_4.setText(_translate("defaultLocationDiag", "Day of Month {d} | Month of Year {m} | Year {y} | Note that using multiple characters equates to representing with that number of digits so: {dd} == 07 or {mm} == 02 or {yy} == 22 or {yyyy} == 2022"))
self.label_5.setText(_translate("defaultLocationDiag", "Folder Path"))
self.label_6.setToolTip(_translate("defaultLocationDiag", "<html><head/><body><p>Default file name to look for. Don\'t foreget the file type (.xlsx)</p></body></html>"))
self.label_6.setText(_translate("defaultLocationDiag", "File Name"))
self.ach_B.setText(_translate("defaultLocationDiag", "Edit ACH"))
self.disp_B.setText(_translate("defaultLocationDiag", "Edit Dispostition"))
self.gl_B.setWhatsThis(_translate("defaultLocationDiag", "<html><head/><body><p>Gain Loss</p></body></html>"))
self.gl_B.setText(_translate("defaultLocationDiag", "Edit Gain Loss"))
self.lb_B.setText(_translate("defaultLocationDiag", "Edit Lock Box"))
self.minv_B.setWhatsThis(_translate("defaultLocationDiag", "<html><head/><body><p>Good for Manual Invoicing</p></body></html>"))
self.minv_B.setText(_translate("defaultLocationDiag", "Edit Manual Invoice"))
self.niv_B.setWhatsThis(_translate("defaultLocationDiag", "<html><head/><body><p>Good for: Net Investment reports (loan and after)</p></body></html>"))
self.niv_B.setText(_translate("defaultLocationDiag", "Edit Net Inv"))
self.ren_B.setWhatsThis(_translate("defaultLocationDiag", "<html><head/><body><p>Renewal Net Investment Trial Balance</p></body></html>"))
self.ren_B.setText(_translate("defaultLocationDiag", "Edit Renewl NIV"))
self.pymt_B.setWhatsThis(_translate("defaultLocationDiag", "<html><head/><body><p>Payment transactions:</p><p>- Wires, VMCC, PBP. EPAY, Returned Check</p></body></html>"))
self.pymt_B.setText(_translate("defaultLocationDiag", "Edit Payments"))
self.uap_B.setWhatsThis(_translate("defaultLocationDiag", "<html><head/><body><p>Unapplied</p></body></html>"))
self.uap_B.setText(_translate("defaultLocationDiag", "Edit Unaplied"))

@ -0,0 +1,196 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'ui/default_locations.ui'
#
# Created by: PyQt5 UI code generator 5.15.7
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_defaultLocationDiag(object):
def setupUi(self, defaultLocationDiag):
defaultLocationDiag.setObjectName("defaultLocationDiag")
defaultLocationDiag.setWindowModality(QtCore.Qt.NonModal)
defaultLocationDiag.resize(954, 525)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(defaultLocationDiag.sizePolicy().hasHeightForWidth())
defaultLocationDiag.setSizePolicy(sizePolicy)
icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap("ui/extract.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
defaultLocationDiag.setWindowIcon(icon)
self.gridLayout_2 = QtWidgets.QGridLayout(defaultLocationDiag)
self.gridLayout_2.setObjectName("gridLayout_2")
self.gridLayout = QtWidgets.QGridLayout()
self.gridLayout.setObjectName("gridLayout")
self.label = QtWidgets.QLabel(defaultLocationDiag)
font = QtGui.QFont()
font.setPointSize(14)
font.setBold(True)
font.setWeight(75)
self.label.setFont(font)
self.label.setObjectName("label")
self.gridLayout.addWidget(self.label, 0, 0, 1, 2)
self.label_2 = QtWidgets.QLabel(defaultLocationDiag)
self.label_2.setWordWrap(True)
self.label_2.setObjectName("label_2")
self.gridLayout.addWidget(self.label_2, 1, 0, 1, 4)
self.label_3 = QtWidgets.QLabel(defaultLocationDiag)
self.label_3.setWordWrap(True)
self.label_3.setObjectName("label_3")
self.gridLayout.addWidget(self.label_3, 2, 0, 1, 4)
self.label_4 = QtWidgets.QLabel(defaultLocationDiag)
font = QtGui.QFont()
font.setItalic(True)
self.label_4.setFont(font)
self.label_4.setWordWrap(True)
self.label_4.setObjectName("label_4")
self.gridLayout.addWidget(self.label_4, 3, 0, 1, 4)
self.label_5 = QtWidgets.QLabel(defaultLocationDiag)
font = QtGui.QFont()
font.setBold(True)
font.setWeight(75)
self.label_5.setFont(font)
self.label_5.setObjectName("label_5")
self.gridLayout.addWidget(self.label_5, 4, 0, 1, 1)
spacerItem = QtWidgets.QSpacerItem(588, 13, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
self.gridLayout.addItem(spacerItem, 4, 1, 1, 2)
self.label_6 = QtWidgets.QLabel(defaultLocationDiag)
font = QtGui.QFont()
font.setBold(True)
font.setWeight(75)
self.label_6.setFont(font)
self.label_6.setObjectName("label_6")
self.gridLayout.addWidget(self.label_6, 4, 3, 1, 1)
self.ach_B = QtWidgets.QPushButton(defaultLocationDiag)
self.ach_B.setObjectName("ach_B")
self.gridLayout.addWidget(self.ach_B, 5, 0, 1, 1)
self.ach_LE = QtWidgets.QLineEdit(defaultLocationDiag)
self.ach_LE.setMinimumSize(QtCore.QSize(581, 0))
self.ach_LE.setObjectName("ach_LE")
self.gridLayout.addWidget(self.ach_LE, 5, 1, 1, 1)
self.ach_FN = QtWidgets.QLineEdit(defaultLocationDiag)
self.ach_FN.setObjectName("ach_FN")
self.gridLayout.addWidget(self.ach_FN, 5, 2, 1, 2)
self.disp_B = QtWidgets.QPushButton(defaultLocationDiag)
self.disp_B.setObjectName("disp_B")
self.gridLayout.addWidget(self.disp_B, 6, 0, 1, 1)
self.disp_LE = QtWidgets.QLineEdit(defaultLocationDiag)
self.disp_LE.setMinimumSize(QtCore.QSize(581, 0))
self.disp_LE.setObjectName("disp_LE")
self.gridLayout.addWidget(self.disp_LE, 6, 1, 1, 1)
self.disp_FN = QtWidgets.QLineEdit(defaultLocationDiag)
self.disp_FN.setObjectName("disp_FN")
self.gridLayout.addWidget(self.disp_FN, 6, 2, 1, 2)
self.gl_B = QtWidgets.QPushButton(defaultLocationDiag)
self.gl_B.setObjectName("gl_B")
self.gridLayout.addWidget(self.gl_B, 7, 0, 1, 1)
self.gl_LE = QtWidgets.QLineEdit(defaultLocationDiag)
self.gl_LE.setMinimumSize(QtCore.QSize(581, 0))
self.gl_LE.setObjectName("gl_LE")
self.gridLayout.addWidget(self.gl_LE, 7, 1, 1, 1)
self.gl_FN = QtWidgets.QLineEdit(defaultLocationDiag)
self.gl_FN.setObjectName("gl_FN")
self.gridLayout.addWidget(self.gl_FN, 7, 2, 1, 2)
self.lb_B = QtWidgets.QPushButton(defaultLocationDiag)
self.lb_B.setObjectName("lb_B")
self.gridLayout.addWidget(self.lb_B, 8, 0, 1, 1)
self.lb_LE = QtWidgets.QLineEdit(defaultLocationDiag)
self.lb_LE.setMinimumSize(QtCore.QSize(581, 0))
self.lb_LE.setObjectName("lb_LE")
self.gridLayout.addWidget(self.lb_LE, 8, 1, 1, 1)
self.lb_FN = QtWidgets.QLineEdit(defaultLocationDiag)
self.lb_FN.setObjectName("lb_FN")
self.gridLayout.addWidget(self.lb_FN, 8, 2, 1, 2)
self.minv_B = QtWidgets.QPushButton(defaultLocationDiag)
self.minv_B.setObjectName("minv_B")
self.gridLayout.addWidget(self.minv_B, 9, 0, 1, 1)
self.minv_LE = QtWidgets.QLineEdit(defaultLocationDiag)
self.minv_LE.setMinimumSize(QtCore.QSize(581, 0))
self.minv_LE.setObjectName("minv_LE")
self.gridLayout.addWidget(self.minv_LE, 9, 1, 1, 1)
self.minv_FN = QtWidgets.QLineEdit(defaultLocationDiag)
self.minv_FN.setObjectName("minv_FN")
self.gridLayout.addWidget(self.minv_FN, 9, 2, 1, 2)
self.niv_B = QtWidgets.QPushButton(defaultLocationDiag)
self.niv_B.setObjectName("niv_B")
self.gridLayout.addWidget(self.niv_B, 10, 0, 1, 1)
self.niv_LE = QtWidgets.QLineEdit(defaultLocationDiag)
self.niv_LE.setMinimumSize(QtCore.QSize(581, 0))
self.niv_LE.setObjectName("niv_LE")
self.gridLayout.addWidget(self.niv_LE, 10, 1, 1, 1)
self.niv_FN = QtWidgets.QLineEdit(defaultLocationDiag)
self.niv_FN.setObjectName("niv_FN")
self.gridLayout.addWidget(self.niv_FN, 10, 2, 1, 2)
self.ren_B = QtWidgets.QPushButton(defaultLocationDiag)
self.ren_B.setObjectName("ren_B")
self.gridLayout.addWidget(self.ren_B, 11, 0, 1, 1)
self.ren_LE = QtWidgets.QLineEdit(defaultLocationDiag)
self.ren_LE.setMinimumSize(QtCore.QSize(581, 0))
self.ren_LE.setObjectName("ren_LE")
self.gridLayout.addWidget(self.ren_LE, 11, 1, 1, 1)
self.ren_FN = QtWidgets.QLineEdit(defaultLocationDiag)
self.ren_FN.setObjectName("ren_FN")
self.gridLayout.addWidget(self.ren_FN, 11, 2, 1, 2)
self.pymt_B = QtWidgets.QPushButton(defaultLocationDiag)
self.pymt_B.setObjectName("pymt_B")
self.gridLayout.addWidget(self.pymt_B, 12, 0, 1, 1)
self.pymt_LE = QtWidgets.QLineEdit(defaultLocationDiag)
self.pymt_LE.setMinimumSize(QtCore.QSize(581, 0))
self.pymt_LE.setObjectName("pymt_LE")
self.gridLayout.addWidget(self.pymt_LE, 12, 1, 1, 1)
self.pymt_FN = QtWidgets.QLineEdit(defaultLocationDiag)
self.pymt_FN.setObjectName("pymt_FN")
self.gridLayout.addWidget(self.pymt_FN, 12, 2, 1, 2)
self.uap_B = QtWidgets.QPushButton(defaultLocationDiag)
self.uap_B.setObjectName("uap_B")
self.gridLayout.addWidget(self.uap_B, 13, 0, 1, 1)
self.uap_LE = QtWidgets.QLineEdit(defaultLocationDiag)
self.uap_LE.setMinimumSize(QtCore.QSize(581, 0))
self.uap_LE.setObjectName("uap_LE")
self.gridLayout.addWidget(self.uap_LE, 13, 1, 1, 1)
self.uap_FN = QtWidgets.QLineEdit(defaultLocationDiag)
self.uap_FN.setObjectName("uap_FN")
self.gridLayout.addWidget(self.uap_FN, 13, 2, 1, 2)
self.optionBBox = QtWidgets.QDialogButtonBox(defaultLocationDiag)
self.optionBBox.setOrientation(QtCore.Qt.Horizontal)
self.optionBBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Save)
self.optionBBox.setObjectName("optionBBox")
self.gridLayout.addWidget(self.optionBBox, 14, 3, 1, 1)
self.gridLayout_2.addLayout(self.gridLayout, 0, 0, 1, 1)
self.retranslateUi(defaultLocationDiag)
self.optionBBox.accepted.connect(defaultLocationDiag.accept) # type: ignore
self.optionBBox.rejected.connect(defaultLocationDiag.reject) # type: ignore
QtCore.QMetaObject.connectSlotsByName(defaultLocationDiag)
def retranslateUi(self, defaultLocationDiag):
_translate = QtCore.QCoreApplication.translate
defaultLocationDiag.setWindowTitle(_translate("defaultLocationDiag", "Default locations"))
self.label.setText(_translate("defaultLocationDiag", "Default File Locations:"))
self.label_2.setText(_translate("defaultLocationDiag", "Here you can determine which folders will be automatically be opened for each report type. You can even specify which file should be defaulted to."))
self.label_3.setText(_translate("defaultLocationDiag", "Use the following inline formaters to specify dates that will be automatically filled with the current date when running the program:"))
self.label_4.setText(_translate("defaultLocationDiag", "Day of Month {d} | Month of Year {m} | Year {y} | Note that using multiple characters equates to representing with that number of digits so: {dd} == 07 or {mm} == 02 or {yy} == 22 or {yyyy} == 2022"))
self.label_5.setText(_translate("defaultLocationDiag", "Folder Path"))
self.label_6.setToolTip(_translate("defaultLocationDiag", "<html><head/><body><p>Default file name to look for. Don\'t foreget the file type (.xlsx)</p></body></html>"))
self.label_6.setText(_translate("defaultLocationDiag", "File Name"))
self.ach_B.setText(_translate("defaultLocationDiag", "Edit ACH"))
self.disp_B.setText(_translate("defaultLocationDiag", "Edit Dispostition"))
self.gl_B.setWhatsThis(_translate("defaultLocationDiag", "<html><head/><body><p>Gain Loss</p></body></html>"))
self.gl_B.setText(_translate("defaultLocationDiag", "Edit Gain Loss"))
self.lb_B.setText(_translate("defaultLocationDiag", "Edit Lock Box"))
self.minv_B.setWhatsThis(_translate("defaultLocationDiag", "<html><head/><body><p>Good for Manual Invoicing</p></body></html>"))
self.minv_B.setText(_translate("defaultLocationDiag", "Edit Manual Invoice"))
self.niv_B.setWhatsThis(_translate("defaultLocationDiag", "<html><head/><body><p>Good for: Net Investment reports (loan and after)</p></body></html>"))
self.niv_B.setText(_translate("defaultLocationDiag", "Edit Net Inv"))
self.ren_B.setWhatsThis(_translate("defaultLocationDiag", "<html><head/><body><p>Renewal Net Investment Trial Balance</p></body></html>"))
self.ren_B.setText(_translate("defaultLocationDiag", "Edit Renewl NIV"))
self.pymt_B.setWhatsThis(_translate("defaultLocationDiag", "<html><head/><body><p>Payment transactions:</p><p>- Wires, VMCC, PBP. EPAY, Returned Check</p></body></html>"))
self.pymt_B.setText(_translate("defaultLocationDiag", "Edit Payments"))
self.uap_B.setWhatsThis(_translate("defaultLocationDiag", "<html><head/><body><p>Unapplied</p></body></html>"))
self.uap_B.setText(_translate("defaultLocationDiag", "Edit Unaplied"))

@ -1,60 +1,97 @@
from mainWindow_new import Ui_MainWindow
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.rtp = False # Ready to Process
self.ofa = False # Output file ready
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.openReportButton.clicked.connect(self.to_clipboard)
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 getfile(self):
inFile = QtWidgets.QFileDialog.getOpenFileName(self, 'Open file')
self.inputFileLE.setText(inFile[0])
if inFile[0] == '' : return ''
# Replacing errors fixes some UTF-8 character issues
with open(inFile[0], errors="replace") as inF:
def set_input(self, ifile):
with open(ifile, errors="replace") as inF:
txt = inF.read()
self.inputFilePreview.setText(txt)
self.inputFile = inFile[0]
self.inputFileLE.setText(ifile)
self.inputFile = ifile
# This gets the actual file name
inFileEnd = inFile[0].split('/')[-1]
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()}_{dt.now().strftime('%Y%m%d_%H%M')}.xlsx"
self.outputFileLE.setText(self.outputFile)
# Check to make sure the user has selected the correct report type
if self.reportTypeCB.currentText().split(" ")[-1].lower() not in self.inputFile.lower():
print("Possibly wrong file type")
warning = QtWidgets.QMessageBox()
warning.setWindowTitle("Warning: File Type Mis-Match")
warning.setText(f"Selected report type is {self.reportTypeCB.currentText()} but input file did not contain '{self.reportTypeCB.currentText().split(' ')[-1].lower()}'!\n\
Make sure you select the correct report type before processing!")
s = warning.exec()
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"
@ -62,47 +99,25 @@ Make sure you select the correct report type before processing!")
def check_ready_to_process(self):
# Makes sure there is an input and output selected before allowing processing
self.rtp = True if ((self.inputFile != "") & (self.outputFile != "")) else False
if self.rtp :
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:
# Here we set the extraction function that will be used on the report
if self.reportTypeCB.currentText() == "ACH":
extract_function = ilx.ach
elif self.reportTypeCB.currentText() == "Disposition":
extract_function = ilx.disposition
elif self.reportTypeCB.currentText() == "Gain Loss":
extract_function = ilx.gainloss
elif self.reportTypeCB.currentText() == "Lock Box":
extract_function = ilx.lockbox
elif self.reportTypeCB.currentText() == "Minv_C":
extract_function = ilx.minv
elif self.reportTypeCB.currentText() == "Net Inv. Loans":
extract_function = ilx.net_invest_trial_balance
elif self.reportTypeCB.currentText() == "NI Renewal":
extract_function = ilx.renewal_net_invest_trial_balance
elif self.reportTypeCB.currentText() == "NIV After":
extract_function = ilx.net_invest_trial_balance
elif self.reportTypeCB.currentText() == "PBP Epay":
extract_function = ilx.payment_transactions
elif self.reportTypeCB.currentText() == "Unapplied":
extract_function = ilx.unapplied
elif self.reportTypeCB.currentText() == "VMCC":
extract_function = ilx.payment_transactions
elif self.reportTypeCB.currentText() == "Wires":
extract_function = ilx.payment_transactions
elif self.reportTypeCB.currentText() == "Returned Check":
extract_function = ilx.payment_transactions
# 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=extract_function,
extraction_function=self.extract_function,
output_location=self.outputFile,
).process()
# The text preview box can have trouble loading the larger dataframes so
@ -113,6 +128,11 @@ Make sure you select the correct report type before processing!")
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)
@ -122,6 +142,261 @@ Make sure you select the correct report type before processing!")
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() == "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()}_{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")

@ -1,2 +1,2 @@
#!/bin/bash
zip -r ILEXTRACT_SRC.zip ../'IL Extract SRC' -x "IL Extract SRC/__pycache__V/*" "IL Extract SRC/GUIVENV/*"
zip -r ILEXTRACT_SRC.zip ../'IL Extract SRC' -x "../IL Extract SRC/GUIVENV/*" "../IL Extract SRC/__pycache__" "../IL Extract SRC/testing"

@ -0,0 +1 @@
{"firstRun": true, "startMaxed": false, "defaultLocations": {"ach": {"dir": "", "fn": "", "custom": false}, "disp": {"dir": "", "fn": "", "custom": false}, "gl": {"dir": "", "fn": "", "custom": false}, "lb": {"dir": "", "fn": "", "custom": false}, "minv": {"dir": "", "fn": "", "custom": false}, "niv": {"dir": "", "fn": "", "custom": false}, "ren": {"dir": "", "fn": "", "custom": false}, "pymt": {"dir": "", "fn": "", "custom": false}, "uap": {"dir": "", "fn": "", "custom": false}}}
Loading…
Cancel
Save