[object Object]

← back to Filemaker Mcp

auto-save: 2026-07-12T19:19:48 (1 files) — scripts/bulk-create-greenland-full.mjs

9f680a3ba6d58d3c6bcd4f106edc71a7db91a11b · 2026-07-12 19:19:51 -0700 · Steve Abrams

Files touched

Diff

commit 9f680a3ba6d58d3c6bcd4f106edc71a7db91a11b
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Sun Jul 12 19:19:51 2026 -0700

    auto-save: 2026-07-12T19:19:48 (1 files) — scripts/bulk-create-greenland-full.mjs
---
 scripts/bulk-create-greenland-full.mjs | 57 ++++++++++++++++++++++++++++++++++
 1 file changed, 57 insertions(+)

diff --git a/scripts/bulk-create-greenland-full.mjs b/scripts/bulk-create-greenland-full.mjs
new file mode 100644
index 0000000..75b441b
--- /dev/null
+++ b/scripts/bulk-create-greenland-full.mjs
@@ -0,0 +1,57 @@
+// Create FileMaker WALLPAPER masters for the 908 full-catalog Greenland→Phillipe Romano SKUs.
+// Series = DW prefix (SILK/PWV/WOOD/SPEC/...), JS Pattern = DW number, Mfr Pattern = real
+// Greenland code, Name = "<City> <MaterialWord> Wallcovering", Color, Width, vid=GREEN.
+// Retail Price left BLANK (quote-only — pricing is a separate gated step). combo-sku-with-dash
+// = <prefix>-<number> = the Shopify DW SKU. Idempotent: skips existing (Series + JS Pattern).
+//   node bulk-create-greenland-full.mjs                 # DRY-RUN
+//   node bulk-create-greenland-full.mjs --apply [--limit=N] [--offset=N]
+import { execFileSync } from 'node:child_process';
+import * as fm from '../src/fm-client.js';
+
+const APPLY = process.argv.includes('--apply');
+const LIMIT = parseInt((process.argv.find(a => a.startsWith('--limit=')) || '').split('=')[1] || '0', 10);
+const OFFSET = parseInt((process.argv.find(a => a.startsWith('--offset=')) || '').split('=')[1] || '0', 10);
+const ENTRY = 'Add wallcovering', FULL = '*List Wallpapers - Full View';
+const PSQL = process.env.PSQL_BIN || '/opt/homebrew/opt/postgresql@14/bin/psql';
+const DB = 'postgresql:///dw_unified?host=/tmp&user=stevestudio2';
+const sleep = ms => new Promise(r => setTimeout(r, ms));
+
+const MATWORD = { Silk:'Silk', Grass:'Grasscloth', Wood:'Wood Veneer', Suede:'Suede', Linen:'Linen',
+  Raffia:'Raffia', 'Paper Weave':'Paper Weave', Abaca:'Abaca', Hemp:'Hemp', Sisal:'Sisal', Jute:'Jute',
+  Velvet:'Velvet', Wool:'Wool', Arrowroot:'Arrowroot', 'Cotton Yarn':'Cotton', 'Water hyacinth':'Water Hyacinth',
+  'Metal Leaf':'Metal Leaf' };
+const matWord = m => (MATWORD[m] ?? '');
+const widthOf = w => { const s = String(w||'');
+  const inch = s.match(/([\d.]+)\s*(?:''|")/); if (inch) return `${Math.round(parseFloat(inch[1]))}"`;
+  const cm = s.match(/([\d.]+)\s*cm/); if (cm) return `${Math.round(parseFloat(cm[1])/2.54)}"`;
+  const n = s.match(/([\d.]+)/); return n ? `${Math.round(parseFloat(n[1]))}"` : ''; };
+
+const rows = JSON.parse(execFileSync(PSQL, [DB, '-tAc',
+  `select coalesce(json_agg(json_build_object('sku',dw_sku,'prefix',prefix,'num',split_part(dw_sku,'-',2),'mfr',mfr_model,'city',city,'mat',material,'color',clean_color,'wi',width) order by dw_sku)::text,'[]')
+   from greenland_full_catalog`], { encoding:'utf8', maxBuffer:128e6 }).trim());
+
+async function exists(prefix, num) {
+  const r = await fm.findRecords('WALLPAPER', FULL, { 'Series':'=='+prefix, 'JS Pattern':'=='+num }, { limit:1 }).catch(()=>({records:[]}));
+  return (r.records?.length||0) > 0;
+}
+
+async function main() {
+  let todo = rows.slice(OFFSET, LIMIT ? OFFSET+LIMIT : undefined);
+  console.log(`greenland_full_catalog: ${rows.length} rows · this run: ${todo.length} (offset ${OFFSET}) · ${APPLY?'APPLY':'DRY-RUN'}`);
+  let ok=0, skip=0, fail=0;
+  for (const r of todo) {
+    const mw = matWord(r.mat);
+    const name = `${r.city} ${mw ? mw+' ' : ''}Wallcovering`.replace(/\s+/g,' ').trim();
+    const fd = { Series:r.prefix, 'JS Pattern':r.num, 'Mfr Pattern':r.mfr,
+      'Name of Pattern':name, 'Color of Pattern':r.color, Width:widthOf(r.wi), vid:'GREEN' };
+    if (!APPLY) { if (ok<6) console.log(`  [${r.sku}] Series=${r.prefix} JS=${r.num} Mfr=${r.mfr} "${name}" (${r.color}) w=${fd.Width}`); ok++; continue; }
+    try {
+      if (await exists(r.prefix, r.num)) { skip++; continue; }
+      await fm.createRecord('WALLPAPER', ENTRY, fd, { dryRun:false });
+      ok++; if (ok%25===0) console.log(`  ...created ${ok} (skip ${skip}, fail ${fail})`);
+      await sleep(120);
+    } catch (e) { fail++; console.error(`  FAIL ${r.sku}: ${e.fmCode||e.message}`); await sleep(400); }
+  }
+  console.log(`\nDONE. ${APPLY?'created':'planned'}=${ok} skipped=${skip} fail=${fail}`);
+}
+main().catch(e=>{console.error(e);process.exit(1);});

← c542aa6 auto-save: 2026-07-12T08:47:12 (2 files) — scripts/bulk-seri  ·  back to Filemaker Mcp  ·  Add Greenland cork disco script: stamps Date Discontinued on 22d9eff →