[object Object]

← back to York Yardgood Exec

York contract yard-good reprice: 73-product executor + dry-run clean + rollback

bc9720a84d695a02e19e7c25b5466c217825ade3 · 2026-09-09 15:39:41 -0700 · Steve

Files touched

Diff

commit bc9720a84d695a02e19e7c25b5466c217825ade3
Author: Steve <steve@designerwallcoverings.com>
Date:   Wed Sep 9 15:39:41 2026 -0700

    York contract yard-good reprice: 73-product executor + dry-run clean + rollback
---
 .gitignore              |   4 +
 data/york73-target.json | 878 ++++++++++++++++++++++++++++++++++++++++++++++++
 york73-rollback.mjs     |  19 ++
 york73.mjs              |  72 ++++
 4 files changed, 973 insertions(+)

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..1bcdbdc
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+node_modules/
+.env*
+*.log
+.DS_Store
diff --git a/data/york73-target.json b/data/york73-target.json
new file mode 100644
index 0000000..5b1fab6
--- /dev/null
+++ b/data/york73-target.json
@@ -0,0 +1,878 @@
+[
+ {
+  "product_id": "7882746822707",
+  "sell_sku": "DWJS-91645",
+  "pattern": "Linen Levels",
+  "title": "Linen Levels Dove",
+  "net": 52.5,
+  "retail": 95.02,
+  "price_code": "G",
+  "current_price": "46.57",
+  "current_uom": "Priced Per Single Roll",
+  "current_min": "2"
+ },
+ {
+  "product_id": "7882746855475",
+  "sell_sku": "DWJS-91646",
+  "pattern": "Linen Levels",
+  "title": "Linen Levels Fig",
+  "net": 52.5,
+  "retail": 95.02,
+  "price_code": "G",
+  "current_price": "46.57",
+  "current_uom": "Priced Per Single Roll",
+  "current_min": "2"
+ },
+ {
+  "product_id": "7882746888243",
+  "sell_sku": "DWJS-91647",
+  "pattern": "Linen Levels Ice",
+  "title": "Linen Levels Ice Blue",
+  "net": 52.5,
+  "retail": 95.02,
+  "price_code": "G",
+  "current_price": "46.57",
+  "current_uom": "Priced Per Single Roll",
+  "current_min": "2"
+ },
+ {
+  "product_id": "7882746921011",
+  "sell_sku": "DWJS-91648",
+  "pattern": "Linen Levels",
+  "title": "Linen Levels Indigo",
+  "net": 52.5,
+  "retail": 95.02,
+  "price_code": "G",
+  "current_price": "46.57",
+  "current_uom": "Priced Per Single Roll",
+  "current_min": "2"
+ },
+ {
+  "product_id": "7882746953779",
+  "sell_sku": "DWJS-91649",
+  "pattern": "Linen Levels",
+  "title": "Linen Levels Mediterranean",
+  "net": 52.5,
+  "retail": 95.02,
+  "price_code": "G",
+  "current_price": "46.57",
+  "current_uom": "Priced Per Single Roll",
+  "current_min": "2"
+ },
+ {
+  "product_id": "7882746986547",
+  "sell_sku": "DWJS-91650",
+  "pattern": "Linen Levels",
+  "title": "Linen Levels Portabella",
+  "net": 52.5,
+  "retail": 95.02,
+  "price_code": "G",
+  "current_price": "46.57",
+  "current_uom": "Priced Per Single Roll",
+  "current_min": "2"
+ },
+ {
+  "product_id": "7882747019315",
+  "sell_sku": "DWJS-91651",
+  "pattern": "Linen Levels",
+  "title": "Linen Levels Russet",
+  "net": 52.5,
+  "retail": 95.02,
+  "price_code": "G",
+  "current_price": "46.57",
+  "current_uom": "Priced Per Single Roll",
+  "current_min": "2"
+ },
+ {
+  "product_id": "7882747052083",
+  "sell_sku": "DWJS-91652",
+  "pattern": "Linen Levels",
+  "title": "Linen Levels Twilight",
+  "net": 52.5,
+  "retail": 95.02,
+  "price_code": "G",
+  "current_price": "46.57",
+  "current_uom": "Priced Per Single Roll",
+  "current_min": "2"
+ },
+ {
+  "product_id": "7882747084851",
+  "sell_sku": "DWJS-91653",
+  "pattern": "Linen Levels",
+  "title": "Linen Levels Whitecaps",
+  "net": 52.5,
+  "retail": 95.02,
+  "price_code": "G",
+  "current_price": "46.57",
+  "current_uom": "Priced Per Single Roll",
+  "current_min": "2"
+ },
+ {
+  "product_id": "7882753081395",
+  "sell_sku": "DWJS-91793",
+  "pattern": "Sundrenched Linen Soft",
+  "title": "Sundrenched Linen Soft White",
+  "net": 85.0,
+  "retail": 153.85,
+  "price_code": "K",
+  "current_price": "75.98",
+  "current_uom": "Priced Per Single Roll",
+  "current_min": "2"
+ },
+ {
+  "product_id": "7882755571763",
+  "sell_sku": "DWJS-91869",
+  "pattern": "Boulevard",
+  "title": "Boulevard Charcoal",
+  "net": 20.0,
+  "retail": 36.2,
+  "price_code": "A",
+  "current_price": "24.51",
+  "current_uom": "Priced Per Single Roll",
+  "current_min": "2"
+ },
+ {
+  "product_id": "7882755604531",
+  "sell_sku": "DWJS-91870",
+  "pattern": "Boulevard",
+  "title": "Boulevard Lakefront",
+  "net": 20.0,
+  "retail": 36.2,
+  "price_code": "A",
+  "current_price": "24.51",
+  "current_uom": "Priced Per Single Roll",
+  "current_min": "2"
+ },
+ {
+  "product_id": "7882755637299",
+  "sell_sku": "DWJS-91871",
+  "pattern": "Boulevard",
+  "title": "Boulevard Nesting",
+  "net": 20.0,
+  "retail": 36.2,
+  "price_code": "A",
+  "current_price": "24.51",
+  "current_uom": "Priced Per Single Roll",
+  "current_min": "2"
+ },
+ {
+  "product_id": "7882755670067",
+  "sell_sku": "DWJS-91872",
+  "pattern": "Boulevard",
+  "title": "Boulevard Whitewash",
+  "net": 20.0,
+  "retail": 36.2,
+  "price_code": "A",
+  "current_price": "24.51",
+  "current_uom": "Priced Per Single Roll",
+  "current_min": "2"
+ },
+ {
+  "product_id": "7882755702835",
+  "sell_sku": "DWJS-91873",
+  "pattern": "Brindled",
+  "title": "Brindled Ash",
+  "net": 20.0,
+  "retail": 36.2,
+  "price_code": "A",
+  "current_price": "24.51",
+  "current_uom": "Priced Per Single Roll",
+  "current_min": "2"
+ },
+ {
+  "product_id": "7882755801139",
+  "sell_sku": "DWJS-91876",
+  "pattern": "Brindled",
+  "title": "Brindled Cotton",
+  "net": 20.0,
+  "retail": 36.2,
+  "price_code": "A",
+  "current_price": "24.51",
+  "current_uom": "Priced Per Single Roll",
+  "current_min": "2"
+ },
+ {
+  "product_id": "7882755866675",
+  "sell_sku": "DWJS-91878",
+  "pattern": "Brindled",
+  "title": "Brindled Linen",
+  "net": 20.0,
+  "retail": 36.2,
+  "price_code": "A",
+  "current_price": "24.51",
+  "current_uom": "Priced Per Single Roll",
+  "current_min": "2"
+ },
+ {
+  "product_id": "7882755932211",
+  "sell_sku": "DWJS-91880",
+  "pattern": "Brindled",
+  "title": "Brindled Mineral",
+  "net": 20.0,
+  "retail": 36.2,
+  "price_code": "A",
+  "current_price": "24.51",
+  "current_uom": "Priced Per Single Roll",
+  "current_min": "2"
+ },
+ {
+  "product_id": "7882755997747",
+  "sell_sku": "DWJS-91881",
+  "pattern": "Brindled",
+  "title": "Brindled Prairie",
+  "net": 20.0,
+  "retail": 36.2,
+  "price_code": "A",
+  "current_price": "24.51",
+  "current_uom": "Priced Per Single Roll",
+  "current_min": "2"
+ },
+ {
+  "product_id": "7882756096051",
+  "sell_sku": "DWJS-91883",
+  "pattern": "Brindled",
+  "title": "Brindled Reservoir",
+  "net": 20.0,
+  "retail": 36.2,
+  "price_code": "A",
+  "current_price": "24.51",
+  "current_uom": "Priced Per Single Roll",
+  "current_min": "2"
+ },
+ {
+  "product_id": "7882756194355",
+  "sell_sku": "DWJS-91886",
+  "pattern": "Brindled",
+  "title": "Brindled Shadow",
+  "net": 20.0,
+  "retail": 36.2,
+  "price_code": "A",
+  "current_price": "24.51",
+  "current_uom": "Priced Per Single Roll",
+  "current_min": "2"
+ },
+ {
+  "product_id": "7882756227123",
+  "sell_sku": "DWJS-91887",
+  "pattern": "Center Square",
+  "title": "Center Square Charcoal",
+  "net": 20.0,
+  "retail": 36.2,
+  "price_code": "A",
+  "current_price": "24.51",
+  "current_uom": "Priced Per Single Roll",
+  "current_min": "2"
+ },
+ {
+  "product_id": "7882756259891",
+  "sell_sku": "DWJS-91888",
+  "pattern": "Center Square",
+  "title": "Center Square Indigo",
+  "net": 20.0,
+  "retail": 36.2,
+  "price_code": "A",
+  "current_price": "24.51",
+  "current_uom": "Priced Per Single Roll",
+  "current_min": "2"
+ },
+ {
+  "product_id": "7882756325427",
+  "sell_sku": "DWJS-91889",
+  "pattern": "Center Square",
+  "title": "Center Square Loft",
+  "net": 20.0,
+  "retail": 36.2,
+  "price_code": "A",
+  "current_price": "24.51",
+  "current_uom": "Priced Per Single Roll",
+  "current_min": "2"
+ },
+ {
+  "product_id": "7882756358195",
+  "sell_sku": "DWJS-91890",
+  "pattern": "Center Square",
+  "title": "Center Square Yarn",
+  "net": 20.0,
+  "retail": 36.2,
+  "price_code": "A",
+  "current_price": "24.51",
+  "current_uom": "Priced Per Single Roll",
+  "current_min": "2"
+ },
+ {
+  "product_id": "7882756423731",
+  "sell_sku": "DWJS-91892",
+  "pattern": "Challenger Deep",
+  "title": "Challenger Deep Rock",
+  "net": 20.0,
+  "retail": 36.2,
+  "price_code": "A",
+  "current_price": "24.51",
+  "current_uom": "Priced Per Single Roll",
+  "current_min": "2"
+ },
+ {
+  "product_id": "7882756489267",
+  "sell_sku": "DWJS-91894",
+  "pattern": "Challenger",
+  "title": "Challenger Mineral",
+  "net": 20.0,
+  "retail": 36.2,
+  "price_code": "A",
+  "current_price": "24.51",
+  "current_uom": "Priced Per Single Roll",
+  "current_min": "2"
+ },
+ {
+  "product_id": "7882756554803",
+  "sell_sku": "DWJS-91896",
+  "pattern": "Challenger",
+  "title": "Challenger Nesting",
+  "net": 20.0,
+  "retail": 36.2,
+  "price_code": "A",
+  "current_price": "24.51",
+  "current_uom": "Priced Per Single Roll",
+  "current_min": "2"
+ },
+ {
+  "product_id": "7882756620339",
+  "sell_sku": "DWJS-91898",
+  "pattern": "Challenger",
+  "title": "Challenger Nook",
+  "net": 20.0,
+  "retail": 36.2,
+  "price_code": "A",
+  "current_price": "24.51",
+  "current_uom": "Priced Per Single Roll",
+  "current_min": "2"
+ },
+ {
+  "product_id": "7882756685875",
+  "sell_sku": "DWJS-91900",
+  "pattern": "Challenger",
+  "title": "Challenger Shadow",
+  "net": 20.0,
+  "retail": 36.2,
+  "price_code": "A",
+  "current_price": "24.51",
+  "current_uom": "Priced Per Single Roll",
+  "current_min": "2"
+ },
+ {
+  "product_id": "7882756915251",
+  "sell_sku": "DWJS-91907",
+  "pattern": "Crossroad",
+  "title": "Crossroad Denim",
+  "net": 20.0,
+  "retail": 36.2,
+  "price_code": "A",
+  "current_price": "24.51",
+  "current_uom": "Priced Per Single Roll",
+  "current_min": "2"
+ },
+ {
+  "product_id": "7882757013555",
+  "sell_sku": "DWJS-91910",
+  "pattern": "Crossroad",
+  "title": "Crossroad Linen",
+  "net": 20.0,
+  "retail": 36.2,
+  "price_code": "A",
+  "current_price": "24.51",
+  "current_uom": "Priced Per Single Roll",
+  "current_min": "2"
+ },
+ {
+  "product_id": "7882757079091",
+  "sell_sku": "DWJS-91912",
+  "pattern": "Crossroad",
+  "title": "Crossroad Oat",
+  "net": 20.0,
+  "retail": 36.2,
+  "price_code": "A",
+  "current_price": "24.51",
+  "current_uom": "Priced Per Single Roll",
+  "current_min": "2"
+ },
+ {
+  "product_id": "7882757111859",
+  "sell_sku": "DWJS-91913",
+  "pattern": "Crossroad",
+  "title": "Crossroad Reservoir",
+  "net": 20.0,
+  "retail": 36.2,
+  "price_code": "A",
+  "current_price": "24.51",
+  "current_uom": "Priced Per Single Roll",
+  "current_min": "2"
+ },
+ {
+  "product_id": "7882757177395",
+  "sell_sku": "DWJS-91915",
+  "pattern": "Crossroad",
+  "title": "Crossroad Trowel",
+  "net": 20.0,
+  "retail": 36.2,
+  "price_code": "A",
+  "current_price": "24.51",
+  "current_uom": "Priced Per Single Roll",
+  "current_min": "2"
+ },
+ {
+  "product_id": "7882757242931",
+  "sell_sku": "DWJS-91917",
+  "pattern": "Crossroad",
+  "title": "Crossroad Whitewash",
+  "net": 20.0,
+  "retail": 36.2,
+  "price_code": "A",
+  "current_price": "24.51",
+  "current_uom": "Priced Per Single Roll",
+  "current_min": "2"
+ },
+ {
+  "product_id": "7882758291507",
+  "sell_sku": "DWJS-91944",
+  "pattern": "In The Details",
+  "title": "In The Details Charcoal",
+  "net": 20.0,
+  "retail": 36.2,
+  "price_code": "A",
+  "current_price": "24.51",
+  "current_uom": "Priced Per Single Roll",
+  "current_min": "2"
+ },
+ {
+  "product_id": "7882758324275",
+  "sell_sku": "DWJS-91945",
+  "pattern": "In The Details",
+  "title": "In The Details Linen",
+  "net": 20.0,
+  "retail": 36.2,
+  "price_code": "A",
+  "current_price": "24.51",
+  "current_uom": "Priced Per Single Roll",
+  "current_min": "2"
+ },
+ {
+  "product_id": "7882758422579",
+  "sell_sku": "DWJS-91948",
+  "pattern": "In The Details",
+  "title": "In The Details Loft",
+  "net": 20.0,
+  "retail": 36.2,
+  "price_code": "A",
+  "current_price": "24.51",
+  "current_uom": "Priced Per Single Roll",
+  "current_min": "2"
+ },
+ {
+  "product_id": "7882758520883",
+  "sell_sku": "DWJS-91950",
+  "pattern": "In The Details",
+  "title": "In The Details Mineral",
+  "net": 20.0,
+  "retail": 36.2,
+  "price_code": "A",
+  "current_price": "24.51",
+  "current_uom": "Priced Per Single Roll",
+  "current_min": "2"
+ },
+ {
+  "product_id": "7882760192051",
+  "sell_sku": "DWJS-91990",
+  "pattern": "Loomed",
+  "title": "Loomed Ash",
+  "net": 20.0,
+  "retail": 36.2,
+  "price_code": "A",
+  "current_price": "24.51",
+  "current_uom": "Priced Per Single Roll",
+  "current_min": "2"
+ },
+ {
+  "product_id": "7882760290355",
+  "sell_sku": "DWJS-91993",
+  "pattern": "Loomed",
+  "title": "Loomed Gravel",
+  "net": 20.0,
+  "retail": 36.2,
+  "price_code": "A",
+  "current_price": "24.51",
+  "current_uom": "Priced Per Single Roll",
+  "current_min": "2"
+ },
+ {
+  "product_id": "7882760355891",
+  "sell_sku": "DWJS-91995",
+  "pattern": "Loomed",
+  "title": "Loomed Indigo",
+  "net": 20.0,
+  "retail": 36.2,
+  "price_code": "A",
+  "current_price": "24.51",
+  "current_uom": "Priced Per Single Roll",
+  "current_min": "2"
+ },
+ {
+  "product_id": "7882760388659",
+  "sell_sku": "DWJS-91996",
+  "pattern": "Loomed",
+  "title": "Loomed Nesting",
+  "net": 20.0,
+  "retail": 36.2,
+  "price_code": "A",
+  "current_price": "24.51",
+  "current_uom": "Priced Per Single Roll",
+  "current_min": "2"
+ },
+ {
+  "product_id": "7882760486963",
+  "sell_sku": "DWJS-91999",
+  "pattern": "Loomed",
+  "title": "Loomed Seed",
+  "net": 20.0,
+  "retail": 36.2,
+  "price_code": "A",
+  "current_price": "24.51",
+  "current_uom": "Priced Per Single Roll",
+  "current_min": "2"
+ },
+ {
+  "product_id": "7882760519731",
+  "sell_sku": "DWJS-92000",
+  "pattern": "Loomed",
+  "title": "Loomed Wheat",
+  "net": 20.0,
+  "retail": 36.2,
+  "price_code": "A",
+  "current_price": "24.51",
+  "current_uom": "Priced Per Single Roll",
+  "current_min": "2"
+ },
+ {
+  "product_id": "7882761535539",
+  "sell_sku": "DWJS-92009",
+  "pattern": "Meadowbrook",
+  "title": "Meadowbrook Charcoal",
+  "net": 20.0,
+  "retail": 36.2,
+  "price_code": "A",
+  "current_price": "24.51",
+  "current_uom": "Priced Per Single Roll",
+  "current_min": "2"
+ },
+ {
+  "product_id": "7882761601075",
+  "sell_sku": "DWJS-92011",
+  "pattern": "Meadowbrook",
+  "title": "Meadowbrook Cotton",
+  "net": 20.0,
+  "retail": 36.2,
+  "price_code": "A",
+  "current_price": "24.51",
+  "current_uom": "Priced Per Single Roll",
+  "current_min": "2"
+ },
+ {
+  "product_id": "7882761666611",
+  "sell_sku": "DWJS-92013",
+  "pattern": "Meadowbrook",
+  "title": "Meadowbrook Gravel",
+  "net": 20.0,
+  "retail": 36.2,
+  "price_code": "A",
+  "current_price": "24.51",
+  "current_uom": "Priced Per Single Roll",
+  "current_min": "2"
+ },
+ {
+  "product_id": "7882761732147",
+  "sell_sku": "DWJS-92015",
+  "pattern": "Meadowbrook",
+  "title": "Meadowbrook Loft",
+  "net": 20.0,
+  "retail": 36.2,
+  "price_code": "A",
+  "current_price": "24.51",
+  "current_uom": "Priced Per Single Roll",
+  "current_min": "2"
+ },
+ {
+  "product_id": "7882761830451",
+  "sell_sku": "DWJS-92018",
+  "pattern": "Meadowbrook",
+  "title": "Meadowbrook Nook",
+  "net": 20.0,
+  "retail": 36.2,
+  "price_code": "A",
+  "current_price": "24.51",
+  "current_uom": "Priced Per Single Roll",
+  "current_min": "2"
+ },
+ {
+  "product_id": "7882761863219",
+  "sell_sku": "DWJS-92019",
+  "pattern": "Meadowbrook",
+  "title": "Meadowbrook Reservoir",
+  "net": 20.0,
+  "retail": 36.2,
+  "price_code": "A",
+  "current_price": "24.51",
+  "current_uom": "Priced Per Single Roll",
+  "current_min": "2"
+ },
+ {
+  "product_id": "7882761961523",
+  "sell_sku": "DWJS-92022",
+  "pattern": "Meadowbrook",
+  "title": "Meadowbrook Thread",
+  "net": 20.0,
+  "retail": 36.2,
+  "price_code": "A",
+  "current_price": "24.51",
+  "current_uom": "Priced Per Single Roll",
+  "current_min": "2"
+ },
+ {
+  "product_id": "7882762944563",
+  "sell_sku": "DWJS-92051",
+  "pattern": "Side By Side",
+  "title": "Side By Side Cotton",
+  "net": 20.0,
+  "retail": 36.2,
+  "price_code": "A",
+  "current_price": "24.51",
+  "current_uom": "Priced Per Single Roll",
+  "current_min": "2"
+ },
+ {
+  "product_id": "7882762977331",
+  "sell_sku": "DWJS-92052",
+  "pattern": "Side By Side",
+  "title": "Side By Side Loft",
+  "net": 20.0,
+  "retail": 36.2,
+  "price_code": "A",
+  "current_price": "24.51",
+  "current_uom": "Priced Per Single Roll",
+  "current_min": "2"
+ },
+ {
+  "product_id": "7882763010099",
+  "sell_sku": "DWJS-92053",
+  "pattern": "Side By Side",
+  "title": "Side By Side Mineral",
+  "net": 20.0,
+  "retail": 36.2,
+  "price_code": "A",
+  "current_price": "24.51",
+  "current_uom": "Priced Per Single Roll",
+  "current_min": "2"
+ },
+ {
+  "product_id": "7882763042867",
+  "sell_sku": "DWJS-92054",
+  "pattern": "Side By Side",
+  "title": "Side By Side Nook",
+  "net": 20.0,
+  "retail": 36.2,
+  "price_code": "A",
+  "current_price": "24.51",
+  "current_uom": "Priced Per Single Roll",
+  "current_min": "2"
+ },
+ {
+  "product_id": "7882763075635",
+  "sell_sku": "DWJS-92055",
+  "pattern": "Side By Side",
+  "title": "Side By Side Whitewash",
+  "net": 20.0,
+  "retail": 36.2,
+  "price_code": "A",
+  "current_price": "24.51",
+  "current_uom": "Priced Per Single Roll",
+  "current_min": "2"
+ },
+ {
+  "product_id": "7882763599923",
+  "sell_sku": "DWJS-92070",
+  "pattern": "Stroll",
+  "title": "Stroll Charcoal",
+  "net": 20.0,
+  "retail": 36.2,
+  "price_code": "A",
+  "current_price": "24.51",
+  "current_uom": "Priced Per Single Roll",
+  "current_min": "2"
+ },
+ {
+  "product_id": "7882763632691",
+  "sell_sku": "DWJS-92071",
+  "pattern": "Stroll",
+  "title": "Stroll Greenhouse",
+  "net": 20.0,
+  "retail": 36.2,
+  "price_code": "A",
+  "current_price": "24.51",
+  "current_uom": "Priced Per Single Roll",
+  "current_min": "2"
+ },
+ {
+  "product_id": "7882763665459",
+  "sell_sku": "DWJS-92072",
+  "pattern": "Stroll",
+  "title": "Stroll Midnight",
+  "net": 20.0,
+  "retail": 36.2,
+  "price_code": "A",
+  "current_price": "24.51",
+  "current_uom": "Priced Per Single Roll",
+  "current_min": "2"
+ },
+ {
+  "product_id": "7882763698227",
+  "sell_sku": "DWJS-92073",
+  "pattern": "Stroll",
+  "title": "Stroll Nook",
+  "net": 20.0,
+  "retail": 36.2,
+  "price_code": "A",
+  "current_price": "24.51",
+  "current_uom": "Priced Per Single Roll",
+  "current_min": "2"
+ },
+ {
+  "product_id": "7882763730995",
+  "sell_sku": "DWJS-92074",
+  "pattern": "Stroll",
+  "title": "Stroll Parchment",
+  "net": 20.0,
+  "retail": 36.2,
+  "price_code": "A",
+  "current_price": "24.51",
+  "current_uom": "Priced Per Single Roll",
+  "current_min": "2"
+ },
+ {
+  "product_id": "7882763763763",
+  "sell_sku": "DWJS-92075",
+  "pattern": "Stroll",
+  "title": "Stroll Whitewash",
+  "net": 20.0,
+  "retail": 36.2,
+  "price_code": "A",
+  "current_price": "24.51",
+  "current_uom": "Priced Per Single Roll",
+  "current_min": "2"
+ },
+ {
+  "product_id": "7882765303859",
+  "sell_sku": "DWJS-92122",
+  "pattern": "Weft And Weave",
+  "title": "Weft And Weave Charcoal",
+  "net": 20.0,
+  "retail": 36.2,
+  "price_code": "A",
+  "current_price": "24.51",
+  "current_uom": "Priced Per Single Roll",
+  "current_min": "2"
+ },
+ {
+  "product_id": "7882765336627",
+  "sell_sku": "DWJS-92123",
+  "pattern": "Weft And Weave",
+  "title": "Weft And Weave Eden",
+  "net": 20.0,
+  "retail": 36.2,
+  "price_code": "A",
+  "current_price": "24.51",
+  "current_uom": "Priced Per Single Roll",
+  "current_min": "2"
+ },
+ {
+  "product_id": "7882765369395",
+  "sell_sku": "DWJS-92124",
+  "pattern": "Weft And Weave",
+  "title": "Weft And Weave Gatherings",
+  "net": 20.0,
+  "retail": 36.2,
+  "price_code": "A",
+  "current_price": "24.51",
+  "current_uom": "Priced Per Single Roll",
+  "current_min": "2"
+ },
+ {
+  "product_id": "7882765402163",
+  "sell_sku": "DWJS-92125",
+  "pattern": "Weft And Weave",
+  "title": "Weft And Weave Indigo",
+  "net": 20.0,
+  "retail": 36.2,
+  "price_code": "A",
+  "current_price": "24.51",
+  "current_uom": "Priced Per Single Roll",
+  "current_min": "2"
+ },
+ {
+  "product_id": "7882765434931",
+  "sell_sku": "DWJS-92126",
+  "pattern": "Weft And Weave",
+  "title": "Weft And Weave Linen",
+  "net": 20.0,
+  "retail": 36.2,
+  "price_code": "A",
+  "current_price": "24.51",
+  "current_uom": "Priced Per Single Roll",
+  "current_min": "2"
+ },
+ {
+  "product_id": "7882754195507",
+  "sell_sku": "DWJS-91827",
+  "pattern": "Vegan Suede Dark",
+  "title": "Vegan Suede Dark Slate",
+  "net": 45.0,
+  "retail": 81.45,
+  "price_code": "D",
+  "current_price": "39.22",
+  "current_uom": "Priced Per Single Roll",
+  "current_min": "2"
+ },
+ {
+  "product_id": "7882754228275",
+  "sell_sku": "DWJS-91828",
+  "pattern": "Vegan Suede",
+  "title": "Vegan Suede Portabella",
+  "net": 45.0,
+  "retail": 81.45,
+  "price_code": "D",
+  "current_price": "39.22",
+  "current_uom": "Priced Per Single Roll",
+  "current_min": "2"
+ },
+ {
+  "product_id": "7882754261043",
+  "sell_sku": "DWJS-91829",
+  "pattern": "Vegan Suede",
+  "title": "Vegan Suede Royal",
+  "net": 45.0,
+  "retail": 81.45,
+  "price_code": "D",
+  "current_price": "39.22",
+  "current_uom": "Priced Per Single Roll",
+  "current_min": "2"
+ },
+ {
+  "product_id": "7882754293811",
+  "sell_sku": "DWJS-91830",
+  "pattern": "Vegan Suede",
+  "title": "Vegan Suede Taupe",
+  "net": 45.0,
+  "retail": 81.45,
+  "price_code": "D",
+  "current_price": "39.22",
+  "current_uom": "Priced Per Single Roll",
+  "current_min": "2"
+ }
+]
\ No newline at end of file
diff --git a/york73-rollback.mjs b/york73-rollback.mjs
new file mode 100644
index 0000000..ab0f9bf
--- /dev/null
+++ b/york73-rollback.mjs
@@ -0,0 +1,19 @@
+#!/usr/bin/env node
+// One-click revert of york73.mjs --apply. Reads data/restore-map.jsonl, restores old price + uom + position.
+import { readFileSync } from 'node:fs';
+const TOKEN = readFileSync(process.env.HOME+'/Projects/secrets-manager/.env','utf8')
+  .split('\n').find(l=>l.startsWith('SHOPIFY_ADMIN_TOKEN=')).split('=')[1].trim();
+const SHOP='https://designer-laboratory-sandbox.myshopify.com/admin/api/2024-10/graphql.json';
+const DIR=new URL('.',import.meta.url).pathname;
+const gql=(q,v)=>fetch(SHOP,{method:'POST',headers:{'X-Shopify-Access-Token':TOKEN,'Content-Type':'application/json'},body:JSON.stringify({query:q,variables:v})}).then(r=>r.json());
+const rows=readFileSync(DIR+'data/restore-map.jsonl','utf8').trim().split('\n').filter(Boolean).map(l=>JSON.parse(l));
+let ok=0;
+for(const r of rows){
+  const pid=`gid://shopify/Product/${r.pid}`;
+  await gql(`mutation($m:[MetafieldsSetInput!]!){metafieldsSet(metafields:$m){userErrors{message}}}`,
+    {m:[{ownerId:pid,namespace:'global',key:'unit_of_measure',type:'single_line_text_field',value:r.old.uom||''}]});
+  await gql(`mutation($pid:ID!,$v:[ProductVariantsBulkInput!]!){productVariantsBulkUpdate(productId:$pid,variants:$v){userErrors{message}}}`,
+    {pid,v:[{id:r.sellVid,price:r.old.price,optionValues:[{optionName:'Size',name:r.old.title}]}]});
+  console.log('reverted',r.pid,'->',r.old.price,r.old.title); ok++;
+}
+console.log('ROLLBACK done —',ok,'products');
diff --git a/york73.mjs b/york73.mjs
new file mode 100644
index 0000000..5dcab5d
--- /dev/null
+++ b/york73.mjs
@@ -0,0 +1,72 @@
+#!/usr/bin/env node
+// York contract yard-good fix — 73 verified products. Generalizes the YGL7005 template.
+// DRY-RUN (default): resolves variants, prints before->after, writes NOTHING.
+// --apply: metafields (Sold Per Yard, min5/step1, MSRP, wholesale) + variant price=retail + option "Sold Per Yard" + sellable@pos1.
+// Reversible: writes data/restore-map.jsonl (old price/uom/min/position per product) BEFORE each apply.
+// Resumable: skips products already at target (idempotent). --limit N --offset N to batch.
+import { readFileSync, appendFileSync, existsSync } from 'node:fs';
+const APPLY = process.argv.includes('--apply');
+const arg = (f,d)=>{const i=process.argv.indexOf(f); return i>=0?process.argv[i+1]:d;};
+const LIMIT = parseInt(arg('--limit','999')); const OFFSET = parseInt(arg('--offset','0'));
+const TOKEN = readFileSync(process.env.HOME+'/Projects/secrets-manager/.env','utf8')
+  .split('\n').find(l=>l.startsWith('SHOPIFY_ADMIN_TOKEN=')).split('=')[1].trim();
+const SHOP='https://designer-laboratory-sandbox.myshopify.com/admin/api/2024-10/graphql.json';
+const T='single_line_text_field', ND='number_decimal';
+const MSRP={45:90.0,52.5:105.0,85.0:170.0,20:50.0};   // per-pattern MSRP by net (portal)
+const DIR=new URL('.',import.meta.url).pathname;
+const targets = JSON.parse(readFileSync(DIR+'data/york73-target.json')).slice(OFFSET, OFFSET+LIMIT);
+const REST = DIR+'data/restore-map.jsonl';
+const sleep=ms=>new Promise(r=>setTimeout(r,ms));
+async function gql(q,v){for(let a=0;a<4;a++){try{const r=await fetch(SHOP,{method:'POST',headers:{'X-Shopify-Access-Token':TOKEN,'Content-Type':'application/json'},body:JSON.stringify({query:q,variables:v})});const j=await r.json();if(j.errors&&/throttl/i.test(JSON.stringify(j.errors))){await sleep(2000);continue;}return j;}catch(e){await sleep(1500);}}throw new Error('gql failed');}
+
+const Q=`query($id:ID!){ product(id:$id){ id title status
+  uomMf:metafield(namespace:"global",key:"unit_of_measure"){value}
+  variants(first:15){edges{node{id title price position sku}}} } }`;
+
+let ok=0,skip=0,fail=0,changes=[];
+for(const t of targets){
+  const pid=`gid://shopify/Product/${t.product_id}`;
+  const r=await gql(Q,{id:pid});
+  const p=r.data && r.data.product;
+  if(!p){console.log('  MISS',t.product_id,t.sell_sku,'(product not found)');fail++;continue;}
+  const vs=p.variants.edges.map(e=>e.node);
+  const sample=vs.find(v=>/sample/i.test(v.title)||v.price==='4.25'||/-sample$/i.test(v.sku||''));
+  const sell=vs.find(v=>v!==sample) || vs[0];
+  const curUom=p.uomMf?.value||'';
+  const already = curUom==='Sold Per Yard' && sell.price===String(t.retail) && sell.position===1;
+  const line={sku:t.sell_sku,pattern:t.pattern,pid:t.product_id,
+    price:{from:sell.price,to:String(t.retail)},uom:{from:curUom||t.current_uom,to:'Sold Per Yard'},
+    sellPos:sell.position,samplePos:sample?.position, retail:t.retail,net:t.net,msrp:MSRP[t.net]};
+  changes.push(line);
+  if(already){console.log('  = already',t.sell_sku,t.pattern,`$${sell.price}`);skip++;continue;}
+  if(!APPLY){console.log(`  DRY ${t.sell_sku} ${t.pattern.padEnd(16)} $${sell.price}->$${t.retail} | ${curUom||'?'}->Sold Per Yard | sellPos ${sell.position}`);ok++;continue;}
+  // ---- APPLY (customer-facing) ----
+  appendFileSync(REST, JSON.stringify({ts:new Date().toISOString(),pid:t.product_id,sellVid:sell.id,sampleVid:sample?.id,
+    old:{price:sell.price,uom:curUom,sellPos:sell.position,samplePos:sample?.position,title:sell.title}})+'\n');
+  const mfs=[
+   {ownerId:pid,namespace:'global',key:'unit_of_measure',type:T,value:'Sold Per Yard'},
+   {ownerId:pid,namespace:'global',key:'v_prods_quantity_order_min',type:T,value:'5'},
+   {ownerId:pid,namespace:'global',key:'v_prods_quantity_order_units',type:T,value:'1'},
+   {ownerId:pid,namespace:'custom',key:'us_msrp',type:ND,value:String(MSRP[t.net].toFixed(2))},
+   {ownerId:pid,namespace:'custom',key:'wholesale_price',type:ND,value:String(t.net.toFixed(2))},
+   {ownerId:sell.id,namespace:'custom',key:'v_prod_quantity_order_min',type:T,value:'5'},
+   {ownerId:sell.id,namespace:'custom',key:'v_prods_quantity_order_units',type:T,value:'1'},
+  ];
+  if(sample) mfs.push({ownerId:sample.id,namespace:'custom',key:'v_prod_quantity_order_min',type:T,value:'1'});
+  let m=await gql(`mutation($m:[MetafieldsSetInput!]!){metafieldsSet(metafields:$m){userErrors{field message}}}`,{m:mfs});
+  const me=m.data.metafieldsSet.userErrors; if(me.length){console.log('  MF-ERR',t.sell_sku,JSON.stringify(me));fail++;continue;}
+  let vu=await gql(`mutation($pid:ID!,$v:[ProductVariantsBulkInput!]!){productVariantsBulkUpdate(productId:$pid,variants:$v){userErrors{field message}}}`,
+    {pid,v:[{id:sell.id,price:String(t.retail),optionValues:[{optionName:'Size',name:'Sold Per Yard'}]}]});
+  const ve=vu.data.productVariantsBulkUpdate.userErrors; if(ve.length){console.log('  VAR-ERR',t.sell_sku,JSON.stringify(ve));fail++;continue;}
+  if(sample && sell.position!==1){
+    await gql(`mutation($pid:ID!,$m:[ProductVariantPositionInput!]!){productVariantsBulkReorder(productId:$pid,positions:$m){userErrors{field message}}}`,
+      {pid,m:[{id:sell.id,position:1},{id:sample.id,position:2}]});
+  }
+  console.log(`  OK ${t.sell_sku} ${t.pattern} $${sell.price}->$${t.retail} Sold Per Yard`);ok++;
+  await sleep(400);
+}
+console.log(`\n${APPLY?'APPLIED':'DRY-RUN'} — ok=${ok} skip=${skip} fail=${fail} of ${targets.length}`);
+if(!APPLY){
+  const totNow=changes.reduce((a,c)=>a+parseFloat(c.price.from),0), totNew=changes.reduce((a,c)=>a+c.retail,0);
+  console.log(`sum current $${totNow.toFixed(2)} -> sum retail $${totNew.toFixed(2)} (${(totNew/totNow).toFixed(2)}x avg lift)`);
+}

(oldest)  ·  back to York Yardgood Exec  ·  Short launchers apply.sh/rollback.sh (avoid paste wrap-break 4b0d976 →