# Phase 3: Network Devices Migration to machines Table

**Date:** 2025-11-10
**Status:** 📋 PLANNING
**Follows:** Phase 2 (PC Migration - Completed)

---

## Executive Summary

Consolidate all network infrastructure devices (servers, switches, cameras, access points, IDFs) into the unified `machines` table. This completes the infrastructure unification started in Phase 2 with PCs, creating a single source of truth for all physical assets except printers.

---

## Scope

### ✅ Migrate INTO machines Table:
- **Servers** → machinetypeid 30
- **Switches** → machinetypeid 31
- **Cameras** → machinetypeid 32
- **Access Points** → machinetypeid 33
- **IDFs** → machinetypeid 34
- **Routers** → machinetypeid 35 (if exists)
- **Firewalls** → machinetypeid 36 (if exists)

### ❌ Keep SEPARATE:
- **Printers** → Stay in `printers` table (unique fields, workflows, APIs)

---

## Why This Migration?

### Current Problems:
1. **Data Fragmentation:** Network devices scattered across 5+ tables
2. **Code Duplication:** Separate pages for each device type
3. **Relationship Limitations:** Can't relate servers to switches to cameras
4. **Query Complexity:** UNION queries to find all devices on a network
5. **Inconsistent UI/UX:** Different interfaces for similar devices

### After Migration:
1. ✅ **Single Source of Truth:** All infrastructure in `machines` table
2. ✅ **Unified Relationships:** Camera → Switch → IDF using `machinerelationships`
3. ✅ **Unified Communications:** All IPs in `communications` table
4. ✅ **Consistent UI:** One set of pages for all devices
5. ✅ **Powerful Queries:** Cross-device reports and topology mapping
6. ✅ **Better Compliance:** All devices tracked in one place

---

## Architecture

### Current Structure:
```
machines table
  ├── Equipment (machinetypeid 1-24, pctypeid IS NULL)
  └── PCs (machinetypeid 25-29, pctypeid IS NOT NULL)

servers table (separate)
switches table (separate)
cameras table (separate)
accesspoints table (separate)
idfs table (separate)

printers table (stays separate)
```

### Target Structure:
```
machines table
  ├── Equipment (machinetypeid 1-24, pctypeid IS NULL)
  ├── PCs (machinetypeid 25-29, pctypeid IS NOT NULL)
  └── Network Devices (machinetypeid 30-36, pctypeid IS NULL) ← NEW

printers table (stays separate - by design)
```

---

## New Machine Types (30-36)

```sql
INSERT INTO machinetypes (machinetypeid, machinetype, category, description, displayorder) VALUES
(30, 'Server', 'Network', 'Physical or virtual server', 30),
(31, 'Switch', 'Network', 'Network switch', 31),
(32, 'Camera', 'Network', 'IP camera or security camera', 32),
(33, 'Access Point', 'Network', 'Wireless access point', 33),
(34, 'IDF', 'Network', 'Intermediate Distribution Frame', 34),
(35, 'Router', 'Network', 'Network router', 35),
(36, 'Firewall', 'Network', 'Network firewall', 36);
```

---

## Filtering Strategy

```sql
-- All PCs
SELECT * FROM machines WHERE pctypeid IS NOT NULL;

-- All Equipment (CNC machines, mills, lathes, etc.)
SELECT * FROM machines WHERE pctypeid IS NULL AND machinetypeid BETWEEN 1 AND 24;

-- All Network Devices
SELECT * FROM machines WHERE pctypeid IS NULL AND machinetypeid BETWEEN 30 AND 36;

-- Specific device types
SELECT * FROM machines WHERE machinetypeid = 30; -- Servers
SELECT * FROM machines WHERE machinetypeid = 31; -- Switches
SELECT * FROM machines WHERE machinetypeid = 32; -- Cameras

-- All non-printer infrastructure
SELECT * FROM machines; -- Everything except printers
```

---

## Data Migration Mapping

### Servers Table → Machines
```
servers.serverid          → machines.machineid (new)
servers.modelid           → machines.modelnumberid
servers.serialnumber      → machines.serialnumber
servers.description       → machines.alias
servers.maptop            → machines.maptop
servers.mapleft           → machines.mapleft
servers.isactive          → machines.isactive
servers.ipaddress         → communications.address (comstypeid=1)
30 (constant)             → machines.machinetypeid
NULL                      → machines.pctypeid
'SERVER-{serverid}'       → machines.machinenumber (generated)
```

### Switches Table → Machines
```
switches.switchid         → machines.machineid (new)
switches.modelid          → machines.modelnumberid
switches.serialnumber     → machines.serialnumber
switches.description      → machines.alias
switches.maptop           → machines.maptop
switches.mapleft          → machines.mapleft
switches.isactive         → machines.isactive
switches.ipaddress        → communications.address (comstypeid=1)
31 (constant)             → machines.machinetypeid
NULL                      → machines.pctypeid
'SWITCH-{switchid}'       → machines.machinenumber (generated)
```

### Cameras Table → Machines
```
cameras.cameraid          → machines.machineid (new)
cameras.modelid           → machines.modelnumberid
cameras.serialnumber      → machines.serialnumber
cameras.description       → machines.alias
cameras.maptop            → machines.maptop
cameras.mapleft           → machines.mapleft
cameras.isactive          → machines.isactive
cameras.ipaddress         → communications.address (comstypeid=1)
32 (constant)             → machines.machinetypeid
NULL                      → machines.pctypeid
'CAMERA-{cameraid}'       → machines.machinenumber (generated)
```

### Access Points Table → Machines (if exists)
```
accesspoints.accesspointid → machines.machineid (new)
accesspoints.modelid       → machines.modelnumberid
accesspoints.serialnumber  → machines.serialnumber
accesspoints.description   → machines.alias
accesspoints.maptop        → machines.maptop
accesspoints.mapleft       → machines.mapleft
accesspoints.isactive      → machines.isactive
accesspoints.ipaddress     → communications.address (comstypeid=1)
33 (constant)              → machines.machinetypeid
NULL                       → machines.pctypeid
'AP-{accesspointid}'       → machines.machinenumber (generated)
```

### IDFs Table → Machines (if exists)
```
idfs.idfid                → machines.machineid (new)
idfs.name                 → machines.machinenumber
idfs.description          → machines.alias
idfs.maptop               → machines.maptop
idfs.mapleft              → machines.mapleft
idfs.isactive             → machines.isactive
34 (constant)             → machines.machinetypeid
NULL                      → machines.pctypeid
```

---

## New Relationship Types

```sql
INSERT INTO relationshiptypes (relationshiptype, description, isbidirectional) VALUES
-- Existing relationships
('Dualpath', 'Machines sharing the same controller', 1),
('Controlled By', 'Machine controlled by PC', 0),
('Controls', 'PC controls this machine', 0),

-- New network relationships
('Connected To', 'Device physically connected to infrastructure', 0),
('Powered By', 'Device powered by this power source', 0),
('Mounted In', 'Device mounted in rack/cabinet', 0),
('Feeds Video To', 'Camera feeds video to this server/NVR', 0),
('Provides Network', 'Infrastructure provides network to device', 0);
```

---

## Migration Scripts Structure

```
/home/camp/projects/windows/shopdb/sql/migration_phase3/
├── 01_create_network_machinetypes.sql
├── 02_migrate_servers_to_machines.sql
├── 03_migrate_switches_to_machines.sql
├── 04_migrate_cameras_to_machines.sql
├── 05_migrate_accesspoints_to_machines.sql
├── 06_migrate_idfs_to_machines.sql
├── 07_migrate_network_communications.sql
├── 08_create_network_relationships.sql
├── 09_update_views_for_network_devices.sql
├── 10_update_vendor_flags.sql
├── VERIFY_PHASE3_MIGRATION.sql
├── RUN_ALL_PHASE3_SCRIPTS.sql
└── ROLLBACK_PHASE3.sql
```

---

## Migration Order

### Pre-Migration:
1. ✅ **Backup database**
2. ✅ **Verify Phase 2 is stable**
3. ✅ **Document current table structures**
4. ✅ **Count records in each table**

### Migration Steps:
1. **Create new machinetypes** (30-36)
2. **Migrate servers** → machines + communications
3. **Migrate switches** → machines + communications
4. **Migrate cameras** → machines + communications
5. **Migrate access points** → machines + communications (if exists)
6. **Migrate IDFs** → machines (if exists)
7. **Create network relationships** (camera → switch → IDF)
8. **Update vendor flags** (isserver, isswitch, etc.)
9. **Update views** (create vw_network_devices if needed)
10. **Verify data integrity**

### Post-Migration:
1. **Run verification queries**
2. **Test UI pages**
3. **Update code references**
4. **Keep old tables temporarily** (for rollback safety)
5. **Monitor for issues**
6. **Drop old tables after 30 days** (if stable)

---

## Code Updates Required

### Pages to Update:
1. ✅ **displaymachines.asp** - Add filter tabs for network devices
2. ✅ **displaymachine.asp** - Already supports all types via machinetypeid
3. ✅ **machine_edit.asp** - Already supports all types
4. ✅ **adddevice.asp** - Update to include network device types

### Pages to Deprecate:
1. ❌ **displayservers.asp** → Redirect to displaymachines.asp?type=server
2. ❌ **displayswitches.asp** → Redirect to displaymachines.asp?type=switch
3. ❌ **displaycameras.asp** → Redirect to displaymachines.asp?type=camera
4. ❌ **network_devices.asp** → Redirect to displaymachines.asp?category=network

### Views to Update:
```sql
-- Update or create
CREATE OR REPLACE VIEW vw_all_infrastructure AS
SELECT
    m.machineid,
    m.machinenumber,
    m.alias,
    mt.machinetype,
    mt.category,
    mo.modelnumber,
    v.vendor,
    c.address AS ipaddress,
    CASE
        WHEN m.pctypeid IS NOT NULL THEN 'PC'
        WHEN mt.category = 'Network' THEN 'Network Device'
        ELSE 'Equipment'
    END AS device_category
FROM machines m
LEFT JOIN machinetypes mt ON m.machinetypeid = mt.machinetypeid
LEFT JOIN models mo ON m.modelnumberid = mo.modelnumberid
LEFT JOIN vendors v ON mo.vendorid = v.vendorid
LEFT JOIN communications c ON m.machineid = c.machineid AND c.isprimary = 1
WHERE m.isactive = 1;
```

---

## Verification Queries

### Record Counts
```sql
-- Before migration
SELECT 'servers' AS table_name, COUNT(*) AS count FROM servers
UNION ALL
SELECT 'switches', COUNT(*) FROM switches
UNION ALL
SELECT 'cameras', COUNT(*) FROM cameras
UNION ALL
SELECT 'accesspoints', COUNT(*) FROM accesspoints
UNION ALL
SELECT 'idfs', COUNT(*) FROM idfs;

-- After migration
SELECT
    mt.machinetype,
    COUNT(*) AS count
FROM machines m
JOIN machinetypes mt ON m.machinetypeid = mt.machinetypeid
WHERE mt.machinetypeid BETWEEN 30 AND 36
GROUP BY mt.machinetype;
```

### Data Integrity
```sql
-- Verify all network devices have machine types
SELECT COUNT(*) FROM machines
WHERE machinetypeid BETWEEN 30 AND 36
AND machinetypeid IS NULL;
-- Should be 0

-- Verify all network devices have pctypeid = NULL
SELECT COUNT(*) FROM machines
WHERE machinetypeid BETWEEN 30 AND 36
AND pctypeid IS NOT NULL;
-- Should be 0

-- Verify IP addresses migrated
SELECT
    mt.machinetype,
    COUNT(DISTINCT m.machineid) AS total_devices,
    COUNT(DISTINCT c.machineid) AS devices_with_ip
FROM machines m
JOIN machinetypes mt ON m.machinetypeid = mt.machinetypeid
LEFT JOIN communications c ON m.machineid = c.machineid AND c.comstypeid = 1
WHERE mt.machinetypeid BETWEEN 30 AND 36
GROUP BY mt.machinetype;
```

---

## Rollback Plan

### If Issues Found:
1. **Stop immediately**
2. **Run ROLLBACK_PHASE3.sql**
3. **Verify old tables intact**
4. **Restore from backup if needed**
5. **Review errors**
6. **Fix and retry**

### Rollback Script (High-Level):
```sql
-- Delete migrated network devices from machines
DELETE FROM machines WHERE machinetypeid BETWEEN 30 AND 36;

-- Delete migrated communications
DELETE FROM communications WHERE machineid NOT IN (SELECT machineid FROM machines);

-- Delete new relationship types
DELETE FROM relationshiptypes WHERE relationshiptypeid > 5;

-- Delete new machinetypes
DELETE FROM machinetypes WHERE machinetypeid BETWEEN 30 AND 36;

-- Verify old tables still have data
SELECT COUNT(*) FROM servers;
SELECT COUNT(*) FROM switches;
SELECT COUNT(*) FROM cameras;
```

---

## Success Criteria

### ✅ Migration Successful If:
1. All records migrated (counts match)
2. All IP addresses migrated to communications
3. All relationships preserved
4. No NULL values in required fields
5. UI pages display correctly
6. Queries perform well
7. No data loss
8. Rollback tested and works

---

## Timeline Estimate

- **Planning & Script Creation:** 2-3 hours
- **Testing on Dev/Backup:** 1-2 hours
- **Production Migration:** 30-45 minutes
- **Verification:** 1 hour
- **Code Updates:** 3-4 hours
- **Testing & Bug Fixes:** 2-3 hours

**Total:** ~10-15 hours of work

---

## Risk Assessment

### Low Risk:
- ✅ Pattern proven with Phase 2 PC migration
- ✅ Can be rolled back easily
- ✅ Old tables kept temporarily
- ✅ Comprehensive verification

### Medium Risk:
- ⚠️ Multiple tables being migrated
- ⚠️ Code references to update
- ⚠️ Testing required for all device types

### Mitigation:
- ✅ **Test on backup database first**
- ✅ **Migrate one device type at a time**
- ✅ **Verify after each migration**
- ✅ **Keep old tables for 30 days**
- ✅ **Update code incrementally**

---

## Benefits After Completion

### Immediate:
1. ✅ Single query for all infrastructure
2. ✅ Unified relationship management
3. ✅ Camera → IDF relationships work
4. ✅ Consistent UI across all devices
5. ✅ Better network topology visibility

### Long-Term:
1. ✅ Easier to add new device types
2. ✅ Less code duplication
3. ✅ Better reporting capabilities
4. ✅ Simplified maintenance
5. ✅ CMDB-style asset management
6. ✅ Better compliance tracking

---

## Next Steps

1. ✅ **Create migration SQL scripts**
2. ✅ **Create verification scripts**
3. ✅ **Create rollback scripts**
4. ✅ **Test on backup database**
5. ✅ **Review and approve plan**
6. ✅ **Schedule migration window**
7. ✅ **Execute migration**
8. ✅ **Update code**
9. ✅ **Monitor and verify**

---

**Status:** Ready for script creation
**Approval Required:** Yes
**Backup Required:** Yes
**Estimated Duration:** 30-45 minutes (migration only)

---

## Questions to Answer Before Migration

1. ✅ Do accesspoints and idfs tables exist?
2. ✅ Are there any custom fields in device tables we need to preserve?
3. ✅ Are there any foreign key constraints to old tables?
4. ✅ What's the maintenance window schedule?
5. ✅ Should we create camera → IDF relationships during migration or manually after?

---

**Ready to proceed with script creation!**
