Spaces:
Sleeping
Sleeping
File size: 7,857 Bytes
88ff990 4e6e288 88ff990 4e6e288 98b1c1d 4e6e288 a992c26 4e6e288 98b1c1d 4e6e288 98b1c1d 4e6e288 98b1c1d 4e6e288 98b1c1d 4e6e288 268f142 4e6e288 fd030cb 4e6e288 88ff990 4e6e288 88ff990 a992c26 |
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 |
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") # Ensure this is the exact sheet name in Google Sheets
# ------------------ HELPERS ------------------
def load_tab(sheet_name):
return pd.DataFrame(sheet_file.worksheet(sheet_name).get_all_records())
# ------------------ FIELD SALES ------------------
def load_field_sales():
df = load_tab("Field Sales")
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)
# β
Fix: ensure column exists before numeric conversion
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()
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")
curr_col = "Current/Prospect Custor"
if curr_col not in df.columns:
df[curr_col] = ""
current = day_df[day_df[curr_col] == "Current"]
prospect = day_df[day_df[curr_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()
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()
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=["Status"])
else:
return pd.DataFrame([["β οΈ Column 'Customer Type & Status' not found."]], columns=["Status"])
# ------------------ TELESALeS ------------------
def get_telesales_summary():
df = load_tab("TeleSales")
df["Date"] = pd.to_datetime(df.get("Date", datetime.today()), errors='coerce')
df["DateStr"] = df["Date"].dt.date.astype(str)
return df.groupby(["Rep Email", "DateStr"]).size().reset_index(name="Calls Made")
# ------------------ OEM VISITS ------------------
def get_oem_summary():
df = load_tab("OEM Visit")
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():
return load_tab("Customer Requests")
# ------------------ CUSTOMER LISTINGS ------------------
def get_listings():
return load_tab("CustomerListings")
# ------------------ USERS ------------------
def get_users():
return load_tab("Users")
# ------------------ 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)
# --- 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()
|