← back to Japan Enrich

db/stage-sangetsu-all.js

63 lines

#!/usr/bin/env node
/**
 * Bulk-stage the FULL Sangetsu line into dw_unified.sangetsu_catalog (PostgreSQL-first,
 * on_shopify=false — no Shopify publish). Reads staging/sangetsu-staging.jsonl, explodes
 * each pattern to its colorway SKUs (same as the viewer), and upserts with us_distributor
 * derived from the source host (Goodrich). Chunked multi-row upsert inside one transaction.
 *
 * Local mirror is safe + reversible (TRUNCATE sangetsu_catalog). Canonical = gated.
 *   DATABASE_URL=postgresql:///dw_unified node db/stage-sangetsu-all.js
 */
const fs = require('fs'), path = require('path');
const { Client } = require('pg');

const F = path.join(__dirname, '..', 'staging', 'sangetsu-staging.jsonl');
const DSN = process.env.DATABASE_URL || 'postgresql:///dw_unified';
const CHUNK = 500;

const distOf = (url) => /sangetsu-goodrich\.co\.th/.test(url || '') ? 'Goodrich (Thailand)'
  : /sangetsu-goodrich\.vn/.test(url || '') ? 'Goodrich (Vietnam)'
  : /goodrichglobal\.com/.test(url || '') ? 'Goodrich (Singapore)' : 'Goodrich';

(async () => {
  const patterns = fs.readFileSync(F, 'utf8').trim().split('\n').filter(Boolean).map((l) => JSON.parse(l));
  // flatten pattern → colorway SKU rows (mirror the viewer's Sangetsu builder).
  // A colorway SKU can appear under >1 pattern in the feed → dedupe globally (first wins)
  // so no single upsert statement carries the same (vendor_code, mfr_sku) twice.
  const recs = [], seen = new Set();
  let dupes = 0;
  for (const r of patterns) {
    const imgs = r.sku_images || {}, us = distOf(r.source_url);
    for (const sku of (r.colorway_skus || [])) {
      if (seen.has(sku)) { dupes++; continue; }
      seen.add(sku);
      recs.push([ 'sangetsu', sku, r.pattern || sku, r.source_url || null, imgs[sku] || null, us ]);
    }
  }
  if (dupes) console.log(`skipped ${dupes} duplicate SKU(s) across patterns`);
  const db = new Client({ connectionString: DSN });
  await db.connect();
  await db.query('BEGIN');
  let n = 0;
  for (let i = 0; i < recs.length; i += CHUNK) {
    const slice = recs.slice(i, i + CHUNK);
    const vals = [], params = [];
    slice.forEach((row, j) => {
      const b = j * 6;
      vals.push(`($${b+1},$${b+2},$${b+3},$${b+4},$${b+5},$${b+6},false)`);
      params.push(...row);
    });
    await db.query(
      `insert into sangetsu_catalog (vendor_code,mfr_sku,pattern_name,product_url,image_url,us_distributor,on_shopify)
       values ${vals.join(',')}
       on conflict (vendor_code,mfr_sku) do update set
         pattern_name=excluded.pattern_name, product_url=excluded.product_url,
         image_url=excluded.image_url, us_distributor=excluded.us_distributor, updated_at=now()`,
      params);
    n += slice.length;
  }
  await db.query('COMMIT');
  await db.end();
  console.log(`staged ${n} Sangetsu colorway SKUs from ${patterns.length} patterns → sangetsu_catalog`);
})().catch((e) => { console.error(e); process.exit(1); });