← back to Hollywood Import
momentum assign-sku: 2902 unmapped colorways → DWHD-508083..510984 + 258 fresh CA-city collections (staging; drip manifest untouched)
b81b266f460ff6554514eede6d87241f29abd3cc · 2026-07-08 14:08:19 -0700 · steve@designerwallcoverings.com
Files touched
A momentum-feed/assign-sku.mjs
Diff
commit b81b266f460ff6554514eede6d87241f29abd3cc
Author: steve@designerwallcoverings.com <steve@designerwallcoverings.com>
Date: Wed Jul 8 14:08:19 2026 -0700
momentum assign-sku: 2902 unmapped colorways → DWHD-508083..510984 + 258 fresh CA-city collections (staging; drip manifest untouched)
---
momentum-feed/assign-sku.mjs | 83 ++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 83 insertions(+)
diff --git a/momentum-feed/assign-sku.mjs b/momentum-feed/assign-sku.mjs
new file mode 100644
index 0000000..01ab1fb
--- /dev/null
+++ b/momentum-feed/assign-sku.mjs
@@ -0,0 +1,83 @@
+#!/usr/bin/env node
+// Momentum → Hollywood assign-sku: give every unmapped colorway (dw_sku IS NULL) a
+// sequential DWHD- SKU, its pattern a fresh CA-coastal collection name (pl_city_name),
+// and pl_brand='Hollywood Wallcoverings'. STAGING ONLY — decoupled from the go-live drip,
+// which reads the fixed manifest the67_full.json, NOT this table. Reversible.
+// Run: NODE_PATH=.../AbramsOS/node_modules node assign-sku.mjs [--commit]
+import { createRequire } from 'module';
+const require = createRequire(import.meta.url);
+const { Pool } = require('pg');
+const pool = new Pool({ connectionString: 'postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified' });
+const COMMIT = process.argv.includes('--commit');
+
+// Real CA coastal place names (base pool). Expanded with suffixes if 258+ collision-free needed.
+const BASE = `Zuma,Point Dume,Paradise Cove,Leo Carrillo,El Matador,Trancas,Nicholas Canyon,Broad Beach,
+Crystal Cove,Corona del Mar,Little Corona,Reef Point,Pelican Point,Abalone Cove,Portuguese Bend,Royal Palms,
+Cabrillo Beach,White Point,Point Fermin,Redondo Breakwater,Hermosa Strand,El Porto,Dockweiler,Playa del Rey,
+Malaga Cove,Bluff Cove,Lunada Bay,Torrance Beach,Sunset Cliffs,Ocean Beach,La Jolla Shores,Windansea,
+Black's Beach,Torrey Pines,Del Mar,Cardiff Reef,Swami's,Moonlight Beach,Ponto,Terramar,Carlsbad State,
+San Onofre,Trestles,Church Beach,Cottons Point,Poche,Capistrano Beach,Dana Point,Salt Creek,Monarch Bay,
+Three Arch Bay,Woods Cove,Divers Cove,Shaw's Cove,Crescent Bay,Emerald Bay,Cameo Shores,Balboa Peninsula,
+Newport Point,Huntington Cliffs,Bolsa Chica,Sunset Beach,Seal Beach,Cabrillo,Refugio,El Capitan,Gaviota,
+Arroyo Burro,Butterfly Beach,Miramar,Rincon,Carpinteria,Faria,Emma Wood,Surfers Point,Mondos,Solimar,
+Oxnard Shores,Silver Strand,Point Mugu,Sycamore Cove,County Line,Deer Creek,Staircase Beach,Thornhill Broome,
+Pfeiffer Beach,Sand Dollar,Willow Creek,Kirk Creek,Limekiln,Partington Cove,McWay Falls,Andrew Molera,
+Garrapata,Bixby Bridge,Point Lobos,Carmel River,Monastery Beach,Spanish Bay,Asilomar,Lovers Point,
+Moss Landing,Zmudowski,Sunset State,Manresa,Rio Del Mar,Capitola,Pleasure Point,Steamer Lane,Cowell Beach,
+Natural Bridges,Wilder Ranch,Scott Creek,Waddell,Ano Nuevo,Pigeon Point,Pescadero,Pomponio,San Gregorio,
+Pacifica Pier,Rockaway Beach,Mori Point,Montara,Gray Whale Cove,Devils Slide,Half Moon Bay,Miramar Beach,
+Dunes Beach,Poplar Beach,Cowell Ranch,Martins Beach,Ocean Cove,Salt Point,Fort Ross,Timber Cove,
+Stillwater Cove,Gerstle Cove,Goat Rock,Wrights Beach,Duncans Landing,Salmon Creek,Bodega Head,Doran Beach,
+Dillon Beach,Lawsons Landing,McClures Beach,Limantour,Drakes Beach,Point Reyes,Kehoe Beach,Abbotts Lagoon,
+Stinson Beach,Bolinas,Muir Beach,Rodeo Beach,Kirby Cove,Baker Beach,China Beach,Lands End,Ocean Beach SF,
+Mavericks,Trinidad State,Moonstone Beach,Clam Beach,Agate Beach,Luffenholtz,College Cove,Houda Point`
+ .split(',').map(s => s.trim().replace(/\s+/g, ' ')).filter(Boolean);
+const SUFFIX = ['Cove','Point','Bluffs','Landing','Reef','Strand','Shores','Head','Bay','Overlook'];
+
+function buildPool(need, used) {
+ const out = [], seen = new Set([...used].map(s => s.toLowerCase()));
+ const add = n => { const k = n.toLowerCase(); if (!seen.has(k)) { seen.add(k); out.push(n); } };
+ for (const n of BASE) { add(n); if (out.length >= need) return out; }
+ for (const sfx of SUFFIX) for (const n of BASE) { add(`${n.split(' ')[0]} ${sfx}`); if (out.length >= need) return out; }
+ return out; // (BASE 170 × 10 suffixes ≫ 258; guaranteed enough)
+}
+
+async function main() {
+ const used = (await pool.query(`SELECT DISTINCT pl_city_name c FROM momentum_colorways WHERE pl_city_name IS NOT NULL`))
+ .rows.map(r => r.c).filter(Boolean);
+ const maxNum = (await pool.query(
+ `SELECT COALESCE(MAX((substring(dw_sku from 'DWHD-([0-9]+)'))::int),500000) m FROM momentum_colorways WHERE dw_sku ~ '^DWHD-[0-9]+$'`)).rows[0].m;
+ // Deterministic order: WC before Acoustic, then pattern, then colorway.
+ const { rows } = await pool.query(
+ `SELECT id, pattern_name, color_name, color_number, category FROM momentum_colorways
+ WHERE dw_sku IS NULL ORDER BY category, pattern_name, color_number NULLS LAST, id`);
+ const patterns = [...new Set(rows.map(r => r.pattern_name))];
+ const pool2 = buildPool(patterns.length, used);
+ if (pool2.length < patterns.length) throw new Error(`pool short: ${pool2.length} < ${patterns.length}`);
+ const cityOf = new Map(patterns.map((p, i) => [p, pool2[i]]));
+
+ let n = maxNum;
+ const plan = rows.map(r => ({ id: r.id, dw_sku: `DWHD-${++n}`, city: cityOf.get(r.pattern_name),
+ pattern: r.pattern_name, color: r.color_name, cat: r.category }));
+ console.log(`assign-sku: ${plan.length} colorways / ${patterns.length} patterns.`);
+ console.log(` DWHD range: DWHD-${maxNum + 1} … DWHD-${n}`);
+ console.log(` new cities minted: ${patterns.length} (0 collisions w/ ${used.length} existing)`);
+ console.log(' samples:'); plan.slice(0, 4).forEach(p => console.log(` ${p.dw_sku} ${p.cat} "${p.pattern}" / ${p.color} → ${p.city}`));
+
+ if (!COMMIT) { console.log('DRY-RUN — re-run with --commit to write.'); await pool.end(); return; }
+ const c = await pool.connect();
+ let done = 0;
+ try {
+ await c.query('BEGIN');
+ for (const p of plan) {
+ await c.query(
+ `UPDATE momentum_colorways SET dw_sku=$1, pl_city_name=$2, pl_brand='Hollywood Wallcoverings', updated_at=now()
+ WHERE id=$3 AND dw_sku IS NULL`, [p.dw_sku, p.city, p.id]);
+ done++;
+ }
+ await c.query('COMMIT');
+ console.log(`COMMITTED — assigned ${done} DWHD SKUs + ${patterns.length} CA-city collections. pl_brand set. (staging only; drip manifest untouched)`);
+ } catch (e) { await c.query('ROLLBACK'); console.error('ROLLBACK:', e.message); process.exitCode = 1; }
+ finally { c.release(); await pool.end(); }
+}
+main().catch(e => { console.error(e); process.exit(1); });
← c1db41b refresh: add Meilisearch 20k-cap truncation alarm (contraria
·
back to Hollywood Import
·
momentum price-backfill: recover 788 unpriced (incl 509 Acou f603f77 →