mirror of
https://github.com/DumbWareio/DumbAssets.git
synced 2026-01-09 06:10:52 +08:00
10 KiB
10 KiB
🔧 MAINTENANCE NOTIFICATION SYSTEM - CRITICAL FIXES
🚨 CRITICAL DATE CALCULATION BUG - FIXED ✅
ISSUE: "Today" Events Showing as -1 Days Remaining (CRITICAL)
Problem:
- Warranties and maintenance events expiring "today" were showing as
-1days remaining instead of0 - This was causing missed notifications for events due on the current day
- Root cause: Time-based date comparison instead of date-only comparison
Technical Details:
- Cron runs at 12:01 PM daily
- When comparing a warranty expiring "today" (2025-05-26 00:00:00) with current time (2025-05-26 12:01:00)
- The difference is approximately -0.5 days (12 hours past midnight)
Math.floor(-0.5)=-1instead of expected0
Solution:
- Modified both warranty and maintenance date calculations to compare dates at start-of-day level
- This ensures events due "today" correctly show as
0days remaining
// OLD (PROBLEMATIC):
const daysOut = Math.floor(expDate.diff(now, 'days').days);
const daysUntilEvent = Math.floor(eventDate.diff(now, 'days').days);
// NEW (FIXED):
const todayStart = now.startOf('day');
const expDateStart = expDate.startOf('day');
const daysOut = Math.floor(expDateStart.diff(todayStart, 'days').days);
const eventDateStart = eventDate.startOf('day');
const daysUntilEvent = Math.floor(eventDateStart.diff(todayStart, 'days').days);
Impact:
- ✅ Warranties expiring today now correctly show
0days remaining - ✅ Maintenance events due today now correctly show
0days remaining - ✅ All other date calculations remain accurate
- ✅ No missed notifications for events due on current day
🚨 ISSUES IDENTIFIED & RESOLVED
1. TIMEZONE MISMATCH (HIGH RISK) - FIXED ✅
Problem:
- Dates were compared in UTC (
toISOString().split('T')[0]) while cron ran in local timezone - Could cause off-by-one day errors where maintenance is missed or triggered on wrong day
Solution:
- Implemented robust timezone handling using Luxon DateTime library
- All date operations now use configured timezone (
process.env.TZ || 'America/Chicago') - Added
getTodayString()andtoDateString()functions for consistent timezone handling
// OLD (PROBLEMATIC):
const today = now.toISOString().split('T')[0]; // UTC
const dueDateStr = dueDate.toISOString().split('T')[0]; // UTC
// NEW (FIXED):
const today = getTodayString(); // Configured timezone
const dueDateStr = toDateString(dueDate); // Configured timezone
2. DATE PARSING FRAGILITY (HIGH RISK) - FIXED ✅
Problem:
- Basic
new Date()parsing could fail silently with invalid dates - No validation of date formats
- Different parsing methods in different parts of the code
Solution:
- Created robust
parseDate()function that handles multiple formats:- ISO format (YYYY-MM-DD)
- MM/DD/YYYY format
- Date objects, timestamps
- Proper error handling and logging
// OLD (PROBLEMATIC):
const dueDate = new Date(nextDueDate);
if (isNaN(dueDate)) // Might miss edge cases
// NEW (FIXED):
const dueDate = parseDate(nextDueDate);
if (!dueDate) // Comprehensive validation
3. DATE CALCULATION ERRORS (MEDIUM-HIGH RISK) - FIXED ✅
Problem:
- Month arithmetic using
setMonth()had edge cases (Jan 31 + 1 month = March 3) - No validation of calculated dates
- Could result in invalid dates or skipped months
Solution:
- Implemented
addTimePeriod()function using Luxon's robust date arithmetic - Proper handling of month/year boundaries
- Validation of calculated results
// OLD (PROBLEMATIC):
switch (frequencyUnit) {
case 'months':
nextDate.setMonth(dueDate.getMonth() + parseInt(frequency));
break;
}
// NEW (FIXED):
const nextDate = addTimePeriod(dueDate, numericFrequency, frequencyUnit);
if (!nextDate) {
debugLog(`[ERROR] Could not calculate next due date`);
return false;
}
4. MISSING VALIDATION (MEDIUM RISK) - FIXED ✅
Problem:
- No validation of frequency being a valid positive number
- No validation of frequencyUnit being valid
- No error handling for invalid maintenance event configurations
Solution:
- Added comprehensive validation in
validateMaintenanceEvent()function - Validates all required fields before processing
- Validates frequency numbers and units
- Proper error logging for debugging
5. TRACKING SYSTEM GAPS (MEDIUM RISK) - FIXED ✅
Problem:
- Missing events if server was down on exact due date
- No retry logic or safety nets
- No cleanup of old tracking records
Solution:
Added overdue detection (notifications for 1-3 days past due)REMOVED - Overdue detection removed per user request- Implemented tracking record cleanup
Added safety checks for past-due maintenanceREMOVED - No longer checking for overdue events- Enhanced duplicate prevention
6. ERROR HANDLING & MONITORING - ADDED ✅
New Features:
- Comprehensive error handling throughout the system
- Detailed logging for debugging
- Summary reports after each maintenance check
- Graceful handling of individual failures without stopping the entire process
- Enhanced warranty notifications with same comprehensive logging and error handling
7. WARRANTY NOTIFICATION ENHANCEMENTS - ADDED ✅
Problem:
- Warranty notifications had basic logging compared to maintenance notifications
- No comprehensive error handling or summary reports
- Missing timezone consistency and robust date parsing
Solution:
- Applied same robust date parsing using
parseDate()function - Added comprehensive error handling for individual warranty processing
- Implemented detailed summary reporting matching maintenance system
- Added expired warranty detection (1-7 days past expiration)
- Enhanced logging with asset type differentiation (Asset vs Component)
- Consolidated notification threshold logic for cleaner code
New Warranty Features:
// Robust date parsing and validation
const expDate = parseDate(warranty.expirationDate);
if (!expDate) {
debugLog(`[WARNING] Invalid warranty expiration date for ${assetType}: ${asset.name}`);
return;
}
// Comprehensive summary reporting
debugLog(`[SUMMARY] Warranty check completed for ${today}:`);
debugLog(` - Assets checked: ${totalChecked} (${assets.length} main assets, ${subAssets.length} components)`);
debugLog(` - Total warranties: ${totalWarranties}`);
debugLog(` - Notifications sent successfully: ${successfulNotifications}`);
debugLog(` - Notification settings: 1M=${notify1Month}, 2W=${notify2Week}, 7D=${notify7Day}, 3D=${notify3Day}`);
// Expired warranty safety checks
if (daysOut >= -7 && daysOut < 0) {
debugLog(`[WARNING] ${warrantyType} expired ${Math.abs(daysOut)} days ago for ${assetType}: ${asset.name}`);
}
🛡️ SAFETY MECHANISMS ADDED
1. Duplicate Prevention
- Tracking keys prevent duplicate notifications
- Separate tracking for advance, due date, and overdue notifications
2. Data Validation
- All dates parsed and validated before processing
- Invalid events are skipped with logging
- Malformed data doesn't crash the system
3. Comprehensive Logging
// Maintenance Summary
debugLog(`[SUMMARY] Maintenance check completed for ${today}:`);
debugLog(` - Assets checked: ${totalChecked}`);
debugLog(` - Notifications sent successfully: ${successfulNotifications}`);
debugLog(` - Notifications failed: ${failedNotifications}`);
// Warranty Summary (NEW)
debugLog(`[SUMMARY] Warranty check completed for ${today}:`);
debugLog(` - Assets checked: ${totalChecked} (${assets.length} main assets, ${subAssets.length} components)`);
debugLog(` - Total warranties: ${totalWarranties}`);
debugLog(` - Notifications queued: ${notificationsToSend.length}`);
debugLog(` - Notifications sent successfully: ${successfulNotifications}`);
debugLog(` - Notifications failed: ${failedNotifications}`);
debugLog(` - Notification settings: 1M=${notify1Month}, 2W=${notify2Week}, 7D=${notify7Day}, 3D=${notify3Day}`);
🧪 TESTING RECOMMENDATIONS
1. Date Edge Cases
Test maintenance events with:
- February 29th (leap year)
- Month-end dates (Jan 31 + 1 month)
- Timezone transitions (DST changes)
- Invalid date formats
2. Server Downtime Scenarios
- Test overdue notifications work when server is down on due date
- Verify no duplicate notifications after restart
3. Data Validation
- Test with malformed maintenance event data
- Verify system continues processing other events when one fails
4. Timezone Testing
- Test with different timezone configurations
- Verify dates align correctly between frontend and backend
📋 DEPLOYMENT CHECKLIST
- Verify
TZenvironment variable is set correctly - Test maintenance notifications in staging environment
- Monitor logs for any date parsing warnings
- Verify existing maintenance tracking data migrates correctly
- Test both frequency-based and specific date events
- Confirm overdue notifications work as expected
🔍 MONITORING POINTS
Watch for these log messages after deployment:
Good Signs:
[SUMMARY] Maintenance check completed[SUMMARY] Warranty check completed[DEBUG] Maintenance tracking data saved successfullyMaintenance check completed: X/Y notifications sent successfullyWarranty check completed: X/Y notifications sent successfully
Warning Signs:
[WARNING] Invalid frequency unit[WARNING] Maintenance event missing nextDueDate[WARNING] Invalid warranty expiration date[WARNING] Secondary Warranty expired X days ago[ERROR] Failed to send maintenance notification[ERROR] Failed to send warranty notification
Critical Issues:
[ERROR] Date parsing failed[ERROR] Failed to save maintenance tracking data[ERROR] Exception while updating asset files[ERROR] Error processing asset[ERROR] Error processing sub-asset
The maintenance notification system is now robust, with proper timezone handling, comprehensive validation, error recovery, and safety mechanisms to ensure users never miss critical maintenance events.