Spaces:
Sleeping
Sleeping
File size: 8,920 Bytes
88ff990 4e6e288 88ff990 de7d48b 4e6e288 1f48402 4e6e288 de7d48b 4e6e288 1f48402 de7d48b 581bd58 4e6e288 de7d48b 268f142 de7d48b 50acac4 |
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 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 |
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"])
# ------------------ FIELD SALES ------------------
def load_field_sales():
df = load_tab("Field Sales")
if df.empty:
return pd.DataFrame(columns=["Date", "Rep", "Order Value", "Order Received", "Current/Prospect Custor", "Customer Type & Status", "DateStr"])
df['Date'] = pd.to_datetime(df.get("Date", datetime.today()), errors='coerce')
df = df.dropna(subset=["Date"])
df['DateStr'] = df['Date'].dt.date.astype(str)
if "Order Value" not in df.columns:
df["Order Value"] = 0
else:
df["Order Value"] = pd.to_numeric(df["Order Value"], errors="coerce").fillna(0)
return df
def generate_summary(date_str):
df = load_field_sales()
if df.empty:
return pd.DataFrame([["No data"]], columns=["Message"]), pd.DataFrame(), pd.DataFrame()
all_reps = sorted(df['Rep'].dropna().unique())
day_df = df[df['DateStr'] == date_str]
total_visits = day_df.groupby("Rep").size().reset_index(name="Total Visits")
col = "Current/Prospect Custor"
if col not in df.columns:
df[col] = ""
current = day_df[day_df[col] == "Current"]
prospect = day_df[day_df[col] == "Prospect"]
breakdown = pd.DataFrame({
"Rep": all_reps,
"Current": [len(current[current["Rep"] == rep]) for rep in all_reps],
"Prospect": [len(prospect[prospect["Rep"] == rep]) for rep in all_reps]
})
active_list = total_visits['Rep'].tolist()
inactive_list = [rep for rep in all_reps if rep not in active_list]
inactive_df = pd.DataFrame({'Inactive Reps': inactive_list})
return total_visits, breakdown, inactive_df
def get_order_summary(date_str):
df = load_field_sales()
if df.empty:
return pd.DataFrame([["No data"]], columns=["Message"])
day_df = df[df['DateStr'] == date_str]
if "Order Received" not in df.columns:
df["Order Received"] = ""
rep_group = day_df.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"
})
return rep_group.sort_values(by="Total Order Value", ascending=False)
def get_escalations():
df = load_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"])
# ------------------ TELESALeS ------------------
def get_telesales_summary():
df = load_tab("TeleSales")
if df.empty or "Rep Email" not in df.columns:
return pd.DataFrame([["No data available"]], columns=["Message"])
df["Date"] = pd.to_datetime(df.get("Date", datetime.today()), errors='coerce')
df["DateStr"] = df["Date"].dt.date.astype(str)
grouped = df.groupby(["Rep Email", "DateStr"]).size().reset_index(name="Calls Made")
return grouped.rename(columns={"Rep Email": "Rep"})
# ------------------ OEM VISITS ------------------
def get_oem_summary():
df = load_tab("OEM Visit")
if df.empty or "Rep" not in df.columns:
return pd.DataFrame([["No data available"]], columns=["Message"])
df["Date"] = pd.to_datetime(df.get("Date", datetime.today()), errors='coerce')
df["DateStr"] = df["Date"].dt.date.astype(str)
return df.groupby(["Rep", "DateStr"]).size().reset_index(name="OEM Visits")
# ------------------ CUSTOMER REQUESTS ------------------
def get_requests():
df = load_tab("Customer Requests")
return df if not df.empty else pd.DataFrame([["No requests yet."]], columns=["Message"])
# ------------------ CUSTOMER LISTINGS ------------------
def get_listings():
df = load_tab("CustomerListings")
return df if not df.empty else pd.DataFrame([["No listings found."]], columns=["Message"])
# ------------------ USERS ------------------
def get_users():
df = load_tab("Users")
return df if not df.empty else pd.DataFrame([["No users configured."]], columns=["Message"])
# ------------------ 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 []
# --- Summary Tab ---
with gr.Tab("π Summary"):
date_summary = gr.Dropdown(label="Select Date", choices=unique_dates)
visits = gr.Dataframe(label="β
Total Visits")
breakdown = gr.Dataframe(label="π·οΈ Current vs. Prospect")
inactive = gr.Dataframe(label="β οΈ Inactive Reps")
date_summary.change(fn=generate_summary, inputs=date_summary, outputs=[visits, breakdown, inactive])
# --- Orders Tab ---
with gr.Tab("π¦ Orders"):
order_date = gr.Dropdown(label="Select Date", choices=unique_dates)
order_table = gr.Dataframe(label="π° Orders Summary")
order_date.change(fn=get_order_summary, inputs=order_date, outputs=order_table)
# --- Escalations ---
with gr.Tab("π¨ Escalations"):
esc_table = gr.Dataframe(value=get_escalations, label="Second-hand Dealerships")
esc_btn = gr.Button("π Refresh")
esc_btn.click(fn=get_escalations, outputs=esc_table)
# --- TeleSales ---
with gr.Tab("π TeleSales"):
ts_table = gr.Dataframe(value=get_telesales_summary, label="TeleSales Summary")
ts_refresh = gr.Button("π Refresh TeleSales")
ts_refresh.click(fn=get_telesales_summary, outputs=ts_table)
# --- OEM Visits ---
with gr.Tab("π OEM Visits"):
oem_table = gr.Dataframe(value=get_oem_summary, label="OEM Visit Summary")
oem_refresh = gr.Button("π Refresh OEM")
oem_refresh.click(fn=get_oem_summary, outputs=oem_table)
# --- Requests ---
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)
# --- Dealerships ---
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)
# --- Users ---
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() |