Spaces:
Sleeping
Sleeping
File size: 9,709 Bytes
d980008 3a90b51 d980008 3a90b51 d980008 3a90b51 d980008 3a90b51 d980008 3a90b51 d980008 3a90b51 d980008 3a90b51 d980008 3a90b51 d980008 3a90b51 d980008 3a90b51 d980008 3a90b51 d980008 3a90b51 d980008 3a90b51 d980008 3a90b51 d980008 3a90b51 d980008 3a90b51 d980008 |
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 |
import gradio as gr
import uuid
import time
from PIL import Image
import os
# In-memory "DB"
CASES = {}
ENGINEERS = ["ENG_Ramesh", "ENG_Suresh", "ENG_Imran"]
BANKS = ["State Bank of India", "HDFC Bank", "ICICI Bank"]
# Required images checklist (for later completeness calc)
REQUIRED_PHOTOS = [
"Street View",
"Front Elevation",
"Living Room",
"Kitchen",
"Bedroom",
"Bathroom",
"Document Scan"
]
def create_case(bank, case_name, borrower_name, assigned_engineer, lat, lon, notes):
"""Create a case with bank details, assigned engineer and coordinates"""
case_id = str(uuid.uuid4())[:8]
created_at = time.strftime("%Y-%m-%d %H:%M:%S")
CASES[case_id] = {
"case_id": case_id,
"bank": bank,
"case_name": case_name or f"Case-{case_id}",
"borrower_name": borrower_name,
"assigned_engineer": assigned_engineer,
"coordinates": {"lat": lat, "lon": lon},
"images": [], # list of dicts {photo_name, filepath, ts}
"status": "Assigned to Engineer",
"completeness": 0,
"timestamp": created_at,
"reviewer_status": "Pending",
"notes": notes,
}
return f"Created case {case_id} assigned to {assigned_engineer} for {bank}"
def list_cases_for_engineer(engineer):
"""Return simple table of cases assigned to this engineer"""
rows = []
for cid, data in CASES.items():
if data["assigned_engineer"] == engineer:
rows.append([cid, data["case_name"], data["borrower_name"],
data["status"], f"{data['completeness']}%",
data["coordinates"]["lat"], data["coordinates"]["lon"]])
return rows
def engineer_upload_to_case(case_id, engineer_name, images):
"""Attach uploaded images to an existing case (found by case_id).
Accepts multiple image file paths (from Gradio upload)"""
if not case_id:
return "Please provide Case ID to upload images."
if case_id not in CASES:
return "Case ID not found."
# ensure engineer matches assignment (soft check)
if CASES[case_id]["assigned_engineer"] != engineer_name:
# allow upload but warn
warning = f"Warning: case assigned to {CASES[case_id]['assigned_engineer']}, not {engineer_name}."
else:
warning = ""
uploaded_count = 0
if images:
for img_path in images:
ts = time.strftime("%Y-%m-%d %H:%M:%S")
fname = os.path.basename(img_path)
CASES[case_id]["images"].append({
"photo_name": fname,
"filepath": img_path,
"uploaded_by": engineer_name,
"timestamp": ts
})
uploaded_count += 1
# update completeness (simple heuristic)
unique_photos = len(CASES[case_id]["images"])
completeness = int((unique_photos / len(REQUIRED_PHOTOS)) * 100)
completeness = min(100, completeness)
CASES[case_id]["completeness"] = completeness
# update status to indicate submission
if uploaded_count > 0:
CASES[case_id]["status"] = "Submitted to Data Entry"
return f"{warning} Uploaded {uploaded_count} images to case {case_id}. Completeness: {completeness}%"
# Data Entry & Reviewer functions (slight updates to show bank & coords)
def get_data_entry_cases():
rows = []
for cid, data in CASES.items():
rows.append([cid, data["bank"], data["case_name"], data["borrower_name"],
data["assigned_engineer"], data["status"], f"{data['completeness']}%", data["timestamp"]])
return rows
def data_entry_action(case_id, action, notes):
if case_id not in CASES:
return "Case ID not found."
if action == "Approve & Send to Reviewer":
CASES[case_id]["status"] = "Data Entry Completed"
CASES[case_id]["reviewer_status"] = "Review Pending"
elif action == "Request Rework":
CASES[case_id]["status"] = "Rework Requested"
else:
return "Invalid Action"
CASES[case_id]["notes"] = notes
return f"Updated Case {case_id} β {CASES[case_id]['status']}"
def reviewer_dashboard():
rows = []
for cid, data in CASES.items():
rows.append([cid, data["bank"], data["case_name"], data["assigned_engineer"],
data["status"], data["reviewer_status"], f"{data['completeness']}%"])
return rows
def reviewer_action(case_id, decision):
if case_id not in CASES:
return "Invalid Case ID"
if decision == "Approve":
CASES[case_id]["reviewer_status"] = "Approved"
CASES[case_id]["status"] = "Completed"
else:
CASES[case_id]["reviewer_status"] = "Rejected"
CASES[case_id]["status"] = "Rejected"
return f"Reviewer Updated Case {case_id}: {decision}"
def mis_dashboard():
total = len(CASES)
completed = len([c for c in CASES.values() if c["status"] == "Completed"])
rework = len([c for c in CASES.values() if c["status"] == "Rework Requested"])
avg_complete = 0
if total > 0:
avg_complete = sum([c["completeness"] for c in CASES.values()]) / total
# simple listing of recent cases
recent = []
for cid, d in sorted(CASES.items(), key=lambda x: x[1]["timestamp"], reverse=True)[:10]:
recent.append([cid, d["bank"], d["case_name"], d["assigned_engineer"], d["status"], f"{d['completeness']}%"])
return {
"Total Cases": total,
"Completed": completed,
"Rework Cases": rework,
"Average Completeness": f"{avg_complete:.2f}%",
"Recent Cases (top 10)": recent
}
# ---------- UI LAYOUT ----------
with gr.Blocks(title="Property Valuation Automation POC - Case Initiation") as demo:
gr.Markdown("# π¦ Case Initiation β Bank Details + Assignment")
gr.Markdown("Create case with bank selection (3 banks), assign to an engineer, provide coordinates.")
# Case Creation
with gr.Row():
with gr.Column(scale=1):
bank_dropdown = gr.Dropdown(choices=BANKS, value=BANKS[0], label="Select Bank")
case_name = gr.Textbox(label="Case Name (optional)")
borrower_name = gr.Textbox(label="Borrower Name")
engineer_dropdown = gr.Dropdown(choices=ENGINEERS, value=ENGINEERS[0], label="Assign to Engineer")
with gr.Column(scale=1):
lat_input = gr.Textbox(label="Latitude (ex: 17.4390)", value="17.4390")
lon_input = gr.Textbox(label="Longitude (ex: 78.4983)", value="78.4983")
notes_input = gr.Textbox(label="Notes / Instructions (optional)")
create_btn = gr.Button("Create Case & Assign")
create_output = gr.Textbox(label="Create Case Output")
create_btn.click(create_case, [bank_dropdown, case_name, borrower_name, engineer_dropdown, lat_input, lon_input, notes_input], create_output)
gr.Markdown("----")
gr.Markdown("## π· Engineer Panel β Assigned Cases & Upload Images")
with gr.Row():
engineer_select = gr.Dropdown(choices=ENGINEERS, value=ENGINEERS[0], label="Select Engineer to View Assigned Cases")
refresh_eng = gr.Button("Refresh Assigned Cases")
eng_cases_table = gr.DataFrame(headers=["Case ID","Case Name","Borrower","Status","Completeness","Lat","Lon"], interactive=False)
refresh_eng.click(list_cases_for_engineer, engineer_select, eng_cases_table)
gr.Markdown("Upload images to a selected case (paste case id from table):")
with gr.Row():
eng_case_id_input = gr.Textbox(label="Case ID")
eng_name_input = gr.Dropdown(choices=ENGINEERS, value=ENGINEERS[0], label="Uploading Engineer")
eng_images = gr.File(label="Upload Photos (multiple)", file_count="multiple", type="filepath")
eng_upload_btn = gr.Button("Upload Images to Case")
eng_upload_output = gr.Textbox(label="Upload Response")
eng_upload_btn.click(engineer_upload_to_case, [eng_case_id_input, eng_name_input, eng_images], eng_upload_output)
gr.Markdown("----")
gr.Markdown("## π§Ύ Data Entry Panel")
data_table = gr.DataFrame(headers=["Case ID","Bank","Case Name","Borrower","Engineer","Status","Completeness","Created At"],
label="Cases", interactive=False)
refresh_btn = gr.Button("Refresh List")
refresh_btn.click(get_data_entry_cases, None, data_table)
with gr.Row():
case_id_input = gr.Textbox(label="Case ID")
action = gr.Radio(["Approve & Send to Reviewer", "Request Rework"], label="Action")
notes = gr.Textbox(label="Notes")
update_btn = gr.Button("Update Status")
data_entry_output = gr.Textbox(label="Response")
update_btn.click(data_entry_action, [case_id_input, action, notes], data_entry_output)
gr.Markdown("----")
gr.Markdown("## β
Reviewer Panel")
reviewer_table = gr.DataFrame(headers=["Case ID","Bank","Case Name","Engineer","Status","Review Status","Completeness"],
label="Reviewer Queue", interactive=False)
refresh_review = gr.Button("Refresh Reviewer Queue")
refresh_review.click(reviewer_dashboard, None, reviewer_table)
with gr.Row():
reviewer_case = gr.Textbox(label="Case ID")
review_decision = gr.Radio(["Approve", "Reject"], label="Decision")
review_btn = gr.Button("Submit Review")
review_output = gr.Textbox(label="Output")
review_btn.click(reviewer_action, [reviewer_case, review_decision], review_output)
gr.Markdown("----")
gr.Markdown("## π MIS Dashboard")
mis_out = gr.JSON(label="MIS Summary")
mis_refresh_btn = gr.Button("Refresh MIS")
mis_refresh_btn.click(mis_dashboard, None, mis_out)
demo.launch()
|