File size: 11,293 Bytes
e6f9a4e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8c47c78
 
 
 
b335a84
e6f9a4e
8c47c78
 
e6f9a4e
 
 
 
 
 
 
 
 
 
 
 
 
8c47c78
e6f9a4e
 
8c47c78
e6f9a4e
 
 
 
8c47c78
b335a84
8c47c78
b335a84
 
8c47c78
 
b335a84
 
 
8c47c78
b335a84
8c47c78
 
b335a84
8c47c78
 
b335a84
 
 
 
 
8c47c78
 
b335a84
 
 
351ad2c
b335a84
 
351ad2c
b335a84
 
351ad2c
8c47c78
b335a84
 
 
 
 
 
 
 
 
 
 
 
 
8c47c78
 
 
 
 
 
 
 
 
 
b335a84
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8c47c78
 
b335a84
8c47c78
b335a84
8c47c78
 
 
b335a84
8c47c78
 
 
 
b335a84
8c47c78
 
 
 
 
b335a84
e6f9a4e
8c47c78
 
 
 
 
 
 
 
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
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
# import pandas as pd
# from prophet import Prophet
# import gradio as gr
# import plotly.graph_objs as go
# import numpy as np
# import requests
# # Function to train the model and generate forecast
# def predict_sales(time_frame):
#     #login
#     url="https://livesystem.hisabkarlay.com/auth/login"
#     payload={
#       'username':'testuser',
#       'password':'testuser',
#       'client_secret':'3udPXhYSfCpktnls1C3TSzI96JLypqUGwJR05RHf',
#       'client_id':'4',
#       'grant_type':'password'
#     }
#     response=requests.post(url,data=payload)
#     print(response.text)
#     access_token=response.json()['access_token']
#     print(access_token)
#     #fetch all sell data
#     per_page=-1
#     url=f"https://livesystem.hisabkarlay.com/connector/api/sell?per_page={per_page}"
#     headers={
#       'Authorization':f'Bearer {access_token}'
#     }
#     response=requests.get(url,headers=headers)
#     data=response.json()['data']
#     date=[]
#     amount=[]
#     for item in data:
#       date.append(item.get('transaction_date'))
#       amount.append(float(item.get('final_total')))
#     data_dict={
#         'date':date,
#         'amount':amount
#     }
#     data_frame=pd.DataFrame(data_dict)
#     # Convert 'date' column to datetime format
#     data_frame['date'] = pd.to_datetime(data_frame['date'])

#     # Extract only the date part
#     data_frame['date_only'] = data_frame['date'].dt.date

#     # Group by date and calculate total sales
#     daily_sales = data_frame.groupby('date_only').agg(total_sales=('amount', 'sum')).reset_index()

#     # Prepare the DataFrame for Prophet
#     df = pd.DataFrame({
#         'Date': daily_sales['date_only'],
#         'Total paid': daily_sales['total_sales']
#     })

#     # Apply log transformation
#     df['y'] = np.log1p(df['Total paid'])  # Using log1p to avoid log(0)

#     # Prepare Prophet model
#     model = Prophet(weekly_seasonality=True)  # Enable weekly seasonality
#     df['ds'] = df['Date']
#     model.fit(df[['ds', 'y']])

#     # Future forecast based on the time frame
#     future_periods = {
#         'Next Day': 1,
#         '7 days': 7,
#         '10 days': 10,
#         '15 days': 15,
#         '1 month': 30
#     }

#     # Get the last historical date and calculate the start date for the forecast
#     last_date_value = df['Date'].iloc[-1]
#     forecast_start_date = pd.Timestamp(last_date_value) + pd.Timedelta(days=1)  # Start the forecast from the next day

#     # Generate the future time DataFrame starting from the day after the last date
#     future_time = model.make_future_dataframe(periods=future_periods[time_frame], freq='D')

#     # Filter future_time to include only future dates starting from forecast_start_date
#     future_only = future_time[future_time['ds'] >= forecast_start_date]
#     forecast = model.predict(future_only)

#     # Exponentiate the forecast to revert back to the original scale
#     forecast['yhat'] = np.expm1(forecast['yhat'])  # Use expm1 to handle the log transformation
#     forecast['yhat_lower'] = np.expm1(forecast['yhat_lower'])  # Exponentiate lower bound
#     forecast['yhat_upper'] = np.expm1(forecast['yhat_upper'])  # Exponentiate upper bound

#     # Create a DataFrame for weekends only
#     forecast['day_of_week'] = forecast['ds'].dt.day_name()  # Get the day name from the date
#     weekends = forecast[forecast['day_of_week'].isin(['Saturday', 'Sunday'])]  # Filter for weekends

#     # Display the forecasted data for the specified period
#     forecast_table = forecast[['ds', 'yhat', 'yhat_lower', 'yhat_upper']].head(future_periods[time_frame])
#     weekend_forecast_table = weekends[['ds', 'yhat', 'yhat_lower', 'yhat_upper']]  # Weekend forecast

#     # Create a Plotly graph
#     fig = go.Figure()
#     fig.add_trace(go.Scatter(
#         x=forecast['ds'], y=forecast['yhat'],
#         mode='lines+markers',
#         name='Forecasted Sales',
#         line=dict(color='orange'),
#         marker=dict(size=6),
#         hovertemplate='Date: %{x}<br>Forecasted Sales: %{y}<extra></extra>'
#     ))

#     # Add lines for yhat_lower and yhat_upper
#     fig.add_trace(go.Scatter(
#         x=forecast['ds'], y=forecast['yhat_lower'],
#         mode='lines',
#         name='Lower Bound',
#         line=dict(color='red', dash='dash')
#     ))

#     fig.add_trace(go.Scatter(
#         x=forecast['ds'], y=forecast['yhat_upper'],
#         mode='lines',
#         name='Upper Bound',
#         line=dict(color='green', dash='dash')
#     ))

#     fig.update_layout(
#         title='Sales Forecast using Prophet',
#         xaxis_title='Date',
#         yaxis_title='Sales Price',
#         xaxis=dict(tickformat="%Y-%m-%d"),
#         yaxis=dict(autorange=True)
#     )

#     return forecast_table, weekend_forecast_table, fig  # Return the forecast table, weekend forecast, and plot

# # Gradio interface
# def run_gradio():
#     # Create the Gradio Interface
#     time_options = ['Next Day', '7 days', '10 days', '15 days', '1 month']
#     gr.Interface(
#         fn=predict_sales,  # Function to be called
#         inputs=gr.components.Dropdown(time_options, label="Select Forecast Time Range"),  # User input
#         outputs=[
#             gr.components.Dataframe(label="Forecasted Sales Table"),  # Forecasted data in tabular form
#             gr.components.Dataframe(label="Weekend Forecasted Sales Table"),  # Weekend forecast data
#             gr.components.Plot(label="Sales Forecast Plot",min_width=500,scale=2)  # Plotly graph output
#         ],
#         title="Sales Forecasting with Prophet",
#         description="Select a time range for the forecast and click on the button to train the model and see the results."
#     ).launch(debug=True)

# # Run the Gradio interface
# if __name__ == '__main__':
#     run_gradio()
import pandas as pd
from prophet import Prophet
import gradio as gr
import plotly.graph_objs as go
import numpy as np

# Function to train the model and generate forecast
def predict_sales(time_frame):
    all_sales_data = pd.read_csv('All sales - House of Pizza.csv')

    # Clean up the 'Total paid' column by splitting based on '₨' symbol and converting to float
    def clean_total_paid(val):
        if isinstance(val, str):  # Only process if the value is a string
            amounts = [float(x.replace(',', '').strip()) for x in val.split('₨') if x.strip()]
            return sum(amounts)  # Sum if multiple values exist
        elif pd.isna(val):  # Handle NaN values
            return 0.0
        return val  # If it's already a float, return it as-is

    # Apply the cleaning function to the 'Total paid' column
    all_sales_data['Total paid'] = all_sales_data['Total paid'].apply(clean_total_paid)

    # Convert the 'Date' column to datetime, coercing errors
    all_sales_data['Date'] = pd.to_datetime(all_sales_data['Date'], format='%m/%d/%Y %H:%M', errors='coerce')

    # Drop rows with invalid dates
    all_sales_data = all_sales_data.dropna(subset=['Date'])
    all_sales_data['date_only'] = all_sales_data['Date'].dt.date
    daily_sales = all_sales_data.groupby('date_only').agg(total_sales=('Total paid', 'sum')).reset_index()

    # Prepare the DataFrame for Prophet
    df = pd.DataFrame({
        'Date': daily_sales['date_only'],
        'Total paid': daily_sales['total_sales']
    })

    # Apply log transformation
    df['y'] = np.log1p(df['Total paid'])  # Using log1p to avoid log(0)

    # Prepare Prophet model
    model = Prophet(weekly_seasonality=True)  # Enable weekly seasonality
    df['ds'] = df['Date']
    model.fit(df[['ds', 'y']])

    # Future forecast based on the time frame
    future_periods = {
        'Next Day': 1,
        '7 days': 7,
        '10 days': 10,
        '15 days': 15,
        '1 month': 30
    }

    # Get the last historical date and calculate the start date for the forecast
    last_date_value = df['Date'].iloc[-1]
    forecast_start_date = pd.Timestamp(last_date_value) + pd.Timedelta(days=1)  # Start the forecast from the next day

    # Generate the future time DataFrame starting from the day after the last date
    future_time = model.make_future_dataframe(periods=future_periods[time_frame], freq='D')

    # Filter future_time to include only future dates starting from forecast_start_date
    future_only = future_time[future_time['ds'] >= forecast_start_date]
    forecast = model.predict(future_only)

    # Exponentiate the forecast to revert back to the original scale
    forecast['yhat'] = np.expm1(forecast['yhat'])  # Use expm1 to handle the log transformation
    forecast['yhat_lower'] = np.expm1(forecast['yhat_lower'])  # Exponentiate lower bound
    forecast['yhat_upper'] = np.expm1(forecast['yhat_upper'])  # Exponentiate upper bound

    # Create a DataFrame for weekends only
    forecast['day_of_week'] = forecast['ds'].dt.day_name()  # Get the day name from the date
    weekends = forecast[forecast['day_of_week'].isin(['Saturday', 'Sunday'])]  # Filter for weekends

    # Display the forecasted data for the specified period
    forecast_table = forecast[['ds', 'yhat', 'yhat_lower', 'yhat_upper']].head(future_periods[time_frame])
    weekend_forecast_table = weekends[['ds', 'yhat', 'yhat_lower', 'yhat_upper']]  # Weekend forecast

    # Create a Plotly graph
    fig = go.Figure()
    fig.add_trace(go.Scatter(
        x=forecast['ds'], y=forecast['yhat'],
        mode='lines+markers',
        name='Forecasted Sales',
        line=dict(color='orange'),
        marker=dict(size=6),
        hovertemplate='Date: %{x}<br>Forecasted Sales: %{y}<extra></extra>'
    ))

    # Add lines for yhat_lower and yhat_upper
    fig.add_trace(go.Scatter(
        x=forecast['ds'], y=forecast['yhat_lower'],
        mode='lines',
        name='Lower Bound',
        line=dict(color='red', dash='dash')
    ))

    fig.add_trace(go.Scatter(
        x=forecast['ds'], y=forecast['yhat_upper'],
        mode='lines',
        name='Upper Bound',
        line=dict(color='green', dash='dash')
    ))

    fig.update_layout(
        title='Sales Forecast using Prophet',
        xaxis_title='Date',
        yaxis_title='Sales Price',
        xaxis=dict(tickformat="%Y-%m-%d"),
        yaxis=dict(autorange=True)
    )

    return forecast_table, weekend_forecast_table, fig  # Return the forecast table, weekend forecast, and plot

# Gradio interface
def run_gradio():
    # Create the Gradio Interface
    time_options = ['Next Day', '7 days', '10 days', '15 days', '1 month']
    gr.Interface(
        fn=predict_sales,  # Function to be called
        inputs=gr.components.Dropdown(time_options, label="Select Forecast Time Range"),  # User input
        outputs=[
            gr.components.Dataframe(label="Forecasted Sales Table"),  # Forecasted data in tabular form
            gr.components.Dataframe(label="Weekend Forecasted Sales Table"),  # Weekend forecast data
            gr.components.Plot(label="Sales Forecast Plot")  # Plotly graph output
        ],
        title="Sales Forecasting with Prophet",
        description="Select a time range for the forecast and click on the button to train the model and see the results."
    ).launch(debug=True)

# Run the Gradio interface
if __name__ == '__main__':
    run_gradio()