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()