IAMTFRMZA commited on
Commit
f97e304
Β·
verified Β·
1 Parent(s): d5ae19a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +112 -86
app.py CHANGED
@@ -3,6 +3,7 @@ import gspread
3
  import gradio as gr
4
  from oauth2client.service_account import ServiceAccountCredentials
5
  from datetime import datetime
 
6
 
7
  # ------------------ AUTH ------------------
8
  VALID_USERS = {
@@ -25,47 +26,94 @@ def load_tab(sheet_name):
25
  except:
26
  return pd.DataFrame([["⚠️ Could not load sheet."]], columns=["Error"])
27
 
28
- def get_combined_orders(date_str):
29
- df_field = load_tab("Field Sales")
30
- df_ts = load_tab("TeleSales")
31
-
32
- combined = []
33
-
34
- if not df_field.empty:
35
- df_field['Date'] = pd.to_datetime(df_field['Date'], errors='coerce')
36
- df_field['DateStr'] = df_field['Date'].dt.date.astype(str)
37
- df_field = df_field[df_field['DateStr'] == date_str.strip()]
38
- df_field['Order Value'] = pd.to_numeric(df_field['Order Value'], errors='coerce').fillna(0)
39
- df_field_orders = df_field.groupby("Rep").agg({
40
- "Order Received": lambda x: (x == "Yes").sum(),
41
- "Order Value": "sum"
42
- }).reset_index().rename(columns={
43
- "Order Received": "Orders Received",
44
- "Order Value": "Total Order Value"
45
- })
46
- df_field_orders["Source"] = "Field Sales"
47
- combined.append(df_field_orders)
48
-
49
- if not df_ts.empty:
50
- df_ts['Date'] = pd.to_datetime(df_ts['Date'], errors='coerce')
51
- df_ts['DateStr'] = df_ts['Date'].dt.date.astype(str)
52
- df_ts = df_ts[df_ts['DateStr'] == date_str.strip()]
53
- df_ts['Order Value'] = pd.to_numeric(df_ts['Order Value'], errors='coerce').fillna(0)
54
- df_ts_orders = df_ts.groupby("Rep").agg({
55
- "Order Received": lambda x: (x == "Yes").sum(),
56
- "Order Value": "sum"
57
- }).reset_index().rename(columns={
58
- "Order Received": "Orders Received",
59
- "Order Value": "Total Order Value"
60
- })
61
- df_ts_orders["Source"] = "TeleSales"
62
- combined.append(df_ts_orders)
63
-
64
- if combined:
65
- return pd.concat(combined, ignore_index=True)
66
- else:
67
- return pd.DataFrame([["No orders on this date"]], columns=["Message"])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
68
 
 
69
  def get_requests():
70
  df = load_tab("Customer Requests")
71
  return df if not df.empty else pd.DataFrame([["No requests yet."]], columns=["Message"])
@@ -78,22 +126,8 @@ def get_users():
78
  df = load_tab("Users")
79
  return df if not df.empty else pd.DataFrame([["No users configured."]], columns=["Message"])
80
 
81
- def get_telesales_summary():
82
- df = load_tab("TeleSales")
83
- if df.empty or "Rep" not in df.columns:
84
- return pd.DataFrame([["No Telesales data available"]], columns=["Message"])
85
- return df.groupby("Rep").size().reset_index(name="Total Calls Made")
86
-
87
- def get_oem_summary():
88
- df = load_tab("OEM Visit")
89
- if df.empty or "Rep" not in df.columns:
90
- return pd.DataFrame([["No OEM data available"]], columns=["Message"])
91
- return df.groupby("Rep").size().reset_index(name="Total OEM Visits")
92
-
93
  def get_escalations():
94
- df = load_tab("Field Sales")
95
- if df.empty:
96
- return pd.DataFrame([["No data in Field Sales"]], columns=["Message"])
97
  col = "Customer Type & Status"
98
  if col in df.columns:
99
  flagged = df[df[col].str.contains("Second", na=False)]
@@ -101,14 +135,6 @@ def get_escalations():
101
  else:
102
  return pd.DataFrame([["⚠️ Column 'Customer Type & Status' not found."]], columns=["Message"])
103
 
104
- def load_field_sales():
105
- df = load_tab("Field Sales")
106
- if df.empty:
107
- return pd.DataFrame()
108
- df["Date"] = pd.to_datetime(df.get("Date", datetime.today()), errors='coerce')
109
- df["DateStr"] = df["Date"].dt.date.astype(str)
110
- return df
111
-
112
  # ------------------ GRADIO APP ------------------
113
  with gr.Blocks() as app:
114
  with gr.Row():
@@ -122,50 +148,50 @@ with gr.Blocks() as app:
122
  with gr.Column(visible=False) as main_ui:
123
  gr.Markdown("## πŸ—‚οΈ CarMat Dashboard")
124
 
125
- df_initial = load_field_sales()
126
- unique_dates = sorted(df_initial["DateStr"].unique(), reverse=True) if not df_initial.empty else []
127
-
128
- # --- Tabs ---
129
  with gr.Tab("πŸ“Š Summary"):
130
- gr.Markdown("Summary content coming soon...")
131
 
132
- with gr.Tab("πŸ“‚ Field Sales"):
133
- field_df = gr.Dataframe(value=load_field_sales, label="πŸ“‚ Field Sales Records", interactive=False)
134
- field_btn = gr.Button("πŸ”„ Refresh Field Sales")
135
- field_btn.click(fn=load_field_sales, outputs=field_df)
136
 
 
137
  with gr.Tab("πŸ“ž TeleSales"):
138
- ts_table = gr.Dataframe(value=get_telesales_summary, label="πŸ“ž TeleSales Summary")
139
- ts_refresh = gr.Button("πŸ”„ Refresh")
140
- ts_refresh.click(fn=get_telesales_summary, outputs=ts_table)
141
 
142
- with gr.Tab("πŸ“¦ Orders Summary"):
143
- order_date = gr.Dropdown(label="Select Date", choices=unique_dates, interactive=True)
144
- order_table = gr.Dataframe(label="🧾 Combined Order Summary")
145
- order_date.change(fn=get_combined_orders, inputs=order_date, outputs=order_table)
146
 
 
147
  with gr.Tab("🚨 Escalations"):
148
- esc_table = gr.Dataframe(value=get_escalations, label="🚨 Used Dealership Escalations")
149
- esc_btn = gr.Button("πŸ”„ Refresh Escalations")
150
  esc_btn.click(fn=get_escalations, outputs=esc_table)
151
 
 
152
  with gr.Tab("🏭 OEM Visits"):
153
- oem_table = gr.Dataframe(value=get_oem_summary, label="🏭 OEM Visit Summary")
154
- oem_refresh = gr.Button("πŸ”„ Refresh")
155
  oem_refresh.click(fn=get_oem_summary, outputs=oem_table)
156
 
 
157
  with gr.Tab("πŸ“¬ Customer Requests"):
158
- req_table = gr.Dataframe(value=get_requests, label="πŸ“¬ Customer Requests", interactive=False)
159
  req_refresh = gr.Button("πŸ”„ Refresh Requests")
160
  req_refresh.click(fn=get_requests, outputs=req_table)
161
 
 
162
  with gr.Tab("πŸ“‹ Dealership Directory"):
163
- listings_table = gr.Dataframe(value=get_listings, label="πŸ“‹ Customer Listings")
164
  listings_refresh = gr.Button("πŸ”„ Refresh Listings")
165
  listings_refresh.click(fn=get_listings, outputs=listings_table)
166
 
 
167
  with gr.Tab("πŸ‘€ Users"):
168
- users_table = gr.Dataframe(value=get_users, label="πŸ‘₯ Users")
169
  users_refresh = gr.Button("πŸ”„ Refresh Users")
170
  users_refresh.click(fn=get_users, outputs=users_table)
171
 
 
3
  import gradio as gr
4
  from oauth2client.service_account import ServiceAccountCredentials
5
  from datetime import datetime
6
+ from math import radians, cos, sin, asin, sqrt
7
 
8
  # ------------------ AUTH ------------------
9
  VALID_USERS = {
 
26
  except:
27
  return pd.DataFrame([["⚠️ Could not load sheet."]], columns=["Error"])
28
 
29
+ def haversine(coord1, coord2):
30
+ try:
31
+ lon1, lat1 = map(radians, map(float, coord1.split(',')[::-1]))
32
+ lon2, lat2 = map(radians, map(float, coord2.split(',')[::-1]))
33
+ dlon = lon2 - lon1
34
+ dlat = lat2 - lat1
35
+ a = sin(dlat/2)**2 + cos(lat1) * cos(lat2) * sin(dlon/2)**2
36
+ c = 2 * asin(sqrt(a))
37
+ return round(6371 * c, 2)
38
+ except:
39
+ return 0.0
40
+
41
+ # ------------------ FIELD SALES ------------------
42
+ def load_field_sales():
43
+ df = load_tab("Field Sales")
44
+ if df.empty:
45
+ return pd.DataFrame(columns=["Date", "Rep", "Order Value", "Order Received", "Location", "DateStr", "KM Travelled"])
46
+
47
+ df['Date'] = pd.to_datetime(df.get("Date", datetime.today()), errors='coerce')
48
+ df = df.dropna(subset=["Date"])
49
+ df['DateStr'] = df['Date'].dt.date.astype(str)
50
+ df["Order Value"] = pd.to_numeric(df.get("Order Value", 0), errors="coerce").fillna(0)
51
+
52
+ df["KM Travelled"] = 0.0
53
+ for rep in df["Rep"].unique():
54
+ rep_df = df[df["Rep"] == rep].sort_values(by="Date")
55
+ prev_coord = None
56
+ for idx, row in rep_df.iterrows():
57
+ curr_coord = row.get("Location", "")
58
+ if prev_coord:
59
+ df.at[idx, "KM Travelled"] = haversine(prev_coord, curr_coord)
60
+ prev_coord = curr_coord
61
+
62
+ return df
63
+
64
+ def get_field_summary():
65
+ df = load_field_sales()
66
+ if df.empty:
67
+ return pd.DataFrame([["No data available"]], columns=["Message"])
68
+ summary = df.groupby("Rep").agg({
69
+ "Order Value": "sum",
70
+ "Order Received": lambda x: (x == "Yes").sum(),
71
+ "KM Travelled": "sum"
72
+ }).reset_index().rename(columns={
73
+ "Order Value": "Total Order Value",
74
+ "Order Received": "Orders Received"
75
+ })
76
+ return summary
77
+
78
+ # ------------------ TELESALES ------------------
79
+ def get_telesales_summary():
80
+ df = load_tab("TeleSales")
81
+ if df.empty or "Rep" not in df.columns:
82
+ return pd.DataFrame([["No data available"]], columns=["Message"])
83
+ df["Date"] = pd.to_datetime(df.get("Date", datetime.today()), errors='coerce')
84
+ df["DateStr"] = df["Date"].dt.date.astype(str)
85
+ df["Order Value"] = pd.to_numeric(df.get("Order Value", 0), errors="coerce").fillna(0)
86
+
87
+ summary = df.groupby("Rep").agg({
88
+ "Order Value": "sum",
89
+ "Order Received": lambda x: (x == "Yes").sum()
90
+ }).reset_index().rename(columns={
91
+ "Order Value": "Total Order Value",
92
+ "Order Received": "Orders Received"
93
+ })
94
+ return summary
95
+
96
+ # ------------------ COMBINED ORDERS ------------------
97
+ def get_combined_orders():
98
+ fs = get_field_summary()
99
+ ts = get_telesales_summary()
100
+
101
+ fs["Source"] = "Field Sales"
102
+ ts["Source"] = "TeleSales"
103
+
104
+ combined = pd.concat([fs, ts], ignore_index=True)
105
+ return combined[["Rep", "Orders Received", "Total Order Value", "Source"]].sort_values(by="Total Order Value", ascending=False)
106
+
107
+ # ------------------ OEM VISITS ------------------
108
+ def get_oem_summary():
109
+ df = load_tab("OEM Visit")
110
+ if df.empty or "Rep" not in df.columns:
111
+ return pd.DataFrame([["No data available"]], columns=["Message"])
112
+ df["Date"] = pd.to_datetime(df.get("Date", datetime.today()), errors='coerce')
113
+ df["DateStr"] = df["Date"].dt.date.astype(str)
114
+ return df.groupby(["Rep", "DateStr"]).size().reset_index(name="OEM Visits")
115
 
116
+ # ------------------ OTHER TABS ------------------
117
  def get_requests():
118
  df = load_tab("Customer Requests")
119
  return df if not df.empty else pd.DataFrame([["No requests yet."]], columns=["Message"])
 
126
  df = load_tab("Users")
127
  return df if not df.empty else pd.DataFrame([["No users configured."]], columns=["Message"])
128
 
 
 
 
 
 
 
 
 
 
 
 
 
129
  def get_escalations():
130
+ df = load_field_sales()
 
 
131
  col = "Customer Type & Status"
132
  if col in df.columns:
133
  flagged = df[df[col].str.contains("Second", na=False)]
 
135
  else:
136
  return pd.DataFrame([["⚠️ Column 'Customer Type & Status' not found."]], columns=["Message"])
137
 
 
 
 
 
 
 
 
 
138
  # ------------------ GRADIO APP ------------------
139
  with gr.Blocks() as app:
140
  with gr.Row():
 
148
  with gr.Column(visible=False) as main_ui:
149
  gr.Markdown("## πŸ—‚οΈ CarMat Dashboard")
150
 
151
+ # --- Summary Tab ---
 
 
 
152
  with gr.Tab("πŸ“Š Summary"):
153
+ summary_table = gr.Dataframe(label="Combined Orders", value=get_combined_orders)
154
 
155
+ # --- Field Sales Tab ---
156
+ with gr.Tab("πŸ›£οΈ Field Sales"):
157
+ fs_table = gr.Dataframe(label="Field Sales Summary", value=get_field_summary)
158
+ fs_raw = gr.Dataframe(label="Raw Field Sales", value=load_field_sales)
159
 
160
+ # --- Telesales Tab ---
161
  with gr.Tab("πŸ“ž TeleSales"):
162
+ ts_table = gr.Dataframe(label="TeleSales Summary", value=get_telesales_summary)
 
 
163
 
164
+ # --- Orders Tab ---
165
+ with gr.Tab("πŸ“¦ Orders"):
166
+ order_table = gr.Dataframe(label="All Orders Combined", value=get_combined_orders)
 
167
 
168
+ # --- Escalations ---
169
  with gr.Tab("🚨 Escalations"):
170
+ esc_table = gr.Dataframe(value=get_escalations, label="Second-hand Dealerships")
171
+ esc_btn = gr.Button("πŸ”„ Refresh")
172
  esc_btn.click(fn=get_escalations, outputs=esc_table)
173
 
174
+ # --- OEM Visits ---
175
  with gr.Tab("🏭 OEM Visits"):
176
+ oem_table = gr.Dataframe(value=get_oem_summary, label="OEM Visit Summary")
177
+ oem_refresh = gr.Button("πŸ”„ Refresh OEM")
178
  oem_refresh.click(fn=get_oem_summary, outputs=oem_table)
179
 
180
+ # --- Requests ---
181
  with gr.Tab("πŸ“¬ Customer Requests"):
182
+ req_table = gr.Dataframe(value=get_requests, label="Customer Requests", interactive=False)
183
  req_refresh = gr.Button("πŸ”„ Refresh Requests")
184
  req_refresh.click(fn=get_requests, outputs=req_table)
185
 
186
+ # --- Dealership Listings ---
187
  with gr.Tab("πŸ“‹ Dealership Directory"):
188
+ listings_table = gr.Dataframe(value=get_listings, label="Customer Listings")
189
  listings_refresh = gr.Button("πŸ”„ Refresh Listings")
190
  listings_refresh.click(fn=get_listings, outputs=listings_table)
191
 
192
+ # --- Users ---
193
  with gr.Tab("πŸ‘€ Users"):
194
+ users_table = gr.Dataframe(value=get_users, label="Users")
195
  users_refresh = gr.Button("πŸ”„ Refresh Users")
196
  users_refresh.click(fn=get_users, outputs=users_table)
197