← back to Elitis Price 2026
exec/ws4_cleanup.py
76 lines
#!/usr/bin/env python3
"""WS4 - post-reconciliation cleanup of 3 pre-existing Elitis defects (live).
1) Retitle scraped-sentence garbage titles on VP-963-01/-03 to real pattern 'Osorno'.
2) Archive the mongrel 'Raffia Ii Vp 1048 02' product that dodged the WS2 VP-1048
archive and collides on SKU DWEL-142747 with the legit 'Frivole' VP-1036-44.
Idempotent (checks current state first). $0 (Shopify Admin API is free).
Steve-approved via AskUserQuestion 2026-07-11 (options A + B)."""
import sys
import os
import csv
import datetime
sys.path.insert(0, "lib")
from shopify import gql
LEDGER = os.path.join("ledger", "ws4_cleanup.csv")
M_UPD = """mutation($input:ProductInput!){ productUpdate(input:$input){
product{ id legacyResourceId title status handle } userErrors{ field message } } }"""
RETITLE = [
(7787408261171, "Osorno 01 | Elitis"), # was: Vp 963 01 Is Offered up...
(7789388660787, "Osorno 03 | Elitis"), # was: Vp 963 03 Is Offered up...
]
ARCHIVE = [
(7787007475763, "Raffia Ii Vp 1048 02 | Elitis"), # mongrel dup -> ARCHIVED
]
def gid(pid):
return f"gid://shopify/Product/{pid}"
def log(action, pid, before, after, status):
new = not (os.path.exists(LEDGER) and os.path.getsize(LEDGER) > 0)
with open(LEDGER, "a", newline="") as f:
w = csv.writer(f)
if new:
w.writerow(["ts", "action", "product_id", "before", "after", "status"])
w.writerow([datetime.datetime.now().isoformat(timespec="seconds"),
action, pid, before, after, status])
def run():
for pid, newtitle in RETITLE:
cur = gql("query($id:ID!){ product(id:$id){ title } }", {"id": gid(pid)})["product"]
if cur["title"] == newtitle:
print(f" [skip] {pid} already '{newtitle}'")
log("retitle", pid, cur["title"], newtitle, "SKIP")
continue
r = gql(M_UPD, {"input": {"id": gid(pid), "title": newtitle}})
ue = r["productUpdate"]["userErrors"]
if ue:
print(f" [ERR] {pid}: {ue}")
log("retitle", pid, cur["title"], newtitle, "ERR:" + str(ue))
continue
print(f" [ok] retitle {pid}: {cur['title'][:40]!r} -> {newtitle!r}")
log("retitle", pid, cur["title"], newtitle, "OK")
for pid, title in ARCHIVE:
cur = gql("query($id:ID!){ product(id:$id){ status title } }", {"id": gid(pid)})["product"]
if cur["status"] == "ARCHIVED":
print(f" [skip] {pid} already ARCHIVED")
log("archive", pid, title, "ARCHIVED", "SKIP")
continue
r = gql(M_UPD, {"input": {"id": gid(pid), "status": "ARCHIVED"}})
ue = r["productUpdate"]["userErrors"]
if ue:
print(f" [ERR] {pid}: {ue}")
log("archive", pid, title, "ARCHIVED", "ERR:" + str(ue))
continue
print(f" [ok] archive {pid}: {title!r} ({cur['status']} -> ARCHIVED)")
log("archive", pid, title, "ARCHIVED", "OK")
if __name__ == "__main__":
run()
print("\nWS4 cleanup done.")