← back to Designer Wallcoverings
cadence: unit-aware soldBy for Kravet family (soldByUnit) — yard-priced goods (Winfield Thybony foils) label 'Yard'/'Priced Per Yard' not 'Single Roll'; additive, non-opt-in vendors unchanged
202fdad2364483213ab2cf1fb89b9370f13d8104 · 2026-06-25 17:09:32 -0700 · Steve
Files touched
M shopify/scripts/cadence/cadence-import.jsM shopify/scripts/cadence/vendors.js
Diff
commit 202fdad2364483213ab2cf1fb89b9370f13d8104
Author: Steve <steve@designerwallcoverings.com>
Date: Thu Jun 25 17:09:32 2026 -0700
cadence: unit-aware soldBy for Kravet family (soldByUnit) — yard-priced goods (Winfield Thybony foils) label 'Yard'/'Priced Per Yard' not 'Single Roll'; additive, non-opt-in vendors unchanged
---
shopify/scripts/cadence/cadence-import.js | 24 ++++++++++++++++++++++--
shopify/scripts/cadence/vendors.js | 2 +-
2 files changed, 23 insertions(+), 3 deletions(-)
diff --git a/shopify/scripts/cadence/cadence-import.js b/shopify/scripts/cadence/cadence-import.js
index 75550b62..851fbb9a 100644
--- a/shopify/scripts/cadence/cadence-import.js
+++ b/shopify/scripts/cadence/cadence-import.js
@@ -392,6 +392,18 @@ function selectSkus(cfg, limit) {
} catch { hasHouseLine = false; }
}
const houseLineSel = hasHouseLine ? `, (${String(cfg.houseLineCol).replace(/[^a-z0-9_]/gi,'')})::text AS house_line` : '';
+ // Unit-aware soldBy (cfg.soldByUnit): Kravet-family staging mixes ROLL- and YARD-priced
+ // goods in one table (Winfield Thybony foils sell per yard). Select unit_of_measure so
+ // resolveType() labels each row by its real unit, not the cfg 'Single Roll' constant.
+ // Probed for existence like all_images so vendors without the column are unaffected. (2026-06-25)
+ let hasUnit = false;
+ if (cfg.soldByUnit) {
+ try {
+ const t = String(cfg.table).replace(/[^a-z0-9_]/gi,'');
+ hasUnit = (psql(`SELECT 1 FROM information_schema.columns WHERE table_name='${t}' AND column_name='unit_of_measure' LIMIT 1;`) || '').trim() === '1';
+ } catch { hasUnit = false; }
+ }
+ const unitSel = hasUnit ? `, unit_of_measure::text AS unit_of_measure` : '';
// sampleOnly (Quadrille-house, no cost): select net-new rows scoped by brand, NO cost column,
// NO cost>0 filter. description pulled from ai_description / description for the activation gate.
if (cfg.sampleOnly) {
@@ -409,13 +421,13 @@ function selectSkus(cfg, limit) {
const keys = [...STD, 'vendor_desc', ...(hasAllImg ? ['all_images'] : []), ...(hasHouseLine ? ['house_line'] : [])];
return out.split('\n').map(line => { const v=line.split('\t'); const o={}; keys.forEach((k,i)=>o[k]=v[i]); o.material=mfVal(o.material); o.cost=0; o.sampleOnly=true; return o; });
}
- const sql = `SELECT ${cols}, (${cfg.costExpr})::numeric AS cost${sellSel}${allImgSel}${houseLineSel}
+ const sql = `SELECT ${cols}, (${cfg.costExpr})::numeric AS cost${sellSel}${allImgSel}${houseLineSel}${unitSel}
FROM ${cfg.table}
WHERE coalesce(shopify_product_id::text,'')='' AND (${cfg.costExpr})::numeric > 0${dedupSkipClause(cfg.table)}
ORDER BY dw_sku LIMIT ${limit};`;
const out = psql(sql);
if (!out) return [];
- const keys = [...STD, 'cost', ...(cfg.sellExpr ? ['sell'] : []), ...(hasAllImg ? ['all_images'] : []), ...(hasHouseLine ? ['house_line'] : [])];
+ const keys = [...STD, 'cost', ...(cfg.sellExpr ? ['sell'] : []), ...(hasAllImg ? ['all_images'] : []), ...(hasHouseLine ? ['house_line'] : []), ...(hasUnit ? ['unit_of_measure'] : [])];
return out.split('\n').map(line => { const v=line.split('\t'); const o={}; keys.forEach((k,i)=>o[k]=v[i]); o.material=mfVal(o.material); o.cost=parseFloat(o.cost); if(cfg.sellExpr) o.sell=parseFloat(o.sell); return o; });
}
@@ -545,6 +557,14 @@ function resolveType(cfg, row) {
}
if (hit && hit.productType && hit.soldBy) return { productType: hit.productType, soldBy: hit.soldBy };
}
+ // Unit-aware soldBy (cfg.soldByUnit): one staging table mixes ROLL- and YARD-priced
+ // wallcoverings (Kravet family — Winfield Thybony foils sell per yard). Derive soldBy
+ // from the row's unit_of_measure so yard goods aren't mislabeled "Single Roll". (2026-06-25)
+ if (cfg && cfg.soldByUnit && row && row.unit_of_measure) {
+ const u = String(row.unit_of_measure).toUpperCase();
+ if (u.includes('YARD') || u === 'YD') return { productType: cfg.productType || 'Wallcovering', soldBy: 'Yard' };
+ if (u.includes('ROLL')) return { productType: cfg.productType || 'Wallcovering', soldBy: 'Single Roll' };
+ }
return { productType: cfg.productType || 'Wallcovering', soldBy: cfg.soldBy || 'Single Roll' };
}
diff --git a/shopify/scripts/cadence/vendors.js b/shopify/scripts/cadence/vendors.js
index 284f5b4e..8c32dc5b 100644
--- a/shopify/scripts/cadence/vendors.js
+++ b/shopify/scripts/cadence/vendors.js
@@ -64,7 +64,7 @@ module.exports = {
// Mulberry, Threads, Baker Lifestyle, Gaston y Daniela, Clarke & Clarke, etc.):
// Steve 2026-06-11 "use the MAP pricing for all kravet and subbrands" — sell = MAP
// (price_retail_new = NEW MAP from Jan-2026 list, fallback price_retail), NOT cost/0.65/0.85.
- 'Kravet': { table: 'kravet_catalog', costExpr: 'cost_price', sellExpr: 'COALESCE(NULLIF(price_retail_new,0),NULLIF(price_retail,0))', soldBy: 'Single Roll', productType: 'Wallcovering', discountNote: 'cost from GDrive Jan-2026 wholesale list (incl 5% tariff); SELL AT MAP' },
+ 'Kravet': { table: 'kravet_catalog', costExpr: 'cost_price', sellExpr: 'COALESCE(NULLIF(price_retail_new,0),NULLIF(price_retail,0))', soldBy: 'Single Roll', soldByUnit: true, productType: 'Wallcovering', discountNote: 'cost from GDrive Jan-2026 wholesale list (incl 5% tariff); SELL AT MAP. soldByUnit:true → YARD rows (Winfield Thybony foils) labeled per-yard, not Single Roll (2026-06-25)' },
// Schumacher: Designer Net (vendor_registry discount 0.00, confirmed) — cost = priceUsd
// from the authenticated API recrawl (2026-06-11). retail = cost/0.65/0.85.
'Schumacher': { table: 'schumacher_catalog', costExpr: 'cost', soldBy: 'Single Roll', productType: 'Wallcovering', discountNote: 'Designer Net 0% — cost=priceUsd (authenticated API recrawl)' },
← 8bb3a5cd docs(filter-topbar): record Material=Contents data finding +
·
back to Designer Wallcoverings
·
Disable stage-winfield-thybony.py — keyed off stale/collided 96401581 →