← back to Designer Wallcoverings
Daisy Bennett: material-based SKU prefixes (DWGRS/PWV/RAF/SIS/LIN/CORK/ABA), family-consistent majority-vote
4511065a2bd8fb3b41e13dd2bb086b5df301b591 · 2026-07-06 11:36:23 -0700 · Steve
Files touched
A scripts/wallquest-refresh/remap-skus-daisy-bennett.cjs
Diff
commit 4511065a2bd8fb3b41e13dd2bb086b5df301b591
Author: Steve <steve@designerwallcoverings.com>
Date: Mon Jul 6 11:36:23 2026 -0700
Daisy Bennett: material-based SKU prefixes (DWGRS/PWV/RAF/SIS/LIN/CORK/ABA), family-consistent majority-vote
---
.../wallquest-refresh/remap-skus-daisy-bennett.cjs | 63 ++++++++++++++++++++++
1 file changed, 63 insertions(+)
diff --git a/scripts/wallquest-refresh/remap-skus-daisy-bennett.cjs b/scripts/wallquest-refresh/remap-skus-daisy-bennett.cjs
new file mode 100644
index 00000000..ccc7ac23
--- /dev/null
+++ b/scripts/wallquest-refresh/remap-skus-daisy-bennett.cjs
@@ -0,0 +1,63 @@
+// Re-assign Daisy Bennett dw_sku with MATERIAL-BASED prefixes (Steve's directive, 2026-07-06).
+// grasscloth→DWGRS, paperweave→DWPWV, raffia→DWRAF, sisal→DWSIS, linen→DWLIN, cork→DWCORK,
+// mica→DWMIC, abaca→DWABA. Material signal = ai_material_texture, with title/pattern keyword
+// fallback (catches abaca that AI tagged "other"); unknown "other" → DWGRS (naturals default).
+// Rewrites the enriched + normalized files in place (numeric tail = original BX number preserved).
+const fs = require('fs');
+const ENR = '/tmp/wq-daisy-bennett-enriched.json';
+const NORM = '/tmp/wq-daisy-bennett-normalized.json';
+
+const CODE = { grasscloth:'GRS', paperweave:'PWV', raffia:'RAF', sisal:'SIS', linen:'LIN', cork:'CORK', mica:'MIC', abaca:'ABA', bamboo:'BAM', netting:'NET' };
+const KW = [ // title/pattern keyword → material (fallback when ai_texture is "other"/missing)
+ [/abaca/i,'abaca'],[/\bcork\b/i,'cork'],[/mica/i,'mica'],[/raffia/i,'raffia'],
+ [/sisal/i,'sisal'],[/linen/i,'linen'],[/paperweave|paper weave/i,'paperweave'],
+ [/grass\b|grasscloth|hemp|jute/i,'grasscloth'],
+];
+function materialOf(r) {
+ const ai = (r.ai_material_texture || '').toLowerCase();
+ if (ai && ai !== 'other' && CODE[ai]) return ai;
+ const hay = `${r.pattern || ''} ${r.src_title || ''} ${r.material || ''}`;
+ for (const [re, m] of KW) if (re.test(hay)) return m;
+ return 'grasscloth'; // naturals default
+}
+// A pattern's substrate is a property of the PATTERN, not the colorway — so assign each
+// family ONE material by majority vote of its colorways (tiebreak by priority), keeping
+// every family internally consistent. Non-unanimous families are flagged for spot-check.
+const PRIORITY = ['grasscloth','paperweave','raffia','sisal','linen','cork','abaca','mica'];
+function familyMaterialMap(recs) {
+ const byFam = {};
+ for (const r of recs) { const f = (r.pattern||'').trim().toLowerCase(); (byFam[f]=byFam[f]||[]).push(materialOf(r)); }
+ const map = {}, flagged = [];
+ for (const [f, mats] of Object.entries(byFam)) {
+ const counts = {}; mats.forEach(m => counts[m] = (counts[m]||0)+1);
+ const winner = Object.entries(counts).sort((a,b) => b[1]-a[1] || PRIORITY.indexOf(a[0])-PRIORITY.indexOf(b[0]))[0][0];
+ map[f] = winner;
+ if (Object.keys(counts).length > 1) flagged.push(`${f} → ${winner} (mixed: ${Object.entries(counts).map(([m,c])=>m+'×'+c).join(', ')})`);
+ }
+ return { map, flagged };
+}
+function recode(recs, famMap) {
+ const dist = {};
+ for (const r of recs) {
+ const mat = famMap[(r.pattern||'').trim().toLowerCase()] || materialOf(r);
+ const code = CODE[mat] || 'GRS';
+ const tail = (String(r.dw_sku).match(/\d+/) || (String(r.mfr_sku).match(/\d+/)) || ['0'])[0];
+ r.dw_sku = `DW${code}-${tail}`;
+ r._material_resolved = mat;
+ dist[code] = (dist[code] || 0) + 1;
+ }
+ return dist;
+}
+
+let dist = {}, flagged = [];
+const enr = fs.existsSync(ENR) ? JSON.parse(fs.readFileSync(ENR, 'utf8')) : null;
+const fm = familyMaterialMap(enr || JSON.parse(fs.readFileSync(NORM, 'utf8')));
+flagged = fm.flagged;
+if (enr) { dist = recode(enr, fm.map); fs.writeFileSync(ENR, JSON.stringify(enr, null, 2)); }
+if (fs.existsSync(NORM)) { const n = JSON.parse(fs.readFileSync(NORM, 'utf8')); recode(n, fm.map); fs.writeFileSync(NORM, JSON.stringify(n, null, 2)); }
+
+console.log('material-based SKU distribution (family-consistent):');
+Object.entries(dist).sort((a, b) => b[1] - a[1]).forEach(([c, v]) => console.log(` DW${c}- ×${v}`));
+console.log(`total=${Object.values(dist).reduce((a, b) => a + b, 0)}`);
+if (flagged.length) { console.log(`\n⚠ ${flagged.length} families were non-unanimous (AI texture split) — spot-check:`); flagged.forEach(f => console.log(' '+f)); }
+else console.log('\nall families unanimous ✓');
← ad9acbf8 Add Daisy Bennett Vol 2 internal staging viewer (sort+densit
·
back to Designer Wallcoverings
·
Carl Robinson: material-based SKU prefixes (DWGRS/PWV/CORK/M bccb98f8 →