← back to Rentv Sheet Enrich Refine

write_by_contact.py

62 lines

#!/usr/bin/env python3
"""
write_by_contact.py <gid> <results.json>

PER-CONTACT writer — row-shift immune, matched on (company + contact-name) so each
person's data lands on THEIR row (not smeared across every contact at the company like
the company-only write_by_name.py). Each result item = {company, name, contact_li?, email?}.
Only fills empty cells; contact_li becomes =HYPERLINK; email -> "Updated Email (found)".
Reports matched / unmatched / cells.
"""
import sys, os, json, re
sys.path.insert(0, os.path.dirname(__file__))
import lib
GID = int(sys.argv[1]); results = json.load(open(sys.argv[2]))
def norm(s): return re.sub(r'[^a-z0-9]', '', (s or '').lower())

tok = lib.access_token()
title = {s["properties"]["sheetId"]: s["properties"]["title"]
         for s in lib.get_meta(tok)["sheets"]}[GID]
rows = lib.read_tab(tok, title)
hr = next((i for i in range(min(4, len(rows)))
           for j, v in enumerate(rows[i]) if v.strip() == "Contact Name"), 0)
hdr = rows[hr]
def hidx(label): return next((i for i in range(len(hdr)) if (hdr[i] if i < len(hdr) else "").strip() == label), None)
NAME = hidx("Contact Name"); CO = hidx("Company/Venue")
LIC = hidx("LinkedIn (Contact)"); EM = hidx("Updated Email (found)")
# auto-create any missing target columns
rightmost = max((i for i, v in enumerate(hdr) if v.strip()), default=0); nxt = rightmost + 1
newh = []
if LIC is None: LIC = nxt; newh.append({"row0": hr, "col0": nxt, "value": "LinkedIn (Contact)"}); nxt += 1
if EM  is None: EM  = nxt; newh.append({"row0": hr, "col0": nxt, "value": "Updated Email (found)"}); nxt += 1
if newh: lib.batch_fill(tok, GID, newh)
def cell(r, i): return (rows[r][i] if i is not None and r < len(rows) and i < len(rows[r]) else "").strip()

# index (normalized company, normalized name) -> [row0]
idx = {}
for r in range(hr + 1, len(rows)):
    k = (norm(cell(r, CO)), norm(cell(r, NAME)))
    if k[0] or k[1]:
        idx.setdefault(k, []).append(r)

cells = []; matched = 0; unmatched = []
for it in results:
    key = (norm(it.get("company", "")), norm(it.get("name", "")))
    targets = idx.get(key)
    if not targets:  # fallback: same name, company contains
        targets = [r for (co, nm), rs in idx.items()
                   if nm and nm == key[1] and key[0] and (key[0] in co or co in key[0]) for r in rs]
    if not targets:
        unmatched.append(it.get("name", "") + " @ " + it.get("company", "")); continue
    matched += 1
    for r0 in targets:
        li = (it.get("contact_li") or "").strip()
        em = (it.get("email") or "").strip()
        if li and not cell(r0, LIC):
            cells.append({"row0": r0, "col0": LIC, "value": '=HYPERLINK("%s")' % li.replace('"', ""), "formula": True})
        if em and not cell(r0, EM):
            cells.append({"row0": r0, "col0": EM, "value": em})
res = lib.batch_fill(tok, GID, cells)
print(json.dumps({"gid": GID, "matched": matched, "unmatched": len(unmatched),
                  "cells_written": res.get("totalUpdatedCells", 0)}))