← 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
A shopify/scripts/fix-dwtt-annafrench-withs-min-key.py
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 →