|
1 | 1 | import sys |
2 | 2 | from pathlib import Path |
| 3 | +import os |
3 | 4 |
|
4 | 5 | # Add src to PYTHONPATH for local runs |
5 | 6 | sys.path.append(str(Path(__file__).resolve().parents[1] / "src")) |
|
9 | 10 | import traceback |
10 | 11 | import requests |
11 | 12 | import time |
12 | | - |
13 | | -base_url = 'https://aurorabapenv0f528.crm10.dynamics.com' |
| 13 | + |
| 14 | +if not sys.stdin.isatty(): |
| 15 | + print("Interactive input required for org URL. Run this script in a TTY.") |
| 16 | + sys.exit(1) |
| 17 | +entered = input("Enter Dataverse org URL (e.g. https://yourorg.crm.dynamics.com): ").strip() |
| 18 | +if not entered: |
| 19 | + print("No URL entered; exiting.") |
| 20 | + sys.exit(1) |
| 21 | +base_url = entered.rstrip('/') |
14 | 22 | client = DataverseClient(base_url=base_url, credential=InteractiveBrowserCredential()) |
15 | 23 |
|
16 | 24 | # Small helpers: call logging and step pauses |
@@ -259,50 +267,34 @@ def print_line_summaries(label: str, summaries: list[dict]) -> None: |
259 | 267 | # 4) Query records via SQL Custom API |
260 | 268 | print("Query (SQL via Custom API):") |
261 | 269 | try: |
262 | | - # Try singular logical name first, then plural entity set, with short backoff |
263 | 270 | import time |
| 271 | + plan_call(f"client.query_sql(\"SELECT TOP 2 * FROM {logical} ORDER BY {attr_prefix}_amount DESC\")") |
| 272 | + pause("Execute SQL Query") |
264 | 273 |
|
265 | | - candidates = [logical] |
266 | | - if entity_set and entity_set != logical: |
267 | | - candidates.append(entity_set) |
| 274 | + def _run_query(): |
| 275 | + log_call(f"client.query_sql(\"SELECT TOP 2 * FROM {logical} ORDER BY {attr_prefix}_amount DESC\")") |
| 276 | + return client.query_sql(f"SELECT TOP 2 * FROM {logical} ORDER BY {attr_prefix}_amount DESC") |
268 | 277 |
|
269 | | - # Show planned SQL queries before executing |
270 | | - for name in candidates: |
271 | | - plan_call(f"client.query_sql(\"SELECT TOP 2 * FROM {name} ORDER BY {attr_prefix}_amount DESC\")") |
272 | | - pause("Execute SQL Query") |
| 278 | + def _retry_if(ex: Exception) -> bool: |
| 279 | + msg = str(ex) if ex else "" |
| 280 | + return ("Invalid table name" in msg) or ("Invalid object name" in msg) |
273 | 281 |
|
274 | | - rows = [] |
275 | | - for name in candidates: |
276 | | - def _run_query(): |
277 | | - log_call(f"client.query_sql(\"SELECT TOP 2 * FROM {name} ORDER BY {attr_prefix}_amount DESC\")") |
278 | | - return client.query_sql(f"SELECT TOP 2 * FROM {name} ORDER BY {attr_prefix}_amount DESC") |
279 | | - def _retry_if(ex: Exception) -> bool: |
280 | | - msg = str(ex) if ex else "" |
281 | | - return ("Invalid table name" in msg) or ("Invalid object name" in msg) |
282 | | - try: |
283 | | - rows = backoff_retry(_run_query, delays=(0, 2, 5), retry_http_statuses=(), retry_if=_retry_if) |
284 | | - logical_for_ids = logical |
285 | | - id_key = f"{logical_for_ids}id" |
286 | | - ids = [r.get(id_key) for r in rows if isinstance(r, dict) and r.get(id_key)] |
287 | | - print({"entity": name, "rows": len(rows) if isinstance(rows, list) else 0, "ids": ids}) |
288 | | - # Print TDS summaries for clarity |
289 | | - tds_summaries = [] |
290 | | - for row in rows if isinstance(rows, list) else []: |
291 | | - tds_summaries.append( |
292 | | - { |
293 | | - "id": row.get(id_key), |
294 | | - "code": row.get(code_key), |
295 | | - "count": row.get(count_key), |
296 | | - "amount": row.get(amount_key), |
297 | | - "when": row.get(when_key), |
298 | | - } |
299 | | - ) |
300 | | - print_line_summaries("TDS record summaries (top 2 by amount):", tds_summaries) |
301 | | - raise SystemExit |
302 | | - except Exception: |
303 | | - continue |
304 | | -except SystemExit: |
305 | | - pass |
| 282 | + rows = backoff_retry(_run_query, delays=(0, 2, 5), retry_http_statuses=(), retry_if=_retry_if) |
| 283 | + id_key = f"{logical}id" |
| 284 | + ids = [r.get(id_key) for r in rows if isinstance(r, dict) and r.get(id_key)] |
| 285 | + print({"entity": logical, "rows": len(rows) if isinstance(rows, list) else 0, "ids": ids}) |
| 286 | + tds_summaries = [] |
| 287 | + for row in rows if isinstance(rows, list) else []: |
| 288 | + tds_summaries.append( |
| 289 | + { |
| 290 | + "id": row.get(id_key), |
| 291 | + "code": row.get(code_key), |
| 292 | + "count": row.get(count_key), |
| 293 | + "amount": row.get(amount_key), |
| 294 | + "when": row.get(when_key), |
| 295 | + } |
| 296 | + ) |
| 297 | + print_line_summaries("TDS record summaries (top 2 by amount):", tds_summaries) |
306 | 298 | except Exception as e: |
307 | 299 | print(f"SQL via Custom API failed: {e}") |
308 | 300 | # 5) Delete record |
|
0 commit comments