← back to Dw Yolo Loop
scripts/cole-son-apply-map.js
37 lines
#!/usr/bin/env node
/* Apply MAP pricing to Cole & Son from the audit (/tmp/cs_audit.json).
- fixable: $4.25 sample-only → set yard variant to MAP
- offMap: real price ≠ MAP → set yard variant to MAP (Kravet-family prices AT MAP)
Samples stay $4.25. Yard variant only. DRY RUN by default; --apply writes live. */
const fs = require('fs');
const STORE = 'designer-laboratory-sandbox.myshopify.com';
const TOKEN = process.env.T;
const APPLY = process.argv.includes('--apply');
const sleep = ms => new Promise(r => setTimeout(r, ms));
const a = JSON.parse(fs.readFileSync('/tmp/cs_audit.json', 'utf8'));
const todo = [...a.fixable, ...a.offMap].filter(x => x.map > 0 && x.vid);
async function api(p, opts = {}, tries = 5) {
for (let i = 0; i < tries; i++) {
const r = await fetch(`https://${STORE}/admin/api/2024-10${p}`, { ...opts, headers: { 'X-Shopify-Access-Token': TOKEN, 'Content-Type': 'application/json', ...(opts.headers || {}) } });
if (r.status === 429 || r.status >= 500) { await sleep(1500 * (i + 1)); continue; }
await sleep(100); return r;
}
throw new Error('api fail ' + p);
}
(async () => {
console.log(`Cole & Son MAP apply — ${todo.length} variants (${a.fixable.length} $4.25→MAP + ${a.offMap.length} off-MAP→MAP) | mode: ${APPLY ? 'APPLY' : 'DRY RUN'}\n`);
todo.slice(0, 8).forEach(x => console.log(` ${x.code} $${x.cur} → $${x.map} [${x.status}] ${x.title.slice(0,40)}`));
if (!APPLY) { console.log(`\nDRY RUN — re-run with --apply.`); return; }
let ok = 0, fail = 0;
for (const x of todo) {
try {
const r = await api(`/variants/${x.vid}.json`, { method: 'PUT', body: JSON.stringify({ variant: { id: x.vid, price: String(x.map) } }) });
if (r.ok) { ok++; if (ok % 50 === 0) console.log(` …${ok}/${todo.length}`); }
else { fail++; console.log(` FAIL ${x.code} ${r.status}`); }
} catch (e) { fail++; console.log(` ERR ${x.code} ${e.message}`); }
}
console.log(`\nDONE — ${ok} repriced, ${fail} failed.`);
})().catch(e => { console.error(e); process.exit(1); });