← back to Marketing Command Center
calendars: filter Schumacher (internal-only) out of both calendar layers at source
5ea8d24ed0fd7a049b131bb0021efaaf6a0351cc · 2026-07-20 14:07:46 -0700 · Steve Abrams
Schumacher is internal-only and must never surface on a front end. The All
Calendars feed re-projects from dw_unified every ~10min, so scrubbing the JSON
alone would be undone on the next regen. Added a HIDDEN_VENDORS source filter
applied to the activation layer (after date projection, so other vendors keep
their real go-live slots), the launched layer, and the snapshot-fallback path.
Verified: live regen yields 0 Schumacher (activation 20304 -> 20034).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Files touched
M modules/calendars/lib.js
Diff
commit 5ea8d24ed0fd7a049b131bb0021efaaf6a0351cc
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Mon Jul 20 14:07:46 2026 -0700
calendars: filter Schumacher (internal-only) out of both calendar layers at source
Schumacher is internal-only and must never surface on a front end. The All
Calendars feed re-projects from dw_unified every ~10min, so scrubbing the JSON
alone would be undone on the next regen. Added a HIDDEN_VENDORS source filter
applied to the activation layer (after date projection, so other vendors keep
their real go-live slots), the launched layer, and the snapshot-fallback path.
Verified: live regen yields 0 Schumacher (activation 20304 -> 20034).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---
modules/calendars/lib.js | 21 ++++++++++++++++-----
1 file changed, 16 insertions(+), 5 deletions(-)
diff --git a/modules/calendars/lib.js b/modules/calendars/lib.js
index 82bc488..3e03665 100644
--- a/modules/calendars/lib.js
+++ b/modules/calendars/lib.js
@@ -103,6 +103,13 @@ function priceBand(p) {
if (p < 500) return '$200–500'; if (p < 1000) return '$500–1,000'; return '$1,000+';
}
+// Vendors that must NEVER surface on any front-end surface. Schumacher is
+// internal-only (see the schumacher-internal-only standing rule) — it is filtered
+// out of BOTH calendar layers at the source so a cache regeneration can't
+// reintroduce it. Matched case-insensitively against the resolved vendor.
+const HIDDEN_VENDORS = new Set(['schumacher']);
+const isHiddenVendor = (v) => HIDDEN_VENDORS.has(String(v || '').trim().toLowerCase());
+
// Map a shopify_products row → the common filterable fields (shared by the
// activation layer's enrichment join AND the launched layer's direct rows).
function fieldsFrom(e) {
@@ -154,7 +161,7 @@ async function computeActivation() {
} finally { c.release(); }
// launched layer — one item per already-live product, on its launch date (LIVE)
- const launched = launchedRows.map(r => {
+ const launched = launchedRows.filter(r => !isHiddenVendor(r.vendor)).map(r => {
const d = new Date(r.created_at_shopify);
return {
key: r.shopify_id, layer: 'launched',
@@ -199,14 +206,18 @@ async function computeActivation() {
shopify_id: r.shopify_id || '',
};
}
+ // drop internal-only vendors (e.g. Schumacher) AFTER date projection so the
+ // remaining SKUs keep their real go-live slots (never resequenced by a regen)
+ items = items.filter(it => !isHiddenVendor(it.vendor));
+ total = items.length;
start_date = items[0]?.date || null;
end_date = items[total - 1]?.date || null;
} else {
const disk = store.readJson(CACHE_FILE, null) || {};
- items = disk.items || [];
- total = disk.total || items.length;
- start_date = disk.start_date || null;
- end_date = disk.end_date || null;
+ items = (disk.items || []).filter(it => !isHiddenVendor(it.vendor));
+ total = items.length;
+ start_date = items[0]?.date || disk.start_date || null;
+ end_date = items[total - 1]?.date || disk.end_date || null;
}
const out = {
← 540ae08 chore: lint + refactor + v1.6.0 (session close — reel/FB-pag
·
back to Marketing Command Center
·
chore: v1.6.1 (session close — Schumacher calendar filter) 76de953 →