← back to Majilite Onboard

scripts/emit_sql.js

72 lines

#!/usr/bin/env node
/**
 * Emit migrations/001_majilite_catalog.sql — creates the Mac2-canonical staging
 * table majilite_catalog and loads all 160 staged SKUs. Additive + reversible.
 * (vendor_registry INSERT + Shopify publish are drafted separately — gated.)
 */
const fs = require('fs');
const path = require('path');
const ROOT = path.resolve(__dirname, '..');
const products = JSON.parse(fs.readFileSync(path.join(ROOT, 'data/products.json'), 'utf8'));
const coll = JSON.parse(fs.readFileSync(path.join(ROOT, 'data/collection.json'), 'utf8'));
const q = s => s === null || s === undefined ? 'NULL' : `'${String(s).replace(/'/g, "''")}'`;
const j = o => `'${JSON.stringify(o).replace(/'/g, "''")}'::jsonb`;

let sql = `-- Majilite "Metallic Specialties I" (Nytek) staging  — TK-10403
-- Mac2-canonical *_catalog staging table. Additive + reversible.
-- ROLLBACK:  DROP TABLE IF EXISTS majilite_catalog;
BEGIN;
CREATE TABLE IF NOT EXISTS majilite_catalog (
  dw_sku          text PRIMARY KEY,
  variant_sku     text,
  mfr_sku         text,           -- Majilite is name-keyed: "Pattern Colorway"
  title           text,           -- customer-facing (original names kept)
  pattern         text,
  color           text,
  vendor          text,
  brand           text,
  collection      text,
  product_type    text,
  material        text,
  color_family    text,
  color_hex       text,
  image_local     text,
  tags            text[],
  spec            jsonb,          -- shared Nytek spec on every row
  pricing         jsonb,          -- quote-only until cost list (display_prices=false)
  source_page     int,
  onboard_status  text DEFAULT 'staged',
  created_at      timestamptz DEFAULT now()
);
-- idempotent reload
TRUNCATE majilite_catalog;
`;

for (const p of products) {
  const tagsArr = `ARRAY[${p.tags.map(q).join(',')}]::text[]`;
  sql += `INSERT INTO majilite_catalog (dw_sku,variant_sku,mfr_sku,title,pattern,color,vendor,brand,collection,product_type,material,color_family,color_hex,image_local,tags,spec,pricing,source_page,onboard_status,created_at) VALUES (`
    + [q(p.dw_sku), q(p.variant_sku), q(p.mfr_sku), q(p.title), q(p.pattern), q(p.color), q(p.vendor), q(p.brand), q(p.collection), q(p.product_type), q(p.material), q(p.color_family), q(p.color_hex), q(p.image), tagsArr, j(p.spec), j(p.pricing), p.source_page, q(p.onboard_status), q(p.created_at)].join(',')
    + `);\n`;
}
sql += `COMMIT;\n-- rows: ${products.length}\n`;
fs.writeFileSync(path.join(ROOT, 'migrations/001_majilite_catalog.sql'), sql);

// vendor_registry INSERT — DRAFT ONLY (gated; triggers drift-canary + registry-sync semantics)
const reg = `-- DRAFT / GATED — vendor_registry row for Majilite.  Apply only with Steve's go.
-- Adding a Mac2-only vendor_registry row is expected to show on dw-machine-drift-canary
-- until dw-registry-sync pushes it to Kamatera. Reversible: DELETE FROM vendor_registry WHERE vendor_code='MAJ';
INSERT INTO vendor_registry
  (vendor_name, vendor_code, sku_prefix, sku_range_start, catalog_table, is_active, is_private_label,
   pricing_unit, pricing_model, sample_price, display_prices, do_not_price,
   product_type, website_url, notes, created_at, updated_at)
VALUES
  ('Majilite','MAJ','DWMJ-', 600001, 'majilite_catalog', true, false,
   'yard','sample', 4.25, true, false,
   'Wallcovering','https://www.majilite.com',
   'Nytek faux leather. Metallic Specialties I = 160 SKUs (card I of II; II adds ~160 more = 320 total). DW number block 600000 (DWMJ-600001..600160). Name-keyed (mfr_sku = Pattern Colorway). ONBOARDED AS $4.25 SAMPLES; by-the-yard retail pending Majilite cost list (rep: Kathryn Gabriel / Two Gabriels, kathryn@twogabriels.com). Orders/lead-time: Dara Pinn dpinn@majilite.com. Sold by yard, 54in wide.',
   now(), now());
`;
fs.writeFileSync(path.join(ROOT, 'migrations/002_vendor_registry.DRAFT.sql'), reg);

console.log(`Wrote migrations/001_majilite_catalog.sql (${products.length} rows) + migrations/002_vendor_registry.DRAFT.sql`);