master
commit
6c94e493dc
@ -0,0 +1,7 @@ |
||||
*.xlsx |
||||
*.xlsxm |
||||
*.csv |
||||
*.docx |
||||
*.txt |
||||
*test* |
||||
/venv |
||||
@ -0,0 +1,252 @@ |
||||
import pandas as pd |
||||
from pprint import pprint as prt |
||||
import sqlalchemy as sqa |
||||
from datetime import timedelta, time,datetime as dt |
||||
import numpy as np |
||||
import businesstimedelta |
||||
import pytz |
||||
|
||||
|
||||
workday = businesstimedelta.WorkDayRule( |
||||
start_time= time(7), |
||||
end_time= time(18), |
||||
working_days=[0, 1, 2, 3, 4], |
||||
tz=pytz.timezone("US/Eastern")) |
||||
|
||||
businesshrs = businesstimedelta.Rules([workday]) |
||||
|
||||
|
||||
def pfd(dataframe): |
||||
with pd.option_context('display.max_rows', None, 'display.max_columns', None): # more options can be specified also |
||||
prt(dataframe) |
||||
|
||||
def login() -> str: |
||||
""" |
||||
Logs get's login info |
||||
""" |
||||
un = input("What is your LEAF login name? ") |
||||
pw = input("What is your LEAF password? ") |
||||
login_str = f"{un.lower()}:{pw}" |
||||
return login_str |
||||
|
||||
def get_timeframe(): |
||||
start_date = "09/27/2022" |
||||
end_date = dt.now().strftime("%m/%d/%y") |
||||
return start_date, end_date |
||||
|
||||
def get_data() -> pd.DataFrame: |
||||
connection_str = f"mssql+pymssql://leafnow.com\{login()}@LPP-SQL01" |
||||
try: |
||||
print(f"Connectiong to SQL database...") |
||||
with sqa.create_engine(connection_str).connect() as con: |
||||
start_date, end_date = get_timeframe() |
||||
print("Pulling data...") |
||||
query = f""" |
||||
use Onbase |
||||
select |
||||
--id.itemnum, |
||||
RTRIM(ki105.keyvaluechar) as ApplicationNum |
||||
,RTRIM(ki103.keyvaluechar) as CustName |
||||
,RTRIM(ki136.keyvaluechar) as SubmittedBy |
||||
,Rtrim(ki354.keyvaluechar) as MarketingRepEmail |
||||
,RTRIM(ki1076.keyvaluechar) as Status |
||||
,RTRIM(ki1456.keyvaluechar) as APRep |
||||
,RTRIM(ki1457.keyvaluetod) as StatusDateTime |
||||
,RTRIM(kgd426.kg749) as vendornum |
||||
,RTRIM(kgd426.kg750) as vendorname |
||||
,RTRIM(kgd426.kg1388) as firstattempt |
||||
,kgd426.kg1454 as firstattemptdate |
||||
,RTRIM(kgd426.kg1452) as firstattemptcomments |
||||
,RTRIM(kgd426.kg1389) as secondattempt |
||||
,kgd426.kg1455 as secondattemptdate |
||||
,RTRIM(kgd426.kg1453) as secondattemptcomments |
||||
,RTRIM(kgd426.kg1075) as leafemployee |
||||
,RTRIM(kgd426.kg1074) as vendorverifiedwith |
||||
,min(wf101.entrytime) as QueueEntryTime |
||||
,max(wf101.exittime) as QueueExitTime |
||||
|
||||
|
||||
from hsi.itemdata id |
||||
--join hsi.doctype dt on dt.itemtypenum = id.itemtypenum |
||||
join hsi.keyrecorddata426 kgd426 on kgd426.itemnum = id.itemnum |
||||
left outer join hsi.keyitem105 ki105 on ki105.itemnum = id.itemnum |
||||
left outer join hsi.keyitem103 ki103 on ki103.itemnum = id.itemnum |
||||
left outer join hsi.keyitem136 ki136 on ki136.itemnum = id.itemnum |
||||
left outer join hsi.keyitem354 ki354 on ki354.itemnum = id.itemnum |
||||
left outer join hsi.keyitem1076 ki1076 on ki1076.itemnum = id.itemnum |
||||
left outer join hsi.keyitem1457 ki1457 on ki1457.itemnum = id.itemnum |
||||
left outer join hsi.keyitem1456 ki1456 on ki1456.itemnum = id.itemnum |
||||
left outer join hsi.keyitem749 ki749 on ki749.itemnum = id.itemnum |
||||
left outer join hsi.keyitem750 ki750 on ki750.itemnum = id.itemnum |
||||
left outer join hsi.keyitem1388 ki1388 on ki1388.itemnum = id.itemnum |
||||
left outer join hsi.keyitem1454 ki1454 on ki1454.itemnum = id.itemnum |
||||
left outer join hsi.keyitem1452 ki1452 on ki1452.itemnum = id.itemnum |
||||
left outer join hsi.keyitem1389 ki1389 on ki1389.itemnum = id.itemnum |
||||
left outer join hsi.keyitem1455 ki1455 on ki1455.itemnum = id.itemnum |
||||
left outer join hsi.keyitem1453 ki1453 on ki1453.itemnum = id.itemnum |
||||
left outer join hsi.keyitem1075 ki1075 on ki1075.itemnum = id.itemnum |
||||
left outer join hsi.keyitem1074 ki1074 on ki1074.itemnum = id.itemnum |
||||
--PHL LifeCycle = 101; ACH Queue = 405 |
||||
join hsi.wflog wf101 on wf101.itemnum = id.itemnum and wf101.lcnum = '101' and wf101.statenum = '405' |
||||
|
||||
where id.itemtypenum = 535 |
||||
and id.status = 0 |
||||
and CONVERT(DATE,ki1457.keyvaluetod) BETWEEN '{start_date}' and '{end_date}' |
||||
|
||||
group by |
||||
ki105.keyvaluechar |
||||
,ki103.keyvaluechar |
||||
,ki136.keyvaluechar |
||||
,ki354.keyvaluechar |
||||
,ki1076.keyvaluechar |
||||
,ki1456.keyvaluechar |
||||
,ki1457.keyvaluetod |
||||
,kgd426.kg749 |
||||
,kgd426.kg750 |
||||
,kgd426.kg1388 |
||||
,kgd426.kg1454 |
||||
,kgd426.kg1452 |
||||
,kgd426.kg1389 |
||||
,kgd426.kg1455 |
||||
,kgd426.kg1453 |
||||
,kgd426.kg1075 |
||||
,kgd426.kg1074 |
||||
|
||||
UNION |
||||
|
||||
select |
||||
--id.itemnum, |
||||
RTRIM(ki105.keyvaluechar) as ApplicationNum |
||||
,RTRIM(ki103.keyvaluechar) as CustName |
||||
,RTRIM(ki136.keyvaluechar) as SubmittedBy |
||||
,Rtrim(ki354.keyvaluechar) as MarketingRepEmail |
||||
,RTRIM(ki1076.keyvaluechar) as Status |
||||
,RTRIM(ki1456.keyvaluechar) as APRep |
||||
,RTRIM(ki1457.keyvaluetod) as StatusDateTime |
||||
,RTRIM(kgd426.kg749) as vendornum |
||||
,RTRIM(kgd426.kg750) as vendorname |
||||
,RTRIM(kgd426.kg1388) as firstattempt |
||||
,RTRIM(kgd426.kg1454) as firstattemptdate |
||||
,RTRIM(kgd426.kg1452) as firstattemptcomments |
||||
,RTRIM(kgd426.kg1389) as secondattempt |
||||
,RTRIM(kgd426.kg1455) as secondattemptdate |
||||
,RTRIM(kgd426.kg1453) as secondattemptcomments |
||||
,RTRIM(kgd426.kg1075) as leafemployee |
||||
,RTRIM(kgd426.kg1074) as vendorverifiedwith |
||||
,min(wf106.entrytime) as QueueEntryTime |
||||
,max(wf106.exittime) as QueueExitTime |
||||
|
||||
|
||||
from hsi.itemdata id |
||||
--join hsi.doctype dt on dt.itemtypenum = id.itemtypenum |
||||
join hsi.keyrecorddata426 kgd426 on kgd426.itemnum = id.itemnum |
||||
left outer join hsi.keyitem105 ki105 on ki105.itemnum = id.itemnum |
||||
left outer join hsi.keyitem103 ki103 on ki103.itemnum = id.itemnum |
||||
left outer join hsi.keyitem136 ki136 on ki136.itemnum = id.itemnum |
||||
left outer join hsi.keyitem354 ki354 on ki354.itemnum = id.itemnum |
||||
left outer join hsi.keyitem1076 ki1076 on ki1076.itemnum = id.itemnum |
||||
left outer join hsi.keyitem1457 ki1457 on ki1457.itemnum = id.itemnum |
||||
left outer join hsi.keyitem1456 ki1456 on ki1456.itemnum = id.itemnum |
||||
left outer join hsi.keyitem749 ki749 on ki749.itemnum = id.itemnum |
||||
left outer join hsi.keyitem750 ki750 on ki750.itemnum = id.itemnum |
||||
left outer join hsi.keyitem1388 ki1388 on ki1388.itemnum = id.itemnum |
||||
left outer join hsi.keyitem1454 ki1454 on ki1454.itemnum = id.itemnum |
||||
left outer join hsi.keyitem1452 ki1452 on ki1452.itemnum = id.itemnum |
||||
left outer join hsi.keyitem1389 ki1389 on ki1389.itemnum = id.itemnum |
||||
left outer join hsi.keyitem1455 ki1455 on ki1455.itemnum = id.itemnum |
||||
left outer join hsi.keyitem1453 ki1453 on ki1453.itemnum = id.itemnum |
||||
left outer join hsi.keyitem1075 ki1075 on ki1075.itemnum = id.itemnum |
||||
left outer join hsi.keyitem1074 ki1074 on ki1074.itemnum = id.itemnum |
||||
--MOB LifeCycle = 106; ACH Queue = 417 |
||||
join hsi.wflog wf106 on wf106.itemnum = id.itemnum and wf106.lcnum = '106' and wf106.statenum = '417' |
||||
|
||||
where id.itemtypenum = 535 |
||||
and id.status = 0 |
||||
and CONVERT(DATE,ki1457.keyvaluetod) BETWEEN '09/27/2022' and '12/06/2022' |
||||
|
||||
group by |
||||
ki105.keyvaluechar |
||||
,ki103.keyvaluechar |
||||
,ki136.keyvaluechar |
||||
,ki354.keyvaluechar |
||||
,ki1076.keyvaluechar |
||||
,ki1456.keyvaluechar |
||||
,ki1457.keyvaluetod |
||||
,kgd426.kg749 |
||||
,kgd426.kg750 |
||||
,kgd426.kg1388 |
||||
,kgd426.kg1454 |
||||
,kgd426.kg1452 |
||||
,kgd426.kg1389 |
||||
,kgd426.kg1455 |
||||
,kgd426.kg1453 |
||||
,kgd426.kg1075 |
||||
,kgd426.kg1074 |
||||
Order by 1 |
||||
""" |
||||
try: |
||||
result = con.execute(query).all() |
||||
try: |
||||
dataframe = pd.DataFrame(result) |
||||
return dataframe |
||||
except: |
||||
print(f"Failed to create a dataframe from SQL result:\n{result}") |
||||
except Exception as e: |
||||
print(f"Failed to pull data from SQL:\n{query}\n{e}") |
||||
except Exception as e: |
||||
print(f"Failed to connect to SQL:\n{e}\nPlease make sure your username and password are correct!") |
||||
|
||||
def stats_for_col(columns: str, df: pd.DataFrame) -> pd.DataFrame: |
||||
return pd.DataFrame({ |
||||
"Data" : [col for col in columns], |
||||
"Mean": [df[col].mean() for col in columns], |
||||
"Median": [df[col].median() for col in columns], |
||||
"Max": [df[col].max() for col in columns], |
||||
"Std": [df[col].std() for col in columns] |
||||
}) |
||||
|
||||
def process_data(raw_report: pd.DataFrame) -> pd.DataFrame: |
||||
|
||||
# Convert columns to datetime] |
||||
date_time_format = "%Y-%m-%d %H:%M:%S.%f" |
||||
raw_report["StatusDateTime"] = pd.to_datetime(raw_report["StatusDateTime"], format="%b %d %Y %I:%M%p") |
||||
raw_report["firstattemptdate"] = pd.to_datetime(raw_report["firstattemptdate"], format=date_time_format) |
||||
raw_report["secondattemptdate"] = pd.to_datetime(raw_report["secondattemptdate"], format=date_time_format) |
||||
raw_report["QueueEntryTime"] = pd.to_datetime(raw_report["QueueEntryTime"], format=date_time_format) |
||||
raw_report["QueueExitTime"] = pd.to_datetime(raw_report["QueueExitTime"], format=date_time_format) |
||||
raw_report["APTurnAround"] = raw_report.apply(lambda row: businesshrs.difference(row.QueueEntryTime, row.QueueExitTime).timedelta.total_seconds() / 60**2 |
||||
if row.QueueExitTime > dt(1965,1,1) |
||||
and row.QueueExitTime > row.QueueEntryTime |
||||
else None, axis = 1) |
||||
raw_report["AttemptTimeDif"] = raw_report.apply(lambda row: businesshrs.difference(row.firstattemptdate, row.secondattemptdate).timedelta.total_seconds() / 60**2 |
||||
if |
||||
(row.secondattempt != None and row.firstattempt != None) and |
||||
(row.secondattemptdate > row.firstattemptdate) |
||||
else None, axis = 1) |
||||
raw_report["TimeToFirstAttempt"] = raw_report.apply(lambda row: businesshrs.difference(row.QueueEntryTime, row.firstattemptdate).timedelta.total_seconds() / 60**2 |
||||
if row.firstattempt != None and row.QueueEntryTime > dt(1965,1,1) |
||||
else None, axis = 1) |
||||
|
||||
unique_deals = len(raw_report["ApplicationNum"].unique()) |
||||
ver_on_first = len(raw_report.query("firstattempt == 'VERIFICATION COMPLETED'")) |
||||
verified = len(raw_report.query("Status == 'VERIFICATION COMPLETED'")) |
||||
|
||||
failed_on_first = len(raw_report.query("firstattempt != 'VERIFICATION COMPLETED' & firstattempt != 'VERIFICATION IN PROCESS'")) |
||||
|
||||
col_stats = stats_for_col(["APTurnAround", "AttemptTimeDif", "TimeToFirstAttempt"], raw_report) |
||||
prt(col_stats) |
||||
print(f"\n# of deals: {unique_deals} | # payments {len(raw_report)}") |
||||
print(f"Verified on first: {ver_on_first} ({round(ver_on_first/len(raw_report),4) *100}%) | Failed on first: {failed_on_first} ({round(failed_on_first/len(raw_report),4) *100}%)") |
||||
|
||||
pt_by_ap_rep = pd.pivot_table(raw_report, index="APRep", values= ["APTurnAround","AttemptTimeDif","TimeToFirstAttempt"],aggfunc = [np.mean, np.median, np.max]) |
||||
prt(pt_by_ap_rep) |
||||
|
||||
return raw_report |
||||
|
||||
|
||||
ach_raw_report = get_data() |
||||
prt(ach_raw_report) |
||||
#pfd(ach_raw_report) |
||||
report_plus = process_data(ach_raw_report) |
||||
prt(report_plus) |
||||
report_plus.to_excel("test3.xlsx",index=False) |
||||
Loading…
Reference in new issue