File size: 6,210 Bytes
d0b9289
 
 
 
 
 
 
 
 
 
 
 
 
 
486cc90
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d0b9289
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e78b9c5
 
d0b9289
 
 
 
 
 
 
 
 
 
 
 
 
486cc90
 
 
 
 
 
 
 
 
 
d0b9289
 
486cc90
 
 
 
d0b9289
 
486cc90
 
 
 
 
d0b9289
 
486cc90
 
 
d0b9289
 
486cc90
 
 
d0b9289
 
 
e78b9c5
d0b9289
 
 
 
5d3691f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d0b9289
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
486cc90
d0b9289
 
 
 
 
 
 
486cc90
d0b9289
 
 
 
e78b9c5
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
import gradio as gr
import pandas as pd
import joblib
import plotly.express as px
import plotly.graph_objects as go

# --- 1. DATA & MODEL LOADING ---
# Load your model and feature list
model = joblib.load("sales_model.joblib")
feature_names = joblib.load("feature_names.joblib")

# Load your CSV for EDA charts
df = pd.read_csv("sales_data.csv")
df['date'] = pd.to_datetime(df['date'])
df['revenue'] = df['units_sold'] * df['price_unit']
df['weekday'] = df['date'].dt.day_name()

# --- 2. HELPERS & INSIGHTS ---
def get_business_insights():
    promo_avg = df.groupby('promotion_flag')['units_sold'].mean()
    lift = ((promo_avg[1] - promo_avg[0]) / promo_avg[0]) * 100
    top_brand = df.groupby('brand')['revenue'].sum().idxmax()
    top_region = df.groupby('region')['units_sold'].sum().idxmax()
    
    insights = f"""
    ### ๐Ÿ’ก Key Business Insights
    * **Promotion Impact:** Promotions drive a **{lift:.1f}% increase** in average sales volume.
    * **Revenue Leader:** **{top_brand}** is currently the top-performing brand by total revenue.
    * **Regional Powerhouse:** **{top_region}** is the highest volume region.
    * **Inventory Note:** Average stock availability is currently **{df['stock_available'].mean():.1f} units**.
    """
    return insights

# --- 2. PREDICTION LOGIC ---
def predict_sales(u_date, u_brand, u_region, u_price, u_promo, u_stock):
    target_date = pd.to_datetime(u_date)
    
    # Initialize input row with zeros matching training features
    input_row = pd.DataFrame(0, index=[0], columns=feature_names)
    
    # Fill Time Features
    input_row['month'] = target_date.month
    input_row['day_of_week'] = target_date.weekday()
    input_row['is_weekend'] = 1 if target_date.weekday() >= 5 else 0
    
    # Fill Numerical Features
    input_row['price_unit'] = u_price
    input_row['promotion_flag'] = 1 if u_promo else 0
    input_row['stock_available'] = u_stock
    
    # Fill Categorical Features (One-Hot Encoding match)
    brand_col = f"brand_{u_brand}"
    region_col = f"region_{u_region}"
    
    if brand_col in input_row.columns: input_row[brand_col] = 1
    if region_col in input_row.columns: input_row[region_col] = 1
            
    # Predict
    prediction = model.predict(input_row)[0]
    prediction = max(0, int(prediction))
    revenue = prediction * u_price
    
    # Context Chart
    brand_avg = df[df['brand'] == u_brand]['units_sold'].mean()
    categories = ['Predicted', f'{u_brand} Avg']
    values = [prediction, brand_avg]
    fig = px.bar(x=categories, y=values, color=categories, 
                 title=f"Forecast vs. {u_brand} Average",
                 labels={'x': '', 'y': 'Units'})
    fig.update_layout(showlegend=False, height=300)
    
    return f"{prediction} Units", f"${revenue:,.2f}", fig

# --- 3. EDA CHART FUNCTIONS ---
def plot_brand_revenue():
    brand_rev = df.groupby('brand')['revenue'].sum().sort_values(ascending=True).reset_index()
    fig = px.bar(brand_rev, x='revenue', y='brand', orientation='h',
                 title="Total Revenue by Brand", color='revenue', color_continuous_scale='Viridis')
    return fig

def plot_promo_lift():
    promo_data = df.groupby('promotion_flag')['units_sold'].mean().reset_index()
    promo_data['promotion_flag'] = promo_data['promotion_flag'].map({0: 'No Promo', 1: 'Promo Active'})
    fig = px.bar(promo_data, x='promotion_flag', y='units_sold', color='promotion_flag',
                 title="Average Volume: Promotion Impact")
    return fig

def plot_region_sales():
    region_sales = df.groupby('region')['units_sold'].sum().reset_index()
    fig = px.pie(region_sales, values='units_sold', names='region', title="Volume by Region", hole=0.4)
    return fig

def plot_sales_trend():
    trend = df.resample('W', on='date')['units_sold'].sum().reset_index()
    fig = px.line(trend, x='date', y='units_sold', title="Weekly Sales Trend", markers=True)
    return fig

# --- 4. GRADIO UI LAYOUT ---
with gr.Blocks() as demo:
    gr.Markdown("# ๐Ÿฅ› Smart Sales & Revenue Intelligence")
    gr.Markdown("Predict future performance and explore historical data patterns.")

    with gr.Tabs():
        # TAB 1: DATA EXPLORATION
        with gr.TabItem("๐Ÿ“Š EDA Dashboard"):
            gr.Markdown(get_business_insights())
            
            with gr.Row():
                gr.Plot(plot_brand_revenue())
                gr.Plot(plot_promo_lift())
            with gr.Row():
                gr.Plot(plot_sales_trend())
                gr.Plot(plot_region_sales())
            
            with gr.Accordion("View Raw Data Snippet", open=False):
                gr.DataFrame(df.sample(10))

        # TAB 2: PREDICTOR
        with gr.TabItem("๐Ÿ”ฎ Sales Forecast"):
            with gr.Row():
                with gr.Column():
                    gr.Markdown("### Input Parameters")
                    u_date = gr.DateTime(label="Select Target Date")
                    u_brand = gr.Dropdown(sorted(df['brand'].unique().tolist()), label="Brand")
                    u_region = gr.Dropdown(sorted(df['region'].unique().tolist()), label="Region")
                    u_price = gr.Number(label="Unit Price ($)", value=2.50)
                    u_promo = gr.Checkbox(label="Is Promotion Active?")
                    u_stock = gr.Slider(0, 500, label="Stock Availability", value=150)
                    predict_btn = gr.Button("Generate Prediction", variant="primary")
                
                with gr.Column():
                    gr.Markdown("### Model Output")
                    out_sales = gr.Textbox(label="Predicted Sales Volume")
                    out_rev = gr.Textbox(label="Estimated Gross Revenue")
                    out_plot = gr.Plot(label="Forecast Context")
                    
                    gr.Markdown("---")
                    gr.Info("Note: Predictions are based on historical XGBoost training patterns.")

            predict_btn.click(
                predict_sales, 
                inputs=[u_date, u_brand, u_region, u_price, u_promo, u_stock], 
                outputs=[out_sales, out_rev, out_plot]
            )

# --- 5. LAUNCH ---
if __name__ == "__main__":
    demo.launch(theme=gr.themes.Soft())