Fred808 commited on
Commit
1f27208
·
verified ·
1 Parent(s): a8a5939

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +58 -42
app.py CHANGED
@@ -49,6 +49,7 @@ class Order(Base):
49
  price = Column(String, default="0")
50
  status = Column(String, default="Pending Payment")
51
  payment_reference = Column(String, nullable=True)
 
52
  timestamp = Column(DateTime, default=datetime.utcnow)
53
 
54
  class UserProfile(Base):
@@ -212,9 +213,10 @@ def stream_image_completion(image_b64: str):
212
  def process_order_flow(user_id: str, message: str) -> str:
213
  """
214
  Implements an FSM-based order flow that:
215
- - In step 1, expects the user to mention a dish name (optionally with quantity)
216
- - In step 2, asks for quantity if not provided
217
- - In step 3, finalizes the order and creates a payment link
 
218
  """
219
  # Retrieve or initialize conversation state
220
  state = user_state.get(user_id)
@@ -253,7 +255,6 @@ def process_order_flow(user_id: str, message: str) -> str:
253
  if dish.lower() in message.lower():
254
  found_dish = dish
255
  break
256
-
257
  numbers = re.findall(r'\d+', message)
258
  if found_dish:
259
  state.data["dish"] = found_dish
@@ -262,9 +263,11 @@ def process_order_flow(user_id: str, message: str) -> str:
262
  if quantity <= 0:
263
  return "Please enter a valid quantity (e.g., 1, 2, 3)."
264
  state.data["quantity"] = quantity
265
- state.step = 3 # ready to finalize the order
 
266
  else:
267
  state.step = 2 # ask for quantity
 
268
  else:
269
  return "I couldn't identify the dish. Please type the dish name from our menu."
270
 
@@ -278,44 +281,59 @@ def process_order_flow(user_id: str, message: str) -> str:
278
  return "Please enter a valid quantity (e.g., 1, 2, 3)."
279
  state.data["quantity"] = quantity
280
  state.step = 3
 
281
 
282
- # --- Step 3: Finalize Order ---
283
  if state.step == 3:
284
- order_id = f"ORD-{int(time.time())}"
285
- state.data["order_id"] = order_id
286
- price_per_serving = 1500 # fixed price per serving for demonstration
287
- quantity = state.data.get("quantity", 1)
288
- total_price = quantity * price_per_serving
289
- state.data["price"] = str(total_price)
290
-
291
- # Save the order asynchronously
292
- async def save_order():
293
- async with async_session() as session:
294
- order = Order(
295
- order_id=order_id,
296
- user_id=user_id,
297
- dish=state.data["dish"],
298
- quantity=str(quantity),
299
- price=str(total_price),
300
- status="Pending Payment"
301
- )
302
- session.add(order)
303
- await session.commit()
304
- asyncio.create_task(save_order())
305
-
306
- email = "[email protected]" # Placeholder; retrieve from profile if available
307
- payment_data = create_paystack_payment_link(email, total_price * 100, order_id)
308
- dish_name = state.data.get("dish", "")
309
- state.reset()
310
- if user_id in user_state:
311
- del user_state[user_id]
312
-
313
- if payment_data.get("status"):
314
- payment_link = payment_data["data"]["authorization_url"]
315
- return (f"Thank you for your order of {quantity} serving(s) of {dish_name}! "
316
- f"Your Order ID is {order_id}.\nPlease complete payment here: {payment_link}")
 
 
 
 
 
 
 
 
 
 
 
317
  else:
318
- return f"Your order has been placed with Order ID {order_id}, but we could not initialize payment. Please try again later."
 
 
 
319
 
320
  return ""
321
 
@@ -508,8 +526,6 @@ async def chatbot_response(request: Request, background_tasks: BackgroundTasks):
508
  return StreamingResponse(stream_response(), media_type="text/plain")
509
 
510
  # --- Other Endpoints (Chat History, Order Details, User Profile, Analytics, Voice, Payment Callback) ---
511
- # ... (Implement other endpoints as needed) ...
512
-
513
  @app.get("/chat_history/{user_id}")
514
  async def get_chat_history(user_id: str):
515
  async with async_session() as session:
 
49
  price = Column(String, default="0")
50
  status = Column(String, default="Pending Payment")
51
  payment_reference = Column(String, nullable=True)
52
+ delivery_address = Column(String, default="") # New field for address
53
  timestamp = Column(DateTime, default=datetime.utcnow)
54
 
55
  class UserProfile(Base):
 
213
  def process_order_flow(user_id: str, message: str) -> str:
214
  """
215
  Implements an FSM-based order flow that:
216
+ - Step 1: Expects the user to mention a dish name (optionally with quantity)
217
+ - Step 2: Asks for quantity if not provided
218
+ - Step 3: Requests the delivery address
219
+ - Step 4: Asks for order confirmation (yes/no) and finalizes the order
220
  """
221
  # Retrieve or initialize conversation state
222
  state = user_state.get(user_id)
 
255
  if dish.lower() in message.lower():
256
  found_dish = dish
257
  break
 
258
  numbers = re.findall(r'\d+', message)
259
  if found_dish:
260
  state.data["dish"] = found_dish
 
263
  if quantity <= 0:
264
  return "Please enter a valid quantity (e.g., 1, 2, 3)."
265
  state.data["quantity"] = quantity
266
+ state.step = 3 # move directly to address step
267
+ return f"You selected {found_dish} with {quantity} serving(s). Please provide your delivery address."
268
  else:
269
  state.step = 2 # ask for quantity
270
+ return f"You selected {found_dish}. How many servings would you like?"
271
  else:
272
  return "I couldn't identify the dish. Please type the dish name from our menu."
273
 
 
281
  return "Please enter a valid quantity (e.g., 1, 2, 3)."
282
  state.data["quantity"] = quantity
283
  state.step = 3
284
+ return f"Got it. {quantity} serving(s) of {state.data.get('dish')}. Now, please provide your delivery address."
285
 
286
+ # --- Step 3: Requesting Delivery Address ---
287
  if state.step == 3:
288
+ # Assume any text is a valid address
289
+ state.data["address"] = message
290
+ state.step = 4
291
+ return f"Thanks. Your delivery address is recorded as: {message}. Confirm order? (yes/no)"
292
+
293
+ # --- Step 4: Order Confirmation & Finalization ---
294
+ if state.step == 4:
295
+ if message.lower() in ["yes", "y"]:
296
+ order_id = f"ORD-{int(time.time())}"
297
+ state.data["order_id"] = order_id
298
+ price_per_serving = 1500 # fixed price per serving for demonstration
299
+ quantity = state.data.get("quantity", 1)
300
+ total_price = quantity * price_per_serving
301
+ state.data["price"] = str(total_price)
302
+
303
+ # Save the order asynchronously (including delivery_address)
304
+ async def save_order():
305
+ async with async_session() as session:
306
+ order = Order(
307
+ order_id=order_id,
308
+ user_id=user_id,
309
+ dish=state.data["dish"],
310
+ quantity=str(quantity),
311
+ price=str(total_price),
312
+ status="Pending Payment",
313
+ delivery_address=state.data.get("address", "")
314
+ )
315
+ session.add(order)
316
+ await session.commit()
317
+ asyncio.create_task(save_order())
318
+
319
+ email = "[email protected]" # Placeholder; retrieve from profile if available
320
+ payment_data = create_paystack_payment_link(email, total_price * 100, order_id)
321
+ dish_name = state.data.get("dish", "")
322
+ state.reset()
323
+ if user_id in user_state:
324
+ del user_state[user_id]
325
+ if payment_data.get("status"):
326
+ payment_link = payment_data["data"]["authorization_url"]
327
+ return (f"Thank you for your order of {quantity} serving(s) of {dish_name}! "
328
+ f"Your Order ID is {order_id}.\nPlease complete payment here: {payment_link}\n"
329
+ "You can track your order status using your Order ID.")
330
+ else:
331
+ return f"Your order has been placed with Order ID {order_id}, but we could not initialize payment. Please try again later."
332
  else:
333
+ state.reset()
334
+ if user_id in user_state:
335
+ del user_state[user_id]
336
+ return "Order canceled. Let me know if you'd like to try again."
337
 
338
  return ""
339
 
 
526
  return StreamingResponse(stream_response(), media_type="text/plain")
527
 
528
  # --- Other Endpoints (Chat History, Order Details, User Profile, Analytics, Voice, Payment Callback) ---
 
 
529
  @app.get("/chat_history/{user_id}")
530
  async def get_chat_history(user_id: str):
531
  async with async_session() as session: