Saurabh502 commited on
Commit
078556c
·
verified ·
1 Parent(s): 15cbf41

Upload 6 files

Browse files
Files changed (6) hide show
  1. app.py +412 -0
  2. chatbot.py +120 -0
  3. data_manager.py +335 -0
  4. gemini_client.py +57 -0
  5. generate_data.py +145 -0
  6. requirements.txt +3 -0
app.py ADDED
@@ -0,0 +1,412 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import data_manager
3
+ import gemini_client
4
+ import re
5
+ import os
6
+ import pandas as pd # For displaying data in a table
7
+ import datetime
8
+
9
+ # --- Functions copied/adapted from chatbot.py ---
10
+
11
+ def extract_order_id(query):
12
+ """Attempts to extract an order ID (assumed to be a number) from the query."""
13
+ match = re.search(r'\b\d+\b', query)
14
+ if match:
15
+ return int(match.group(0))
16
+ return None
17
+
18
+ def format_prompt(query, order_details=None, order_items=None, recent_orders=None):
19
+ """Formats the prompt for the Gemini API, including context."""
20
+ prompt = f"You are an e-commerce customer support assistant. Answer the user's query based *only* on the provided information. If the information is insufficient, say so.\n\nUser Query: \"{query}\"\n\n"
21
+
22
+ if order_details:
23
+ prompt += "--- Order Information ---\n"
24
+ prompt += f"Order ID: {order_details.get('order_id')}\n"
25
+ prompt += f"Customer: {order_details.get('user_name')} ({order_details.get('email')})\n"
26
+ prompt += f"Date: {order_details.get('order_date')}\n"
27
+ prompt += f"Status: {order_details.get('status')}\n"
28
+ prompt += f"Total: ${order_details.get('total_amount'):.2f}\n"
29
+
30
+ if order_items:
31
+ prompt += "\n--- Items in Order ---\n"
32
+ for item in order_items:
33
+ prompt += f"- {item.get('product_name')} (Qty: {item.get('quantity')}, Price/Unit: ${item.get('price_per_unit'):.2f})\n"
34
+
35
+ if recent_orders:
36
+ prompt += "\n--- Recent Orders ---\n"
37
+ for order in recent_orders:
38
+ prompt += f"- Order ID: {order.get('order_id')}, Date: {order.get('order_date')}, Status: {order.get('status')}, Total: ${order.get('total_amount'):.2f}\n"
39
+
40
+ prompt += "\n---\nAssistant Response:"
41
+ return prompt
42
+
43
+ # --- Data Management Functions ---
44
+
45
+ def get_product_dataframe():
46
+ """Fetches all products and returns them as a Pandas DataFrame."""
47
+ products = data_manager.get_all_products()
48
+ if products:
49
+ return pd.DataFrame(products)
50
+ else:
51
+ return pd.DataFrame({"message": ["No products found"]}) # Empty DataFrame with a message
52
+
53
+ def get_user_dataframe():
54
+ """Fetches all users and returns them as a Pandas DataFrame."""
55
+ users = data_manager.get_all_users()
56
+ if users:
57
+ return pd.DataFrame(users)
58
+ else:
59
+ return pd.DataFrame({"message": ["No users found"]})
60
+
61
+ def get_order_dataframe():
62
+ """Fetches all orders and returns them as a Pandas DataFrame."""
63
+ orders = data_manager.get_all_orders()
64
+ if orders:
65
+ return pd.DataFrame(orders)
66
+ else:
67
+ return pd.DataFrame({"message": ["No orders found"]})
68
+
69
+ def get_order_item_dataframe():
70
+ """Fetches all order items and returns them as a Pandas DataFrame."""
71
+ order_items = data_manager.get_all_order_details()
72
+ if order_items:
73
+ return pd.DataFrame(order_items)
74
+ else:
75
+ return pd.DataFrame({"message": ["No order items found"]})
76
+
77
+ def add_product_interface(name, description, price, stock):
78
+ """Adds a product using the data_manager function and returns a message."""
79
+ try:
80
+ price = float(price)
81
+ stock = int(stock)
82
+ if not all([name, description, price >= 0, stock >= 0]):
83
+ return "Error: Please fill all fields correctly. Price and stock must be non-negative.", get_product_dataframe()
84
+
85
+ product_id = data_manager.add_product(name, description, price, stock)
86
+ if product_id:
87
+ return "Product added successfully. Refreshing data...", get_product_dataframe()
88
+ else:
89
+ return "Error: Could not add product.", get_product_dataframe()
90
+ except ValueError:
91
+ return "Error: Invalid price or stock value.", get_product_dataframe()
92
+
93
+ def remove_product_interface(product_id):
94
+ """Removes a product using the data_manager function and returns a message."""
95
+ try:
96
+ product_id = int(product_id)
97
+ if product_id <= 0:
98
+ return "Error: Product ID must be a positive integer.", get_product_dataframe()
99
+ removed = data_manager.remove_product(product_id)
100
+ if removed:
101
+ return f"Product with ID {product_id} removed successfully.", get_product_dataframe()
102
+ else:
103
+ return f"Error: Could not remove product with ID {product_id} (product not found or in use).", get_product_dataframe()
104
+ except ValueError:
105
+ return "Error: Invalid product ID.", get_product_dataframe()
106
+
107
+ def add_user_interface(name, email, address):
108
+ """Adds a user using the data_manager function."""
109
+ user_id = data_manager.add_user(name, email, address)
110
+ if user_id:
111
+ return f"User added successfully with ID: {user_id}", get_user_dataframe()
112
+ else:
113
+ return "Error: Could not add user.", get_user_dataframe()
114
+
115
+ def add_order_interface(user_id, order_date, status, total_amount):
116
+ """Adds an order using the data_manager function."""
117
+ try:
118
+ user_id = int(user_id)
119
+ total_amount = float(total_amount)
120
+ datetime.datetime.strptime(order_date, '%Y-%m-%d') # Validate date format
121
+ if status not in ['Pending', 'Processing', 'Shipped', 'Delivered', 'Cancelled']:
122
+ return "Error: Invalid order status.", get_order_dataframe()
123
+
124
+ order_id = data_manager.add_order(user_id, order_date, status, total_amount)
125
+ if order_id:
126
+ return f"Order added successfully with ID: {order_id}", get_order_dataframe()
127
+ else:
128
+ return "Error: Could not add order.", get_order_dataframe()
129
+ except ValueError:
130
+ return "Error: Invalid user ID or total amount.", get_order_dataframe()
131
+ except ValueError:
132
+ return "Error: Invalid date format. Use YYYY-MM-DD.", get_order_dataframe()
133
+
134
+ def add_order_item_interface(order_id, product_id, quantity, price_per_unit):
135
+ """Adds an order item using the data_manager function."""
136
+ try:
137
+ order_id = int(order_id)
138
+ product_id = int(product_id)
139
+ quantity = int(quantity)
140
+ price_per_unit = float(price_per_unit)
141
+
142
+ order_item_id = data_manager.add_order_item(order_id, product_id, quantity, price_per_unit)
143
+ if order_item_id:
144
+ return f"Order item added successfully with ID: {order_item_id}", get_order_item_dataframe()
145
+ else:
146
+ return "Error: Could not add order item.", get_order_item_dataframe()
147
+ except ValueError:
148
+ return "Error: Invalid order ID, product ID, quantity, or price per unit.", get_order_item_dataframe()
149
+
150
+ def remove_user_interface(user_id):
151
+ """Removes a user using the data_manager function and returns a message."""
152
+ try:
153
+ user_id = int(user_id)
154
+ if user_id <= 0:
155
+ return "Error: User ID must be a positive integer.", get_user_dataframe()
156
+ removed = data_manager.remove_user(user_id)
157
+ if removed:
158
+ return f"User with ID {user_id} removed successfully.", get_user_dataframe()
159
+ else:
160
+ return f"Error: Could not remove user with ID {user_id} (user not found or in use).", get_user_dataframe()
161
+ except ValueError:
162
+ return "Error: Invalid user ID.", get_user_dataframe()
163
+
164
+ def remove_order_interface(order_id):
165
+ """Removes an order using the data_manager function and returns a message."""
166
+ try:
167
+ order_id = int(order_id)
168
+ if order_id <= 0:
169
+ return "Error: Order ID must be a positive integer.", get_order_dataframe()
170
+ removed = data_manager.remove_order(order_id)
171
+ if removed:
172
+ return f"Order with ID {order_id} removed successfully.", get_order_dataframe()
173
+ else:
174
+ return f"Error: Could not remove order with ID {order_id} (order not found or in use).", get_order_dataframe()
175
+ except ValueError:
176
+ return "Error: Invalid order ID.", get_order_dataframe()
177
+
178
+ def remove_order_item_interface(order_id, product_id):
179
+ """Removes an order item using the data_manager function and returns a message."""
180
+ try:
181
+ order_id = int(order_id)
182
+ product_id = int(product_id)
183
+ if order_id <= 0 or product_id <= 0:
184
+ return "Error: IDs must be positive integers.", get_order_item_dataframe()
185
+
186
+ conn = data_manager.get_db_connection()
187
+ cursor = conn.cursor()
188
+ try:
189
+ cursor.execute("DELETE FROM order_items WHERE order_id = ? AND product_id = ?",
190
+ (order_id, product_id))
191
+ conn.commit()
192
+ removed = cursor.rowcount > 0
193
+ conn.close()
194
+
195
+ if removed:
196
+ return f"Order item (Order: {order_id}, Product: {product_id}) removed successfully.", get_order_item_dataframe()
197
+ else:
198
+ return f"Error: Could not remove order item (Order: {order_id}, Product: {product_id}) - not found.", get_order_item_dataframe()
199
+ except sqlite3.Error as e:
200
+ conn.rollback()
201
+ conn.close()
202
+ return f"Database error: {e}", get_order_item_dataframe()
203
+ except ValueError:
204
+ return "Error: Invalid order ID or product ID.", get_order_item_dataframe()
205
+
206
+ # --- Chatbot Functions ---
207
+
208
+ def get_chatbot_response(user_email, query):
209
+ """Handles the chatbot logic for the Gradio interface."""
210
+ if not user_email:
211
+ return "Error: Please enter your email address."
212
+
213
+ user_info = data_manager.get_user_by_email(user_email)
214
+ if not user_info:
215
+ return f"Error: User with email {user_email} not found."
216
+
217
+ user_id = user_info['user_id']
218
+ order_id = extract_order_id(query)
219
+ order_details = None
220
+ order_items = None
221
+ recent_orders = None
222
+ response_message = ""
223
+
224
+ try:
225
+ # Determine context based on query and extracted info
226
+ if order_id:
227
+ order_details = data_manager.get_order_details(order_id)
228
+ if order_details:
229
+ # Security check: Ensure the order belongs to the logged-in user
230
+ if order_details['email'] != user_email:
231
+ response_message = f"Order {order_id} does not belong to user {user_email}."
232
+ order_details = None # Clear details if not authorized
233
+ else:
234
+ # Fetch items only if order details are valid and authorized
235
+ order_items = data_manager.get_order_items(order_id)
236
+ else:
237
+ response_message = f"Order ID {order_id} not found."
238
+
239
+ # Check for recent orders query (simple keyword check)
240
+ elif "recent orders" in query.lower() or "my orders" in query.lower():
241
+ recent_orders = data_manager.get_user_recent_orders(user_id)
242
+ if not recent_orders:
243
+ response_message = "You have no recent orders."
244
+
245
+ # Construct and send prompt if we have relevant context
246
+ if order_details or recent_orders:
247
+ prompt = format_prompt(query, order_details, order_items, recent_orders)
248
+ # print("\nAssistant thinking...") # No console print in Gradio func
249
+ response = gemini_client.get_gemini_response(prompt)
250
+ response_message = response
251
+ elif order_id and not order_details and not response_message:
252
+ # Already handled the "not found" or "not authorized" message above
253
+ pass # response_message already set
254
+ elif not response_message: # If no context found and no error message yet
255
+ response_message = "Please specify an order ID (e.g., 'status for order 123') or ask about 'recent orders'."
256
+
257
+ return response_message
258
+
259
+ except FileNotFoundError as e:
260
+ return f"Error: Database not found at {data_manager.DB_PATH}. Please ensure it exists."
261
+ except Exception as e:
262
+ # Log the full error for debugging if needed, but return a user-friendly message
263
+ print(f"An unexpected error occurred: {e}") # Log to console where Gradio runs
264
+ return f"An unexpected error occurred. Please try again later."
265
+
266
+ # --- Database Check ---
267
+ if not os.path.exists(data_manager.DB_PATH):
268
+ print(f"Database not found at {data_manager.DB_PATH}.")
269
+ print("Please run 'python generate_data.py' first to create and populate the database.")
270
+ # Optionally, exit or prevent Gradio launch
271
+ # exit() # Uncomment to stop if DB is missing
272
+
273
+ # --- Gradio Interface ---
274
+ with gr.Blocks(title="E-commerce Management") as iface:
275
+ gr.Markdown("# E-commerce Chatbot and Data Management")
276
+
277
+ with gr.Tab("Chatbot"):
278
+ email_input = gr.Textbox(label="Your Email Address")
279
+ query_input = gr.Textbox(label="Your Query", placeholder="e.g., 'What is the status of order 1?' or 'Show my recent orders'")
280
+ chatbot_output = gr.Textbox(label="Assistant Response")
281
+ chatbot_button = gr.Button("Submit")
282
+
283
+ chatbot_button.click(
284
+ fn=get_chatbot_response,
285
+ inputs=[email_input, query_input],
286
+ outputs=chatbot_output
287
+ )
288
+
289
+ with gr.Tab("Data Management"):
290
+ with gr.Tabs():
291
+ with gr.Tab("Products"):
292
+ gr.Markdown("## Product Data")
293
+ product_table = gr.DataFrame(get_product_dataframe(), interactive=False, label="Current Products")
294
+
295
+ with gr.Accordion("Add New Product", open=False):
296
+ new_name_input = gr.Textbox(label="Product Name")
297
+ new_description_input = gr.Textbox(label="Description")
298
+ new_price_input = gr.Number(label="Price")
299
+ new_stock_input = gr.Number(label="Stock")
300
+ add_product_button = gr.Button("Add Product")
301
+ add_product_output = gr.Textbox()
302
+
303
+ add_product_button.click(
304
+ fn=add_product_interface,
305
+ inputs=[new_name_input, new_description_input, new_price_input, new_stock_input],
306
+ outputs=[add_product_output, product_table]
307
+ )
308
+
309
+ with gr.Accordion("Remove Product", open=False):
310
+ remove_id_input = gr.Number(label="Product ID to Remove")
311
+ remove_product_button = gr.Button("Remove Product")
312
+ remove_product_output = gr.Textbox()
313
+
314
+ remove_product_button.click(
315
+ fn=remove_product_interface,
316
+ inputs=[remove_id_input],
317
+ outputs=[remove_product_output, product_table]
318
+ )
319
+
320
+ with gr.Tab("Users"):
321
+ gr.Markdown("## User Data")
322
+ user_table = gr.DataFrame(get_user_dataframe(), interactive=False, label="Current Users")
323
+
324
+ with gr.Accordion("Add User", open=False):
325
+ new_user_name_input = gr.Textbox(label="User Name")
326
+ new_user_email_input = gr.Textbox(label="Email")
327
+ new_user_address_input = gr.Textbox(label="Address")
328
+ add_user_button = gr.Button("Add User")
329
+ add_user_output = gr.Textbox()
330
+
331
+ add_user_button.click(
332
+ fn=add_user_interface,
333
+ inputs=[new_user_name_input, new_user_email_input, new_user_address_input],
334
+ outputs=[add_user_output, user_table]
335
+ )
336
+
337
+ with gr.Accordion("Remove User", open=False):
338
+ remove_user_id_input = gr.Number(label="User ID to Remove")
339
+ remove_user_button = gr.Button("Remove User")
340
+ remove_user_output = gr.Textbox()
341
+
342
+ remove_user_button.click(
343
+ fn=remove_user_interface,
344
+ inputs=[remove_user_id_input],
345
+ outputs=[remove_user_output, user_table]
346
+ )
347
+
348
+ with gr.Tab("Orders"):
349
+ gr.Markdown("## Order Data")
350
+ order_table = gr.DataFrame(get_order_dataframe(), interactive=False, label="Current Orders")
351
+
352
+ with gr.Accordion("Add Order", open=False):
353
+ new_order_user_id_input = gr.Number(label="User ID")
354
+ new_order_date_input = gr.Textbox(label="Order Date (YYYY-MM-DD)")
355
+ new_order_status_input = gr.Dropdown(label="Status", choices=['Pending', 'Processing', 'Shipped', 'Delivered', 'Cancelled'])
356
+ new_order_total_amount_input = gr.Number(label="Total Amount")
357
+ add_order_button = gr.Button("Add Order")
358
+ add_order_output = gr.Textbox()
359
+
360
+ add_order_button.click(
361
+ fn=add_order_interface,
362
+ inputs=[new_order_user_id_input, new_order_date_input, new_order_status_input, new_order_total_amount_input],
363
+ outputs=[add_order_output, order_table]
364
+ )
365
+
366
+ with gr.Accordion("Remove Order", open=False):
367
+ remove_order_id_input = gr.Number(label="Order ID to Remove")
368
+ remove_order_button = gr.Button("Remove Order")
369
+ remove_order_output = gr.Textbox()
370
+
371
+ remove_order_button.click(
372
+ fn=remove_order_interface,
373
+ inputs=[remove_order_id_input],
374
+ outputs=[remove_order_output, order_table]
375
+ )
376
+
377
+ with gr.Tab("Order Items"):
378
+ gr.Markdown("## Order Item Data")
379
+ order_item_table = gr.DataFrame(get_order_item_dataframe(), interactive=False, label="Current Order Items")
380
+
381
+ with gr.Accordion("Add Order Item", open=False):
382
+ new_order_item_order_id_input = gr.Number(label="Order ID")
383
+ new_order_item_product_id_input = gr.Number(label="Product ID")
384
+ new_order_item_quantity_input = gr.Number(label="Quantity")
385
+ new_order_item_price_per_unit_input = gr.Number(label="Price per Unit")
386
+ add_order_item_button = gr.Button("Add Order Item")
387
+ add_order_item_output = gr.Textbox()
388
+
389
+ add_order_item_button.click(
390
+ fn=add_order_item_interface,
391
+ inputs=[new_order_item_order_id_input, new_order_item_product_id_input, new_order_item_quantity_input, new_order_item_price_per_unit_input],
392
+ outputs=[add_order_item_output, order_item_table]
393
+ )
394
+
395
+ with gr.Accordion("Remove Order Item", open=False):
396
+ remove_order_id_input = gr.Number(label="Order ID")
397
+ remove_product_id_input = gr.Number(label="Product ID")
398
+ remove_order_item_button = gr.Button("Remove Order Item")
399
+ remove_order_item_output = gr.Textbox()
400
+
401
+ remove_order_item_button.click(
402
+ fn=remove_order_item_interface,
403
+ inputs=[remove_order_id_input, remove_product_id_input],
404
+ outputs=[remove_order_item_output, order_item_table]
405
+ )
406
+
407
+ if __name__ == "__main__":
408
+ if os.path.exists(data_manager.DB_PATH):
409
+ print("Launching Gradio interface...")
410
+ iface.launch(share=True)
411
+ else:
412
+ print("Gradio interface not launched because the database is missing.")
chatbot.py ADDED
@@ -0,0 +1,120 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import data_manager
2
+ import gemini_client
3
+ import re
4
+ import os
5
+ def extract_order_id(query):
6
+ """Attempts to extract an order ID (assumed to be a number) from the query."""
7
+ match = re.search(r'\b\d+\b', query)
8
+ if match:
9
+ return int(match.group(0))
10
+ return None
11
+
12
+ def format_prompt(query, order_details=None, order_items=None, recent_orders=None):
13
+ """Formats the prompt for the Gemini API, including context."""
14
+ prompt = f"You are an e-commerce customer support assistant. Answer the user's query based *only* on the provided information. If the information is insufficient, say so.\n\nUser Query: \"{query}\"\n\n"
15
+
16
+ if order_details:
17
+ prompt += "--- Order Information ---\n"
18
+ prompt += f"Order ID: {order_details.get('order_id')}\n"
19
+ prompt += f"Customer: {order_details.get('user_name')} ({order_details.get('email')})\n"
20
+ prompt += f"Date: {order_details.get('order_date')}\n"
21
+ prompt += f"Status: {order_details.get('status')}\n"
22
+ prompt += f"Total: ${order_details.get('total_amount'):.2f}\n"
23
+
24
+ if order_items:
25
+ prompt += "\n--- Items in Order ---\n"
26
+ for item in order_items:
27
+ prompt += f"- {item.get('product_name')} (Qty: {item.get('quantity')}, Price/Unit: ${item.get('price_per_unit'):.2f})\n"
28
+
29
+ if recent_orders:
30
+ prompt += "\n--- Recent Orders ---\n"
31
+ for order in recent_orders:
32
+ prompt += f"- Order ID: {order.get('order_id')}, Date: {order.get('order_date')}, Status: {order.get('status')}, Total: ${order.get('total_amount'):.2f}\n"
33
+
34
+ prompt += "\n---\nAssistant Response:"
35
+ return prompt
36
+
37
+ def main():
38
+ """Main loop for the chatbot interaction."""
39
+ print("Welcome to the E-commerce Chat Assistant!")
40
+ print("You can ask about order status, items, or recent orders.")
41
+ print("Example: 'What is the status of order 1?' or 'Show my recent orders for alice@example.com'")
42
+ print("Type 'quit' to exit.")
43
+
44
+ # Basic way to identify user - could be improved with login simulation
45
+ user_email = input("Please enter your email address to start: ")
46
+ user_info = data_manager.get_user_by_email(user_email)
47
+ if not user_info:
48
+ print(f"User with email {user_email} not found. Exiting.")
49
+ return
50
+ print(f"Welcome, {user_info['name']}!")
51
+ user_id = user_info['user_id']
52
+
53
+
54
+ while True:
55
+ query = input("\nYour query: ")
56
+ if query.lower() == 'quit':
57
+ break
58
+
59
+ order_id = extract_order_id(query)
60
+ order_details = None
61
+ order_items = None
62
+ recent_orders = None
63
+
64
+ try:
65
+ # Determine context based on query and extracted info
66
+ if order_id:
67
+ order_details = data_manager.get_order_details(order_id)
68
+ if order_details:
69
+ # Security check: Ensure the order belongs to the logged-in user
70
+ if order_details['email'] != user_email:
71
+ print(f"Order {order_id} does not belong to user {user_email}.")
72
+ order_details = None # Clear details if not authorized
73
+ else:
74
+ # Fetch items only if order details are valid and authorized
75
+ order_items = data_manager.get_order_items(order_id)
76
+ else:
77
+ print(f"Order ID {order_id} not found.")
78
+
79
+ # Check for recent orders query (simple keyword check)
80
+ elif "recent orders" in query.lower() or "my orders" in query.lower():
81
+ recent_orders = data_manager.get_user_recent_orders(user_id)
82
+ if not recent_orders:
83
+ print("You have no recent orders.")
84
+
85
+
86
+ # Construct and send prompt if we have relevant context
87
+ if order_details or recent_orders:
88
+ prompt = format_prompt(query, order_details, order_items, recent_orders)
89
+ print("\nAssistant thinking...")
90
+ response = gemini_client.get_gemini_response(prompt)
91
+ print(f"\nAssistant: {response}")
92
+ elif order_id and not order_details:
93
+ # Already handled the "not found" or "not authorized" message
94
+ pass
95
+ else:
96
+ # If no specific context found, try sending the query directly (less reliable)
97
+ # Or inform the user context is needed
98
+ # print("Could not determine specific order information. Trying a general query...")
99
+ # prompt = format_prompt(query) # Send without specific context
100
+ # response = gemini_client.get_gemini_response(prompt)
101
+ # print(f"\nAssistant: {response}")
102
+ print("Please specify an order ID or ask about 'recent orders'.")
103
+
104
+
105
+ except FileNotFoundError as e:
106
+ print(f"Error: {e}. Please ensure the database exists.")
107
+ break
108
+ except Exception as e:
109
+ print(f"An unexpected error occurred: {e}")
110
+
111
+ print("Goodbye!")
112
+
113
+ if __name__ == "__main__":
114
+ # Optional: Run data generation if DB doesn't exist?
115
+ # For simplicity, we assume generate_data.py is run manually first.
116
+ if not os.path.exists(data_manager.DB_PATH):
117
+ print(f"Database not found at {data_manager.DB_PATH}.")
118
+ print("Please run 'python generate_data.py' first to create and populate the database.")
119
+ else:
120
+ main()
data_manager.py ADDED
@@ -0,0 +1,335 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import sqlite3
2
+ import os
3
+
4
+ # Define the path for the database
5
+ DB_DIR = "data"
6
+ DB_PATH = os.path.join(DB_DIR, "ecommerce_data.db")
7
+
8
+ def get_db_connection():
9
+ """Establishes a connection to the SQLite database."""
10
+ if not os.path.exists(DB_PATH):
11
+ raise FileNotFoundError(f"Database file not found at {DB_PATH}. Run generate_data.py first.")
12
+ conn = sqlite3.connect(DB_PATH)
13
+ conn.row_factory = sqlite3.Row # Return rows as dictionary-like objects
14
+ return conn
15
+
16
+ def get_order_details(order_id):
17
+ """Fetches details for a specific order."""
18
+ conn = get_db_connection()
19
+ cursor = conn.cursor()
20
+ cursor.execute("""
21
+ SELECT o.order_id, o.order_date, o.status, o.total_amount, u.name as user_name, u.email
22
+ FROM orders o
23
+ JOIN users u ON o.user_id = u.user_id
24
+ WHERE o.order_id = ?
25
+ """, (order_id,))
26
+ order = cursor.fetchone()
27
+ conn.close()
28
+ return dict(order) if order else None
29
+
30
+ def get_order_items(order_id):
31
+ """Fetches all items associated with a specific order."""
32
+ conn = get_db_connection()
33
+ cursor = conn.cursor()
34
+ cursor.execute("""
35
+ SELECT p.name as product_name, oi.quantity, oi.price_per_unit
36
+ FROM order_items oi
37
+ JOIN products p ON oi.product_id = p.product_id
38
+ WHERE oi.order_id = ?
39
+ """, (order_id,))
40
+ items = cursor.fetchall()
41
+ conn.close()
42
+ return [dict(item) for item in items]
43
+
44
+ def get_user_recent_orders(user_id, limit=5):
45
+ """Fetches the most recent orders for a specific user."""
46
+ conn = get_db_connection()
47
+ cursor = conn.cursor()
48
+ cursor.execute("""
49
+ SELECT order_id, order_date, status, total_amount
50
+ FROM orders
51
+ WHERE user_id = ?
52
+ ORDER BY order_date DESC
53
+ LIMIT ?
54
+ """, (user_id, limit))
55
+ orders = cursor.fetchall()
56
+ conn.close()
57
+ return [dict(order) for order in orders]
58
+
59
+ def remove_order_details(order_id):
60
+ """Removes order details from the database for a given order_id."""
61
+ conn = get_db_connection()
62
+ cursor = conn.cursor()
63
+ try:
64
+ cursor.execute("DELETE FROM order_items WHERE order_id = ?", (order_id,))
65
+ conn.commit()
66
+ conn.close()
67
+ return True
68
+ except sqlite3.Error as e:
69
+ conn.rollback()
70
+ conn.close()
71
+ print(f"Database error removing order details: {e}")
72
+ return False
73
+
74
+ def remove_order(order_id):
75
+ """Removes an order from the database."""
76
+ conn = get_db_connection()
77
+ cursor = conn.cursor()
78
+ try:
79
+ cursor.execute("DELETE FROM orders WHERE order_id = ?", (order_id,))
80
+ conn.commit()
81
+ conn.close()
82
+ return True
83
+ except sqlite3.Error as e:
84
+ conn.rollback()
85
+ conn.close()
86
+ print(f"Database error removing order: {e}")
87
+ return False
88
+
89
+ def remove_user(user_id):
90
+ """Removes a user from the database."""
91
+ conn = get_db_connection()
92
+ cursor = conn.cursor()
93
+ try:
94
+ cursor.execute("DELETE FROM users WHERE user_id = ?", (user_id,))
95
+ conn.commit()
96
+ conn.close()
97
+ return True
98
+ except sqlite3.Error as e:
99
+ conn.rollback()
100
+ conn.close()
101
+ print(f"Database error removing user: {e}")
102
+ return False
103
+
104
+
105
+ def add_product(name, description, price, stock):
106
+ """Adds a new product to the database."""
107
+ conn = get_db_connection()
108
+ cursor = conn.cursor()
109
+ try:
110
+ cursor.execute("""
111
+ INSERT INTO products (name, description, price, stock)
112
+ VALUES (?, ?, ?, ?)
113
+ """, (name, description, price, stock))
114
+ conn.commit()
115
+ product_id = cursor.lastrowid
116
+ conn.close()
117
+ return product_id # Return the ID of the newly added product
118
+ except sqlite3.Error as e:
119
+ conn.rollback() # Roll back changes if error occurs
120
+ conn.close()
121
+ print(f"Database error adding product: {e}")
122
+ return None # Indicate failure
123
+
124
+ def add_user(name, email, address):
125
+ """Adds a new user to the database."""
126
+ conn = get_db_connection()
127
+ cursor = conn.cursor()
128
+ try:
129
+ cursor.execute("""
130
+ INSERT INTO users (name, email, address)
131
+ VALUES (?, ?, ?)
132
+ """, (name, email, address))
133
+ conn.commit()
134
+ user_id = cursor.lastrowid
135
+ conn.close()
136
+ return user_id
137
+ except sqlite3.Error as e:
138
+ conn.rollback()
139
+ conn.close()
140
+ print(f"Database error adding user: {e}")
141
+ return None
142
+
143
+ def add_order(user_id, order_date, status, total_amount):
144
+ """Adds a new order to the database."""
145
+ conn = get_db_connection()
146
+ cursor = conn.cursor()
147
+ try:
148
+ cursor.execute("""
149
+ INSERT INTO orders (user_id, order_date, status, total_amount)
150
+ VALUES (?, ?, ?, ?)
151
+ """, (user_id, order_date, status, total_amount))
152
+ conn.commit()
153
+ order_id = cursor.lastrowid
154
+ conn.close()
155
+ return order_id
156
+ except sqlite3.Error as e:
157
+ conn.rollback()
158
+ conn.close()
159
+ print(f"Database error adding order: {e}")
160
+ return None
161
+
162
+ def add_order_item(order_id, product_id, quantity, price_per_unit):
163
+ """Adds a new order item to the database."""
164
+ conn = get_db_connection()
165
+ cursor = conn.cursor()
166
+ try:
167
+ cursor.execute("""
168
+ INSERT INTO order_items (order_id, product_id, quantity, price_per_unit)
169
+ VALUES (?, ?, ?, ?)
170
+ """, (order_id, product_id, quantity, price_per_unit))
171
+ conn.commit()
172
+ order_item_id = cursor.lastrowid
173
+ conn.close()
174
+ return order_item_id
175
+ except sqlite3.Error as e:
176
+ conn.rollback()
177
+ conn.close()
178
+ print(f"Database error adding order item: {e}")
179
+ return None
180
+
181
+
182
+ def get_all_order_details():
183
+ """Fetches all order details from the database."""
184
+ conn = get_db_connection()
185
+ cursor = conn.cursor()
186
+ cursor.execute("SELECT order_id, product_id, quantity, price_per_unit FROM order_items ORDER BY order_id")
187
+ order_details = cursor.fetchall()
188
+ conn.close()
189
+ return [dict(order_detail) for order_detail in order_details]
190
+
191
+ def get_user_by_email(email):
192
+ """Fetches user details by email address."""
193
+ conn = get_db_connection()
194
+ cursor = conn.cursor()
195
+ cursor.execute("SELECT user_id, name, email, address FROM users WHERE email = ?", (email,))
196
+ user = cursor.fetchone()
197
+ conn.close()
198
+ return dict(user) if user else None
199
+
200
+ def get_all_products():
201
+ """Fetches all products from the database."""
202
+ conn = get_db_connection()
203
+ cursor = conn.cursor()
204
+ cursor.execute("SELECT product_id, name, description, price, stock FROM products ORDER BY product_id")
205
+ products = cursor.fetchall()
206
+ conn.close()
207
+ return [dict(product) for product in products]
208
+
209
+ # Example usage (optional, for testing)
210
+ if __name__ == "__main__":
211
+ print("Testing Data Manager...")
212
+ # Ensure data exists first by running generate_data.py if needed
213
+ if not os.path.exists(DB_PATH):
214
+ print("Database not found. Please run generate_data.py first.")
215
+ else:
216
+ test_order_id = 1
217
+ print(f"\n--- Order Details (ID: {test_order_id}) ---")
218
+ details = get_order_details(test_order_id)
219
+ if details:
220
+ print(details)
221
+ print(f"\n--- Items for Order ID: {test_order_id} ---")
222
+ items = get_order_items(test_order_id)
223
+ for item in items:
224
+ print(item)
225
+ else:
226
+ print(f"Order {test_order_id} not found.")
227
+
228
+ test_user_id = 1
229
+ print(f"\n--- Recent Orders for User ID: {test_user_id}) ---")
230
+ recent_orders = get_user_recent_orders(test_user_id)
231
+ if recent_orders:
232
+ for order in recent_orders:
233
+ print(order)
234
+ else:
235
+ print(f"No orders found for user {test_user_id}.")
236
+
237
+ test_email = 'alice@example.com'
238
+ print(f"\n--- User details for Email: {test_email} ---")
239
+ user = get_user_by_email(test_email)
240
+ if user:
241
+ print(user)
242
+ else:
243
+ print(f"User with email {test_email} not found.")
244
+
245
+ print("\n--- All Products ---")
246
+ all_products = get_all_products()
247
+ if all_products:
248
+ for prod in all_products[:5]: # Print first 5
249
+ print(prod)
250
+ else:
251
+ print("No products found.")
252
+
253
+ # Example Add/Remove (Use with caution on real data)
254
+ # print("\n--- Adding Test Product ---")
255
+ # new_id = add_product("Test Widget", "A temporary test product", 99.99, 50)
256
+ # if new_id:
257
+ # print(f"Added product with ID: {new_id}")
258
+ # print("\n--- Removing Test Product ---")
259
+ # removed = remove_product(new_id)
260
+ # print(f"Removal successful: {removed}")
261
+ # else:
262
+ # print("Failed to add test product.")
263
+
264
+
265
+ def get_all_order_details():
266
+ """Fetches all order details from the database."""
267
+ conn = get_db_connection()
268
+ cursor = conn.cursor()
269
+ cursor.execute("SELECT order_id, product_id, quantity, price_per_unit FROM order_items ORDER BY order_id")
270
+ order_details = cursor.fetchall()
271
+ conn.close()
272
+ return [dict(order_detail) for order_detail in order_details]
273
+
274
+ def remove_user(user_id):
275
+ """Removes a user from the database."""
276
+ conn = get_db_connection()
277
+ cursor = conn.cursor()
278
+ try:
279
+ cursor.execute("DELETE FROM users WHERE user_id = ?", (user_id,))
280
+ conn.commit()
281
+ conn.close()
282
+ return True
283
+ except sqlite3.Error as e:
284
+ conn.rollback()
285
+ conn.close()
286
+ print(f"Database error removing user: {e}")
287
+ return False
288
+
289
+ def remove_order(order_id):
290
+ """Removes an order from the database."""
291
+ conn = get_db_connection()
292
+ cursor = conn.cursor()
293
+ try:
294
+ cursor.execute("DELETE FROM orders WHERE order_id = ?", (order_id,))
295
+ conn.commit()
296
+ conn.close()
297
+ return True
298
+ except sqlite3.Error as e:
299
+ conn.rollback()
300
+ conn.close()
301
+ print(f"Database error removing order: {e}")
302
+ return False
303
+
304
+ def remove_order_details(order_id):
305
+ """Removes order details from the database for a given order_id."""
306
+ conn = get_db_connection()
307
+ cursor = conn.cursor()
308
+ try:
309
+ cursor.execute("DELETE FROM order_items WHERE order_id = ?", (order_id,))
310
+ conn.commit()
311
+ conn.close()
312
+ return True
313
+ except sqlite3.Error as e:
314
+ conn.rollback()
315
+ conn.close()
316
+ print(f"Database error removing order details: {e}")
317
+ return False
318
+
319
+ def get_all_users():
320
+ """Fetches all users from the database."""
321
+ conn = get_db_connection()
322
+ cursor = conn.cursor()
323
+ cursor.execute("SELECT user_id, name, email, address FROM users ORDER BY user_id")
324
+ users = cursor.fetchall()
325
+ conn.close()
326
+ return [dict(user) for user in users]
327
+
328
+ def get_all_orders():
329
+ """Fetches all orders from the database."""
330
+ conn = get_db_connection()
331
+ cursor = conn.cursor()
332
+ cursor.execute("SELECT order_id, user_id, order_date, status, total_amount FROM orders ORDER BY order_id")
333
+ orders = cursor.fetchall()
334
+ conn.close()
335
+ return [dict(order) for order in orders]
gemini_client.py ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import google.generativeai as genai
3
+ from dotenv import load_dotenv
4
+
5
+ # Load environment variables from .env file
6
+ load_dotenv()
7
+
8
+ # Configure the Gemini API
9
+ api_key = os.getenv("GEMINI_API_KEY")
10
+ if not api_key:
11
+ raise ValueError("GEMINI_API_KEY not found in .env file or environment variables.")
12
+
13
+ genai.configure(api_key=api_key)
14
+
15
+ # Initialize the generative model
16
+ # Using gemini-1.0-pro, check documentation for other available models
17
+ model = genai.GenerativeModel('gemini-2.0-flash')
18
+
19
+ def get_gemini_response(prompt):
20
+ """
21
+ Sends a prompt to the Gemini API and returns the generated text response.
22
+
23
+ Args:
24
+ prompt (str): The complete prompt including context and user query.
25
+
26
+ Returns:
27
+ str: The text response from the Gemini model, or an error message.
28
+ """
29
+ try:
30
+ response = model.generate_content(prompt)
31
+ # Accessing the text part of the response
32
+ # Handle potential cases where response might not have 'text' directly
33
+ if response.parts:
34
+ # Assuming the first part contains the text response
35
+ # Adjust if the API response structure differs or has multiple parts
36
+ return response.parts[0].text
37
+ elif hasattr(response, 'text'):
38
+ # Fallback if 'text' attribute exists directly (older versions/different models)
39
+ return response.text
40
+ else:
41
+ # If no text found, return the raw response or an error indicator
42
+ # Log the full response for debugging if necessary
43
+ print(f"Unexpected Gemini response structure: {response}")
44
+ return "Error: Could not extract text from Gemini response."
45
+
46
+ except Exception as e:
47
+ print(f"An error occurred while calling the Gemini API: {e}")
48
+ # Consider more specific error handling based on potential API errors
49
+ return f"Error communicating with AI assistant: {e}"
50
+
51
+ # Example usage (optional, for testing)
52
+ if __name__ == "__main__":
53
+ print("Testing Gemini Client...")
54
+ test_prompt = "Explain what an e-commerce order status 'Shipped' means in simple terms."
55
+ print(f"\nSending prompt: {test_prompt}")
56
+ response_text = get_gemini_response(test_prompt)
57
+ print(f"\nGemini Response:\n{response_text}")
generate_data.py ADDED
@@ -0,0 +1,145 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import sqlite3
2
+ import os
3
+ import datetime
4
+ import random
5
+
6
+ # Define the path for the database
7
+ DB_DIR = "data"
8
+ DB_PATH = os.path.join(DB_DIR, "ecommerce_data.db")
9
+
10
+ def create_database():
11
+ """Creates the SQLite database and tables if they don't exist."""
12
+ # Ensure the data directory exists
13
+ os.makedirs(DB_DIR, exist_ok=True)
14
+
15
+ conn = sqlite3.connect(DB_PATH)
16
+ cursor = conn.cursor()
17
+
18
+ # Create users table
19
+ cursor.execute("""
20
+ CREATE TABLE IF NOT EXISTS users (
21
+ user_id INTEGER PRIMARY KEY AUTOINCREMENT,
22
+ name TEXT NOT NULL,
23
+ email TEXT UNIQUE NOT NULL,
24
+ address TEXT
25
+ );
26
+ """)
27
+
28
+ # Create products table
29
+ cursor.execute("""
30
+ CREATE TABLE IF NOT EXISTS products (
31
+ product_id INTEGER PRIMARY KEY AUTOINCREMENT,
32
+ name TEXT NOT NULL,
33
+ description TEXT,
34
+ price REAL NOT NULL CHECK(price > 0),
35
+ stock INTEGER NOT NULL DEFAULT 0 CHECK(stock >= 0)
36
+ );
37
+ """)
38
+
39
+ # Create orders table
40
+ cursor.execute("""
41
+ CREATE TABLE IF NOT EXISTS orders (
42
+ order_id INTEGER PRIMARY KEY AUTOINCREMENT,
43
+ user_id INTEGER NOT NULL,
44
+ order_date TEXT NOT NULL,
45
+ status TEXT NOT NULL CHECK(status IN ('Pending', 'Processing', 'Shipped', 'Delivered', 'Cancelled')),
46
+ total_amount REAL NOT NULL CHECK(total_amount >= 0),
47
+ FOREIGN KEY (user_id) REFERENCES users(user_id)
48
+ );
49
+ """)
50
+
51
+ # Create order_items table (linking orders and products)
52
+ cursor.execute("""
53
+ CREATE TABLE IF NOT EXISTS order_items (
54
+ order_item_id INTEGER PRIMARY KEY AUTOINCREMENT,
55
+ order_id INTEGER NOT NULL,
56
+ product_id INTEGER NOT NULL,
57
+ quantity INTEGER NOT NULL CHECK(quantity > 0),
58
+ price_per_unit REAL NOT NULL CHECK(price_per_unit > 0),
59
+ FOREIGN KEY (order_id) REFERENCES orders(order_id),
60
+ FOREIGN KEY (product_id) REFERENCES products(product_id)
61
+ );
62
+ """)
63
+
64
+ conn.commit()
65
+ conn.close()
66
+ print(f"Database created/verified at {DB_PATH}")
67
+
68
+ def populate_data():
69
+ """Populates the database with sample data if tables are empty."""
70
+ conn = sqlite3.connect(DB_PATH)
71
+ cursor = conn.cursor()
72
+
73
+ try:
74
+ # Check if tables are already populated
75
+ cursor.execute("SELECT COUNT(*) FROM users")
76
+ if cursor.fetchone()[0] > 0:
77
+ print("Database already contains data. Skipping population.")
78
+ return
79
+
80
+ # Sample Users
81
+ users_data = [
82
+ ('Alice Wonderland', 'alice@example.com', '123 Fantasy Lane'),
83
+ ('Bob The Builder', 'bob@example.com', '456 Construction Ave'),
84
+ ('Charlie Chaplin', 'charlie@example.com', '789 Silent Film St')
85
+ ]
86
+ cursor.executemany("INSERT INTO users (name, email, address) VALUES (?, ?, ?)", users_data)
87
+ print(f"Inserted {len(users_data)} users.")
88
+
89
+ # Sample Products
90
+ products_data = [
91
+ ('Laptop Pro', 'High-end laptop for professionals', 1200.00, 100),
92
+ ('Wireless Mouse', 'Ergonomic wireless mouse', 25.50, 500),
93
+ ('Mechanical Keyboard', 'RGB Mechanical Keyboard', 75.00, 200),
94
+ ('USB-C Hub', '7-in-1 USB-C Hub', 40.00, 300),
95
+ ('Monitor 27"', '27 inch 4K Monitor', 300.00, 150)
96
+ ]
97
+ cursor.executemany("INSERT INTO products (name, description, price, stock) VALUES (?, ?, ?, ?)", products_data)
98
+ print(f"Inserted {len(products_data)} products.")
99
+
100
+ # Sample Orders and Order Items
101
+ order_statuses = ['Pending', 'Processing', 'Shipped', 'Delivered', 'Cancelled']
102
+ user_ids = [row[0] for row in cursor.execute("SELECT user_id FROM users").fetchall()]
103
+ product_info = {row[0]: row[1] for row in cursor.execute("SELECT product_id, price FROM products").fetchall()}
104
+ product_ids = list(product_info.keys())
105
+
106
+ for i in range(5): # Create 5 sample orders
107
+ user_id = random.choice(user_ids)
108
+ order_date = (datetime.datetime.now() - datetime.timedelta(days=random.randint(1, 30))).strftime('%Y-%m-%d %H:%M:%S')
109
+ status = random.choice(order_statuses)
110
+
111
+ # Insert order first with a placeholder total
112
+ cursor.execute("INSERT INTO orders (user_id, order_date, status, total_amount) VALUES (?, ?, ?, ?)",
113
+ (user_id, order_date, status, 0.0))
114
+ order_id = cursor.lastrowid
115
+
116
+ order_total = 0.0
117
+ num_items = random.randint(1, 3)
118
+ items_in_order = random.sample(product_ids, num_items)
119
+
120
+ order_items_data = []
121
+ for product_id in items_in_order:
122
+ quantity = random.randint(1, 2)
123
+ price_per_unit = product_info[product_id]
124
+ order_items_data.append((order_id, product_id, quantity, price_per_unit))
125
+ order_total += quantity * price_per_unit
126
+
127
+ cursor.executemany("INSERT INTO order_items (order_id, product_id, quantity, price_per_unit) VALUES (?, ?, ?, ?)", order_items_data)
128
+
129
+ # Update order total
130
+ cursor.execute("UPDATE orders SET total_amount = ? WHERE order_id = ?", (round(order_total, 2), order_id))
131
+
132
+ print(f"Inserted 5 sample orders with items.")
133
+
134
+ conn.commit()
135
+
136
+ except sqlite3.Error as e:
137
+ print(f"An error occurred: {e}")
138
+ conn.rollback()
139
+ finally:
140
+ conn.close()
141
+
142
+ if __name__ == "__main__":
143
+ create_database()
144
+ populate_data()
145
+ print("Data generation complete.")
requirements.txt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ google-generativeai
2
+ python-dotenv
3
+ gradio