← back to Filemaker Mcp
add DWKK-120156 master (order 32513/inv 102387) + invoice probes; codify fuzzy-SKU rule
a231cf054a19cce23d2ca425b1f2af61a96df156 · 2026-07-02 07:08:11 -0700 · Steve
Files touched
A scripts/create-dwkk-120156.mjsA scripts/probe-32513-invoice.mjsA scripts/probe-invoice-102387.mjs
Diff
commit a231cf054a19cce23d2ca425b1f2af61a96df156
Author: Steve <steve@designerwallcoverings.com>
Date: Thu Jul 2 07:08:11 2026 -0700
add DWKK-120156 master (order 32513/inv 102387) + invoice probes; codify fuzzy-SKU rule
---
scripts/create-dwkk-120156.mjs | 85 ++++++++++++++++++++++++++++++++++++++++
scripts/probe-32513-invoice.mjs | 44 +++++++++++++++++++++
scripts/probe-invoice-102387.mjs | 25 ++++++++++++
3 files changed, 154 insertions(+)
diff --git a/scripts/create-dwkk-120156.mjs b/scripts/create-dwkk-120156.mjs
new file mode 100644
index 0000000..288606c
--- /dev/null
+++ b/scripts/create-dwkk-120156.mjs
@@ -0,0 +1,85 @@
+// One-off: create the missing WALLPAPER master for DWKK-120156 (Shopify order #32513,
+// FM invoice 102387). Gaston Y Daniela "Albuquerque", Verde Agua Multi — Gaston Uptown,
+// stripes upholstery weave FABRIC sold per yard. Mfr# GDT5151.003.0 (Shopify
+// global.manufacturer_sku). Kravet-family pricing: retail 308.70 IS MAP => whls = MAP/1.5
+// = 205.80 (universal 1.5x rule; SKU absent from kravet_master_price — fabric line).
+// Width: 55" per the selling variant title ("Sold Per Yard - 55In Wide"); the stale
+// global.width metafield says 36" — variant title wins, it's what the customer bought.
+// Repeat/Content left blank — not in any source; never invent specs.
+// Conventions from DWKK siblings (recordId 480584+): vid=KRA, Series=DWKK, JS Pattern
+// numeric, Mfr Pattern dotted Kravet number. CALC FIELDS omitted (combo sku,
+// comboskuwithdash, comboskuplussample, Dw Retail Price) — verified post-create.
+// Usage: node scripts/create-dwkk-120156.mjs [--commit] (default = dry-run)
+
+import { readFileSync } from 'node:fs';
+import { fileURLToPath } from 'node:url';
+import { dirname, join } from 'node:path';
+
+const __dir = dirname(fileURLToPath(import.meta.url));
+for (const line of readFileSync(join(__dir, '..', '.env'), 'utf8').split('\n')) {
+ const m = line.match(/^([A-Z_]+)=(.*)$/);
+ if (m && !process.env[m[1]]) process.env[m[1]] = m[2];
+}
+
+const { findRecords, createRecord } = await import('../src/fm-client.js');
+
+const DB = 'WALLPAPER';
+const LAYOUT = '*List Wallpapers - Shopify Detail Database';
+const commit = process.argv.includes('--commit');
+const SKU = 'DWKK120156'; // expected value of the "combo sku" calc — guard/verify only
+
+const fieldData = {
+ 'Series': 'DWKK',
+ 'vid': 'KRA',
+ 'JS Pattern': '120156',
+ 'Mfr Pattern': 'GDT5151.003.0',
+ 'mfr pattern number': 'GDT5151.003.0',
+ 'Name of Pattern': 'Albuquerque',
+ 'Mfr Name of Pattern': 'Albuquerque',
+ 'Color of Pattern': 'Verde Agua Multi',
+ 'Mfr Color of Pattern': 'Verde Agua Multi',
+ 'Collection': 'GASTON UPTOWN',
+ 'Width': '55"',
+ 'Record Type': 'Master',
+ 'Date Line Put Up:': '7/2/2026',
+ 'Net Price': 205.80,
+ 'MFR MAP PRICE': 308.70,
+};
+
+// fail-closed duplicate guard — probe dashless calc AND dashed variant (standing rule)
+for (const [field, value] of [['combo sku', SKU], ['comboskuwithdash', 'DWKK-120156']]) {
+ try {
+ const { records } = await findRecords(DB, LAYOUT, { [field]: `==${value}` }, { limit: 1 });
+ if (records.length) {
+ console.log(`SKIP: already exists via ${field}=${value} as recordId ${records[0].recordId}`);
+ process.exit(0);
+ }
+ } catch (e) {
+ if (e.fmCode !== '401') throw e; // 401 = no records match = safe to create
+ }
+}
+
+const res = await createRecord(DB, LAYOUT, fieldData, { dryRun: !commit });
+console.log(commit ? `CREATED ${SKU}:` : `DRY RUN ${SKU}:`, JSON.stringify(res, null, 1));
+
+if (commit) {
+ const { records } = await findRecords(DB, LAYOUT, { 'combo sku': `==${SKU}` }, { limit: 2 });
+ const f = records[0]?.fieldData || {};
+ console.log(`VERIFY ${SKU}:`, JSON.stringify({
+ recordId: records[0]?.recordId,
+ 'combo sku': f['combo sku'],
+ 'comboskuwithdash': f['comboskuwithdash'],
+ 'comboskuplussample': f['comboskuplussample'],
+ 'vid': f['vid'],
+ 'Mfr Pattern': f['Mfr Pattern'],
+ 'mfr pattern number': f['mfr pattern number'],
+ 'Name of Pattern': f['Name of Pattern'],
+ 'Color of Pattern': f['Color of Pattern'],
+ 'Collection': f['Collection'],
+ 'Width': f['Width'],
+ 'Net Price': f['Net Price'],
+ 'MFR MAP PRICE': f['MFR MAP PRICE'],
+ 'Dw Retail Price': f['Dw Retail Price'],
+ 'Record Type': f['Record Type'],
+ }, null, 1));
+}
diff --git a/scripts/probe-32513-invoice.mjs b/scripts/probe-32513-invoice.mjs
new file mode 100644
index 0000000..cac5964
--- /dev/null
+++ b/scripts/probe-32513-invoice.mjs
@@ -0,0 +1,44 @@
+// Probe: find the FM invoice carrying Shopify order #32513's SKU (DWKK-120156)
+// and show the line-level lookup fields (Name/Color/Mfr#/VID). Steve's indicator:
+// SKU filled but Name+Color+Mfr#+VID all blank => WALLPAPER master missing, create it.
+// Read-only. Usage: node scripts/probe-32513-invoice.mjs
+import { readFileSync } from 'node:fs';
+import { fileURLToPath } from 'node:url';
+import { dirname, join } from 'node:path';
+
+const __dir = dirname(fileURLToPath(import.meta.url));
+for (const line of readFileSync(join(__dir, '..', '.env'), 'utf8').split('\n')) {
+ const m = line.match(/^([A-Z_]+)=(.*)$/);
+ if (m && !process.env[m[1]]) process.env[m[1]] = m[2];
+}
+
+const { findRecords, fieldMetadata } = await import('../src/fm-client.js');
+
+const DB = 'invoice';
+const LAYOUT = 'Order Detail';
+
+// what line-level fields exist on this layout (find the lookup columns)
+const meta = await fieldMetadata(DB, LAYOUT);
+const names = (meta.fieldMetaData || []).map((f) => f.name);
+console.log('LINE-ISH FIELDS:', JSON.stringify(names.filter((n) =>
+ /name|color|colour|mfr|vid|detail|js|pattern|q1|unit|net|retail/i.test(n))));
+
+// the SKU can be stored with or without the dash — probe both on the JS#/detail column
+for (const sku of ['DWKK120156', 'DWKK-120156', 'DWKK-120156-Sample']) {
+ for (const field of names.filter((n) => /^(DETAIL 1|JS)/i.test(n) && !/\(/.test(n))) {
+ try {
+ const { records } = await findRecords(DB, LAYOUT, { [field]: `==${sku}` }, { limit: 3 });
+ for (const r of records) {
+ console.log(`MATCH via ${field}=${sku} recordId=${r.recordId}`);
+ const f = r.fieldData;
+ const show = {};
+ for (const k of Object.keys(f)) {
+ if (/invoice|name|color|colour|mfr|vid|detail|q1|unit|net 1|retail 1|paid|grand/i.test(k)) show[k] = f[k];
+ }
+ console.log(JSON.stringify(show, null, 1));
+ }
+ } catch (e) {
+ if (e.fmCode !== '401') console.error(`probe ${field}=${sku}: ${e.message}`);
+ }
+ }
+}
diff --git a/scripts/probe-invoice-102387.mjs b/scripts/probe-invoice-102387.mjs
new file mode 100644
index 0000000..1067bfb
--- /dev/null
+++ b/scripts/probe-invoice-102387.mjs
@@ -0,0 +1,25 @@
+// Read-only: pull invoice 102387 (Shopify #32513) via the HDR layout and show the
+// line columns + lookup fields (Name/Color/Mfr#/VID) to confirm the missing-master tell.
+import { readFileSync } from 'node:fs';
+import { fileURLToPath } from 'node:url';
+import { dirname, join } from 'node:path';
+const __dir = dirname(fileURLToPath(import.meta.url));
+for (const line of readFileSync(join(__dir, '..', '.env'), 'utf8').split('\n')) {
+ const m = line.match(/^([A-Z_]+)=(.*)$/);
+ if (m && !process.env[m[1]]) process.env[m[1]] = m[2];
+}
+const { findRecords, fieldMetadata } = await import('../src/fm-client.js');
+const HDR = 'Invoice to Client Copy';
+const meta = await fieldMetadata('invoice', HDR);
+const names = (meta.fieldMetaData || []).map((f) => f.name);
+const invField = names.find((n) => /^invoice$/i.test(n)) || names.find((n) => /invoice/i.test(n) && /#|no|num/i.test(n));
+const { records } = await findRecords('invoice', HDR, { [invField]: '==102387' }, { limit: 3 });
+if (!records.length) { console.log('NOT FOUND on HDR layout'); process.exit(1); }
+const r = records[0];
+console.log('recordId:', r.recordId);
+const f = r.fieldData;
+const show = {};
+for (const k of Object.keys(f)) {
+ if (/invoice|date|sold|ship name|name|color|colour|mfr|vid|detail|js|q1|unit|net|retail|total|paid|tax|resale/i.test(k)) show[k] = f[k];
+}
+console.log(JSON.stringify(show, null, 1));
← bcf5e67 chore: v0.1.1 (session close — Baxter records, invoice 10237
·
back to Filemaker Mcp
·
auto-save: 2026-07-02T07:11:42 (1 files) — scripts/relookup- 5a0d50e →