# Complete Cache Invalidation for All System Mappings

## Issue
Company 29683395 (TK Plastics) was not showing Addigy (ARMM) devices even though:
- 3 Addigy org mappings existed in the database
- The API code was correct to fetch Addigy devices
- The cache was returning stale data from before the mappings were added

## Root Cause
The cache key only included RMM mapping count:
```
rmm-devices:29683395:active:mappings-2
```

When Addigy or Auvik mappings were added, the cache key didn't change, so the system continued serving cached data with 0 Addigy/Auvik devices.

## Database Verification

### Company 29683395 Mappings:
- **RMM Sites**: 2 mappings
  - TK Plastics (612f6b1f-9228-4e2a-8e63-f0ec5d0b6aaa)
  - TK Plastics - Kaercher (aba39a7b-d9b3-4eff-88e4-4d0182d478cb)

- **Auvik Tenants**: 1 mapping
  - tkplastics (1228237269652810493)

- **Addigy Orgs**: 3 mappings
  - TK Plastics (b194ffe7-c354-4cb0-a5e5-c99876729b4b)
  - TK - iPads (393f67b0-5449-41b4-a5f2-f72de849c5d5)
  - TK - Macs (36f89454-6dbf-4c03-8843-3dfc34b9534f)

## Solution

Updated the cache key to include mapping counts for ALL three external systems:

### Before:
```typescript
const cacheKey = `rmm-devices:${companyId}:${activeFilter}:mappings-${mappingCount}`;
```

### After:
```typescript
const cacheKey = `rmm-devices:${companyId}:${activeFilter}:rmm-${rmmMappingCount}:auvik-${auvikMappingCount}:addigy-${addigyMappingCount}`;
```

### Implementation:
```typescript
// Get mapping counts to include in cache key (so cache invalidates when mappings change)
let rmmMappingCount = 0;
let auvikMappingCount = 0;
let addigyMappingCount = 0;

if (companyId) {
  // RMM site mappings
  const rmmMappingsResult = await pool.query(
    'SELECT COUNT(*) as count FROM rmm_site_mappings WHERE company_id = $1',
    [parseInt(companyId)]
  );
  rmmMappingCount = parseInt(rmmMappingsResult.rows[0]?.count || '0');
  
  // Auvik tenant mappings
  const auvikMappingsResult = await pool.query(
    'SELECT COUNT(*) as count FROM auvik_tenant_mappings WHERE autotask_company_id = $1',
    [parseInt(companyId)]
  );
  auvikMappingCount = parseInt(auvikMappingsResult.rows[0]?.count || '0');
  
  // Addigy org mappings
  const addigyMappingsResult = await pool.query(
    'SELECT COUNT(*) as count FROM addigy_org_mappings WHERE autotask_company_id = $1',
    [parseInt(companyId)]
  );
  addigyMappingCount = parseInt(addigyMappingsResult.rows[0]?.count || '0');
}
```

## Cache Key Examples

### For Company 29683395:
- **Old key**: `rmm-devices:29683395:active:mappings-2`
- **New key**: `rmm-devices:29683395:active:rmm-2:auvik-1:addigy-3`

### Cache Invalidation Scenarios:
1. **Add RMM site mapping**: `rmm-2` → `rmm-3` (cache invalidated)
2. **Add Auvik tenant mapping**: `auvik-1` → `auvik-2` (cache invalidated)
3. **Add Addigy org mapping**: `addigy-3` → `addigy-4` (cache invalidated)
4. **Remove any mapping**: Count decreases, cache invalidated

## Benefits

1. **Automatic Cache Invalidation**: Cache automatically expires when ANY system mapping changes
2. **No Manual Cache Clearing**: No need to manually clear cache or use skipCache parameter
3. **Accurate Data**: Users always see current device data after mapping changes
4. **System Consistency**: All three external systems (RMM, NMS, ARMM) are treated equally

## Files Modified
- `/app/api/rmm-devices/route.ts` - Updated cache key generation logic

## Testing
After deploying:
1. The cache key for company 29683395 will change from `rmm-devices:29683395:active:mappings-2` to `rmm-devices:29683395:active:rmm-2:auvik-1:addigy-3`
2. This will trigger a fresh API call
3. Addigy devices from all 3 mapped organizations will be fetched and displayed
4. Future mapping changes will automatically invalidate the cache

## Related Documentation
- `/docs/fixes/rmm-cache-invalidation-fix.md` - Initial RMM cache fix
- `/docs/fixes/all-systems-inventory-display.md` - All systems display implementation
- `/docs/rmm-multi-site-integration.md` - RMM multi-site architecture
