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()