[object Object]

← back to Mfr Review Viewer Corruption

executor: add belongs-to-SKU (skuMatch) guard to execute-time re-verify — refuses to delete a foreign record even if a plan lists it

e24c2874ce942afaf0a5a410d211bab733605213 · 2026-08-27 11:20:30 -0700 · Steve Abrams

Files touched

Diff

commit e24c2874ce942afaf0a5a410d211bab733605213
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Thu Aug 27 11:20:30 2026 -0700

    executor: add belongs-to-SKU (skuMatch) guard to execute-time re-verify — refuses to delete a foreign record even if a plan lists it
---
 scripts/execute-sweep.mjs | 17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)

diff --git a/scripts/execute-sweep.mjs b/scripts/execute-sweep.mjs
index 459b0e3..0caa907 100644
--- a/scripts/execute-sweep.mjs
+++ b/scripts/execute-sweep.mjs
@@ -93,7 +93,8 @@ function parseNoteMfr(note) {
 // Given a live fieldData object + the dw_sku, compute (sampleOrdered, mfrPlaceholder).
 // This IS the execute-time re-verification predicate.
 function classifyRecord(fd, dwSku) {
-  const tail = numericTail(String(dwSku || '').trim().replace(/[-_ ]?sample$/i, ''));
+  const clean = String(dwSku || '').trim().replace(/[-_ ]?sample$/i, '');
+  const tail = numericTail(clean);
   const mfrPattern = String(fd['Mfr Pattern'] || '').trim();
   const chaseMemo = String(fd['Vendor Sample - Where is Memo Send 2nd day'] || '').trim();
   const mfrNote = mfrPattern || (/#/.test(chaseMemo) ? chaseMemo : '');
@@ -106,7 +107,18 @@ function classifyRecord(fd, dwSku) {
   const codeHasAlpha = /[A-Za-z]/.test(noteMfr || '');
   const codeDigits = String(noteMfr || mfrPattern || '').replace(/[^0-9]/g, '');
   const mfrPlaceholder = !codeHasAlpha && !!tail && codeDigits === tail;
-  return { sampleOrdered, mfrPlaceholder, mfrPattern, noteMfr };
+
+  // BELONGS-TO-SKU guard (2026-08-27, critical): a record's Series+JS Pattern must
+  // normalize to THIS dw_sku. A foreign record (e.g. Schumacher SCH|51526 that merely
+  // shares the number 51526 with HSW-51526) is NOT this SKU and must NEVER be deleted,
+  // even though it reads no-sample + placeholder. Mirrors candidates.mjs skuMatch.
+  const normSku = (s) => String(s || '').toUpperCase().replace(/[^A-Z0-9]/g, '');
+  const target = normSku(clean);
+  const storedKey = normSku(String(fd.Series || '') + String(fd['JS Pattern'] || ''));
+  const comboKey = normSku(fd['combo sku']);
+  const skuMatch = !!target && (storedKey === target || comboKey === target);
+
+  return { sampleOrdered, mfrPlaceholder, mfrPattern, noteMfr, skuMatch };
 }
 
 // ---- plan loading ----------------------------------------------------------
@@ -253,6 +265,7 @@ async function main() {
       const rec = live[rid];
       if (!rec) { console.log(`  SKIP delete ${rid}: record no longer exists`); skippedMismatch++; continue; }
       const c = classifyRecord(rec.fieldData || {}, e.dw_sku);
+      if (!c.skuMatch) { console.log(`  SKIP delete ${rid}: does NOT belong to ${e.dw_sku} (foreign record ${rec.fieldData?.Series || ''}|${rec.fieldData?.['JS Pattern'] || ''}) — NEVER delete a different SKU's record`); skippedMismatch++; continue; }
       if (c.sampleOrdered) { console.log(`  SKIP delete ${rid}: now has SAMPLE history (sampleOrdered) — KEEP`); skippedMismatch++; continue; }
       if (!c.mfrPlaceholder) { console.log(`  SKIP delete ${rid}: mfr no longer a placeholder ("${c.mfrPattern}") — KEEP`); skippedMismatch++; continue; }
       confirmedDeletes.push(rid);

← ac96049 viewer: prominent 'Suggested real mfr → Approve into field'  ·  back to Mfr Review Viewer Corruption  ·  scope to ACTIVE patterns only: default status='ACTIVE' in bu dcd7c8f →