Vishwas1 commited on
Commit
69cee64
·
verified ·
1 Parent(s): b3109bb

FINAL FIX: Ultra-minimal gr.Interface version to resolve all JSON schema errors

Browse files
Files changed (1) hide show
  1. app.py +120 -198
app.py CHANGED
@@ -1,7 +1,6 @@
1
  import gradio as gr
2
  import pandas as pd
3
  from simple_salesforce import Salesforce
4
- import io
5
  from datetime import datetime
6
  import logging
7
 
@@ -9,13 +8,16 @@ import logging
9
  logging.basicConfig(level=logging.INFO)
10
  logger = logging.getLogger(__name__)
11
 
12
- # Global variables to store connection
13
  sf_connection = None
14
- available_objects = []
15
 
16
- def connect_to_salesforce(username, password, security_token, sandbox):
17
- """Connect to Salesforce"""
18
- global sf_connection, available_objects
 
 
 
 
19
 
20
  try:
21
  domain = 'test' if sandbox else None
@@ -26,213 +28,133 @@ def connect_to_salesforce(username, password, security_token, sandbox):
26
  domain=domain
27
  )
28
 
29
- # Test connection and get objects
30
- common_objects = ['Account', 'Contact', 'Lead', 'Opportunity', 'Case']
31
- available_objects = []
32
 
33
- for obj_name in common_objects:
 
34
  try:
35
- obj = getattr(sf_connection, obj_name)
36
- obj.describe()
37
- available_objects.append(obj_name)
38
- except:
39
- continue
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
40
 
41
- if not available_objects:
42
- available_objects = ['Account', 'Contact', 'Lead']
43
 
44
- return f"✅ Successfully connected to Salesforce as {username}\nAvailable objects: {', '.join(available_objects)}"
45
-
46
  except Exception as e:
47
- sf_connection = None
48
- available_objects = []
49
  error_msg = str(e)
50
-
51
  if "INVALID_LOGIN" in error_msg:
52
  return "❌ Invalid credentials. Please check your username, password, and security token."
53
  elif "API_DISABLED_FOR_ORG" in error_msg:
54
- return "❌ API access is disabled for your organization. Please contact your Salesforce admin."
55
  elif "LOGIN_MUST_USE_SECURITY_TOKEN" in error_msg:
56
- return "❌ Security token required. Please append your security token to your password."
57
  else:
58
  return f"❌ Connection failed: {error_msg}"
59
 
60
- def upload_data_to_salesforce(file, object_name, operation):
61
- """Upload data to Salesforce"""
62
- global sf_connection
63
-
64
- if not sf_connection:
65
- return " Please connect to Salesforce first", None
66
-
67
- if not file or not object_name:
68
- return "❌ Please select a file and object", None
69
-
70
- try:
71
- # Read the uploaded file
72
- if file.name.endswith('.csv'):
73
- df = pd.read_csv(file.name)
74
- elif file.name.endswith(('.xlsx', '.xls')):
75
- df = pd.read_excel(file.name)
76
- else:
77
- return "❌ Please upload a CSV or Excel file", None
78
-
79
- if df.empty:
80
- return "❌ The uploaded file is empty", None
81
-
82
- # Get Salesforce object
83
- sf_object = getattr(sf_connection, object_name)
84
-
85
- # Prepare data for upload
86
- records = df.to_dict('records')
87
-
88
- # Clean data - remove NaN values
89
- cleaned_records = []
90
- for record in records:
91
- cleaned_record = {k: v for k, v in record.items() if pd.notna(v)}
92
- cleaned_records.append(cleaned_record)
93
-
94
- # Perform operation
95
- if operation == "Insert":
96
- result = sf_object.bulk.insert(cleaned_records)
97
- elif operation == "Update":
98
- result = sf_object.bulk.update(cleaned_records)
99
- else: # Upsert
100
- return "❌ Upsert operation requires additional configuration", None
101
-
102
- # Process results
103
- success_count = sum(1 for r in result if r.get('success'))
104
- error_count = len(result) - success_count
105
-
106
- summary = f"✅ Operation completed!\n"
107
- summary += f"📊 Total records: {len(records)}\n"
108
- summary += f"✅ Successful: {success_count}\n"
109
- summary += f"❌ Failed: {error_count}\n"
110
-
111
- # Create results file
112
- results_df = pd.DataFrame(result)
113
- results_file = f"salesforce_upload_results_{datetime.now().strftime('%Y%m%d_%H%M%S')}.csv"
114
- results_df.to_csv(results_file, index=False)
115
-
116
- return summary, results_file
117
-
118
- except Exception as e:
119
- logger.error(f"Upload error: {str(e)}")
120
- return f"❌ Error: {str(e)}", None
121
-
122
- def export_data_from_salesforce(object_name, record_limit):
123
- """Export data from Salesforce"""
124
- global sf_connection
125
-
126
- if not sf_connection:
127
- return "❌ Please connect to Salesforce first", None
128
-
129
- if not object_name:
130
- return "❌ Please select an object", None
131
-
132
- try:
133
- # Get object metadata to find some fields
134
- obj = getattr(sf_connection, object_name)
135
- metadata = obj.describe()
136
-
137
- # Get first 10 fields
138
- fields = [field['name'] for field in metadata['fields'][:10]]
139
- fields_str = ', '.join(fields)
140
-
141
- # Build and execute query
142
- query = f"SELECT {fields_str} FROM {object_name} LIMIT {record_limit}"
143
- result = sf_connection.query_all(query)
144
- records = result['records']
145
-
146
- if not records:
147
- return "❌ No records found", None
148
-
149
- # Convert to DataFrame and clean
150
- df = pd.DataFrame(records)
151
- if 'attributes' in df.columns:
152
- df = df.drop('attributes', axis=1)
153
-
154
- # Create export file
155
- export_file = f"salesforce_export_{object_name}_{datetime.now().strftime('%Y%m%d_%H%M%S')}.csv"
156
- df.to_csv(export_file, index=False)
157
-
158
- summary = f"✅ Export completed!\n"
159
- summary += f"📊 Records exported: {len(records)}\n"
160
- summary += f"📋 Fields: {', '.join(fields)}\n"
161
-
162
- return summary, export_file
163
-
164
- except Exception as e:
165
- logger.error(f"Export error: {str(e)}")
166
- return f"❌ Error: {str(e)}", None
167
-
168
- # Create the Gradio interface
169
- with gr.Blocks(title="Salesforce Data Loader", theme=gr.themes.Default()) as demo:
170
- gr.Markdown("""
171
- # 🚀 Salesforce Data Loader
172
- A simple tool to upload and download data from Salesforce.
173
- """)
174
-
175
- with gr.Tab("🔐 Connect"):
176
- gr.Markdown("### Connect to Salesforce")
177
- username = gr.Textbox(label="Username", placeholder="[email protected]")
178
- password = gr.Textbox(label="Password", type="password")
179
- security_token = gr.Textbox(label="Security Token", type="password")
180
- sandbox = gr.Checkbox(label="Sandbox Environment")
181
- connect_btn = gr.Button("🔗 Connect", variant="primary")
182
- connection_status = gr.Textbox(label="Connection Status", interactive=False)
183
-
184
- connect_btn.click(
185
- fn=connect_to_salesforce,
186
- inputs=[username, password, security_token, sandbox],
187
- outputs=[connection_status]
188
- )
189
 
190
- with gr.Tab("📤 Upload"):
191
- gr.Markdown("### Upload CSV/Excel data to Salesforce")
192
- file_upload = gr.File(label="Upload CSV or Excel file")
193
- upload_object = gr.Dropdown(
194
- label="Salesforce Object",
195
- choices=["Account", "Contact", "Lead", "Opportunity", "Case"],
196
- value="Contact"
197
- )
198
- upload_operation = gr.Dropdown(
199
- label="Operation",
200
- choices=["Insert", "Update"],
201
- value="Insert"
202
- )
203
- upload_btn = gr.Button("📤 Upload Data", variant="primary")
204
- upload_results = gr.Textbox(label="Upload Results", interactive=False)
205
- download_results = gr.File(label="Download Results")
206
-
207
- upload_btn.click(
208
- fn=upload_data_to_salesforce,
209
- inputs=[file_upload, upload_object, upload_operation],
210
- outputs=[upload_results, download_results]
211
- )
212
 
213
- with gr.Tab("📥 Export"):
214
- gr.Markdown("### Export data from Salesforce")
215
- export_object = gr.Dropdown(
216
- label="Salesforce Object",
217
- choices=["Account", "Contact", "Lead", "Opportunity", "Case"],
218
- value="Account"
219
- )
220
- export_limit = gr.Slider(
221
- label="Record Limit",
222
- minimum=100,
223
- maximum=10000,
224
- value=1000,
225
- step=100
226
- )
227
- export_btn = gr.Button("📥 Export Data", variant="primary")
228
- export_results = gr.Textbox(label="Export Results", interactive=False)
229
- download_export = gr.File(label="Download Export")
230
-
231
- export_btn.click(
232
- fn=export_data_from_salesforce,
233
- inputs=[export_object, export_limit],
234
- outputs=[export_results, download_export]
235
- )
236
 
237
  if __name__ == "__main__":
238
  demo.launch(server_name="0.0.0.0", server_port=7860)
 
1
  import gradio as gr
2
  import pandas as pd
3
  from simple_salesforce import Salesforce
 
4
  from datetime import datetime
5
  import logging
6
 
 
8
  logging.basicConfig(level=logging.INFO)
9
  logger = logging.getLogger(__name__)
10
 
11
+ # Global connection
12
  sf_connection = None
 
13
 
14
+ def salesforce_data_loader(username, password, security_token, sandbox, operation, csv_file):
15
+ """Main function that handles all Salesforce operations"""
16
+ global sf_connection
17
+
18
+ # Step 1: Connect to Salesforce
19
+ if not username or not password or not security_token:
20
+ return "❌ Please provide username, password, and security token"
21
 
22
  try:
23
  domain = 'test' if sandbox else None
 
28
  domain=domain
29
  )
30
 
31
+ connection_msg = f"✅ Connected to Salesforce as {username}\n"
 
 
32
 
33
+ # Step 2: Handle file upload if provided
34
+ if csv_file is not None and operation != "connect_only":
35
  try:
36
+ # Read the file
37
+ if csv_file.name.endswith('.csv'):
38
+ df = pd.read_csv(csv_file.name)
39
+ elif csv_file.name.endswith(('.xlsx', '.xls')):
40
+ df = pd.read_excel(csv_file.name)
41
+ else:
42
+ return connection_msg + "❌ Please upload a CSV or Excel file"
43
+
44
+ if df.empty:
45
+ return connection_msg + "❌ The uploaded file is empty"
46
+
47
+ # Clean data
48
+ records = df.to_dict('records')
49
+ cleaned_records = []
50
+ for record in records:
51
+ cleaned_record = {k: v for k, v in record.items() if pd.notna(v)}
52
+ cleaned_records.append(cleaned_record)
53
+
54
+ # Determine object based on columns (simple heuristic)
55
+ columns = df.columns.str.lower()
56
+ if any(col in columns for col in ['firstname', 'lastname', 'email']):
57
+ sf_object = sf_connection.Contact
58
+ object_name = "Contact"
59
+ elif any(col in columns for col in ['company', 'name']):
60
+ sf_object = sf_connection.Account
61
+ object_name = "Account"
62
+ else:
63
+ sf_object = sf_connection.Lead
64
+ object_name = "Lead"
65
+
66
+ # Perform operation
67
+ if operation == "insert":
68
+ result = sf_object.bulk.insert(cleaned_records)
69
+ elif operation == "update":
70
+ result = sf_object.bulk.update(cleaned_records)
71
+ else:
72
+ return connection_msg + "❌ Invalid operation"
73
+
74
+ # Process results
75
+ success_count = sum(1 for r in result if r.get('success'))
76
+ error_count = len(result) - success_count
77
+
78
+ upload_msg = f"\n📤 Upload Results:\n"
79
+ upload_msg += f"Object: {object_name}\n"
80
+ upload_msg += f"Total records: {len(records)}\n"
81
+ upload_msg += f"✅ Successful: {success_count}\n"
82
+ upload_msg += f"❌ Failed: {error_count}\n"
83
+
84
+ return connection_msg + upload_msg
85
+
86
+ except Exception as e:
87
+ return connection_msg + f"❌ Upload error: {str(e)}"
88
+
89
+ # Step 3: Handle export operation
90
+ elif operation == "export":
91
+ try:
92
+ # Export some Account records as example
93
+ query = "SELECT Id, Name, Type, Phone, Website FROM Account LIMIT 100"
94
+ result = sf_connection.query_all(query)
95
+ records = result['records']
96
+
97
+ if records:
98
+ df = pd.DataFrame(records)
99
+ if 'attributes' in df.columns:
100
+ df = df.drop('attributes', axis=1)
101
+
102
+ export_msg = f"\n📥 Export Results:\n"
103
+ export_msg += f"Records exported: {len(records)}\n"
104
+ export_msg += f"Fields: {', '.join(df.columns)}\n"
105
+ export_msg += f"Sample data:\n{df.head().to_string()}"
106
+
107
+ return connection_msg + export_msg
108
+ else:
109
+ return connection_msg + "\n❌ No records found to export"
110
+
111
+ except Exception as e:
112
+ return connection_msg + f"\n❌ Export error: {str(e)}"
113
 
114
+ else:
115
+ return connection_msg + "\n💡 Connection successful! Upload a file to insert/update data, or select 'export' to download data."
116
 
 
 
117
  except Exception as e:
 
 
118
  error_msg = str(e)
 
119
  if "INVALID_LOGIN" in error_msg:
120
  return "❌ Invalid credentials. Please check your username, password, and security token."
121
  elif "API_DISABLED_FOR_ORG" in error_msg:
122
+ return "❌ API access is disabled. Contact your Salesforce admin."
123
  elif "LOGIN_MUST_USE_SECURITY_TOKEN" in error_msg:
124
+ return "❌ Security token required. Append it to your password."
125
  else:
126
  return f"❌ Connection failed: {error_msg}"
127
 
128
+ # Create the interface
129
+ demo = gr.Interface(
130
+ fn=salesforce_data_loader,
131
+ inputs=[
132
+ gr.Textbox(label="Username", placeholder="[email protected]"),
133
+ gr.Textbox(label="Password", type="password"),
134
+ gr.Textbox(label="Security Token", type="password"),
135
+ gr.Checkbox(label="Sandbox Environment"),
136
+ gr.Dropdown(
137
+ label="Operation",
138
+ choices=["connect_only", "insert", "update", "export"],
139
+ value="connect_only"
140
+ ),
141
+ gr.File(label="CSV/Excel File (optional)", file_types=[".csv", ".xlsx", ".xls"])
142
+ ],
143
+ outputs=gr.Textbox(label="Results", lines=10),
144
+ title="🚀 Salesforce Data Loader",
145
+ description="""
146
+ **Simple Salesforce Data Management Tool**
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
147
 
148
+ 1. **Connect**: Enter your credentials and select 'connect_only'
149
+ 2. **Upload**: Select 'insert' or 'update' and upload a CSV/Excel file
150
+ 3. **Export**: Select 'export' to download Account data
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
151
 
152
+ **Note**: For uploads, the tool auto-detects object type based on column names.
153
+ """,
154
+ examples=[
155
+ ["[email protected]", "password123", "token123", False, "connect_only", None],
156
+ ]
157
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
158
 
159
  if __name__ == "__main__":
160
  demo.launch(server_name="0.0.0.0", server_port=7860)