[object Object]

← 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

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 →