← 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
A scripts/bulk-create-greenland-full.mjs
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 →