← back to Dw Photo Capture

create_22_new.py

57 lines

#!/usr/bin/env python3
"""Bulk-create the net-new GRS sheet items as DRAFT Shopify products with full info
   (no image yet — they go live once photographed). DRY default; CONFIRM=1 writes."""
import os,sys,json,re,time,urllib.request
SHOP="designer-laboratory-sandbox.myshopify.com";API="2024-10";DRY=os.environ.get("CONFIRM","0")!="1"
TOKEN=""
for l in open(os.path.expanduser("~/Projects/secrets-manager/.env")):
    if l.startswith("SHOPIFY_ADMIN_TOKEN="): TOKEN=l.strip().split("=",1)[1];break
H={"X-Shopify-Access-Token":TOKEN,"Content-Type":"application/json"}
def api(m,p,pl=None):
    d=json.dumps(pl).encode() if pl is not None else None
    r=urllib.request.Request(f"https://{SHOP}/admin/api/{API}"+p,data=d,headers=H,method=m)
    with urllib.request.urlopen(r,timeout=60) as x: b=x.read().decode();return x.status,(json.loads(b) if b.strip() else {})
SHEET={x["grs"].upper():x for x in json.load(open(os.path.expanduser("~/Projects/dw-photo-capture/data/sheet_grs.json")))}
# the net-new list straight from the app
import urllib.request as u, base64
req=u.Request("http://127.0.0.1:9890/api/new",headers={"Authorization":"Basic "+base64.b64encode(b"admin:DW2024!").decode()})
NEW=json.loads(u.urlopen(req,timeout=20).read())["items"]
def title(s):
    name=(s.get("name") or "").strip(); color=(s.get("color") or "").strip()
    nl,cl=name.lower(),color.lower()
    col=(" "+color) if (color and nl!=cl and cl not in nl and nl not in cl) else ""
    if name: return f"{name}{col} Grasscloth Wallcovering | Fentucci"
    if s.get("material"): return f"Fentucci {s['material']} Grasscloth Wallcovering"+((" — "+color) if color else "")
    return "Fentucci Grasscloth Wallcovering"+((" — "+color) if color else "")
def body(s):
    lead=s.get("name") or (("Fentucci "+s["material"]+" grasscloth") if s.get("material") else "This Fentucci grasscloth")
    de=(s.get("desc") or "").strip()
    if de and de.lower().startswith("is "): return f"{lead} {de}"
    return de or f"{lead} is a natural woven grasscloth wallcovering with handcrafted natural-fiber texture."
def mf(ns,k,v): return {"namespace":ns,"key":k,"value":str(v),"type":"single_line_text_field"} if v else None
print(f"{len(NEW)} net-new to create as DRAFT (full info, no image)")
created=0
for it in NEW:
    s=SHEET.get(it["dw_sku"].upper())
    if not s: print(f"   skip {it['dw_sku']} (no sheet row)"); continue
    grs=s["grs"]; price=s.get("price"); col=(s.get("color") or "").strip()
    tags=["Grasscloth","Natural Wallcovering","Fentucci","TWIL Naturals","display_variant","Needs-Image"]+([f"color:{col}"] if col else [])+([] if price else ["Needs-Cost"])
    roll={"option1":"Roll","sku":grs,"inventory_management":"shopify","inventory_quantity":2026}
    if price: roll["price"]=str(price)
    payload={"product":{"title":title(s),"body_html":body(s),"vendor":"Fentucci","product_type":"Wallcovering",
      "status":"draft","published_scope":"global","tags":", ".join(tags),"options":[{"name":"Size"}],
      "variants":[roll,{"option1":"Sample","sku":grs+"-Sample","price":"4.25","inventory_management":"shopify","inventory_quantity":2026}],
      "metafields":[x for x in [mf("global","width",s.get("width") or "36 Inches"),mf("global","length",s.get("length") or "8 Yards"),
        mf("global","unit_of_measure","Priced Per Single Roll"),mf("global","Content","Natural Grasscloth"),
        mf("global","Brand","Fentucci"),mf("global","Collection","TWIL Naturals"),mf("global","Color-Way",col),mf("custom","color",col),
        mf("custom","manufacturer_sku",s.get("mfr")),mf("dwc","manufacturer_sku",s.get("mfr")),
        mf("custom","pattern_name",s.get("name")),mf("dwc","pattern_name",s.get("name"))] if x]}}
    if DRY: print(f"   [dry] {grs:12} {('$'+str(price)) if price else 'no-price':9} {title(s)[:46]}"); continue
    try:
        st,r=api("POST","/products.json",payload); created+=1
        print(f"   created {grs} -> {r.get('product',{}).get('id')} (draft)"); time.sleep(0.5)
    except Exception as e:
        bd=getattr(e,'read',lambda:b'')() if hasattr(e,'read') else b''; print(f"   ERR {grs}: {e} {bd[:140]}")
if DRY: print(f"\n[DRY] would create {len(NEW)} drafts. CONFIRM=1 to create.")
else: print(f"\nDONE — created {created} draft products (Needs-Image; photograph to go live).")