← back to Designer Wallcoverings
auto-save: 2026-07-02T11:47:40 (7 files) — pending-approval/boost-filter-consolidation-2026-06-25 shopify/scripts/cadence/data/cadence-cursor.json shopify/scripts/cadence/data/cadence-plan-am-2026-07-02.json shopify/scripts/cadence/data/upload-restore-2026-07-02.jsonl vendor-scrapers/china-seas-refresh
7568c2faa3111cb43f56264f0e5a337f3392c2cb · 2026-07-02 11:47:47 -0700 · Steve Abrams
Files touched
A audits/dwtt-conflict-2-before-state.jsonlM shopify/scripts/cadence/data/cadence-cursor.jsonM shopify/scripts/cadence/data/cadence-plan-am-2026-07-02.jsonM shopify/scripts/cadence/data/upload-restore-2026-07-02.jsonlA shopify/scripts/fix-dwtt-conflict-2-skus.py
Diff
commit 7568c2faa3111cb43f56264f0e5a337f3392c2cb
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Thu Jul 2 11:47:47 2026 -0700
auto-save: 2026-07-02T11:47:40 (7 files) — pending-approval/boost-filter-consolidation-2026-06-25 shopify/scripts/cadence/data/cadence-cursor.json shopify/scripts/cadence/data/cadence-plan-am-2026-07-02.json shopify/scripts/cadence/data/upload-restore-2026-07-02.jsonl vendor-scrapers/china-seas-refresh
---
audits/dwtt-conflict-2-before-state.jsonl | 2 +
shopify/scripts/cadence/data/cadence-cursor.json | 2 +-
.../cadence/data/cadence-plan-am-2026-07-02.json | 220 ++++++++++-----------
.../cadence/data/upload-restore-2026-07-02.jsonl | 18 ++
shopify/scripts/fix-dwtt-conflict-2-skus.py | 151 ++++++++++++++
5 files changed, 281 insertions(+), 112 deletions(-)
diff --git a/audits/dwtt-conflict-2-before-state.jsonl b/audits/dwtt-conflict-2-before-state.jsonl
new file mode 100644
index 00000000..4485cf88
--- /dev/null
+++ b/audits/dwtt-conflict-2-before-state.jsonl
@@ -0,0 +1,2 @@
+{"ts": "2026-07-02T11:21:57.165712", "product_id": "gid://shopify/Product/7552689897523", "mfr": "AT57882", "before": {"handle": "tate-trellis-green-anna-french", "status": "ACTIVE", "title": "Tate Trellis Green Wallcovering", "width": "27\" x 4.5yds", "length": "11 Yards", "unit_of_measure": "Full Roll"}}
+{"ts": "2026-07-02T11:21:57.165738", "product_id": "gid://shopify/Product/7552706543667", "mfr": "T41013", "before": {"handle": "dwtt-80529-designer-wallcoverings-los-angeles", "status": "ACTIVE", "title": "Hinton Tunnel Ivory | Thibaut", "width": "27 Inches", "length": "4.5 yd (13.5 ft)", "unit_of_measure": ""}}
diff --git a/shopify/scripts/cadence/data/cadence-cursor.json b/shopify/scripts/cadence/data/cadence-cursor.json
index 575ad4c7..64fd75b8 100644
--- a/shopify/scripts/cadence/data/cadence-cursor.json
+++ b/shopify/scripts/cadence/data/cadence-cursor.json
@@ -1,5 +1,5 @@
{
- "idx": 6,
+ "idx": 12,
"lastSlot": "am",
"lastRun": "2026-07-02"
}
\ No newline at end of file
diff --git a/shopify/scripts/cadence/data/cadence-plan-am-2026-07-02.json b/shopify/scripts/cadence/data/cadence-plan-am-2026-07-02.json
index cba4f975..f2a440be 100644
--- a/shopify/scripts/cadence/data/cadence-plan-am-2026-07-02.json
+++ b/shopify/scripts/cadence/data/cadence-plan-am-2026-07-02.json
@@ -1,184 +1,182 @@
[
{
- "vendor": "Romo",
- "dw_sku": "DWRM-240167",
- "cost": 1364,
- "retail": 2468.78,
+ "vendor": "Schumacher",
+ "dw_sku": "DWLK-807240",
+ "cost": 38,
+ "retail": 68.78,
"sample": "4.25",
"sampleOnly": false,
- "title": "Bakbak, Indigo Wallcoverings | Romo",
+ "title": "Villandry Damask Print, Neutral Wallcoverings | Schumacher",
"willActivate": true
},
{
- "vendor": "Romo",
- "dw_sku": "DWRM-240187",
- "cost": 490.6,
- "retail": 887.96,
+ "vendor": "Schumacher",
+ "dw_sku": "DWLK-807250",
+ "cost": 38,
+ "retail": 68.78,
"sample": "4.25",
"sampleOnly": false,
- "title": "Suru, Typhoon Wallcoverings | Romo",
+ "title": "Villandry Damask Print, Black Wallcoverings | Schumacher",
"willActivate": true
},
{
- "vendor": "Romo",
- "dw_sku": "DWRM-240194",
- "cost": 451,
- "retail": 816.29,
+ "vendor": "Schumacher",
+ "dw_sku": "DWLK-807260",
+ "cost": 28,
+ "retail": 50.68,
"sample": "4.25",
"sampleOnly": false,
- "title": "Palm, Harvest Wallcoverings | Romo",
+ "title": "Dedra Damask, Mineral & Leaf Wallcoverings | Schumacher",
"willActivate": true
},
{
- "vendor": "Thibaut",
- "dw_sku": "DWTT-73659",
- "cost": 165.6,
- "retail": 299.73,
+ "vendor": "Quadrille",
+ "dw_sku": "DWQC-600201",
+ "cost": 0,
+ "retail": 0,
"sample": "4.25",
- "sampleOnly": false,
- "title": "Hampton, Lilac Wallcoverings | Thibaut",
+ "sampleOnly": true,
+ "title": "Shanghai, Raspberry on White Wallcoverings | Quadrille",
"willActivate": true
},
{
- "vendor": "Thibaut",
- "dw_sku": "DWTT-73660",
- "cost": 165.6,
- "retail": 299.73,
+ "vendor": "Quadrille",
+ "dw_sku": "DWQC-600202",
+ "cost": 0,
+ "retail": 0,
"sample": "4.25",
- "sampleOnly": false,
- "title": "Hampton, Forest Green Wallcoverings | Thibaut",
+ "sampleOnly": true,
+ "title": "Shanghai, Multi Greys on White Wallcoverings | Quadrille",
"willActivate": true
},
{
- "vendor": "Thibaut",
- "dw_sku": "DWTT-73661",
- "cost": 165.6,
- "retail": 299.73,
+ "vendor": "Quadrille",
+ "dw_sku": "DWQC-600203",
+ "cost": 0,
+ "retail": 0,
"sample": "4.25",
- "sampleOnly": false,
- "title": "Hampton, Mist Wallcoverings | Thibaut",
+ "sampleOnly": true,
+ "title": "Stitched Floral, Multi Blues Turquoise Lilac Wallcoverings | Quadrille",
"willActivate": true
},
{
- "vendor": "Designtex",
- "dw_sku": "DWDX-220516",
- "cost": 58,
- "retail": 104.98,
+ "vendor": "Alan Campbell",
+ "dw_sku": "DWAK-700202",
+ "cost": 0,
+ "retail": 0,
"sample": "4.25",
- "sampleOnly": false,
- "title": "Fragments, New York Wallcoverings | Designtex",
- "willActivate": true,
- "held": true,
- "heldReason": "\"York Wallcoverings\" is a banned front-facing trade-parent name"
+ "sampleOnly": true,
+ "title": "Inca Gold on Tint Wallcoverings | Alan Campbell",
+ "willActivate": true
},
{
- "vendor": "Designtex",
- "dw_sku": "DWDX-220521",
- "cost": 58,
- "retail": 104.98,
+ "vendor": "Alan Campbell",
+ "dw_sku": "DWAK-700203",
+ "cost": 0,
+ "retail": 0,
"sample": "4.25",
- "sampleOnly": false,
- "title": "Resurfacing, Primer Wallcoverings | Designtex",
+ "sampleOnly": true,
+ "title": "Shrimp on Tint Wallcoverings | Alan Campbell",
"willActivate": true
},
{
- "vendor": "Designtex",
- "dw_sku": "DWDX-220522",
- "cost": 58,
- "retail": 104.98,
+ "vendor": "Alan Campbell",
+ "dw_sku": "DWAK-700204",
+ "cost": 0,
+ "retail": 0,
"sample": "4.25",
- "sampleOnly": false,
- "title": "Resurfacing, Blackout Wallcoverings | Designtex",
+ "sampleOnly": true,
+ "title": "French Blue on Tint Wallcoverings | Alan Campbell",
"willActivate": true
},
{
- "vendor": "Newwall",
- "dw_sku": "DWXW-1005721",
- "cost": 88,
- "retail": 159.28,
+ "vendor": "Home Couture",
+ "dw_sku": "DWHJ-900197",
+ "cost": 0,
+ "retail": 0,
"sample": "4.25",
- "sampleOnly": false,
- "title": "Skyscraper Window, Made to Measure Mural Vinyl Wallcoverings | Newwall",
- "willActivate": false
+ "sampleOnly": true,
+ "title": "Fern Green on Tint Wallcoverings | Home Couture",
+ "willActivate": true
},
{
- "vendor": "Newwall",
- "dw_sku": "DWXW-1005722",
- "cost": 88,
- "retail": 159.28,
+ "vendor": "Home Couture",
+ "dw_sku": "DWHJ-900198",
+ "cost": 0,
+ "retail": 0,
"sample": "4.25",
- "sampleOnly": false,
- "title": "Pink Old Wall, Made to Measure Mural Vinyl Wallcoverings | Newwall",
- "willActivate": false
+ "sampleOnly": true,
+ "title": "New Navy on Tint Wallcoverings | Home Couture",
+ "willActivate": true
},
{
- "vendor": "Newwall",
- "dw_sku": "DWXW-1005723",
- "cost": 88,
- "retail": 159.28,
+ "vendor": "Home Couture",
+ "dw_sku": "DWHJ-900199",
+ "cost": 0,
+ "retail": 0,
"sample": "4.25",
- "sampleOnly": false,
- "title": "Fronton Wall, Made to Measure Mural Vinyl Wallcoverings | Newwall",
- "willActivate": false
+ "sampleOnly": true,
+ "title": "Black on Tint Wallcoverings | Home Couture",
+ "willActivate": true
},
{
- "vendor": "Brewster & York",
- "dw_sku": "DWBR-170879",
- "cost": 90,
- "retail": 162.9,
+ "vendor": "Suncloth",
+ "dw_sku": "DWUX-800203",
+ "cost": 0,
+ "retail": 0,
"sample": "4.25",
- "sampleOnly": false,
- "title": "Lindlöv, Moss Wallcoverings | Malibu Wallcovering",
+ "sampleOnly": true,
+ "title": "Magenta New Navy Wallcoverings | Suncloth",
"willActivate": true
},
{
- "vendor": "Brewster & York",
- "dw_sku": "DWBR-170880",
- "cost": 90,
- "retail": 162.9,
+ "vendor": "Suncloth",
+ "dw_sku": "DWUX-800204",
+ "cost": 0,
+ "retail": 0,
"sample": "4.25",
- "sampleOnly": false,
- "title": "Lindlöv, Taupe Wallcoverings | Malibu Wallcovering",
+ "sampleOnly": true,
+ "title": "Pacific Blue Navy Wallcoverings | Suncloth",
"willActivate": true
},
{
- "vendor": "Brewster & York",
- "dw_sku": "DWBR-170881",
- "cost": 90,
- "retail": 162.9,
+ "vendor": "Suncloth",
+ "dw_sku": "DWUX-800205",
+ "cost": 0,
+ "retail": 0,
"sample": "4.25",
- "sampleOnly": false,
- "title": "Lindlöv, Light Grey Wallcoverings | Malibu Wallcovering",
+ "sampleOnly": true,
+ "title": "Black Brown Wallcoverings | Suncloth",
"willActivate": true
},
{
- "vendor": "Kravet",
- "dw_sku": "DWKK-102919",
- "cost": 59.95,
- "retail": 89.93,
+ "vendor": "Plains",
+ "dw_sku": "DWYP-1000200",
+ "cost": 0,
+ "retail": 0,
"sample": "4.25",
- "sampleOnly": false,
- "title": "Poet Plain, Seafoam Green Wallcoverings | Kravet",
+ "sampleOnly": true,
+ "title": "Flax Wallcoverings | Plains",
"willActivate": true
},
{
- "vendor": "Kravet",
- "dw_sku": "DWKK-102920",
- "cost": 59.95,
- "retail": 89.93,
+ "vendor": "Plains",
+ "dw_sku": "DWYP-1000201",
+ "cost": 0,
+ "retail": 0,
"sample": "4.25",
- "sampleOnly": false,
- "title": "Poet Plain, Beige Wallcoverings | Kravet",
+ "sampleOnly": true,
+ "title": "Dove Wallcoverings | Plains",
"willActivate": true
},
{
- "vendor": "Kravet",
- "dw_sku": "DWKK-102921",
- "cost": 59.95,
- "retail": 89.93,
+ "vendor": "Plains",
+ "dw_sku": "DWYP-1000202",
+ "cost": 0,
+ "retail": 0,
"sample": "4.25",
- "sampleOnly": false,
- "title": "Poet Plain, Celadon Wallcoverings | Kravet",
+ "sampleOnly": true,
+ "title": "Natural Wallcoverings | Plains",
"willActivate": true
}
]
\ No newline at end of file
diff --git a/shopify/scripts/cadence/data/upload-restore-2026-07-02.jsonl b/shopify/scripts/cadence/data/upload-restore-2026-07-02.jsonl
index 0733979c..8c94e210 100644
--- a/shopify/scripts/cadence/data/upload-restore-2026-07-02.jsonl
+++ b/shopify/scripts/cadence/data/upload-restore-2026-07-02.jsonl
@@ -281,3 +281,21 @@
{"table":"kravet_catalog","mfr_sku":"36649.15.0","dw_sku":"DWKK-102919","shopify_product_id":"7874188279859","action":"created","activated":true,"published":true,"sampleOnly":false,"status":"ACTIVE","batch_id":"upload-am-2026-07-02T17-40-00-924Z","ts":"2026-07-02T17:40:47.406Z"}
{"table":"kravet_catalog","mfr_sku":"36649.16.0","dw_sku":"DWKK-102920","shopify_product_id":"7874188312627","action":"created","activated":true,"published":true,"sampleOnly":false,"status":"ACTIVE","batch_id":"upload-am-2026-07-02T17-40-00-924Z","ts":"2026-07-02T17:40:50.897Z"}
{"table":"kravet_catalog","mfr_sku":"36649.23.0","dw_sku":"DWKK-102921","shopify_product_id":"7874188345395","action":"created","activated":true,"published":true,"sampleOnly":false,"status":"ACTIVE","batch_id":"upload-am-2026-07-02T17-40-00-924Z","ts":"2026-07-02T17:40:54.358Z"}
+{"table":"schumacher_catalog","mfr_sku":"5011751","dw_sku":"DWLK-807240","shopify_product_id":"7874222030899","action":"created","activated":true,"published":true,"sampleOnly":false,"status":"ACTIVE","batch_id":"upload-am-2026-07-02T18-40-00-149Z","ts":"2026-07-02T18:40:06.137Z"}
+{"table":"schumacher_catalog","mfr_sku":"5011752","dw_sku":"DWLK-807250","shopify_product_id":"7874222129203","action":"created","activated":true,"published":true,"sampleOnly":false,"status":"ACTIVE","batch_id":"upload-am-2026-07-02T18-40-00-149Z","ts":"2026-07-02T18:40:09.833Z"}
+{"table":"schumacher_catalog","mfr_sku":"5011760","dw_sku":"DWLK-807260","shopify_product_id":"7874222161971","action":"created","activated":true,"published":true,"sampleOnly":false,"status":"ACTIVE","batch_id":"upload-am-2026-07-02T18-40-00-149Z","ts":"2026-07-02T18:40:13.488Z"}
+{"table":"quadrille_house_catalog","mfr_sku":"JF01000-06","dw_sku":"DWQC-600201","shopify_product_id":"7874222194739","action":"created","activated":true,"published":true,"sampleOnly":true,"status":"ACTIVE","batch_id":"upload-am-2026-07-02T18-40-00-149Z","ts":"2026-07-02T18:40:17.474Z"}
+{"table":"quadrille_house_catalog","mfr_sku":"JF01000-01","dw_sku":"DWQC-600202","shopify_product_id":"7874222227507","action":"created","activated":true,"published":true,"sampleOnly":true,"status":"ACTIVE","batch_id":"upload-am-2026-07-02T18-40-00-149Z","ts":"2026-07-02T18:40:21.371Z"}
+{"table":"quadrille_house_catalog","mfr_sku":"306541F","dw_sku":"DWQC-600203","shopify_product_id":"7874222293043","action":"created","activated":true,"published":true,"sampleOnly":true,"status":"ACTIVE","batch_id":"upload-am-2026-07-02T18-40-00-149Z","ts":"2026-07-02T18:40:25.156Z"}
+{"table":"quadrille_house_catalog","mfr_sku":"AC303-13","dw_sku":"DWAK-700202","shopify_product_id":"7874222391347","action":"created","activated":true,"published":true,"sampleOnly":true,"status":"ACTIVE","batch_id":"upload-am-2026-07-02T18-40-00-149Z","ts":"2026-07-02T18:40:29.463Z"}
+{"table":"quadrille_house_catalog","mfr_sku":"AC303-17","dw_sku":"DWAK-700203","shopify_product_id":"7874222456883","action":"created","activated":true,"published":true,"sampleOnly":true,"status":"ACTIVE","batch_id":"upload-am-2026-07-02T18-40-00-149Z","ts":"2026-07-02T18:40:33.078Z"}
+{"table":"quadrille_house_catalog","mfr_sku":"AC303-15","dw_sku":"DWAK-700204","shopify_product_id":"7874222555187","action":"created","activated":true,"published":true,"sampleOnly":true,"status":"ACTIVE","batch_id":"upload-am-2026-07-02T18-40-00-149Z","ts":"2026-07-02T18:40:37.270Z"}
+{"table":"quadrille_house_catalog","mfr_sku":"HC1860-02","dw_sku":"DWHJ-900197","shopify_product_id":"7874222587955","action":"created","activated":true,"published":true,"sampleOnly":true,"status":"ACTIVE","batch_id":"upload-am-2026-07-02T18-40-00-149Z","ts":"2026-07-02T18:40:41.220Z"}
+{"table":"quadrille_house_catalog","mfr_sku":"HC1860-07","dw_sku":"DWHJ-900198","shopify_product_id":"7874222653491","action":"created","activated":true,"published":true,"sampleOnly":true,"status":"ACTIVE","batch_id":"upload-am-2026-07-02T18-40-00-149Z","ts":"2026-07-02T18:40:44.861Z"}
+{"table":"quadrille_house_catalog","mfr_sku":"HC1860-09","dw_sku":"DWHJ-900199","shopify_product_id":"7874222719027","action":"created","activated":true,"published":true,"sampleOnly":true,"status":"ACTIVE","batch_id":"upload-am-2026-07-02T18-40-00-149Z","ts":"2026-07-02T18:40:48.445Z"}
+{"table":"quadrille_house_catalog","mfr_sku":"149-34SUN","dw_sku":"DWUX-800203","shopify_product_id":"7874222784563","action":"created","activated":true,"published":true,"sampleOnly":true,"status":"ACTIVE","batch_id":"upload-am-2026-07-02T18-40-00-149Z","ts":"2026-07-02T18:40:52.759Z"}
+{"table":"quadrille_house_catalog","mfr_sku":"149-35SUN","dw_sku":"DWUX-800204","shopify_product_id":"7874222817331","action":"created","activated":true,"published":true,"sampleOnly":true,"status":"ACTIVE","batch_id":"upload-am-2026-07-02T18-40-00-149Z","ts":"2026-07-02T18:40:56.467Z"}
+{"table":"quadrille_house_catalog","mfr_sku":"149-30SUN","dw_sku":"DWUX-800205","shopify_product_id":"7874222850099","action":"created","activated":true,"published":true,"sampleOnly":true,"status":"ACTIVE","batch_id":"upload-am-2026-07-02T18-40-00-149Z","ts":"2026-07-02T18:41:00.094Z"}
+{"table":"quadrille_house_catalog","mfr_sku":"HC1420-05","dw_sku":"DWYP-1000200","shopify_product_id":"7874222882867","action":"created","activated":true,"published":true,"sampleOnly":true,"status":"ACTIVE","batch_id":"upload-am-2026-07-02T18-40-00-149Z","ts":"2026-07-02T18:41:03.962Z"}
+{"table":"quadrille_house_catalog","mfr_sku":"HC1420-04","dw_sku":"DWYP-1000201","shopify_product_id":"7874222948403","action":"created","activated":true,"published":true,"sampleOnly":true,"status":"ACTIVE","batch_id":"upload-am-2026-07-02T18-40-00-149Z","ts":"2026-07-02T18:41:07.455Z"}
+{"table":"quadrille_house_catalog","mfr_sku":"HC1450-01","dw_sku":"DWYP-1000202","shopify_product_id":"7874222981171","action":"created","activated":true,"published":true,"sampleOnly":true,"status":"ACTIVE","batch_id":"upload-am-2026-07-02T18-40-00-149Z","ts":"2026-07-02T18:41:10.948Z"}
diff --git a/shopify/scripts/fix-dwtt-conflict-2-skus.py b/shopify/scripts/fix-dwtt-conflict-2-skus.py
new file mode 100644
index 00000000..3e8c2f18
--- /dev/null
+++ b/shopify/scripts/fix-dwtt-conflict-2-skus.py
@@ -0,0 +1,151 @@
+#!/usr/bin/env python3
+"""
+Fix the 2 wave-1 conflict SKUs held for manual review (DTD verdict A, 3/3,
+2026-07-02): AT57882 (double-roll "11 Yards" length -> single-roll) and
+T41013 (imperial "13.5 ft" -> metric "(4.11 m)" formatting) + the withheld
+single-roll unit_of_measure copy on both.
+
+Values re-confirmed against the LIVE thibautdesign.com PDPs 2026-07-02
+(RollLength 5.5 / 4.5, width 27) — NOT from anna_french_catalog, whose
+AT57882 length column has since drifted to a bad "11 Feet" re-scrape parse.
+
+Same write path as set-dwtt-single-roll-dimensions.py (metafieldsSet,
+global namespace, single_line_text_field). Only writes fields that differ.
+Default: --dry-run. Cost: $0 (Shopify Admin API).
+"""
+import json, os, sys, time, urllib.request, datetime
+
+TOKEN = os.environ["SHOPIFY_ADMIN_TOKEN"]
+SHOP = "designer-laboratory-sandbox.myshopify.com"
+GQL = f"https://{SHOP}/admin/api/2024-10/graphql.json"
+DRY = "--dry-run" in sys.argv or "--dry" in sys.argv
+COPY = "Priced per single roll. Single Roll Dimensions. Packed in 2 roll increments only."
+BEFORE_PATH = os.path.expanduser(
+ "~/Projects/Designer-Wallcoverings/audits/dwtt-conflict-2-before-state.jsonl")
+AUDIT_PATH = os.path.expanduser(
+ "~/Projects/Designer-Wallcoverings/shopify/scripts/audits/dwtt-conflict-2-fix.json")
+
+TARGETS = {
+ "gid://shopify/Product/7552689897523": dict(
+ mfr="AT57882",
+ width="27 in (68.58 cm)",
+ length="5.5 yd (5.03 m)",
+ unit_of_measure=COPY),
+ "gid://shopify/Product/7552706543667": dict(
+ mfr="T41013",
+ width=None, # not flagged; wave already handled — leave untouched
+ length="4.5 yd (4.11 m)",
+ unit_of_measure=COPY),
+}
+
+NODES = """
+query($ids:[ID!]!){
+ nodes(ids:$ids){
+ ... on Product{
+ id status title handle
+ w:metafield(namespace:"global",key:"width"){value}
+ l:metafield(namespace:"global",key:"length"){value}
+ uom:metafield(namespace:"global",key:"unit_of_measure"){value}
+ }
+ }
+}
+"""
+
+SET = """
+mutation($mfs:[MetafieldsSetInput!]!){
+ metafieldsSet(metafields:$mfs){
+ metafields{ id }
+ userErrors{ field message }
+ }
+}
+"""
+
+def gql(q, v=None):
+ body = json.dumps({"query": q, "variables": v or {}}).encode()
+ req = urllib.request.Request(GQL, data=body, headers={
+ "X-Shopify-Access-Token": TOKEN, "Content-Type": "application/json"})
+ for _ in range(8):
+ try:
+ with urllib.request.urlopen(req) as r:
+ d = json.load(r)
+ if d.get("errors"):
+ if "THROTTLED" in json.dumps(d["errors"]):
+ time.sleep(2.5); continue
+ raise SystemExit("GQL ERR: " + json.dumps(d["errors"]))
+ return d["data"]
+ except urllib.error.HTTPError as e:
+ if e.code == 429:
+ time.sleep(2.5); continue
+ raise
+ raise SystemExit("retries exhausted")
+
+def clean(s):
+ return (s or "").replace(" ", " ").strip()
+
+def snapshot():
+ d = gql(NODES, {"ids": list(TARGETS.keys())})
+ out = {}
+ for n in d["nodes"]:
+ if not n: continue
+ out[n["id"]] = dict(
+ handle=n["handle"], status=n["status"], title=n["title"],
+ width=clean((n["w"] or {}).get("value")),
+ length=clean((n["l"] or {}).get("value")),
+ unit_of_measure=clean((n["uom"] or {}).get("value")))
+ return out
+
+def main():
+ before = snapshot()
+ os.makedirs(os.path.dirname(BEFORE_PATH), exist_ok=True)
+ with open(BEFORE_PATH, "a") as f:
+ for gid, cur in before.items():
+ f.write(json.dumps(dict(ts=datetime.datetime.now().isoformat(),
+ product_id=gid, mfr=TARGETS[gid]["mfr"],
+ before=cur)) + "\n")
+
+ writes, plan = [], []
+ for gid, t in TARGETS.items():
+ cur = before.get(gid)
+ if not cur:
+ raise SystemExit(f"product not found: {gid} ({t['mfr']})")
+ if cur["status"] == "ARCHIVED":
+ raise SystemExit(f"ARCHIVED, refusing: {t['mfr']}")
+ for key in ("width", "length", "unit_of_measure"):
+ want = t.get(key)
+ if want is None or cur[key] == want:
+ continue
+ plan.append(f"{t['mfr']}.{key}: {cur[key]!r} -> {want!r}")
+ writes.append({"ownerId": gid, "namespace": "global", "key": key,
+ "type": "single_line_text_field", "value": want})
+
+ print("PLAN:")
+ for p in plan: print(" " + p)
+ print(f"{len(writes)} metafield writes queued")
+
+ if DRY:
+ print("DRY RUN — no writes performed.")
+ return
+
+ d = gql(SET, {"mfs": writes})
+ ue = d["metafieldsSet"]["userErrors"]
+ print(f"wrote {len(writes)} metafields, userErrors={ue or 0}")
+
+ after = snapshot()
+ ok = True
+ for gid, t in TARGETS.items():
+ for key in ("width", "length", "unit_of_measure"):
+ want = t.get(key)
+ if want is not None and after[gid][key] != want:
+ ok = False
+ print(f"VERIFY FAIL {t['mfr']}.{key}: {after[gid][key]!r}")
+ print("VERIFY: " + ("all values confirmed on Shopify" if ok else "MISMATCH — see above"))
+
+ with open(AUDIT_PATH, "w") as f:
+ json.dump(dict(generated_at=datetime.datetime.now().isoformat(),
+ verdict="DTD A 3/3 2026-07-02", plan=plan,
+ before=before, after=after,
+ user_errors=ue, verified=ok), f, indent=1)
+ print(f"Audit JSON: {AUDIT_PATH}")
+
+if __name__ == "__main__":
+ main()
← a6251257 discontinued-sweep FINAL: thibaut 299 discontinued (285 dual
·
back to Designer Wallcoverings
·
PDP qty-inline: move quantity stepper to the right of the pr 631ae2c3 →