ChatbotRAG / scenario_handlers /price_inquiry.py
minhvtt's picture
Upload 36 files
ffb5f88 verified
"""
Price Inquiry Scenario Handler
Helps users understand pricing and collects leads
"""
from typing import Dict, Any
from .base_handler import BaseScenarioHandler
class PriceInquiryHandler(BaseScenarioHandler):
"""
Handle price inquiry flow
Steps:
1. Ask which event
2. Ask group size (1 person vs group)
3. Show pricing info
4. Ask if want PDF via email
5. Collect email → Send PDF
6. Ask if want SMS reminder
7-8. Collect phone → Send SMS
"""
def start(self, initial_data: Dict = None) -> Dict[str, Any]:
"""Start price inquiry flow"""
return {
"message": "Hello 👋 Bạn muốn xem giá vé của show nào?",
"new_state": {
"active_scenario": "price_inquiry",
"scenario_step": 1,
"scenario_data": initial_data or {}
}
}
def next_step(self, current_step: int, user_input: str, scenario_data: Dict) -> Dict[str, Any]:
"""Process user input and advance scenario"""
expected_type = self._get_expected_type(current_step)
unexpected = self.handle_unexpected_input(user_input, expected_type, current_step)
if unexpected:
return unexpected
# STEP 1: Which event?
if current_step == 1:
scenario_data['event_name'] = user_input
return {
"message": "Bạn đi 1 mình hay đi nhóm?",
"new_state": {
"active_scenario": "price_inquiry",
"scenario_step": 2,
"scenario_data": scenario_data
},
"scenario_active": True
}
# STEP 2: Group size
elif current_step == 2:
group = self._detect_group_size(user_input)
scenario_data['group_size'] = group
event = scenario_data.get('event_name', 'event này')
# Show pricing based on group size
if group == 'single':
msg = f"Giá vé cho **{event}**:\n- Vé thường: 300k\n- Vé VIP: 500k"
else:
msg = f"Giá vé nhóm cho **{event}**:\n- Nhóm 3-5: 250k/người\n- Nhóm 6+: 200k/người"
return {
"message": msg + "\n\nBạn muốn mình gửi bảng giá chi tiết qua email không?",
"new_state": {
"active_scenario": "price_inquiry",
"scenario_step": 4, # Skip step 3
"scenario_data": scenario_data
},
"scenario_active": True
}
# STEP 4: Want PDF?
elif current_step == 4:
choice = self._detect_yes_no(user_input)
if choice == 'yes':
return {
"message": "Cho mình xin email để gửi PDF bảng giá nhé?",
"new_state": {
"active_scenario": "price_inquiry",
"scenario_step": 5,
"scenario_data": scenario_data
},
"scenario_active": True
}
else:
return {
"message": "Okie! Bạn cần tư vấn gì thêm không? 😊",
"new_state": None,
"scenario_active": False,
"end_scenario": True
}
# STEP 5: Collect email
elif current_step == 5:
email = user_input.strip()
if not self._validate_email(email):
return {
"message": "Email này có vẻ không đúng. Bạn nhập lại giúp mình nhé?",
"new_state": None,
"scenario_active": True
}
scenario_data['email'] = email
# Save lead
try:
self.lead_storage.save_lead(
event_name=scenario_data.get('event_name'),
email=email,
interests={"group": scenario_data.get('group_size'), "wants_pdf": True},
session_id=scenario_data.get('session_id')
)
print(f"📧 Lead saved: {email}")
except Exception as e:
print(f"⚠️ Error saving lead: {e}")
return {
"message": "Đã gửi PDF rồi nha 🎫\n\nBạn muốn nhận nhắc lịch qua SMS không?",
"new_state": {
"active_scenario": "price_inquiry",
"scenario_step": 6,
"scenario_data": scenario_data
},
"scenario_active": True,
"action": "send_pdf_email"
}
# STEP 6: Want SMS?
elif current_step == 6:
choice = self._detect_yes_no(user_input)
if choice == 'yes':
return {
"message": "Cho mình xin số điện thoại để gửi SMS nhắc lịch nhé?",
"new_state": {
"active_scenario": "price_inquiry",
"scenario_step": 8,
"scenario_data": scenario_data
},
"scenario_active": True
}
else:
return {
"message": "Okie! Cảm ơn bạn nha ✨",
"new_state": None,
"scenario_active": False,
"end_scenario": True
}
# STEP 8: Collect phone
elif current_step == 8:
phone = user_input.strip()
if not self._validate_phone(phone):
return {
"message": "Số điện thoại này có vẻ không đúng. Bạn nhập lại giúp mình nhé? (VD: 0901234567)",
"new_state": None,
"scenario_active": True
}
scenario_data['phone'] = phone
# Save lead with phone
try:
self.lead_storage.save_lead(
event_name=scenario_data.get('event_name'),
email=scenario_data.get('email'),
phone=phone,
interests={"group": scenario_data.get('group_size'), "wants_reminder": True},
session_id=scenario_data.get('session_id')
)
print(f"📱 Lead saved: {phone}")
except Exception as e:
print(f"⚠️ Error saving lead: {e}")
return {
"message": "Đã lưu rồi nha! Mình sẽ nhắc bạn trước show 1 ngày ✨",
"new_state": None,
"scenario_active": False,
"end_scenario": True,
"action": "save_lead_phone"
}
# Fallback
return {
"message": "Có lỗi xảy ra. Bạn muốn bắt đầu lại không?",
"new_state": None,
"scenario_active": False,
"end_scenario": True
}
def _get_expected_type(self, step: int) -> str:
"""Get expected input type for each step"""
type_map = {
1: 'event_name',
2: 'choice',
4: 'choice',
5: 'email',
6: 'choice',
8: 'phone'
}
return type_map.get(step, 'text')
def _detect_group_size(self, user_input: str) -> str:
"""Detect if single or group"""
input_lower = user_input.lower()
if any(k in input_lower for k in ['nhóm', 'group', 'team', 'mấy người', 'nhiều']):
return 'group'
else:
return 'single'
def _detect_yes_no(self, user_input: str) -> str:
"""Detect yes/no"""
input_lower = user_input.lower()
return 'yes' if any(k in input_lower for k in ['có', 'yes', 'ok', 'được', 'ừ']) else 'no'