muflhi001 commited on
Commit
3328dd3
·
verified ·
1 Parent(s): 827a753

You are an inventory management expert. Design a web dashboard that: 1. Connects to a parts database (SQL schema). 2. Imports monthly sales history. 3. Uses ARIMA/LSTM to forecast next 3–6 months demand. 4. Sends email/SMS alerts when projected stock < threshold. Provide DB schema, Python scripts for forecasting, and frontend wireframes. - Initial Deployment

Browse files
Files changed (2) hide show
  1. README.md +6 -4
  2. index.html +838 -19
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: Stockforecasting
3
- emoji: 💻
4
  colorFrom: blue
5
- colorTo: red
6
  sdk: static
7
  pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
+ title: stockforecasting
3
+ emoji: 🐳
4
  colorFrom: blue
5
+ colorTo: yellow
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite
10
  ---
11
 
12
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
index.html CHANGED
@@ -1,19 +1,838 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Inventory Forecast Dashboard</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
9
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
10
+ <style>
11
+ .sidebar {
12
+ transition: all 0.3s;
13
+ }
14
+ .dashboard-content {
15
+ transition: all 0.3s;
16
+ }
17
+ .card-hover:hover {
18
+ transform: translateY(-5px);
19
+ box-shadow: 0 10px 20px rgba(0,0,0,0.1);
20
+ }
21
+ .progress-bar {
22
+ height: 6px;
23
+ border-radius: 3px;
24
+ }
25
+ .notification-badge {
26
+ position: absolute;
27
+ top: -5px;
28
+ right: -5px;
29
+ }
30
+ .chart-container {
31
+ position: relative;
32
+ height: 300px;
33
+ }
34
+ @media (max-width: 768px) {
35
+ .sidebar {
36
+ position: absolute;
37
+ z-index: 100;
38
+ left: -100%;
39
+ }
40
+ .sidebar.active {
41
+ left: 0;
42
+ }
43
+ .dashboard-content {
44
+ margin-left: 0 !important;
45
+ }
46
+ }
47
+ </style>
48
+ </head>
49
+ <body class="bg-gray-100 font-sans">
50
+ <div class="flex h-screen overflow-hidden">
51
+ <!-- Sidebar -->
52
+ <div class="sidebar bg-indigo-800 text-white w-64 flex-shrink-0">
53
+ <div class="p-4 flex items-center justify-between border-b border-indigo-700">
54
+ <div class="flex items-center">
55
+ <i class="fas fa-boxes text-2xl mr-3"></i>
56
+ <span class="text-xl font-bold">StockForecast</span>
57
+ </div>
58
+ <button id="sidebarToggle" class="md:hidden text-white">
59
+ <i class="fas fa-times"></i>
60
+ </button>
61
+ </div>
62
+ <nav class="p-4">
63
+ <div class="mb-8">
64
+ <p class="text-indigo-300 uppercase text-xs font-bold mb-3">Main</p>
65
+ <a href="#" class="flex items-center py-2 px-3 bg-indigo-700 rounded-lg mb-2">
66
+ <i class="fas fa-tachometer-alt mr-3"></i>
67
+ <span>Dashboard</span>
68
+ </a>
69
+ <a href="#" class="flex items-center py-2 px-3 hover:bg-indigo-700 rounded-lg mb-2">
70
+ <i class="fas fa-box-open mr-3"></i>
71
+ <span>Inventory</span>
72
+ </a>
73
+ <a href="#" class="flex items-center py-2 px-3 hover:bg-indigo-700 rounded-lg mb-2">
74
+ <i class="fas fa-chart-line mr-3"></i>
75
+ <span>Forecasting</span>
76
+ </a>
77
+ <a href="#" class="flex items-center py-2 px-3 hover:bg-indigo-700 rounded-lg mb-2">
78
+ <i class="fas fa-bell mr-3"></i>
79
+ <span>Alerts</span>
80
+ <span class="notification-badge bg-red-500 text-white text-xs rounded-full h-5 w-5 flex items-center justify-center ml-auto">3</span>
81
+ </a>
82
+ </div>
83
+ <div class="mb-8">
84
+ <p class="text-indigo-300 uppercase text-xs font-bold mb-3">Management</p>
85
+ <a href="#" class="flex items-center py-2 px-3 hover:bg-indigo-700 rounded-lg mb-2">
86
+ <i class="fas fa-users mr-3"></i>
87
+ <span>Suppliers</span>
88
+ </a>
89
+ <a href="#" class="flex items-center py-2 px-3 hover:bg-indigo-700 rounded-lg mb-2">
90
+ <i class="fas fa-file-import mr-3"></i>
91
+ <span>Imports</span>
92
+ </a>
93
+ <a href="#" class="flex items-center py-2 px-3 hover:bg-indigo-700 rounded-lg mb-2">
94
+ <i class="fas fa-cog mr-3"></i>
95
+ <span>Settings</span>
96
+ </a>
97
+ </div>
98
+ <div class="mb-4">
99
+ <p class="text-indigo-300 uppercase text-xs font-bold mb-3">Reports</p>
100
+ <a href="#" class="flex items-center py-2 px-3 hover:bg-indigo-700 rounded-lg mb-2">
101
+ <i class="fas fa-file-alt mr-3"></i>
102
+ <span>Monthly</span>
103
+ </a>
104
+ <a href="#" class="flex items-center py-2 px-3 hover:bg-indigo-700 rounded-lg mb-2">
105
+ <i class="fas fa-chart-pie mr-3"></i>
106
+ <span>Analytics</span>
107
+ </a>
108
+ </div>
109
+ </nav>
110
+ </div>
111
+
112
+ <!-- Main Content -->
113
+ <div class="dashboard-content flex-1 overflow-auto">
114
+ <!-- Top Navigation -->
115
+ <header class="bg-white shadow-sm p-4 flex items-center justify-between">
116
+ <div class="flex items-center">
117
+ <button id="mobileSidebarToggle" class="md:hidden text-gray-600 mr-4">
118
+ <i class="fas fa-bars text-xl"></i>
119
+ </button>
120
+ <h1 class="text-xl font-semibold text-gray-800">Inventory Forecast Dashboard</h1>
121
+ </div>
122
+ <div class="flex items-center">
123
+ <div class="relative mr-4">
124
+ <input type="text" placeholder="Search..." class="pl-10 pr-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500">
125
+ <i class="fas fa-search absolute left-3 top-3 text-gray-400"></i>
126
+ </div>
127
+ <div class="relative">
128
+ <img src="https://randomuser.me/api/portraits/women/44.jpg" alt="User" class="w-10 h-10 rounded-full cursor-pointer">
129
+ <span class="absolute bottom-0 right-0 bg-green-500 rounded-full w-3 h-3 border-2 border-white"></span>
130
+ </div>
131
+ </div>
132
+ </header>
133
+
134
+ <!-- Dashboard Content -->
135
+ <main class="p-6">
136
+ <!-- Stats Cards -->
137
+ <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-6">
138
+ <div class="bg-white rounded-xl shadow-sm p-6 card-hover transition-all duration-300">
139
+ <div class="flex items-center justify-between">
140
+ <div>
141
+ <p class="text-gray-500 text-sm">Total Items</p>
142
+ <h3 class="text-2xl font-bold text-gray-800">1,248</h3>
143
+ <p class="text-green-500 text-sm mt-1"><i class="fas fa-caret-up mr-1"></i> 12% from last month</p>
144
+ </div>
145
+ <div class="bg-indigo-100 p-3 rounded-full">
146
+ <i class="fas fa-boxes text-indigo-600 text-xl"></i>
147
+ </div>
148
+ </div>
149
+ </div>
150
+ <div class="bg-white rounded-xl shadow-sm p-6 card-hover transition-all duration-300">
151
+ <div class="flex items-center justify-between">
152
+ <div>
153
+ <p class="text-gray-500 text-sm">Low Stock Items</p>
154
+ <h3 class="text-2xl font-bold text-gray-800">47</h3>
155
+ <p class="text-red-500 text-sm mt-1"><i class="fas fa-caret-up mr-1"></i> 5% from last month</p>
156
+ </div>
157
+ <div class="bg-red-100 p-3 rounded-full">
158
+ <i class="fas fa-exclamation-triangle text-red-600 text-xl"></i>
159
+ </div>
160
+ </div>
161
+ </div>
162
+ <div class="bg-white rounded-xl shadow-sm p-6 card-hover transition-all duration-300">
163
+ <div class="flex items-center justify-between">
164
+ <div>
165
+ <p class="text-gray-500 text-sm">Forecast Accuracy</p>
166
+ <h3 class="text-2xl font-bold text-gray-800">87%</h3>
167
+ <p class="text-green-500 text-sm mt-1"><i class="fas fa-caret-up mr-1"></i> 2% improvement</p>
168
+ </div>
169
+ <div class="bg-green-100 p-3 rounded-full">
170
+ <i class="fas fa-chart-line text-green-600 text-xl"></i>
171
+ </div>
172
+ </div>
173
+ </div>
174
+ <div class="bg-white rounded-xl shadow-sm p-6 card-hover transition-all duration-300">
175
+ <div class="flex items-center justify-between">
176
+ <div>
177
+ <p class="text-gray-500 text-sm">Alerts This Month</p>
178
+ <h3 class="text-2xl font-bold text-gray-800">23</h3>
179
+ <p class="text-yellow-500 text-sm mt-1"><i class="fas fa-caret-down mr-1"></i> 3% from last month</p>
180
+ </div>
181
+ <div class="bg-yellow-100 p-3 rounded-full">
182
+ <i class="fas fa-bell text-yellow-600 text-xl"></i>
183
+ </div>
184
+ </div>
185
+ </div>
186
+ </div>
187
+
188
+ <!-- Charts Row -->
189
+ <div class="grid grid-cols-1 lg:grid-cols-2 gap-6 mb-6">
190
+ <!-- Inventory Forecast Chart -->
191
+ <div class="bg-white rounded-xl shadow-sm p-6">
192
+ <div class="flex items-center justify-between mb-4">
193
+ <h2 class="text-lg font-semibold text-gray-800">6-Month Demand Forecast</h2>
194
+ <div class="flex">
195
+ <button class="px-3 py-1 bg-indigo-100 text-indigo-700 rounded-l-lg text-sm">ARIMA</button>
196
+ <button class="px-3 py-1 bg-gray-100 text-gray-700 rounded-r-lg text-sm">LSTM</button>
197
+ </div>
198
+ </div>
199
+ <div class="chart-container">
200
+ <canvas id="forecastChart"></canvas>
201
+ </div>
202
+ </div>
203
+
204
+ <!-- Stock Status Chart -->
205
+ <div class="bg-white rounded-xl shadow-sm p-6">
206
+ <div class="flex items-center justify-between mb-4">
207
+ <h2 class="text-lg font-semibold text-gray-800">Stock Status by Category</h2>
208
+ <select class="border rounded-lg px-3 py-1 text-sm focus:outline-none focus:ring-2 focus:ring-indigo-500">
209
+ <option>This Month</option>
210
+ <option>Last Month</option>
211
+ <option>Last Quarter</option>
212
+ </select>
213
+ </div>
214
+ <div class="chart-container">
215
+ <canvas id="stockChart"></canvas>
216
+ </div>
217
+ </div>
218
+ </div>
219
+
220
+ <!-- Low Stock Items and Recent Alerts -->
221
+ <div class="grid grid-cols-1 lg:grid-cols-2 gap-6 mb-6">
222
+ <!-- Low Stock Items -->
223
+ <div class="bg-white rounded-xl shadow-sm p-6">
224
+ <div class="flex items-center justify-between mb-4">
225
+ <h2 class="text-lg font-semibold text-gray-800">Critical Stock Items</h2>
226
+ <button class="text-indigo-600 text-sm font-medium">View All</button>
227
+ </div>
228
+ <div class="overflow-x-auto">
229
+ <table class="min-w-full divide-y divide-gray-200">
230
+ <thead>
231
+ <tr>
232
+ <th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Item</th>
233
+ <th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Current</th>
234
+ <th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Threshold</th>
235
+ <th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Status</th>
236
+ </tr>
237
+ </thead>
238
+ <tbody class="bg-white divide-y divide-gray-200">
239
+ <tr>
240
+ <td class="px-4 py-3 whitespace-nowrap">
241
+ <div class="flex items-center">
242
+ <div class="flex-shrink-0 h-10 w-10 bg-indigo-100 rounded-full flex items-center justify-center">
243
+ <i class="fas fa-microchip text-indigo-600"></i>
244
+ </div>
245
+ <div class="ml-4">
246
+ <div class="text-sm font-medium text-gray-900">IC-555 Timer</div>
247
+ <div class="text-sm text-gray-500">Electronics</div>
248
+ </div>
249
+ </div>
250
+ </td>
251
+ <td class="px-4 py-3 whitespace-nowrap text-sm text-gray-500">12</td>
252
+ <td class="px-4 py-3 whitespace-nowrap text-sm text-gray-500">50</td>
253
+ <td class="px-4 py-3 whitespace-nowrap">
254
+ <span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-red-100 text-red-800">Critical</span>
255
+ </td>
256
+ </tr>
257
+ <tr>
258
+ <td class="px-4 py-3 whitespace-nowrap">
259
+ <div class="flex items-center">
260
+ <div class="flex-shrink-0 h-10 w-10 bg-blue-100 rounded-full flex items-center justify-center">
261
+ <i class="fas fa-bolt text-blue-600"></i>
262
+ </div>
263
+ <div class="ml-4">
264
+ <div class="text-sm font-medium text-gray-900">9V Battery</div>
265
+ <div class="text-sm text-gray-500">Power</div>
266
+ </div>
267
+ </div>
268
+ </td>
269
+ <td class="px-4 py-3 whitespace-nowrap text-sm text-gray-500">23</td>
270
+ <td class="px-4 py-3 whitespace-nowrap text-sm text-gray-500">100</td>
271
+ <td class="px-4 py-3 whitespace-nowrap">
272
+ <span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-yellow-100 text-yellow-800">Low</span>
273
+ </td>
274
+ </tr>
275
+ <tr>
276
+ <td class="px-4 py-3 whitespace-nowrap">
277
+ <div class="flex items-center">
278
+ <div class="flex-shrink-0 h-10 w-10 bg-green-100 rounded-full flex items-center justify-center">
279
+ <i class="fas fa-plug text-green-600"></i>
280
+ </div>
281
+ <div class="ml-4">
282
+ <div class="text-sm font-medium text-gray-900">USB-C Connector</div>
283
+ <div class="text-sm text-gray-500">Connectors</div>
284
+ </div>
285
+ </div>
286
+ </td>
287
+ <td class="px-4 py-3 whitespace-nowrap text-sm text-gray-500">45</td>
288
+ <td class="px-4 py-3 whitespace-nowrap text-sm text-gray-500">150</td>
289
+ <td class="px-4 py-3 whitespace-nowrap">
290
+ <span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-yellow-100 text-yellow-800">Low</span>
291
+ </td>
292
+ </tr>
293
+ </tbody>
294
+ </table>
295
+ </div>
296
+ </div>
297
+
298
+ <!-- Recent Alerts -->
299
+ <div class="bg-white rounded-xl shadow-sm p-6">
300
+ <div class="flex items-center justify-between mb-4">
301
+ <h2 class="text-lg font-semibold text-gray-800">Recent Alerts</h2>
302
+ <button class="text-indigo-600 text-sm font-medium">View All</button>
303
+ </div>
304
+ <div class="space-y-4">
305
+ <div class="flex items-start p-3 hover:bg-gray-50 rounded-lg">
306
+ <div class="flex-shrink-0 mt-1">
307
+ <div class="h-10 w-10 bg-red-100 rounded-full flex items-center justify-center">
308
+ <i class="fas fa-exclamation-circle text-red-600"></i>
309
+ </div>
310
+ </div>
311
+ <div class="ml-3 flex-1">
312
+ <div class="flex items-center justify-between">
313
+ <h3 class="text-sm font-medium text-gray-900">Stock Alert</h3>
314
+ <time class="text-xs text-gray-500">2h ago</time>
315
+ </div>
316
+ <p class="text-sm text-gray-500">IC-555 Timer stock below threshold (12/50)</p>
317
+ <div class="mt-2 flex space-x-2">
318
+ <button class="text-xs bg-red-100 text-red-700 px-2 py-1 rounded">Order Now</button>
319
+ <button class="text-xs bg-gray-100 text-gray-700 px-2 py-1 rounded">Dismiss</button>
320
+ </div>
321
+ </div>
322
+ </div>
323
+ <div class="flex items-start p-3 hover:bg-gray-50 rounded-lg">
324
+ <div class="flex-shrink-0 mt-1">
325
+ <div class="h-10 w-10 bg-yellow-100 rounded-full flex items-center justify-center">
326
+ <i class="fas fa-clock text-yellow-600"></i>
327
+ </div>
328
+ </div>
329
+ <div class="ml-3 flex-1">
330
+ <div class="flex items-center justify-between">
331
+ <h3 class="text-sm font-medium text-gray-900">Forecast Update</h3>
332
+ <time class="text-xs text-gray-500">5h ago</time>
333
+ </div>
334
+ <p class="text-sm text-gray-500">New forecast suggests 20% increase in resistor demand</p>
335
+ <div class="mt-2 flex space-x-2">
336
+ <button class="text-xs bg-indigo-100 text-indigo-700 px-2 py-1 rounded">Adjust Order</button>
337
+ </div>
338
+ </div>
339
+ </div>
340
+ <div class="flex items-start p-3 hover:bg-gray-50 rounded-lg">
341
+ <div class="flex-shrink-0 mt-1">
342
+ <div class="h-10 w-10 bg-green-100 rounded-full flex items-center justify-center">
343
+ <i class="fas fa-check-circle text-green-600"></i>
344
+ </div>
345
+ </div>
346
+ <div class="ml-3 flex-1">
347
+ <div class="flex items-center justify-between">
348
+ <h3 class="text-sm font-medium text-gray-900">Order Confirmed</h3>
349
+ <time class="text-xs text-gray-500">1d ago</time>
350
+ </div>
351
+ <p class="text-sm text-gray-500">Order #45678 for capacitors has been shipped</p>
352
+ <div class="mt-2 flex space-x-2">
353
+ <button class="text-xs bg-gray-100 text-gray-700 px-2 py-1 rounded">Track</button>
354
+ </div>
355
+ </div>
356
+ </div>
357
+ </div>
358
+ </div>
359
+ </div>
360
+
361
+ <!-- Quick Actions -->
362
+ <div class="bg-white rounded-xl shadow-sm p-6 mb-6">
363
+ <h2 class="text-lg font-semibold text-gray-800 mb-4">Quick Actions</h2>
364
+ <div class="grid grid-cols-2 md:grid-cols-4 gap-4">
365
+ <button class="flex flex-col items-center justify-center p-4 border rounded-lg hover:bg-indigo-50 hover:border-indigo-200 transition-all">
366
+ <div class="bg-indigo-100 p-3 rounded-full mb-2">
367
+ <i class="fas fa-file-import text-indigo-600 text-xl"></i>
368
+ </div>
369
+ <span class="text-sm font-medium">Import Data</span>
370
+ </button>
371
+ <button class="flex flex-col items-center justify-center p-4 border rounded-lg hover:bg-green-50 hover:border-green-200 transition-all">
372
+ <div class="bg-green-100 p-3 rounded-full mb-2">
373
+ <i class="fas fa-plus-circle text-green-600 text-xl"></i>
374
+ </div>
375
+ <span class="text-sm font-medium">New Order</span>
376
+ </button>
377
+ <button class="flex flex-col items-center justify-center p-4 border rounded-lg hover:bg-blue-50 hover:border-blue-200 transition-all">
378
+ <div class="bg-blue-100 p-3 rounded-full mb-2">
379
+ <i class="fas fa-chart-bar text-blue-600 text-xl"></i>
380
+ </div>
381
+ <span class="text-sm font-medium">Run Forecast</span>
382
+ </button>
383
+ <button class="flex flex-col items-center justify-center p-4 border rounded-lg hover:bg-purple-50 hover:border-purple-200 transition-all">
384
+ <div class="bg-purple-100 p-3 rounded-full mb-2">
385
+ <i class="fas fa-envelope text-purple-600 text-xl"></i>
386
+ </div>
387
+ <span class="text-sm font-medium">Send Alerts</span>
388
+ </button>
389
+ </div>
390
+ </div>
391
+ </main>
392
+ </div>
393
+ </div>
394
+
395
+ <script>
396
+ // Toggle sidebar on mobile
397
+ document.getElementById('mobileSidebarToggle').addEventListener('click', function() {
398
+ document.querySelector('.sidebar').classList.toggle('active');
399
+ });
400
+
401
+ document.getElementById('sidebarToggle').addEventListener('click', function() {
402
+ document.querySelector('.sidebar').classList.toggle('active');
403
+ });
404
+
405
+ // Initialize charts
406
+ document.addEventListener('DOMContentLoaded', function() {
407
+ // Forecast Chart
408
+ const forecastCtx = document.getElementById('forecastChart').getContext('2d');
409
+ const forecastChart = new Chart(forecastCtx, {
410
+ type: 'line',
411
+ data: {
412
+ labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
413
+ datasets: [
414
+ {
415
+ label: 'Actual Sales',
416
+ data: [120, 190, 170, 220, 250, 210, 240, 280, 300, 320, 350, 380],
417
+ borderColor: '#4F46E5',
418
+ backgroundColor: 'rgba(79, 70, 229, 0.1)',
419
+ borderWidth: 2,
420
+ fill: true,
421
+ tension: 0.4
422
+ },
423
+ {
424
+ label: 'Forecast (ARIMA)',
425
+ data: [null, null, null, null, null, null, null, null, 320, 340, 370, 400],
426
+ borderColor: '#10B981',
427
+ backgroundColor: 'rgba(16, 185, 129, 0.1)',
428
+ borderWidth: 2,
429
+ borderDash: [5, 5],
430
+ fill: false,
431
+ tension: 0.4
432
+ }
433
+ ]
434
+ },
435
+ options: {
436
+ responsive: true,
437
+ maintainAspectRatio: false,
438
+ plugins: {
439
+ legend: {
440
+ position: 'top',
441
+ },
442
+ tooltip: {
443
+ mode: 'index',
444
+ intersect: false,
445
+ }
446
+ },
447
+ scales: {
448
+ y: {
449
+ beginAtZero: true,
450
+ grid: {
451
+ drawBorder: false
452
+ }
453
+ },
454
+ x: {
455
+ grid: {
456
+ display: false
457
+ }
458
+ }
459
+ }
460
+ }
461
+ });
462
+
463
+ // Stock Chart
464
+ const stockCtx = document.getElementById('stockChart').getContext('2d');
465
+ const stockChart = new Chart(stockCtx, {
466
+ type: 'bar',
467
+ data: {
468
+ labels: ['Electronics', 'Power', 'Connectors', 'Mechanical', 'Tools'],
469
+ datasets: [
470
+ {
471
+ label: 'Current Stock',
472
+ data: [120, 190, 170, 220, 250],
473
+ backgroundColor: '#4F46E5',
474
+ borderRadius: 4
475
+ },
476
+ {
477
+ label: 'Threshold',
478
+ data: [150, 200, 180, 240, 270],
479
+ backgroundColor: '#E5E7EB',
480
+ borderRadius: 4
481
+ }
482
+ ]
483
+ },
484
+ options: {
485
+ responsive: true,
486
+ maintainAspectRatio: false,
487
+ plugins: {
488
+ legend: {
489
+ position: 'top',
490
+ },
491
+ tooltip: {
492
+ mode: 'index',
493
+ intersect: false,
494
+ }
495
+ },
496
+ scales: {
497
+ y: {
498
+ beginAtZero: true,
499
+ grid: {
500
+ drawBorder: false
501
+ }
502
+ },
503
+ x: {
504
+ grid: {
505
+ display: false
506
+ }
507
+ }
508
+ }
509
+ }
510
+ });
511
+ });
512
+ </script>
513
+
514
+ <!-- Database Schema and Python Scripts (hidden by default) -->
515
+ <div style="display: none;">
516
+ <!-- Database Schema -->
517
+ <pre>
518
+ /*
519
+ Inventory Management Database Schema
520
+ */
521
+
522
+ CREATE TABLE parts (
523
+ part_id INT PRIMARY KEY AUTO_INCREMENT,
524
+ sku VARCHAR(50) UNIQUE NOT NULL,
525
+ name VARCHAR(100) NOT NULL,
526
+ description TEXT,
527
+ category_id INT NOT NULL,
528
+ supplier_id INT NOT NULL,
529
+ unit_cost DECIMAL(10,2) NOT NULL,
530
+ unit_price DECIMAL(10,2) NOT NULL,
531
+ min_stock_level INT NOT NULL,
532
+ max_stock_level INT NOT NULL,
533
+ lead_time_days INT NOT NULL,
534
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
535
+ updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
536
+ FOREIGN KEY (category_id) REFERENCES categories(category_id),
537
+ FOREIGN KEY (supplier_id) REFERENCES suppliers(supplier_id)
538
+ );
539
+
540
+ CREATE TABLE inventory (
541
+ inventory_id INT PRIMARY KEY AUTO_INCREMENT,
542
+ part_id INT NOT NULL,
543
+ quantity_on_hand INT NOT NULL,
544
+ quantity_allocated INT DEFAULT 0,
545
+ last_counted_date DATE,
546
+ location VARCHAR(50),
547
+ FOREIGN KEY (part_id) REFERENCES parts(part_id)
548
+ );
549
+
550
+ CREATE TABLE sales_history (
551
+ sale_id INT PRIMARY KEY AUTO_INCREMENT,
552
+ part_id INT NOT NULL,
553
+ sale_date DATE NOT NULL,
554
+ quantity INT NOT NULL,
555
+ unit_price DECIMAL(10,2) NOT NULL,
556
+ customer_id INT,
557
+ FOREIGN KEY (part_id) REFERENCES parts(part_id),
558
+ FOREIGN KEY (customer_id) REFERENCES customers(customer_id)
559
+ );
560
+
561
+ CREATE TABLE categories (
562
+ category_id INT PRIMARY KEY AUTO_INCREMENT,
563
+ name VARCHAR(50) NOT NULL,
564
+ description TEXT
565
+ );
566
+
567
+ CREATE TABLE suppliers (
568
+ supplier_id INT PRIMARY KEY AUTO_INCREMENT,
569
+ name VARCHAR(100) NOT NULL,
570
+ contact_person VARCHAR(100),
571
+ email VARCHAR(100),
572
+ phone VARCHAR(20),
573
+ lead_time_days INT
574
+ );
575
+
576
+ CREATE TABLE customers (
577
+ customer_id INT PRIMARY KEY AUTO_INCREMENT,
578
+ name VARCHAR(100) NOT NULL,
579
+ email VARCHAR(100),
580
+ phone VARCHAR(20)
581
+ );
582
+
583
+ CREATE TABLE forecast_results (
584
+ forecast_id INT PRIMARY KEY AUTO_INCREMENT,
585
+ part_id INT NOT NULL,
586
+ forecast_date DATE NOT NULL,
587
+ forecast_model VARCHAR(20) NOT NULL, -- 'ARIMA' or 'LSTM'
588
+ forecast_period INT NOT NULL, -- in months
589
+ forecast_quantity DECIMAL(10,2) NOT NULL,
590
+ confidence_interval_lower DECIMAL(10,2),
591
+ confidence_interval_upper DECIMAL(10,2),
592
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
593
+ FOREIGN KEY (part_id) REFERENCES parts(part_id)
594
+ );
595
+
596
+ CREATE TABLE alerts (
597
+ alert_id INT PRIMARY KEY AUTO_INCREMENT,
598
+ part_id INT NOT NULL,
599
+ alert_type VARCHAR(20) NOT NULL, -- 'low_stock', 'forecast', etc.
600
+ alert_message TEXT NOT NULL,
601
+ alert_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
602
+ resolved BOOLEAN DEFAULT FALSE,
603
+ resolved_date TIMESTAMP NULL,
604
+ FOREIGN KEY (part_id) REFERENCES parts(part_id)
605
+ );
606
+
607
+ CREATE TABLE alert_recipients (
608
+ recipient_id INT PRIMARY KEY AUTO_INCREMENT,
609
+ name VARCHAR(100) NOT NULL,
610
+ email VARCHAR(100) NOT NULL,
611
+ phone VARCHAR(20),
612
+ receive_email BOOLEAN DEFAULT TRUE,
613
+ receive_sms BOOLEAN DEFAULT FALSE,
614
+ alert_types VARCHAR(100) -- comma-separated list of alert types to receive
615
+ );
616
+ </pre>
617
+
618
+ <!-- Python Forecasting Script -->
619
+ <pre>
620
+ """
621
+ Inventory Forecasting Script using ARIMA and LSTM
622
+ """
623
+
624
+ import pandas as pd
625
+ import numpy as np
626
+ from statsmodels.tsa.arima.model import ARIMA
627
+ from tensorflow.keras.models import Sequential
628
+ from tensorflow.keras.layers import LSTM, Dense
629
+ from sklearn.preprocessing import MinMaxScaler
630
+ from sklearn.metrics import mean_absolute_error
631
+ import sqlalchemy
632
+ import smtplib
633
+ from email.mime.text import MIMEText
634
+ import warnings
635
+ warnings.filterwarnings('ignore')
636
+
637
+ # Database connection
638
+ def get_db_connection():
639
+ engine = sqlalchemy.create_engine('mysql+pymysql://user:password@localhost/inventory_db')
640
+ return engine.connect()
641
+
642
+ # Fetch sales data for a specific part
643
+ def fetch_sales_data(part_id, months=24):
644
+ conn = get_db_connection()
645
+ query = f"""
646
+ SELECT sale_date, quantity
647
+ FROM sales_history
648
+ WHERE part_id = {part_id}
649
+ AND sale_date >= DATE_SUB(CURRENT_DATE, INTERVAL {months} MONTH)
650
+ ORDER BY sale_date
651
+ """
652
+ df = pd.read_sql(query, conn)
653
+ conn.close()
654
+
655
+ # Resample to monthly data if needed
656
+ df['sale_date'] = pd.to_datetime(df['sale_date'])
657
+ df.set_index('sale_date', inplace=True)
658
+ monthly_df = df.resample('M').sum()
659
+ return monthly_df
660
+
661
+ # ARIMA Forecasting
662
+ def arima_forecast(data, periods=6):
663
+ # Fit ARIMA model
664
+ model = ARIMA(data, order=(1,1,1))
665
+ model_fit = model.fit()
666
+
667
+ # Make forecast
668
+ forecast = model_fit.forecast(steps=periods)
669
+ return forecast
670
+
671
+ # LSTM Forecasting
672
+ def lstm_forecast(data, periods=6, look_back=6):
673
+ # Normalize data
674
+ scaler = MinMaxScaler(feature_range=(0, 1))
675
+ scaled_data = scaler.fit_transform(data.values.reshape(-1,1))
676
+
677
+ # Prepare data for LSTM
678
+ def create_dataset(dataset, look_back=1):
679
+ X, Y = [], []
680
+ for i in range(len(dataset)-look_back-1):
681
+ a = dataset[i:(i+look_back), 0]
682
+ X.append(a)
683
+ Y.append(dataset[i + look_back, 0])
684
+ return np.array(X), np.array(Y)
685
+
686
+ X, Y = create_dataset(scaled_data, look_back)
687
+ X = np.reshape(X, (X.shape[0], X.shape[1], 1))
688
+
689
+ # Build LSTM model
690
+ model = Sequential()
691
+ model.add(LSTM(50, return_sequences=True, input_shape=(look_back, 1)))
692
+ model.add(LSTM(50))
693
+ model.add(Dense(1))
694
+ model.compile(loss='mean_squared_error', optimizer='adam')
695
+ model.fit(X, Y, epochs=20, batch_size=1, verbose=0)
696
+
697
+ # Make forecast
698
+ forecast_input = scaled_data[-look_back:].reshape(1, look_back, 1)
699
+ forecast = []
700
+ for _ in range(periods):
701
+ next_step = model.predict(forecast_input)
702
+ forecast.append(next_step[0,0])
703
+ forecast_input = np.append(forecast_input[:,1:,:], [[next_step]], axis=1)
704
+
705
+ forecast = scaler.inverse_transform(np.array(forecast).reshape(-1,1))
706
+ return forecast.flatten()
707
+
708
+ # Save forecast to database
709
+ def save_forecast(part_id, forecast, model_name, forecast_date):
710
+ conn = get_db_connection()
711
+ for i, value in enumerate(forecast):
712
+ query = f"""
713
+ INSERT INTO forecast_results
714
+ (part_id, forecast_date, forecast_model, forecast_period, forecast_quantity)
715
+ VALUES ({part_id}, DATE_ADD('{forecast_date}', INTERVAL {i+1} MONTH),
716
+ '{model_name}', {i+1}, {value})
717
+ """
718
+ conn.execute(query)
719
+ conn.close()
720
+
721
+ # Check stock levels and send alerts
722
+ def check_stock_and_alert(part_id, forecast):
723
+ conn = get_db_connection()
724
+
725
+ # Get current inventory and threshold
726
+ query = f"""
727
+ SELECT p.part_id, p.name, p.min_stock_level, i.quantity_on_hand
728
+ FROM parts p
729
+ JOIN inventory i ON p.part_id = i.part_id
730
+ WHERE p.part_id = {part_id}
731
+ """
732
+ inventory = pd.read_sql(query, conn).iloc[0]
733
+
734
+ # Get forecast for next month
735
+ monthly_forecast = forecast[0]
736
+
737
+ # Check if projected stock will be below threshold
738
+ projected_stock = inventory['quantity_on_hand'] - monthly_forecast
739
+ if projected_stock < inventory['min_stock_level']:
740
+ # Create alert
741
+ alert_msg = f"Projected stock for {inventory['name']} will be below threshold ({projected_stock}/{inventory['min_stock_level']})"
742
+ query = f"""
743
+ INSERT INTO alerts (part_id, alert_type, alert_message)
744
+ VALUES ({part_id}, 'low_stock', '{alert_msg}')
745
+ """
746
+ conn.execute(query)
747
+
748
+ # Send email/SMS to recipients
749
+ send_alerts(part_id, alert_msg)
750
+
751
+ conn.close()
752
+
753
+ # Send email/SMS alerts
754
+ def send_alerts(part_id, message):
755
+ conn = get_db_connection()
756
+
757
+ # Get recipients who should receive this type of alert
758
+ query = f"""
759
+ SELECT * FROM alert_recipients
760
+ WHERE alert_types LIKE '%low_stock%'
761
+ """
762
+ recipients = pd.read_sql(query, conn)
763
+
764
+ # Send alerts
765
+ for _, recipient in recipients.iterrows():
766
+ if recipient['receive_email']:
767
+ send_email(recipient['email'], "Inventory Alert", message)
768
+ if recipient['receive_sms']:
769
+ send_sms(recipient['phone'], message)
770
+
771
+ conn.close()
772
+
773
+ def send_email(to_email, subject, body):
774
+ # Configure your email settings
775
+ smtp_server = "smtp.example.com"
776
+ smtp_port = 587
777
+ smtp_user = "[email protected]"
778
+ smtp_password = "password"
779
+
780
+ msg = MIMEText(body)
781
+ msg['Subject'] = subject
782
+ msg['From'] = smtp_user
783
+ msg['To'] = to_email
784
+
785
+ try:
786
+ server = smtplib.SMTP(smtp_server, smtp_port)
787
+ server.starttls()
788
+ server.login(smtp_user, smtp_password)
789
+ server.sendmail(smtp_user, [to_email], msg.as_string())
790
+ server.quit()
791
+ except Exception as e:
792
+ print(f"Failed to send email: {e}")
793
+
794
+ def send_sms(phone_number, message):
795
+ # Implement your SMS gateway integration here
796
+ pass
797
+
798
+ # Main forecasting workflow
799
+ def run_forecast_for_part(part_id):
800
+ # Get historical sales data
801
+ sales_data = fetch_sales_data(part_id)
802
+
803
+ if len(sales_data) < 6:
804
+ print(f"Not enough data for part {part_id}")
805
+ return
806
+
807
+ # Run ARIMA forecast
808
+ arima_result = arima_forecast(sales_data['quantity'])
809
+
810
+ # Run LSTM forecast
811
+ lstm_result = lstm_forecast(sales_data['quantity'])
812
+
813
+ # Save forecasts
814
+ today = pd.to_datetime('today').strftime('%Y-%m-%d')
815
+ save_forecast(part_id, arima_result, 'ARIMA', today)
816
+ save_forecast(part_id, lstm_result, 'LSTM', today)
817
+
818
+ # Check stock levels and send alerts
819
+ check_stock_and_alert(part_id, arima_result)
820
+
821
+ # Example usage
822
+ if __name__ == "__main__":
823
+ # Get list of parts that need forecasting (e.g., all active parts)
824
+ conn = get_db_connection()
825
+ parts = pd.read_sql("SELECT part_id FROM parts WHERE active = TRUE", conn)
826
+ conn.close()
827
+
828
+ # Run forecast for each part
829
+ for part_id in parts['part_id']:
830
+ try:
831
+ run_forecast_for_part(part_id)
832
+ print(f"Forecast completed for part {part_id}")
833
+ except Exception as e:
834
+ print(f"Error forecasting for part {part_id}: {e}")
835
+ </pre>
836
+ </div>
837
+ <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=muflhi001/stockforecasting" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
838
+ </html>