← back to York Reprice 2026 08
TK-10058: fix 2 live settlement-risk images (Malin/Denim, Sheehan/Pearl) — wrong palm/leaf images swapped for correct grasscloth, verified live
5a9d2adf394e2b55b1897265c16dcc7e357b2300 · 2026-07-30 19:49:10 -0700 · Steve Abrams
Files touched
Diff
commit 5a9d2adf394e2b55b1897265c16dcc7e357b2300
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Thu Jul 30 19:49:10 2026 -0700
TK-10058: fix 2 live settlement-risk images (Malin/Denim, Sheehan/Pearl) — wrong palm/leaf images swapped for correct grasscloth, verified live
---
fix-2-settlement.mjs | 39 +++++++++++++++++++++++++++++++++++++++
1 file changed, 39 insertions(+)
diff --git a/fix-2-settlement.mjs b/fix-2-settlement.mjs
new file mode 100644
index 0000000..1ac2e33
--- /dev/null
+++ b/fix-2-settlement.mjs
@@ -0,0 +1,39 @@
+#!/usr/bin/env node
+// fix-2-settlement.mjs — TK-10058: swap the WRONG live image for the recovered CORRECT one on the 2
+// eyeball-verified settlement-risk products (Malin/Denim 4172-27527, Sheehan/Pearl 4141-27163).
+// Steve-approved 2026-07-30. Safe sequence: add correct media -> wait READY -> reorder first -> delete wrong.
+import fs from 'node:fs';
+const T=(fs.readFileSync(process.env.HOME+'/Projects/secrets-manager/.env','utf8').match(/^SHOPIFY_ADMIN_TOKEN=(.+)$/m)||[])[1]?.trim();
+const URL='https://designer-laboratory-sandbox.myshopify.com/admin/api/2024-10/graphql.json';
+const sleep=ms=>new Promise(r=>setTimeout(r,ms));
+const g=async(q,v)=>{for(let a=0;a<8;a++){let j;try{const r=await fetch(URL,{method:'POST',headers:{'X-Shopify-Access-Token':T,'Content-Type':'application/json'},body:JSON.stringify({query:q,variables:v})});j=await r.json();}catch(e){await sleep(1500*(a+1));continue;}if(j.errors){if(JSON.stringify(j.errors).includes('THROTTLED')){await sleep(2000*(a+1));continue;}throw new Error(JSON.stringify(j.errors));}return j.data;}throw new Error('retries');};
+const rec=JSON.parse(fs.readFileSync('RECOVER-7-SETTLEMENT-TK10058.json','utf8'));
+const targets=rec.filter(r=>['4172-27527','4141-27163'].includes(r.mfr) && r.recovered);
+const Q=`query($q:String!){productVariants(first:1,query:$q){nodes{product{id title media(first:30){nodes{id mediaContentType ... on MediaImage{status image{url}}}}}}}}`;
+for(const t of targets){
+ // find product by roll SKU — Malin=DWJS? no, these are pre-existing; look up by mfr metafield
+ const d=await g(`query($q:String!){products(first:1,query:$q){nodes{id title media(first:30){nodes{id mediaContentType ... on MediaImage{status image{url}}}}}}}`,{q:`(metafield:dwc.manufacturer_sku:${t.mfr})`});
+ const p=d?.products?.nodes?.[0];
+ if(!p){console.log(`${t.mfr}: PRODUCT NOT FOUND — skip`);continue;}
+ const wrong=p.media.nodes.filter(m=>m.mediaContentType==='IMAGE');
+ console.log(`\n${t.mfr} ${(p.title||'').slice(0,32)} | current media: ${wrong.map(m=>(m.image?.url||'').split('/').pop()).join(', ')}`);
+ // 1. add correct image
+ const cm=await g(`mutation($pid:ID!,$media:[CreateMediaInput!]!){productCreateMedia(productId:$pid,media:$media){media{... on MediaImage{id status}} mediaUserErrors{field message}}}`,
+ {pid:p.id,media:[{originalSource:t.recovered,mediaContentType:'IMAGE'}]});
+ const ue=cm.productCreateMedia?.mediaUserErrors||[]; if(ue.length){console.log(' ADD ERR',JSON.stringify(ue));continue;}
+ const newId=cm.productCreateMedia.media[0].id; console.log(` added ${t.recovered.split('/').pop()} (${newId}) — waiting READY...`);
+ // 2. poll until READY
+ let ready=false; for(let i=0;i<20;i++){await sleep(2500);
+ const s=await g(`query($id:ID!){node(id:$id){... on MediaImage{status image{url}}}}`,{id:newId});
+ const st=s?.node?.status; if(st==='READY'){ready=true;break;} if(st==='FAILED'){console.log(' media FAILED');break;}
+ }
+ if(!ready){console.log(' not READY in time — leaving new image added, NOT deleting wrong (manual finish)');continue;}
+ // 3. reorder new to first (featured)
+ const ro=await g(`mutation($id:ID!,$moves:[MoveInput!]!){productReorderMedia(id:$id,moves:$moves){userErrors{field message}}}`,{id:p.id,moves:[{id:newId,newPosition:'0'}]});
+ const roe=ro.productReorderMedia?.userErrors||[]; if(roe.length)console.log(' reorder warn',JSON.stringify(roe)); else console.log(' set featured ✓');
+ // 4. delete the wrong image(s)
+ const delIds=wrong.map(m=>m.id);
+ const dm=await g(`mutation($pid:ID!,$ids:[ID!]!){productDeleteMedia(productId:$pid,mediaIds:$ids){deletedMediaIds mediaUserErrors{field message}}}`,{pid:p.id,ids:delIds});
+ const de=dm.productDeleteMedia?.mediaUserErrors||[]; if(de.length)console.log(' delete warn',JSON.stringify(de)); else console.log(` deleted ${dm.productDeleteMedia.deletedMediaIds.length} wrong image(s) ✓`);
+}
+console.log('\nDONE.');
← 8d97b4e TK-10058: recover+eyeball 7 settlement-risk — only 2 clean (
·
back to York Reprice 2026 08
·
auto-save: 2026-07-31T06:54:53 (1 files) — cadence/data/late d58a32a →