dschandra commited on
Commit
3a90b51
·
verified ·
1 Parent(s): d980008

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +157 -69
app.py CHANGED
@@ -2,11 +2,14 @@ import gradio as gr
2
  import uuid
3
  import time
4
  from PIL import Image
 
5
 
6
- # Mock DB in memory
7
  CASES = {}
 
 
8
 
9
- # Required images checklist
10
  REQUIRED_PHOTOS = [
11
  "Street View",
12
  "Front Elevation",
@@ -17,30 +20,82 @@ REQUIRED_PHOTOS = [
17
  "Document Scan"
18
  ]
19
 
20
- def engineer_submit(case_name, engineer_name, images):
 
21
  case_id = str(uuid.uuid4())[:8]
22
- uploaded_count = len(images) if images else 0
23
- completeness = int((uploaded_count / len(REQUIRED_PHOTOS)) * 100)
24
-
25
  CASES[case_id] = {
26
  "case_id": case_id,
27
- "case_name": case_name,
28
- "engineer": engineer_name,
29
- "images": images,
30
- "status": "Submitted to Data Entry",
31
- "completeness": completeness,
32
- "timestamp": time.strftime("%Y-%m-%d %H:%M:%S"),
 
 
 
33
  "reviewer_status": "Pending",
34
- "notes": "",
35
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36
 
37
- return f"Case Created: {case_id}\nCompleteness: {completeness}%"
 
38
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
39
  def get_data_entry_cases():
40
  rows = []
41
  for cid, data in CASES.items():
42
- rows.append([cid, data["case_name"], data["engineer"],
43
- data["status"], f"{data['completeness']}%", data["timestamp"]])
44
  return rows
45
 
46
  def data_entry_action(case_id, action, notes):
@@ -61,8 +116,8 @@ def data_entry_action(case_id, action, notes):
61
  def reviewer_dashboard():
62
  rows = []
63
  for cid, data in CASES.items():
64
- rows.append([cid, data["case_name"], data["engineer"],
65
- data["status"], data["reviewer_status"]])
66
  return rows
67
 
68
  def reviewer_action(case_id, decision):
@@ -85,66 +140,99 @@ def mis_dashboard():
85
  avg_complete = 0
86
  if total > 0:
87
  avg_complete = sum([c["completeness"] for c in CASES.values()]) / total
88
-
 
 
 
 
 
89
  return {
90
  "Total Cases": total,
91
  "Completed": completed,
92
  "Rework Cases": rework,
93
  "Average Completeness": f"{avg_complete:.2f}%",
 
94
  }
95
 
96
 
97
  # ---------- UI LAYOUT ----------
98
 
99
- with gr.Blocks(title="Property Valuation Automation POC") as demo:
100
-
101
- gr.Markdown("# 🏠 Property Valuation Automation POC Demo")
102
- gr.Markdown("Engineer Data Entry Reviewer MIS Dashboard")
103
-
104
- with gr.Tab("1️⃣ Engineer Panel"):
105
- case_name = gr.Textbox(label="Case Name")
106
- engineer_name = gr.Textbox(label="Engineer Name")
107
- images = gr.File(label="Upload Required Photos", file_count="multiple", type="filepath")
108
-
109
- submit_btn = gr.Button("Submit Case")
110
- eng_output = gr.Textbox(label="Output")
111
-
112
- submit_btn.click(engineer_submit, [case_name, engineer_name, images], eng_output)
113
-
114
- with gr.Tab("2️⃣ Data Entry Panel"):
115
- data_table = gr.DataFrame(headers=["Case ID","Case Name","Engineer","Status","Completeness","Timestamp"],
116
- label="Cases", interactive=False)
117
-
118
- refresh_btn = gr.Button("Refresh List")
119
- refresh_btn.click(get_data_entry_cases, None, data_table)
120
-
121
- with gr.Row():
122
- case_id_input = gr.Textbox(label="Case ID")
123
- action = gr.Radio(["Approve & Send to Reviewer", "Request Rework"], label="Action")
124
- notes = gr.Textbox(label="Notes")
125
- update_btn = gr.Button("Update Status")
126
- data_entry_output = gr.Textbox(label="Response")
127
-
128
- update_btn.click(data_entry_action, [case_id_input, action, notes], data_entry_output)
129
-
130
- with gr.Tab("3️⃣ Reviewer Panel"):
131
- reviewer_table = gr.DataFrame(headers=["Case ID","Case Name","Engineer","Status","Review Status"],
132
- label="Cases", interactive=False)
133
-
134
- refresh_review = gr.Button("Refresh Reviewer Queue")
135
- refresh_review.click(reviewer_dashboard, None, reviewer_table)
136
-
137
- with gr.Row():
138
- reviewer_case = gr.Textbox(label="Case ID")
139
- review_decision = gr.Radio(["Approve", "Reject"], label="Decision")
140
- review_btn = gr.Button("Submit Review")
141
- review_output = gr.Textbox(label="Output")
142
-
143
- review_btn.click(reviewer_action, [reviewer_case, review_decision], review_output)
144
-
145
- with gr.Tab("4️⃣ MIS Dashboard"):
146
- mis_out = gr.JSON(label="MIS Summary")
147
- mis_refresh_btn = gr.Button("Refresh MIS")
148
- mis_refresh_btn.click(mis_dashboard, None, mis_out)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
149
 
150
  demo.launch()
 
2
  import uuid
3
  import time
4
  from PIL import Image
5
+ import os
6
 
7
+ # In-memory "DB"
8
  CASES = {}
9
+ ENGINEERS = ["ENG_Ramesh", "ENG_Suresh", "ENG_Imran"]
10
+ BANKS = ["State Bank of India", "HDFC Bank", "ICICI Bank"]
11
 
12
+ # Required images checklist (for later completeness calc)
13
  REQUIRED_PHOTOS = [
14
  "Street View",
15
  "Front Elevation",
 
20
  "Document Scan"
21
  ]
22
 
23
+ def create_case(bank, case_name, borrower_name, assigned_engineer, lat, lon, notes):
24
+ """Create a case with bank details, assigned engineer and coordinates"""
25
  case_id = str(uuid.uuid4())[:8]
26
+ created_at = time.strftime("%Y-%m-%d %H:%M:%S")
 
 
27
  CASES[case_id] = {
28
  "case_id": case_id,
29
+ "bank": bank,
30
+ "case_name": case_name or f"Case-{case_id}",
31
+ "borrower_name": borrower_name,
32
+ "assigned_engineer": assigned_engineer,
33
+ "coordinates": {"lat": lat, "lon": lon},
34
+ "images": [], # list of dicts {photo_name, filepath, ts}
35
+ "status": "Assigned to Engineer",
36
+ "completeness": 0,
37
+ "timestamp": created_at,
38
  "reviewer_status": "Pending",
39
+ "notes": notes,
40
  }
41
+ return f"Created case {case_id} assigned to {assigned_engineer} for {bank}"
42
+
43
+ def list_cases_for_engineer(engineer):
44
+ """Return simple table of cases assigned to this engineer"""
45
+ rows = []
46
+ for cid, data in CASES.items():
47
+ if data["assigned_engineer"] == engineer:
48
+ rows.append([cid, data["case_name"], data["borrower_name"],
49
+ data["status"], f"{data['completeness']}%",
50
+ data["coordinates"]["lat"], data["coordinates"]["lon"]])
51
+ return rows
52
+
53
+ def engineer_upload_to_case(case_id, engineer_name, images):
54
+ """Attach uploaded images to an existing case (found by case_id).
55
+ Accepts multiple image file paths (from Gradio upload)"""
56
+ if not case_id:
57
+ return "Please provide Case ID to upload images."
58
 
59
+ if case_id not in CASES:
60
+ return "Case ID not found."
61
 
62
+ # ensure engineer matches assignment (soft check)
63
+ if CASES[case_id]["assigned_engineer"] != engineer_name:
64
+ # allow upload but warn
65
+ warning = f"Warning: case assigned to {CASES[case_id]['assigned_engineer']}, not {engineer_name}."
66
+ else:
67
+ warning = ""
68
+
69
+ uploaded_count = 0
70
+ if images:
71
+ for img_path in images:
72
+ ts = time.strftime("%Y-%m-%d %H:%M:%S")
73
+ fname = os.path.basename(img_path)
74
+ CASES[case_id]["images"].append({
75
+ "photo_name": fname,
76
+ "filepath": img_path,
77
+ "uploaded_by": engineer_name,
78
+ "timestamp": ts
79
+ })
80
+ uploaded_count += 1
81
+
82
+ # update completeness (simple heuristic)
83
+ unique_photos = len(CASES[case_id]["images"])
84
+ completeness = int((unique_photos / len(REQUIRED_PHOTOS)) * 100)
85
+ completeness = min(100, completeness)
86
+ CASES[case_id]["completeness"] = completeness
87
+
88
+ # update status to indicate submission
89
+ if uploaded_count > 0:
90
+ CASES[case_id]["status"] = "Submitted to Data Entry"
91
+ return f"{warning} Uploaded {uploaded_count} images to case {case_id}. Completeness: {completeness}%"
92
+
93
+ # Data Entry & Reviewer functions (slight updates to show bank & coords)
94
  def get_data_entry_cases():
95
  rows = []
96
  for cid, data in CASES.items():
97
+ rows.append([cid, data["bank"], data["case_name"], data["borrower_name"],
98
+ data["assigned_engineer"], data["status"], f"{data['completeness']}%", data["timestamp"]])
99
  return rows
100
 
101
  def data_entry_action(case_id, action, notes):
 
116
  def reviewer_dashboard():
117
  rows = []
118
  for cid, data in CASES.items():
119
+ rows.append([cid, data["bank"], data["case_name"], data["assigned_engineer"],
120
+ data["status"], data["reviewer_status"], f"{data['completeness']}%"])
121
  return rows
122
 
123
  def reviewer_action(case_id, decision):
 
140
  avg_complete = 0
141
  if total > 0:
142
  avg_complete = sum([c["completeness"] for c in CASES.values()]) / total
143
+
144
+ # simple listing of recent cases
145
+ recent = []
146
+ for cid, d in sorted(CASES.items(), key=lambda x: x[1]["timestamp"], reverse=True)[:10]:
147
+ recent.append([cid, d["bank"], d["case_name"], d["assigned_engineer"], d["status"], f"{d['completeness']}%"])
148
+
149
  return {
150
  "Total Cases": total,
151
  "Completed": completed,
152
  "Rework Cases": rework,
153
  "Average Completeness": f"{avg_complete:.2f}%",
154
+ "Recent Cases (top 10)": recent
155
  }
156
 
157
 
158
  # ---------- UI LAYOUT ----------
159
 
160
+ with gr.Blocks(title="Property Valuation Automation POC - Case Initiation") as demo:
161
+
162
+ gr.Markdown("# 🏦 Case Initiation Bank Details + Assignment")
163
+ gr.Markdown("Create case with bank selection (3 banks), assign to an engineer, provide coordinates.")
164
+
165
+ # Case Creation
166
+ with gr.Row():
167
+ with gr.Column(scale=1):
168
+ bank_dropdown = gr.Dropdown(choices=BANKS, value=BANKS[0], label="Select Bank")
169
+ case_name = gr.Textbox(label="Case Name (optional)")
170
+ borrower_name = gr.Textbox(label="Borrower Name")
171
+ engineer_dropdown = gr.Dropdown(choices=ENGINEERS, value=ENGINEERS[0], label="Assign to Engineer")
172
+ with gr.Column(scale=1):
173
+ lat_input = gr.Textbox(label="Latitude (ex: 17.4390)", value="17.4390")
174
+ lon_input = gr.Textbox(label="Longitude (ex: 78.4983)", value="78.4983")
175
+ notes_input = gr.Textbox(label="Notes / Instructions (optional)")
176
+ create_btn = gr.Button("Create Case & Assign")
177
+ create_output = gr.Textbox(label="Create Case Output")
178
+
179
+ create_btn.click(create_case, [bank_dropdown, case_name, borrower_name, engineer_dropdown, lat_input, lon_input, notes_input], create_output)
180
+
181
+ gr.Markdown("----")
182
+ gr.Markdown("## 👷 Engineer Panel — Assigned Cases & Upload Images")
183
+ with gr.Row():
184
+ engineer_select = gr.Dropdown(choices=ENGINEERS, value=ENGINEERS[0], label="Select Engineer to View Assigned Cases")
185
+ refresh_eng = gr.Button("Refresh Assigned Cases")
186
+ eng_cases_table = gr.DataFrame(headers=["Case ID","Case Name","Borrower","Status","Completeness","Lat","Lon"], interactive=False)
187
+
188
+ refresh_eng.click(list_cases_for_engineer, engineer_select, eng_cases_table)
189
+
190
+ gr.Markdown("Upload images to a selected case (paste case id from table):")
191
+ with gr.Row():
192
+ eng_case_id_input = gr.Textbox(label="Case ID")
193
+ eng_name_input = gr.Dropdown(choices=ENGINEERS, value=ENGINEERS[0], label="Uploading Engineer")
194
+ eng_images = gr.File(label="Upload Photos (multiple)", file_count="multiple", type="filepath")
195
+ eng_upload_btn = gr.Button("Upload Images to Case")
196
+ eng_upload_output = gr.Textbox(label="Upload Response")
197
+
198
+ eng_upload_btn.click(engineer_upload_to_case, [eng_case_id_input, eng_name_input, eng_images], eng_upload_output)
199
+
200
+ gr.Markdown("----")
201
+ gr.Markdown("## 🧾 Data Entry Panel")
202
+ data_table = gr.DataFrame(headers=["Case ID","Bank","Case Name","Borrower","Engineer","Status","Completeness","Created At"],
203
+ label="Cases", interactive=False)
204
+ refresh_btn = gr.Button("Refresh List")
205
+ refresh_btn.click(get_data_entry_cases, None, data_table)
206
+
207
+ with gr.Row():
208
+ case_id_input = gr.Textbox(label="Case ID")
209
+ action = gr.Radio(["Approve & Send to Reviewer", "Request Rework"], label="Action")
210
+ notes = gr.Textbox(label="Notes")
211
+ update_btn = gr.Button("Update Status")
212
+ data_entry_output = gr.Textbox(label="Response")
213
+
214
+ update_btn.click(data_entry_action, [case_id_input, action, notes], data_entry_output)
215
+
216
+ gr.Markdown("----")
217
+ gr.Markdown("## ✅ Reviewer Panel")
218
+ reviewer_table = gr.DataFrame(headers=["Case ID","Bank","Case Name","Engineer","Status","Review Status","Completeness"],
219
+ label="Reviewer Queue", interactive=False)
220
+
221
+ refresh_review = gr.Button("Refresh Reviewer Queue")
222
+ refresh_review.click(reviewer_dashboard, None, reviewer_table)
223
+
224
+ with gr.Row():
225
+ reviewer_case = gr.Textbox(label="Case ID")
226
+ review_decision = gr.Radio(["Approve", "Reject"], label="Decision")
227
+ review_btn = gr.Button("Submit Review")
228
+ review_output = gr.Textbox(label="Output")
229
+
230
+ review_btn.click(reviewer_action, [reviewer_case, review_decision], review_output)
231
+
232
+ gr.Markdown("----")
233
+ gr.Markdown("## 📊 MIS Dashboard")
234
+ mis_out = gr.JSON(label="MIS Summary")
235
+ mis_refresh_btn = gr.Button("Refresh MIS")
236
+ mis_refresh_btn.click(mis_dashboard, None, mis_out)
237
 
238
  demo.launch()