lokesh341 commited on
Commit
b5489cb
·
verified ·
1 Parent(s): 9cb50d5

Update menu.py

Browse files
Files changed (1) hide show
  1. menu.py +358 -231
menu.py CHANGED
@@ -1,311 +1,438 @@
1
  from flask import Blueprint, render_template, request, session, jsonify, redirect, url_for
2
  from salesforce import get_salesforce_connection
3
  import os
 
 
 
 
 
 
 
4
 
5
  menu_blueprint = Blueprint('menu', __name__)
6
 
7
  # Initialize Salesforce connection
8
  sf = get_salesforce_connection()
9
 
10
- # Constants for video handling
11
  STATIC_DIR = os.path.join(os.path.dirname(__file__), 'static')
12
  PLACEHOLDER_VIDEO = 'placeholder.mp4'
13
- PLACEHOLDER_PATH = os.path.join(STATIC_DIR, PLACEHOLDER_VIDEO)
14
- SECTION_ORDER = ["Best Sellers", "Starters", "Biryanis", "Curries", "Breads", "Customized dish", "Apetizer", "Desserts", "Soft Drinks"]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
 
16
- # Create placeholder video at startup if it doesn't exist
17
- if not os.path.exists(PLACEHOLDER_PATH):
18
- open(PLACEHOLDER_PATH, 'wb').close()
19
- print(f"Created placeholder video at {PLACEHOLDER_PATH}")
20
 
21
- def get_valid_video_path(item_name, video_url=None):
22
  """
23
- Get valid video path for item with placeholder fallback
24
- Priority: 1. Video1__c from Salesforce 2. placeholder.mp4
 
 
 
 
25
  """
26
- # First try: Video1__c from Salesforce if provided
27
- if video_url:
28
- # If it's a complete URL (http/https)
29
- if video_url.startswith(('http://', 'https://')):
30
- return video_url
31
- # If it's a relative path (/videos/xxx.mp4)
32
- elif video_url.startswith('/'):
33
- return video_url
34
- # If it's a Salesforce File ID (starts with '069')
35
- elif video_url.startswith('069'):
36
- return f"https://yourdomain.my.salesforce.com/sfc/servlet.shepherd/version/download/{video_url}"
 
 
37
 
38
- # Final fallback: placeholder.mp4
39
- if not os.path.exists(PLACEHOLDER_PATH):
40
- open(PLACEHOLDER_PATH, 'wb').close()
41
- print(f"Created missing placeholder video at {PLACEHOLDER_PATH}")
42
 
43
- return f"/static/{PLACEHOLDER_VIDEO}"
44
 
45
- @menu_blueprint.route("/menu", methods=["GET", "POST"])
46
- def menu():
47
- selected_category = request.args.get("category", "All")
48
  user_email = session.get('user_email')
49
-
 
50
  if not user_email:
51
- user_email = request.args.get("email")
52
- user_name = request.args.get("name")
53
-
54
  if user_email:
55
  session['user_email'] = user_email
56
  session['user_name'] = user_name
57
  else:
58
- return redirect(url_for("login"))
59
- else:
60
- user_name = session.get('user_name')
61
-
62
  first_letter = user_name[0].upper() if user_name else "A"
 
63
 
 
 
64
  try:
65
- # Fetch user referral and reward points
66
- user_query = f"SELECT Referral__c, Reward_Points__c FROM Customer_Login__c WHERE Email__c = '{user_email}'"
67
- user_result = sf.query(user_query)
68
-
69
- if not user_result['records']:
70
- return redirect(url_for('login'))
71
-
72
- referral_code = user_result['records'][0].get('Referral__c', 'N/A')
73
- reward_points = user_result['records'][0].get('Reward_Points__c', 0)
 
 
 
 
 
 
 
 
74
 
75
- # Get cart item count
76
- cart_query = f"SELECT COUNT() FROM Cart_Item__c WHERE Customer_Email__c = '{user_email}'"
77
- cart_count_result = sf.query(cart_query)
78
- cart_item_count = cart_count_result['totalSize']
 
 
 
 
 
79
 
80
- # Query to fetch Menu_Item__c records including Video1__c
 
 
 
81
  menu_query = """
82
- SELECT Name, Price__c, Description__c, Image1__c, Image2__c,
83
- Veg_NonVeg__c, Section__c, Total_Ordered__c, Video1__c
 
84
  FROM Menu_Item__c
 
85
  """
86
- result = sf.query(menu_query)
87
- food_items = result['records'] if 'records' in result else []
88
-
89
- # Process items and add video paths
90
- for item in food_items:
91
- if 'Total_Ordered__c' not in item or item['Total_Ordered__c'] is None:
92
- item['Total_Ordered__c'] = 0
93
- item['Video1__c'] = get_valid_video_path(item['Name'], item.get('Video1__c'))
94
-
95
- # Query to fetch Custom_Dish__c records
96
  custom_dish_query = """
97
- SELECT Name, Price__c, Description__c, Image1__c, Image2__c,
98
- Veg_NonVeg__c, Section__c, Total_Ordered__c
99
  FROM Custom_Dish__c
100
- WHERE CreatedDate >= LAST_N_DAYS:7
101
  """
102
- custom_dish_result = sf.query(custom_dish_query)
103
  custom_dishes = custom_dish_result.get('records', [])
104
-
105
- # Process custom dishes and add video paths
106
- for item in custom_dishes:
107
- if 'Total_Ordered__c' not in item or item['Total_Ordered__c'] is None:
108
- item['Total_Ordered__c'] = 0
109
- item['Video1__c'] = get_valid_video_path(item['Name'])
110
-
111
- # Merge both Menu_Item__c and Custom_Dish__c records
112
- all_items = food_items + custom_dishes
113
- ordered_menu = {section: [] for section in SECTION_ORDER}
114
-
115
- # Process best sellers
116
- best_sellers = sorted(all_items, key=lambda x: x.get("Total_Ordered__c", 0), reverse=True)
117
 
118
- if selected_category == "Veg":
119
- best_sellers = [item for item in best_sellers if item.get("Veg_NonVeg__c") in ["Veg", "both"]]
120
- elif selected_category == "Non veg":
121
- best_sellers = [item for item in best_sellers if item.get("Veg_NonVeg__c") in ["Non veg", "both"]]
122
-
123
- best_sellers = best_sellers[:4]
124
- if best_sellers:
125
- ordered_menu["Best Sellers"] = best_sellers
126
-
127
- # Organize other sections
128
- added_item_names = set()
129
- for item in all_items:
130
- section = item.get("Section__c", "Others")
131
- if section not in ordered_menu:
132
- ordered_menu[section] = []
133
-
134
- if item['Name'] in added_item_names:
135
- continue
136
-
137
- if selected_category == "Veg" and item.get("Veg_NonVeg__c") not in ["Veg", "both"]:
 
 
138
  continue
139
- if selected_category == "Non veg" and item.get("Veg_NonVeg__c") not in ["Non veg", "both"]:
140
  continue
 
 
 
 
 
 
 
 
141
 
142
- ordered_menu[section].append(item)
143
- added_item_names.add(item['Name'])
144
-
145
- ordered_menu = {section: items for section, items in ordered_menu.items() if items}
146
- categories = ["All", "Veg", "Non veg"]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
147
 
148
- except Exception as e:
149
- print(f"Error fetching menu data: {str(e)}")
150
- # Fallback data with video support
151
- ordered_menu = {section: [] for section in SECTION_ORDER}
152
- best_sellers = ["Chicken Biryani", "Paneer Butter Masala", "Veg Manchurian", "Prawn Fry"]
153
- ordered_menu["Best Sellers"] = [{
154
- "Name": name,
155
- "Price__c": "12.99",
156
- "Description__c": f"Popular {name}",
157
- "Image1__c": "/static/placeholder.jpg",
158
- "Video1__c": get_valid_video_path(name),
159
- "Total_Ordered__c": 100,
160
- "Veg_NonVeg__c": "Veg" if "Paneer" in name or "Veg" in name else "Non veg"
161
- } for name in best_sellers]
 
 
 
162
 
 
 
 
 
 
163
  categories = ["All", "Veg", "Non veg"]
164
- referral_code = 'N/A'
165
- reward_points = 0
166
- cart_item_count = 0
167
-
168
- return render_template(
169
- "menu.html",
170
- ordered_menu=ordered_menu,
171
- categories=categories,
172
- selected_category=selected_category,
173
- referral_code=referral_code,
174
- reward_points=reward_points,
175
- user_name=user_name,
176
- first_letter=first_letter,
177
- cart_item_count=cart_item_count
178
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
179
 
180
  @menu_blueprint.route('/api/addons', methods=['GET'])
181
  def get_addons():
182
- item_name = request.args.get('item_name')
183
- item_section = request.args.get('item_section')
184
-
185
- if not item_name or not item_section:
186
- return jsonify({"success": False, "error": "Item name and section are required."}), 400
187
-
188
  try:
 
 
 
 
 
 
 
 
 
 
189
  query = f"""
190
- SELECT Name, Customization_Type__c, Options__c, Max_Selections__c, Extra_Charge__c, Extra_Charge_Amount__c
 
 
191
  FROM Customization_Options__c
192
  WHERE Section__c = '{item_section}'
 
 
193
  """
194
  result = sf.query(query)
195
  addons = result.get('records', [])
196
-
197
  if not addons:
198
- return jsonify({"success": False, "error": "No customization options found for the given section."}), 404
199
-
 
 
 
 
200
  formatted_addons = []
201
  for addon in addons:
202
  options = addon.get("Options__c", "")
203
- if options:
204
- options = options.split(", ")
205
- else:
206
- options = []
207
-
208
  formatted_addons.append({
209
- "name": addon["Name"],
210
- "type": addon["Customization_Type__c"],
 
211
  "options": options,
212
  "max_selections": addon.get("Max_Selections__c", 1),
213
  "extra_charge": addon.get("Extra_Charge__c", False),
214
- "extra_charge_amount": addon.get("Extra_Charge_Amount__c", 0)
215
  })
216
-
217
- return jsonify({"success": True, "addons": formatted_addons})
218
-
 
 
 
219
  except Exception as e:
220
- print(f"Error fetching addons: {str(e)}")
221
- return jsonify({"success": False, "error": "An error occurred while fetching customization options."}), 500
 
 
 
222
 
223
  @menu_blueprint.route('/cart/add', methods=['POST'])
224
  def add_to_cart():
225
  try:
226
- data = request.json
227
- item_name = data.get('itemName', '').strip()
228
- item_price = data.get('itemPrice')
229
- item_image = data.get('itemImage')
230
- addons = data.get('addons', [])
231
- instructions = data.get('instructions', '')
232
- category = data.get('category')
233
- section = data.get('section')
234
- quantity = data.get('quantity', 1)
235
- customer_email = session.get('user_email')
236
-
237
- if not item_name or not item_price:
238
- return jsonify({"success": False, "error": "Item name and price are required."}), 400
239
-
240
- if not customer_email:
241
- return jsonify({"success": False, "error": "User email is required."}), 400
242
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
243
  query = f"""
244
  SELECT Id, Quantity__c, Add_Ons__c, Add_Ons_Price__c, Instructions__c
245
  FROM Cart_Item__c
246
- WHERE Customer_Email__c = '{customer_email}' AND Name = '{item_name}'
 
 
247
  """
248
  result = sf.query(query)
249
- cart_items = result.get("records", [])
250
-
251
- addons_price = sum(addon['price'] for addon in addons)
252
- new_addons = "; ".join([f"{addon['name']} (${addon['price']})" for addon in addons])
253
-
254
- if cart_items:
255
- cart_item_id = cart_items[0]['Id']
256
- existing_quantity = cart_items[0]['Quantity__c']
257
- existing_addons = cart_items[0].get('Add_Ons__c', "None")
258
- existing_addons_price = cart_items[0].get('Add_Ons_Price__c', 0)
259
- existing_instructions = cart_items[0].get('Instructions__c', "")
260
-
261
- combined_addons = existing_addons if existing_addons != "None" else ""
262
- if new_addons:
263
- combined_addons = f"{combined_addons}; {new_addons}".strip("; ")
264
-
265
- combined_instructions = existing_instructions
266
- if instructions:
267
- combined_instructions = f"{combined_instructions} | {instructions}".strip(" | ")
268
-
269
- combined_addons_list = combined_addons.split("; ")
270
- combined_addons_price = sum(
271
- float(addon.split("($")[1][:-1]) for addon in combined_addons_list if "($" in addon
272
- )
273
-
274
- sf.Cart_Item__c.update(cart_item_id, {
275
- "Quantity__c": existing_quantity + quantity,
276
- "Add_Ons__c": combined_addons,
277
- "Add_Ons_Price__c": combined_addons_price,
278
- "Instructions__c": combined_instructions,
279
- "Price__c": (existing_quantity + quantity) * item_price + combined_addons_price,
280
- "Category__c": category,
281
- "Section__c": section
282
  })
283
  else:
284
- addons_string = "None"
285
- if addons:
286
- addons_string = new_addons
287
-
288
- total_price = item_price * quantity + addons_price
289
-
290
  sf.Cart_Item__c.create({
291
- "Name": item_name,
292
  "Price__c": total_price,
293
- "Base_Price__c": item_price,
294
- "Quantity__c": quantity,
295
  "Add_Ons_Price__c": addons_price,
296
  "Add_Ons__c": addons_string,
297
- "Image1__c": item_image,
298
- "Customer_Email__c": customer_email,
299
- "Instructions__c": instructions,
300
- "Category__c": category,
301
- "Section__c": section
302
  })
303
-
304
- return jsonify({"success": True, "message": "Item added to cart successfully."})
305
-
306
- except KeyError as e:
307
- return jsonify({"success": False, "error": f"Missing required field: {str(e)}"}), 400
308
-
 
 
 
 
 
 
 
309
  except Exception as e:
310
- print(f"Error adding item to cart: {str(e)}")
311
- return jsonify({"success": False, "error": "An error occurred while adding the item to the cart."}), 500
 
 
 
 
1
  from flask import Blueprint, render_template, request, session, jsonify, redirect, url_for
2
  from salesforce import get_salesforce_connection
3
  import os
4
+ import logging
5
+ from urllib.parse import quote
6
+ from datetime import datetime, timedelta
7
+
8
+ # Initialize logging
9
+ logging.basicConfig(level=logging.INFO)
10
+ logger = logging.getLogger(__name__)
11
 
12
  menu_blueprint = Blueprint('menu', __name__)
13
 
14
  # Initialize Salesforce connection
15
  sf = get_salesforce_connection()
16
 
17
+ # Constants
18
  STATIC_DIR = os.path.join(os.path.dirname(__file__), 'static')
19
  PLACEHOLDER_VIDEO = 'placeholder.mp4'
20
+ PLACEHOLDER_IMAGE = 'placeholder.jpg'
21
+ PLACEHOLDER_VIDEO_PATH = os.path.join(STATIC_DIR, PLACEHOLDER_VIDEO)
22
+ PLACEHOLDER_IMAGE_PATH = os.path.join(STATIC_DIR, PLACEHOLDER_IMAGE)
23
+ SECTION_ORDER = ["Best Sellers", "Starters", "Biryanis", "Curries", "Breads",
24
+ "Customized Dish", "Appetizer", "Desserts", "Soft Drinks"]
25
+ MAX_BEST_SELLERS = 4
26
+ DEFAULT_VIDEO_URL = "https://yourdomain.my.salesforce.com/sfc/servlet.shepherd/version/download/"
27
+
28
+ # Create placeholder files if they don't exist
29
+ def initialize_placeholders():
30
+ try:
31
+ if not os.path.exists(PLACEHOLDER_VIDEO_PATH):
32
+ with open(PLACEHOLDER_VIDEO_PATH, 'wb') as f:
33
+ f.write(b'') # Empty file
34
+ logger.info(f"Created placeholder video at {PLACEHOLDER_VIDEO_PATH}")
35
+
36
+ if not os.path.exists(PLACEHOLDER_IMAGE_PATH):
37
+ with open(PLACEHOLDER_IMAGE_PATH, 'wb') as f:
38
+ f.write(b'') # Empty file
39
+ logger.info(f"Created placeholder image at {PLACEHOLDER_IMAGE_PATH}")
40
+ except Exception as e:
41
+ logger.error(f"Error creating placeholder files: {str(e)}")
42
 
43
+ initialize_placeholders()
 
 
 
44
 
45
+ def get_valid_media_path(media_url=None, media_type='video'):
46
  """
47
+ Get valid media path with placeholder fallback
48
+ Args:
49
+ media_url: URL or ID from Salesforce
50
+ media_type: 'video' or 'image'
51
+ Returns:
52
+ Valid URL for the media
53
  """
54
+ # Default placeholders
55
+ default_path = f"/static/{PLACEHOLDER_VIDEO if media_type == 'video' else PLACEHOLDER_IMAGE}"
56
+
57
+ if not media_url:
58
+ return default_path
59
+
60
+ # Handle Salesforce File ID (starts with '069')
61
+ if media_url.startswith('069'):
62
+ return f"{DEFAULT_VIDEO_URL}{media_url}"
63
+
64
+ # Handle complete URLs
65
+ if media_url.startswith(('http://', 'https://')):
66
+ return media_url
67
 
68
+ # Handle relative paths
69
+ if media_url.startswith('/'):
70
+ return media_url
 
71
 
72
+ return default_path
73
 
74
+ def validate_user_session():
75
+ """Validate and return user session data or redirect to login"""
 
76
  user_email = session.get('user_email')
77
+ user_name = session.get('user_name')
78
+
79
  if not user_email:
80
+ user_email = request.args.get('email')
81
+ user_name = request.args.get('name')
82
+
83
  if user_email:
84
  session['user_email'] = user_email
85
  session['user_name'] = user_name
86
  else:
87
+ return None, None, redirect(url_for("login"))
88
+
 
 
89
  first_letter = user_name[0].upper() if user_name else "A"
90
+ return user_email, first_letter, None
91
 
92
+ def get_user_details(sf_connection, email):
93
+ """Fetch user details from Salesforce"""
94
  try:
95
+ query = f"""
96
+ SELECT Id, Referral__c, Reward_Points__c
97
+ FROM Customer_Login__c
98
+ WHERE Email__c = '{email}'
99
+ """
100
+ result = sf_connection.query(query)
101
+
102
+ if not result['records']:
103
+ return None
104
+
105
+ return {
106
+ 'referral_code': result['records'][0].get('Referral__c', 'N/A'),
107
+ 'reward_points': result['records'][0].get('Reward_Points__c', 0)
108
+ }
109
+ except Exception as e:
110
+ logger.error(f"Error fetching user details: {str(e)}")
111
+ return None
112
 
113
+ def get_cart_count(sf_connection, email):
114
+ """Get cart item count for user"""
115
+ try:
116
+ query = f"SELECT COUNT() FROM Cart_Item__c WHERE Customer_Email__c = '{email}'"
117
+ result = sf_connection.query(query)
118
+ return result['totalSize']
119
+ except Exception as e:
120
+ logger.error(f"Error fetching cart count: {str(e)}")
121
+ return 0
122
 
123
+ def fetch_menu_items(sf_connection, selected_category):
124
+ """Fetch and process menu items from Salesforce"""
125
+ try:
126
+ # Query for standard menu items
127
  menu_query = """
128
+ SELECT Id, Name, Price__c, Description__c, Image1__c, Image2__c,
129
+ Veg_NonVeg__c, Section__c, Total_Ordered__c, Video1__c,
130
+ Is_Available__c, Spice_Level__c, Preparation_Time__c
131
  FROM Menu_Item__c
132
+ WHERE Is_Available__c = true
133
  """
134
+ menu_result = sf_connection.query(menu_query)
135
+ food_items = menu_result.get('records', [])
136
+
137
+ # Query for custom dishes (last 7 days)
 
 
 
 
 
 
138
  custom_dish_query = """
139
+ SELECT Id, Name, Price__c, Description__c, Image1__c, Image2__c,
140
+ Veg_NonVeg__c, Section__c, Total_Ordered__c, Is_Available__c
141
  FROM Custom_Dish__c
142
+ WHERE CreatedDate >= LAST_N_DAYS:7 AND Is_Available__c = true
143
  """
144
+ custom_dish_result = sf_connection.query(custom_dish_query)
145
  custom_dishes = custom_dish_result.get('records', [])
 
 
 
 
 
 
 
 
 
 
 
 
 
146
 
147
+ # Process and merge items
148
+ all_items = []
149
+
150
+ for item in food_items + custom_dishes:
151
+ processed_item = {
152
+ 'id': item.get('Id'),
153
+ 'name': item.get('Name', 'Unnamed Item'),
154
+ 'price': item.get('Price__c', 0),
155
+ 'description': item.get('Description__c', 'No description available'),
156
+ 'image1': get_valid_media_path(item.get('Image1__c'), 'image'),
157
+ 'image2': get_valid_media_path(item.get('Image2__c'), 'image'),
158
+ 'video': get_valid_media_path(item.get('Video1__c'), 'video'),
159
+ 'veg_non_veg': item.get('Veg_NonVeg__c', 'Unknown'),
160
+ 'section': item.get('Section__c', 'Others'),
161
+ 'total_ordered': item.get('Total_Ordered__c', 0),
162
+ 'is_available': item.get('Is_Available__c', True),
163
+ 'spice_level': item.get('Spice_Level__c', 'Medium'),
164
+ 'prep_time': item.get('Preparation_Time__c', 20)
165
+ }
166
+
167
+ # Apply category filter
168
+ if selected_category == "Veg" and processed_item['veg_non_veg'] not in ["Veg", "both"]:
169
  continue
170
+ if selected_category == "Non veg" and processed_item['veg_non_veg'] not in ["Non veg", "both"]:
171
  continue
172
+
173
+ all_items.append(processed_item)
174
+
175
+ return all_items
176
+
177
+ except Exception as e:
178
+ logger.error(f"Error fetching menu items: {str(e)}")
179
+ return []
180
 
181
+ def organize_menu_items(items, selected_category):
182
+ """Organize menu items into sections"""
183
+ ordered_menu = {section: [] for section in SECTION_ORDER}
184
+ added_item_ids = set()
185
+
186
+ # Process best sellers
187
+ best_sellers = sorted(
188
+ [item for item in items if item['total_ordered'] > 0],
189
+ key=lambda x: x['total_ordered'],
190
+ reverse=True
191
+ )[:MAX_BEST_SELLERS]
192
+
193
+ if best_sellers:
194
+ ordered_menu["Best Sellers"] = best_sellers
195
+ added_item_ids.update(item['id'] for item in best_sellers)
196
+
197
+ # Organize other sections
198
+ for item in items:
199
+ if item['id'] in added_item_ids:
200
+ continue
201
+
202
+ section = item['section']
203
+ if section not in ordered_menu:
204
+ section = "Others" # Fallback section
205
+
206
+ ordered_menu[section].append(item)
207
+ added_item_ids.add(item['id'])
208
+
209
+ # Remove empty sections
210
+ return {section: items for section, items in ordered_menu.items() if items}
211
 
212
+ @menu_blueprint.route("/menu", methods=["GET"])
213
+ def menu():
214
+ # Validate session
215
+ user_email, first_letter, redirect_response = validate_user_session()
216
+ if redirect_response:
217
+ return redirect_response
218
+
219
+ selected_category = request.args.get("category", "All")
220
+
221
+ try:
222
+ # Get user details
223
+ user_details = get_user_details(sf, user_email)
224
+ if not user_details:
225
+ return redirect(url_for('login'))
226
+
227
+ # Get cart count
228
+ cart_item_count = get_cart_count(sf, user_email)
229
 
230
+ # Fetch and organize menu items
231
+ all_items = fetch_menu_items(sf, selected_category)
232
+ ordered_menu = organize_menu_items(all_items, selected_category)
233
+
234
+ # Prepare categories
235
  categories = ["All", "Veg", "Non veg"]
236
+
237
+ return render_template(
238
+ "menu.html",
239
+ ordered_menu=ordered_menu,
240
+ categories=categories,
241
+ selected_category=selected_category,
242
+ referral_code=user_details['referral_code'],
243
+ reward_points=user_details['reward_points'],
244
+ user_name=session.get('user_name'),
245
+ first_letter=first_letter,
246
+ cart_item_count=cart_item_count
247
+ )
248
+
249
+ except Exception as e:
250
+ logger.error(f"Error in menu route: {str(e)}")
251
+ # Fallback data
252
+ return render_template(
253
+ "menu.html",
254
+ ordered_menu={},
255
+ categories=["All", "Veg", "Non veg"],
256
+ selected_category=selected_category,
257
+ referral_code='N/A',
258
+ reward_points=0,
259
+ user_name=session.get('user_name'),
260
+ first_letter=first_letter,
261
+ cart_item_count=0,
262
+ error_message="We're experiencing technical difficulties. Please try again later."
263
+ )
264
 
265
  @menu_blueprint.route('/api/addons', methods=['GET'])
266
  def get_addons():
 
 
 
 
 
 
267
  try:
268
+ item_name = request.args.get('item_name', '').strip()
269
+ item_section = request.args.get('item_section', '').strip()
270
+
271
+ if not item_name or not item_section:
272
+ return jsonify({
273
+ "success": False,
274
+ "error": "Item name and section are required."
275
+ }), 400
276
+
277
+ # Query customization options
278
  query = f"""
279
+ SELECT Id, Name, Customization_Type__c, Options__c,
280
+ Max_Selections__c, Extra_Charge__c, Extra_Charge_Amount__c,
281
+ Is_Active__c
282
  FROM Customization_Options__c
283
  WHERE Section__c = '{item_section}'
284
+ AND Is_Active__c = true
285
+ ORDER BY Display_Order__c NULLS LAST
286
  """
287
  result = sf.query(query)
288
  addons = result.get('records', [])
289
+
290
  if not addons:
291
+ return jsonify({
292
+ "success": False,
293
+ "error": "No customization options found."
294
+ }), 404
295
+
296
+ # Format response
297
  formatted_addons = []
298
  for addon in addons:
299
  options = addon.get("Options__c", "")
300
+ options = [opt.strip() for opt in options.split(",")] if options else []
301
+
 
 
 
302
  formatted_addons.append({
303
+ "id": addon.get("Id"),
304
+ "name": addon.get("Name"),
305
+ "type": addon.get("Customization_Type__c", "checkbox"),
306
  "options": options,
307
  "max_selections": addon.get("Max_Selections__c", 1),
308
  "extra_charge": addon.get("Extra_Charge__c", False),
309
+ "extra_charge_amount": float(addon.get("Extra_Charge_Amount__c", 0))
310
  })
311
+
312
+ return jsonify({
313
+ "success": True,
314
+ "addons": formatted_addons
315
+ })
316
+
317
  except Exception as e:
318
+ logger.error(f"Error in get_addons: {str(e)}")
319
+ return jsonify({
320
+ "success": False,
321
+ "error": "An error occurred while fetching options."
322
+ }), 500
323
 
324
  @menu_blueprint.route('/cart/add', methods=['POST'])
325
  def add_to_cart():
326
  try:
327
+ # Validate session
328
+ if 'user_email' not in session:
329
+ return jsonify({
330
+ "success": False,
331
+ "error": "Authentication required."
332
+ }), 401
333
+
334
+ # Validate input
335
+ data = request.get_json()
336
+ if not data:
337
+ return jsonify({
338
+ "success": False,
339
+ "error": "Invalid JSON data."
340
+ }), 400
341
+
342
+ required_fields = ['itemName', 'itemPrice', 'itemImage', 'section']
343
+ for field in required_fields:
344
+ if field not in data or not data[field]:
345
+ return jsonify({
346
+ "success": False,
347
+ "error": f"Missing required field: {field}"
348
+ }), 400
349
+
350
+ # Prepare data
351
+ item_data = {
352
+ 'name': data['itemName'].strip(),
353
+ 'price': float(data['itemPrice']),
354
+ 'image': data['itemImage'].strip(),
355
+ 'section': data['section'].strip(),
356
+ 'category': data.get('category', ''),
357
+ 'addons': data.get('addons', []),
358
+ 'instructions': data.get('instructions', '').strip(),
359
+ 'quantity': int(data.get('quantity', 1)),
360
+ 'customer_email': session['user_email']
361
+ }
362
+
363
+ # Calculate addons
364
+ addons_price = sum(float(addon.get('price', 0)) for addon in item_data['addons'])
365
+ addons_string = "; ".join(
366
+ f"{addon.get('name', '')} (${addon.get('price', 0):.2f})"
367
+ for addon in item_data['addons']
368
+ ) if item_data['addons'] else "None"
369
+
370
+ total_price = (item_data['price'] * item_data['quantity']) + addons_price
371
+
372
+ # Check if item already exists in cart
373
  query = f"""
374
  SELECT Id, Quantity__c, Add_Ons__c, Add_Ons_Price__c, Instructions__c
375
  FROM Cart_Item__c
376
+ WHERE Customer_Email__c = '{item_data['customer_email']}'
377
+ AND Name = '{item_data['name']}'
378
+ LIMIT 1
379
  """
380
  result = sf.query(query)
381
+ existing_items = result.get('records', [])
382
+
383
+ if existing_items:
384
+ # Update existing item
385
+ existing_item = existing_items[0]
386
+ new_quantity = existing_item['Quantity__c'] + item_data['quantity']
387
+
388
+ # Merge addons
389
+ existing_addons = existing_item.get('Add_Ons__c', "None")
390
+ merged_addons = existing_addons if existing_addons == "None" else f"{existing_addons}; {addons_string}"
391
+
392
+ # Merge instructions
393
+ existing_instructions = existing_item.get('Instructions__c', "")
394
+ merged_instructions = existing_instructions if not item_data['instructions'] else \
395
+ f"{existing_instructions} | {item_data['instructions']}".strip(" | ")
396
+
397
+ # Update in Salesforce
398
+ sf.Cart_Item__c.update(existing_item['Id'], {
399
+ "Quantity__c": new_quantity,
400
+ "Add_Ons__c": merged_addons,
401
+ "Add_Ons_Price__c": addons_price + existing_item.get('Add_Ons_Price__c', 0),
402
+ "Instructions__c": merged_instructions,
403
+ "Price__c": total_price + existing_item.get('Price__c', 0)
 
 
 
 
 
 
 
 
 
 
404
  })
405
  else:
406
+ # Create new cart item
 
 
 
 
 
407
  sf.Cart_Item__c.create({
408
+ "Name": item_data['name'],
409
  "Price__c": total_price,
410
+ "Base_Price__c": item_data['price'],
411
+ "Quantity__c": item_data['quantity'],
412
  "Add_Ons_Price__c": addons_price,
413
  "Add_Ons__c": addons_string,
414
+ "Image1__c": item_data['image'],
415
+ "Customer_Email__c": item_data['customer_email'],
416
+ "Instructions__c": item_data['instructions'],
417
+ "Category__c": item_data['category'],
418
+ "Section__c": item_data['section']
419
  })
420
+
421
+ return jsonify({
422
+ "success": True,
423
+ "message": "Item added to cart successfully."
424
+ })
425
+
426
+ except ValueError as e:
427
+ logger.error(f"Value error in add_to_cart: {str(e)}")
428
+ return jsonify({
429
+ "success": False,
430
+ "error": "Invalid price or quantity format."
431
+ }), 400
432
+
433
  except Exception as e:
434
+ logger.error(f"Error in add_to_cart: {str(e)}")
435
+ return jsonify({
436
+ "success": False,
437
+ "error": "An error occurred while adding to cart."
438
+ }), 500