hf_rabbit_life_poc / app_p /handler /customer_data_handler.py
SUMANA SUMANAKUL (ING)
first commit
30adccc
raw
history blame
10.7 kB
import pandas as pd
import json
import re
from pathlib import Path
# --- Data Loading ---
try:
print("Loading data for CustomerDataHandler module...")
PROJECT_ROOT = Path(__file__).resolve().parent.parent.parent # หา Path ของ Root Directory
DATA_PATH = PROJECT_ROOT / "data"
CONFIG_PATH = PROJECT_ROOT / "config"
# customer df
CUSTOMER_DF = pd.read_csv(DATA_PATH / "mock_customer_data.csv")
COLUMN_MAP_DF = pd.read_csv(DATA_PATH / "column_mapping.csv")
COLUMN_MAP_DICT = pd.Series(COLUMN_MAP_DF.Description.values, index=COLUMN_MAP_DF.Field_name).to_dict() # dict mapping
# persona json
# ABSOLUTE_PATH_TO_CONFIG = '/Users/jts-ai-sumana/rabbitlife_gemini/config/personas.json'
# with open(ABSOLUTE_PATH_TO_CONFIG, "r", encoding="utf-8") as f:
with open(CONFIG_PATH / "personas.json", "r", encoding="utf-8") as f:
PERSONAS = json.load(f)
print("✅ Customer data, mapping, and personas loaded successfully.")
except Exception as e:
print(f"‼️ ERROR: Could not load data/config files for CustomerDataHandler: {e}")
CUSTOMER_DF = pd.DataFrame()
COLUMN_MAP_DICT = {}
PERSONAS = {}
# map ชื่อ: ประเภท
PLAN_NAME_TO_TYPE_MAP = {
"Smart Term Bronze 5": "ประกันคุ้มครองชีวิต", "Smart Term Bronze 10": "ประกันคุ้มครองชีวิต",
"Chai Leoy 99/20": "ประกันคุ้มครองชีวิต", "Chai Leoy 99/10": "ประกันคุ้มครองชีวิต",
"Chai Leoy 99/5": "ประกันคุ้มครองชีวิต", "High Protect 3/3": "ประกันคุ้มครองชีวิต",
"Smart Wellness 90/15": "ประกันคุ้มครองชีวิต", "Save 5 C": "ประกันคุ้มครองชีวิต",
"Sabai Jai 14/5": "ประกันเพื่อการลงทุน", "Jai Jai 25/9": "ประกันเพื่อการลงทุน",
"Protection Plus 18/9": "ประกันเพื่อการลงทุน", "Jai Jai 12/6": "ประกันเพื่อการลงทุน",
"Jai Jai 15/6": "ประกันเพื่อการลงทุน",
"Health Protect (สัญญาเพิ่มเติมสุขภาพค่ารักษาพยาบาล)": "ประกันสุขภาพ", "Health Smile": "ประกันสุขภาพ",
"Worry Free Cancer (สัญญาเพิ่มเติมคุ้มครองโรคมะเร็ง)": "ประกันสุขภาพ", "Worry Free 50 Critical Illness": "ประกันสุขภาพ",
"Rider HIB 365 (สัญญาเพิ่มเติมสุขภาพค่าชดเชยรายวัน)": "ประกันสุขภาพ",
"PA Max (สัญญาเพิ่มเติมสุขภาพค่ารักษาผู้ป่วยนอก)": "ประกันสุขภาพ", "PA Prompt (สัญญาเพิ่มเติมสุขภาพค่ารักษาผู้ป่วยนอก)": "ประกันสุขภาพ",
"สัญญาเพิ่มเติมยกเว้นเบี้ยประกันภัย": "ประกันสุขภาพ", "OPD": "ประกันสุขภาพ", "Mental Health": "ประกันสุขภาพ",
"PA Max (อุบัติเหตุส่วนบุคคล)": "ประกันอุบัติเหตุ", "PA Prompt (อุบัติเหตุส่วนบุคคล)": "ประกันอุบัติเหตุ",
"Rider ADD (สัญญาเพิ่มเติมอุบัติเหตุ)": "ประกันอุบัติเหตุ", "Rider AI (สัญญาเพิ่มเติมอุบัติเหตุ)": "ประกันอุบัติเหตุ",
"Rider ADB (สัญญาเพิ่มเติมอุบัติเหตุ)": "ประกันอุบัติเหตุ",
"PA Max (สัญญาเพิ่มเติมสุขภาพค่ารักษาเนื่องจากอุบัติเหตุ)": "ประกันอุบัติเหตุ", "PA Prompt (สัญญาเพิ่มเติมสุขภาพค่ารักษาเนื่องจากอุบัติเหตุ)": "ประกันอุบัติเหตุ",
"Rider ADB and ADD(สัญญาเพิ่มเติมอุบัติเหตุ)": "ประกันอุบัติเหตุ"
}
# --- Utilize Fuctions ---
def clean_name(name):
if not isinstance(name, str): return ""
return re.sub(r'\s*\(.*\)\s*', '', name).strip()
def find_customer_data(identifier: str) -> pd.DataFrame | None:
"""
return df
"""
if CUSTOMER_DF.empty:
return None
identifier = str(identifier).strip()
# ลองค้นหาด้วยเลขบัตรประชาชนก่อน
numeric_identifier = re.sub(r'\D', '', identifier)
if len(numeric_identifier) == 13:
result_df = CUSTOMER_DF[CUSTOMER_DF['insured_id_number'] == int(numeric_identifier)]
if not result_df.empty:
return result_df
# ถ้าไม่เจอ ลองค้นหาด้วยชื่อ-นามสกุล
name_parts = identifier.split()
if len(name_parts) >= 2:
firstname, lastname = name_parts[0], " ".join(name_parts[1:])
result_df = CUSTOMER_DF[(CUSTOMER_DF['insured_firstname'] == firstname) & (CUSTOMER_DF['insured_lastname'] == lastname)]
if not result_df.empty:
return result_df
return None
def translate_and_format_data(customer_df: pd.DataFrame) -> str:
"""
เลือกคอลัมน์ที่ต้องการ --> แปลชื่อคอลัมน์เป็นภาษาไทย --> และแปลงเป็น JSON string
"""
columns_to_show = [
'policy_no', 'policy_plan_name', 'plan_type', 'total_premium', 'policy_status',
'policy_effective_date', 'premium_duedate', 'policy_maturity_date', 'sum_insured_first'
]
existing_columns = [col for col in columns_to_show if col in customer_df.columns]
df_to_format = customer_df[existing_columns].copy()
df_to_format.rename(columns=COLUMN_MAP_DICT, inplace=True)
return df_to_format.to_json(orient='records', force_ascii=False, indent=2)
def find_recommendation_gaps(customer_df: pd.DataFrame) -> list:
"""
วิเคราะห์ข้อมูลกรมธรรม์ของลูกค้าเพื่อหาผลิตภัณฑ์ที่น่าแนะนำเพิ่มเติม (Gap Analysis)
โดยพิจารณาจาก Age และ Salary
"""
# print("[Gap Analysis] Starting analysis for existing customer...")
if customer_df.empty or not PERSONAS:
return []
try:
customer_info = customer_df.iloc[0]
age = customer_info.get('insured_age_latest')
gender = str(customer_info.get('insured_gender', '')).upper()
salary = customer_info.get('insured_salary', 0)
if age is None or not gender:
# print("[Gap Analysis] Missing age or gender. Cannot perform analysis.")
return []
# print(f"[Gap Analysis] Analyzing profile: Age={age}, Gender='{gender}', Salary={salary}")
# หา Persona
matched_persona = next((details for _, details in PERSONAS.items() if details.get("age_min", -1) <= age <= details.get("age_max", -1)), None)
if not matched_persona:
return []
# หา Tier จากเงินเดือน
products_from_tier = []
salary_tiers = matched_persona.get('recommendations_by_salary', [])
for tier in salary_tiers:
if tier.get("salary_min", 0) <= salary <= tier.get("salary_max", float('inf')):
products_from_tier = tier.get("products", [])
break
if not products_from_tier and salary_tiers:
products_from_tier = salary_tiers[0].get("products", [])
# ดึงลิสต์ผลิตภัณฑ์ที่ ideal จาก Tier และ เพศ
ideal_products = [p for p in products_from_tier if p.get('gender') == 'all' or p.get('gender') == gender]
# ดึงลิสต์ผลิตภัณฑ์ที่ "มีอยู่แล้ว" และทำความสะอาดชื่อ
existing_products_raw = set(customer_df['policy_plan_name'].unique())
existing_products_names = {clean_name(name) for name in existing_products_raw}
# หา Gaps
gaps = []
for ideal_product in ideal_products:
ideal_product_name_clean = clean_name(ideal_product.get('product_name', ''))
if ideal_product_name_clean not in existing_products_names:
gaps.append(ideal_product)
gaps.sort(key=lambda x: ('Rider' not in x.get('product_category', '')), reverse=False)
# print(f"[Gap Analysis] Found {len(gaps)} potential products to recommend.")
return gaps
except Exception as e:
print(f"‼️ ERROR during Gap Analysis: {e}")
import traceback
traceback.print_exc()
return []
def generate_upsell_text_from_gaps(gaps: list) -> str:
"""สร้างประโยค Upsell สั้นๆ จาก Gap ที่หาเจอ"""
if gaps:
main_recommendation = gaps[0]
return (f"\n\nจากข้อมูลความคุ้มครองปัจจุบัน สังเกตว่าแผนประกันของท่านจะครอบคลุมยิ่งขึ้น "
f"หากมีสัญญาเพิ่มเติม **{main_recommendation['product_name']}** "
f"ซึ่งจะช่วยดูแลในเรื่อง{main_recommendation.get('product_description', 'ความคุ้มครองเพิ่มเติม')}ค่ะ"
f"\n\nสนใจรับข้อมูลเพิ่มเติมเกี่ยวกับแผนนี้ไหมคะ")
return ""