sync: Auto-sync from ACG-M-L5090 at 2026-03-10 19:11:00
Synced files: - Quote wizard frontend (all components, hooks, types, config) - API updates (config, models, routers, schemas, services) - Client work (bg-builders, gurushow) - Scripts (BGB Lesley termination, CIPP, Datto, migration) - Temp files (Bardach contacts, VWP investigation, misc) - Credentials and session logs - Email service, PHP API, session logs Machine: ACG-M-L5090 Timestamp: 2026-03-10 19:11:00 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
140
temp/bardach_ops_4_verify.py
Normal file
140
temp/bardach_ops_4_verify.py
Normal file
@@ -0,0 +1,140 @@
|
||||
"""
|
||||
Final Verification: Count remaining Temp contacts and summarize all operations.
|
||||
"""
|
||||
import json
|
||||
import subprocess
|
||||
import urllib.parse
|
||||
|
||||
TENANT_ID = "dd4a82e8-85a3-44ac-8800-07945ab4d95f"
|
||||
CLIENT_ID = "fabb3421-8b34-484b-bc17-e46de9703418"
|
||||
CLIENT_SECRET = "~QJ8Q~NyQSs4OcGqHZyPrA2CVnq9KBfKiimntbMO"
|
||||
SCOPE = "https://graph.microsoft.com/.default"
|
||||
USER = "barbara@bardach.net"
|
||||
|
||||
TEMP_FOLDER_ID = None # Will be resolved dynamically
|
||||
|
||||
def get_token():
|
||||
url = f"https://login.microsoftonline.com/{TENANT_ID}/oauth2/v2.0/token"
|
||||
data = (
|
||||
f"client_id={CLIENT_ID}"
|
||||
f"&scope={urllib.parse.quote(SCOPE)}"
|
||||
f"&client_secret={urllib.parse.quote(CLIENT_SECRET)}"
|
||||
f"&grant_type=client_credentials"
|
||||
)
|
||||
result = subprocess.run(
|
||||
["curl", "-s", "-X", "POST", url,
|
||||
"-H", "Content-Type: application/x-www-form-urlencoded",
|
||||
"-d", data],
|
||||
capture_output=True, text=True
|
||||
)
|
||||
resp = json.loads(result.stdout)
|
||||
if "access_token" not in resp:
|
||||
print(f"[ERROR] Token acquisition failed: {resp}")
|
||||
raise Exception("Failed to get token")
|
||||
return resp["access_token"]
|
||||
|
||||
def count_temp_contacts(token):
|
||||
"""Count contacts in Temp folder using $count."""
|
||||
url = (
|
||||
f"https://graph.microsoft.com/v1.0/users/{USER}"
|
||||
f"/contactFolders/{TEMP_FOLDER_ID}/contacts?$count=true&$top=1&$select=id"
|
||||
)
|
||||
result = subprocess.run(
|
||||
["curl", "-s", "-X", "GET", url,
|
||||
"-H", f"Authorization: Bearer {token}",
|
||||
"-H", "ConsistencyLevel: eventual"],
|
||||
capture_output=True, text=True
|
||||
)
|
||||
resp = json.loads(result.stdout)
|
||||
count = resp.get("@odata.count")
|
||||
if count is not None:
|
||||
return count
|
||||
# Fallback: page through all
|
||||
print("[INFO] @odata.count not available, paging through contacts...")
|
||||
total = 0
|
||||
page_url = (
|
||||
f"https://graph.microsoft.com/v1.0/users/{USER}"
|
||||
f"/contactFolders/{TEMP_FOLDER_ID}/contacts?$top=100&$select=id"
|
||||
)
|
||||
while page_url:
|
||||
result = subprocess.run(
|
||||
["curl", "-s", "-X", "GET", page_url,
|
||||
"-H", f"Authorization: Bearer {token}"],
|
||||
capture_output=True, text=True
|
||||
)
|
||||
resp = json.loads(result.stdout)
|
||||
contacts = resp.get("value", [])
|
||||
total += len(contacts)
|
||||
page_url = resp.get("@odata.nextLink")
|
||||
if total % 500 == 0 and total > 0:
|
||||
print(f" ...counted {total} so far")
|
||||
return total
|
||||
|
||||
def main():
|
||||
print("=" * 60)
|
||||
print("FINAL VERIFICATION")
|
||||
print("=" * 60)
|
||||
|
||||
token = get_token()
|
||||
print("[OK] Token acquired")
|
||||
|
||||
# Find Temp folder ID
|
||||
global TEMP_FOLDER_ID
|
||||
url = f"https://graph.microsoft.com/v1.0/users/{USER}/contactFolders"
|
||||
result = subprocess.run(
|
||||
["curl", "-s", "-X", "GET", url,
|
||||
"-H", f"Authorization: Bearer {token}"],
|
||||
capture_output=True, text=True
|
||||
)
|
||||
folders = json.loads(result.stdout).get("value", [])
|
||||
for f in folders:
|
||||
if "temp" in f.get("displayName", "").lower():
|
||||
TEMP_FOLDER_ID = f["id"]
|
||||
print(f"[INFO] Found Temp folder: '{f['displayName']}' -> {TEMP_FOLDER_ID[:40]}...")
|
||||
break
|
||||
if not TEMP_FOLDER_ID:
|
||||
print("[ERROR] Could not find Temp contact folder!")
|
||||
for f in folders:
|
||||
print(f" Folder: {f.get('displayName')} -> {f['id'][:40]}...")
|
||||
return
|
||||
|
||||
# Count remaining Temp contacts
|
||||
print("\n[INFO] Counting remaining Temp contacts...")
|
||||
remaining = count_temp_contacts(token)
|
||||
print(f"[INFO] Remaining Temp contacts: {remaining}")
|
||||
print(f"[INFO] Expected: ~3,888 (matches_with_extras)")
|
||||
|
||||
# Load operation results
|
||||
print("\n--- OPERATION SUMMARIES ---")
|
||||
for op_file, label in [
|
||||
("D:/ClaudeTools/temp/bardach_op1_delete_exact.json", "Op1: Delete Exact Matches"),
|
||||
("D:/ClaudeTools/temp/bardach_op2_move_unique.json", "Op2: Move Unique Contacts"),
|
||||
("D:/ClaudeTools/temp/bardach_op3_delete_blank.json", "Op3: Delete Blank Contacts"),
|
||||
]:
|
||||
try:
|
||||
with open(op_file, "r") as f:
|
||||
r = json.load(f)
|
||||
print(f"\n {label}:")
|
||||
print(f" Total: {r['total']}")
|
||||
print(f" Successes: {r['successes']}")
|
||||
print(f" Failures: {r['failures']}")
|
||||
if r.get("elapsed_seconds"):
|
||||
print(f" Time: {r['elapsed_seconds']}s")
|
||||
if r.get("method"):
|
||||
print(f" Method: {r['method']}")
|
||||
except FileNotFoundError:
|
||||
print(f"\n {label}: [NOT FOUND] {op_file}")
|
||||
except Exception as e:
|
||||
print(f"\n {label}: [ERROR] {e}")
|
||||
|
||||
print(f"\n{'=' * 60}")
|
||||
print(f"Remaining Temp contacts: {remaining}")
|
||||
diff = remaining - 3888
|
||||
if abs(diff) < 10:
|
||||
print(f"[OK] Close to expected (~3,888), difference: {diff}")
|
||||
else:
|
||||
print(f"[WARNING] Difference from expected (3,888): {diff}")
|
||||
print("=" * 60)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user