Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -3,7 +3,6 @@ import sqlite3
|
|
| 3 |
import os
|
| 4 |
import datetime
|
| 5 |
import random
|
| 6 |
-
import json
|
| 7 |
|
| 8 |
DB_FILE = "cases.db"
|
| 9 |
|
|
@@ -14,37 +13,46 @@ def init_db():
|
|
| 14 |
conn = sqlite3.connect(DB_FILE)
|
| 15 |
c = conn.cursor()
|
| 16 |
|
| 17 |
-
#
|
| 18 |
c.execute("""CREATE TABLE IF NOT EXISTS summons_cases (
|
| 19 |
case_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
| 20 |
citizen_name TEXT,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 21 |
offence_en TEXT,
|
| 22 |
offence_bm TEXT,
|
| 23 |
offence_cn TEXT,
|
| 24 |
fine_amount REAL,
|
| 25 |
-
status TEXT
|
| 26 |
-
evidence_files TEXT
|
| 27 |
)""")
|
| 28 |
|
|
|
|
| 29 |
c.execute("""CREATE TABLE IF NOT EXISTS appeals (
|
| 30 |
appeal_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
| 31 |
case_id INTEGER,
|
| 32 |
appeal_text TEXT,
|
| 33 |
-
evidence_file TEXT,
|
| 34 |
target TEXT,
|
| 35 |
created_at TEXT
|
| 36 |
)""")
|
| 37 |
|
|
|
|
| 38 |
c.execute("""CREATE TABLE IF NOT EXISTS reviews (
|
| 39 |
review_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
| 40 |
case_id INTEGER,
|
| 41 |
reviewer TEXT,
|
| 42 |
decision TEXT,
|
| 43 |
-
|
|
|
|
|
|
|
| 44 |
reduced_fine REAL,
|
| 45 |
created_at TEXT
|
| 46 |
)""")
|
| 47 |
|
|
|
|
| 48 |
c.execute("""CREATE TABLE IF NOT EXISTS payments (
|
| 49 |
payment_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
| 50 |
case_id INTEGER,
|
|
@@ -52,6 +60,7 @@ def init_db():
|
|
| 52 |
paid_at TEXT
|
| 53 |
)""")
|
| 54 |
|
|
|
|
| 55 |
c.execute("""CREATE TABLE IF NOT EXISTS receipts (
|
| 56 |
receipt_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
| 57 |
payment_id INTEGER,
|
|
@@ -59,27 +68,6 @@ def init_db():
|
|
| 59 |
issued_at TEXT
|
| 60 |
)""")
|
| 61 |
|
| 62 |
-
c.execute("""CREATE TABLE IF NOT EXISTS audit_logs (
|
| 63 |
-
log_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
| 64 |
-
case_id INTEGER,
|
| 65 |
-
actor TEXT,
|
| 66 |
-
action TEXT,
|
| 67 |
-
log_text TEXT,
|
| 68 |
-
created_at TEXT
|
| 69 |
-
)""")
|
| 70 |
-
|
| 71 |
-
# Seed mock data if empty
|
| 72 |
-
c.execute("SELECT COUNT(*) FROM summons_cases")
|
| 73 |
-
if c.fetchone()[0] == 0:
|
| 74 |
-
cases = [
|
| 75 |
-
("Ali", "Not obeying correct lane", "Tidak mematuhi lorong yang betul", "未按规定车道行驶", 300.0, "ISSUED"),
|
| 76 |
-
("Ah Kow", "Running a red light", "Melanggar lampu merah", "闯红灯", 250.0, "APPEAL_PENDING"),
|
| 77 |
-
("Muthu", "Illegal parking", "Letak kereta haram", "非法停车", 100.0, "APPEAL_APPROVED_REDUCED"),
|
| 78 |
-
]
|
| 79 |
-
c.executemany(
|
| 80 |
-
"INSERT INTO summons_cases (citizen_name, offence_en, offence_bm, offence_cn, fine_amount, status) VALUES (?,?,?,?,?,?)",
|
| 81 |
-
cases
|
| 82 |
-
)
|
| 83 |
conn.commit()
|
| 84 |
conn.close()
|
| 85 |
|
|
@@ -88,113 +76,47 @@ init_db()
|
|
| 88 |
# ----------------------
|
| 89 |
# Helpers
|
| 90 |
# ----------------------
|
| 91 |
-
def
|
| 92 |
-
conn = sqlite3.connect(DB_FILE)
|
| 93 |
-
c = conn.cursor()
|
| 94 |
-
c.execute(
|
| 95 |
-
"INSERT INTO audit_logs (case_id, actor, action, log_text, created_at) VALUES (?,?,?,?,?)",
|
| 96 |
-
(case_id, actor, action, log_text, datetime.datetime.now().isoformat())
|
| 97 |
-
)
|
| 98 |
-
conn.commit()
|
| 99 |
-
conn.close()
|
| 100 |
-
|
| 101 |
-
def autonomous_pdrm_decision(case_id):
|
| 102 |
-
"""Auto-decide compound fine appeals using rules"""
|
| 103 |
-
conn = sqlite3.connect(DB_FILE)
|
| 104 |
-
c = conn.cursor()
|
| 105 |
-
c.execute("SELECT fine_amount FROM summons_cases WHERE case_id=?", (case_id,))
|
| 106 |
-
row = c.fetchone()
|
| 107 |
-
if not row:
|
| 108 |
-
conn.close()
|
| 109 |
-
return None
|
| 110 |
-
fine = row[0]
|
| 111 |
-
|
| 112 |
-
# Rules: simple example
|
| 113 |
-
if fine > 200:
|
| 114 |
-
decision = "ApproveReduced"
|
| 115 |
-
reduced_fine = fine * 0.5
|
| 116 |
-
rationale = "Pengurangan denda automatik: kesalahan ringan."
|
| 117 |
-
else:
|
| 118 |
-
decision = "Reject"
|
| 119 |
-
reduced_fine = None
|
| 120 |
-
rationale = "Permohonan ditolak automatik: denda rendah."
|
| 121 |
-
|
| 122 |
-
# Save review
|
| 123 |
-
c.execute(
|
| 124 |
-
"INSERT INTO reviews (case_id, reviewer, decision, rationale, reduced_fine, created_at) VALUES (?,?,?,?,?,?)",
|
| 125 |
-
(case_id, "PDRM-AI", decision, rationale, reduced_fine, datetime.datetime.now().isoformat())
|
| 126 |
-
)
|
| 127 |
-
new_status = "APPEAL_APPROVED_REDUCED" if decision == "ApproveReduced" else "APPEAL_REJECTED"
|
| 128 |
-
c.execute("UPDATE summons_cases SET status=?, fine_amount=? WHERE case_id=?", (new_status, reduced_fine if reduced_fine else fine, case_id))
|
| 129 |
-
conn.commit()
|
| 130 |
-
conn.close()
|
| 131 |
-
|
| 132 |
-
log_text = f"PDRM-AI membuat keputusan: {decision}, sebab: {rationale}"
|
| 133 |
-
log_action(case_id, "PDRM-AI", "auto_review", log_text)
|
| 134 |
-
return decision, rationale, reduced_fine
|
| 135 |
-
|
| 136 |
-
def autonomous_magistrate_decision(case_id):
|
| 137 |
-
"""AI-assisted magistrate review"""
|
| 138 |
conn = sqlite3.connect(DB_FILE)
|
| 139 |
c = conn.cursor()
|
| 140 |
-
c.execute("SELECT fine_amount FROM summons_cases WHERE case_id=?", (case_id,))
|
| 141 |
-
row = c.fetchone()
|
| 142 |
-
if not row:
|
| 143 |
-
conn.close()
|
| 144 |
-
return None
|
| 145 |
-
fine = row[0]
|
| 146 |
-
|
| 147 |
-
# Rules: small fines often waived, medium fines reduced, high fines rejected
|
| 148 |
-
if fine <= 100:
|
| 149 |
-
decision = "ApproveNoFine"
|
| 150 |
-
reduced_fine = 0
|
| 151 |
-
rationale = "Kesalahan kecil, denda dihapuskan automatik."
|
| 152 |
-
elif fine <= 250:
|
| 153 |
-
decision = "ApproveReduced"
|
| 154 |
-
reduced_fine = fine * 0.5
|
| 155 |
-
rationale = "Kesalahan sederhana, denda dikurangkan automatik."
|
| 156 |
-
else:
|
| 157 |
-
decision = "Reject"
|
| 158 |
-
reduced_fine = None
|
| 159 |
-
rationale = "Kesalahan serius, rayuan ditolak automatik."
|
| 160 |
-
|
| 161 |
-
# Save review
|
| 162 |
c.execute(
|
| 163 |
-
"INSERT INTO
|
| 164 |
-
(
|
|
|
|
|
|
|
| 165 |
)
|
| 166 |
-
new_status = "APPEAL_APPROVED_REDUCED" if decision == "ApproveReduced" else \
|
| 167 |
-
"APPEAL_APPROVED_NOFINE" if decision == "ApproveNoFine" else \
|
| 168 |
-
"APPEAL_REJECTED"
|
| 169 |
-
c.execute("UPDATE summons_cases SET status=?, fine_amount=? WHERE case_id=?", (new_status, reduced_fine if reduced_fine else fine, case_id))
|
| 170 |
conn.commit()
|
| 171 |
conn.close()
|
|
|
|
| 172 |
|
| 173 |
-
log_text = f"Magistrate-AI decision: {decision}, reason: {rationale}"
|
| 174 |
-
log_action(case_id, "Magistrate-AI", "auto_review", log_text)
|
| 175 |
-
return decision, rationale, reduced_fine
|
| 176 |
-
|
| 177 |
-
# ----------------------
|
| 178 |
-
# Citizen Portal
|
| 179 |
-
# ----------------------
|
| 180 |
def view_case(case_id):
|
| 181 |
conn = sqlite3.connect(DB_FILE)
|
| 182 |
c = conn.cursor()
|
| 183 |
-
c.execute("SELECT
|
| 184 |
row = c.fetchone()
|
| 185 |
conn.close()
|
| 186 |
if not row:
|
| 187 |
return "❌ Case not found."
|
| 188 |
-
|
| 189 |
-
|
| 190 |
-
|
| 191 |
-
|
| 192 |
-
|
| 193 |
-
Offence (EN): {offence_en}
|
| 194 |
-
Kesalahan (BM): {offence_bm}
|
| 195 |
-
违法 (中文): {offence_cn}
|
| 196 |
|
| 197 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 198 |
📌 Status: {status}
|
| 199 |
"""
|
| 200 |
|
|
@@ -208,15 +130,20 @@ def submit_appeal(case_id, appeal_text, target):
|
|
| 208 |
c.execute("UPDATE summons_cases SET status=? WHERE case_id=?", ("APPEAL_PENDING", case_id))
|
| 209 |
conn.commit()
|
| 210 |
conn.close()
|
| 211 |
-
|
| 212 |
-
|
| 213 |
-
|
| 214 |
-
|
| 215 |
-
|
| 216 |
-
|
| 217 |
-
|
| 218 |
-
|
| 219 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 220 |
|
| 221 |
def pay_fine(case_id):
|
| 222 |
conn = sqlite3.connect(DB_FILE)
|
|
@@ -235,30 +162,57 @@ def pay_fine(case_id):
|
|
| 235 |
c.execute("UPDATE summons_cases SET status=? WHERE case_id=?", ("PAID", case_id))
|
| 236 |
conn.commit()
|
| 237 |
conn.close()
|
| 238 |
-
|
| 239 |
-
return f"
|
|
|
|
|
|
|
|
|
|
|
|
|
| 240 |
|
| 241 |
# ----------------------
|
| 242 |
-
# Gradio
|
| 243 |
# ----------------------
|
| 244 |
with gr.Blocks() as demo:
|
| 245 |
-
gr.Markdown("# 🚦 SwiftCase.ai – Citizen Portal (
|
| 246 |
-
|
| 247 |
-
|
| 248 |
-
|
| 249 |
-
|
| 250 |
-
|
| 251 |
-
|
| 252 |
-
|
| 253 |
-
|
| 254 |
-
|
| 255 |
-
|
| 256 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 257 |
appeal_btn.click(fn=submit_appeal, inputs=[appeal_case_id, appeal_text, appeal_target], outputs=appeal_out)
|
| 258 |
-
|
| 259 |
-
|
| 260 |
-
|
| 261 |
-
|
|
|
|
| 262 |
pay_btn.click(fn=pay_fine, inputs=pay_case_id, outputs=pay_out)
|
| 263 |
|
| 264 |
if __name__ == "__main__":
|
|
@@ -274,3 +228,4 @@ if __name__ == "__main__":
|
|
| 274 |
|
| 275 |
|
| 276 |
|
|
|
|
|
|
| 3 |
import os
|
| 4 |
import datetime
|
| 5 |
import random
|
|
|
|
| 6 |
|
| 7 |
DB_FILE = "cases.db"
|
| 8 |
|
|
|
|
| 13 |
conn = sqlite3.connect(DB_FILE)
|
| 14 |
c = conn.cursor()
|
| 15 |
|
| 16 |
+
# Summons table with full details
|
| 17 |
c.execute("""CREATE TABLE IF NOT EXISTS summons_cases (
|
| 18 |
case_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
| 19 |
citizen_name TEXT,
|
| 20 |
+
address TEXT,
|
| 21 |
+
ticket_number TEXT,
|
| 22 |
+
vehicle_number TEXT,
|
| 23 |
+
road_name TEXT,
|
| 24 |
+
town_city TEXT,
|
| 25 |
+
state TEXT,
|
| 26 |
offence_en TEXT,
|
| 27 |
offence_bm TEXT,
|
| 28 |
offence_cn TEXT,
|
| 29 |
fine_amount REAL,
|
| 30 |
+
status TEXT
|
|
|
|
| 31 |
)""")
|
| 32 |
|
| 33 |
+
# Appeals
|
| 34 |
c.execute("""CREATE TABLE IF NOT EXISTS appeals (
|
| 35 |
appeal_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
| 36 |
case_id INTEGER,
|
| 37 |
appeal_text TEXT,
|
|
|
|
| 38 |
target TEXT,
|
| 39 |
created_at TEXT
|
| 40 |
)""")
|
| 41 |
|
| 42 |
+
# Reviews (AI or human)
|
| 43 |
c.execute("""CREATE TABLE IF NOT EXISTS reviews (
|
| 44 |
review_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
| 45 |
case_id INTEGER,
|
| 46 |
reviewer TEXT,
|
| 47 |
decision TEXT,
|
| 48 |
+
rationale_en TEXT,
|
| 49 |
+
rationale_bm TEXT,
|
| 50 |
+
rationale_cn TEXT,
|
| 51 |
reduced_fine REAL,
|
| 52 |
created_at TEXT
|
| 53 |
)""")
|
| 54 |
|
| 55 |
+
# Payments
|
| 56 |
c.execute("""CREATE TABLE IF NOT EXISTS payments (
|
| 57 |
payment_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
| 58 |
case_id INTEGER,
|
|
|
|
| 60 |
paid_at TEXT
|
| 61 |
)""")
|
| 62 |
|
| 63 |
+
# Receipts
|
| 64 |
c.execute("""CREATE TABLE IF NOT EXISTS receipts (
|
| 65 |
receipt_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
| 66 |
payment_id INTEGER,
|
|
|
|
| 68 |
issued_at TEXT
|
| 69 |
)""")
|
| 70 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 71 |
conn.commit()
|
| 72 |
conn.close()
|
| 73 |
|
|
|
|
| 76 |
# ----------------------
|
| 77 |
# Helpers
|
| 78 |
# ----------------------
|
| 79 |
+
def insert_case(name, address, ticket_number, vehicle, road, town, state, offence_en, offence_bm, offence_cn, fine):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 80 |
conn = sqlite3.connect(DB_FILE)
|
| 81 |
c = conn.cursor()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 82 |
c.execute(
|
| 83 |
+
"""INSERT INTO summons_cases
|
| 84 |
+
(citizen_name, address, ticket_number, vehicle_number, road_name, town_city, state, offence_en, offence_bm, offence_cn, fine_amount, status)
|
| 85 |
+
VALUES (?,?,?,?,?,?,?,?,?,?,?,?)""",
|
| 86 |
+
(name, address, ticket_number, vehicle, road, town, state, offence_en, offence_bm, offence_cn, fine, "ISSUED")
|
| 87 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
| 88 |
conn.commit()
|
| 89 |
conn.close()
|
| 90 |
+
return "✅ Summons case created successfully."
|
| 91 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 92 |
def view_case(case_id):
|
| 93 |
conn = sqlite3.connect(DB_FILE)
|
| 94 |
c = conn.cursor()
|
| 95 |
+
c.execute("SELECT * FROM summons_cases WHERE case_id=?", (case_id,))
|
| 96 |
row = c.fetchone()
|
| 97 |
conn.close()
|
| 98 |
if not row:
|
| 99 |
return "❌ Case not found."
|
| 100 |
+
(
|
| 101 |
+
case_id, citizen_name, address, ticket_number, vehicle, road, town, state,
|
| 102 |
+
offence_en, offence_bm, offence_cn, fine, status
|
| 103 |
+
) = row
|
|
|
|
|
|
|
|
|
|
|
|
|
| 104 |
|
| 105 |
+
return f"""
|
| 106 |
+
🆔 Case ID / Nombor Kes / 案件编号: {case_id}
|
| 107 |
+
👤 Name / Nama / 姓名: {citizen_name}
|
| 108 |
+
🏠 Address / Alamat / 地址: {address}
|
| 109 |
+
📄 Ticket No. / Nombor Saman / 罚单号码: {ticket_number}
|
| 110 |
+
🚗 Vehicle No. / Nombor Kenderaan / 车牌号码: {vehicle}
|
| 111 |
+
🛣 Road / Jalan / 道路: {road}
|
| 112 |
+
🏙 Town/City / Bandar / 城市: {town}
|
| 113 |
+
🗺 State / Negeri / 州: {state}
|
| 114 |
+
|
| 115 |
+
⚖️ Offence (EN): {offence_en}
|
| 116 |
+
⚖️ Kesalahan (BM): {offence_bm}
|
| 117 |
+
⚖️ 违法 (中文): {offence_cn}
|
| 118 |
+
|
| 119 |
+
💰 Fine / Denda / 罚款: RM {fine:.2f}
|
| 120 |
📌 Status: {status}
|
| 121 |
"""
|
| 122 |
|
|
|
|
| 130 |
c.execute("UPDATE summons_cases SET status=? WHERE case_id=?", ("APPEAL_PENDING", case_id))
|
| 131 |
conn.commit()
|
| 132 |
conn.close()
|
| 133 |
+
|
| 134 |
+
# Generate AI recommendation text
|
| 135 |
+
rationale_en = "AI suggests reducing fine due to mitigating factors."
|
| 136 |
+
rationale_bm = "AI mencadangkan pengurangan denda kerana faktor meringankan."
|
| 137 |
+
rationale_cn = "人工智能建议减轻罚款,因为有减轻因素。"
|
| 138 |
+
|
| 139 |
+
return f"""
|
| 140 |
+
✅ Appeal Submitted / Rayuan Dihantar / 上诉已提交
|
| 141 |
+
📌 Target: {target}
|
| 142 |
+
|
| 143 |
+
🤖 Recommendation (EN): {rationale_en}
|
| 144 |
+
🤖 Cadangan (BM): {rationale_bm}
|
| 145 |
+
🤖 建议 (中文): {rationale_cn}
|
| 146 |
+
"""
|
| 147 |
|
| 148 |
def pay_fine(case_id):
|
| 149 |
conn = sqlite3.connect(DB_FILE)
|
|
|
|
| 162 |
c.execute("UPDATE summons_cases SET status=? WHERE case_id=?", ("PAID", case_id))
|
| 163 |
conn.commit()
|
| 164 |
conn.close()
|
| 165 |
+
|
| 166 |
+
return f"""
|
| 167 |
+
✅ Fine Paid / Denda Dibayar / 已付款
|
| 168 |
+
💰 Amount / Jumlah / 金额: RM {fine:.2f}
|
| 169 |
+
🧾 Receipt No. / No. Resit / 收据号码: {receipt_no}
|
| 170 |
+
"""
|
| 171 |
|
| 172 |
# ----------------------
|
| 173 |
+
# Gradio UI
|
| 174 |
# ----------------------
|
| 175 |
with gr.Blocks() as demo:
|
| 176 |
+
gr.Markdown("# 🚦 SwiftCase.ai – Citizen Portal (3 Languages / 3 Bahasa)")
|
| 177 |
+
|
| 178 |
+
with gr.Tab("➕ Create Case"):
|
| 179 |
+
name = gr.Textbox(label="Name / Nama / 姓名")
|
| 180 |
+
address = gr.Textbox(label="Address / Alamat / 地址")
|
| 181 |
+
ticket_number = gr.Textbox(label="Summon Ticket No. / Nombor Saman / 罚单号码")
|
| 182 |
+
vehicle_number = gr.Textbox(label="Vehicle No. / Nombor Kenderaan / 车牌号码")
|
| 183 |
+
road_name = gr.Textbox(label="Road / Jalan / 道路")
|
| 184 |
+
town_city = gr.Textbox(label="Town/City / Bandar / 城市")
|
| 185 |
+
state = gr.Textbox(label="State / Negeri / 州")
|
| 186 |
+
offence_en = gr.Textbox(label="Offence (EN)")
|
| 187 |
+
offence_bm = gr.Textbox(label="Kesalahan (BM)")
|
| 188 |
+
offence_cn = gr.Textbox(label="违法 (中文)")
|
| 189 |
+
fine_amount = gr.Number(label="Fine Amount (RM)", value=300)
|
| 190 |
+
create_btn = gr.Button("Create Case / Buat Kes / 建立案件")
|
| 191 |
+
create_out = gr.Textbox(label="Result / Keputusan / 结果")
|
| 192 |
+
create_btn.click(
|
| 193 |
+
fn=insert_case,
|
| 194 |
+
inputs=[name, address, ticket_number, vehicle_number, road_name, town_city, state, offence_en, offence_bm, offence_cn, fine_amount],
|
| 195 |
+
outputs=create_out
|
| 196 |
+
)
|
| 197 |
+
|
| 198 |
+
with gr.Tab("🔍 View Case"):
|
| 199 |
+
view_case_id = gr.Number(label="Enter Case ID / Masukkan Nombor Kes / 输入案件编号", value=1)
|
| 200 |
+
view_btn = gr.Button("View Case / Lihat Kes / 查看案件")
|
| 201 |
+
view_out = gr.Textbox(label="Case Details / Butiran Kes / 案件详情", lines=15)
|
| 202 |
+
view_btn.click(fn=view_case, inputs=view_case_id, outputs=view_out)
|
| 203 |
+
|
| 204 |
+
with gr.Tab("📨 Submit Appeal"):
|
| 205 |
+
appeal_case_id = gr.Number(label="Case ID / Nombor Kes / 案件编号")
|
| 206 |
+
appeal_text = gr.Textbox(label="Appeal Text / Teks Rayuan / 上诉内容", lines=3)
|
| 207 |
+
appeal_target = gr.Radio(choices=["PDRM", "Magistrate"], label="Submit To / Hantar Kepada / 提交至")
|
| 208 |
+
appeal_btn = gr.Button("Submit Appeal / Hantar Rayuan / 提交上诉")
|
| 209 |
+
appeal_out = gr.Textbox(label="Appeal Status / Status Rayuan / 上诉状态", lines=8)
|
| 210 |
appeal_btn.click(fn=submit_appeal, inputs=[appeal_case_id, appeal_text, appeal_target], outputs=appeal_out)
|
| 211 |
+
|
| 212 |
+
with gr.Tab("💳 Pay Fine"):
|
| 213 |
+
pay_case_id = gr.Number(label="Case ID / Nombor Kes / 案件编号")
|
| 214 |
+
pay_btn = gr.Button("Pay Fine / Bayar Denda / 支付罚款")
|
| 215 |
+
pay_out = gr.Textbox(label="Payment Result / Keputusan Bayaran / 付款结果", lines=6)
|
| 216 |
pay_btn.click(fn=pay_fine, inputs=pay_case_id, outputs=pay_out)
|
| 217 |
|
| 218 |
if __name__ == "__main__":
|
|
|
|
| 228 |
|
| 229 |
|
| 230 |
|
| 231 |
+
|