← back to Hollywood Price 2026

build_plan.py

78 lines

#!/usr/bin/env python3
"""Build the Hollywood/Momentum pricing plan.
Scope (Steve 2026-07-12): price ACTIVE + Needs-Price Hollywood Wallcoverings products
whose custom.dw_sku matches the Momentum feed. EXCLUDE DWHW2- (garbage prefix).
Price = feed `hw` (Hollywood retail = Momentum list x 1.448). Unit = feed `uom`.
Output: plan.csv (gid, dw_sku, sample_sku_base, uom, hw, pattern, color, width, title). $0."""
import sys
import os
import json
import csv
import collections
sys.path.insert(0, "lib")
from shopify import gql

FEED = os.path.expanduser("~/Projects/hollywood-import/momentum-feed/acoustic-golive.json")
OUT = "plan.csv"
Q = """query($q:String!,$after:String){ products(first:200, after:$after, query:$q){
  pageInfo{hasNextPage endCursor}
  edges{ node{ id legacyResourceId handle title
    dwsku: metafield(namespace:"custom", key:"dw_sku"){ value }
    variants(first:5){ edges{ node{ sku title } } } } } } }"""
SEARCH = "vendor:'Hollywood Wallcoverings' status:active tag:Needs-Price"


def sample_base(node):
    for e in node["variants"]["edges"]:
        sk = (e["node"]["sku"] or "")
        low = sk.lower()
        if low.endswith("-sample"):
            return sk[:-len("-sample")]
    return None


def main():
    feed = json.load(open(FEED))
    by_dw = {str(r.get("dw_sku")).strip(): r for r in feed if r.get("dw_sku")}
    prods, cur = [], None
    while True:
        d = gql(Q, {"q": SEARCH, "after": cur})
        p = d["products"]; prods += [e["node"] for e in p["edges"]]
        if not p["pageInfo"]["hasNextPage"]:
            break
        cur = p["pageInfo"]["endCursor"]
    rows, skipped = [], {"dwhw2": 0, "no_dwsku": 0, "no_feed": 0, "no_hw": 0, "no_sample": 0}
    for n in prods:
        dw = (n.get("dwsku") or {}).get("value")
        if not dw:
            skipped["no_dwsku"] += 1; continue
        if dw.startswith("DWHW2"):
            skipped["dwhw2"] += 1; continue
        fr = by_dw.get(dw.strip())
        if not fr:
            skipped["no_feed"] += 1; continue
        hw = fr.get("hw")
        if not hw or float(hw) <= 0:
            skipped["no_hw"] += 1; continue
        sb = sample_base(n)
        if not sb:
            skipped["no_sample"] += 1; continue
        rows.append({
            "gid": n["id"], "product_id": n["legacyResourceId"], "handle": n["handle"],
            "title": n["title"], "dw_sku": dw, "sample_sku_base": sb,
            "uom": fr.get("uom"), "hw": hw, "pattern": fr.get("pattern"),
            "color": fr.get("color"), "width": fr.get("width"),
        })
    with open(OUT, "w", newline="") as f:
        w = csv.DictWriter(f, fieldnames=list(rows[0].keys()))
        w.writeheader(); w.writerows(rows)
    print(f"PLAN: {len(rows)} priceable products -> {OUT}")
    print("  skipped:", skipped)
    print("  uom:", dict(collections.Counter(r["uom"] for r in rows)))
    hws = sorted(float(r["hw"]) for r in rows)
    print(f"  hw range: ${hws[0]:.2f} - ${hws[-1]:.2f}  median ${hws[len(hws)//2]:.2f}")


if __name__ == "__main__":
    main()