javascript:(async function() { console.log(">>> SCRIPT STARTED"); const wait = (ms) => new Promise(resolve => setTimeout(resolve, ms)); function parseDate(input) { const d = new Date(input); if (isNaN(d.getTime())) return null; d.setHours(0, 0, 0, 0); return d; } function getUnitName(addressText) { const text = addressText.trim(); if (text.toLowerCase().includes("laundry")) { if (text.includes("504")) return "CY1 Laundry"; if (text.includes("13129")) return "CY2 Laundry"; if (text.includes("13203")) return "CY3 Laundry"; if (text.includes("524")) return "CY4 Laundry"; return "Laundry"; } const parts = text.split(" "); return parts[parts.length - 1]; } let capturedUrl = null; const originalWindowOpen = window.open; function enableInterceptor() { capturedUrl = null; window.open = function(url) { capturedUrl = url; return { focus:()=>{}, close:()=>{} }; }; } function disableInterceptor() { window.open = originalWindowOpen; } async function setTableTo100() { const wrapper = document.querySelector("#statement-history-table-title")?.parentElement; if (!wrapper) return; const select = wrapper.querySelector("select[name*='length']"); if (select && select.value !== "100") { select.value = "100"; select.dispatchEvent(new Event('change', { bubbles: true })); await wait(2000); } } async function ensureMenuOpen() { const table = document.querySelector("#my-accounts-table"); if (table && table.offsetParent !== null) return; const buttons = Array.from(document.querySelectorAll("button, a, span[role='button']")); const trigger = buttons.find(b => { const t = b.innerText.toLowerCase(); return t.includes("switch account") || t.includes("change account") || t.includes("choose account"); }); if (trigger) { trigger.click(); await wait(1000); } else { const header = document.querySelector("address"); if (header) { header.click(); await wait(1000); } } } async function processCurrentAccount(cutoffDate) { await setTableTo100(); const addrSpan = document.querySelector("address span[data-bind*='fullAddress']"); const fullAddress = addrSpan ? addrSpan.innerText : "Unknown"; const extraName = getUnitName(fullAddress); const rows = document.querySelectorAll("#statements-table tbody tr"); let downloadCount = 0; for (const row of rows) { const dateCell = row.cells[2]; const btn = row.querySelector(".view-statement-details-button"); if (!dateCell || !btn) continue; const rawDate = dateCell.innerText.trim(); const stmtDate = new Date(rawDate); stmtDate.setHours(0,0,0,0); if (stmtDate < cutoffDate) continue; const yyyy = stmtDate.getFullYear(); const mm = String(stmtDate.getMonth()+1).padStart(2,'0'); const dd = String(stmtDate.getDate()).padStart(2,'0'); const cleanDate = yyyy + "-" + mm + "-" + dd; const filename = "Vera - Brookstone " + extraName + " - " + cleanDate + ".pdf"; enableInterceptor(); btn.click(); let attempts = 0; while (capturedUrl === null && attempts < 15) { await wait(200); attempts++; } disableInterceptor(); if (capturedUrl) { try { const response = await fetch(capturedUrl); const blob = await response.blob(); const url = window.URL.createObjectURL(blob); const a = document.createElement('a'); a.style.display = 'none'; a.href = url; a.download = filename; document.body.appendChild(a); a.click(); window.URL.revokeObjectURL(url); document.body.removeChild(a); downloadCount++; } catch (e) { console.error("Fetch failed", e); } } await wait(1000); } } const inputStr = prompt("Enter Cutoff Date (MM/DD/YYYY).\nLeave BLANK for ALL history.\nClick Cancel to stop.", "9/18/2025"); if (inputStr === null) return; let cutoffDate; if (inputStr.trim() === "") { cutoffDate = new Date("1900-01-01"); } else { cutoffDate = parseDate(inputStr); if (!cutoffDate) { alert("Invalid Date format. Please use MM/DD/YYYY."); return; } } let accountRows = document.querySelectorAll("#my-accounts-table tbody tr"); if (accountRows.length === 0) { alert("Please open the 'Choose Account' popup first!"); return; } const totalAccounts = accountRows.length; for (let i = 0; i < totalAccounts; i++) { await ensureMenuOpen(); accountRows = document.querySelectorAll("#my-accounts-table tbody tr"); if (!accountRows[i]) break; const row = accountRows[i]; const targetCell = row.cells[2] || row.cells[1]; const targetAcctNum = row.cells[1].innerText.trim(); targetCell.click(); let loaded = false; for (let j=0; j<20; j++) { await wait(500); const headerAcct = document.querySelector("address span[data-bind*='accountNumber']"); if (headerAcct && headerAcct.innerText.trim() === targetAcctNum) { loaded = true; break; } } if (!loaded) continue; await wait(2000); await processCurrentAccount(cutoffDate); } alert("Batch completed. All accounts processed."); })();