diff --git a/downloader.py b/downloader.py index bc5d324..e28e6e4 100644 --- a/downloader.py +++ b/downloader.py @@ -120,11 +120,13 @@ def get_invoice_links(page: Page) -> list[dict]: links = [] seen = set() - def _add_link(url: str, label: str) -> None: + def _add_link(url: str, label: str, **meta) -> None: if not url or url in seen: return seen.add(url) - links.append({"url": url, "label": label}) + entry = {"url": url, "label": label} + entry.update(meta) + links.append(entry) rows = page.locator("table.billing-table tbody tr, table#billingTable tbody tr, table tbody tr").all() for row in rows: @@ -151,23 +153,25 @@ def get_invoice_links(page: Page) -> list[dict]: print_links = page.locator("a.no-print[data-reference-object-id], a[data-reference-object-id]").all() for anchor in print_links: href = anchor.get_attribute("href") or "" + ref_id = anchor.get_attribute("data-reference-object-id") or "" + label = anchor.inner_text().strip() or ref_id + if href: if not href.startswith("http"): href = f"{BASE_URL}/{href.lstrip('/')}" - _add_link(href, anchor.inner_text().strip()) + _add_link(href, label) continue - try: - anchor.scroll_into_view_if_needed() - with page.expect_popup() as popup_info: - anchor.click() - popup = popup_info.value - popup.wait_for_load_state("domcontentloaded") - label = anchor.inner_text().strip() or anchor.get_attribute("data-reference-object-id") or popup.title() - _add_link(popup.url, label) - popup.close() - except Exception as e: - logger.warning("Failed to open invoice popup: %s", e) + if ref_id: + _add_link( + f"{BASE_URL}/billing_print_invoice.htm", + label, + reference_id=ref_id, + open_via_popup=True, + ) + continue + + logger.warning("Invoice link missing href and reference id") return links @@ -246,15 +250,34 @@ def sanitize_filename(name: str) -> str: return name.strip('_') -def export_invoice_pdf(context: BrowserContext, page: Page, invoice_url: str, output_path: Path) -> tuple[Page, Path]: - page = _goto_with_retry(context, page, invoice_url) +def export_invoice_pdf(context: BrowserContext, page: Page, invoice: dict, output_path: Path) -> tuple[Page, Path]: + invoice_page = None + if invoice.get("open_via_popup") and invoice.get("reference_id"): + page = _goto_with_retry(context, page, BILLING_URL) + selector = f"a[data-reference-object-id='{invoice['reference_id']}']" + anchor = page.locator(selector).first + if anchor.count() == 0: + raise RuntimeError(f"Invoice link not found for reference id {invoice['reference_id']}") + anchor.scroll_into_view_if_needed() + with page.expect_popup() as popup_info: + anchor.click() + invoice_page = popup_info.value + invoice_page.wait_for_load_state("domcontentloaded") + else: + page = _goto_with_retry(context, page, invoice["url"]) + invoice_page = page + time.sleep(1) - fill_invoice_fields(page) + fill_invoice_fields(invoice_page) time.sleep(0.5) - page.pdf(path=str(output_path), format="A4", print_background=True) + invoice_page.pdf(path=str(output_path), format="A4", print_background=True) logger.info("Saved: %s", output_path) + + if invoice_page is not page: + invoice_page.close() + return page, output_path @@ -344,7 +367,7 @@ def download_all_invoices() -> list[Path]: continue try: - page, path = export_invoice_pdf(context, page, invoice["url"], pdf_path) + page, path = export_invoice_pdf(context, page, invoice, pdf_path) saved.append(path) except Exception: logger.exception("Failed to export: %s", invoice["url"])