[object Object]

← back to Jf Fabrics Recrawl

DWJJ: wrote JF enrichment specs (removability/paste/coverage/yards/origin/washable) to 61 live products, 0 errors; images held (sibling-bleed risk)

94a55b1014b22f57293d4ef64dfaed8b0c3abd5e · 2026-06-29 09:13:25 -0700 · steve@designerwallcoverings.com

Files touched

Diff

commit 94a55b1014b22f57293d4ef64dfaed8b0c3abd5e
Author: steve@designerwallcoverings.com <steve@designerwallcoverings.com>
Date:   Mon Jun 29 09:13:25 2026 -0700

    DWJJ: wrote JF enrichment specs (removability/paste/coverage/yards/origin/washable) to 61 live products, 0 errors; images held (sibling-bleed risk)
---
 dwjj-mfr-backfill/write-enrichment.py | 35 +++++++++++++++++++++++++++++++++++
 1 file changed, 35 insertions(+)

diff --git a/dwjj-mfr-backfill/write-enrichment.py b/dwjj-mfr-backfill/write-enrichment.py
new file mode 100755
index 0000000..b5527eb
--- /dev/null
+++ b/dwjj-mfr-backfill/write-enrichment.py
@@ -0,0 +1,35 @@
+#!/usr/bin/env python3
+"""Write JF enrichment specs (removability/paste/coverage/yards/origin/washable) onto the 58
+DWJJ products as internal global.* metafields. DRY-RUN by default; --live to write; --test=N to limit.
+Images deliberately excluded (sibling-colorway bleed risk)."""
+import json, subprocess, sys, os
+DRY = '--live' not in sys.argv
+TEST = next((int(a.split('=')[1]) for a in sys.argv if a.startswith('--test=')), None)
+os.chdir(os.path.expanduser('~/Projects/Designer-Wallcoverings'))
+TOKEN = subprocess.check_output("grep -E '^SHOPIFY_ADMIN_TOKEN=' .env|head -1|cut -d= -f2|tr -d '\"'", shell=True, text=True).strip()
+DOMAIN = "designer-laboratory-sandbox.myshopify.com"
+def gql(q, v=None):
+    body = {"query": q}
+    if v: body["variables"] = v
+    p = subprocess.run(["curl","-s","-X","POST",f"https://{DOMAIN}/admin/api/2024-10/graphql.json","-H",f"X-Shopify-Access-Token: {TOKEN}","-H","Content-Type: application/json","-d",json.dumps(body)], capture_output=True, text=True)
+    return json.loads(p.stdout)
+# staged record field -> Shopify global metafield key
+FIELDS = {"removability":"Removability","paste":"Paste","coverage":"Coverage","yards_dr":"Yards Per Double Roll","origin":"Country of Origin","washable":"Washable"}
+SPECS = os.path.expanduser('~/Projects/jf-fabrics-recrawl/dwjj-mfr-backfill/dwjj_specs.jsonl')
+with open(SPECS, encoding='utf-8') as fh:
+    recs = [json.loads(l) for l in fh if l.strip()]
+targets = [r for r in recs if r.get('ok') and any(r.get(f) for f in FIELDS)]
+if TEST: targets = targets[:TEST]
+M = '''mutation($mf:[MetafieldsSetInput!]!){ metafieldsSet(metafields:$mf){ metafields{ key } userErrors{ field message } } }'''
+print(f"{'DRY-RUN' if DRY else 'LIVE'} — {len(targets)} products, up to {len(FIELDS)} enrichment fields each")
+errs = 0; wrote = 0
+for r in targets:
+    mfs = [{"ownerId":r['gid'],"namespace":"global","key":k,"type":"single_line_text_field","value":str(r[f])}
+           for f,k in FIELDS.items() if r.get(f)]
+    if DRY:
+        print(f"  {r['base']:<10} -> " + ", ".join(f"{m['key']}={m['value']}" for m in mfs)); continue
+    d = gql(M, {"mf": mfs})
+    ue = d.get('data',{}).get('metafieldsSet',{}).get('userErrors',[]) if 'data' in d else [{'message':json.dumps(d)[:120]}]
+    if ue: errs += 1; print(f"  ERR {r['base']}: {ue}")
+    else: wrote += 1; print(f"  OK  {r['base']} ({len(mfs)} fields)")
+print(f"done. wrote={wrote} errors={errs}" if not DRY else "(dry-run, nothing written)")

← 5bd349a chore: refactor write-metafields (with-block + utf-8 on open  ·  back to Jf Fabrics Recrawl  ·  chore: lint + refactor write-enrichment (split imports, extr 83e7ae7 →