Spaces:
Sleeping
Sleeping
File size: 7,015 Bytes
b386adb b45e10b b386adb fd3f251 b2176ab fd3f251 a2e44f6 5c415f6 a2e44f6 5c415f6 b386adb fd3f251 e013f86 b386adb b45e10b b386adb fd3f251 a2e44f6 b386adb b45e10b b386adb b45e10b fd3f251 e013f86 1fda108 b45e10b 1fda108 fd3f251 e013f86 b45e10b b386adb fd3f251 1fda108 b45e10b f47805a fd3f251 b45e10b fd3f251 b45e10b fd3f251 b45e10b a2e44f6 fd3f251 b45e10b b386adb b45e10b a2e44f6 b386adb b45e10b b386adb b45e10b a2e44f6 b386adb a2e44f6 1fda108 b45e10b 1fda108 b45e10b a2e44f6 2084298 b45e10b 2084298 b45e10b f47805a b45e10b | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 | import sqlite3
import datetime
import json
import os
import random # <--- Thêm thư viện này để random dữ liệu
# --- CẤU HÌNH ĐƯỜNG DẪN TUYỆT ĐỐI ---
# Lấy thư mục chứa file database.py hiện tại
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
# Tạo đường dẫn file DB nằm ngay tại thư mục này
DB_PATH = os.path.join(BASE_DIR, "vnpt_call_center.db")
print(f"[DB SYSTEM] Database file path: {DB_PATH}")
# --- HÀM SINH DỮ LIỆU MẪU THÔNG MINH (DYNAMIC DATE) ---
def generate_seed_data():
data = []
now = datetime.datetime.now()
# Tạo 20 cuộc gọi mẫu
for i in range(20):
# 12 cuộc gọi cho ngày HÔM NAY (Để Dashboard nhảy số ngay)
if i < 12:
minutes_ago = random.randint(5, 700) # Cách đây vài phút đến vài tiếng
call_time = now - datetime.timedelta(minutes=minutes_ago)
else:
# 8 cuộc gọi còn lại cho TUẦN NÀY (Cách đây 1-6 ngày)
days_ago = random.randint(1, 6)
call_time = now - datetime.timedelta(days=days_ago)
timestamp_str = call_time.isoformat()
# Random chỉ số để biểu đồ đẹp
intent = random.choice(["network_issue", "cancel_package", "competitor", "low_data"])
# Logic giả lập cảm xúc theo intent
if intent == "cancel_package":
sentiment = "negative"
csat = random.randint(1, 3)
elif intent == "competitor":
sentiment = "neutral"
csat = random.randint(3, 4)
else:
sentiment = "positive"
csat = 5
item = {
"customer_id": f"CUS_{i+1:03d}",
"call_id": f"SEED_{i+1}",
"call_timestamp": timestamp_str,
"call_duration_seconds": random.randint(60, 300),
"intent": intent,
"sentiment": sentiment,
"ai_resolved": random.choice([True, True, False]), # Tỉ lệ True cao hơn
"upsell_success": random.choice([True, False, False]),
"csat": csat,
"cost_per_call_vnd": random.randint(1500, 5000)
}
data.append(item)
return data
class Database:
def __init__(self):
self.conn = None
self._init_db()
def _get_conn(self):
# SỬA LỖI: Dùng DB_PATH tuyệt đối
return sqlite3.connect(DB_PATH, check_same_thread=False)
def _init_db(self):
conn = self._get_conn()
cursor = conn.cursor()
# Tạo bảng nếu chưa có
cursor.execute('''
CREATE TABLE IF NOT EXISTS calls (
id INTEGER PRIMARY KEY AUTOINCREMENT,
customer_id TEXT,
call_id TEXT,
call_timestamp DATETIME,
duration INTEGER,
intent TEXT,
sentiment TEXT,
ai_resolved BOOLEAN,
upsell BOOLEAN,
csat INTEGER,
cost INTEGER
)
''')
# Kiểm tra dữ liệu
cursor.execute("SELECT count(*) FROM calls")
count = cursor.fetchone()[0]
if count == 0:
print(" [DB] Database trống. Đang nạp 20 bản ghi mẫu cho HÔM NAY...")
# Gọi hàm sinh dữ liệu động thay vì dùng list tĩnh
seed_data = generate_seed_data()
self._seed_data(cursor, seed_data)
conn.commit()
conn.close()
def _seed_data(self, cursor, data):
for item in data:
cursor.execute('''
INSERT INTO calls (customer_id, call_id, call_timestamp, duration, intent, sentiment, ai_resolved, upsell, csat, cost)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
''', (
item['customer_id'],
item['call_id'],
item['call_timestamp'],
item['call_duration_seconds'],
item['intent'],
item['sentiment'],
item['ai_resolved'],
item['upsell_success'],
item['csat'],
item['cost_per_call_vnd']
))
# --- HÀM THÊM MỚI (Logic giữ nguyên) ---
def add_call(self, customer_id, duration, intent, sentiment, ai_resolved, upsell, cost):
conn = self._get_conn()
cursor = conn.cursor()
call_id = f"LIVE_{int(datetime.datetime.now().timestamp())}"
timestamp = datetime.datetime.now().isoformat()
# Xử lý cost dictionary
cost_val = cost['value'] if isinstance(cost, dict) else cost
csat_val = cost['csat'] if isinstance(cost, dict) else 4
cursor.execute('''
INSERT INTO calls (customer_id, call_id, call_timestamp, duration, intent, sentiment, ai_resolved, upsell, csat, cost)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
''', (customer_id, call_id, timestamp, duration, intent, sentiment, ai_resolved, upsell, csat_val, cost_val))
conn.commit()
conn.close()
# --- HÀM CẬP NHẬT ĐÁNH GIÁ SAO (Logic giữ nguyên) ---
def update_call_rating(self, customer_id, stars, note):
conn = self._get_conn()
cursor = conn.cursor()
try:
cursor.execute('''
SELECT id FROM calls
WHERE customer_id = ?
ORDER BY id DESC
LIMIT 1
''', (str(customer_id),))
row = cursor.fetchone()
if row:
call_id_db = row[0]
cursor.execute('UPDATE calls SET csat = ? WHERE id = ?', (int(stars), call_id_db))
conn.commit()
print(f" [DB] Đã cập nhật CSAT={stars} cho khách {customer_id}")
else:
print(f" [DB] Không tìm thấy cuộc gọi nào của khách {customer_id} để update.")
except Exception as e:
print(f" [DB Error] Update Rating: {e}")
finally:
conn.close()
# --- HÀM LẤY DỮ LIỆU CHO DASHBOARD (Sửa key trả về cho khớp Frontend) ---
def get_all_calls(self):
conn = self._get_conn()
cursor = conn.cursor()
cursor.execute("SELECT * FROM calls ORDER BY call_timestamp DESC")
rows = cursor.fetchall()
result = []
for r in rows:
result.append({
"id": r[1], # customer_id
"time": r[3], # call_timestamp
"dur": r[4], # duration
"intent": r[5],
"sent": r[6],
"ai": bool(r[7]),
"upsell": bool(r[8]),
"csat": r[9],
"cost": r[10]
})
conn.close()
return result
# Khởi tạo singleton
db = Database() |