from simple_salesforce import Salesforce #from your_salesforce_connection import sf # Assuming you have a salesforce connection setup import logging from flask import Flask, render_template_string, request, jsonify import speech_recognition as sr from tempfile import NamedTemporaryFile import os import ffmpeg from werkzeug.exceptions import BadRequest import re import requests import datetime # Import datetime for order date app = Flask(__name__) logging.basicConfig(level=logging.INFO) SALESFORCE_INSTANCE = "https://biryanihub-dev-ed.develop.my.salesforce.com" API_VERSION = "v59.0" # Salesforce connection setup sf = Salesforce( username='diggavalli98@gmail.com', password='Sati@1020', security_token='sSSjyhInIsUohKpG8sHzty2q', consumer_key='3MVG9WVXk15qiz1JbtW1tT9a7Wnkos2RuGamw6p1lC5uPescT5NB2nPygpo6rQ87K1T.zBEn.wR.A6JdgHnIU', consumer_secret='A75C6B7801D5D20BED0E46631CF58C4F7FF28E4DAF442FE667553D29C35C0451' ) AUTH_HEADERS = { "Authorization": f"Bearer {sf.session_id}", "Content-Type": "application/json" } # Global variables cart = [] # To store items, quantities, and prices MENU = {} current_category = None current_item = None awaiting_quantity = False # Initialize customer details to None to avoid errors if not filled yet customer_name = None customer_email = None customer_mobile = None # Fetching menu items dynamically from Salesforce def get_menu_items(): menu_items = {} query = "SELECT Name, Category__c, Price__c, Ingredients__c FROM Menu_Item__c" results = sf.query_all(query) for record in results['records']: category = record['Category__c'] item_name = record['Name'] price = record['Price__c'] # Replacing ₹ with $ to ensure dollar symbol is used price = price # if it's needed, convert price as needed if category not in menu_items: menu_items[category] = {} menu_items[category][item_name] = price return menu_items # Update global MENU variable MENU = get_menu_items() def find_customer_by_email(email): """Finds a customer by email in Salesforce.""" query = f"SELECT Id FROM Customer_Login__c WHERE Email__c = '{email}'" results = sf.query(query) if results["records"]: return results["records"][0]["Id"] # Return customer ID return None def extract_email(command): """Extracts an email address from a speech command.""" # Replace ' at ' with '@' for common speech-to-text variations command = command.replace(" at ", "@") # Use regex to find a valid email address match = re.search(r'[\w\.-]+@[\w\.-]+\.\w+', command) return match.group(0) if match else None def create_customer(email, name, phone): """Creates a new customer in Salesforce.""" customer_data = { "Email__c": email, "Name": name, "Phone_Number__c": phone } try: result = sf.Customer_Login__c.create(customer_data) return result["id"] # Return created Customer ID except Exception as e: print(f"Error creating customer: {e}") return None def create_order(email, total_amount): """Creates an order linked to the customer email in Salesforce with additional details.""" customer_id = find_customer_by_email(email) # Find customer by email if not customer_id: print(f"Customer with email {email} not found. Cannot create order.") return None # Ensure order_details is defined here order_details = "; ".join([f"{item} x{quantity} (${price * quantity})" for item, price, quantity in cart]) # Define order status (default to 'Pending') order_status = "Pending" # Get current date order_date = datetime.datetime.now().isoformat() # ISO format (YYYY-MM-DD) # Prepare the order data dictionary order_data = { "Customer__c": customer_id, # Link the order to the customer using Customer ID "Total_Amount__c": total_amount, # Total price of the order "Order_Date__c": order_date, # Date of the order "Order_Status__c": order_status, # Status of the order "Order_Details__c": order_details, # Ensure order_details is passed correctly "Customer_Email__c": customer_email, "Total_Bill__c":total_amount } try: result = sf.Order__c.create(order_data) # Create Order record in Salesforce print("Order successfully created!") return result["id"] # Return created order ID except Exception as e: print(f"Error creating order: {e}") return None def process_order(email, name, phone, total_amount): """Main function to process an order.""" customer_id = find_customer_by_email(email) if not customer_id: print("Email not found. Creating new customer...") customer_id = create_customer(email, name, phone) if customer_id: # Correct the call to create_order by passing only email and total_amount create_order(email, total_amount) else: print("Failed to process order. Could not create/find customer.") # HTML Template for Frontend html_code = """ AI Dining Assistant

AI Dining Assistant

Press the mic button to start...
""" @app.route("/") def index(): return render_template_string(html_code) def display_menu(): """Returns the available menu categories to the user.""" global MENU menu_text = "Here are the available categories: " categories = list(MENU.keys()) if categories: menu_text += ", ".join(categories) else: menu_text = "Sorry, the menu is unavailable at the moment." return menu_text @app.route("/process-audio", methods=["POST"]) def process_audio(): global current_category, current_item, awaiting_quantity, customer_name, customer_email, customer_mobile try: audio_file = request.files.get("audio") if not audio_file: raise BadRequest("No audio file provided.") temp_file = NamedTemporaryFile(delete=False, suffix=".webm") audio_file.save(temp_file.name) if os.path.getsize(temp_file.name) == 0: raise BadRequest("Uploaded audio file is empty.") converted_file = NamedTemporaryFile(delete=False, suffix=".wav") ffmpeg.input(temp_file.name).output( converted_file.name, acodec="pcm_s16le", ac=1, ar="16000" ).run(overwrite_output=True) recognizer = sr.Recognizer() with sr.AudioFile(converted_file.name) as source: audio_data = recognizer.record(source) try: command = recognizer.recognize_google(audio_data) logging.info(f"Recognized command: {command}") response = process_command(command) except sr.UnknownValueError: response = "Sorry, I couldn't understand your command. Could you please repeat?" except sr.RequestError as e: response = f"Error with the speech recognition service: {e}" return jsonify({"response": response}) except BadRequest as br: return jsonify({"response": f"Bad Request: {str(br)}"}), 400 except Exception as e: return jsonify({"response": f"An error occurred: {str(e)}"}), 500 finally: if os.path.exists(temp_file.name): os.unlink(temp_file.name) if os.path.exists(converted_file.name): os.unlink(converted_file.name) # Global function to store the order in Salesforce (line item creation) def store_order_in_salesforce(cart, total_amount, name, email, phone): """Stores an order in Salesforce along with the line items.""" customer_id = find_customer_by_email(email) if not customer_id: customer_id = create_customer(email, name, phone) if not customer_id: return "Error: Unable to create customer in Salesforce." # Create the order and store the details in the Order object order_id = create_order(email, total_amount) # This function now creates the order and saves details to the Order object if order_id: # After creating the order, now add line items for each cart item (without Order_Details__c in order line) for item, price, quantity in cart: # Create an Order Line Item without the Order_Details__c order_data = { "Order__c": order_id, # Link the order to the Order Line Item "Customer_Name__c": customer_name, # Use name instead of customer_name "Customer_Email__c": customer_email,# Email "Order_Details__c": order_details, # Order_details (fixed) "Quantity__c": quantity, # Quantity ordered "Unit_Price__c": price, # Price per unit "Total_Amount__c": price * quantity, # Total price for this item "Customer2__c": customer_id, # Ensure this is valid, maybe replace with customer_id "Total_Bill__c": total_amount, "Order_Status__c": "Pending", # Fixed order_status } try: sf.Order_Line_Item__c.create(order_line_data) # Create Order Line Item in Salesforce logging.info(f"Order Line Item for {item} created successfully!") except Exception as e: logging.error(f"Error creating order line item for {item}: {e}") return "Order placed successfully with line items!" else: return "There was an error processing your order." # Function to extract mobile number from the command def extract_mobile_number(command): """Extracts mobile number using regex.""" match = re.search(r'\b\d{10}\b', command) # Looks for a 10-digit number return match.group(0) if match else None def extract_quantity(command): match = re.search(r'\b\d+\b', command) # Look for numbers in the command return int(match.group(0)) if match else None # Return an integer or None # Extract quantity from command (e.g., "two" -> 2, "three" -> 3, etc.) def extract_quantity(command): number_words = { "one": 1, "two": 2, "three": 3, "four": 4, "five": 5, "six": 6, "seven": 7, "eight": 8, "nine": 9, "ten": 10, "1": 1, "2": 2, "3": 3, "4": 4, "5": 5, "6": 6, "7": 7, "8": 8, "9": 9, "10": 10 } command_words = command.split() for word in command_words: if word in number_words: return number_words[word] return None # Main logic to process the command # This is the function that processes the commands, make sure the logic is inside it def process_command(command): global cart, MENU, current_category, current_item, awaiting_quantity, customer_name, customer_email, customer_mobile command = command.lower().strip() logging.debug(f"Command received: {command}") # Handle name input if "my name is" in command: customer_name = command.replace("my name is", "").strip() if not customer_email: return f"Thanks, {customer_name}. Can you please provide your email address?" elif not customer_mobile: return f"Got it! Can you provide your mobile number?" return f"Thanks, {customer_name}. How can I assist you further?" # Handle email input if "my email is" in command: email = extract_email(command) if email: customer_email = email if not customer_name: return "Thanks! Can you also provide your name?" elif not customer_mobile: return "Got it! Can you provide your mobile number?" return f"Thanks! Your email is {customer_email}. How can I assist you further?" return "Sorry, I couldn't detect a valid email. Please try again." # Handle mobile number input if "my mobile number is" in command or customer_mobile is None: mobile_number = extract_mobile_number(command) if mobile_number: customer_mobile = mobile_number if not customer_name: return "Thanks! Can you also provide your name?" elif not customer_email: return "Got it! Can you provide your email address?" return f"Got your mobile number: {customer_mobile}. How can I assist you further?" elif "my mobile number is" in command: return "Sorry, I couldn't detect a valid mobile number. Please try again." # Handle menu request if "menu" in command or "yes" in command or "yeah" in command: return display_menu() # Handle category selection for category, items in MENU.items(): if category.lower() in command: current_category = category item_list = ", ".join([f"{item} (${price})" for item, price in items.items()]) return f"You're in the {category} category. We have: {item_list}. What would you like to order?" # Handle item selection after category selection if current_category: for item in MENU[current_category].keys(): if item.lower() in command: current_item = item awaiting_quantity = True return f"How many quantities of {current_item} would you like?" # Handle quantity input if awaiting_quantity: quantity = extract_quantity(command) # Extract quantity from command if quantity is not None: cart.append((current_item, MENU[current_category][current_item], quantity)) awaiting_quantity = False total = sum(i[1] * i[2] for i in cart) cart_summary = ", ".join([f"{i[0]} x{i[2]} (${i[1] * i[2]})" for i in cart]) return f"Added {quantity} x {current_item} to your cart. Your current cart: {cart_summary}. Total: ${total}. Would you like to add more items?" else: return "Sorry, I couldn't understand the quantity. Please provide a valid quantity." # Handle final order if "final order" in command or "submit" in command or "proceed" in command or "place the order" in command: if not customer_name: return "Can you please provide your name? You can say, 'My name is [your name]'" if not customer_email: return "Can you please provide your email? You can say, 'My email is [your email]'" if not customer_mobile: return "Can you please provide your mobile number? You can say, 'My mobile is [your number]'" if cart: total = sum(item[1] * item[2] for item in cart) store_response = store_order_in_salesforce(cart, total, customer_name, customer_email, customer_mobile) cart.clear() # Ensure cart is cleared after final order return f"Your final order has been placed successfully! Total price: ${total}. {store_response}" else: return "Your cart is empty. Please add items before placing the final order." return "Sorry, I didn't understand that. Please try again." if __name__ == "__main__": app.run(host="0.0.0.0", port=7860)