sonuprasad23 commited on
Commit
ed9a133
·
1 Parent(s): 96e57ad

Fixing this

Browse files
Files changed (2) hide show
  1. server.py +1 -8
  2. worker.py +42 -20
server.py CHANGED
@@ -54,7 +54,6 @@ def _read_tabular_from_b64(filename: str, b64_content: str) -> pd.DataFrame:
54
  bio = io.BytesIO(raw)
55
  if ext.endswith('.xlsx'):
56
  return pd.read_excel(bio)
57
- # default csv
58
  return pd.read_csv(io.StringIO(raw.decode('utf-8', errors='ignore')))
59
 
60
  # =========================
@@ -70,7 +69,7 @@ class GmailApiService:
70
  from googleapiclient.discovery import build
71
  base64_creds = os.getenv('GDRIVE_SA_KEY_BASE64')
72
  if not base64_creds:
73
- print("[Server Log] WARNING: GDRIVE_SA_KEY_BASE4 not found for Gmail.")
74
  return
75
  creds_json = base64.b64decode(base64_creds).decode('utf-8')
76
  creds_dict = json.loads(creds_json)
@@ -349,7 +348,6 @@ def handle_initialize_and_process_files(payload):
349
  if k not in payload:
350
  raise ValueError(f"Missing required field: {k}")
351
 
352
- # Read files
353
  df_app = _read_tabular_from_b64(payload['app_data_filename'], payload['app_data_content'])
354
  df_quantum = _read_tabular_from_b64(payload['quantum_data_filename'], payload['quantum_data_content'])
355
 
@@ -358,7 +356,6 @@ def handle_initialize_and_process_files(payload):
358
  if 'Name' not in df_quantum.columns:
359
  raise ValueError("Quantum Data must contain a 'Name' column.")
360
 
361
- # Build PRN lookup from App Data
362
  df_app_filtered = df_app.dropna(subset=['PRN'])
363
  df_app_filtered = df_app_filtered[df_app_filtered['PRN'].astype(str).str.strip() != '']
364
  prn_lookup = {
@@ -366,16 +363,13 @@ def handle_initialize_and_process_files(payload):
366
  for _, row in df_app_filtered.iterrows()
367
  }
368
 
369
- # Assign PRN to Quantum by exact Name match (expected to be cleaned already)
370
  df_quantum['PRN'] = df_quantum['Name'].apply(lambda name: prn_lookup.get(name, ""))
371
 
372
- # Prepare master with Status
373
  master_df = df_quantum.copy()
374
  if 'PRN' not in master_df.columns:
375
  master_df['PRN'] = ''
376
  master_df['Status'] = ''
377
 
378
- # Save to session
379
  session_data[session_id] = {
380
  'emails': payload.get('emails', []),
381
  'filename': (payload.get('filename') or '').strip(),
@@ -386,7 +380,6 @@ def handle_initialize_and_process_files(payload):
386
  'patient_data': master_df.to_dict('records')
387
  }
388
 
389
- # Signal UI to open login modal
390
  emit('data_processed')
391
  print(f"[Server Log] Data prepared. Total records: {len(master_df)}")
392
  except Exception as e:
 
54
  bio = io.BytesIO(raw)
55
  if ext.endswith('.xlsx'):
56
  return pd.read_excel(bio)
 
57
  return pd.read_csv(io.StringIO(raw.decode('utf-8', errors='ignore')))
58
 
59
  # =========================
 
69
  from googleapiclient.discovery import build
70
  base64_creds = os.getenv('GDRIVE_SA_KEY_BASE64')
71
  if not base64_creds:
72
+ print("[Server Log] WARNING: GDRIVE_SA_KEY_BASE64 not found for Gmail.")
73
  return
74
  creds_json = base64.b64decode(base64_creds).decode('utf-8')
75
  creds_dict = json.loads(creds_json)
 
348
  if k not in payload:
349
  raise ValueError(f"Missing required field: {k}")
350
 
 
351
  df_app = _read_tabular_from_b64(payload['app_data_filename'], payload['app_data_content'])
352
  df_quantum = _read_tabular_from_b64(payload['quantum_data_filename'], payload['quantum_data_content'])
353
 
 
356
  if 'Name' not in df_quantum.columns:
357
  raise ValueError("Quantum Data must contain a 'Name' column.")
358
 
 
359
  df_app_filtered = df_app.dropna(subset=['PRN'])
360
  df_app_filtered = df_app_filtered[df_app_filtered['PRN'].astype(str).str.strip() != '']
361
  prn_lookup = {
 
363
  for _, row in df_app_filtered.iterrows()
364
  }
365
 
 
366
  df_quantum['PRN'] = df_quantum['Name'].apply(lambda name: prn_lookup.get(name, ""))
367
 
 
368
  master_df = df_quantum.copy()
369
  if 'PRN' not in master_df.columns:
370
  master_df['PRN'] = ''
371
  master_df['Status'] = ''
372
 
 
373
  session_data[session_id] = {
374
  'emails': payload.get('emails', []),
375
  'filename': (payload.get('filename') or '').strip(),
 
380
  'patient_data': master_df.to_dict('records')
381
  }
382
 
 
383
  emit('data_processed')
384
  print(f"[Server Log] Data prepared. Total records: {len(master_df)}")
385
  except Exception as e:
worker.py CHANGED
@@ -12,6 +12,7 @@ from selenium.webdriver.support.ui import WebDriverWait
12
  from selenium.webdriver.support import expected_conditions as EC
13
  from selenium.common.exceptions import TimeoutException
14
 
 
15
  class QuantumBot:
16
  def __init__(self, socketio, app):
17
  self.socketio = socketio
@@ -31,8 +32,8 @@ class QuantumBot:
31
 
32
  def initialize_driver(self):
33
  """
34
- Headless on Linux/HF (HEADLESS=1 default), desktop Chrome when HEADLESS=0.
35
- Optionally define CHROME_BINARY and CHROMEDRIVER for custom paths.
36
  """
37
  try:
38
  self.micro_status("Initializing browser...")
@@ -40,7 +41,6 @@ class QuantumBot:
40
  headless = os.getenv("HEADLESS", "1") == "1"
41
 
42
  if headless:
43
- # Headless / CI / HF runner
44
  chrome_binary = os.getenv("CHROME_BINARY", "/usr/bin/chromium")
45
  chromedriver_path = os.getenv("CHROMEDRIVER", "/usr/bin/chromedriver")
46
  options.binary_location = chrome_binary
@@ -53,12 +53,10 @@ class QuantumBot:
53
  options.add_argument(f"--user-agent={ua}")
54
  service = ChromeService(executable_path=chromedriver_path)
55
  else:
56
- # Local desktop with installed Chrome
57
  from webdriver_manager.chrome import ChromeDriverManager
58
  options.add_argument("--start-maximized")
59
  service = ChromeService(ChromeDriverManager().install())
60
 
61
- # Anti-automation flags
62
  options.add_argument('--disable-blink-features=AutomationControlled')
63
  options.add_experimental_option("excludeSwitches", ["enable-automation"])
64
  options.add_experimental_option('useAutomationExtension', False)
@@ -148,7 +146,9 @@ class QuantumBot:
148
 
149
  def _set_date_range_on_page(self, start_date_str, end_date_str):
150
  self.micro_status("Opening calendar...")
151
- date_button = WebDriverWait(self.driver, self.DEFAULT_TIMEOUT).until(EC.element_to_be_clickable((By.XPATH, "//button[.//span[contains(text(), '-')]]")))
 
 
152
  time.sleep(2)
153
  date_button.click()
154
  self._wait_for_page_load(timeout=10)
@@ -234,7 +234,6 @@ class QuantumBot:
234
  self.micro_status(f"Navigating to Void page for '{patient_name}'")
235
  self.driver.get("https://gateway.quantumepay.com/credit-card/void")
236
 
237
- # Search with retries for stability
238
  for attempt in range(15):
239
  try:
240
  self.micro_status(f"Searching... (Attempt {attempt + 1})")
@@ -252,11 +251,17 @@ class QuantumBot:
252
  EC.element_to_be_clickable((By.XPATH, f"//tr[contains(., \"{patient_name}\")]//button[@data-v-b6b33fa0]"))
253
  ).click()
254
 
255
- WebDriverWait(self.driver, self.DEFAULT_TIMEOUT).until(EC.element_to_be_clickable((By.LINK_TEXT, "Transaction Detail"))).click()
 
 
256
 
257
  self.micro_status("Adding to Vault...")
258
- WebDriverWait(self.driver, self.DEFAULT_TIMEOUT).until(EC.element_to_be_clickable((By.XPATH, "//button/span[normalize-space()='Add to Vault']"))).click()
259
- WebDriverWait(self.driver, self.DEFAULT_TIMEOUT).until(EC.element_to_be_clickable((By.XPATH, "//div[@class='modal-footer']//button/span[normalize-space()='Confirm']"))).click()
 
 
 
 
260
 
261
  try:
262
  self.micro_status("Verifying success and saving...")
@@ -264,18 +269,23 @@ class QuantumBot:
264
  company_input.clear(); company_input.send_keys(patient_name)
265
 
266
  contact_input = WebDriverWait(self.driver, 5).until(EC.element_to_be_clickable((By.NAME, "company_contact")))
267
- # Clear reliably then fill PRN
268
  contact_input.click(); contact_input.send_keys(Keys.CONTROL + "a"); contact_input.send_keys(Keys.BACK_SPACE)
269
  contact_input.send_keys(str(patient_prn))
270
 
271
- WebDriverWait(self.driver, self.DEFAULT_TIMEOUT).until(EC.element_to_be_clickable((By.XPATH, "//button/span[normalize-space()='Save Changes']"))).click()
272
- WebDriverWait(self.driver, self.DEFAULT_TIMEOUT).until(EC.element_to_be_clickable((By.XPATH, "//button[.//span[normalize-space()='Confirm']]"))).click()
 
 
 
 
273
  time.sleep(2)
274
  return 'Done'
275
  except TimeoutException:
276
  self.micro_status(f"'{patient_name}' is in a bad state, cancelling.")
277
  try:
278
- WebDriverWait(self.driver, self.DEFAULT_TIMEOUT).until(EC.element_to_be_clickable((By.XPATH, "//button[.//span[normalize-space()='Cancel']]"))).click()
 
 
279
  except Exception:
280
  pass
281
  return 'Bad'
@@ -309,16 +319,22 @@ class QuantumBot:
309
  time.sleep(0.6); details_button.click()
310
  self._wait_for_page_load(timeout=5)
311
 
312
- transaction_link = WebDriverWait(self.driver, self.DEFAULT_TIMEOUT).until(EC.element_to_be_clickable((By.LINK_TEXT, "Transaction Detail")))
 
 
313
  time.sleep(0.6); transaction_link.click()
314
  self._wait_for_page_load()
315
 
316
  self.micro_status("Adding to Vault...")
317
- vault_button = WebDriverWait(self.driver, self.DEFAULT_TIMEOUT).until(EC.element_to_be_clickable((By.XPATH, "//button/span[normalize-space()='Add to Vault']")))
 
 
318
  time.sleep(0.6); vault_button.click()
319
  self._wait_for_page_load()
320
 
321
- confirm_button = WebDriverWait(self.driver, self.DEFAULT_TIMEOUT).until(EC.element_to_be_clickable((By.XPATH, "//div[@class='modal-footer']//button/span[normalize-space()='Confirm']")))
 
 
322
  time.sleep(0.6); confirm_button.click()
323
  self._wait_for_page_load()
324
 
@@ -335,11 +351,15 @@ class QuantumBot:
335
  contact_input.click(); contact_input.send_keys(Keys.CONTROL + "a"); contact_input.send_keys(Keys.BACK_SPACE)
336
  contact_input.send_keys(str(patient_prn))
337
 
338
- save_button = WebDriverWait(self.driver, self.DEFAULT_TIMEOUT).until(EC.element_to_be_clickable((By.XPATH, "//button/span[normalize-space()='Save Changes']")))
 
 
339
  time.sleep(0.6); save_button.click()
340
  self._wait_for_page_load()
341
 
342
- final_confirm = WebDriverWait(self.driver, self.DEFAULT_TIMEOUT).until(EC.element_to_be_clickable((By.XPATH, "//button[.//span[normalize-space()='Confirm']]")))
 
 
343
  time.sleep(0.6); final_confirm.click()
344
  time.sleep(1.2)
345
  self._wait_for_page_load()
@@ -347,7 +367,9 @@ class QuantumBot:
347
  except TimeoutException:
348
  self.micro_status(f"'{patient_name}' is in a bad state, cancelling.")
349
  try:
350
- cancel_button = WebDriverWait(self.driver, self.DEFAULT_TIMEOUT).until(EC.element_to_be_clickable((By.XPATH, "//button[.//span[normalize-space()='Cancel']]")))
 
 
351
  time.sleep(0.5); cancel_button.click()
352
  except Exception:
353
  pass
 
12
  from selenium.webdriver.support import expected_conditions as EC
13
  from selenium.common.exceptions import TimeoutException
14
 
15
+
16
  class QuantumBot:
17
  def __init__(self, socketio, app):
18
  self.socketio = socketio
 
32
 
33
  def initialize_driver(self):
34
  """
35
+ Headless on Linux/CI (HEADLESS=1 default), desktop Chrome when HEADLESS=0.
36
+ Optional env: CHROME_BINARY, CHROMEDRIVER, USER_AGENT
37
  """
38
  try:
39
  self.micro_status("Initializing browser...")
 
41
  headless = os.getenv("HEADLESS", "1") == "1"
42
 
43
  if headless:
 
44
  chrome_binary = os.getenv("CHROME_BINARY", "/usr/bin/chromium")
45
  chromedriver_path = os.getenv("CHROMEDRIVER", "/usr/bin/chromedriver")
46
  options.binary_location = chrome_binary
 
53
  options.add_argument(f"--user-agent={ua}")
54
  service = ChromeService(executable_path=chromedriver_path)
55
  else:
 
56
  from webdriver_manager.chrome import ChromeDriverManager
57
  options.add_argument("--start-maximized")
58
  service = ChromeService(ChromeDriverManager().install())
59
 
 
60
  options.add_argument('--disable-blink-features=AutomationControlled')
61
  options.add_experimental_option("excludeSwitches", ["enable-automation"])
62
  options.add_experimental_option('useAutomationExtension', False)
 
146
 
147
  def _set_date_range_on_page(self, start_date_str, end_date_str):
148
  self.micro_status("Opening calendar...")
149
+ date_button = WebDriverWait(self.driver, self.DEFAULT_TIMEOUT).until(
150
+ EC.element_to_be_clickable((By.XPATH, "//button[.//span[contains(text(), '-')]]"))
151
+ )
152
  time.sleep(2)
153
  date_button.click()
154
  self._wait_for_page_load(timeout=10)
 
234
  self.micro_status(f"Navigating to Void page for '{patient_name}'")
235
  self.driver.get("https://gateway.quantumepay.com/credit-card/void")
236
 
 
237
  for attempt in range(15):
238
  try:
239
  self.micro_status(f"Searching... (Attempt {attempt + 1})")
 
251
  EC.element_to_be_clickable((By.XPATH, f"//tr[contains(., \"{patient_name}\")]//button[@data-v-b6b33fa0]"))
252
  ).click()
253
 
254
+ WebDriverWait(self.driver, self.DEFAULT_TIMEOUT).until(
255
+ EC.element_to_be_clickable((By.LINK_TEXT, "Transaction Detail"))
256
+ ).click()
257
 
258
  self.micro_status("Adding to Vault...")
259
+ WebDriverWait(self.driver, self.DEFAULT_TIMEOUT).until(
260
+ EC.element_to_be_clickable((By.XPATH, "//button/span[normalize-space()='Add to Vault']"))
261
+ ).click()
262
+ WebDriverWait(self.driver, self.DEFAULT_TIMEOUT).until(
263
+ EC.element_to_be_clickable((By.XPATH, "//div[@class='modal-footer']//button/span[normalize-space()='Confirm']"))
264
+ ).click()
265
 
266
  try:
267
  self.micro_status("Verifying success and saving...")
 
269
  company_input.clear(); company_input.send_keys(patient_name)
270
 
271
  contact_input = WebDriverWait(self.driver, 5).until(EC.element_to_be_clickable((By.NAME, "company_contact")))
 
272
  contact_input.click(); contact_input.send_keys(Keys.CONTROL + "a"); contact_input.send_keys(Keys.BACK_SPACE)
273
  contact_input.send_keys(str(patient_prn))
274
 
275
+ WebDriverWait(self.driver, self.DEFAULT_TIMEOUT).until(
276
+ EC.element_to_be_clickable((By.XPATH, "//button/span[normalize-space()='Save Changes']"))
277
+ ).click()
278
+ WebDriverWait(self.driver, self.DEFAULT_TIMEOUT).until(
279
+ EC.element_to_be_clickable((By.XPATH, "//button[.//span[normalize-space()='Confirm']]"))
280
+ ).click()
281
  time.sleep(2)
282
  return 'Done'
283
  except TimeoutException:
284
  self.micro_status(f"'{patient_name}' is in a bad state, cancelling.")
285
  try:
286
+ WebDriverWait(self.driver, self.DEFAULT_TIMEOUT).until(
287
+ EC.element_to_be_clickable((By.XPATH, "//button[.//span[normalize-space()='Cancel']]"))
288
+ ).click()
289
  except Exception:
290
  pass
291
  return 'Bad'
 
319
  time.sleep(0.6); details_button.click()
320
  self._wait_for_page_load(timeout=5)
321
 
322
+ transaction_link = WebDriverWait(self.driver, self.DEFAULT_TIMEOUT).until(
323
+ EC.element_to_be_clickable((By.LINK_TEXT, "Transaction Detail"))
324
+ )
325
  time.sleep(0.6); transaction_link.click()
326
  self._wait_for_page_load()
327
 
328
  self.micro_status("Adding to Vault...")
329
+ vault_button = WebDriverWait(self.driver, self.DEFAULT_TIMEOUT).until(
330
+ EC.element_to_be_clickable((By.XPATH, "//button/span[normalize-space()='Add to Vault']"))
331
+ )
332
  time.sleep(0.6); vault_button.click()
333
  self._wait_for_page_load()
334
 
335
+ confirm_button = WebDriverWait(self.driver, self.DEFAULT_TIMEOUT).until(
336
+ EC.element_to_be_clickable((By.XPATH, "//div[@class='modal-footer']//button/span[normalize-space()='Confirm']"))
337
+ )
338
  time.sleep(0.6); confirm_button.click()
339
  self._wait_for_page_load()
340
 
 
351
  contact_input.click(); contact_input.send_keys(Keys.CONTROL + "a"); contact_input.send_keys(Keys.BACK_SPACE)
352
  contact_input.send_keys(str(patient_prn))
353
 
354
+ save_button = WebDriverWait(self.driver, self.DEFAULT_TIMEOUT).until(
355
+ EC.element_to_be_clickable((By.XPATH, "//button/span[normalize-space()='Save Changes']"))
356
+ )
357
  time.sleep(0.6); save_button.click()
358
  self._wait_for_page_load()
359
 
360
+ final_confirm = WebDriverWait(self.driver, self.DEFAULT_TIMEOUT).until(
361
+ EC.element_to_be_clickable((By.XPATH, "//button[.//span[normalize-space()='Confirm']]"))
362
+ )
363
  time.sleep(0.6); final_confirm.click()
364
  time.sleep(1.2)
365
  self._wait_for_page_load()
 
367
  except TimeoutException:
368
  self.micro_status(f"'{patient_name}' is in a bad state, cancelling.")
369
  try:
370
+ cancel_button = WebDriverWait(self.driver, self.DEFAULT_TIMEOUT).until(
371
+ EC.element_to_be_clickable((By.XPATH, "//button[.//span[normalize-space()='Cancel']]"))
372
+ )
373
  time.sleep(0.5); cancel_button.click()
374
  except Exception:
375
  pass