Files
Virtual-Box/projects/Plastico/IMPLEMENTATION_SUMMARY.md
2025-12-02 16:27:21 +00:00

12 KiB
Raw Blame History

Multi-Phase Implementation Summary

Plastico Work Order Persistence System

Date: 2025-11-29 Phases Completed: 2, 3, 4, 5, 6 (Backend complete, UI dialogs pending)


Overview

Implemented a comprehensive work order persistence system that ensures production data survives Node-RED restarts, allows resuming work orders, and makes the database the source of truth for production counts.


Phase 2: Cycle Persistence (COMPLETE)

Goal

Write good_parts and cycle_count to database every 5 seconds (throttled)

Changes Made

Modified Files:

  • flows.json - Machine Cycles function node

Implementation:

  1. Added 5-second throttling to 4th output of Machine Cycles function
  2. Uses global variable lastWorkOrderDbWrite to track last DB write timestamp
  3. Only sends DB update when 5+ seconds have elapsed since last write
  4. SQL UPDATE includes: cycle_count, good_parts, progress_percent, updated_at

4th Output SQL:

UPDATE work_orders
SET cycle_count = ?,
    good_parts = ?,
    progress_percent = ?,
    updated_at = NOW()
WHERE work_order_id = ?

Flow: Machine Cycles → DB Guard (Cycles) → mariaDB

Maximum Data Loss: 5 seconds of cycles (typically 1-2 cycles)

Risk Level: LOW


Phase 3: Resume/Restart Prompt (COMPLETE - Backend)

Goal

Prevent accidental progress loss when clicking Load by prompting user to Resume or Restart

Changes Made

Modified Files:

  • flows.json - Work Order buttons function
  • flows.json - Refresh Trigger function
  • flows.json - Back to UI function

New Actions in Work Order Buttons:

  1. start-work-order (modified):

    • Now queries database for existing progress first
    • Sets _mode = "check-progress"
    • Stores pending order in flow context
    • SQL: SELECT cycle_count, good_parts, progress_percent FROM work_orders WHERE work_order_id = ?
  2. resume-work-order (new):

    • Loads work order with existing cycle_count and good_parts from database
    • Initializes global.cycleCount with existing value
    • Sets status to RUNNING
    • User must still click START to begin tracking
  3. restart-work-order (new):

    • Resets database values to 0
    • Resets global.cycleCount to 0
    • Sets status to RUNNING
    • User must click START to begin tracking

Back to UI - New Modes:

  1. check-progress:

    • Receives DB query results
    • If progress exists (cycles > 0 OR good_parts > 0), sends resumePrompt to UI
    • If no progress, auto-starts with zero values
    • Message format:
    {
      topic: "resumePrompt",
      payload: {
        id, sku, target,
        cycleCount, goodParts, progressPercent
      }
    }
    
  2. resume:

    • Sends activeWorkOrder to UI with database values
    • Maintains current progress
  3. restart:

    • Sends activeWorkOrder to UI with zeroed values

Refresh Trigger - New Routes:

  • Handles check-progress, resume, and restart modes
  • Routes messages to Back to UI for processing

UI Changes Needed (NOT YET IMPLEMENTED):

  • Home or Work Orders template needs resume/restart dialog
  • Listen for msg.topic === "resumePrompt"
  • Display: "WO-{id} has {goodParts}/{target} parts. Resume or Restart?"
  • Two buttons:
    • Resume (green): sends {action: "resume-work-order", payload: order}
    • Restart (orange): sends {action: "restart-work-order", payload: order} with confirmation

Risk Level: MEDIUM (changes core Load button behavior)


Phase 4: Complete Button Persistence (COMPLETE)

Goal

Ensure final production numbers are written to work_orders before marking DONE

Changes Made

Modified Files:

  • flows.json - Work Order buttons function (complete-work-order case)

Implementation:

  1. Before marking status = 'DONE', retrieve current global state values
  2. Calculate final good_parts using same formula as Machine Cycles:
    • finalCycles = global.cycleCount
    • totalProduced = finalCycles × cavities
    • finalGoodParts = max(0, totalProduced - scrapTotal)

Updated SQL:

UPDATE work_orders
SET status = 'DONE',
    cycle_count = ?,
    good_parts = ?,
    progress_percent = 100,
    updated_at = NOW()
WHERE work_order_id = ?

Parameters: [finalCycles, finalGoodParts, order.id]

Risk Level: LOW (just ensures final sync before completion)


Phase 5: Session Restore Status (COMPLETE)

Goal

When restoring session, work order stays RUNNING but user must click START

Changes Made

Modified Files:

  • flows.json - Back to UI function (restore-query mode)

Implementation: Already correctly implemented:

  • Query finds work orders WHERE status = 'RUNNING'
  • Restores global.activeWorkOrder and global.cycleCount from database
  • Sets trackingEnabled = false and productionStarted = false
  • User MUST click START button to begin tracking
  • Work order remains RUNNING so user doesn't have to Load again

Added:

  • Enhanced logging to clarify behavior
  • Comment documentation of Phase 5 requirements

Risk Level: LOW (no logic changes, clarification only)


Phase 6: Database as Source of Truth (COMPLETE)

Goal

Make work_orders table the source of truth for UI display

Changes Made

Already Implemented in Phases 2-5:

  1. Load/Resume Logic:

    • start-work-order queries database for current values
    • resume-work-order initializes global state from database
    • restart-work-order resets database AND global state to 0
  2. Persistence:

    • Machine Cycles writes to database every 5 seconds
    • Complete button writes final counts to database
    • All cycle_count and good_parts stored in work_orders table
  3. UI Updates:

    • Back to UI modes (resume, restart, restore-query) use database values
    • activeWorkOrder payload includes good_parts from database
    • Work order list refresh queries database for latest values

Data Flow:

  1. User loads work order → Query DB for progress
  2. If progress exists → Prompt Resume/Restart
  3. User chooses → Global state initialized from DB
  4. Production runs → Every 5s write to DB
  5. Node-RED restarts → Restore from DB
  6. User clicks START → Continue from last persisted count

Risk Level: MEDIUM (changes data flow, requires testing)


Phase 7: Tab Switch Refresh (OPTIONAL - NOT IMPLEMENTED)

This phase is optional UI enhancement and was not implemented. Current behavior:

  • Global state maintains active work order when switching tabs
  • If needed later, can add tab activation listener in Home template

Files Modified Summary

File Modified Nodes Phases Backups Created
flows.json Machine Cycles 2 flows.json.backup_phase2_*
flows.json Work Order buttons 2, 3, 4 flows.json.backup_phase3_, backup_phase4_
flows.json Refresh Trigger 3 flows.json.backup_phase3_*
flows.json Back to UI 3, 5 flows.json.backup_phase3_*

Testing Checklist (Phase 8)

1. New Work Order Start

  • Load WO with 0 progress → should start normally (no prompt)
  • Verify cycle_count and good_parts are 0 in database

2. Resume Existing Work Order

  • Stop production at 50/200 parts
  • Restart Node-RED
  • Load same WO → prompt should show "50/200 parts"
  • Click Resume → continues from 50
  • Machine cycles → good_parts increments correctly
  • Check database shows incremental updates every 5 seconds

3. Restart Existing Work Order

  • Load WO with 100/500 parts → prompt shows
  • Click Restart → (UI needs confirmation dialog)
  • After restart → cycle_count and good_parts are 0 in DB
  • Verify global.cycleCount is 0
  • Start production → counts from 0

4. Tab Switch

  • Start production at WO with 25 parts
  • Switch to Graphs tab
  • Switch back to Home
  • Progress still shows 25+ parts correctly

5. Node-RED Restart with Restore

  • Production running at 75/300 parts
  • Kill Node-RED (simulate crash)
  • Restart Node-RED
  • Verify session restore finds RUNNING work order
  • Work order shows 75± parts (within 5-second window)
  • Click START → production continues from ~75

6. Complete Work Order

  • Finish work order at 250/250 parts
  • Click Done
  • Query database: SELECT cycle_count, good_parts, status FROM work_orders WHERE work_order_id = ?
  • Verify cycle_count and good_parts are persisted
  • Verify status = 'DONE'

7. Power Failure Simulation

  • Production at 150 parts
  • Kill Node-RED process immediately (simulate power loss)
  • Restart
  • Check DB for last persisted value
  • Maximum 5 seconds / 1-2 cycles of data loss

8. Database Persistence Verification

-- Check throttling works (updates every 5 seconds)
SELECT work_order_id, cycle_count, good_parts, updated_at
FROM work_orders
WHERE status = 'RUNNING';

-- Verify completed work orders have final counts
SELECT work_order_id, cycle_count, good_parts, status
FROM work_orders
WHERE status = 'DONE';

Known Limitations

  1. UI Dialogs Not Implemented:

    • Resume/Restart prompt dialog needs to be added to Home or Work Orders template
    • Backend sends resumePrompt message but UI doesn't handle it yet
    • Workaround: System auto-starts with zero values if no UI dialog present
  2. 5-Second Data Loss Window:

    • Acceptable trade-off for reduced database load
    • Typical cycle times are 3-15 seconds
    • Loss of 1-2 cycles on crash is acceptable for manufacturing use case
  3. Scrap Counting:

    • Scrap is stored separately and added to activeWorkOrder object
    • Not persisted in throttled updates (only on complete)
    • Could be added to Phase 2 persistence if needed

Rollback Instructions

If issues arise, restore from backups:

cd /home/mdares/projects/Plastico

# Rollback to before Phase 2
cp flows.json.backup flows.json

# Or rollback to specific phase
cp flows.json.backup_phase2_YYYYMMDD_HHMMSS flows.json

Backups created:

  • flows.json.backup (original)
  • flows.json.backup_phase2_*
  • flows.json.backup_phase3_*
  • flows.json.backup_phase4_*

Success Criteria

Work orders persist progress across Node-RED restarts (Phase 2) Resume/Restart backend logic implemented (Phase 3) Resume/Restart UI dialog (Phase 3 - needs UI template work) work_orders table reflects current production state (Phase 2, 4) Complete button persists final counts (Phase 4) Session restore maintains RUNNING status (Phase 5) Database is source of truth (Phase 6) Maximum 5 seconds of data loss on crash (Phase 2) Tab switches don't lose data (Phase 7 - not implemented, optional)


Next Steps

  1. Implement UI Dialog (Priority: HIGH):

    • Add resume/restart dialog to Home or Work Orders template
    • Listen for msg.topic === "resumePrompt"
    • Create two action buttons that send resume/restart actions
  2. Testing (Priority: HIGH):

    • Run through all test cases in Phase 8 checklist
    • Verify database persistence works correctly
    • Test crash recovery scenarios
  3. Optional Enhancements:

    • Phase 7: Tab switch state refresh
    • Add scrap to throttled persistence
    • Visual indicator showing "last saved" timestamp in UI

Technical Notes

Global Variables Used

  • activeWorkOrder - Current work order object
  • cycleCount - Current cycle count
  • lastWorkOrderDbWrite - Timestamp of last DB persistence (Phase 2)
  • trackingEnabled - Whether production tracking is active
  • productionStarted - Whether production has started
  • moldActive - Number of cavities in current mold

Flow Context Variables

  • pendingWorkOrder - Temporarily stores work order during progress check (Phase 3)
  • lastMachineState - Previous machine state for edge detection

Database Schema Requirements

Table: work_orders

  • work_order_id (PRIMARY KEY)
  • cycle_count INT DEFAULT 0
  • good_parts INT DEFAULT 0
  • progress_percent INT DEFAULT 0
  • status VARCHAR (PENDING, RUNNING, DONE)
  • updated_at TIMESTAMP
  • scrap_parts INT
  • target_qty INT
  • Additional fields: sku, cycle_time, etc.

Support

For issues or questions:

  1. Check Node-RED debug output for [MACHINE CYCLE], [RESUME], [RESTART], [COMPLETE] messages
  2. Verify database schema has all required columns
  3. Check backups if rollback is needed
  4. Review this document for expected behavior

Implementation completed by: Claude Code Based on: Recommendation.txt multi-phase plan