Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -1,145 +1,66 @@
|
|
1 |
import os
|
2 |
os.environ["OMP_NUM_THREADS"] = "1"
|
3 |
|
4 |
-
import re
|
5 |
-
import json
|
6 |
-
import datetime as dt
|
7 |
import gradio as gr
|
8 |
from utils import extract_kyc_fields
|
9 |
from simple_salesforce import Salesforce
|
10 |
|
11 |
-
#
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
def _parse_birthdate(dob_text: str):
|
19 |
-
if not dob_text or dob_text == "Not found":
|
20 |
-
return None
|
21 |
-
s = dob_text.strip()
|
22 |
-
|
23 |
-
m = re.fullmatch(r"(\d{4})-(\d{2})-(\d{2})", s)
|
24 |
-
if m:
|
25 |
-
y, mo, d = map(int, m.groups())
|
26 |
-
try:
|
27 |
-
return dt.date(y, mo, d).isoformat()
|
28 |
-
except ValueError:
|
29 |
-
return None
|
30 |
-
|
31 |
-
m = re.fullmatch(r"(\d{2})[./-](\d{2})[./-](\d{4})", s)
|
32 |
-
if m:
|
33 |
-
d, mo, y = map(int, m.groups())
|
34 |
-
try:
|
35 |
-
return dt.date(y, mo, d).isoformat()
|
36 |
-
except ValueError:
|
37 |
-
return None
|
38 |
-
|
39 |
-
m = re.fullmatch(r"(19|20)\d{2}", s)
|
40 |
-
if m:
|
41 |
-
y = int(s)
|
42 |
-
try:
|
43 |
-
return dt.date(y, 6, 15).isoformat()
|
44 |
-
except ValueError:
|
45 |
-
return None
|
46 |
-
|
47 |
-
return None
|
48 |
-
|
49 |
-
def sf_login():
|
50 |
-
sf = Salesforce(
|
51 |
-
username=SF_USERNAME,
|
52 |
-
password=SF_PASSWORD,
|
53 |
-
security_token=SF_SECURITY_TOKEN,
|
54 |
-
domain=SF_DOMAIN,
|
55 |
-
)
|
56 |
-
sf.query("SELECT Id FROM User LIMIT 1")
|
57 |
-
return sf
|
58 |
-
|
59 |
-
def sf_create_kyc_via_session(sf, payload: dict):
|
60 |
-
url = f"{sf.base_url}sobjects/KYC_Record__c"
|
61 |
-
resp = sf.session.post(url, json=payload, headers=sf.headers, timeout=30)
|
62 |
|
|
|
|
|
63 |
try:
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
71 |
|
72 |
return {
|
73 |
-
"
|
74 |
-
"
|
75 |
-
"
|
76 |
-
"response_json": body,
|
77 |
-
"response_text": resp.text,
|
78 |
}
|
79 |
|
80 |
-
|
81 |
-
|
82 |
-
p = (ocr_results.get("pan") or {})
|
83 |
-
|
84 |
-
payload = {
|
85 |
-
"Aadhaar_Number__c": a.get("aadhaar_number") if a.get("card_type") == "AADHAAR" else None,
|
86 |
-
"Aadhaar_Name__c": a.get("name") if a.get("card_type") == "AADHAAR" else None,
|
87 |
-
"Aadhaar_DOB__c": _parse_birthdate(a.get("dob")) if a.get("card_type") == "AADHAAR" else None,
|
88 |
-
"PAN_Number__c": p.get("pan_number") if p.get("card_type") == "PAN" else None,
|
89 |
-
"Pan_Name__c": p.get("name") if p.get("card_type") == "PAN" else None,
|
90 |
-
"Pan_DOB__c": _parse_birthdate(p.get("dob")) if p.get("card_type") == "PAN" else None,
|
91 |
-
}
|
92 |
-
return {k: v for k, v in payload.items() if v is not None}
|
93 |
-
|
94 |
-
def process_documents(aadhaar_file, pan_file, push_to_sf):
|
95 |
-
results = {"aadhaar": None, "pan": None}
|
96 |
-
|
97 |
-
if not aadhaar_file and not pan_file:
|
98 |
-
return {"error": "Please upload at least one file (Aadhaar and/or PAN)."}
|
99 |
-
|
100 |
-
if aadhaar_file:
|
101 |
-
try:
|
102 |
-
res = extract_kyc_fields(aadhaar_file.name)
|
103 |
-
res["source_file"] = os.path.basename(aadhaar_file.name)
|
104 |
-
results["aadhaar"] = res
|
105 |
-
except Exception as e:
|
106 |
-
results["aadhaar"] = {"error": f"Aadhaar OCR failed: {str(e)}", "card_type": "UNKNOWN"}
|
107 |
-
|
108 |
-
if pan_file:
|
109 |
-
try:
|
110 |
-
res = extract_kyc_fields(pan_file.name)
|
111 |
-
res["source_file"] = os.path.basename(pan_file.name)
|
112 |
-
results["pan"] = res
|
113 |
-
except Exception as e:
|
114 |
-
results["pan"] = {"error": f"PAN OCR failed: {str(e)}", "card_type": "UNKNOWN"}
|
115 |
-
|
116 |
-
output = {"ocr": results}
|
117 |
-
|
118 |
-
if push_to_sf:
|
119 |
-
payload = build_payload(results)
|
120 |
-
try:
|
121 |
-
sf = sf_login()
|
122 |
-
created = sf_create_kyc_via_session(sf, payload)
|
123 |
-
output["salesforce"] = {"pushed": created.get("success", False), **created}
|
124 |
-
except Exception as e:
|
125 |
-
output["salesforce"] = {"pushed": False, "error": {"type": e.__class__.__name__, "message": str(e)}}
|
126 |
-
|
127 |
-
return output
|
128 |
-
|
129 |
-
with gr.Blocks(title="Smart KYC OCR β Salesforce (KYC_Record__c)") as demo:
|
130 |
-
gr.Markdown("# π§Ύ Smart KYC OCR β Salesforce\nUpload Aadhaar and PAN, then optionally push one record.")
|
131 |
|
132 |
with gr.Row():
|
133 |
with gr.Column():
|
134 |
-
aadhaar_uploader = gr.File(label="π€ Aadhaar
|
|
|
|
|
|
|
135 |
with gr.Column():
|
136 |
-
|
137 |
|
138 |
-
|
139 |
-
submit_btn = gr.Button("π Extract KYC Info", variant="primary")
|
140 |
-
output_json = gr.JSON(label="π Output")
|
141 |
|
142 |
-
|
|
|
143 |
|
144 |
if __name__ == "__main__":
|
145 |
demo.launch()
|
|
|
1 |
import os
|
2 |
os.environ["OMP_NUM_THREADS"] = "1"
|
3 |
|
|
|
|
|
|
|
4 |
import gradio as gr
|
5 |
from utils import extract_kyc_fields
|
6 |
from simple_salesforce import Salesforce
|
7 |
|
8 |
+
# Salesforce login
|
9 |
+
sf = Salesforce(
|
10 |
+
username="licproject@2025.com",
|
11 |
+
password="Lic@2025",
|
12 |
+
security_token="AmmfRcd6IiYaRtSGntBnzNMQU"
|
13 |
+
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
14 |
|
15 |
+
def send_to_salesforce(aadhaar_data, pan_data):
|
16 |
+
"""Send both Aadhaar & PAN extracted data to Salesforce."""
|
17 |
try:
|
18 |
+
record = {
|
19 |
+
"Aadhaar_Name__c": aadhaar_data.get("name", ""),
|
20 |
+
"Aadhaar_Number__c": aadhaar_data.get("aadhaar_number", ""),
|
21 |
+
"Aadhaar_DOB__c": aadhaar_data.get("dob", ""),
|
22 |
+
"Aadhaar_Gender__c": aadhaar_data.get("gender", ""),
|
23 |
+
"PAN_Name__c": pan_data.get("name", ""),
|
24 |
+
"PAN_Number__c": pan_data.get("pan_number", ""),
|
25 |
+
"PAN_DOB__c": pan_data.get("dob", "")
|
26 |
+
}
|
27 |
+
result = sf.KYC_Record__c.create(record)
|
28 |
+
return {"status": "success", "salesforce_id": result.get("id")}
|
29 |
+
except Exception as e:
|
30 |
+
return {"status": "error", "message": str(e)}
|
31 |
+
|
32 |
+
def process_documents(aadhaar_file, pan_file):
|
33 |
+
if aadhaar_file is None or pan_file is None:
|
34 |
+
return {"error": "Please upload both Aadhaar and PAN images."}
|
35 |
+
|
36 |
+
aadhaar_data = extract_kyc_fields(aadhaar_file.name)
|
37 |
+
pan_data = extract_kyc_fields(pan_file.name)
|
38 |
+
|
39 |
+
# Send to Salesforce
|
40 |
+
sf_result = send_to_salesforce(aadhaar_data, pan_data)
|
41 |
|
42 |
return {
|
43 |
+
"aadhaar_data": aadhaar_data,
|
44 |
+
"pan_data": pan_data,
|
45 |
+
"salesforce_result": sf_result
|
|
|
|
|
46 |
}
|
47 |
|
48 |
+
with gr.Blocks(title="Smart KYC OCR") as demo:
|
49 |
+
gr.Markdown("# π§Ύ Smart KYC OCR Tool β Aadhaar & PAN Scanner")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
50 |
|
51 |
with gr.Row():
|
52 |
with gr.Column():
|
53 |
+
aadhaar_uploader = gr.File(label="π€ Upload Aadhaar Card", file_types=[".jpg", ".jpeg", ".png"])
|
54 |
+
pan_uploader = gr.File(label="π€ Upload PAN Card", file_types=[".jpg", ".jpeg", ".png"])
|
55 |
+
submit_btn = gr.Button("π Extract & Send to Salesforce", variant="primary")
|
56 |
+
|
57 |
with gr.Column():
|
58 |
+
output_json = gr.JSON(label="π Extracted KYC Data")
|
59 |
|
60 |
+
submit_btn.click(fn=process_documents, inputs=[aadhaar_uploader, pan_uploader], outputs=output_json)
|
|
|
|
|
61 |
|
62 |
+
gr.Markdown("---")
|
63 |
+
gr.Markdown("π **Privacy Note:** This app processes your document locally in the cloud. No data is stored or shared.")
|
64 |
|
65 |
if __name__ == "__main__":
|
66 |
demo.launch()
|