jithenderchoudary commited on
Commit
8a21dba
·
verified ·
1 Parent(s): 486a750

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +203 -0
app.py ADDED
@@ -0,0 +1,203 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import FastAPI, Request, HTTPException
2
+ from fastapi.responses import HTMLResponse, FileResponse
3
+ from fastapi.staticfiles import StaticFiles
4
+ from fastapi.templating import Jinja2Templates
5
+ from simple_salesforce import Salesforce
6
+ from apscheduler.schedulers.asyncio import AsyncIOScheduler
7
+ import sqlite3
8
+ import os
9
+ import logging
10
+ from tenacity import retry, stop_after_attempt, wait_fixed, retry_if_exception_type
11
+ from dotenv import load_dotenv
12
+
13
+ # Load environment variables from .env file (for local development)
14
+ load_dotenv()
15
+
16
+ # Set up logging
17
+ logging.basicConfig(level=logging.DEBUG)
18
+ logger = logging.getLogger(__name__)
19
+
20
+ app = FastAPI()
21
+
22
+ # Mount static files
23
+ app.mount("/static", StaticFiles(directory="static"), name="static")
24
+
25
+ # Set up templates
26
+ templates = Jinja2Templates(directory="templates")
27
+
28
+ # Initialize SQLite database
29
+ def init_db():
30
+ try:
31
+ conn = sqlite3.connect("cases.db")
32
+ cursor = conn.cursor()
33
+ cursor.execute("""
34
+ CREATE TABLE IF NOT EXISTS cases (
35
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
36
+ name TEXT NOT NULL,
37
+ mobile_number TEXT,
38
+ email TEXT NOT NULL,
39
+ issue_description TEXT NOT NULL,
40
+ synced INTEGER DEFAULT 0
41
+ )
42
+ """)
43
+ conn.commit()
44
+ conn.close()
45
+ logger.debug("SQLite database initialized successfully.")
46
+ except Exception as e:
47
+ logger.error(f"Error initializing SQLite database: {e}")
48
+ raise
49
+
50
+ # Run database initialization on startup
51
+ init_db()
52
+
53
+ # Salesforce connection (using environment variables)
54
+ def get_salesforce_connection():
55
+ try:
56
+ username = os.getenv("SFDC_USERNAME")
57
+ password = os.getenv("SFDC_PASSWORD")
58
+ security_token = os.getenv("SFDC_SECURITY_TOKEN")
59
+ domain = os.getenv("SFDC_DOMAIN", "login")
60
+
61
+ if not username or not password or not security_token:
62
+ logger.error("Missing Salesforce credentials.")
63
+ return None
64
+
65
+ sf = Salesforce(
66
+ username=username,
67
+ password=password,
68
+ security_token=security_token,
69
+ domain=domain
70
+ )
71
+ logger.debug("Salesforce connection successful.")
72
+ return sf
73
+ except Exception as e:
74
+ logger.error(f"Error connecting to Salesforce: {e}")
75
+ return None
76
+
77
+ # Sync function with retry logic
78
+ @retry(
79
+ stop=stop_after_attempt(3),
80
+ wait=wait_fixed(2),
81
+ retry=retry_if_exception_type(Exception),
82
+ before_sleep=lambda retry_state: logger.debug(f"Retrying Salesforce sync, attempt {retry_state.attempt_number}")
83
+ )
84
+ async def sync_to_salesforce():
85
+ try:
86
+ sf = get_salesforce_connection()
87
+ if not sf:
88
+ logger.error("Cannot sync: Salesforce connection failed.")
89
+ return
90
+
91
+ conn = sqlite3.connect("cases.db")
92
+ cursor = conn.cursor()
93
+ cursor.execute("SELECT * FROM cases WHERE synced = 0")
94
+ cases = cursor.fetchall()
95
+
96
+ for case in cases:
97
+ case_id, name, mobile_number, email, issue_description, _ = case
98
+ case_data = {
99
+ "Name": name,
100
+ "Mobile_Number__c": mobile_number,
101
+ "Email__c": email,
102
+ "Issue_Description__c": issue_description
103
+ }
104
+ sf.Case__c.create(case_data)
105
+ cursor.execute("UPDATE cases SET synced = 1 WHERE id = ?", (case_id,))
106
+ conn.commit()
107
+ logger.debug(f"Synced case ID {case_id} to Salesforce.")
108
+ conn.close()
109
+ except Exception as e:
110
+ logger.error(f"Error syncing to Salesforce: {str(e)}")
111
+ raise
112
+
113
+ # Set up scheduler
114
+ scheduler = AsyncIOScheduler()
115
+ scheduler.add_job(sync_to_salesforce, "interval", hours=4)
116
+
117
+ @app.on_event("startup")
118
+ async def startup_event():
119
+ scheduler.start()
120
+ logger.debug("Scheduler started successfully.")
121
+
122
+ @app.on_event("shutdown")
123
+ async def shutdown_event():
124
+ scheduler.shutdown()
125
+ logger.debug("Scheduler shut down successfully.")
126
+
127
+ @app.get("/", response_class=HTMLResponse)
128
+ async def index(request: Request):
129
+ return templates.TemplateResponse("index.html", {"request": request})
130
+
131
+ @app.get("/static/{filename}")
132
+ async def serve_static(filename: str):
133
+ file_path = os.path.join("static", filename)
134
+ if not os.path.exists(file_path):
135
+ raise HTTPException(status_code=404, detail="File not found")
136
+ return FileResponse(file_path)
137
+
138
+ @app.post("/submit-case")
139
+ async def submit_case(request: Request):
140
+ try:
141
+ data = await request.json()
142
+ logger.debug(f"Received form data: {data}")
143
+
144
+ # Extract form data with default values and strip whitespace
145
+ name = data.get("name", "").strip()
146
+ mobile_number = data.get("mobileNumber", "").strip()
147
+ email = data.get("email", "").strip()
148
+ issue_description = data.get("issueDescription", "").strip()
149
+
150
+ # Validate required fields with specific error messages
151
+ if not name:
152
+ logger.error("Missing 'name' field in form data.")
153
+ raise HTTPException(status_code=400, detail="Name is required")
154
+ if not email:
155
+ logger.error("Missing 'email' field in form data.")
156
+ raise HTTPException(status_code=400, detail="Email is required")
157
+ if not issue_description:
158
+ logger.error("Missing 'issueDescription' field in form data.")
159
+ raise HTTPException(status_code=400, detail="Issue description is required")
160
+
161
+ # Basic email validation
162
+ if "@" not in email or "." not in email:
163
+ logger.error("Invalid email format.")
164
+ raise HTTPException(status_code=400, detail="Invalid email format")
165
+
166
+ # Store in SQLite
167
+ conn = sqlite3.connect("cases.db")
168
+ cursor = conn.cursor()
169
+ cursor.execute(
170
+ """
171
+ INSERT INTO cases (name, mobile_number, email, issue_description)
172
+ VALUES (?, ?, ?, ?)
173
+ """,
174
+ (name, mobile_number, email, issue_description)
175
+ )
176
+ conn.commit()
177
+ conn.close()
178
+ logger.debug("Data successfully stored in SQLite.")
179
+
180
+ # Immediately trigger sync
181
+ await sync_to_salesforce()
182
+
183
+ return {"success": True}
184
+ except Exception as e:
185
+ logger.error(f"Error processing request: {str(e)}")
186
+ raise HTTPException(status_code=500, detail=str(e))
187
+
188
+ @app.get("/debug-cases")
189
+ async def debug_cases():
190
+ try:
191
+ conn = sqlite3.connect("cases.db")
192
+ cursor = conn.cursor()
193
+ cursor.execute("SELECT * FROM cases")
194
+ cases = cursor.fetchall()
195
+ conn.close()
196
+ return {"cases": cases}
197
+ except Exception as e:
198
+ logger.error(f"Error retrieving cases: {str(e)}")
199
+ raise HTTPException(status_code=500, detail=str(e))
200
+
201
+ if __name__ == "__main__":
202
+ import uvicorn
203
+ uvicorn.run(app, host="0.0.0.0", port=7860)