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']
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
# Format order details from the cart
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 # Itemized order details
}
try:
result = sf.Order__c.create(order_data)
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...
Response will appear here...
"""
@app.route("/")
def index():
return render_template_string(html_code)
def display_menu():
"""Returns the available menu categories and items 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."
# Update the item listing to use $ instead of ₹
for category, items in MENU.items():
item_list = ", ".join([f"{item} (${price})" for item, price in items.items()])
menu_text += f"\nIn {category}: {item_list}"
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
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."
# Define order_details
order_details = "; ".join([f"{item} x{quantity} (₹{price * quantity})" for item, price, quantity in cart])
# Create the order
order_id = create_order(email, total_amount)
if order_id:
# After creating the order, now add line items for each cart item
for item, price, quantity in cart:
# Create an Order Line Item
order_line_data = {
"Order__c": order_id, # Link the order
"Customer_Name__c": name, # Use name instead of customer_name
"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
"Total_Bill__c": total_amount,
"Order_Status__c": "Pending", # Fixed order_status
"Customer2__c": customer_id # Ensure this is valid, maybe replace with customer_id
}
try:
sf.Order_Line_Item__c.create(order_line_data)
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):
"""Processes the command to extract user details, place orders, and interact with the user."""
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
# Ensure we display the prices with $ symbol
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
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)