rairo commited on
Commit
d0c9194
·
verified ·
1 Parent(s): 5ee8011

Update main.py

Browse files
Files changed (1) hide show
  1. main.py +348 -1
main.py CHANGED
@@ -28,6 +28,38 @@ bucket = storage.bucket()
28
  api_key = os.environ['Gemini']
29
  FIREBASE_API_KEY = os.environ.get('FIREBASE_API_KEY')
30
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31
  # Product Categories
32
  CATEGORIES = [
33
  'Masks',
@@ -193,10 +225,325 @@ def user_profile():
193
  'updated_fields': list(updates.keys())
194
  })
195
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
196
  except Exception as e:
197
  return jsonify({'error': str(e)}), 500
198
 
199
- # [Previous code remains the same...]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
200
 
201
  if __name__ == '__main__':
202
  app.run(debug=True, host="0.0.0.0", port=7860)
 
28
  api_key = os.environ['Gemini']
29
  FIREBASE_API_KEY = os.environ.get('FIREBASE_API_KEY')
30
 
31
+
32
+ 500
33
+
34
+ # Helper functions
35
+ def configure_gemini():
36
+ genai.configure(api_key=api_key)
37
+ return genai.GenerativeModel('gemini-2.0-flash-thinking-exp')
38
+
39
+ def verify_token(token):
40
+ try:
41
+ decoded_token = auth.verify_id_token(token)
42
+ return decoded_token['uid']
43
+ except Exception:
44
+ return None
45
+
46
+ def verify_admin(auth_header):
47
+ if not auth_header or not auth_header.startswith('Bearer '):
48
+ raise ValueError('Invalid token')
49
+
50
+ token = auth_header.split(' ')[1]
51
+ uid = verify_token(token)
52
+ if not uid:
53
+ raise PermissionError('Invalid user')
54
+
55
+ user_ref = db.reference(f'users/{uid}')
56
+ user_data = user_ref.get()
57
+ if not user_data or not user_data.get('is_admin', False):
58
+ raise PermissionError('Admin access required')
59
+
60
+ return uid
61
+
62
+
63
  # Product Categories
64
  CATEGORIES = [
65
  'Masks',
 
225
  'updated_fields': list(updates.keys())
226
  })
227
 
228
+ except Exception as e:
229
+ return jsonify({'error': str(e)}),
230
+
231
+ # Product Management Endpoints
232
+ @app.route('/api/admin/products', methods=['POST'])
233
+ def create_product():
234
+ try:
235
+ verify_admin(request.headers.get('Authorization', ''))
236
+
237
+ if 'image' not in request.files:
238
+ return jsonify({'error': 'No image file uploaded'}), 400
239
+
240
+ file = request.files['image']
241
+ name = request.form.get('name')
242
+ category = request.form.get('category')
243
+ price = float(request.form.get('price'))
244
+ description = request.form.get('description')
245
+ stock = int(request.form.get('stock', 0))
246
+
247
+ if category not in CATEGORIES:
248
+ return jsonify({'error': 'Invalid category'}), 400
249
+
250
+ # Upload image
251
+ image_bytes = file.read()
252
+ timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
253
+ file_hash = hashlib.md5(image_bytes).hexdigest()
254
+ blob = bucket.blob(f'products/{timestamp}_{file_hash}.jpg')
255
+ blob.upload_from_string(image_bytes, content_type='image/jpeg')
256
+ image_url = blob.public_url
257
+
258
+ # Create product
259
+ product_ref = db.reference('products').push({
260
+ 'name': name,
261
+ 'category': category,
262
+ 'price': price,
263
+ 'description': description,
264
+ 'stock': stock,
265
+ 'image_url': image_url,
266
+ 'created_at': datetime.now(pytz.UTC).isoformat(),
267
+ 'active': True
268
+ })
269
+
270
+ return jsonify({
271
+ 'success': True,
272
+ 'product_id': product_ref.key
273
+ }), 201
274
+
275
  except Exception as e:
276
  return jsonify({'error': str(e)}), 500
277
 
278
+ @app.route('/api/admin/products/<string:product_id>', methods=['PUT'])
279
+ def update_product(product_id):
280
+ try:
281
+ verify_admin(request.headers.get('Authorization', ''))
282
+
283
+ updates = {}
284
+ if 'name' in request.form:
285
+ updates['name'] = request.form['name']
286
+ if 'category' in request.form and request.form['category'] in CATEGORIES:
287
+ updates['category'] = request.form['category']
288
+ if 'price' in request.form:
289
+ updates['price'] = float(request.form['price'])
290
+ if 'description' in request.form:
291
+ updates['description'] = request.form['description']
292
+ if 'stock' in request.form:
293
+ updates['stock'] = int(request.form['stock'])
294
+ if 'active' in request.form:
295
+ updates['active'] = request.form['active'].lower() == 'true'
296
+
297
+ if 'image' in request.files:
298
+ file = request.files['image']
299
+ image_bytes = file.read()
300
+ timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
301
+ file_hash = hashlib.md5(image_bytes).hexdigest()
302
+ blob = bucket.blob(f'products/{timestamp}_{file_hash}.jpg')
303
+ blob.upload_from_string(image_bytes, content_type='image/jpeg')
304
+ updates['image_url'] = blob.public_url
305
+
306
+ db.reference(f'products/{product_id}').update(updates)
307
+
308
+ return jsonify({'success': True})
309
+
310
+ except Exception as e:
311
+ return jsonify({'error': str(e)}), 500
312
+
313
+ # Shopping Cart and Order Management
314
+ @app.route('/api/cart/add', methods=['POST'])
315
+ def add_to_cart():
316
+ try:
317
+ data = request.get_json()
318
+ product_id = data['product_id']
319
+ quantity = int(data['quantity'])
320
+
321
+ # Get user ID if logged in
322
+ auth_header = request.headers.get('Authorization')
323
+ uid = verify_token(auth_header.split(' ')[1]) if auth_header else None
324
+
325
+ # Use session ID for non-logged in users
326
+ session_id = data.get('session_id')
327
+ if not uid and not session_id:
328
+ return jsonify({'error': 'Either login or provide session_id'}), 400
329
+
330
+ cart_id = uid if uid else f'session_{session_id}'
331
+ cart_ref = db.reference(f'carts/{cart_id}')
332
+
333
+ # Check product availability
334
+ product = db.reference(f'products/{product_id}').get()
335
+ if not product:
336
+ return jsonify({'error': 'Product not found'}), 404
337
+ if not product.get('active', False):
338
+ return jsonify({'error': 'Product not available'}), 400
339
+ if product.get('stock', 0) < quantity:
340
+ return jsonify({'error': 'Insufficient stock'}), 400
341
+
342
+ # Update cart
343
+ cart_item = cart_ref.child(product_id).get() or {'quantity': 0}
344
+ new_quantity = cart_item['quantity'] + quantity
345
+
346
+ cart_ref.child(product_id).set({
347
+ 'quantity': new_quantity,
348
+ 'price': product['price'],
349
+ 'name': product['name']
350
+ })
351
+
352
+ return jsonify({'success': True})
353
+
354
+ except Exception as e:
355
+ return jsonify({'error': str(e)}), 500
356
+
357
+ @app.route('/api/orders', methods=['POST'])
358
+ def create_order():
359
+ try:
360
+ data = request.get_json()
361
+ auth_header = request.headers.get('Authorization')
362
+ uid = verify_token(auth_header.split(' ')[1]) if auth_header else None
363
+
364
+ cart_id = uid if uid else f'session_{data["session_id"]}'
365
+ cart_ref = db.reference(f'carts/{cart_id}')
366
+ cart = cart_ref.get()
367
+
368
+ if not cart:
369
+ return jsonify({'error': 'Cart is empty'}), 400
370
+
371
+ # Validate stock and calculate total
372
+ total = 0
373
+ items = []
374
+ for product_id, item in cart.items():
375
+ product = db.reference(f'products/{product_id}').get()
376
+ if not product or not product.get('active', False):
377
+ return jsonify({'error': f'Product {product_id} not available'}), 400
378
+ if product['stock'] < item['quantity']:
379
+ return jsonify({'error': f'Insufficient stock for {product["name"]}'}), 400
380
+
381
+ total += item['quantity'] * product['price']
382
+ items.append({
383
+ 'product_id': product_id,
384
+ 'quantity': item['quantity'],
385
+ 'price': product['price'],
386
+ 'name': product['name']
387
+ })
388
+
389
+ # Update stock
390
+ db.reference(f'products/{product_id}').update({
391
+ 'stock': product['stock'] - item['quantity']
392
+ })
393
+
394
+ # Create order
395
+ order_ref = db.reference('orders').push({
396
+ 'user_id': uid,
397
+ 'session_id': None if uid else data.get('session_id'),
398
+ 'items': items,
399
+ 'total': total,
400
+ 'status': 'pending',
401
+ 'shipping_address': data.get('shipping_address'),
402
+ 'contact_email': data.get('contact_email'),
403
+ 'created_at': datetime.now(pytz.UTC).isoformat()
404
+ })
405
+
406
+ # Clear cart
407
+ cart_ref.delete()
408
+
409
+ return jsonify({
410
+ 'success': True,
411
+ 'order_id': order_ref.key
412
+ })
413
+
414
+ except Exception as e:
415
+ return jsonify({'error': str(e)}), 500
416
+
417
+ # AI Reporting
418
+ @app.route('/api/admin/reports', methods=['POST'])
419
+ def generate_report():
420
+ try:
421
+ verify_admin(request.headers.get('Authorization', ''))
422
+ data = request.get_json()
423
+ start_date = datetime.fromisoformat(data['start_date'])
424
+ end_date = datetime.fromisoformat(data['end_date'])
425
+
426
+ # Get orders within date range
427
+ orders_ref = db.reference('orders')
428
+ orders = orders_ref.get() or {}
429
+
430
+ filtered_orders = {
431
+ k: v for k, v in orders.items()
432
+ if start_date <= datetime.fromisoformat(v['created_at']) <= end_date
433
+ }
434
+
435
+ prompt = f"""Analyze this e-commerce data for medical PPE products and generate a comprehensive business report.
436
+ Focus on:
437
+ 1. Total sales and revenue
438
+ 2. Popular products and categories
439
+ 3. Customer behavior patterns
440
+ 4. Stock management recommendations
441
+ 5. Market trends and insights
442
+
443
+ Data period: {start_date.date()} to {end_date.date()}"""
444
+
445
+ model = configure_gemini()
446
+ response = model.generate_content([prompt, json.dumps(filtered_orders)])
447
+
448
+ return jsonify({
449
+ 'report': response.text,
450
+ 'data': {
451
+ 'total_orders': len(filtered_orders),
452
+ 'total_revenue': sum(order['total'] for order in filtered_orders.values())
453
+ }
454
+ })
455
+
456
+ except Exception as e:
457
+ return jsonify({'error': str(e)}), 500
458
+
459
+ # Product Browsing
460
+ @app.route('/api/products', methods=['GET'])
461
+ def get_products():
462
+ try:
463
+ category = request.args.get('category')
464
+ search = request.args.get('search', '').lower()
465
+
466
+ products_ref = db.reference('products')
467
+ products = products_ref.get() or {}
468
+
469
+ filtered_products = []
470
+ for product_id, product in products.items():
471
+ if not product.get('active', False):
472
+ continue
473
+ if category and product['category'] != category:
474
+ continue
475
+ if search and search not in product['name'].lower():
476
+ continue
477
+
478
+ filtered_products.append({
479
+ 'id': product_id,
480
+ **product
481
+ })
482
+
483
+ return jsonify(filtered_products)
484
+
485
+ except Exception as e:
486
+ return jsonify({'error': str(e)}), 500
487
+
488
+ # User Order History
489
+ @app.route('/api/user/orders', methods=['GET'])
490
+ def get_user_orders():
491
+ try:
492
+ auth_header = request.headers.get('Authorization')
493
+ if not auth_header:
494
+ return jsonify({'error': 'Authorization required'}), 401
495
+
496
+ uid = verify_token(auth_header.split(' ')[1])
497
+ if not uid:
498
+ return jsonify({'error': 'Invalid token'}), 401
499
+
500
+ orders_ref = db.reference('orders')
501
+ orders = orders_ref.order_by_child('user_id').equal_to(uid).get() or {}
502
+
503
+ return jsonify([{
504
+ 'id': order_id,
505
+ **order_data
506
+ } for order_id, order_data in orders.items()])
507
+
508
+ except Exception as e:
509
+ return jsonify({'error': str(e)}), 500
510
+
511
+ # Admin Dashboard Data
512
+ @app.route('/api/admin/dashboard', methods=['GET'])
513
+ def get_admin_dashboard():
514
+ try:
515
+ verify_admin(request.headers.get('Authorization', ''))
516
+
517
+ # Get recent orders
518
+ orders_ref = db.reference('orders')
519
+ recent_orders = orders_ref.order_by_child('created_at').limit_to_last(10).get() or {}
520
+
521
+ # Get low stock products
522
+ products_ref = db.reference('products')
523
+ products = products_ref.get() or {}
524
+ low_stock = [
525
+ {'id': pid, **p}
526
+ for pid, p in products.items()
527
+ if p.get('active', False) and p.get('stock', 0) < 10
528
+ ]
529
+
530
+ # Calculate statistics
531
+ total_revenue = sum(order['total'] for order in recent_orders.values())
532
+ total_orders = len(recent_orders)
533
+
534
+ return jsonify({
535
+ 'recent_orders': recent_orders,
536
+ 'low_stock_products': low_stock,
537
+ 'statistics': {
538
+ 'total_revenue': total_revenue,
539
+ 'total_orders': total_orders,
540
+ 'total_products': len(products),
541
+ 'low_stock_count': len(low_stock)
542
+ }
543
+ })
544
+
545
+ except Exception as e:
546
+ return jsonify({'error': str(e)}), 500
547
 
548
  if __name__ == '__main__':
549
  app.run(debug=True, host="0.0.0.0", port=7860)