File size: 14,108 Bytes
b346555
 
bc9d7e8
b346555
68752b9
03b3d1d
c636403
 
c89ca6c
03b3d1d
 
b346555
03b3d1d
1804064
 
03b3d1d
c89ca6c
c636403
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bc9d7e8
 
 
c636403
b346555
 
c636403
 
 
 
 
 
dcbb9df
c636403
 
 
 
 
 
dcbb9df
c636403
dcbb9df
 
 
c636403
 
 
 
 
 
 
 
bc9d7e8
 
c636403
 
 
 
 
 
42407ae
c636403
42407ae
b346555
68752b9
42407ae
68752b9
 
1804064
 
be1fa6a
 
1804064
c636403
be1fa6a
1804064
be1fa6a
 
bc9d7e8
be1fa6a
0957e29
be1fa6a
0957e29
 
1804064
bc9d7e8
 
 
 
 
42407ae
0957e29
42407ae
0957e29
 
 
42407ae
c636403
42407ae
0957e29
 
1804064
0957e29
 
 
42407ae
 
c636403
42407ae
bc9d7e8
42407ae
bc9d7e8
42407ae
bc9d7e8
42407ae
bc9d7e8
42407ae
bc9d7e8
42407ae
0957e29
42407ae
0957e29
bc9d7e8
42407ae
 
bc9d7e8
c636403
 
42407ae
0957e29
bc9d7e8
 
 
 
 
 
 
 
 
c636403
 
 
 
 
 
 
 
 
 
 
bc9d7e8
c636403
 
bc9d7e8
1804064
bc9d7e8
 
 
 
 
 
 
 
 
 
 
 
 
 
c636403
1804064
 
bc9d7e8
 
c636403
 
 
 
 
 
bc9d7e8
 
c636403
bc9d7e8
c636403
 
 
 
 
 
1804064
 
c636403
 
 
 
 
 
 
 
 
 
 
 
 
 
1804064
 
0957e29
b346555
 
0957e29
590c33f
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
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
import gradio as gr
from graph_manager import user_input_handler
from nodes import session_form_data, get_form_info, set_form_info
import ast
import uuid
import logging
import sqlite3
import pandas as pd
import os
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

def generate_session_id():
    session_id = str(uuid.uuid4())
    return session_id, f"Session ID: {session_id}"

DB_PATH = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'database', 'hello_earth_data_2.db')

def connect_db():
    return sqlite3.connect(DB_PATH)

def fetch_df(query, params=None):
    with connect_db() as conn:
        return pd.read_sql_query(query, conn, params=params or ())

def get_deliverable_data():
    return fetch_df("SELECT * FROM Deliverable")

def get_deliverable_titles():
    df = get_deliverable_data()
    return ['None'] + df['title'].dropna().tolist()

def save_expense_to_db(form_info_dict):
    deliverable_df = get_deliverable_data()
    title_to_id = dict(zip(deliverable_df['title'], deliverable_df['deliverable_id']))

    associated_title = form_info_dict.get("Associated Deliverable", "None")
    associated_id = title_to_id.get(associated_title, None)
    if associated_id is None:
        logger.warning(f"No matching deliverable ID found for title: {associated_title}")
        return False

    expense_id = str(uuid.uuid4())
    seller_name = form_info_dict.get("Seller Name")
    seller_address = form_info_dict.get("Seller Address")
    seller_phone_number = form_info_dict.get("Seller Phone Number")
    buyer_name = form_info_dict.get("Buyer Name")
    buyer_address = form_info_dict.get("Buyer Address")
    raw_date = form_info_dict.get("Transaction Date")
    transaction_date = pd.to_datetime(raw_date).date().isoformat() if raw_date else None
    total_payment_amount = form_info_dict.get("Total Payment Amount")
    expense_description = form_info_dict.get("Expense Description")
    status = "approved"

    insert_query = """
        INSERT INTO Expense (
            expense_id, associated_deliverable_id, seller_name, seller_address, seller_phone_number,
            buyer_name, buyer_address, transaction_date, total_payment_amount, expense_description, status
        ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
    """
    with connect_db() as conn:
        cursor = conn.cursor()
        cursor.execute(insert_query, (
            expense_id, associated_id, seller_name, seller_address, seller_phone_number,
            buyer_name, buyer_address, transaction_date, total_payment_amount, expense_description, status
        ))
        conn.commit()
    logger.info(f"Expense saved: {expense_id}")
    return True

def is_form_complete(form_info_dict):
    required_keys = [
        "Associated Deliverable", "Seller Name", "Seller Address", "Seller Phone Number",
        "Buyer Name", "Buyer Address", "Transaction Date", "Total Payment Amount", "Expense Description"
    ]
    for key in required_keys:
        value = form_info_dict.get(key)
        if not value or value == "None":
            return gr.update(interactive=False)
    return gr.update(interactive=True)

def update_field_input(key):
    def inner(session_id, value):
        set_form_info(session_id, key, value)
        return get_form_info(session_id)
    return inner

def update_form_information_handler(form_information):
    valid_titles = get_deliverable_titles()
    target_deliverable = form_information.get("Associated Deliverable")
    target_deliverable = target_deliverable if target_deliverable in valid_titles else "None"
    
    def clean(val):
        return None if val == "None" else val

    seller_name_input = clean(form_information.get("Seller Name"))
    seller_address_input = clean(form_information.get("Seller Address"))
    seller_phone_number_input = clean(form_information.get("Seller Phone Number"))
    buyer_name_input = clean(form_information.get("Buyer Name"))
    buyer_address_input = clean(form_information.get("Buyer Address"))
    transaction_date_input = clean(form_information.get("Transaction Date"))

    total_payment_amount_input = form_information.get("Total Payment Amount")
    if total_payment_amount_input and total_payment_amount_input != "None":
        total_payment_amount_input = float(total_payment_amount_input)

    expense_description_input = clean(form_information.get("Expense Description"))

    return (
        target_deliverable, seller_name_input, seller_address_input, seller_phone_number_input,
        buyer_name_input, buyer_address_input, transaction_date_input,
        total_payment_amount_input, expense_description_input
    )

def handle_submit(session_id):
    form_data = get_form_info(session_id)
    required_fields = [
        "Associated Deliverable", "Seller Name", "Seller Address", "Seller Phone Number",
        "Buyer Name", "Buyer Address", "Transaction Date", "Total Payment Amount", "Expense Description"
    ]
    for field in required_fields:
        if not form_data.get(field) or form_data.get(field) == "None":
            return gr.update(value="❌ กรุณากรอกข้อมูลในทุกช่องให้ครบถ้วน", visible=True)
    save_expense_to_db(form_data)
    return gr.update(value="✅ บันทึกค่าใช้จ่ายเรียบร้อยแล้ว", visible=True)

_chat_prefill = [
    {"role": "assistant", "content": "สวัสดีค่ะ ดิฉันชื่อ เอมมี่ ค่ะ ยินดีช่วยคุณเรื่องการนำส่งรายการค่าใช้จ่ายค่ะ คุณสามารถเริ่มต้นด้วยการอัพโหลดรูปภาพของบิล 1 รูปค่ะ"}
]

def chat_handler(message,history,session_id):
    # global CURRENT_SESSION_ID
    logger.info(f"Received message: {message}")
    if len(message['files']) > 0:
        response = user_input_handler(str(message['files'][0]), session_id)
    elif message['text'] != "":
        try:
            response = user_input_handler(message['text'], session_id)
        except Exception as e:
            raise e
    form_information = get_form_info(session_id)
    update_form_information_handler(form_information)
    return response, form_information

def create_expense_register_page():
    with gr.Blocks() as page:
        session_id = gr.State("")
        form_information = gr.State({})

        with gr.Row():
            session_id_display = gr.Markdown("Session ID: Loading...")

        new_btn = gr.Button("เริ่มใหม่", variant="primary")
        with gr.Tabs():
            with gr.Tab("แชท"):
                chat_interface = gr.ChatInterface(
                    fn=chat_handler,
                    type="messages",
                    chatbot=gr.Chatbot(value=_chat_prefill, type="messages", label="กล่องข้อความ"),
                    multimodal=True,
                    submit_btn="ส่งข้อความ",
                    autofocus=True,
                    examples=None,
                    additional_inputs=[session_id],
                    additional_outputs=[form_information]
                )

            with gr.Tab("ฟอร์ม"):
                gr.Markdown("**การส่งมอบงาน**")
                deliverable_dropdown = gr.Dropdown(choices=get_deliverable_titles(), filterable=False, container=False)
                gr.Markdown("**ชื่อผู้ขาย**")
                seller_name_input = gr.Textbox(value=ast.literal_eval(session_form_data[session_id]["Seller Name"]), label="", container=False)
                gr.Markdown("**ที่อยู่ผู้ขาย**")
                seller_address_input = gr.Textbox(value=ast.literal_eval(session_form_data[session_id]["Seller Address"]), label="", container=False)
                gr.Markdown("**เบอร์โทรศัพท์ผู้ขาย**")
                seller_phone_number_input = gr.Textbox(value=ast.literal_eval(session_form_data[session_id]["Seller Phone Number"]), label="", container=False)
                gr.Markdown("**ชื่อผู้ซื้อ**")
                buyer_name_input = gr.Textbox(value=ast.literal_eval(session_form_data[session_id]["Buyer Name"]), label="", container=False)
                gr.Markdown("**ที่อยู่ผู้ซื้อ**")
                buyer_address_input = gr.Textbox(value=ast.literal_eval(session_form_data[session_id]["Buyer Address"]), label="", container=False)
                gr.Markdown("**วันที่ทำรายการ**")
                transaction_date_input = gr.DateTime(include_time=False, type="datetime", show_label=False)
                gr.Markdown("**ยอดชำระเงินทั้งหมด**")
                with gr.Row():
                    total_payment_amount_input = gr.Number(value=ast.literal_eval(session_form_data[session_id]['Total Payment Amount']), label="", container=False)
                    gr.Markdown("บาท")
                gr.Markdown("**คำอธิบายค่าใช้จ่าย**")
                expense_description_input = gr.Textbox(value=ast.literal_eval(session_form_data[session_id]["Expense Description"]), label="", container=False, lines=4)
                
                feedback_message = gr.Markdown("", visible=False)
                submit_btn = gr.Button("บันทึกค่าใช้จ่าย", variant="primary")

                deliverable_dropdown.change(update_field_input("Associated Deliverable"), inputs=[session_id, deliverable_dropdown], outputs=[form_information],queue=False)
                seller_name_input.change(update_field_input("Seller Name"), inputs=[session_id, seller_name_input], outputs=[form_information],queue=False)
                seller_address_input.change(update_field_input("Seller Address"), inputs=[session_id, seller_address_input], outputs=[form_information],queue=False)
                seller_phone_number_input.change(update_field_input("Seller Phone Number"), inputs=[session_id, seller_phone_number_input], outputs=[form_information],queue=False)
                buyer_name_input.change(update_field_input("Buyer Name"), inputs=[session_id, buyer_name_input], outputs=[form_information],queue=False)
                buyer_address_input.change(update_field_input("Buyer Address"), inputs=[session_id, buyer_address_input], outputs=[form_information],queue=False)
                transaction_date_input.change(update_field_input("Transaction Date"), inputs=[session_id, transaction_date_input], outputs=[form_information],queue=False)
                total_payment_amount_input.change(update_field_input("Total Payment Amount"), inputs=[session_id, total_payment_amount_input], outputs=[form_information],queue=False)
                expense_description_input.change(update_field_input("Expense Description"), inputs=[session_id, expense_description_input], outputs=[form_information],queue=False)

                form_information.change(
                    update_form_information_handler,
                    inputs=[form_information],
                    outputs=[
                        deliverable_dropdown, seller_name_input, seller_address_input, seller_phone_number_input,
                        buyer_name_input, buyer_address_input, transaction_date_input,
                        total_payment_amount_input, expense_description_input,
                    ],
                    queue=False,
                )
                submit_btn.click(fn=handle_submit, inputs=[session_id], outputs=[feedback_message])

        def reset_chat():
            new_session_id, new_session_id_display = generate_session_id()
            logger.info(f"Chat reset with new session ID: {new_session_id}")

            # Reset the state dictionary for the new session
            session_form_data[new_session_id] = {
                "Associated Deliverable": "None",
                "Seller Name": "",
                "Seller Address": "",
                "Seller Phone Number": "",
                "Buyer Name": "",
                "Buyer Address": "",
                "Transaction Date": None,
                "Total Payment Amount": None,
                "Expense Description": "",
            }

            return (
                new_session_id,
                new_session_id_display,
                _chat_prefill,
                session_form_data[new_session_id],  # return the new form state
                "None",             # deliverable_dropdown
                "",                 # seller_name_input
                "",                 # seller_address_input
                "",                 # seller_phone_number_input
                "",                 # buyer_name_input
                "",                 # buyer_address_input
                None,               # transaction_date_input
                None,               # total_payment_amount_input
                "",                 # expense_description_input
                gr.update(visible=False, value="")  # feedback_message
            )
        
        new_btn.click(
            fn=reset_chat,
            inputs=[],
            outputs=[
                session_id,
                session_id_display,
                chat_interface.chatbot_value,
                form_information,
                deliverable_dropdown,
                seller_name_input,
                seller_address_input,
                seller_phone_number_input,
                buyer_name_input,
                buyer_address_input,
                transaction_date_input,
                total_payment_amount_input,
                expense_description_input,
                feedback_message
            ],
        )

        page.load(generate_session_id, outputs=[session_id, session_id_display])
    return page

if __name__ == "__main__":
    page = create_expense_register_page()
    page.launch()