Spaces:
Sleeping
Sleeping
File size: 7,831 Bytes
88ff990 4e6e288 88ff990 de7d48b 4e6e288 1f48402 4e6e288 de7d48b 4e6e288 1f48402 de7d48b 16ba360 6259813 16ba360 de7d48b 16ba360 12477af 16ba360 12477af 16ba360 12477af 16ba360 12477af 16ba360 12477af 16ba360 12477af 4e6e288 de7d48b 268f142 de7d48b 16ba360 de7d48b 16ba360 6259813 de7d48b 50acac4 6259813 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 |
import pandas as pd
import gspread
import gradio as gr
from oauth2client.service_account import ServiceAccountCredentials
from datetime import datetime
# ------------------ AUTH ------------------
VALID_USERS = {
"[email protected]": "Pass.123",
"[email protected]": "Pass.123",
"[email protected]": "Pass.123"
}
# ------------------ GOOGLE SHEET SETUP ------------------
scope = ["https://spreadsheets.google.com/feeds", "https://www.googleapis.com/auth/drive"]
creds = ServiceAccountCredentials.from_json_keyfile_name("credentials.json", scope)
client = gspread.authorize(creds)
sheet_file = client.open("userAccess")
# ------------------ HELPERS ------------------
def load_tab(sheet_name):
try:
df = pd.DataFrame(sheet_file.worksheet(sheet_name).get_all_records())
return df
except:
return pd.DataFrame([["β οΈ Could not load sheet."]], columns=["Error"])
def get_combined_orders(date_str):
df_field = load_tab("Field Sales")
df_ts = load_tab("TeleSales")
combined = []
if not df_field.empty:
df_field['Date'] = pd.to_datetime(df_field['Date'], errors='coerce')
df_field['DateStr'] = df_field['Date'].dt.date.astype(str)
df_field = df_field[df_field['DateStr'] == date_str.strip()]
df_field['Order Value'] = pd.to_numeric(df_field['Order Value'], errors='coerce').fillna(0)
df_field_orders = df_field.groupby("Rep").agg({
"Order Received": lambda x: (x == "Yes").sum(),
"Order Value": "sum"
}).reset_index().rename(columns={
"Order Received": "Orders Received",
"Order Value": "Total Order Value"
})
df_field_orders["Source"] = "Field Sales"
combined.append(df_field_orders)
if not df_ts.empty:
df_ts['Date'] = pd.to_datetime(df_ts['Date'], errors='coerce')
df_ts['DateStr'] = df_ts['Date'].dt.date.astype(str)
df_ts = df_ts[df_ts['DateStr'] == date_str.strip()]
df_ts['Order Value'] = pd.to_numeric(df_ts['Order Value'], errors='coerce').fillna(0)
df_ts_orders = df_ts.groupby("Rep").agg({
"Order Received": lambda x: (x == "Yes").sum(),
"Order Value": "sum"
}).reset_index().rename(columns={
"Order Received": "Orders Received",
"Order Value": "Total Order Value"
})
df_ts_orders["Source"] = "TeleSales"
combined.append(df_ts_orders)
if combined:
return pd.concat(combined, ignore_index=True)
else:
return pd.DataFrame([["No orders on this date"]], columns=["Message"])
def get_requests():
df = load_tab("Customer Requests")
return df if not df.empty else pd.DataFrame([["No requests yet."]], columns=["Message"])
def get_listings():
df = load_tab("CustomerListings")
return df if not df.empty else pd.DataFrame([["No listings found."]], columns=["Message"])
def get_users():
df = load_tab("Users")
return df if not df.empty else pd.DataFrame([["No users configured."]], columns=["Message"])
def get_telesales_summary():
df = load_tab("TeleSales")
if df.empty or "Rep" not in df.columns:
return pd.DataFrame([["No Telesales data available"]], columns=["Message"])
return df.groupby("Rep").size().reset_index(name="Total Calls Made")
def get_oem_summary():
df = load_tab("OEM Visit")
if df.empty or "Rep" not in df.columns:
return pd.DataFrame([["No OEM data available"]], columns=["Message"])
return df.groupby("Rep").size().reset_index(name="Total OEM Visits")
def get_escalations():
df = load_tab("Field Sales")
if df.empty:
return pd.DataFrame([["No data in Field Sales"]], columns=["Message"])
col = "Customer Type & Status"
if col in df.columns:
flagged = df[df[col].str.contains("Second", na=False)]
return flagged if not flagged.empty else pd.DataFrame([["No second-hand dealerships flagged."]], columns=["Message"])
else:
return pd.DataFrame([["β οΈ Column 'Customer Type & Status' not found."]], columns=["Message"])
def load_field_sales():
df = load_tab("Field Sales")
if df.empty:
return pd.DataFrame()
df["Date"] = pd.to_datetime(df.get("Date", datetime.today()), errors='coerce')
df["DateStr"] = df["Date"].dt.date.astype(str)
return df
# ------------------ GRADIO APP ------------------
with gr.Blocks() as app:
with gr.Row():
with gr.Column(visible=True) as login_ui:
gr.Markdown("## π Login Required")
email = gr.Textbox(label="Email")
password = gr.Textbox(label="Password", type="password")
login_btn = gr.Button("Login")
login_msg = gr.Markdown("")
with gr.Column(visible=False) as main_ui:
gr.Markdown("## ποΈ CarMat Dashboard")
df_initial = load_field_sales()
unique_dates = sorted(df_initial["DateStr"].unique(), reverse=True) if not df_initial.empty else []
# --- Tabs ---
with gr.Tab("π Summary"):
gr.Markdown("Summary content coming soon...")
with gr.Tab("π Field Sales"):
field_df = gr.Dataframe(value=load_field_sales, label="π Field Sales Records", interactive=False)
field_btn = gr.Button("π Refresh Field Sales")
field_btn.click(fn=load_field_sales, outputs=field_df)
with gr.Tab("π TeleSales"):
ts_table = gr.Dataframe(value=get_telesales_summary, label="π TeleSales Summary")
ts_refresh = gr.Button("π Refresh")
ts_refresh.click(fn=get_telesales_summary, outputs=ts_table)
with gr.Tab("π¦ Orders Summary"):
order_date = gr.Dropdown(label="Select Date", choices=unique_dates, interactive=True)
order_table = gr.Dataframe(label="π§Ύ Combined Order Summary")
order_date.change(fn=get_combined_orders, inputs=order_date, outputs=order_table)
with gr.Tab("π¨ Escalations"):
esc_table = gr.Dataframe(value=get_escalations, label="π¨ Used Dealership Escalations")
esc_btn = gr.Button("π Refresh Escalations")
esc_btn.click(fn=get_escalations, outputs=esc_table)
with gr.Tab("π OEM Visits"):
oem_table = gr.Dataframe(value=get_oem_summary, label="π OEM Visit Summary")
oem_refresh = gr.Button("π Refresh")
oem_refresh.click(fn=get_oem_summary, outputs=oem_table)
with gr.Tab("π¬ Customer Requests"):
req_table = gr.Dataframe(value=get_requests, label="π¬ Customer Requests", interactive=False)
req_refresh = gr.Button("π Refresh Requests")
req_refresh.click(fn=get_requests, outputs=req_table)
with gr.Tab("π Dealership Directory"):
listings_table = gr.Dataframe(value=get_listings, label="π Customer Listings")
listings_refresh = gr.Button("π Refresh Listings")
listings_refresh.click(fn=get_listings, outputs=listings_table)
with gr.Tab("π€ Users"):
users_table = gr.Dataframe(value=get_users, label="π₯ Users")
users_refresh = gr.Button("π Refresh Users")
users_refresh.click(fn=get_users, outputs=users_table)
def do_login(user, pw):
if VALID_USERS.get(user) == pw:
return gr.update(visible=False), gr.update(visible=True), ""
else:
return gr.update(visible=True), gr.update(visible=False), "β Invalid login."
login_btn.click(fn=do_login, inputs=[email, password], outputs=[login_ui, main_ui, login_msg])
app.launch()
|