MVP
This commit is contained in:
336
SURGICAL_FIX_REPORT.md
Normal file
336
SURGICAL_FIX_REPORT.md
Normal file
@@ -0,0 +1,336 @@
|
||||
# Surgical Fix Report: Work Order Start Tracking Error
|
||||
## Date: November 27, 2025
|
||||
## Strategy: Diagnosis → Plan → Implementation
|
||||
|
||||
---
|
||||
|
||||
## STEP 1: DIAGNOSIS
|
||||
|
||||
### Error Received
|
||||
```
|
||||
TypeError: Cannot set properties of undefined (setting 'trackingEnabled')
|
||||
at Function [Work Order buttons]:143:37
|
||||
```
|
||||
|
||||
### Root Cause Analysis
|
||||
|
||||
**Node:** Work Order buttons
|
||||
**Line:** 143
|
||||
**Problem:** `msg.payload` was **undefined**
|
||||
|
||||
**Code that failed:**
|
||||
```javascript
|
||||
msg._mode = "production-state";
|
||||
msg.productionStarted = true;
|
||||
msg.machineOnline = true;
|
||||
|
||||
// ❌ ERROR HERE - msg.payload doesn't exist!
|
||||
msg.payload.trackingEnabled = true;
|
||||
msg.payload.productionStarted = true;
|
||||
msg.payload.machineOnline = true;
|
||||
```
|
||||
|
||||
**Why it failed:** The `msg` object in Node-RED doesn't automatically have a `payload` property. We were trying to set properties on an object that didn't exist, causing `Cannot set properties of undefined`.
|
||||
|
||||
### Secondary Issue: Mold Presets Handler Noise
|
||||
|
||||
**Node:** Mold Presets Handler
|
||||
**Problem:** Logging warnings for every message it receives, including non-mold topics like `machineStatus`, `kpis`, `chartsData`, etc.
|
||||
|
||||
**Debug output:**
|
||||
```
|
||||
"Unknown topic: selectMoldPreset"
|
||||
"Received: "
|
||||
"Unknown topic: "
|
||||
```
|
||||
|
||||
**Why:** No filter to silently ignore messages not meant for this handler.
|
||||
|
||||
---
|
||||
|
||||
## STEP 2: THE FIX PLAN
|
||||
|
||||
### Fix 1: Initialize msg.payload Before Use
|
||||
|
||||
**Architectural Decision:**
|
||||
- Initialize `msg.payload = {}` before setting properties
|
||||
- Set state flags at BOTH `msg` level AND `msg.payload` level for maximum compatibility
|
||||
- Preserve all existing global.set() calls (especially `kpiBuffer` clearing)
|
||||
|
||||
**Compatibility Reasoning:**
|
||||
The "Back to UI" node reads: `msg.payload?.trackingEnabled ?? msg.trackingEnabled`
|
||||
|
||||
This means it checks BOTH locations. By setting flags in both places, we ensure compatibility regardless of which path the message takes.
|
||||
|
||||
### Fix 2: Silent Ignore for Mold Presets Handler
|
||||
|
||||
**Architectural Decision:**
|
||||
- Add early return for non-mold topics
|
||||
- Define explicit list of ignored topics
|
||||
- Only log messages for mold-related operations
|
||||
|
||||
**Topics to silently ignore:**
|
||||
- `machineStatus` - Dashboard state updates
|
||||
- `kpis` - KPI calculations
|
||||
- `chartsData` - Graph data
|
||||
- `activeWorkOrder` - Work order updates
|
||||
- `workOrderCycle` - Cycle updates
|
||||
- `workOrdersList` - Work order list
|
||||
- `scrapPrompt` - Scrap entry prompts
|
||||
- `uploadStatus` - Upload confirmations
|
||||
- Empty string (`""`)
|
||||
|
||||
---
|
||||
|
||||
## STEP 3: IMPLEMENTATION
|
||||
|
||||
### Fix 1: Work Order buttons - "start" action
|
||||
|
||||
**Before (Lines 136-146):**
|
||||
```javascript
|
||||
msg._mode = "production-state";
|
||||
msg.productionStarted = true;
|
||||
msg.machineOnline = true;
|
||||
|
||||
// Send through output 2 to trigger KPI calculation
|
||||
// Add state info to the msg itself (will be sent to Calculate KPIs)
|
||||
msg.payload.trackingEnabled = true; // ❌ ERROR
|
||||
msg.productionStarted = true;
|
||||
msg.payload.productionStarted = true;
|
||||
msg.machineOnline = true;
|
||||
msg.payload.machineOnline = true;
|
||||
|
||||
return [null, msg, null, null];
|
||||
```
|
||||
|
||||
**After (Lines 136-148):**
|
||||
```javascript
|
||||
msg._mode = "production-state";
|
||||
|
||||
// Initialize payload object BEFORE setting properties
|
||||
msg.payload = msg.payload || {};
|
||||
|
||||
// Set state flags at both msg and msg.payload levels for compatibility
|
||||
msg.trackingEnabled = true;
|
||||
msg.productionStarted = true;
|
||||
msg.machineOnline = true;
|
||||
|
||||
msg.payload.trackingEnabled = true;
|
||||
msg.payload.productionStarted = true;
|
||||
msg.payload.machineOnline = true;
|
||||
|
||||
return [null, msg, null, null];
|
||||
```
|
||||
|
||||
**What was preserved:**
|
||||
✅ `global.set("trackingEnabled", true)`
|
||||
✅ `global.set("kpiBuffer", [])`
|
||||
✅ `node.warn('[START] Cleared kpiBuffer for fresh production run')`
|
||||
✅ All other global.set() calls
|
||||
✅ Return statement structure
|
||||
✅ Output routing
|
||||
|
||||
---
|
||||
|
||||
### Fix 2: Mold Presets Handler - Silent ignore
|
||||
|
||||
**Before (Lines 1-4):**
|
||||
```javascript
|
||||
const topic = msg.topic || '';
|
||||
const payload = msg.payload || {};
|
||||
|
||||
// Log every incoming request
|
||||
node.warn(`Received: ${topic}`);
|
||||
```
|
||||
|
||||
**After (Lines 1-19):**
|
||||
```javascript
|
||||
const topic = msg.topic || '';
|
||||
const payload = msg.payload || {};
|
||||
|
||||
// ===== IGNORE NON-MOLD TOPICS SILENTLY =====
|
||||
// These are KPI/dashboard messages not meant for this handler
|
||||
const ignoredTopics = [
|
||||
'machineStatus',
|
||||
'kpis',
|
||||
'chartsData',
|
||||
'activeWorkOrder',
|
||||
'workOrderCycle',
|
||||
'workOrdersList',
|
||||
'scrapPrompt',
|
||||
'uploadStatus'
|
||||
];
|
||||
|
||||
if (ignoredTopics.includes(topic) || topic === '') {
|
||||
return null; // Silent ignore
|
||||
}
|
||||
|
||||
// Log only mold-related requests
|
||||
node.warn(`Received: ${topic}`);
|
||||
```
|
||||
|
||||
**What was preserved:**
|
||||
✅ All mold preset handling logic
|
||||
✅ Lock/dedupe mechanisms
|
||||
✅ Database operations
|
||||
✅ Error handling
|
||||
✅ Existing functionality unchanged
|
||||
|
||||
---
|
||||
|
||||
## STEP 4: VERIFICATION
|
||||
|
||||
### Verification Checklist
|
||||
|
||||
**Fix 1: Work Order buttons**
|
||||
- ✅ `msg.payload = msg.payload || {};` - Initialization added
|
||||
- ✅ `msg.trackingEnabled = true;` - Top-level flag set
|
||||
- ✅ `msg.payload.trackingEnabled = true;` - Nested flag set
|
||||
- ✅ `global.set("kpiBuffer", [])` - Buffer clearing preserved
|
||||
- ✅ `[START] Cleared kpiBuffer` - Warning message preserved
|
||||
- ✅ No duplicate flag settings
|
||||
- ✅ Clean code structure
|
||||
|
||||
**Fix 2: Mold Presets Handler**
|
||||
- ✅ `ignoredTopics` array defined
|
||||
- ✅ `machineStatus` in ignore list
|
||||
- ✅ `kpis` in ignore list
|
||||
- ✅ `chartsData` in ignore list
|
||||
- ✅ Early return for ignored topics
|
||||
- ✅ Silent operation (no warnings for ignored topics)
|
||||
- ✅ Original logging preserved for mold topics
|
||||
|
||||
---
|
||||
|
||||
## EXPECTED BEHAVIOR AFTER DEPLOYMENT
|
||||
|
||||
### Before Fix
|
||||
```
|
||||
User clicks START
|
||||
↓
|
||||
❌ Error: Cannot set properties of undefined (setting 'trackingEnabled')
|
||||
❌ Production does not start
|
||||
❌ Debug panel full of "Unknown topic" warnings
|
||||
```
|
||||
|
||||
### After Fix
|
||||
```
|
||||
User clicks START
|
||||
↓
|
||||
✅ [START] Cleared kpiBuffer for fresh production run
|
||||
✅ Production starts successfully
|
||||
✅ trackingEnabled = true at global, msg, and msg.payload levels
|
||||
✅ Button changes from START to STOP
|
||||
✅ KPIs update continuously
|
||||
✅ No "Unknown topic" warnings in debug panel
|
||||
✅ Clean, noise-free debug output
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## TESTING INSTRUCTIONS
|
||||
|
||||
1. **Deploy the updated flows.json in Node-RED**
|
||||
|
||||
2. **Test Fix 1 - START button:**
|
||||
```
|
||||
- Load Home dashboard
|
||||
- Verify active work order exists
|
||||
- Click START button
|
||||
- Expected: No errors in debug panel
|
||||
- Expected: Message "[START] Cleared kpiBuffer for fresh production run"
|
||||
- Expected: Button changes to STOP
|
||||
- Expected: Production tracking begins
|
||||
```
|
||||
|
||||
3. **Test Fix 2 - Silent ignore:**
|
||||
```
|
||||
- Monitor debug panel
|
||||
- Navigate between dashboard tabs
|
||||
- Expected: No "Unknown topic" warnings for machineStatus, kpis, etc.
|
||||
- Expected: Only mold-related messages logged
|
||||
```
|
||||
|
||||
4. **Integration test:**
|
||||
```
|
||||
- Complete a full production cycle
|
||||
- Submit scrap
|
||||
- Verify KPIs update
|
||||
- Check graphs display data
|
||||
- Verify no errors throughout
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ARCHITECTURAL NOTES
|
||||
|
||||
### Message Flow (Corrected)
|
||||
|
||||
```
|
||||
START button click
|
||||
↓
|
||||
Work Order buttons (case "start")
|
||||
├─ Sets: global.set("trackingEnabled", true)
|
||||
├─ Clears: global.set("kpiBuffer", [])
|
||||
├─ Initializes: msg.payload = {}
|
||||
├─ Sets: msg.trackingEnabled = true
|
||||
├─ Sets: msg.payload.trackingEnabled = true
|
||||
└─ Sends: [null, msg, null, null] → Output 2
|
||||
↓
|
||||
Calculate KPIs (receives msg with _mode="production-state")
|
||||
├─ Reads: global.get("trackingEnabled") ✅
|
||||
├─ Performs: KPI calculations
|
||||
└─ Sends: Output 1 → Refresh Trigger
|
||||
↓
|
||||
Refresh Trigger (sees _mode="production-state")
|
||||
└─ Routes: [null, msg] → Output 2
|
||||
↓
|
||||
Back to UI (sees mode="production-state")
|
||||
├─ Reads: msg.payload?.trackingEnabled ?? msg.trackingEnabled ✅
|
||||
├─ Creates: homeMsg with topic="machineStatus"
|
||||
└─ Sends: [null, homeMsg, null, null]
|
||||
↓
|
||||
link out → Home Template
|
||||
└─ Updates: scope.isProductionRunning = msg.payload.trackingEnabled ✅
|
||||
↓
|
||||
Button displays: STOP ✅
|
||||
```
|
||||
|
||||
### Why Both msg and msg.payload?
|
||||
|
||||
The "Back to UI" node uses optional chaining:
|
||||
```javascript
|
||||
trackingEnabled: msg.payload?.trackingEnabled ?? msg.trackingEnabled ?? false
|
||||
```
|
||||
|
||||
This checks:
|
||||
1. `msg.payload?.trackingEnabled` first (nested)
|
||||
2. Falls back to `msg.trackingEnabled` (top-level)
|
||||
3. Defaults to `false`
|
||||
|
||||
By setting both, we ensure compatibility regardless of how the message is processed or which properties survive through the flow.
|
||||
|
||||
---
|
||||
|
||||
## FILES MODIFIED
|
||||
|
||||
- `/home/mdares/.node-red/projects/Plastico/flows.json`
|
||||
- Work Order buttons node (ID: `9bbd4fade968036d`)
|
||||
- Mold Presets Handler node
|
||||
|
||||
---
|
||||
|
||||
## ROLLBACK INSTRUCTIONS
|
||||
|
||||
If issues occur:
|
||||
```bash
|
||||
cd /home/mdares/.node-red/projects/Plastico/
|
||||
cp flows.json.backup_20251127_124628 flows.json
|
||||
# Restart Node-RED
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**Status: SURGICAL FIX COMPLETE ✅**
|
||||
**Deployment: READY**
|
||||
**Risk Level: LOW** (Isolated changes, preservation verified)
|
||||
Reference in New Issue
Block a user