- Add admin dashboard with sync controls and data browser - Implement RMM, Auvik, and Addigy organization mappings - Add chunked ticket sync with progress tracking - Implement entity sync service with rate limiting - Add analytics engine and performance optimizer - Create data browser for all PSA entities - Add navigation components and UI improvements - Implement background processing and sync services - Add comprehensive documentation and migration scripts - Update configuration items with multi-system support - Enhance contact management and purchase history - Add issue type assignment and LLM analyzer - Improve error handling and logging utilities
5.3 KiB
All Systems Inventory Display Implementation
Issue
The configuration items page was only showing devices from PSA (Autotask) and RMM (Datto RMM), but not displaying devices that exist ONLY in NMS (Auvik) or ARMM (Addigy). This violated the goals document requirement to show "the combination of inventories across all the systems."
Root Cause
The comparison logic in /app/api/rmm-devices/route.ts was:
- Adding RMM devices (matched or RMM-only)
- Adding Autotask devices (matched or Autotask-only)
- Matching Auvik and Addigy devices to existing Autotask devices
- BUT never adding unmatched Auvik-only or Addigy-only devices
Solution
Backend Changes (/app/api/rmm-devices/route.ts)
1. Added Unmatched Device Logic
After processing PSA and RMM devices, added logic to include devices that exist only in Auvik or Addigy:
// Track which Auvik and Addigy devices have been matched
const matchedAuvikIds = new Set<string>();
const matchedAddigyIds = new Set<string>();
comparison.forEach(item => {
if (item.auvikDevice?.id) matchedAuvikIds.add(item.auvikDevice.id);
if (item.addigyDevice?.agentid) matchedAddigyIds.add(item.addigyDevice.agentid);
});
// Add unmatched Auvik devices (NMS-only)
for (const auvikDevice of auvikDevices) {
if (!matchedAuvikIds.has(auvikDevice.id)) {
// Try to match with Addigy by serial number
let addigyMatch = addigyDevices.find(d =>
d['Serial Number']?.toLowerCase().trim() === auvikDevice.serialNumber?.toLowerCase().trim() &&
!matchedAddigyIds.has(d.agentid)
);
comparison.push({
auvikDevice: auvikDevice,
addigyDevice: addigyMatch,
status: 'rmm-only'
});
}
}
// Add unmatched Addigy devices (ARMM-only)
for (const addigyDevice of addigyDevices) {
if (!matchedAddigyIds.has(addigyDevice.agentid)) {
comparison.push({
addigyDevice: addigyDevice,
status: 'rmm-only'
});
}
}
2. Updated Sorting Logic
Enhanced device name sorting to check all four systems:
const aName = a.autotaskDevice?.referenceTitle ||
a.rmmDevice?.hostname ||
a.auvikDevice?.deviceName ||
a.addigyDevice?.['Device Name'] ||
'';
3. Added Stats for All Systems
Updated response to include counts for all four systems:
stats: {
totalRmm: rmmDevices.length,
totalAutotask: autotaskDevices.length,
totalAuvik: auvikDevices.length,
totalAddigy: addigyDevices.length,
matched: comparison.filter(c => c.status === 'matched').length,
autotaskOnly: comparison.filter(c => c.status === 'autotask-only').length,
rmmOnly: comparison.filter(c => c.status === 'rmm-only').length,
}
Frontend Changes (/app/configuration-items/page.tsx)
1. Updated Device Name Display
Modified table cells to show device names from any of the four systems:
{item.autotaskDevice?.referenceTitle ||
item.rmmDevice?.hostname ||
item.auvikDevice?.deviceName ||
item.addigyDevice?.['Device Name'] ||
'Unknown Device'}
2. Updated Serial Number Display
{item.autotaskDevice?.serialNumber ||
item.rmmDevice?.serialNumber ||
item.auvikDevice?.serialNumber ||
item.addigyDevice?.['Serial Number'] ||
'-'}
3. Updated IP Address Display
{item.autotaskDevice?.rmmDeviceAuditIPAddress ||
item.rmmDevice?.intIpAddress ||
item.auvikDevice?.ipAddresses?.[0] ||
item.addigyDevice?.['IP Address'] ||
'-'}
4. Updated Stats Display
Both the compact stats badge and detailed table header now show all four systems:
Compact: PSA: X | RMM: X | NMS: X | ARMM: X
Detailed: Individual counts for PSA, RMM, NMS, ARMM, plus Matched count
Matching Priority (Per Goals Document)
The system now properly implements the matching priority across all systems:
- Reference UID - PSA has reference to RMM device UID
- Serial Number - Primary matching across all systems
- MAC Address - Used for Auvik matching
- IP Address - Used for RMM matching
- Hostname - Used with client/site filter
Device Status Types
- matched - Device exists in PSA and at least one other system
- autotask-only - Device exists only in PSA (may have NMS/ARMM matches)
- rmm-only - Device exists in RMM, NMS, or ARMM but not in PSA
Benefits
- Complete Visibility - All devices from all four systems are now visible
- Better Asset Tracking - No devices are hidden from view
- Compliance with Goals - Fully implements the "combination of inventories" requirement
- Cross-System Matching - Auvik and Addigy devices can match each other even without PSA entry
- Accurate Counts - Stats show true device counts across all systems
Files Modified
/app/api/rmm-devices/route.ts- Backend comparison logic/app/configuration-items/page.tsx- Frontend display logic
Testing Recommendations
- Select a company with devices in all four systems
- Verify devices appear from PSA, RMM, NMS, and ARMM
- Check that stats show correct counts for each system
- Verify devices that exist only in Auvik or Addigy are displayed
- Confirm matching works across all system combinations
Related Documentation
/docs/configuration-item-goals.md- Original requirements/docs/fixes/configuration-items-table-improvements.md- UI improvements/docs/fixes/rmm-cache-invalidation-fix.md- Cache fix