[object Object]

← back to Dw Photo Capture

Check Sample In → incoming queue: /api/incoming-samples finds vendor-ordered+not-sent samples in FileMaker (the arriving ones), enriched with catalog image+spec. fmFind gains portal:[] to suppress heavy portalData (fixed the FM timeout)

2d627acd44ed94a935c466888148defdacf49227 · 2026-07-07 16:45:44 -0700 · Steve Abrams

Files touched

Diff

commit 2d627acd44ed94a935c466888148defdacf49227
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Tue Jul 7 16:45:44 2026 -0700

    Check Sample In → incoming queue: /api/incoming-samples finds vendor-ordered+not-sent samples in FileMaker (the arriving ones), enriched with catalog image+spec. fmFind gains portal:[] to suppress heavy portalData (fixed the FM timeout)
---
 fm-client.js |  3 ++-
 server.js    | 30 ++++++++++++++++++++++++++++++
 2 files changed, 32 insertions(+), 1 deletion(-)

diff --git a/fm-client.js b/fm-client.js
index db347d0..3ae36fd 100644
--- a/fm-client.js
+++ b/fm-client.js
@@ -73,9 +73,10 @@ async function fm(db, path, { method = 'GET', body } = {}) {
   return json.response;
 }
 
-async function fmFind(db, layout, query, { limit = 20, offset = 1, sort } = {}) {
+async function fmFind(db, layout, query, { limit = 20, offset = 1, sort, portal } = {}) {
   const body = { query: Array.isArray(query) ? query : [query], limit: String(limit), offset: String(offset) };
   if (sort) body.sort = sort;
+  if (portal) body.portal = portal;   // e.g. [] → suppress heavy portalData (big speedup on portal-laden layouts)
   const r = await fm(db, `/layouts/${encodeURIComponent(layout)}/_find`, { method: 'POST', body });
   return { records: r.data || [], dataInfo: r.dataInfo };
 }
diff --git a/server.js b/server.js
index b652cfd..08b8e88 100644
--- a/server.js
+++ b/server.js
@@ -1326,6 +1326,36 @@ const appHandler = (req, res) => {
     return;
   }
 
+  // INCOMING SAMPLES: what Check Sample In focuses on — samples ordered from the vendor but not yet
+  // sent to the client (vendor-order date filled, WP-sample-sent empty = still in-flight / arriving).
+  // Enriched with each sample's image + spec from the unified catalog so we know what's coming in.
+  if (u.pathname === '/api/incoming-samples' && req.method === 'GET') {
+    if (!FM_ENABLED()) return send(res, 200, { ok: false, err: 'FileMaker not configured', samples: [] });
+    (async () => {
+      const query = [{ 'Date Sample Request printed for vendor': '*', 'Date WP Sample Sent': '=' }];
+      let r;
+      try { r = await FM.fmFind(FM_DB, FM_LAYOUT, query, { limit: 40, portal: [], sort: [{ fieldName: 'Date Sample Request printed for vendor', sortOrder: 'descend' }] }); }
+      catch (e) { return send(res, 200, { ok: false, err: e.message, samples: [] }); }
+      const recs = (r.records || []);
+      const base = recs.map(rec => { const f = rec.fieldData; return {
+        recordId: rec.recordId, mfr_pattern: f['Mfr Pattern'] || null, combo_sku: f['combo sku'] || null,
+        series: f['Series'] || null, vid: f['vid'] || null, client: f['company for client fileS'] || null,
+        vendor_ordered: f['Date Sample Request printed for vendor'] || null, client_ordered: f['today for client'] || null }; });
+      // enrich with image + spec from the catalog, capped concurrency (identifyUnified shells to psql)
+      const out = [];
+      for (let i = 0; i < base.length; i += 6) {
+        const chunk = await Promise.all(base.slice(i, i + 6).map(async s => {
+          const key = (s.combo_sku || s.mfr_pattern || '').toString().trim();
+          const id = key ? await identifyUnified(key).catch(() => null) : null;
+          return Object.assign(s, { image: (id && id.image) || null, pattern: (id && id.pattern) || null,
+            vendor: (id && id.vendor) || null, dw_sku: (id && id.internal_sku) || null, mfr_sku: (id && id.mfr_sku) || null }); }));
+        out.push(...chunk);
+      }
+      send(res, 200, { ok: true, count: out.length, samples: out });
+    })();
+    return;
+  }
+
   // Print-sticker "send": STAMP the sample as sent (Date WP Sample Sent = today — Steve's "field to
   // fill in") and, if a flag field is configured, ALSO flag the record so the Mac's FileMaker Pro
   // poller runs the physical Zebra print. Write is dryRun unless FM_WRITE=1 (protects the live file).

← 17b5c68 Local aug-model deploy pipeline (mac_deploy_embed): embed fu  ·  back to Dw Photo Capture  ·  Check Sample In: incoming-queue panel — shows vendor-ordered 427db51 →