Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -2313,20 +2313,15 @@ async def process_incoming_message(from_number: str, msg: dict):
|
|
| 2313 |
current_menu='product_inquiry',
|
| 2314 |
current_menu_options=list(MENU_CONFIG['product_inquiry']['option_descriptions'].values())
|
| 2315 |
)
|
| 2316 |
-
await send_product_image_with_caption(from_number, selected_product, user_context
|
| 2317 |
else:
|
| 2318 |
send_whatsjet_message(from_number, get_menu_validation_message(current_state, user_context))
|
| 2319 |
elif current_state == 'all_products_menu':
|
| 2320 |
# Handle product selection from all products
|
| 2321 |
-
|
| 2322 |
-
|
| 2323 |
-
|
| 2324 |
-
|
| 2325 |
-
available_products = products_df.to_dict('records')
|
| 2326 |
-
|
| 2327 |
-
if available_products:
|
| 2328 |
-
if message_body.isdigit() and 1 <= int(message_body) <= len(available_products):
|
| 2329 |
-
selected_product = available_products[int(message_body) - 1]
|
| 2330 |
context_manager.update_context(
|
| 2331 |
from_number,
|
| 2332 |
current_product=selected_product,
|
|
@@ -2334,14 +2329,11 @@ async def process_incoming_message(from_number: str, msg: dict):
|
|
| 2334 |
current_menu='product_inquiry',
|
| 2335 |
current_menu_options=list(MENU_CONFIG['product_inquiry']['option_descriptions'].values())
|
| 2336 |
)
|
| 2337 |
-
await send_product_image_with_caption(from_number, selected_product, user_context
|
| 2338 |
-
return # Exit after handling product selection
|
| 2339 |
else:
|
| 2340 |
send_whatsjet_message(from_number, get_menu_validation_message(current_state, user_context))
|
| 2341 |
-
return # Exit after showing validation message
|
| 2342 |
else:
|
| 2343 |
send_whatsjet_message(from_number, "β No products available. Type 'main' to return to main menu.")
|
| 2344 |
-
return # Exit after showing error message
|
| 2345 |
elif current_state == 'product_inquiry':
|
| 2346 |
await handle_veterinary_product_followup(message_body, from_number)
|
| 2347 |
elif current_state == 'intelligent_products_menu':
|
|
@@ -2356,19 +2348,11 @@ async def process_incoming_message(from_number: str, msg: dict):
|
|
| 2356 |
current_menu='product_inquiry',
|
| 2357 |
current_menu_options=list(MENU_CONFIG['product_inquiry']['option_descriptions'].values())
|
| 2358 |
)
|
| 2359 |
-
await send_product_image_with_caption(from_number, selected_product, user_context
|
| 2360 |
return
|
| 2361 |
else:
|
| 2362 |
-
|
| 2363 |
-
|
| 2364 |
-
if products:
|
| 2365 |
-
logger.info(f"[Process] Invalid menu selection but product found: '{message_body}' -> Handling as product query")
|
| 2366 |
-
await handle_intelligent_product_inquiry(from_number, message_body, user_context, reply_language)
|
| 2367 |
-
return
|
| 2368 |
-
else:
|
| 2369 |
-
# Show menu validation message with guidance
|
| 2370 |
-
send_whatsjet_message(from_number, get_menu_validation_message(current_state, user_context))
|
| 2371 |
-
return
|
| 2372 |
return # Exit after handling menu selection
|
| 2373 |
|
| 2374 |
# π― PRIORITY 6: Product names - works from ANY menu state
|
|
@@ -2376,21 +2360,18 @@ async def process_incoming_message(from_number: str, msg: dict):
|
|
| 2376 |
logger.info(f"[Process] Checking for product name in message: '{message_body}' from state: {current_state}")
|
| 2377 |
products = get_veterinary_product_matches(message_body)
|
| 2378 |
|
| 2379 |
-
# ---
|
| 2380 |
normalized_input = normalize(message_body).lower().strip()
|
| 2381 |
exact_match = None
|
| 2382 |
-
|
| 2383 |
-
|
| 2384 |
-
|
| 2385 |
-
|
| 2386 |
-
|
| 2387 |
-
|
| 2388 |
-
|
| 2389 |
-
exact_match = row.to_dict()
|
| 2390 |
-
logger.info(f"[Process] Exact product name match found: {exact_match.get('Product Name', 'Unknown')}")
|
| 2391 |
-
break
|
| 2392 |
-
|
| 2393 |
if exact_match:
|
|
|
|
| 2394 |
context_manager.update_context(
|
| 2395 |
from_number,
|
| 2396 |
current_product=exact_match,
|
|
@@ -2399,7 +2380,7 @@ async def process_incoming_message(from_number: str, msg: dict):
|
|
| 2399 |
current_menu_options=list(MENU_CONFIG['product_inquiry']['option_descriptions'].values())
|
| 2400 |
)
|
| 2401 |
# Only send one reply: image+caption if possible, else text
|
| 2402 |
-
await send_product_image_with_caption(from_number, exact_match, user_context
|
| 2403 |
return
|
| 2404 |
|
| 2405 |
# --- END NEW LOGIC ---
|
|
@@ -2432,7 +2413,7 @@ async def process_incoming_message(from_number: str, msg: dict):
|
|
| 2432 |
current_menu='product_inquiry',
|
| 2433 |
current_menu_options=list(MENU_CONFIG['product_inquiry']['option_descriptions'].values())
|
| 2434 |
)
|
| 2435 |
-
await send_product_image_with_caption(from_number, selected_product, user_context
|
| 2436 |
return
|
| 2437 |
|
| 2438 |
# If it's a category/symptom search with multiple products, show all products
|
|
@@ -2443,9 +2424,37 @@ async def process_incoming_message(from_number: str, msg: dict):
|
|
| 2443 |
return
|
| 2444 |
|
| 2445 |
else:
|
| 2446 |
-
#
|
| 2447 |
-
|
| 2448 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2449 |
|
| 2450 |
except Exception as e:
|
| 2451 |
logger.error(f"Error in process_incoming_message: {e}")
|
|
|
|
| 2313 |
current_menu='product_inquiry',
|
| 2314 |
current_menu_options=list(MENU_CONFIG['product_inquiry']['option_descriptions'].values())
|
| 2315 |
)
|
| 2316 |
+
await send_product_image_with_caption(from_number, selected_product, user_context)
|
| 2317 |
else:
|
| 2318 |
send_whatsjet_message(from_number, get_menu_validation_message(current_state, user_context))
|
| 2319 |
elif current_state == 'all_products_menu':
|
| 2320 |
# Handle product selection from all products
|
| 2321 |
+
if products_df is not None and not products_df.empty:
|
| 2322 |
+
all_products = products_df.to_dict('records')
|
| 2323 |
+
if message_body.isdigit() and 1 <= int(message_body) <= len(all_products):
|
| 2324 |
+
selected_product = all_products[int(message_body) - 1]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2325 |
context_manager.update_context(
|
| 2326 |
from_number,
|
| 2327 |
current_product=selected_product,
|
|
|
|
| 2329 |
current_menu='product_inquiry',
|
| 2330 |
current_menu_options=list(MENU_CONFIG['product_inquiry']['option_descriptions'].values())
|
| 2331 |
)
|
| 2332 |
+
await send_product_image_with_caption(from_number, selected_product, user_context)
|
|
|
|
| 2333 |
else:
|
| 2334 |
send_whatsjet_message(from_number, get_menu_validation_message(current_state, user_context))
|
|
|
|
| 2335 |
else:
|
| 2336 |
send_whatsjet_message(from_number, "β No products available. Type 'main' to return to main menu.")
|
|
|
|
| 2337 |
elif current_state == 'product_inquiry':
|
| 2338 |
await handle_veterinary_product_followup(message_body, from_number)
|
| 2339 |
elif current_state == 'intelligent_products_menu':
|
|
|
|
| 2348 |
current_menu='product_inquiry',
|
| 2349 |
current_menu_options=list(MENU_CONFIG['product_inquiry']['option_descriptions'].values())
|
| 2350 |
)
|
| 2351 |
+
await send_product_image_with_caption(from_number, selected_product, user_context)
|
| 2352 |
return
|
| 2353 |
else:
|
| 2354 |
+
send_whatsjet_message(from_number, get_menu_validation_message(current_state, user_context))
|
| 2355 |
+
return
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2356 |
return # Exit after handling menu selection
|
| 2357 |
|
| 2358 |
# π― PRIORITY 6: Product names - works from ANY menu state
|
|
|
|
| 2360 |
logger.info(f"[Process] Checking for product name in message: '{message_body}' from state: {current_state}")
|
| 2361 |
products = get_veterinary_product_matches(message_body)
|
| 2362 |
|
| 2363 |
+
# --- NEW LOGIC: Check for exact match first ---
|
| 2364 |
normalized_input = normalize(message_body).lower().strip()
|
| 2365 |
exact_match = None
|
| 2366 |
+
for product in products:
|
| 2367 |
+
product_name = product.get('Product Name', '')
|
| 2368 |
+
normalized_product_name = normalize(product_name).lower().strip()
|
| 2369 |
+
if normalized_product_name == normalized_input:
|
| 2370 |
+
exact_match = product
|
| 2371 |
+
break
|
| 2372 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2373 |
if exact_match:
|
| 2374 |
+
logger.info(f"[Process] Exact product match found: {exact_match.get('Product Name', 'Unknown')}")
|
| 2375 |
context_manager.update_context(
|
| 2376 |
from_number,
|
| 2377 |
current_product=exact_match,
|
|
|
|
| 2380 |
current_menu_options=list(MENU_CONFIG['product_inquiry']['option_descriptions'].values())
|
| 2381 |
)
|
| 2382 |
# Only send one reply: image+caption if possible, else text
|
| 2383 |
+
await send_product_image_with_caption(from_number, exact_match, user_context)
|
| 2384 |
return
|
| 2385 |
|
| 2386 |
# --- END NEW LOGIC ---
|
|
|
|
| 2413 |
current_menu='product_inquiry',
|
| 2414 |
current_menu_options=list(MENU_CONFIG['product_inquiry']['option_descriptions'].values())
|
| 2415 |
)
|
| 2416 |
+
await send_product_image_with_caption(from_number, selected_product, user_context)
|
| 2417 |
return
|
| 2418 |
|
| 2419 |
# If it's a category/symptom search with multiple products, show all products
|
|
|
|
| 2424 |
return
|
| 2425 |
|
| 2426 |
else:
|
| 2427 |
+
# Enhanced "not found" response with veterinary suggestions
|
| 2428 |
+
message = (
|
| 2429 |
+
"β *Product Not Found*\n\n"
|
| 2430 |
+
f"π *We couldn't find '{message_body}' in our veterinary database.*\n\n"
|
| 2431 |
+
"π‘ *Try these alternatives:*\n"
|
| 2432 |
+
"β’ Check spelling (e.g., 'Hydropex' not 'Hydro pex')\n"
|
| 2433 |
+
"β’ Search by symptoms (e.g., 'respiratory', 'liver support')\n"
|
| 2434 |
+
"β’ Search by category (e.g., 'antibiotic', 'vitamin')\n"
|
| 2435 |
+
"β’ Search by species (e.g., 'poultry', 'livestock')\n\n"
|
| 2436 |
+
"π₯ *Popular Veterinary Products:*\n"
|
| 2437 |
+
"β’ Hydropex (Electrolyte supplement)\n"
|
| 2438 |
+
"β’ Heposel (Liver tonic)\n"
|
| 2439 |
+
"β’ Bromacid (Respiratory support)\n"
|
| 2440 |
+
"β’ Tribiotic (Antibiotic)\n"
|
| 2441 |
+
"β’ Symodex (Multivitamin)\n\n"
|
| 2442 |
+
"π¬ *Type 'main' to return to main menu or try another search.*"
|
| 2443 |
+
)
|
| 2444 |
+
|
| 2445 |
+
# Translate response if needed
|
| 2446 |
+
if reply_language == 'ur':
|
| 2447 |
+
try:
|
| 2448 |
+
translated_message = GoogleTranslator(source='auto', target='ur').translate(message)
|
| 2449 |
+
send_whatsjet_message(from_number, translated_message)
|
| 2450 |
+
except Exception as e:
|
| 2451 |
+
logger.error(f"[AI] Translation error: {e}")
|
| 2452 |
+
send_whatsjet_message(from_number, message)
|
| 2453 |
+
else:
|
| 2454 |
+
send_whatsjet_message(from_number, message)
|
| 2455 |
+
|
| 2456 |
+
# π― PRIORITY 5: Default: treat as general query with intelligent product inquiry
|
| 2457 |
+
await handle_intelligent_product_inquiry(from_number, message_body, user_context, reply_language)
|
| 2458 |
|
| 2459 |
except Exception as e:
|
| 2460 |
logger.error(f"Error in process_incoming_message: {e}")
|