Spaces:
Sleeping
Sleeping
Update sheets_integration.py
Browse files- sheets_integration.py +37 -94
sheets_integration.py
CHANGED
@@ -1,9 +1,11 @@
|
|
|
|
1 |
import os
|
2 |
import json
|
3 |
from datetime import datetime
|
4 |
from enum import Enum
|
5 |
import gspread
|
6 |
from google.oauth2 import service_account
|
|
|
7 |
|
8 |
class RequestStatus(Enum):
|
9 |
NEW = "New"
|
@@ -17,6 +19,7 @@ class RequestStatus(Enum):
|
|
17 |
|
18 |
class SheetsLogger:
|
19 |
def __init__(self):
|
|
|
20 |
self.gc = None
|
21 |
self.sheet = None
|
22 |
self.initialize_client()
|
@@ -27,10 +30,16 @@ class SheetsLogger:
|
|
27 |
# Get credentials from environment variable
|
28 |
creds_json = os.getenv('GOOGLE_SHEETS_CREDS')
|
29 |
if not creds_json:
|
30 |
-
|
31 |
-
|
|
|
32 |
# Parse credentials JSON
|
33 |
-
|
|
|
|
|
|
|
|
|
|
|
34 |
|
35 |
# Create credentials object
|
36 |
credentials = service_account.Credentials.from_service_account_info(
|
@@ -44,17 +53,20 @@ class SheetsLogger:
|
|
44 |
self.gc = gspread.authorize(credentials)
|
45 |
|
46 |
# Open spreadsheet by ID
|
47 |
-
|
48 |
-
if not
|
49 |
-
|
|
|
50 |
|
51 |
-
self.sheet = self.gc.open_by_key(
|
|
|
52 |
|
53 |
# Initialize headers if needed
|
54 |
self.initialize_sheet()
|
55 |
|
56 |
except Exception as e:
|
57 |
print(f"Error initializing Google Sheets client: {str(e)}")
|
|
|
58 |
self.gc = None
|
59 |
self.sheet = None
|
60 |
|
@@ -80,21 +92,22 @@ class SheetsLogger:
|
|
80 |
# Check if headers exist
|
81 |
existing_headers = self.sheet.row_values(1)
|
82 |
if not existing_headers:
|
|
|
83 |
self.sheet.insert_row(headers, 1)
|
84 |
# Format header row
|
85 |
self.sheet.format('A1:M1', {
|
86 |
"backgroundColor": {"red": 0.2, "green": 0.2, "blue": 0.2},
|
87 |
"textFormat": {"bold": True, "foregroundColor": {"red": 1, "green": 1, "blue": 1}}
|
88 |
})
|
89 |
-
|
90 |
-
|
91 |
-
"wrapStrategy": "WRAP"
|
92 |
-
})
|
93 |
except Exception as e:
|
94 |
print(f"Error initializing headers: {str(e)}")
|
|
|
95 |
|
96 |
-
def log_request(self, data):
|
97 |
"""Log a request to Google Sheets"""
|
|
|
98 |
if not self.sheet:
|
99 |
print("Sheet not initialized")
|
100 |
return False
|
@@ -102,7 +115,7 @@ class SheetsLogger:
|
|
102 |
try:
|
103 |
# Prepare row data
|
104 |
row = [
|
105 |
-
|
106 |
data.get('name', ''),
|
107 |
data.get('employee_id', ''),
|
108 |
data.get('email', ''),
|
@@ -118,12 +131,14 @@ class SheetsLogger:
|
|
118 |
]
|
119 |
|
120 |
# Append row to sheet
|
|
|
121 |
self.sheet.append_row(row)
|
122 |
|
123 |
# Get the row number that was just added
|
124 |
last_row = len(self.sheet.get_all_values())
|
125 |
|
126 |
# Apply conditional formatting for status
|
|
|
127 |
self.apply_status_formatting(last_row)
|
128 |
|
129 |
print(f"Successfully logged request to row {last_row}")
|
@@ -131,36 +146,19 @@ class SheetsLogger:
|
|
131 |
|
132 |
except Exception as e:
|
133 |
print(f"Error logging to sheet: {str(e)}")
|
|
|
134 |
return False
|
135 |
|
136 |
-
def apply_status_formatting(self, row_number):
|
137 |
"""Apply conditional formatting based on status"""
|
138 |
status_cell = f'K{row_number}'
|
139 |
formats = {
|
140 |
-
RequestStatus.NEW.value: {
|
141 |
-
|
142 |
-
},
|
143 |
-
RequestStatus.
|
144 |
-
|
145 |
-
}
|
146 |
-
RequestStatus.PENDING_INFO.value: {
|
147 |
-
"backgroundColor": {"red": 1, "green": 0.8, "blue": 0.8} # Light red
|
148 |
-
},
|
149 |
-
RequestStatus.DATA_COLLECTION.value: {
|
150 |
-
"backgroundColor": {"red": 0.8, "green": 1, "blue": 0.8} # Light green
|
151 |
-
},
|
152 |
-
RequestStatus.READY_FOR_REVIEW.value: {
|
153 |
-
"backgroundColor": {"red": 0.9, "green": 0.9, "blue": 1} # Light purple
|
154 |
-
},
|
155 |
-
RequestStatus.COMPLETED.value: {
|
156 |
-
"backgroundColor": {"red": 0.9, "green": 1, "blue": 0.9} # Lighter green
|
157 |
-
},
|
158 |
-
RequestStatus.CANCELLED.value: {
|
159 |
-
"backgroundColor": {"red": 0.9, "green": 0.9, "blue": 0.9} # Gray
|
160 |
-
},
|
161 |
-
RequestStatus.ON_HOLD.value: {
|
162 |
-
"backgroundColor": {"red": 1, "green": 0.9, "blue": 0.8} # Light orange
|
163 |
-
}
|
164 |
}
|
165 |
|
166 |
try:
|
@@ -168,59 +166,4 @@ class SheetsLogger:
|
|
168 |
if status in formats:
|
169 |
self.sheet.format(status_cell, formats[status])
|
170 |
except Exception as e:
|
171 |
-
print(f"Error applying formatting: {str(e)}")
|
172 |
-
|
173 |
-
def update_status(self, row_number, new_status, notes=None):
|
174 |
-
"""Update the status and notes of a request"""
|
175 |
-
try:
|
176 |
-
if not isinstance(new_status, str):
|
177 |
-
if isinstance(new_status, RequestStatus):
|
178 |
-
new_status = new_status.value
|
179 |
-
else:
|
180 |
-
raise ValueError("Invalid status type")
|
181 |
-
|
182 |
-
# Update status
|
183 |
-
self.sheet.update_cell(row_number, 11, new_status) # Column K
|
184 |
-
|
185 |
-
# Update notes if provided
|
186 |
-
if notes:
|
187 |
-
current_notes = self.sheet.cell(row_number, 12).value # Column L
|
188 |
-
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
189 |
-
updated_notes = f"{current_notes}\n{timestamp}: {notes}" if current_notes else f"{timestamp}: {notes}"
|
190 |
-
self.sheet.update_cell(row_number, 12, updated_notes)
|
191 |
-
|
192 |
-
# Update last updated timestamp
|
193 |
-
self.sheet.update_cell(row_number, 13, datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
|
194 |
-
|
195 |
-
# Apply formatting
|
196 |
-
self.apply_status_formatting(row_number)
|
197 |
-
|
198 |
-
return True
|
199 |
-
except Exception as e:
|
200 |
-
print(f"Error updating status: {str(e)}")
|
201 |
-
return False
|
202 |
-
|
203 |
-
def get_request_history(self, request_id=None, employee_id=None):
|
204 |
-
"""Get request history filtered by ID or employee"""
|
205 |
-
try:
|
206 |
-
all_data = self.sheet.get_all_records()
|
207 |
-
if request_id:
|
208 |
-
return [row for row in all_data if str(row.get('Employee ID', '')).strip() == str(request_id).strip()]
|
209 |
-
elif employee_id:
|
210 |
-
return [row for row in all_data if str(row.get('Employee ID', '')).strip() == str(employee_id).strip()]
|
211 |
-
return all_data
|
212 |
-
except Exception as e:
|
213 |
-
print(f"Error getting history: {str(e)}")
|
214 |
-
return []
|
215 |
-
|
216 |
-
def get_request_by_row(self, row_number):
|
217 |
-
"""Get a specific request by row number"""
|
218 |
-
try:
|
219 |
-
if row_number < 2: # Row 1 is headers
|
220 |
-
return None
|
221 |
-
row_data = self.sheet.row_values(row_number)
|
222 |
-
headers = self.sheet.row_values(1)
|
223 |
-
return dict(zip(headers, row_data))
|
224 |
-
except Exception as e:
|
225 |
-
print(f"Error getting row {row_number}: {str(e)}")
|
226 |
-
return None
|
|
|
1 |
+
# sheets_integration.py
|
2 |
import os
|
3 |
import json
|
4 |
from datetime import datetime
|
5 |
from enum import Enum
|
6 |
import gspread
|
7 |
from google.oauth2 import service_account
|
8 |
+
import traceback
|
9 |
|
10 |
class RequestStatus(Enum):
|
11 |
NEW = "New"
|
|
|
19 |
|
20 |
class SheetsLogger:
|
21 |
def __init__(self):
|
22 |
+
print("Initializing SheetsLogger")
|
23 |
self.gc = None
|
24 |
self.sheet = None
|
25 |
self.initialize_client()
|
|
|
30 |
# Get credentials from environment variable
|
31 |
creds_json = os.getenv('GOOGLE_SHEETS_CREDS')
|
32 |
if not creds_json:
|
33 |
+
print("Google Sheets credentials not found in environment")
|
34 |
+
return
|
35 |
+
|
36 |
# Parse credentials JSON
|
37 |
+
try:
|
38 |
+
creds_dict = json.loads(creds_json)
|
39 |
+
print("Credentials JSON parsed successfully")
|
40 |
+
except json.JSONDecodeError as e:
|
41 |
+
print(f"Error parsing credentials JSON: {e}")
|
42 |
+
return
|
43 |
|
44 |
# Create credentials object
|
45 |
credentials = service_account.Credentials.from_service_account_info(
|
|
|
53 |
self.gc = gspread.authorize(credentials)
|
54 |
|
55 |
# Open spreadsheet by ID
|
56 |
+
sheet_id = os.getenv('GOOGLE_SHEET_ID')
|
57 |
+
if not sheet_id:
|
58 |
+
print("Google Sheet ID not found in environment")
|
59 |
+
return
|
60 |
|
61 |
+
self.sheet = self.gc.open_by_key(sheet_id).sheet1
|
62 |
+
print("Sheet connected successfully")
|
63 |
|
64 |
# Initialize headers if needed
|
65 |
self.initialize_sheet()
|
66 |
|
67 |
except Exception as e:
|
68 |
print(f"Error initializing Google Sheets client: {str(e)}")
|
69 |
+
print(traceback.format_exc())
|
70 |
self.gc = None
|
71 |
self.sheet = None
|
72 |
|
|
|
92 |
# Check if headers exist
|
93 |
existing_headers = self.sheet.row_values(1)
|
94 |
if not existing_headers:
|
95 |
+
print("Adding headers to sheet")
|
96 |
self.sheet.insert_row(headers, 1)
|
97 |
# Format header row
|
98 |
self.sheet.format('A1:M1', {
|
99 |
"backgroundColor": {"red": 0.2, "green": 0.2, "blue": 0.2},
|
100 |
"textFormat": {"bold": True, "foregroundColor": {"red": 1, "green": 1, "blue": 1}}
|
101 |
})
|
102 |
+
else:
|
103 |
+
print("Headers already exist")
|
|
|
|
|
104 |
except Exception as e:
|
105 |
print(f"Error initializing headers: {str(e)}")
|
106 |
+
print(traceback.format_exc())
|
107 |
|
108 |
+
def log_request(self, data: dict) -> bool:
|
109 |
"""Log a request to Google Sheets"""
|
110 |
+
print("Attempting to log request to sheets")
|
111 |
if not self.sheet:
|
112 |
print("Sheet not initialized")
|
113 |
return False
|
|
|
115 |
try:
|
116 |
# Prepare row data
|
117 |
row = [
|
118 |
+
datetime.now().strftime("%Y-%m-%d %H:%M:%S"), # Timestamp
|
119 |
data.get('name', ''),
|
120 |
data.get('employee_id', ''),
|
121 |
data.get('email', ''),
|
|
|
131 |
]
|
132 |
|
133 |
# Append row to sheet
|
134 |
+
print("Appending row to sheet")
|
135 |
self.sheet.append_row(row)
|
136 |
|
137 |
# Get the row number that was just added
|
138 |
last_row = len(self.sheet.get_all_values())
|
139 |
|
140 |
# Apply conditional formatting for status
|
141 |
+
print("Applying status formatting")
|
142 |
self.apply_status_formatting(last_row)
|
143 |
|
144 |
print(f"Successfully logged request to row {last_row}")
|
|
|
146 |
|
147 |
except Exception as e:
|
148 |
print(f"Error logging to sheet: {str(e)}")
|
149 |
+
print(traceback.format_exc())
|
150 |
return False
|
151 |
|
152 |
+
def apply_status_formatting(self, row_number: int):
|
153 |
"""Apply conditional formatting based on status"""
|
154 |
status_cell = f'K{row_number}'
|
155 |
formats = {
|
156 |
+
RequestStatus.NEW.value: {"backgroundColor": {"red": 1, "green": 1, "blue": 0.8}},
|
157 |
+
RequestStatus.IN_PROGRESS.value: {"backgroundColor": {"red": 0.8, "green": 0.9, "blue": 1}},
|
158 |
+
RequestStatus.PENDING_INFO.value: {"backgroundColor": {"red": 1, "green": 0.8, "blue": 0.8}},
|
159 |
+
RequestStatus.DATA_COLLECTION.value: {"backgroundColor": {"red": 0.8, "green": 1, "blue": 0.8}},
|
160 |
+
RequestStatus.READY_FOR_REVIEW.value: {"backgroundColor": {"red": 0.9, "green": 0.9, "blue": 1}},
|
161 |
+
RequestStatus.COMPLETED.value: {"backgroundColor": {"red": 0.9, "green": 1, "blue": 0.9}}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
162 |
}
|
163 |
|
164 |
try:
|
|
|
166 |
if status in formats:
|
167 |
self.sheet.format(status_cell, formats[status])
|
168 |
except Exception as e:
|
169 |
+
print(f"Error applying formatting: {str(e)}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|