[object Object]

← back to Designer Wallcoverings

Fix DWTT/AF qty stuck-at-1: set theme with-s global.v_prods_quantity_order_min=2 (10 products had min on ignored no-s key)

e04ff3857f34a21be36866d2bf6a872d74419963 · 2026-06-30 19:10:55 -0700 · Steve

Files touched

Diff

commit e04ff3857f34a21be36866d2bf6a872d74419963
Author: Steve <steve@designerwallcoverings.com>
Date:   Tue Jun 30 19:10:55 2026 -0700

    Fix DWTT/AF qty stuck-at-1: set theme with-s global.v_prods_quantity_order_min=2 (10 products had min on ignored no-s key)
---
 .../scripts/fix-dwtt-annafrench-withs-min-key.py   | 45 ++++++++++++++++++++++
 1 file changed, 45 insertions(+)

diff --git a/shopify/scripts/fix-dwtt-annafrench-withs-min-key.py b/shopify/scripts/fix-dwtt-annafrench-withs-min-key.py
new file mode 100644
index 00000000..caa26e21
--- /dev/null
+++ b/shopify/scripts/fix-dwtt-annafrench-withs-min-key.py
@@ -0,0 +1,45 @@
+import json,urllib.request,os,sys,time
+TOK=os.environ['SHOPIFY_ADMIN_TOKEN']  # env-only; no hardcoded secret
+STORE='designer-laboratory-sandbox.myshopify.com'
+URL=f'https://{STORE}/admin/api/2024-10/graphql.json'
+APPLY='--apply' in sys.argv
+def gql(q,v=None):
+    body=json.dumps({'query':q,'variables':v or {}}).encode()
+    r=urllib.request.Request(URL,body,{'X-Shopify-Access-Token':TOK,'Content-Type':'application/json'})
+    for _ in range(4):
+        try: return json.load(urllib.request.urlopen(r,timeout=40))
+        except Exception as e: time.sleep(2)
+    raise RuntimeError('gql fail')
+Q='''query($q:String!,$c:String){products(first:100,query:$q,after:$c){pageInfo{hasNextPage endCursor}
+ edges{node{id title
+  minS:metafield(namespace:"global",key:"v_prods_quantity_order_min"){value}
+  unitsS:metafield(namespace:"global",key:"v_prods_quantity_order_units"){value}
+  variants(first:10){edges{node{title}}}}}}}'''
+# scope: active Thibaut + Anna French, roll variants
+scope='(vendor:Thibaut OR vendor:\"Anna French\") status:active'
+broken=[]; total=0; roll=0; c=None
+while True:
+    d=gql(Q,{'q':scope,'c':c})
+    pg=d['data']['products']
+    for e in pg['edges']:
+        n=e['node']; total+=1
+        hasroll=any('roll' in (v['node']['title'] or '').lower() for v in n['variants']['edges'])
+        if not hasroll: continue
+        roll+=1
+        minv=(n['minS'] or {}).get('value') if n['minS'] else None
+        if minv!='2': broken.append((n['id'],n['title'],minv))
+    if not pg['pageInfo']['hasNextPage']: break
+    c=pg['pageInfo']['endCursor']
+print(f'scanned={total} roll_products={roll} BROKEN(with-s min != 2)={len(broken)}')
+for b in broken[:8]: print('  ',b[1][:45],'min=',b[2])
+if APPLY and broken:
+    print(f'--- fixing {len(broken)} products ---')
+    M='mutation($mf:[MetafieldsSetInput!]!){metafieldsSet(metafields:$mf){userErrors{message}}}'
+    fixed=0
+    for i in range(0,len(broken),25):
+        batch=broken[i:i+25]
+        mfs=[{'ownerId':b[0],'namespace':'global','key':'v_prods_quantity_order_min','type':'single_line_text_field','value':'2'} for b in batch]
+        r=gql(M,{'mf':mfs}); errs=r['data']['metafieldsSet']['userErrors']
+        if errs: print('  errors:',errs[:2])
+        fixed+=len(batch); print(f'  fixed {fixed}/{len(broken)}',end='\r')
+    print(f'\nDONE fixed {fixed}')

← a73611a1 auto-save: 2026-06-30T18:42:37 (5 files) — pending-approval/  ·  back to Designer Wallcoverings  ·  auto-save: 2026-06-30T19:42:55 (5 files) — pending-approval/ 87ce255a →