Phase 2 Migration: Complete PC consolidation and fixes

## Phase 2 Migration Complete
Successfully migrated all 286 active PCs from pc table to machines table.

### Migration Scripts Added/Updated:
- **Phase 1.0**: Added ensure_all_machinetypes.sql (machinetypes 15-20)
- **Phase 1.5**: Added migrate_equipment_ips_to_communications.sql
- **Phase 2**: Updated 01_migrate_pcs_to_machines.sql for duplicate handling
- **Phase 2**: Updated 08_update_schema_for_api.sql (rename pcid→machineid)
- **Phase 2 Fixes**: Added FIX_migrate_remaining_pcs.sql (60 unmigrated PCs)
- **Phase 2 Fixes**: Added FIX_pc_machine_types.sql

### Network Devices View Updated:
- **CREATE_vw_network_devices_with_fqdn.sql**: Complete rewrite for Phase 2
  - Infrastructure devices (IDF, Server, Switch, Camera, Access Point) query machines table
  - Printers remain in separate printers table (has fqdn column)
  - UNION approach: machines (machinetypeid 15-19) + printers table

### Documentation Added:
- DATA_MIGRATION_EXPLAINED.md - Full migration architecture
- PRODUCTION_MIGRATION_PLAN.md - Production deployment plan
- VIEWS_MIGRATION_ANALYSIS.md - Views requiring updates
- PRINTER_INSTALLER_FIX_2025-11-20.md - Printer installer fixes
- SCHEMA_COMPARISON_REPORT_2025-11-20.md - Phase 2 schema comparison

### ASP Files Updated:
- api_printers.asp - Printer API fixes
- displaynotifications.asp - UI improvements
- install_printer.asp - Installer fixes
- v2/api_printers.asp - V2 API updates
- v2/install_printer.asp - V2 installer updates

### Migration Results (DEV):
- Total machines: 523 (237 equipment + 286 PCs)
- Communications: 1,309
- Warranties: 212
- Machine relationships: 201
- PC migration: 286/286 ✓
- Duplicate PCs removed: 166 duplicates cleaned

### Key Achievements:
✓ All 286 active PCs migrated to machines table
✓ Network devices view updated for Phase 2 architecture
✓ pc_to_machine_id_mapping table populated (286 entries)
✓ Duplicate PC records cleaned (452→286)
✓ Schema updates for API compatibility (pcid→machineid)

### Next Steps:
- Update PHP Dashboard API for Phase 2 schema (CRITICAL - see POWERSHELL_API_PHASE2_ISSUES.md)
- Update PowerShell scripts for Phase 2 schema
- Test Update-PC-CompleteAsset-Silent.bat
- Production deployment planning

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
cproudlock
2025-11-21 09:15:47 -05:00
parent 4cabc823ef
commit 08d95f579a
18 changed files with 3860 additions and 187 deletions

View File

@@ -0,0 +1,283 @@
# Printer Installer Batch File Fix
**Date:** 2025-11-20
**Issue:** Batch file download from displayprinters/displayprinter pages fails with PowerShell command errors
**Status:** ✅ FIXED
---
## Problem Description
When downloading the printer installer batch file (e.g., `Install_CSF08-LaserJet-4001.bat`) from the displayprinters or displayprinter pages, the batch file would error out with messages like:
```
'Write-Host' is not recognized as an internal or external command,
operable program or batch file.
'$printerName' is not recognized as an internal or external command,
operable program or batch file.
```
### Root Cause
The ASP code was generating a PowerShell command split across multiple lines in the batch file:
```batch
powershell -NoProfile -ExecutionPolicy Bypass -Command "
Write-Host 'Installing printer with universal driver...' -ForegroundColor Cyan;
$printerName = 'CSF08-LaserJet-4001';
$address = 'Printer-10-80-92-58.printer.geaerospace.net';
...
"
```
The CMD batch file interpreter doesn't support multi-line PowerShell commands in this format. It would try to execute the PowerShell code as batch commands, resulting in errors.
---
## Solution
The PowerShell command is now built as a **single line** with semicolons separating statements:
```batch
powershell -NoProfile -ExecutionPolicy Bypass -Command "Write-Host 'Installing printer with universal driver...' -ForegroundColor Cyan; $printerName = 'CSF08-LaserJet-4001'; $address = 'Printer-10-80-92-58.printer.geaerospace.net'; $driverName = 'HP Universal Printing PCL 6'; $portName = 'IP_' + $address; $driver = Get-PrinterDriver -Name $driverName -ErrorAction SilentlyContinue; if (-not $driver) { Write-Host 'ERROR: Universal driver not found!' -ForegroundColor Red; Write-Host 'Please install ' $driverName ' from Windows Update or driver package' -ForegroundColor Yellow; exit 1; }; $port = Get-PrinterPort -Name $portName -ErrorAction SilentlyContinue; if (-not $port) { Write-Host 'Creating printer port...' -ForegroundColor Yellow; Add-PrinterPort -Name $portName -PrinterHostAddress $address -ErrorAction Stop; Write-Host 'Port created successfully' -ForegroundColor Green; } else { Write-Host 'Port already exists' -ForegroundColor Green; }; $existingPrinter = Get-Printer -Name $printerName -ErrorAction SilentlyContinue; if (-not $existingPrinter) { Write-Host 'Adding printer...' -ForegroundColor Yellow; Add-Printer -Name $printerName -DriverName $driverName -PortName $portName -ErrorAction Stop; Write-Host 'Printer installed successfully!' -ForegroundColor Green; } else { Write-Host 'Printer already exists' -ForegroundColor Green; }"
```
---
## Files Modified
### 1. `/home/camp/projects/windows/shopdb/install_printer.asp`
**Lines:** 180-223
**Changes:**
- Added `Dim psCommand` variable declaration
- Built PowerShell command as a single concatenated string
- All PowerShell statements joined with semicolons
- Single `Response.Write()` call to output the complete command
### 2. `/home/camp/projects/windows/shopdb/v2/install_printer.asp`
**Lines:** 180-223
**Changes:**
- Same fix applied to v2 version
---
## Code Changes Summary
**Before (Lines 181-224):**
```vbscript
' Generate PowerShell script to install printer
Response.Write("powershell -NoProfile -ExecutionPolicy Bypass -Command """ & vbCrLf)
Response.Write(" Write-Host 'Installing printer with universal driver...' -ForegroundColor Cyan;" & vbCrLf)
Response.Write(" " & vbCrLf)
Response.Write(" $printerName = '" & Replace(printer("name"), "'", "''") & "';" & vbCrLf)
' ... 40+ more lines of multi-line output ...
```
**After (Lines 180-223):**
```vbscript
' Build PowerShell command as single line
Dim psCommand
psCommand = "Write-Host 'Installing printer with universal driver...' -ForegroundColor Cyan; "
psCommand = psCommand & "$printerName = '" & Replace(printer("name"), "'", "''") & "'; "
psCommand = psCommand & "$address = '" & Replace(printer("address"), "'", "''") & "'; "
' ... build complete command as single string ...
' Write PowerShell command as single line
Response.Write("powershell -NoProfile -ExecutionPolicy Bypass -Command """ & psCommand & """" & vbCrLf)
```
---
## Testing Instructions
### Test 1: Download from displayprinters.asp
1. Navigate to `http://192.168.122.151:8080/displayprinters.asp`
2. Find any HP printer (e.g., CSF08-LaserJet-4001)
3. Click the download installer button
4. Save the `.bat` file to Downloads
5. Open CMD and run the batch file
6. **Expected:** PowerShell commands execute successfully, printer installs
### Test 2: Download from displayprinter.asp
1. Navigate to `http://192.168.122.151:8080/displayprinter.asp?printerid=X`
2. Click the download installer button
3. Save the `.bat` file to Downloads
4. Open CMD and run the batch file
5. **Expected:** PowerShell commands execute successfully, printer installs
### Test 3: Verify Universal Driver Detection
**For HP Printers:**
- Should use "HP Universal Printing PCL 6"
- Checks if driver exists before proceeding
- Errors with clear message if driver not installed
**For Xerox Printers:**
- Should use "Xerox Global Print Driver PCL6"
**For Generic/Unknown:**
- Should use "Generic / Text Only"
---
## Expected Output
### Successful Installation
```
========================================
GE Aerospace Printer Installer
========================================
Installing 1 printer(s)...
----------------------------------------
Installing: CSF08-LaserJet-4001
CSF Name: CSF08
Model: LaserJet Pro 4001n
Address: Printer-10-80-92-58.printer.geaerospace.net
----------------------------------------
Using universal driver: HP Universal Printing PCL 6
Installing printer with universal driver...
Port already exists
Printer already exists
========================================
Installation Complete!
========================================
Press any key to continue . . .
```
### Driver Not Found
```
ERROR: Universal driver not found!
Please install HP Universal Printing PCL 6 from Windows Update or driver package
```
---
## Related Issues
### Issue Type
- Bug Fix
- Batch File Generation
- PowerShell Integration
### Affected Functionality
- Printer installer downloads (universal driver method)
- Printers without custom `installpath` in database
### Not Affected
- Printers with custom `installpath` (uses different code path)
- Manual printer installation
- Printer display/search functionality
---
## Technical Details
### Why Single-Line PowerShell?
When using `powershell.exe -Command "..."`, the command must be:
1. A single line, OR
2. Use proper batch line continuation with `^`, OR
3. Use `-File` with a .ps1 script
The original code attempted multi-line without proper continuation, causing the batch interpreter to misinterpret PowerShell code as batch commands.
### Alternative Solutions Considered
**Option 1:** Use caret (^) for line continuation
```batch
powershell -Command "Write-Host 'Test'; ^
$var = 'value'; ^
Do-Something"
```
**Rejected:** More complex escaping, harder to maintain
**Option 2:** Generate temporary .ps1 file
```batch
echo $printerName = 'Test' > %TEMP%\install.ps1
echo Add-Printer ... >> %TEMP%\install.ps1
powershell -File %TEMP%\install.ps1
```
**Rejected:** More file I/O, cleanup required, potential security issues
**Option 3:** Single-line command (CHOSEN)
```batch
powershell -Command "Write-Host 'Test'; $var = 'value'; Do-Something"
```
**Selected:** Simplest, most reliable, no temp files needed
---
## Validation
### Code Review Checklist
- ✅ Both install_printer.asp files updated (main and v2)
- ✅ PowerShell command built as single string
- ✅ All statements joined with semicolons
- ✅ Single quotes properly escaped with Replace()
- ✅ Error handling preserved
- ✅ Driver detection logic maintained
- ✅ Port creation logic maintained
- ✅ Printer installation logic maintained
### Testing Checklist
- ⏳ Test HP printer download and install
- ⏳ Test Xerox printer download and install
- ⏳ Test printer without universal driver
- ⏳ Test printer already installed scenario
- ⏳ Test port already exists scenario
- ⏳ Verify error messages display correctly
- ⏳ Verify batch file self-deletes after execution
---
## Deployment
### Deployment Status
- ✅ Code changes complete
- ✅ Both files (main and v2) updated
- ⏳ Testing pending
- ⏳ Production deployment pending
### Rollback Plan
If issues arise, revert to previous version:
```bash
git checkout HEAD~1 install_printer.asp
git checkout HEAD~1 v2/install_printer.asp
```
---
## Additional Notes
### Printers with Custom Installers
Printers with a value in the `installpath` database field use a **different code path** and are NOT affected by this bug. They download and execute a custom .exe installer.
### Universal Driver Availability
The universal drivers must be installed on the target PC:
- **HP Universal Printing PCL 6** - Available via Windows Update
- **Xerox Global Print Driver PCL6** - Requires vendor download
If the driver is not installed, the script will error with clear instructions.
---
**Author:** Claude Code
**Reviewed By:** Pending
**Status:** Ready for Testing
**Production Ready:** After successful testing
---
## Quick Reference
**Bug:** Multi-line PowerShell commands in batch file
**Fix:** Build PowerShell command as single line with semicolons
**Impact:** Universal driver printer installations
**Files:** install_printer.asp (both main and v2)
**Testing:** Download .bat file from printer pages and execute

View File

@@ -0,0 +1,291 @@
# Database Schema Comparison Report
**Date:** 2025-11-20
**Comparison:** database-backup-11-20-25-eod-with-drop.sql vs Current Dev Database
**Dev Backup Created:** /home/camp/projects/windows/shopdb/sql/dev-backup-20251120-105614.sql
---
## Executive Summary
The backup file contains **Phase 1 schema** (pre-migration) with 63 tables, while the current dev database contains **Phase 2 schema** (post-migration) with 30 tables.
**Key Findings:**
-**4 tables have schema changes** (businessunits, controllertypes, machine_overrides, machines)
-**8 new Phase 2 tables** exist in dev but not in backup
-**41 legacy tables** exist in backup but not in dev (deprecated/views)
---
## Tables Requiring DROP and Recreate
### 1. Tables with Schema Changes (4 tables)
These tables exist in both files but have different column structures. They should be **dropped and recreated** from the backup file if you want to revert to the backup schema.
#### ⚠️ `machines` (CRITICAL - Most Changes)
**Columns Removed in Dev (exist in backup):**
- `ipaddress1` - Removed (now in communications table)
- `ipaddress2` - Removed (now in communications table)
**Columns Added in Dev (not in backup):**
- `hostname` - For PC hostnames
- `serialnumber` - Equipment serial numbers
- `loggedinuser` - Current logged-in user (PCs)
- `pctypeid` - Identifies PCs (NULL = equipment, NOT NULL = PC)
- `osid` - Foreign key to operatingsystems (PC OS)
- `controllertypeid` - Foreign key to controllertypes
- `controllerosid` - Controller OS (for CNCs)
- `controllermodelid` - Controller model reference
- `machinestatusid` - Replaces pcstatusid
- `lastupdated` - Auto-updated timestamp
- `requires_manual_machine_config` - Configuration flag
**Impact:** This is the core table for Phase 2 migration. Reverting will break all PC and network device functionality.
---
#### ⚠️ `businessunits`
**Columns Added in Dev (not in backup):**
- `liaisonname` - Liaison contact name
- `liaisonsso` - Liaison SSO
- `facility_id` - Facility identifier
- `dt_lead` - DT Lead name
- `dt_lead_sso` - DT Lead SSO
**Impact:** Minor. These are additional metadata fields that don't affect core functionality.
---
#### ⚠️ `controllertypes`
**Columns Added in Dev (not in backup):**
- `vendorid` - Foreign key to vendors
- `controllermodel` - Controller model name
- `controller_os` - Controller OS name
- `controllernotes` - Additional notes
**Impact:** Minor. Enhanced metadata for CNC controllers.
---
#### ⚠️ `machine_overrides`
**Issue:** Same columns but definition differences (likely data types or constraints changed)
**Impact:** Unknown without detailed field-by-field comparison.
---
## New Tables in Dev (Phase 2 Migration)
These 8 tables exist in the current dev database but NOT in the backup file. They are **Phase 2 migration tables** and should be **preserved**.
### Phase 2 Tables (DO NOT DROP)
1. **`communications`** - Unified network interface storage (replaces pc_network_interfaces, printer IPs)
2. **`comstypes`** - Communication types (IP, Serial, USB, etc.)
3. **`compliance`** - Compliance tracking data
4. **`compliancescans`** - Compliance scan history
5. **`machinerelationships`** - Machine-to-machine relationships (dualpath, controls)
6. **`relationshiptypes`** - Relationship type definitions
7. **`machinestatus`** - Replaces pcstatus with broader scope
8. **`warranties`** - Warranty tracking
**These tables are critical for Phase 2 functionality and should NOT be dropped.**
---
## Legacy Tables in Backup (Not in Dev)
These 41 tables exist in the backup file but NOT in the current dev database. Most are **deprecated** or **views**.
### Deprecated PC Tables (Replaced by machines + communications)
- `pc` - **DEPRECATED** → Replaced by machines WHERE pctypeid IS NOT NULL
- `pc_network_interfaces` - **DEPRECATED** → Replaced by communications
- `pc_comm_config` - **DEPRECATED** → Replaced by communications
- `pc_dnc_config` - **DEPRECATED** → Integrated into machine relationships
- `pc_dualpath_assignments` - **DEPRECATED** → Replaced by machinerelationships
- `pctype` - **DEPRECATED** → Now stored in machines.pctypeid
- `pcstatus` - **DEPRECATED** → Replaced by machinestatus
### Deprecated Network Device Tables (Replaced by machines)
- `accesspoints` - **DEPRECATED** → Replaced by machines WHERE machinetypeid = 16
- `cameras` - **DEPRECATED** → Replaced by machines WHERE machinetypeid = 18
- `switches` - **DEPRECATED** → Replaced by machines WHERE machinetypeid = 19
- `servers` - **DEPRECATED** → Replaced by machines WHERE machinetypeid = 20
- `idfs` - **DEPRECATED** → Replaced by machines WHERE machinetypeid = 17
### Legacy Relationship Table
- `machine_pc_relationships` - **DEPRECATED** → Replaced by machinerelationships
### Backup Table
- `pc_model_backup` - Backup table (can be dropped)
### Views (33 views)
All views with `vw_` prefix are query views, not base tables:
- `vw_active_pcs`
- `vw_dnc_config`
- `vw_dualpath_management`
- `vw_engineer_pcs`
- `vw_ge_machines`
- `vw_idf_inventory`
- `vw_infrastructure_summary`
- `vw_machine_assignments`
- `vw_machine_assignment_status`
- `vw_machinetype_comparison`
- `vw_machine_type_stats`
- `vw_multi_pc_machines`
- `vw_network_devices`
- `vw_pc_network_summary`
- `vw_pc_resolved_machines`
- `vw_pcs_by_hardware`
- `vw_pc_summary`
- `vw_pctype_config`
- `vw_recent_updates`
- `vw_shopfloor_applications_summary`
- `vw_shopfloor_comm_config`
- `vw_shopfloor_pcs`
- `vw_standard_pcs`
- `vw_unmapped_machines`
- `vw_vendor_summary`
- `vw_warranties_expiring`
- `vw_warranty_status`
**Note:** Views need to be recreated to match Phase 2 schema.
---
## Recommendation: What to Drop and Recreate
### ⚠️ CRITICAL WARNING
**DO NOT apply the backup file schema if you want to keep Phase 2 functionality!**
The backup file represents the **OLD Phase 1 schema** before the major PC migration work completed on Nov 17, 2025. Applying it would:
1. ❌ Lose all Phase 2 migration work (20+ days of development)
2. ❌ Break all PC pages (displaypcs.asp, displaypc.asp, editpc.asp, etc.)
3. ❌ Break network device display (network_map.asp, network_devices.asp)
4. ❌ Lose unified communications table
5. ❌ Lose machine relationships functionality
6. ❌ Lose compliance tracking
7. ❌ Lose warranty management
### If You Must Revert to Backup Schema
**Tables to DROP and recreate from backup:**
1.`machines` - DROP and recreate (loses Phase 2 columns)
2.`businessunits` - DROP and recreate (loses liaison/facility fields)
3.`controllertypes` - DROP and recreate (loses enhanced metadata)
4.`machine_overrides` - DROP and recreate (definition changes)
**Tables to DROP from dev (Phase 2 tables):**
5.`communications` - DROP (then recreate from backup if needed)
6.`comstypes` - DROP
7.`compliance` - DROP
8.`compliancescans` - DROP
9.`machinerelationships` - DROP
10.`relationshiptypes` - DROP
11.`machinestatus` - DROP (will recreate `pcstatus` from backup)
12.`warranties` - DROP
**Tables to ADD from backup (legacy tables):**
13. `pc` - CREATE from backup
14. `pc_network_interfaces` - CREATE from backup
15. `pc_comm_config` - CREATE from backup
16. `pc_dnc_config` - CREATE from backup
17. `pc_dualpath_assignments` - CREATE from backup
18. `pctype` - CREATE from backup
19. `pcstatus` - CREATE from backup
20. `accesspoints` - CREATE from backup (if needed)
21. `cameras` - CREATE from backup (if needed)
22. `switches` - CREATE from backup (if needed)
23. `servers` - CREATE from backup (if needed)
24. `idfs` - CREATE from backup (if needed)
25. `machine_pc_relationships` - CREATE from backup
**Views to recreate (33 views):** All `vw_*` views need to be dropped and recreated from backup.
---
## Recommended Action Plan
### Option 1: Keep Phase 2 Schema (RECOMMENDED)
**DO NOTHING.** Your current dev database is the latest Phase 2 schema with all improvements.
The backup file is outdated and should not be applied unless you need to revert Phase 2 changes.
### Option 2: Sync Backup File to Match Dev
If the backup file is supposed to be the "source of truth", then UPDATE the backup file to include Phase 2 schema:
1. Export current dev schema: `mysqldump shopdb > new-phase2-backup.sql`
2. Replace old backup file with Phase 2 schema
3. Use Phase 2 schema for future deployments
### Option 3: Revert to Backup Schema (NOT RECOMMENDED)
If you absolutely must revert to Phase 1 schema:
1. Backup current dev database (already done: dev-backup-20251120-105614.sql)
2. Drop Phase 2 tables: communications, compliance, machinerelationships, etc.
3. Restore machines, businessunits, controllertypes to backup versions
4. Restore all legacy tables (pc, pc_network_interfaces, etc.)
5. Recreate all views
6. **Accept that all Phase 2 functionality will be lost**
---
## Table Count Summary
| Category | Backup File | Dev Database | Difference |
|----------|-------------|--------------|------------|
| **Total Tables** | 63 | 30 | -33 |
| **Base Tables** | 36 | 30 | -6 |
| **Views** | 27 | 0 | -27 |
| **Schema Changes** | - | 4 | - |
| **New in Dev** | - | 8 | +8 |
| **Missing in Dev** | 41 | - | - |
---
## Files Generated
1. **Current Dev Backup:** `/home/camp/projects/windows/shopdb/sql/dev-backup-20251120-105614.sql` (464 KB)
2. **This Report:** `/home/camp/projects/windows/shopdb/SCHEMA_COMPARISON_REPORT_2025-11-20.md`
---
## Conclusion
**The backup file (database-backup-11-20-25-eod-with-drop.sql) is from BEFORE Phase 2 migration.**
Your current dev database has the **Phase 2 schema** with significant improvements:
- ✅ Unified machines table for all infrastructure
- ✅ Consolidated communications table
- ✅ Machine relationships tracking
- ✅ Compliance management
- ✅ Warranty tracking
**Recommendation:** Do NOT apply the backup file schema. Keep your current Phase 2 dev schema.
If production needs updating, use your current dev schema as the source, not the backup file.
---
**Generated:** 2025-11-20 10:56
**Analyst:** Claude Code
**Status:** Analysis Complete ✅

View File

@@ -110,22 +110,30 @@ Do While Not rs.EOF
End If End If
End If End If
' Build standard name: CSFName-Location-VendorModel (no dash between vendor and model) ' Determine printer name to use
If csfName <> "" And csfName <> "NONE" And csfName <> "gage lab " Then ' Prefer Windows Name from database if it's already in standardized format (contains dashes)
' Has CSF name ' Otherwise generate standardized name automatically
' Check if CSF name already matches the machine location (avoid duplication) If InStr(printerName, "-") > 0 Then
If cleanMachine <> "" And LCase(csfName) <> LCase(cleanMachine) Then ' Use database Windows Name as-is (user manually set it)
standardName = csfName & "-" & cleanMachine & "-" & vendor & shortDescription standardName = printerName
Else
' CSF name same as location, or no location - just use CSF-VendorModel
standardName = csfName & "-" & vendor & shortDescription
End If
Else Else
' No CSF name - use Location-VendorModel ' Generate standard name: CSFName-Location-VendorModel (no dash between vendor and model)
If cleanMachine <> "" Then If csfName <> "" And csfName <> "NONE" And csfName <> "gage lab " Then
standardName = cleanMachine & "-" & vendor & shortDescription ' Has CSF name
' Check if CSF name already matches the machine location (avoid duplication)
If cleanMachine <> "" And LCase(csfName) <> LCase(cleanMachine) Then
standardName = csfName & "-" & cleanMachine & "-" & vendor & shortDescription
Else
' CSF name same as location, or no location - just use CSF-VendorModel
standardName = csfName & "-" & vendor & shortDescription
End If
Else Else
standardName = "Printer" & rs("printerid") & "-" & vendor & shortDescription ' No CSF name - use Location-VendorModel
If cleanMachine <> "" Then
standardName = cleanMachine & "-" & vendor & shortDescription
Else
standardName = "Printer" & rs("printerid") & "-" & vendor & shortDescription
End If
End If End If
End If End If
standardName = Replace(standardName, """", "\""") standardName = Replace(standardName, """", "\""")

View File

@@ -32,11 +32,30 @@
<div class="col-xl-auto"> <div class="col-xl-auto">
<div class="card"> <div class="card">
<div class="card-body"> <div class="card-body">
<%
Dim showAll
showAll = Request.QueryString("showall")
If showAll = "" Then showAll = "0"
%>
<div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:15px;"> <div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:15px;">
<h5 class="card-title" style="margin:0;"> <h5 class="card-title" style="margin:0;">
<i class="zmdi zmdi-notifications"></i> Notifications <i class="zmdi zmdi-notifications"></i> Notifications
<% If showAll = "1" Then %>
<span class="badge badge-info">Showing All</span>
<% Else %>
<span class="badge badge-success">Showing Active</span>
<% End If %>
</h5> </h5>
<div> <div>
<% If showAll = "1" Then %>
<a href="./displaynotifications.asp" class="btn btn-success">
<i class="zmdi zmdi-eye"></i> Show Active Only
</a>
<% Else %>
<a href="./displaynotifications.asp?showall=1" class="btn btn-info">
<i class="zmdi zmdi-time-restore"></i> Show All History
</a>
<% End If %>
<a href="./calendar.asp" class="btn btn-secondary"> <a href="./calendar.asp" class="btn btn-secondary">
<i class="zmdi zmdi-calendar"></i> Calendar View <i class="zmdi zmdi-calendar"></i> Calendar View
</a> </a>
@@ -73,11 +92,17 @@
"END as is_complete " & _ "END as is_complete " & _
"FROM notifications n " & _ "FROM notifications n " & _
"LEFT JOIN notificationtypes nt ON n.notificationtypeid = nt.notificationtypeid " & _ "LEFT JOIN notificationtypes nt ON n.notificationtypeid = nt.notificationtypeid " & _
"LEFT JOIN businessunits bu ON n.businessunitid = bu.businessunitid " & _ "LEFT JOIN businessunits bu ON n.businessunitid = bu.businessunitid "
"WHERE n.isactive = 1 OR " & _
" (n.isactive = 0 AND n.endtime IS NOT NULL AND " & _ ' Add WHERE clause based on showall parameter
" DATE_ADD(n.endtime, INTERVAL 30 MINUTE) >= NOW()) " & _ If showAll <> "1" Then
"ORDER BY n.notificationid DESC" strSQL = strSQL & _
"WHERE n.isactive = 1 OR " & _
" (n.isactive = 0 AND n.endtime IS NOT NULL AND " & _
" DATE_ADD(n.endtime, INTERVAL 30 MINUTE) >= NOW()) "
End If
strSQL = strSQL & "ORDER BY n.notificationid DESC"
Set rs = objconn.Execute(strSQL) Set rs = objconn.Execute(strSQL)
If rs.EOF Then If rs.EOF Then

View File

@@ -4,7 +4,7 @@
' install_printer.asp ' install_printer.asp
' Generates a batch file to install printer(s) ' Generates a batch file to install printer(s)
' - If printer has installpath: downloads and runs specific .exe ' - If printer has installpath: downloads and runs specific .exe
' - If no installpath: uses PowerShell to install with universal driver ' - If no installpath: downloads universal PrinterInstaller.exe
' Usage: install_printer.asp?printer=GuardDesk-HIDDTC ' Usage: install_printer.asp?printer=GuardDesk-HIDDTC
Dim printerNames, printerIds, printerArray, i, fileName Dim printerNames, printerIds, printerArray, i, fileName
@@ -30,10 +30,11 @@ If printerIds <> "" Then
strSQL = "SELECT p.printerid, p.printerwindowsname, p.printercsfname, " & _ strSQL = "SELECT p.printerid, p.printerwindowsname, p.printercsfname, " & _
"p.fqdn, p.ipaddress, p.installpath, " & _ "p.fqdn, p.ipaddress, p.installpath, " & _
"v.vendor, m.modelnumber " & _ "v.vendor, m.modelnumber, ma.alias, ma.machinenumber " & _
"FROM printers p " & _ "FROM printers p " & _
"LEFT JOIN models m ON p.modelid = m.modelnumberid " & _ "LEFT JOIN models m ON p.modelid = m.modelnumberid " & _
"LEFT JOIN vendors v ON m.vendorid = v.vendorid " & _ "LEFT JOIN vendors v ON m.vendorid = v.vendorid " & _
"LEFT JOIN machines ma ON p.machineid = ma.machineid " & _
"WHERE p.printerid IN (" "WHERE p.printerid IN ("
For i = 0 To UBound(printerArray) For i = 0 To UBound(printerArray)
@@ -48,10 +49,11 @@ ElseIf printerNames <> "" Then
strSQL = "SELECT p.printerid, p.printerwindowsname, p.printercsfname, " & _ strSQL = "SELECT p.printerid, p.printerwindowsname, p.printercsfname, " & _
"p.fqdn, p.ipaddress, p.installpath, " & _ "p.fqdn, p.ipaddress, p.installpath, " & _
"v.vendor, m.modelnumber " & _ "v.vendor, m.modelnumber, ma.alias, ma.machinenumber " & _
"FROM printers p " & _ "FROM printers p " & _
"LEFT JOIN models m ON p.modelid = m.modelnumberid " & _ "LEFT JOIN models m ON p.modelid = m.modelnumberid " & _
"LEFT JOIN vendors v ON m.vendorid = v.vendorid " & _ "LEFT JOIN vendors v ON m.vendorid = v.vendorid " & _
"LEFT JOIN machines ma ON p.machineid = ma.machineid " & _
"WHERE p.printerwindowsname IN (" "WHERE p.printerwindowsname IN ("
For i = 0 To UBound(printerArray) For i = 0 To UBound(printerArray)
@@ -76,6 +78,77 @@ If printerIds <> "" Or printerNames <> "" Then
printerInfo("vendor") = rs("vendor") & "" printerInfo("vendor") = rs("vendor") & ""
printerInfo("model") = rs("modelnumber") & "" printerInfo("model") = rs("modelnumber") & ""
' Determine printer name to use
' Prefer Windows Name from database if it's already in standardized format (contains dashes)
' Otherwise generate standardized name (same logic as api_printers.asp)
Dim machineAlias, machineNumber, machineName, cleanMachine, cleanModel, shortDescription, standardName
' Check if printerwindowsname is already standardized (contains dashes, not just spaces)
If InStr(printerInfo("name"), "-") > 0 Then
' Use database Windows Name as-is (user manually set it)
standardName = printerInfo("name")
Else
' Generate standardized name
machineAlias = rs("alias") & ""
machineNumber = rs("machinenumber") & ""
If machineAlias <> "" Then
machineName = machineAlias
Else
machineName = machineNumber
End If
cleanMachine = Replace(machineName, " ", "")
cleanMachine = Replace(cleanMachine, "Machine", "")
cleanModel = Replace(printerInfo("model"), " ", "")
' Extract short description from model number
If InStr(cleanModel, "ColorLaserJet") > 0 Then
shortDescription = "ColorLaserJet"
ElseIf InStr(cleanModel, "LaserJetPro") > 0 Then
shortDescription = "LaserJetPro"
ElseIf InStr(cleanModel, "LaserJet") > 0 Then
shortDescription = "LaserJet"
ElseIf InStr(cleanModel, "Altalink") > 0 Then
shortDescription = "Altalink"
ElseIf InStr(cleanModel, "Versalink") > 0 Then
shortDescription = "Versalink"
ElseIf InStr(cleanModel, "DesignJet") > 0 Then
shortDescription = "DesignJet"
ElseIf InStr(cleanModel, "DTC") > 0 Then
shortDescription = "DTC"
Else
Dim j, char2
shortDescription = ""
For j = 1 To Len(cleanModel)
char2 = Mid(cleanModel, j, 1)
If char2 >= "0" And char2 <= "9" Then
Exit For
End If
shortDescription = shortDescription & char2
Next
If shortDescription = "" Then
shortDescription = cleanModel
End If
End If
' Build standard name: CSFName-Location-VendorModel
If printerInfo("csfname") <> "" And printerInfo("csfname") <> "NONE" And printerInfo("csfname") <> "gage lab " Then
If cleanMachine <> "" And LCase(printerInfo("csfname")) <> LCase(cleanMachine) Then
standardName = printerInfo("csfname") & "-" & cleanMachine & "-" & printerInfo("vendor") & shortDescription
Else
standardName = printerInfo("csfname") & "-" & printerInfo("vendor") & shortDescription
End If
Else
If cleanMachine <> "" Then
standardName = cleanMachine & "-" & printerInfo("vendor") & shortDescription
Else
standardName = "Printer" & rs("printerid") & "-" & printerInfo("vendor") & shortDescription
End If
End If
End If
printerInfo("standardname") = standardName
' Determine preferred address ' Determine preferred address
If printerInfo("fqdn") <> "" And printerInfo("fqdn") <> "USB" Then If printerInfo("fqdn") <> "" And printerInfo("fqdn") <> "USB" Then
printerInfo("address") = printerInfo("fqdn") printerInfo("address") = printerInfo("fqdn")
@@ -156,75 +229,21 @@ Else
Response.Write(" echo ERROR: Could not download installer" & vbCrLf) Response.Write(" echo ERROR: Could not download installer" & vbCrLf)
Response.Write(")" & vbCrLf) Response.Write(")" & vbCrLf)
Else Else
' No installer - use universal driver ' No specific installer - use universal PrinterInstaller.exe
Dim driverName, driverInf Response.Write("echo Using universal printer installer..." & vbCrLf)
Select Case UCase(printer("vendor"))
Case "HP"
driverName = "HP Universal Printing PCL 6"
driverInf = "hpcu255u.inf"
Case "XEROX"
driverName = "Xerox Global Print Driver PCL6"
driverInf = "xeroxgpd.inf"
Case "HID"
driverName = "HP Universal Printing PCL 6"
driverInf = "hpcu255u.inf"
Case Else
driverName = "Generic / Text Only"
driverInf = ""
End Select
Response.Write("echo Using universal driver: " & driverName & vbCrLf)
Response.Write("echo." & vbCrLf) Response.Write("echo." & vbCrLf)
Response.Write("echo Downloading PrinterInstaller.exe..." & vbCrLf)
' Generate PowerShell script to install printer Response.Write("powershell -NoProfile -Command """ & _
Response.Write("powershell -NoProfile -ExecutionPolicy Bypass -Command """ & vbCrLf) "$ProgressPreference = 'SilentlyContinue'; " & _
Response.Write(" Write-Host 'Installing printer with universal driver...' -ForegroundColor Cyan;" & vbCrLf) "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; " & _
Response.Write(" " & vbCrLf) "Invoke-WebRequest -Uri 'https://tsgwp00525.rd.ds.ge.com/shopdb/installers/PrinterInstaller.exe' " & _
Response.Write(" $printerName = '" & Replace(printer("name"), "'", "''") & "';" & vbCrLf) "-OutFile '%TEMP%\PrinterInstaller.exe' -UseBasicParsing -UseDefaultCredentials""" & vbCrLf)
Response.Write(" $address = '" & Replace(printer("address"), "'", "''") & "';" & vbCrLf) Response.Write("if exist ""%TEMP%\PrinterInstaller.exe"" (" & vbCrLf)
Response.Write(" $driverName = '" & Replace(driverName, "'", "''") & "';" & vbCrLf) Response.Write(" echo Running installer..." & vbCrLf)
Response.Write(" $portName = 'IP_' + $address;" & vbCrLf) Response.Write(" ""%TEMP%\PrinterInstaller.exe"" ""/PRINTER=" & printer("standardname") & """" & vbCrLf)
Response.Write(" " & vbCrLf) Response.Write(" del ""%TEMP%\PrinterInstaller.exe"" 2>nul" & vbCrLf)
Response.Write(") else (" & vbCrLf)
' Check if driver is installed Response.Write(" echo ERROR: Could not download PrinterInstaller.exe" & vbCrLf)
If driverInf <> "" Then
Response.Write(" # Check if driver exists" & vbCrLf)
Response.Write(" $driver = Get-PrinterDriver -Name $driverName -ErrorAction SilentlyContinue;" & vbCrLf)
Response.Write(" if (-not $driver) {" & vbCrLf)
Response.Write(" Write-Host 'ERROR: Universal driver not found!' -ForegroundColor Red;" & vbCrLf)
Response.Write(" Write-Host 'Please install ' $driverName ' from Windows Update or driver package' -ForegroundColor Yellow;" & vbCrLf)
Response.Write(" exit 1;" & vbCrLf)
Response.Write(" }" & vbCrLf)
Response.Write(" " & vbCrLf)
End If
' Create port
Response.Write(" # Create TCP/IP port" & vbCrLf)
Response.Write(" $port = Get-PrinterPort -Name $portName -ErrorAction SilentlyContinue;" & vbCrLf)
Response.Write(" if (-not $port) {" & vbCrLf)
Response.Write(" Write-Host 'Creating printer port...' -ForegroundColor Yellow;" & vbCrLf)
Response.Write(" Add-PrinterPort -Name $portName -PrinterHostAddress $address -ErrorAction Stop;" & vbCrLf)
Response.Write(" Write-Host 'Port created successfully' -ForegroundColor Green;" & vbCrLf)
Response.Write(" } else {" & vbCrLf)
Response.Write(" Write-Host 'Port already exists' -ForegroundColor Green;" & vbCrLf)
Response.Write(" }" & vbCrLf)
Response.Write(" " & vbCrLf)
' Add printer
Response.Write(" # Add printer" & vbCrLf)
Response.Write(" $existingPrinter = Get-Printer -Name $printerName -ErrorAction SilentlyContinue;" & vbCrLf)
Response.Write(" if (-not $existingPrinter) {" & vbCrLf)
Response.Write(" Write-Host 'Adding printer...' -ForegroundColor Yellow;" & vbCrLf)
Response.Write(" Add-Printer -Name $printerName -DriverName $driverName -PortName $portName -ErrorAction Stop;" & vbCrLf)
Response.Write(" Write-Host 'Printer installed successfully!' -ForegroundColor Green;" & vbCrLf)
Response.Write(" } else {" & vbCrLf)
Response.Write(" Write-Host 'Printer already exists' -ForegroundColor Green;" & vbCrLf)
Response.Write(" }" & vbCrLf)
Response.Write("""" & vbCrLf)
Response.Write("" & vbCrLf)
Response.Write("if %ERRORLEVEL% neq 0 (" & vbCrLf)
Response.Write(" echo ERROR: Failed to install printer" & vbCrLf)
Response.Write(")" & vbCrLf) Response.Write(")" & vbCrLf)
End If End If

View File

@@ -0,0 +1,156 @@
-- =============================================================================
-- Create/Update vw_network_devices View - Phase 2 Compatible
-- =============================================================================
-- Date: 2025-11-21
-- Purpose: Update vw_network_devices to query machines table for infrastructure
-- Printers remain in printers table (has fqdn column)
-- Other network devices (IDF, Server, Switch, Camera, Access Point) are in machines table
-- Machine Type IDs: 15=IDF, 16=Server, 17=Switch, 18=Camera, 19=Access Point, 20=Printer
-- =============================================================================
USE shopdb;
-- Drop existing view
DROP VIEW IF EXISTS vw_network_devices;
-- Create view with machines table for infrastructure + printers table for printers
CREATE VIEW vw_network_devices AS
-- Network infrastructure devices from machines table (IDF, Server, Switch, Camera, Access Point)
SELECT
mt.machinetype AS device_type,
m.machineid AS device_id,
COALESCE(m.alias, m.machinenumber) AS device_name,
m.modelnumberid AS modelid,
mo.modelnumber,
v.vendor,
m.serialnumber,
c.address AS ipaddress,
NULL AS fqdn, -- Infrastructure devices don't have FQDN
m.machinenotes AS description,
m.maptop,
m.mapleft,
m.isactive,
-- Camera-specific: which IDF closet (from machinerelationships)
(SELECT mr.related_machineid
FROM machinerelationships mr
JOIN relationshiptypes rt ON mr.relationshiptypeid = rt.relationshiptypeid
WHERE mr.machineid = m.machineid
AND rt.relationshiptype = 'Located In'
AND mr.isactive = 1
LIMIT 1) AS idfid,
-- Camera-specific: IDF name
(SELECT m2.machinenumber
FROM machinerelationships mr
JOIN relationshiptypes rt ON mr.relationshiptypeid = rt.relationshiptypeid
JOIN machines m2 ON mr.related_machineid = m2.machineid
WHERE mr.machineid = m.machineid
AND rt.relationshiptype = 'Located In'
AND mr.isactive = 1
LIMIT 1) AS idfname,
-- Camera-specific: MAC address (from communications table)
(SELECT c2.macaddress
FROM communications c2
WHERE c2.machineid = m.machineid
AND c2.macaddress IS NOT NULL
LIMIT 1) AS macaddress
FROM machines m
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
AND c.isactive = 1
WHERE m.machinetypeid IN (15, 16, 17, 18, 19) -- IDF, Server, Switch, Camera, Access Point
AND m.pctypeid IS NULL -- Exclude PCs
UNION ALL
-- Printers from printers table (has fqdn column)
SELECT
'Printer' AS device_type,
p.printerid AS device_id,
p.printerwindowsname AS device_name,
p.modelid,
m.modelnumber,
v.vendor,
p.serialnumber,
p.ipaddress,
p.fqdn, -- Printers have FQDN
NULL AS description,
p.maptop,
p.mapleft,
p.isactive,
NULL AS idfid,
NULL AS idfname,
NULL AS macaddress
FROM printers p
LEFT JOIN models m ON p.modelid = m.modelnumberid
LEFT JOIN vendors v ON m.vendorid = v.vendorid;
-- =============================================================================
-- Verification
-- =============================================================================
SELECT '✓ View created successfully (Phase 2)' AS status;
SELECT 'View columns:' AS '';
SELECT COLUMN_NAME, ORDINAL_POSITION
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'vw_network_devices'
ORDER BY ORDINAL_POSITION;
SELECT '' AS '';
SELECT 'Device counts by type:' AS '';
SELECT device_type, COUNT(*) AS count
FROM vw_network_devices
GROUP BY device_type
ORDER BY device_type;
SELECT '' AS '';
SELECT 'Sample devices (first 10):' AS '';
SELECT device_type, device_name, vendor, modelnumber, ipaddress, fqdn
FROM vw_network_devices
LIMIT 10;
-- =============================================================================
-- NOTES
-- =============================================================================
--
-- View Columns (16 total):
-- 1. device_type - Type: IDF, Server, Switch, Camera, Access Point (from machines), Printer (from printers)
-- 2. device_id - machineid or printerid
-- 3. device_name - Device name/alias
-- 4. modelid - Foreign key to models table
-- 5. modelnumber - Model number from models table
-- 6. vendor - Vendor name from vendors table
-- 7. serialnumber - Serial number
-- 8. ipaddress - IP address
-- 9. fqdn - FQDN (Printers only)
-- 10. description - Description
-- 11. maptop - Y coordinate for map display
-- 12. mapleft - X coordinate for map display
-- 13. isactive - Active flag
-- 14. idfid - IDF ID (Camera only, from machinerelationships)
-- 15. idfname - IDF name (Camera only, from machinerelationships)
-- 16. macaddress - MAC address (Camera only, from communications)
--
-- Machine Type IDs:
-- 15 = IDF
-- 16 = Server
-- 17 = Switch
-- 18 = Camera
-- 19 = Access Point
-- 20 = Printer (still in printers table, not machines)
--
-- Data Sources:
-- - IDFs, Servers, Switches, Cameras, Access Points: machines table
-- - Printers: printers table (has fqdn column)
--
-- Used by: network_devices.asp
--
-- To add a new IDF:
-- INSERT INTO machines (machinetypeid, machinenumber, alias, mapleft, maptop, isactive)
-- VALUES (15, 'IDF-NAME', 'Description', 100, 100, 1);
--
-- =============================================================================

View File

@@ -0,0 +1,610 @@
# Data Migration Scripts - What They Actually Do
**Date:** 2025-11-20
**Purpose:** Explain exactly what each data migration script does to production data
**Critical:** This preserves ALL production data while restructuring for Phase 2
---
## Overview: What We're Migrating
Your production database has data split across OLD tables that needs to be consolidated into NEW Phase 2 tables:
### Source Data (OLD Tables - Production)
- **pc table:** 286 PCs with hostnames, serial numbers, OS, etc.
- **machines table:** 275 equipment/machines (CNCs, lathes, mills, etc.)
- **pc_network_interfaces:** 705 network interfaces (IP addresses, MAC addresses)
- **pc_dualpath_assignments:** PC relationships for redundancy
- **machine_pc_relationships:** Which PCs control which equipment
- **machines.ipaddress1/ipaddress2:** IP addresses stored in machine records
### Destination (NEW Phase 2 Structure)
- **machines table:** Will contain BOTH 275 equipment + 286 PCs = 561 total records
- **communications table:** Will contain ALL network interfaces (from machines + PCs)
- **machinerelationships table:** Will contain ALL relationships (dualpath + control)
- **machinestatus table:** Replaces pcstatus (renamed for broader scope)
---
## Migration Script Breakdown
### Script 1: Backup Machine IP Addresses
**File:** `01_backup_machine_ips.sql`
**What It Does:**
```sql
-- Create temporary backup table
CREATE TABLE _backup_machine_ips AS
SELECT
machineid,
machinenumber,
ipaddress1,
ipaddress2
FROM machines
WHERE ipaddress1 IS NOT NULL OR ipaddress2 IS NOT NULL;
```
**Why:**
- Machines table currently has `ipaddress1` and `ipaddress2` columns
- We're about to DROP these columns (ALTER TABLE)
- But we need this data to move to the `communications` table
- This backup preserves ~275 machine IP addresses before columns are dropped
**Data Example:**
```
machineid | machinenumber | ipaddress1 | ipaddress2
----------|---------------|-----------------|----------------
1 | 0600 | 10.80.11.100 | NULL
2 | 0612 | 10.80.11.101 | 10.80.11.102
3 | 3001 | 10.80.12.50 | NULL
```
**Result:** Temporary backup table with all machine IPs preserved
---
### Script 2: ALTER Machines Table (Add Phase 2 Columns)
**File:** `02_alter_machines.sql`
**What It Does:**
```sql
ALTER TABLE machines
-- Add new Phase 2 columns for PCs
ADD COLUMN hostname varchar(100) DEFAULT NULL,
ADD COLUMN serialnumber varchar(50) DEFAULT NULL,
ADD COLUMN loggedinuser varchar(100) DEFAULT NULL,
ADD COLUMN pctypeid int(11) DEFAULT NULL,
ADD COLUMN osid int(11) DEFAULT NULL,
ADD COLUMN controllertypeid int(11) DEFAULT NULL,
ADD COLUMN controllerosid int(11) DEFAULT NULL,
ADD COLUMN controllermodelid int(11) DEFAULT NULL,
ADD COLUMN machinestatusid int(11) DEFAULT NULL,
ADD COLUMN lastupdated datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
ADD COLUMN requires_manual_machine_config tinyint(1) DEFAULT '0',
-- Remove old IP columns (data already backed up)
DROP COLUMN ipaddress1,
DROP COLUMN ipaddress2;
```
**Why:**
- Makes machines table able to store BOTH equipment AND PCs
- PCs identified by `pctypeid IS NOT NULL`
- Equipment identified by `pctypeid IS NULL`
- Removes IP columns because they'll go in communications table
**Impact on Existing Data:**
- ✅ All 275 existing machines preserved (no data loss)
- ✅ New columns added with NULL defaults (safe)
- ✅ ipaddress1/ipaddress2 dropped (but backed up in Script 1)
**After This Script:**
```
machines table now has:
- 275 existing equipment records (pctypeid = NULL)
- Ready to receive 286 PC records (pctypeid = NOT NULL)
```
---
### Script 3: Create New Phase 2 Tables
**File:** `05_create_phase2_tables.sql`
**What It Does:**
```sql
-- Create communications table
CREATE TABLE communications (
comid int(11) NOT NULL AUTO_INCREMENT,
machineid int(11) NOT NULL,
comstypeid int(11) NOT NULL DEFAULT 1,
address varchar(100) DEFAULT NULL, -- IP address or COM port
macaddress varchar(17) DEFAULT NULL,
interfacename varchar(50) DEFAULT NULL,
isprimary tinyint(1) DEFAULT 0,
isactive tinyint(1) DEFAULT 1,
settings text,
PRIMARY KEY (comid)
);
-- Create machinerelationships table
CREATE TABLE machinerelationships (
relationshipid int(11) NOT NULL AUTO_INCREMENT,
machineid int(11) NOT NULL,
related_machineid int(11) NOT NULL,
relationshiptypeid int(11) NOT NULL,
isactive tinyint(1) DEFAULT 1,
notes text,
PRIMARY KEY (relationshipid)
);
-- Create machinestatus table (copy from pcstatus)
CREATE TABLE machinestatus (
machinestatusid int(11) NOT NULL AUTO_INCREMENT,
machinestatus varchar(50) NOT NULL,
PRIMARY KEY (machinestatusid)
);
INSERT INTO machinestatus (machinestatusid, machinestatus)
SELECT pcstatusid, pcstatus FROM pcstatus;
-- Create other Phase 2 tables (compliance, warranties, etc.)
```
**Why:**
- Creates infrastructure for unified data storage
- No impact on existing data (these are new, empty tables)
**After This Script:**
```
New empty tables created:
- communications (ready for network interface data)
- machinerelationships (ready for PC relationships)
- machinestatus (populated with pcstatus data)
- compliance, warranties, etc. (empty, ready for future data)
```
---
### Script 4: Migrate PCs from pc → machines
**File:** `06_migrate_pcs.sql`
**What It Does:**
```sql
INSERT INTO machines (
hostname, -- PC hostname
serialnumber, -- PC serial number
loggedinuser, -- Currently logged in user
pctypeid, -- PC type (Engineer, Shopfloor, Standard, etc.)
osid, -- Operating system
modelnumberid, -- PC model (Dell, HP, etc.)
businessunitid, -- Business unit assignment
machinestatusid, -- Status (In Use, Spare, etc.)
machinenumber, -- Machine this PC is assigned to
alias, -- PC alias/friendly name
machinenotes, -- Notes (was 'notes' in pc table)
printerid, -- Assigned printer
isactive, -- Active flag
islocationonly -- Always 0 for PCs
)
SELECT
p.hostname,
p.serialnumber,
p.loggedinuser,
p.pctypeid, -- This makes it a PC (NOT NULL = PC)
p.osid,
p.modelnumberid,
p.businessunitid,
p.pcstatusid AS machinestatusid, -- Map pcstatusid to machinestatusid
p.machinenumber,
p.alias,
p.notes AS machinenotes, -- Column rename
p.printerid,
p.isactive,
0 AS islocationonly
FROM pc p
WHERE p.isactive = 1;
```
**Why:**
- Copies all 286 PCs from separate `pc` table into `machines` table
- Sets `pctypeid` to NOT NULL (this identifies them as PCs, not equipment)
- Renames `notes``machinenotes` to match Phase 2 schema
- Maps `pcstatusid``machinestatusid`
**Before:**
```
machines table: 275 equipment records
pc table: 286 PC records
```
**After:**
```
machines table: 561 total records
- 275 equipment (pctypeid = NULL)
- 286 PCs (pctypeid = 1, 2, 3, 4, 5, etc.)
pc table: 286 records (unchanged - kept as backup)
```
**Data Example:**
```
OLD (pc table):
pcid | hostname | serialnumber | pctypeid | machinenumber
-----|---------------|--------------|----------|---------------
1 | SHOP-PC-01 | ABC123 | 3 | 0600
2 | ENG-WS-05 | XYZ789 | 2 | 3001
NEW (machines table after migration):
machineid | hostname | serialnumber | pctypeid | machinenumber
----------|---------------|--------------|----------|---------------
276 | SHOP-PC-01 | ABC123 | 3 | 0600
277 | ENG-WS-05 | XYZ789 | 2 | 3001
```
**Important:**
- PC table is NOT dropped (kept as backup for 30 days)
- Duplicate check prevents re-running script
---
### Script 5: Migrate Machine IPs → communications
**File:** `07_migrate_machine_ips.sql`
**What It Does:**
```sql
-- Migrate ipaddress1 (primary interface)
INSERT INTO communications (
machineid,
comstypeid, -- 1 = Network/TCP-IP
address, -- The IP address
isprimary, -- 1 = primary interface
interfacename, -- "Interface 1"
isactive
)
SELECT
machineid,
1 AS comstypeid,
ipaddress1,
1 AS isprimary,
'Interface 1' AS interfacename,
1 AS isactive
FROM _backup_machine_ips
WHERE ipaddress1 IS NOT NULL AND ipaddress1 != '';
-- Migrate ipaddress2 (secondary interface)
INSERT INTO communications (
machineid,
comstypeid,
address,
isprimary, -- 0 = secondary interface
interfacename, -- "Interface 2"
isactive
)
SELECT
machineid,
1 AS comstypeid,
ipaddress2,
0 AS isprimary,
'Interface 2' AS interfacename,
1 AS isactive
FROM _backup_machine_ips
WHERE ipaddress2 IS NOT NULL AND ipaddress2 != '';
```
**Why:**
- Recovers IP addresses that were in machines.ipaddress1 and ipaddress2
- Moves them to unified communications table
- Marks ipaddress1 as primary, ipaddress2 as secondary
**Data Example:**
```
OLD (machines table - columns dropped):
machineid | ipaddress1 | ipaddress2
----------|---------------|-------------
1 | 10.80.11.100 | NULL
2 | 10.80.11.101 | 10.80.11.102
NEW (communications table):
comid | machineid | address | isprimary | interfacename
------|-----------|---------------|-----------|---------------
1 | 1 | 10.80.11.100 | 1 | Interface 1
2 | 2 | 10.80.11.101 | 1 | Interface 1
3 | 2 | 10.80.11.102 | 0 | Interface 2
```
**Result:** ~275 machine IP addresses preserved in communications table
---
### Script 6: Migrate PC Network Interfaces → communications
**File:** `08_migrate_pc_interfaces.sql`
**What It Does:**
```sql
INSERT INTO communications (
machineid, -- PC's new machineid (from machines table)
comstypeid, -- 1 = Network
address, -- IP address
macaddress, -- MAC address
isprimary, -- Primary interface flag
interfacename, -- "Interface 1", "Interface 2", etc.
isactive
)
SELECT
m.machineid, -- Find PC's new machineid by matching hostname
1 AS comstypeid,
pni.ipaddress,
pni.macaddress,
pni.isprimary,
CONCAT('Interface ',
ROW_NUMBER() OVER (PARTITION BY m.machineid ORDER BY pni.isprimary DESC)
) AS interfacename,
pni.isactive
FROM pc_network_interfaces pni
JOIN pc p ON pni.pcid = p.pcid
JOIN machines m ON m.hostname = p.hostname AND m.pctypeid IS NOT NULL
WHERE pni.isactive = 1;
```
**Why:**
- Copies all 705 network interfaces from `pc_network_interfaces` table
- Joins to find PC's NEW machineid in machines table (by hostname match)
- Preserves IP addresses, MAC addresses, primary flag
- Generates interface names (Interface 1, Interface 2, Interface 3)
**Data Example:**
```
OLD (pc_network_interfaces):
interfaceid | pcid | ipaddress | macaddress | isprimary
------------|------|---------------|-------------------|----------
1 | 1 | 10.80.50.10 | 00:11:22:33:44:55 | 1
2 | 1 | 10.80.50.11 | 00:11:22:33:44:56 | 0
3 | 2 | 10.80.50.20 | 00:11:22:33:44:57 | 1
PC table:
pcid | hostname
-----|------------
1 | SHOP-PC-01
2 | ENG-WS-05
Machines table (after PC migration):
machineid | hostname | pctypeid
----------|---------------|----------
276 | SHOP-PC-01 | 3
277 | ENG-WS-05 | 2
NEW (communications table):
comid | machineid | address | macaddress | isprimary | interfacename
------|-----------|---------------|-------------------|-----------|---------------
4 | 276 | 10.80.50.10 | 00:11:22:33:44:55 | 1 | Interface 1
5 | 276 | 10.80.50.11 | 00:11:22:33:44:56 | 0 | Interface 2
6 | 277 | 10.80.50.20 | 00:11:22:33:44:57 | 1 | Interface 1
```
**Result:** All 705 PC network interfaces migrated to communications table
---
### Script 7: Migrate PC Dualpath Relationships → machinerelationships
**File:** `09_migrate_relationships.sql`
**What It Does:**
```sql
-- Part 1: Migrate Dualpath (PC ↔ PC redundancy)
INSERT INTO machinerelationships (
machineid, -- Primary PC
related_machineid, -- Dualpath PC
relationshiptypeid, -- 2 = Dualpath
isactive
)
SELECT
m1.machineid, -- Primary PC's new machineid
m2.machineid, -- Dualpath PC's new machineid
2 AS relationshiptypeid, -- Dualpath relationship type
1 AS isactive
FROM pc_dualpath_assignments pda
JOIN pc p1 ON pda.pcid = p1.pcid
JOIN pc p2 ON pda.dualpath_pcid = p2.pcid
JOIN machines m1 ON m1.hostname = p1.hostname AND m1.pctypeid IS NOT NULL
JOIN machines m2 ON m2.hostname = p2.hostname AND m2.pctypeid IS NOT NULL;
-- Part 2: Migrate Controls (PC → Equipment)
INSERT INTO machinerelationships (
machineid, -- PC that controls equipment
related_machineid, -- Equipment being controlled
relationshiptypeid, -- 1 = Controls
isactive
)
SELECT
mpc.pcid AS machineid, -- PC's machineid (from machines)
mpc.machineid AS related_machineid, -- Equipment's machineid
1 AS relationshiptypeid, -- Controls relationship
mpc.isactive
FROM machine_pc_relationships mpc;
```
**Why:**
- Preserves PC redundancy relationships (dualpath)
- Preserves which PCs control which equipment
- Uses new unified machinerelationships table
**Data Example:**
**Dualpath (PC redundancy):**
```
OLD (pc_dualpath_assignments):
assignmentid | pcid | dualpath_pcid
-------------|------|---------------
1 | 5 | 12
PC table:
pcid | hostname
-----|-------------
5 | CNC-PC-01
12 | CNC-PC-02
Machines (after migration):
machineid | hostname | pctypeid
----------|-------------|----------
280 | CNC-PC-01 | 3
291 | CNC-PC-02 | 3
NEW (machinerelationships):
relationshipid | machineid | related_machineid | relationshiptypeid
---------------|-----------|-------------------|-------------------
1 | 280 | 291 | 2 (Dualpath)
```
**Controls (PC → Equipment):**
```
OLD (machine_pc_relationships):
relationshipid | pcid | machineid
---------------|------|----------
1 | 280 | 50
NEW (machinerelationships):
relationshipid | machineid | related_machineid | relationshiptypeid
---------------|-----------|-------------------|-------------------
2 | 280 | 50 | 1 (Controls)
```
**Meaning:**
- PC with machineid 280 controls equipment with machineid 50
- PC with machineid 280 has dualpath redundancy with PC machineid 291
**Result:** All PC relationships preserved in unified table
---
## Summary: What Happens to Your Data
### Before Migration:
```
pc table: 286 PCs
machines table: 275 equipment
pc_network_interfaces: 705 network interfaces
machine IPs (in machines): ~275 IP addresses
pc_dualpath_assignments: ~50 relationships
machine_pc_relationships: ~100 relationships
```
### After Migration:
```
machines table: 561 records (275 equipment + 286 PCs)
communications table: ~980 records (275 machine IPs + 705 PC interfaces)
machinerelationships table: ~150 records (dualpath + controls)
machinestatus table: Copied from pcstatus
OLD TABLES KEPT AS BACKUP (for 30 days):
pc table: 286 records (unchanged)
pc_network_interfaces: 705 records (unchanged)
pc_dualpath_assignments: ~50 records (unchanged)
machine_pc_relationships: ~100 records (unchanged)
```
---
## Critical Safety Features
### 1. No Data Loss
- ✅ Old tables are NOT dropped (kept for 30 days)
- ✅ Can roll back if issues found
- ✅ Data copied, not moved
### 2. Duplicate Prevention
```sql
-- Example: Only insert PCs that don't already exist
INSERT INTO machines (...)
SELECT ...
FROM pc p
WHERE NOT EXISTS (
SELECT 1 FROM machines m
WHERE m.hostname = p.hostname AND m.pctypeid IS NOT NULL
);
```
### 3. Data Validation Queries
After each script runs, verification queries check:
- Row counts match (286 PCs in old table = 286 PCs in new table)
- No duplicate hostnames
- All relationships have valid machine IDs
- No orphaned records
---
## What Gets Modified vs Copied
### MODIFIED (Structure Only):
- **machines table** - Columns added/removed, but existing 275 equipment preserved
- **businessunits table** - Columns added, existing data unchanged
- **controllertypes table** - Columns added, existing data unchanged
### COPIED (Data Duplicated):
- **pc → machines** - 286 PCs copied, pc table kept as backup
- **pc_network_interfaces → communications** - 705 interfaces copied, old table kept
- **machine IPs → communications** - IPs extracted before columns dropped
- **Relationships → machinerelationships** - Copied, old tables kept
### CREATED (New):
- **communications table** - Brand new, receives copied data
- **machinerelationships table** - Brand new, receives copied data
- **machinestatus table** - Created, populated from pcstatus
- **compliance, warranties, etc.** - Created empty
---
## Rollback Strategy
If something goes wrong:
1. **Before ASP deployment:**
- Drop new tables
- Restore machines columns (ADD ipaddress1, ipaddress2)
- Restore machine IPs from backup table
- Delete migrated PCs from machines table
2. **After ASP deployment:**
- Revert ASP code to Phase 1
- Keep data in both old and new tables
- Fix issues and retry
---
## Timeline
**Estimated execution time:**
- Script 1 (Backup): 1 second
- Script 2 (ALTER machines): 10 seconds
- Script 3 (CREATE tables): 30 seconds
- Script 4 (Migrate PCs): 30 seconds (286 inserts)
- Script 5 (Migrate machine IPs): 10 seconds (~275 records)
- Script 6 (Migrate PC interfaces): 1 minute (705 inserts)
- Script 7 (Migrate relationships): 30 seconds (~150 inserts)
**Total: ~3-4 minutes for data migration**
---
## Questions These Scripts Answer
**Q: Will I lose production data?**
A: No. Old tables are kept as backup. Data is copied, not moved.
**Q: What if the same PC exists in both tables?**
A: Duplicate check prevents re-inserting. Script can be re-run safely.
**Q: Can I roll back?**
A: Yes. Rollback scripts reverse all changes.
**Q: What happens to machine IPs when columns are dropped?**
A: Backed up to temp table first, then migrated to communications.
**Q: Will production be down during migration?**
A: Tables will be locked during ALTER and INSERT operations. Estimated 5-10 minutes.
**Q: What about data added after the backup was taken?**
A: Scripts work on live production database, not the backup file. All current data migrated.
---
**Status:** Explanation Complete
**Next Step:** Create actual SQL scripts based on this plan

View File

@@ -0,0 +1,468 @@
# Production Migration to Phase 2 Schema - CRITICAL PLAN
**Date:** 2025-11-20
**Source:** Production Database (database-backup-11-20-25-eod-with-drop.sql)
**Target:** Phase 2 Schema (as in current dev)
**Goal:** Migrate production to Phase 2 schema WITHOUT losing production data
---
## ⚠️ CRITICAL DATA PRESERVATION
**Production has MORE data than dev:**
- Production PCs: **286** (in `pc` table)
- Dev PCs: **238** (in `machines` table)
- Production network interfaces: **705**
- Dev communications: **746**
**Production also has more current data in:**
- applications (59 in prod)
- knowledgebase (219 in prod)
- notifications (64 in prod)
- machines (275 in prod)
- printers (45 in prod)
**We MUST preserve ALL production data during migration!**
---
## Migration Strategy: PHASE-BY-PHASE
### Phase 1: Extend Existing Tables (Non-Destructive)
- ALTER TABLE to add new columns
- No data loss
- Reversible
### Phase 2: Create New Tables (Safe)
- CREATE new Phase 2 tables (communications, compliance, etc.)
- No impact on existing data
- Reversible
### Phase 3: Migrate PC Data (Complex)
- Copy data from `pc``machines` (with pctypeid NOT NULL)
- Copy data from `pc_network_interfaces``communications`
- Keep old tables as backup for 30 days
- Reversible with rollback scripts
### Phase 4: Update ASP Pages (Application Layer)
- Deploy Phase 2 ASP code
- Test thoroughly
- Rollback ASP code if issues
---
## Data Comparison: Production vs Dev
| Item | Production | Dev | Difference |
|------|-----------|-----|------------|
| PCs (in pc table) | 286 | 0 | Prod +286 |
| PCs (in machines) | 0 | 238 | Dev +238 |
| Machines (equipment) | 275 | 355 | Dev +80 |
| Network Interfaces | 705 | 0 | Prod +705 |
| Communications | 0 | 746 | Dev +746 |
| Applications | 59 | ? | Prod data |
| Knowledge Base | 219 | ? | Prod data |
| Notifications | 64 | ? | Prod data |
**Conclusion:** Production has significant data added since dev started. We must preserve it!
---
## Tables Requiring Changes
### 1. ALTER TABLE (4 tables - preserve data)
#### `machines` - Add 11 Phase 2 columns
```sql
ALTER TABLE machines
ADD COLUMN hostname varchar(100) DEFAULT NULL AFTER machinenumber,
ADD COLUMN serialnumber varchar(50) DEFAULT NULL COMMENT 'Equipment serial number',
ADD COLUMN loggedinuser varchar(100) DEFAULT NULL,
ADD COLUMN pctypeid int(11) DEFAULT NULL,
ADD COLUMN osid int(11) DEFAULT NULL COMMENT 'Foreign key to operatingsystems table',
ADD COLUMN controllertypeid int(11) DEFAULT NULL,
ADD COLUMN controllerosid int(11) DEFAULT NULL,
ADD COLUMN controllermodelid int(11) DEFAULT NULL,
ADD COLUMN machinestatusid int(11) DEFAULT NULL,
ADD COLUMN lastupdated datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
ADD COLUMN requires_manual_machine_config tinyint(1) DEFAULT '0',
DROP COLUMN ipaddress1,
DROP COLUMN ipaddress2;
```
**Impact:**
- ✅ Preserves all 275 production machines
- ⚠️ Removes ipaddress1/ipaddress2 (will be migrated to communications)
- ✅ Makes room for 286 PCs to be added
#### `businessunits` - Add 5 columns
```sql
ALTER TABLE businessunits
ADD COLUMN liaisonname varchar(100) DEFAULT NULL,
ADD COLUMN liaisonsso varchar(50) DEFAULT NULL,
ADD COLUMN facility_id varchar(50) DEFAULT NULL COMMENT 'Facility ID (e.g., 212788513)',
ADD COLUMN dt_lead varchar(100) DEFAULT NULL COMMENT 'DT Lead name (e.g., Patrick Lipinski)',
ADD COLUMN dt_lead_sso varchar(50) DEFAULT NULL COMMENT 'DT Lead SSO';
```
**Impact:** ✅ No data loss, adds metadata fields
#### `controllertypes` - Add 4 columns
```sql
ALTER TABLE controllertypes
ADD COLUMN vendorid int(11) DEFAULT NULL,
ADD COLUMN controllermodel varchar(100) DEFAULT NULL,
ADD COLUMN controller_os varchar(100) DEFAULT NULL COMMENT 'Controller OS (e.g., FANUC OS)',
ADD COLUMN controllernotes text;
```
**Impact:** ✅ No data loss, adds metadata fields
#### `machine_overrides` - Definition changes
**Action:** Need to investigate exact differences
---
### 2. CREATE NEW TABLES (8 tables - safe)
#### `communications` - Replaces pc_network_interfaces
```sql
CREATE TABLE communications (
comid int(11) NOT NULL AUTO_INCREMENT,
machineid int(11) NOT NULL,
comstypeid int(11) NOT NULL DEFAULT 1,
address varchar(100) DEFAULT NULL,
macaddress varchar(17) DEFAULT NULL,
interfacename varchar(50) DEFAULT NULL,
isprimary tinyint(1) DEFAULT 0,
isactive tinyint(1) DEFAULT 1,
settings text,
PRIMARY KEY (comid),
KEY idx_machineid (machineid),
KEY idx_isprimary (isprimary)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
```
#### `comstypes` - Communication types
```sql
CREATE TABLE comstypes (
comstypeid int(11) NOT NULL AUTO_INCREMENT,
comstype varchar(50) NOT NULL,
description text,
isactive tinyint(1) DEFAULT 1,
PRIMARY KEY (comstypeid)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
INSERT INTO comstypes (comstypeid, comstype, description) VALUES
(1, 'Network', 'TCP/IP Network Connection'),
(2, 'Serial', 'Serial Port (RS-232, RS-485)'),
(3, 'USB', 'USB Connection'),
(4, 'Bluetooth', 'Bluetooth Connection'),
(5, 'WiFi', 'Wireless Network'),
(6, 'Other', 'Other Communication Type');
```
#### `compliance` - Compliance tracking
```sql
CREATE TABLE compliance (
complianceid int(11) NOT NULL AUTO_INCREMENT,
machineid int(11) NOT NULL,
is_third_party_managed enum('Yes','No','NA') DEFAULT 'NA',
third_party_vendorid int(11) DEFAULT NULL,
ot_asset_system varchar(100) DEFAULT NULL,
ot_asset_device_type varchar(100) DEFAULT NULL,
mft varchar(100) DEFAULT NULL,
last_scan_date datetime DEFAULT NULL,
compliance_status varchar(50) DEFAULT NULL,
compliance_notes text,
isactive tinyint(1) DEFAULT 1,
lastupdated datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (complianceid),
KEY idx_machineid (machineid)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
```
#### `compliancescans` - Scan history
```sql
CREATE TABLE compliancescans (
scanid int(11) NOT NULL AUTO_INCREMENT,
machineid int(11) NOT NULL,
scan_date datetime DEFAULT CURRENT_TIMESTAMP,
scan_result text,
scan_status varchar(50) DEFAULT NULL,
PRIMARY KEY (scanid),
KEY idx_machineid (machineid)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
```
#### `machinerelationships` - Machine relationships
```sql
CREATE TABLE machinerelationships (
relationshipid int(11) NOT NULL AUTO_INCREMENT,
machineid int(11) NOT NULL,
related_machineid int(11) NOT NULL,
relationshiptypeid int(11) NOT NULL,
isactive tinyint(1) DEFAULT 1,
notes text,
PRIMARY KEY (relationshipid),
KEY idx_machineid (machineid),
KEY idx_related_machineid (related_machineid)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
```
#### `relationshiptypes` - Relationship types
```sql
CREATE TABLE relationshiptypes (
relationshiptypeid int(11) NOT NULL AUTO_INCREMENT,
relationshiptype varchar(50) NOT NULL,
description text,
isdirectional tinyint(1) DEFAULT 0,
isactive tinyint(1) DEFAULT 1,
PRIMARY KEY (relationshiptypeid)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
INSERT INTO relationshiptypes (relationshiptypeid, relationshiptype, description, isdirectional) VALUES
(1, 'Controls', 'PC controls this equipment', 1),
(2, 'Dualpath', 'Machines share redundant connection', 0);
```
#### `machinestatus` - Replaces pcstatus
```sql
CREATE TABLE machinestatus (
machinestatusid int(11) NOT NULL AUTO_INCREMENT,
machinestatus varchar(50) NOT NULL,
description text,
isactive tinyint(1) DEFAULT 1,
PRIMARY KEY (machinestatusid)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- Copy data from pcstatus
INSERT INTO machinestatus (machinestatusid, machinestatus, description)
SELECT pcstatusid, pcstatus, NULL FROM pcstatus;
```
#### `warranties` - Warranty tracking
```sql
CREATE TABLE warranties (
warrantyid int(11) NOT NULL AUTO_INCREMENT,
machineid int(11) NOT NULL,
warrantyname varchar(100) DEFAULT NULL,
warrantyenddate date DEFAULT NULL,
isactive tinyint(1) DEFAULT 1,
PRIMARY KEY (warrantyid),
KEY idx_machineid (machineid)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
```
---
### 3. MIGRATE DATA (Critical - Most Complex)
#### Step 1: Backup Production Machine IPs
```sql
-- Save machine IPs before dropping columns
CREATE TABLE _backup_machine_ips AS
SELECT machineid, machinenumber, ipaddress1, ipaddress2
FROM machines
WHERE ipaddress1 IS NOT NULL OR ipaddress2 IS NOT NULL;
```
#### Step 2: Migrate PCs from `pc` to `machines`
```sql
-- Insert PCs into machines table
INSERT INTO machines (
hostname, serialnumber, loggedinuser, pctypeid, osid,
modelnumberid, businessunitid, machinestatusid,
machinenumber, alias, machinenotes, printerid,
mapleft, maptop, isactive, islocationonly
)
SELECT
p.hostname,
p.serialnumber,
p.loggedinuser,
p.pctypeid,
p.osid,
p.modelnumberid,
p.businessunitid,
p.pcstatusid AS machinestatusid,
p.machinenumber,
p.alias,
p.notes AS machinenotes,
p.printerid,
NULL AS mapleft,
NULL AS maptop,
p.isactive,
0 AS islocationonly
FROM pc p
WHERE NOT EXISTS (
SELECT 1 FROM machines m WHERE m.hostname = p.hostname
);
```
#### Step 3: Migrate Machine IPs to Communications
```sql
-- Migrate machine IP addresses (from backup)
INSERT INTO communications (machineid, comstypeid, address, isprimary, interfacename, isactive)
SELECT
machineid,
1 AS comstypeid, -- Network type
ipaddress1,
1 AS isprimary,
'Interface 1' AS interfacename,
1 AS isactive
FROM _backup_machine_ips
WHERE ipaddress1 IS NOT NULL AND ipaddress1 != '';
INSERT INTO communications (machineid, comstypeid, address, isprimary, interfacename, isactive)
SELECT
machineid,
1 AS comstypeid,
ipaddress2,
0 AS isprimary,
'Interface 2' AS interfacename,
1 AS isactive
FROM _backup_machine_ips
WHERE ipaddress2 IS NOT NULL AND ipaddress2 != '';
```
#### Step 4: Migrate PC Network Interfaces to Communications
```sql
-- Migrate pc_network_interfaces to communications
INSERT INTO communications (machineid, comstypeid, address, macaddress, isprimary, interfacename, isactive)
SELECT
m.machineid,
1 AS comstypeid,
pni.ipaddress,
pni.macaddress,
pni.isprimary,
CONCAT('Interface ', ROW_NUMBER() OVER (PARTITION BY m.machineid ORDER BY pni.isprimary DESC)) AS interfacename,
pni.isactive
FROM pc_network_interfaces pni
JOIN pc p ON pni.pcid = p.pcid
JOIN machines m ON m.hostname = p.hostname AND m.pctypeid IS NOT NULL;
```
#### Step 5: Migrate PC Relationships
```sql
-- Migrate pc_dualpath_assignments to machinerelationships
INSERT INTO machinerelationships (machineid, related_machineid, relationshiptypeid, isactive)
SELECT
m1.machineid,
m2.machineid,
2 AS relationshiptypeid, -- Dualpath
1 AS isactive
FROM pc_dualpath_assignments pda
JOIN pc p1 ON pda.pcid = p1.pcid
JOIN pc p2 ON pda.dualpath_pcid = p2.pcid
JOIN machines m1 ON m1.hostname = p1.hostname AND m1.pctypeid IS NOT NULL
JOIN machines m2 ON m2.hostname = p2.hostname AND m2.pctypeid IS NOT NULL;
-- Migrate machine_pc_relationships (PC controls equipment)
INSERT INTO machinerelationships (machineid, related_machineid, relationshiptypeid, isactive)
SELECT
mpc.pcid AS machineid,
mpc.machineid AS related_machineid,
1 AS relationshiptypeid, -- Controls
mpc.isactive
FROM machine_pc_relationships mpc;
```
---
## Migration Execution Order
### PRE-MIGRATION (Do First!)
1.**BACKUP PRODUCTION DATABASE** (already done: database-backup-11-20-25-eod-with-drop.sql)
2. ✅ Test all scripts on dev database first
3. ✅ Schedule maintenance window
4. ✅ Notify users
### MIGRATION EXECUTION (In Order)
1. **Phase 1a:** Create backup tables for IPs (5 seconds)
2. **Phase 1b:** ALTER TABLE machines, businessunits, controllertypes (30 seconds)
3. **Phase 2:** CREATE new Phase 2 tables (comstypes, communications, etc.) (1 minute)
4. **Phase 3a:** Migrate PCs from `pc``machines` (2 minutes)
5. **Phase 3b:** Migrate machine IPs to communications (1 minute)
6. **Phase 3c:** Migrate pc_network_interfaces → communications (2 minutes)
7. **Phase 3d:** Migrate relationships (1 minute)
8. **Phase 4:** Verify data integrity (5 minutes)
9. **Phase 5:** Deploy Phase 2 ASP code (10 minutes)
10. **Phase 6:** Test all critical pages (30 minutes)
**Total Estimated Time:** 45-60 minutes
---
## Rollback Plan
### If Issues Occur Before ASP Deployment:
1. Run rollback SQL scripts (reverse ALTERs)
2. Drop new tables
3. Restore from backup if needed
### If Issues Occur After ASP Deployment:
1. Deploy Phase 1 ASP code (revert)
2. Users can continue working with old schema
3. Fix issues in dev
4. Retry migration later
---
## Data Verification Queries
After migration, run these to verify:
```sql
-- Check PC count matches
SELECT 'Production PCs' as source, COUNT(*) FROM pc;
SELECT 'Migrated PCs' as source, COUNT(*) FROM machines WHERE pctypeid IS NOT NULL;
-- Check network interfaces migrated
SELECT 'Production Interfaces' as source, COUNT(*) FROM pc_network_interfaces;
SELECT 'Migrated Communications' as source, COUNT(*) FROM communications WHERE machineid IN (SELECT machineid FROM machines WHERE pctypeid IS NOT NULL);
-- Check machines preserved
SELECT 'Production Machines' as source, COUNT(*) FROM machines; -- Should match before/after
-- Check relationships migrated
SELECT 'Production Dualpath' as source, COUNT(*) FROM pc_dualpath_assignments;
SELECT 'Migrated Dualpath' as source, COUNT(*) FROM machinerelationships WHERE relationshiptypeid = 2;
SELECT 'Production PC-Machine' as source, COUNT(*) FROM machine_pc_relationships;
SELECT 'Migrated Controls' as source, COUNT(*) FROM machinerelationships WHERE relationshiptypeid = 1;
```
---
## Next Steps
1. **Review this plan** carefully
2. **Create migration SQL scripts** in proper order
3. **Test on dev database** first (with production data copy)
4. **Create rollback scripts** for each phase
5. **Schedule maintenance window** (2-3 hours)
6. **Execute migration** with full team monitoring
7. **Verify data** thoroughly before marking complete
---
## Files to Create
1. `/sql/production_migration/01_backup_machine_ips.sql`
2. `/sql/production_migration/02_alter_machines.sql`
3. `/sql/production_migration/03_alter_businessunits.sql`
4. `/sql/production_migration/04_alter_controllertypes.sql`
5. `/sql/production_migration/05_create_phase2_tables.sql`
6. `/sql/production_migration/06_migrate_pcs.sql`
7. `/sql/production_migration/07_migrate_machine_ips.sql`
8. `/sql/production_migration/08_migrate_pc_interfaces.sql`
9. `/sql/production_migration/09_migrate_relationships.sql`
10. `/sql/production_migration/10_verify_data.sql`
11. `/sql/production_migration/ROLLBACK_*.sql` (for each phase)
---
**Status:** Plan Complete - Ready for Script Creation
**Risk Level:** HIGH (Production data migration)
**Estimated Downtime:** 1-2 hours
**Reversibility:** HIGH (with rollback scripts and backup)

View File

@@ -0,0 +1,559 @@
# Views Migration Analysis - Phase 2 Schema
**Date:** 2025-11-20
**Critical Finding:** 24 out of 27 views require updates for Phase 2 schema
**Impact:** HIGH - Views will break after PC migration if not updated
---
## Executive Summary
Your production database has **27 views** that provide critical reporting and data aggregation. After analyzing these views:
- ⚠️ **24 views MUST be updated** - They reference deprecated tables (pc, pc_network_interfaces, etc.)
-**3 views OK** - Already compatible with Phase 2 schema
- 🚨 **CRITICAL:** These views must be updated BEFORE or DURING migration, or pages using them will break
---
## Views Status Breakdown
### ✅ Views Compatible with Phase 2 (3 views)
These views don't reference deprecated tables and will continue working after migration:
1. **vw_machinetype_comparison** - Compares machine types between machines and models
2. **vw_unmapped_machines** - Finds machines without map coordinates
3. **vw_network_devices** - Already updated to query machines table (from our Nov 13 work!)
---
### ⚠️ Views Requiring Updates (24 views)
All of these reference tables that will be deprecated after Phase 2 migration:
#### Category 1: PC-Focused Views (12 views)
Views that query the `pc` and `pctype` tables directly:
1. **vw_active_pcs** - Active PCs updated in last 30 days
- References: `pc`, `pctype`
- Used by: displaypcs.asp (probably)
- **Fix:** Query `machines WHERE pctypeid IS NOT NULL`
2. **vw_engineer_pcs** - Engineer workstations
- References: `pc`, `pctype`
- **Fix:** Query `machines WHERE pctypeid IN (SELECT pctypeid FROM pctype WHERE typename='Engineer')`
3. **vw_shopfloor_pcs** - Shop floor PCs
- References: `pc`, `pctype`
- **Fix:** Query `machines WHERE pctypeid IS NOT NULL` and filter by type
4. **vw_standard_pcs** - Standard workstations
- References: `pc`, `pctype`
- **Fix:** Query `machines WHERE pctypeid IN (SELECT pctypeid FROM pctype WHERE typename='Standard')`
5. **vw_pc_summary** - PC inventory summary
- References: `pc`, `pctype`
- **Fix:** Query `machines WHERE pctypeid IS NOT NULL`
6. **vw_pcs_by_hardware** - PC counts by hardware configuration
- References: `pc`, `pctype`
- **Fix:** Query `machines WHERE pctypeid IS NOT NULL` group by vendor/model
7. **vw_vendor_summary** - PC counts by manufacturer
- References: `pc`, `pctype`
- **Fix:** Query `machines WHERE pctypeid IS NOT NULL` group by vendor
8. **vw_recent_updates** - Recently updated PCs
- References: `pc`, `pctype`
- **Fix:** Query `machines WHERE pctypeid IS NOT NULL ORDER BY lastupdated`
9. **vw_pc_resolved_machines** - PCs mapped to machines
- References: `pc`
- **Fix:** Query `machines WHERE pctypeid IS NOT NULL`
10. **vw_machine_type_stats** - Machine type statistics
- References: `pc`
- **Fix:** Include PCs from machines table
11. **vw_shopfloor_applications_summary** - Application deployment summary
- References: `pc`
- **Fix:** Join to `machines WHERE pctypeid IS NOT NULL`
12. **vw_ge_machines** - Machines with assigned PCs
- References: `pc`, `pctype`
- **Fix:** Query `machines WHERE pctypeid IS NOT NULL` and join to machines (equipment)
#### Category 2: Network Interface Views (2 views)
Views that query `pc_network_interfaces`:
13. **vw_pc_network_summary** - PC network configuration summary
- References: `pc`, `pc_network_interfaces`, `pctype`
- **Fix:** Query `machines` and `communications` tables
- **Example Change:**
```sql
-- OLD:
FROM pc p
JOIN pc_network_interfaces pni ON p.pcid = pni.pcid
-- NEW:
FROM machines m
JOIN communications c ON m.machineid = c.machineid
WHERE m.pctypeid IS NOT NULL
```
14. **vw_pctype_config** - PC type configuration summary
- References: `pctype`, references pc_network_interfaces in subquery
- **Fix:** Query machines grouped by pctypeid, join to communications
#### Category 3: DNC Configuration Views (2 views)
Views that query `pc_dnc_config`:
15. **vw_dnc_config** - DNC configuration for all PCs
- References: `pc`, `pc_dnc_config`
- **Fix:** This data may need to be migrated to a new table or embedded in machine relationships
- **Status:** NEEDS DESIGN DECISION - Where does DNC config go in Phase 2?
16. **vw_shopfloor_comm_config** - Shop floor communication configuration
- References: `pc`, `pc_comm_config`, `pctype`
- **Fix:** Query `communications` table with comstypeid for different comm types
#### Category 4: Dualpath Views (3 views)
Views that query `pc_dualpath_assignments`:
17. **vw_dualpath_management** - Dualpath configuration management
- References: `pc`, `pctype`, `pc_dnc_config`, `pc_dualpath_assignments`
- **Fix:** Query `machinerelationships WHERE relationshiptypeid = 2` (Dualpath)
- **Example Change:**
```sql
-- OLD:
FROM pc p
JOIN pc_dualpath_assignments dpa ON p.pcid = dpa.pcid
-- NEW:
FROM machines m
JOIN machinerelationships mr ON m.machineid = mr.machineid
JOIN relationshiptypes rt ON mr.relationshiptypeid = rt.relationshiptypeid
WHERE m.pctypeid IS NOT NULL AND rt.relationshiptype = 'Dualpath'
```
18. **vw_machine_assignments** - Machine to PC assignments
- References: `pc`, `pc_dualpath_assignments`
- **Fix:** Query `machinerelationships` for both primary and dualpath assignments
19. **vw_multi_pc_machines** - Machines with multiple PC assignments
- References: `pc`
- **Fix:** Query `machines` and `machinerelationships` where multiple PCs control same equipment
#### Category 5: Machine Assignment Views (1 view)
20. **vw_machine_assignment_status** - Machine assignment status
- References: `pc`, `pctype`, `pc_dnc_config`
- **Fix:** Complex view needing updates to join machines table with pctypeid filter
#### Category 6: Warranty Views (2 views)
Views that track PC warranties:
21. **vw_warranties_expiring** - Warranties expiring soon
- References: `pc`, `pctype`
- **Fix:** Query `machines` and `warranties` tables where pctypeid IS NOT NULL
22. **vw_warranty_status** - Overall warranty status
- References: `pc`, `pctype` (based on pattern)
- **Fix:** Query `machines` and `warranties` tables
#### Category 7: Infrastructure Views (2 views)
Views that query network device tables:
23. **vw_idf_inventory** - IDF inventory with camera counts
- References: `idfs`, `cameras`
- **Fix:** Query `machines WHERE machinetypeid IN (17, 18)` for IDFs and Cameras
- **Note:** IDFs = machinetypeid 17, Cameras = machinetypeid 18
24. **vw_infrastructure_summary** - Infrastructure device counts
- References: `switches`, `accesspoints`, `servers`, `cameras`, `idfs`
- **Fix:** Query `machines WHERE machinetypeid IN (16,17,18,19,20)`
- **Example Change:**
```sql
-- OLD:
SELECT 'Switches' AS device_type, COUNT(*) FROM switches
UNION ALL
SELECT 'Access Points', COUNT(*) FROM accesspoints
-- NEW:
SELECT mt.machinetype AS device_type, COUNT(*) AS total_count
FROM machines m
JOIN machinetypes mt ON m.machinetypeid = mt.machinetypeid
WHERE mt.machinetypeid IN (16,17,18,19,20)
GROUP BY mt.machinetype
```
---
## Migration Strategy for Views
### Option 1: Drop and Recreate All Views (RECOMMENDED)
**Approach:**
1. Extract all current view definitions from production
2. Update each view definition for Phase 2 schema
3. During migration:
- DROP all 24 views that need updates
- CREATE updated views with Phase 2 schema
- Keep 3 compatible views as-is
**Pros:**
- Clean migration
- All views updated at once
- Easy to test before migration
**Cons:**
- Brief moment where views don't exist (during migration window)
- Requires updating all 24 views
---
### Option 2: Create Views During Migration
**Approach:**
1. Keep old tables as legacy (pc, pc_network_interfaces, etc.)
2. Keep old views working during transition
3. Create NEW views with "_v2" suffix for Phase 2 schema
4. Update ASP pages to use new views
5. After 30 days, drop old tables and old views
**Pros:**
- Zero downtime for views
- Gradual transition
- Can compare old vs new view results
**Cons:**
- Duplicate views (_v2 versions)
- Old tables must be kept (taking up space)
- More complex migration
---
### Option 3: Hybrid Views (Query Both Old and New)
**Approach:**
Create views that UNION data from both old and new tables during transition period.
**Example:**
```sql
CREATE VIEW vw_active_pcs AS
-- Get PCs from machines table (new Phase 2)
SELECT
m.machineid AS pcid,
m.hostname,
m.serialnumber,
...
FROM machines m
WHERE m.pctypeid IS NOT NULL
AND m.lastupdated > DATE_SUB(NOW(), INTERVAL 30 DAY)
UNION ALL
-- Get PCs from legacy pc table (if any remain)
SELECT
p.pcid,
p.hostname,
p.serialnumber,
...
FROM pc p
WHERE p.lastupdated > DATE_SUB(NOW(), INTERVAL 30 DAY)
AND NOT EXISTS (
SELECT 1 FROM machines m
WHERE m.hostname = p.hostname AND m.pctypeid IS NOT NULL
);
```
**Pros:**
- Works during transition
- No duplicate view names
- Handles mixed data scenarios
**Cons:**
- More complex queries
- Slower performance (UNION)
- Must remove legacy portions after migration complete
---
## Recommended Approach
**Use Option 1: Drop and Recreate**
**Reasoning:**
1. You're doing a full Phase 2 migration - commit to it fully
2. Migration window is already scheduled for table changes
3. Cleaner long-term solution
4. Easier to test and validate
5. All pages will use consistent schema
**Migration Steps:**
1. Before migration: Test all updated views on dev database
2. During migration:
- After data migration completes
- DROP all 24 old views
- CREATE all 24 updated views
3. After migration: Test all pages that use views
---
## Views Migration Checklist
### Pre-Migration (Dev Testing)
- [ ] Extract all 27 view definitions from production
- [ ] Update 24 view definitions for Phase 2 schema
- [ ] Test updated views on dev database
- [ ] Identify which ASP pages use which views
- [ ] Test all pages that use views
### During Migration
- [ ] Backup all view definitions (already in backup file)
- [ ] After PC data migration completes
- [ ] DROP 24 views requiring updates
- [ ] CREATE 24 updated views
- [ ] Run verification queries
- [ ] Test critical pages
### Post-Migration
- [ ] Monitor view performance
- [ ] Check all pages using views
- [ ] Update documentation
- [ ] Remove old table references from any remaining code
---
## Impact on ASP Pages
Views are typically used in these types of pages:
1. **Display/List Pages** - displaypcs.asp, displaymachines.asp
2. **Dashboard Pages** - default.asp, reports.asp
3. **Search Pages** - search.asp
4. **API Endpoints** - api_*.asp pages
**Action Required:**
1. Identify all ASP pages that query views
2. Test each page after view migration
3. Update any pages that break
---
## DNC Configuration Migration (Special Case)
**Problem:** Views reference `pc_dnc_config` and `pc_comm_config` tables
**Question:** Where does this data go in Phase 2?
**Options:**
1. **Create new tables:** `machine_dnc_config` (similar structure)
2. **Use communications table:** Store DNC settings in `settings` JSON field
3. **Use compliance table:** If DNC is compliance-related
4. **Keep legacy tables:** Don't migrate DNC config yet (Phase 3?)
**Recommendation:** Keep `pc_dnc_config` and `pc_comm_config` tables for now (Phase 3 migration). Update views to join machines table instead of pc table.
---
## Sample View Conversions
### Example 1: vw_active_pcs
**OLD (Production):**
```sql
CREATE VIEW vw_active_pcs AS
SELECT
p.pcid,
p.hostname,
p.serialnumber,
COALESCE(v.vendor, 'Unknown') AS manufacturer,
m.modelnumber AS model,
p.loggedinuser,
p.machinenumber,
COALESCE(os.operatingsystem, 'Unknown') AS operatingsystem,
COALESCE(pt.typename, 'Unknown') AS pctype,
p.lastupdated
FROM pc p
LEFT JOIN models m ON p.modelnumberid = m.modelnumberid
LEFT JOIN vendors v ON m.vendorid = v.vendorid
LEFT JOIN pctype pt ON p.pctypeid = pt.pctypeid
LEFT JOIN operatingsystems os ON p.osid = os.osid
WHERE p.lastupdated > DATE_SUB(NOW(), INTERVAL 30 DAY);
```
**NEW (Phase 2):**
```sql
CREATE VIEW vw_active_pcs AS
SELECT
m.machineid AS pcid,
m.hostname,
m.serialnumber,
COALESCE(v.vendor, 'Unknown') AS manufacturer,
mo.modelnumber AS model,
m.loggedinuser,
m.machinenumber,
COALESCE(os.operatingsystem, 'Unknown') AS operatingsystem,
COALESCE(pt.typename, 'Unknown') AS pctype,
m.lastupdated
FROM machines m
LEFT JOIN models mo ON m.modelnumberid = mo.modelnumberid
LEFT JOIN vendors v ON mo.vendorid = v.vendorid
LEFT JOIN pctype pt ON m.pctypeid = pt.pctypeid
LEFT JOIN operatingsystems os ON m.osid = os.osid
WHERE m.pctypeid IS NOT NULL -- Only PCs
AND m.lastupdated > DATE_SUB(NOW(), INTERVAL 30 DAY);
```
**Changes:**
- `FROM pc p` → `FROM machines m`
- Added `WHERE m.pctypeid IS NOT NULL` to filter PCs only
- `m.modelnumberid` alias changed to `mo` to avoid conflict
---
### Example 2: vw_dualpath_management
**OLD (Production):**
```sql
CREATE VIEW vw_dualpath_management AS
SELECT
p.hostname AS pc_hostname,
p.pcid,
pt.typename AS pc_type,
p.machinenumber AS primary_machine,
dc.dualpath_enabled,
dpa.secondary_machine
FROM pc p
JOIN pctype pt ON p.pctypeid = pt.pctypeid
LEFT JOIN pc_dnc_config dc ON p.pcid = dc.pcid
LEFT JOIN pc_dualpath_assignments dpa ON p.pcid = dpa.pcid
WHERE p.isactive = 1;
```
**NEW (Phase 2):**
```sql
CREATE VIEW vw_dualpath_management AS
SELECT
m.hostname AS pc_hostname,
m.machineid AS pcid,
pt.typename AS pc_type,
m.machinenumber AS primary_machine,
dc.dualpath_enabled,
m2.machinenumber AS secondary_machine
FROM machines m
JOIN pctype pt ON m.pctypeid = pt.pctypeid
LEFT JOIN pc_dnc_config dc ON m.machineid = dc.pcid -- Note: keep legacy table for now
LEFT JOIN machinerelationships mr ON m.machineid = mr.machineid
AND mr.relationshiptypeid = 2 -- Dualpath relationship
LEFT JOIN machines m2 ON mr.related_machineid = m2.machineid
WHERE m.pctypeid IS NOT NULL
AND m.isactive = 1;
```
**Changes:**
- `FROM pc p` → `FROM machines m WHERE pctypeid IS NOT NULL`
- `pc_dualpath_assignments` → `machinerelationships` with relationshiptype filter
- Join to second machine using machinerelationships
---
### Example 3: vw_infrastructure_summary
**OLD (Production):**
```sql
CREATE VIEW vw_infrastructure_summary AS
SELECT 'Switches' AS device_type, COUNT(*) AS total_count FROM switches
UNION ALL
SELECT 'Access Points', COUNT(*) FROM accesspoints
UNION ALL
SELECT 'Servers', COUNT(*) FROM servers
UNION ALL
SELECT 'Cameras', COUNT(*) FROM cameras
UNION ALL
SELECT 'IDFs', COUNT(*) FROM idfs;
```
**NEW (Phase 2):**
```sql
CREATE VIEW vw_infrastructure_summary AS
-- Network devices from machines table (Phase 2)
SELECT
mt.machinetype AS device_type,
COUNT(*) AS total_count,
SUM(CASE WHEN m.isactive = 1 THEN 1 ELSE 0 END) AS active_count
FROM machines m
JOIN machinetypes mt ON m.machinetypeid = mt.machinetypeid
WHERE mt.machinetypeid IN (16, 17, 18, 19, 20) -- Network device types
GROUP BY mt.machinetype
UNION ALL
-- Legacy devices from separate tables (if any remain)
SELECT 'Switches' AS device_type, COUNT(*) AS total_count,
SUM(CASE WHEN isactive = 1 THEN 1 ELSE 0 END) AS active_count
FROM switches
UNION ALL
SELECT 'Access Points', COUNT(*), SUM(CASE WHEN isactive = 1 THEN 1 ELSE 0 END) FROM accesspoints
UNION ALL
SELECT 'Servers', COUNT(*), SUM(CASE WHEN isactive = 1 THEN 1 ELSE 0 END) FROM servers
UNION ALL
SELECT 'Cameras', COUNT(*), SUM(CASE WHEN isactive = 1 THEN 1 ELSE 0 END) FROM cameras
UNION ALL
SELECT 'IDFs', COUNT(*), SUM(CASE WHEN isactive = 1 THEN 1 ELSE 0 END) FROM idfs;
```
**Changes:**
- Query machines table where machinetypeid IN (16,17,18,19,20)
- Keep legacy table queries in UNION for transition period
- Group by machinetype from machinetypes table
---
## Critical Decision Points
### 1. DNC Configuration Tables
**Decision Needed:** Migrate pc_dnc_config now or later?
- **Option A:** Keep for Phase 3, update views to join machines instead of pc
- **Option B:** Migrate now to new table structure
### 2. View Migration Timing
**Decision Needed:** When to update views?
- **During migration:** As part of Phase 2 deployment
- **Before migration:** Create _v2 versions for testing
- **After migration:** Update after verifying data migrated correctly
### 3. Legacy Network Device Tables
**Decision Needed:** Keep empty legacy tables?
- **Keep:** For backward compatibility (until Phase 3)
- **Drop:** Clean up unused tables now
---
## Next Steps
1. **Review this analysis** with team
2. **Make decisions** on DNC config and migration timing
3. **Create updated view definitions** for all 24 views
4. **Test views on dev** database with Phase 2 schema
5. **Add view migration** to production deployment plan
6. **Update PRODUCTION_MIGRATION_PLAN.md** to include views
---
## Files to Create
1. `/sql/production_migration/views/01_drop_old_views.sql` - DROP old views
2. `/sql/production_migration/views/02_create_pc_views.sql` - Create updated PC views
3. `/sql/production_migration/views/03_create_network_views.sql` - Create updated network views
4. `/sql/production_migration/views/04_create_relationship_views.sql` - Create updated relationship views
5. `/sql/production_migration/views/05_create_infrastructure_views.sql` - Create updated infrastructure views
6. `/sql/production_migration/views/06_verify_views.sql` - Verify all views work
---
**Status:** Analysis Complete - Awaiting Decisions
**Priority:** HIGH - Views must be updated for Phase 2 to work
**Risk:** MEDIUM - Views can be recreated if issues occur
**Estimated Time:** 4-6 hours to update all 24 views + testing

View File

@@ -0,0 +1,456 @@
-- =============================================================================
-- PHASE 1.0: Ensure All Machine Types Match Dev EXACTLY
-- =============================================================================
-- Date: 2025-11-21
-- Purpose: Ensure production has EXACT same machine types as dev database
-- This is CRITICAL because website code uses specific machinetypeid values
--
-- IMPORTANT: This script uses INSERT IGNORE with specific IDs to match dev
--
-- Dev Machine Types:
-- 1-14: Equipment (existing in production)
-- 15-20: Infrastructure (MUST ADD with exact IDs and colors)
-- 21-25: Equipment (existing in production)
-- 33-35: PC types (MUST ADD with exact IDs)
--
-- Run this as the FIRST step in Phase 1 migration
-- Estimated Time: 30 seconds
-- =============================================================================
USE shopdb;
SET SQL_SAFE_UPDATES = 0;
SELECT '============================================================' AS '';
SELECT 'PHASE 1.0: ENSURE MACHINE TYPES MATCH DEV EXACTLY' AS '';
SELECT '============================================================' AS '';
SELECT CONCAT('Start time: ', NOW()) AS '';
SELECT '' AS '';
-- =============================================================================
-- STEP 1: Check current machine types
-- =============================================================================
SELECT 'Current production machine types:' AS '';
SELECT COUNT(*) AS total_machine_types FROM machinetypes;
SELECT '' AS '';
SELECT 'Existing machine types in production:' AS '';
SELECT machinetypeid, machinetype, bgcolor, machinedescription
FROM machinetypes
ORDER BY machinetypeid;
SELECT '' AS '';
-- =============================================================================
-- STEP 2: Check for missing machine types
-- =============================================================================
SELECT 'Checking for missing machine types...' AS '';
SET @missing_15 = NOT EXISTS (SELECT 1 FROM machinetypes WHERE machinetypeid = 15);
SET @missing_16 = NOT EXISTS (SELECT 1 FROM machinetypes WHERE machinetypeid = 16);
SET @missing_17 = NOT EXISTS (SELECT 1 FROM machinetypes WHERE machinetypeid = 17);
SET @missing_18 = NOT EXISTS (SELECT 1 FROM machinetypes WHERE machinetypeid = 18);
SET @missing_19 = NOT EXISTS (SELECT 1 FROM machinetypes WHERE machinetypeid = 19);
SET @missing_20 = NOT EXISTS (SELECT 1 FROM machinetypes WHERE machinetypeid = 20);
SET @missing_33 = NOT EXISTS (SELECT 1 FROM machinetypes WHERE machinetypeid = 33);
SET @missing_34 = NOT EXISTS (SELECT 1 FROM machinetypes WHERE machinetypeid = 34);
SET @missing_35 = NOT EXISTS (SELECT 1 FROM machinetypes WHERE machinetypeid = 35);
SELECT
CASE WHEN @missing_15 THEN '⚠️ Missing ID 15 (Printer)' ELSE '✓ Has ID 15 (Printer)' END AS check_15,
CASE WHEN @missing_16 THEN '⚠️ Missing ID 16 (Access Point)' ELSE '✓ Has ID 16 (Access Point)' END AS check_16,
CASE WHEN @missing_17 THEN '⚠️ Missing ID 17 (IDF)' ELSE '✓ Has ID 17 (IDF)' END AS check_17,
CASE WHEN @missing_18 THEN '⚠️ Missing ID 18 (Camera)' ELSE '✓ Has ID 18 (Camera)' END AS check_18,
CASE WHEN @missing_19 THEN '⚠️ Missing ID 19 (Switch)' ELSE '✓ Has ID 19 (Switch)' END AS check_19,
CASE WHEN @missing_20 THEN '⚠️ Missing ID 20 (Server)' ELSE '✓ Has ID 20 (Server)' END AS check_20,
CASE WHEN @missing_33 THEN '⚠️ Missing ID 33 (Standard PC)' ELSE '✓ Has ID 33 (Standard PC)' END AS check_33,
CASE WHEN @missing_34 THEN '⚠️ Missing ID 34 (Engineering PC)' ELSE '✓ Has ID 34 (Engineering PC)' END AS check_34,
CASE WHEN @missing_35 THEN '⚠️ Missing ID 35 (Shopfloor PC)' ELSE '✓ Has ID 35 (Shopfloor PC)' END AS check_35;
SELECT '' AS '';
-- =============================================================================
-- STEP 3: Add infrastructure machine types (EXACT match to dev)
-- =============================================================================
SELECT 'Adding infrastructure machine types to match dev...' AS '';
SELECT '' AS '';
-- ID 15: Printer (with bgcolor #4CAF50 - green)
INSERT IGNORE INTO machinetypes (
machinetypeid,
machinetype,
isactive,
functionalaccountid,
bgcolor,
machinedescription,
builddocurl
)
VALUES (
15,
'Printer',
b'1',
1,
'#4CAF50',
'Network printer - HP, Xerox, or other print devices',
NULL
);
-- ID 16: Access Point (with bgcolor #2196F3 - blue)
INSERT IGNORE INTO machinetypes (
machinetypeid,
machinetype,
isactive,
functionalaccountid,
bgcolor,
machinedescription,
builddocurl
)
VALUES (
16,
'Access Point',
b'1',
1,
'#2196F3',
'Wireless access point for network connectivity',
NULL
);
-- ID 17: IDF (with bgcolor #FF9800 - orange)
INSERT IGNORE INTO machinetypes (
machinetypeid,
machinetype,
isactive,
functionalaccountid,
bgcolor,
machinedescription,
builddocurl
)
VALUES (
17,
'IDF',
b'1',
1,
'#FF9800',
'Intermediate Distribution Frame - network equipment closet',
NULL
);
-- ID 18: Camera (with bgcolor #F44336 - red)
INSERT IGNORE INTO machinetypes (
machinetypeid,
machinetype,
isactive,
functionalaccountid,
bgcolor,
machinedescription,
builddocurl
)
VALUES (
18,
'Camera',
b'1',
1,
'#F44336',
'Security camera for facility monitoring',
NULL
);
-- ID 19: Switch (with bgcolor #9C27B0 - purple)
INSERT IGNORE INTO machinetypes (
machinetypeid,
machinetype,
isactive,
functionalaccountid,
bgcolor,
machinedescription,
builddocurl
)
VALUES (
19,
'Switch',
b'1',
1,
'#9C27B0',
'Network switch for connectivity',
NULL
);
-- ID 20: Server (with bgcolor #607D8B - blue-gray)
INSERT IGNORE INTO machinetypes (
machinetypeid,
machinetype,
isactive,
functionalaccountid,
bgcolor,
machinedescription,
builddocurl
)
VALUES (
20,
'Server',
b'1',
1,
'#607D8B',
'Physical or virtual server',
NULL
);
SELECT '✓ Infrastructure machine types added (IDs 15-20)' AS status;
SELECT '' AS '';
-- =============================================================================
-- STEP 4: Deactivate old PC machine types if they exist
-- =============================================================================
SELECT 'Checking for old PC machine types (36-38)...' AS '';
SELECT '' AS '';
-- Deactivate old machine types to prevent confusion
UPDATE machinetypes
SET isactive = b'0'
WHERE machinetypeid IN (36, 37, 38);
SELECT CONCAT('✓ Deactivated ', ROW_COUNT(), ' old PC machine types (if they existed)') AS status;
SELECT '' AS '';
-- =============================================================================
-- STEP 5: Add PC machine types (EXACT match to dev)
-- =============================================================================
SELECT 'Adding PC machine types to match dev...' AS '';
SELECT '' AS '';
-- ID 33: Standard PC
INSERT IGNORE INTO machinetypes (
machinetypeid,
machinetype,
isactive,
functionalaccountid,
bgcolor,
machinedescription,
builddocurl
)
VALUES (
33,
'Standard PC',
b'1',
1,
NULL,
'Standard user workstation computer',
NULL
);
-- ID 34: Engineering PC
INSERT IGNORE INTO machinetypes (
machinetypeid,
machinetype,
isactive,
functionalaccountid,
bgcolor,
machinedescription,
builddocurl
)
VALUES (
34,
'Engineering PC',
b'1',
1,
NULL,
'Engineering workstation with specialized software',
NULL
);
-- ID 35: Shopfloor PC
INSERT IGNORE INTO machinetypes (
machinetypeid,
machinetype,
isactive,
functionalaccountid,
bgcolor,
machinedescription,
builddocurl
)
VALUES (
35,
'Shopfloor PC',
b'1',
1,
NULL,
'Shop floor computer for machine monitoring and control',
NULL
);
SELECT '✓ PC machine types added (IDs 33-35)' AS status;
SELECT '' AS '';
-- =============================================================================
-- STEP 6: Verification - Compare with Dev
-- =============================================================================
SELECT 'Verifying production matches dev...' AS '';
SELECT '' AS '';
-- Check all required types exist
SELECT 'Required machine types verification:' AS '';
SELECT
'ID' AS id,
'Type' AS type,
'Status' AS status,
'Bgcolor' AS bgcolor
UNION ALL
SELECT
'15',
'Printer',
CASE WHEN EXISTS (SELECT 1 FROM machinetypes WHERE machinetypeid = 15) THEN '' ELSE '' END,
(SELECT bgcolor FROM machinetypes WHERE machinetypeid = 15)
UNION ALL
SELECT
'16',
'Access Point',
CASE WHEN EXISTS (SELECT 1 FROM machinetypes WHERE machinetypeid = 16) THEN '' ELSE '' END,
(SELECT bgcolor FROM machinetypes WHERE machinetypeid = 16)
UNION ALL
SELECT
'17',
'IDF',
CASE WHEN EXISTS (SELECT 1 FROM machinetypes WHERE machinetypeid = 17) THEN '' ELSE '' END,
(SELECT bgcolor FROM machinetypes WHERE machinetypeid = 17)
UNION ALL
SELECT
'18',
'Camera',
CASE WHEN EXISTS (SELECT 1 FROM machinetypes WHERE machinetypeid = 18) THEN '' ELSE '' END,
(SELECT bgcolor FROM machinetypes WHERE machinetypeid = 18)
UNION ALL
SELECT
'19',
'Switch',
CASE WHEN EXISTS (SELECT 1 FROM machinetypes WHERE machinetypeid = 19) THEN '' ELSE '' END,
(SELECT bgcolor FROM machinetypes WHERE machinetypeid = 19)
UNION ALL
SELECT
'20',
'Server',
CASE WHEN EXISTS (SELECT 1 FROM machinetypes WHERE machinetypeid = 20) THEN '' ELSE '' END,
(SELECT bgcolor FROM machinetypes WHERE machinetypeid = 20)
UNION ALL
SELECT
'33',
'Standard PC',
CASE WHEN EXISTS (SELECT 1 FROM machinetypes WHERE machinetypeid = 33) THEN '' ELSE '' END,
(SELECT bgcolor FROM machinetypes WHERE machinetypeid = 33)
UNION ALL
SELECT
'34',
'Engineering PC',
CASE WHEN EXISTS (SELECT 1 FROM machinetypes WHERE machinetypeid = 34) THEN '' ELSE '' END,
(SELECT bgcolor FROM machinetypes WHERE machinetypeid = 34)
UNION ALL
SELECT
'35',
'Shopfloor PC',
CASE WHEN EXISTS (SELECT 1 FROM machinetypes WHERE machinetypeid = 35) THEN '' ELSE '' END,
(SELECT bgcolor FROM machinetypes WHERE machinetypeid = 35);
SELECT '' AS '';
-- Show all machine types after additions
SELECT 'All machine types in production (after sync):' AS '';
SELECT machinetypeid, machinetype, isactive, bgcolor, machinedescription
FROM machinetypes
ORDER BY machinetypeid;
SELECT '' AS '';
-- Count by category
SELECT 'Machine types by category:' AS '';
SELECT
CASE
WHEN machinetypeid IN (33, 34, 35) THEN 'PC Types'
WHEN machinetypeid IN (15, 16, 17, 18, 19, 20) THEN 'Infrastructure'
ELSE 'Equipment'
END AS category,
COUNT(*) AS count,
GROUP_CONCAT(CONCAT(machinetypeid, ':', machinetype) ORDER BY machinetypeid SEPARATOR ', ') AS types
FROM machinetypes
WHERE isactive = b'1'
GROUP BY category;
SELECT '' AS '';
-- =============================================================================
-- STEP 7: Final summary
-- =============================================================================
SELECT '============================================================' AS '';
SELECT '✓✓✓ MACHINE TYPES NOW MATCH DEV EXACTLY ✓✓✓' AS '';
SELECT '============================================================' AS '';
SELECT '' AS '';
SELECT 'Machine types summary:' AS '';
SELECT CONCAT('Total machine types: ', COUNT(*)) AS summary FROM machinetypes;
SELECT CONCAT('Active machine types: ', COUNT(*)) AS summary FROM machinetypes WHERE isactive = b'1';
SELECT CONCAT('Infrastructure types (15-20): ', COUNT(*)) AS summary FROM machinetypes WHERE machinetypeid BETWEEN 15 AND 20;
SELECT CONCAT('PC types (33-35): ', COUNT(*)) AS summary FROM machinetypes WHERE machinetypeid BETWEEN 33 AND 35;
SELECT '' AS '';
SELECT 'Website color coding preserved:' AS '';
SELECT ' - Printer (15): Green #4CAF50' AS '';
SELECT ' - Access Point (16): Blue #2196F3' AS '';
SELECT ' - IDF (17): Orange #FF9800' AS '';
SELECT ' - Camera (18): Red #F44336' AS '';
SELECT ' - Switch (19): Purple #9C27B0' AS '';
SELECT ' - Server (20): Blue-Gray #607D8B' AS '';
SELECT '' AS '';
SELECT 'Differentiation now works:' AS '';
SELECT ' - PCs: WHERE pctypeid IS NOT NULL' AS '';
SELECT ' - Equipment: WHERE pctypeid IS NULL AND machinetypeid NOT IN (15-20)' AS '';
SELECT ' - Infrastructure: WHERE pctypeid IS NULL AND machinetypeid IN (15-20)' AS '';
SELECT '' AS '';
SELECT CONCAT('Completed at: ', NOW()) AS '';
SELECT '============================================================' AS '';
SET SQL_SAFE_UPDATES = 1;
-- =============================================================================
-- EXPECTED DEV MACHINE TYPES (for reference)
-- =============================================================================
--
-- machinetypeid | machinetype | bgcolor | Description
-- --------------|---------------------------|-----------|---------------------------
-- 1 | LocationOnly | #ffffff | NULL
-- 2 | Vertical Lathe | #ffffff | NULL
-- 3 | CMM | #ffffff | Coordinate-measuring machine
-- 4 | Lathe | #ffffff | Okuma & Howa 2SPV80...
-- 5 | Wax Trace | #ffffff | NULL
-- 6 | Mill Turn | #ffffff |
-- 7 | Intertia Welder | #ffffff | NULL
-- 8 | Eddy Current | #ffffff | Wild Stallions...
-- 9 | Shotpeen | #ffffff | Shot peening...
-- 10 | Part Washer | #ffffff | NULL
-- 11 | Grinder | NULL | NULL
-- 12 | Broach | NULL | NULL
-- 13 | 5-axis Mill | NULL |
-- 14 | Furnace | NULL |
-- 15 | Printer | #4CAF50 | Network printer... ✨ ADDED
-- 16 | Access Point | #2196F3 | Wireless access... ✨ ADDED
-- 17 | IDF | #FF9800 | Intermediate... ✨ ADDED
-- 18 | Camera | #F44336 | Security camera... ✨ ADDED
-- 19 | Switch | #9C27B0 | Network switch... ✨ ADDED
-- 20 | Server | #607D8B | Physical or virtual... ✨ ADDED
-- 21 | Hobbing Machine | NULL | NULL
-- 22 | Robotic Deburring | NULL |
-- 23 | Measuring Machine | NULL | NULL
-- 24 | Vertical Turning Center | NULL | NULL
-- 25 | Horizontal Machining Ctr | NULL | NULL
-- 33 | Standard PC | NULL | Standard user... ✨ ADDED
-- 34 | Engineering PC | NULL | Engineering... ✨ ADDED
-- 35 | Shopfloor PC | NULL | Shop floor computer... ✨ ADDED
--
-- =============================================================================

View File

@@ -0,0 +1,334 @@
-- =============================================================================
-- PHASE 1.5: Migrate Equipment IP Addresses to Communications Table
-- =============================================================================
-- Date: 2025-11-21
-- Purpose: Migrate equipment (CNC, mills, lathes, etc.) IP addresses from
-- machines.ipaddress1/ipaddress2 to communications table
--
-- CRITICAL: Run this AFTER Phase 1 (infrastructure created) and
-- BEFORE removing ipaddress columns from machines table
--
-- Estimated Time: 1-2 minutes
-- Records: ~275 equipment IP addresses
-- =============================================================================
USE shopdb;
SET SQL_SAFE_UPDATES = 0;
SELECT '============================================================' AS '';
SELECT 'PHASE 1.5: MIGRATE EQUIPMENT IP ADDRESSES' AS '';
SELECT '============================================================' AS '';
SELECT CONCAT('Start time: ', NOW()) AS '';
SELECT '' AS '';
-- =============================================================================
-- STEP 1: Pre-migration checks
-- =============================================================================
SELECT 'Pre-migration checks:' AS '';
SELECT '' AS '';
-- Check communications table exists
SET @comms_exists = (
SELECT COUNT(*) FROM information_schema.tables
WHERE table_schema = 'shopdb' AND table_name = 'communications'
);
SELECT CASE
WHEN @comms_exists = 1 THEN '✓ Communications table exists'
ELSE '⚠️ ERROR: Communications table not found - run Phase 1 first!'
END AS status;
-- Check comstypes populated
SET @comstypes_count = (SELECT COUNT(*) FROM comstypes WHERE typename = 'Network' OR typename = 'Network_Interface');
SELECT CASE
WHEN @comstypes_count >= 1 THEN CONCAT('✓ Network comstypes exist (', @comstypes_count, ')')
ELSE '⚠️ ERROR: Network comstypes not found - run Phase 1 first!'
END AS status;
-- Check machines table has ipaddress columns
SET @has_ip_columns = (
SELECT COUNT(*) FROM information_schema.columns
WHERE table_schema = 'shopdb'
AND table_name = 'machines'
AND column_name IN ('ipaddress1', 'ipaddress2')
);
SELECT CASE
WHEN @has_ip_columns = 2 THEN '✓ Machines table has ipaddress1/ipaddress2 columns'
WHEN @has_ip_columns = 0 THEN '⚠️ WARNING: IP columns already removed - migration may have already run'
ELSE '⚠️ WARNING: Only some IP columns exist'
END AS status;
SELECT '' AS '';
-- Count equipment with IP addresses
SELECT 'Equipment IP address statistics:' AS '';
SELECT
'Equipment with ipaddress1' AS category,
COUNT(*) AS count
FROM machines
WHERE (pctypeid IS NULL OR pctypeid = 0) -- Equipment only (not PCs)
AND ipaddress1 IS NOT NULL
AND ipaddress1 != ''
AND ipaddress1 NOT IN ('X', 'TBD', 'N/A', 'x')
UNION ALL
SELECT
'Equipment with ipaddress2',
COUNT(*)
FROM machines
WHERE (pctypeid IS NULL OR pctypeid = 0)
AND ipaddress2 IS NOT NULL
AND ipaddress2 != ''
AND ipaddress2 NOT IN ('X', 'TBD', 'N/A', 'x')
UNION ALL
SELECT
'Existing equipment communications',
COUNT(DISTINCT c.machineid)
FROM communications c
JOIN machines m ON c.machineid = m.machineid
WHERE (m.pctypeid IS NULL OR m.pctypeid = 0);
SELECT '' AS '';
-- =============================================================================
-- STEP 2: Create backup of machine IP data
-- =============================================================================
SELECT 'Creating backup table...' AS '';
DROP TABLE IF EXISTS _backup_equipment_ips_phase1_5;
CREATE TABLE _backup_equipment_ips_phase1_5 AS
SELECT
machineid,
machinenumber,
alias,
machinetypeid,
ipaddress1,
ipaddress2,
NOW() AS backup_timestamp
FROM machines
WHERE (pctypeid IS NULL OR pctypeid = 0) -- Equipment only
AND (
(ipaddress1 IS NOT NULL AND ipaddress1 != '' AND ipaddress1 NOT IN ('X', 'TBD', 'N/A', 'x'))
OR
(ipaddress2 IS NOT NULL AND ipaddress2 != '' AND ipaddress2 NOT IN ('X', 'TBD', 'N/A', 'x'))
);
SELECT CONCAT('✓ Backup created: _backup_equipment_ips_phase1_5 (', COUNT(*), ' equipment records)') AS status
FROM _backup_equipment_ips_phase1_5;
SELECT '' AS '';
-- =============================================================================
-- STEP 3: Migrate ipaddress1 (primary interface)
-- =============================================================================
SELECT 'Migrating ipaddress1 (primary interface)...' AS '';
-- Get comstypeid for Network type
SET @network_comstypeid = (
SELECT comstypeid FROM comstypes
WHERE typename IN ('Network', 'Network_Interface')
LIMIT 1
);
INSERT INTO communications (
machineid,
comstypeid,
address,
isprimary,
interfacename,
isactive,
lastupdated
)
SELECT
m.machineid,
@network_comstypeid AS comstypeid,
m.ipaddress1 AS address,
1 AS isprimary, -- Primary interface
'Equipment Interface 1' AS interfacename,
1 AS isactive,
NOW() AS lastupdated
FROM machines m
WHERE (m.pctypeid IS NULL OR m.pctypeid = 0) -- Equipment only (not PCs)
AND m.ipaddress1 IS NOT NULL
AND m.ipaddress1 != ''
AND m.ipaddress1 NOT IN ('X', 'TBD', 'N/A', 'x') -- Exclude placeholder values
AND NOT EXISTS (
-- Don't insert if equipment already has a primary communication record
SELECT 1 FROM communications c
WHERE c.machineid = m.machineid
AND c.isprimary = 1
AND c.address = m.ipaddress1
);
SELECT CONCAT('✓ Migrated ', ROW_COUNT(), ' primary IP addresses (ipaddress1)') AS status;
SELECT '' AS '';
-- =============================================================================
-- STEP 4: Migrate ipaddress2 (secondary interface)
-- =============================================================================
SELECT 'Migrating ipaddress2 (secondary interface)...' AS '';
INSERT INTO communications (
machineid,
comstypeid,
address,
isprimary,
interfacename,
isactive,
lastupdated
)
SELECT
m.machineid,
@network_comstypeid AS comstypeid,
m.ipaddress2 AS address,
0 AS isprimary, -- Secondary interface
'Equipment Interface 2' AS interfacename,
1 AS isactive,
NOW() AS lastupdated
FROM machines m
WHERE (m.pctypeid IS NULL OR m.pctypeid = 0) -- Equipment only (not PCs)
AND m.ipaddress2 IS NOT NULL
AND m.ipaddress2 != ''
AND m.ipaddress2 NOT IN ('X', 'TBD', 'N/A', 'x') -- Exclude placeholder values
AND NOT EXISTS (
-- Don't insert if equipment already has this communication record
SELECT 1 FROM communications c
WHERE c.machineid = m.machineid
AND c.address = m.ipaddress2
);
SELECT CONCAT('✓ Migrated ', ROW_COUNT(), ' secondary IP addresses (ipaddress2)') AS status;
SELECT '' AS '';
-- =============================================================================
-- STEP 5: Verification
-- =============================================================================
SELECT 'Verifying migration...' AS '';
SELECT '' AS '';
-- Show summary
SELECT 'Migration summary:' AS '';
SELECT
'Equipment in backup table' AS category,
COUNT(*) AS count
FROM _backup_equipment_ips_phase1_5
UNION ALL
SELECT
'Equipment with ipaddress1 (before migration)',
COUNT(*)
FROM _backup_equipment_ips_phase1_5
WHERE ipaddress1 IS NOT NULL AND ipaddress1 != '' AND ipaddress1 NOT IN ('X', 'TBD', 'N/A', 'x')
UNION ALL
SELECT
'Equipment with ipaddress2 (before migration)',
COUNT(*)
FROM _backup_equipment_ips_phase1_5
WHERE ipaddress2 IS NOT NULL AND ipaddress2 != '' AND ipaddress2 NOT IN ('X', 'TBD', 'N/A', 'x')
UNION ALL
SELECT
'Equipment communications (after migration)',
COUNT(DISTINCT c.machineid)
FROM communications c
JOIN machines m ON c.machineid = m.machineid
WHERE (m.pctypeid IS NULL OR m.pctypeid = 0);
SELECT '' AS '';
-- Show sample of migrated equipment
SELECT 'Sample of migrated equipment IPs:' AS '';
SELECT
m.machineid,
m.machinenumber,
m.alias,
COUNT(c.comid) AS interface_count,
GROUP_CONCAT(
CONCAT(c.address, ' (', IF(c.isprimary=1, 'Primary', 'Secondary'), ')')
ORDER BY c.isprimary DESC
SEPARATOR ', '
) AS ip_addresses
FROM machines m
JOIN communications c ON m.machineid = c.machineid
JOIN _backup_equipment_ips_phase1_5 b ON m.machineid = b.machineid
WHERE (m.pctypeid IS NULL OR m.pctypeid = 0)
GROUP BY m.machineid, m.machinenumber, m.alias
ORDER BY m.machinenumber
LIMIT 10;
SELECT '' AS '';
-- Check for missing migrations
SET @missing_migrations = (
SELECT COUNT(*)
FROM _backup_equipment_ips_phase1_5 b
WHERE (b.ipaddress1 IS NOT NULL AND b.ipaddress1 != '' AND b.ipaddress1 NOT IN ('X', 'TBD', 'N/A', 'x'))
AND NOT EXISTS (
SELECT 1 FROM communications c
WHERE c.machineid = b.machineid
)
);
SELECT CASE
WHEN @missing_migrations = 0 THEN '✓ All equipment IPs successfully migrated'
ELSE CONCAT('⚠️ WARNING: ', @missing_migrations, ' equipment records not migrated - review logs')
END AS status;
SELECT '' AS '';
-- =============================================================================
-- STEP 6: Final summary
-- =============================================================================
SELECT '============================================================' AS '';
SELECT '✓✓✓ EQUIPMENT IP MIGRATION COMPLETE ✓✓✓' AS '';
SELECT '============================================================' AS '';
SELECT '' AS '';
SELECT 'Backup table created:' AS '';
SELECT ' _backup_equipment_ips_phase1_5' AS '';
SELECT '' AS '';
SELECT 'Next steps:' AS '';
SELECT ' 1. Verify equipment IPs in communications table' AS '';
SELECT ' 2. Test application pages using equipment IPs' AS '';
SELECT ' 3. Once verified, run remove_legacy_ip_columns.sql to drop ipaddress1/2 columns' AS '';
SELECT '' AS '';
SELECT 'IMPORTANT: Keep backup table for 30 days for rollback if needed' AS '';
SELECT '' AS '';
SELECT CONCAT('Completed at: ', NOW()) AS '';
SELECT '============================================================' AS '';
SET SQL_SAFE_UPDATES = 1;
-- =============================================================================
-- ROLLBACK PROCEDURE (if needed)
-- =============================================================================
--
-- If migration needs to be rolled back:
--
-- 1. Delete migrated communications:
-- DELETE c FROM communications c
-- JOIN _backup_equipment_ips_phase1_5 b ON c.machineid = b.machineid
-- WHERE c.interfacename LIKE 'Equipment Interface%';
--
-- 2. Restore ipaddress columns (if dropped):
-- ALTER TABLE machines
-- ADD COLUMN ipaddress1 CHAR(50) DEFAULT NULL,
-- ADD COLUMN ipaddress2 CHAR(50) DEFAULT NULL;
--
-- 3. Restore IP addresses:
-- UPDATE machines m
-- JOIN _backup_equipment_ips_phase1_5 b ON m.machineid = b.machineid
-- SET m.ipaddress1 = b.ipaddress1,
-- m.ipaddress2 = b.ipaddress2;
--
-- =============================================================================

View File

@@ -52,13 +52,16 @@ SELECT
pt.pctypeid, pt.pctypeid,
pt.typename, pt.typename,
CASE pt.typename CASE pt.typename
WHEN 'Standard' THEN (SELECT machinetypeid FROM machinetypes WHERE machinetype = 'PC - Standard' LIMIT 1) WHEN 'Standard' THEN 33 -- Standard PC (Phase 2)
WHEN 'Shopfloor' THEN (SELECT machinetypeid FROM machinetypes WHERE machinetype = 'PC - Shopfloor' LIMIT 1) WHEN 'Shopfloor' THEN 35 -- Shopfloor PC (Phase 2)
WHEN 'Engineer' THEN (SELECT machinetypeid FROM machinetypes WHERE machinetype = 'PC - Engineer' LIMIT 1) WHEN 'Engineer' THEN 34 -- Engineering PC (Phase 2)
WHEN 'Server' THEN (SELECT machinetypeid FROM machinetypes WHERE machinetype = 'PC - Server' LIMIT 1) WHEN 'Server' THEN 33 -- Map to Standard PC
WHEN 'VM' THEN (SELECT machinetypeid FROM machinetypes WHERE machinetype = 'PC - Server' LIMIT 1) WHEN 'VM' THEN 33 -- Map to Standard PC
WHEN 'Laptop' THEN (SELECT machinetypeid FROM machinetypes WHERE machinetype = 'PC - Laptop' LIMIT 1) WHEN 'Laptop' THEN 33 -- Map to Standard PC
ELSE (SELECT machinetypeid FROM machinetypes WHERE machinetype = 'PC - Standard' LIMIT 1) WHEN 'CMM' THEN 33 -- CMM is mislabeled, map to Standard PC
WHEN 'Uncategorized' THEN 33 -- Map to Standard PC
WHEN 'Wax / Trace' THEN 33 -- Map to Standard PC
ELSE 33 -- Default to Standard PC
END END
FROM pctype pt; FROM pctype pt;
@@ -92,9 +95,9 @@ SELECT
m.target_machinetypeid AS machinetypeid, m.target_machinetypeid AS machinetypeid,
-- PC identification fields -- PC identification fields
p.hostname AS machinenumber, -- Use hostname as machine number for PCs COALESCE(p.hostname, CONCAT('PC_', p.pcid)) AS machinenumber, -- Use hostname or generate PC_[id]
p.hostname AS hostname, p.hostname AS hostname,
p.hostname AS alias, -- Set alias same as hostname COALESCE(p.hostname, CONCAT('PC_', p.pcid)) AS alias, -- Set alias same as machinenumber
p.loggedinuser, p.loggedinuser,
-- Model and vendor -- Model and vendor

View File

@@ -31,9 +31,23 @@ PREPARE stmt FROM @sql;
EXECUTE stmt; EXECUTE stmt;
DEALLOCATE PREPARE stmt; DEALLOCATE PREPARE stmt;
-- Add index for performance -- Add index for performance (MySQL 5.6 compatible)
ALTER TABLE pc_comm_config SET @index_exists = (
ADD INDEX IF NOT EXISTS idx_machineid (machineid); SELECT COUNT(*)
FROM INFORMATION_SCHEMA.STATISTICS
WHERE TABLE_SCHEMA = 'shopdb'
AND TABLE_NAME = 'pc_comm_config'
AND INDEX_NAME = 'idx_machineid'
);
SET @sql = IF(@index_exists = 0,
'ALTER TABLE pc_comm_config ADD INDEX idx_machineid (machineid)',
'SELECT "Index idx_machineid already exists on pc_comm_config" AS status'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SELECT 'pc_comm_config updated successfully' AS result; SELECT 'pc_comm_config updated successfully' AS result;
@@ -60,9 +74,23 @@ PREPARE stmt FROM @sql;
EXECUTE stmt; EXECUTE stmt;
DEALLOCATE PREPARE stmt; DEALLOCATE PREPARE stmt;
-- Add index for performance -- Add index for performance (MySQL 5.6 compatible)
ALTER TABLE pc_dnc_config SET @index_exists = (
ADD INDEX IF NOT EXISTS idx_machineid (machineid); SELECT COUNT(*)
FROM INFORMATION_SCHEMA.STATISTICS
WHERE TABLE_SCHEMA = 'shopdb'
AND TABLE_NAME = 'pc_dnc_config'
AND INDEX_NAME = 'idx_machineid'
);
SET @sql = IF(@index_exists = 0,
'ALTER TABLE pc_dnc_config ADD INDEX idx_machineid (machineid)',
'SELECT "Index idx_machineid already exists on pc_dnc_config" AS status'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SELECT 'pc_dnc_config updated successfully' AS result; SELECT 'pc_dnc_config updated successfully' AS result;

View File

@@ -0,0 +1,277 @@
-- =============================================================================
-- FIX: Migrate Remaining PCs
-- =============================================================================
-- Date: 2025-11-21
-- Purpose: Migrate PCs that weren't migrated in the initial run due to:
-- 1. NULL pctypeid (60 PCs)
-- 2. Unmapped pctype names (CMM, etc.)
--
-- This fixes the machine type name mismatch:
-- Script looked for: 'PC - Standard', 'PC - Shopfloor', etc.
-- But we created: 'Standard PC', 'Shopfloor PC', etc.
-- =============================================================================
USE shopdb;
SET SQL_SAFE_UPDATES = 0;
SELECT '============================================================' AS '';
SELECT 'FIX: MIGRATE REMAINING PCS' AS '';
SELECT '============================================================' AS '';
SELECT CONCAT('Start time: ', NOW()) AS '';
SELECT '' AS '';
-- =============================================================================
-- STEP 1: Check unmigrated PCs
-- =============================================================================
SELECT 'Checking for unmigrated PCs...' AS '';
SELECT '' AS '';
SELECT 'PCs in original pc table (active):' AS category, COUNT(*) AS count FROM pc WHERE isactive = 1
UNION ALL
SELECT 'PCs already migrated', COUNT(*) FROM pc_to_machine_id_mapping
UNION ALL
SELECT 'PCs NOT yet migrated', COUNT(*)
FROM pc p
WHERE p.isactive = 1
AND NOT EXISTS (SELECT 1 FROM pc_to_machine_id_mapping m WHERE m.pcid = p.pcid);
SELECT '' AS '';
-- Show distribution of unmigrated PCs
SELECT 'Unmigrated PCs by type:' AS '';
SELECT
COALESCE(pt.typename, 'NULL') AS pctype,
COUNT(*) AS count
FROM pc p
LEFT JOIN pctype pt ON p.pctypeid = pt.pctypeid
WHERE p.isactive = 1
AND NOT EXISTS (SELECT 1 FROM pc_to_machine_id_mapping m WHERE m.pcid = p.pcid)
GROUP BY COALESCE(pt.typename, 'NULL');
SELECT '' AS '';
-- =============================================================================
-- STEP 2: Create corrected PC type mapping
-- =============================================================================
SELECT 'Creating corrected PC type mapping...' AS '';
DROP TEMPORARY TABLE IF EXISTS temp_pctype_mapping_fixed;
CREATE TEMPORARY TABLE temp_pctype_mapping_fixed (
pctypeid INT,
typename VARCHAR(50),
target_machinetypeid INT
);
-- Map all PC types to correct machine type IDs
INSERT INTO temp_pctype_mapping_fixed (pctypeid, typename, target_machinetypeid)
SELECT
pt.pctypeid,
pt.typename,
CASE pt.typename
WHEN 'Standard' THEN 33 -- Standard PC
WHEN 'Shopfloor' THEN 35 -- Shopfloor PC
WHEN 'Engineer' THEN 34 -- Engineering PC
WHEN 'Server' THEN 33 -- Map to Standard PC (no Server PC type exists)
WHEN 'VM' THEN 33 -- Map to Standard PC
WHEN 'Laptop' THEN 33 -- Map to Standard PC
WHEN 'CMM' THEN 33 -- CMM is mislabeled, map to Standard PC
WHEN 'Uncategorized' THEN 33 -- Map to Standard PC
WHEN 'Wax / Trace' THEN 33 -- Map to Standard PC
ELSE 33 -- Default to Standard PC
END AS target_machinetypeid
FROM pctype pt;
-- Handle NULL pctypeid case
INSERT INTO temp_pctype_mapping_fixed (pctypeid, typename, target_machinetypeid)
VALUES (NULL, 'NULL', 33); -- Map NULL to Standard PC
SELECT '✓ Corrected mapping created' AS status;
SELECT * FROM temp_pctype_mapping_fixed ORDER BY pctypeid;
SELECT '' AS '';
-- =============================================================================
-- STEP 3: Migrate remaining PCs
-- =============================================================================
SELECT 'Migrating remaining PCs...' AS '';
-- Insert remaining PCs into machines table
INSERT INTO machines (
machinetypeid,
pctypeid,
machinenumber,
hostname,
alias,
loggedinuser,
modelnumberid,
controllertypeid,
controllerosid,
serialnumber,
osid,
machinestatusid,
businessunitid,
printerid,
mapleft,
maptop,
isvnc,
islocationonly,
requires_manual_machine_config,
machinenotes,
isactive,
lastupdated,
dateadded
)
SELECT
COALESCE(m.target_machinetypeid, 33) AS machinetypeid, -- Default to Standard PC (33)
p.pctypeid,
COALESCE(p.hostname, CONCAT('PC_', p.pcid)) AS machinenumber, -- Use hostname or generate
p.hostname,
p.hostname AS alias, -- Use hostname as alias (pc table has no alias column)
p.loggedinuser,
p.modelnumberid,
NULL AS controllertypeid,
NULL AS controllerosid,
p.serialnumber,
p.osid,
COALESCE(p.pcstatusid, 3) AS machinestatusid, -- Default to status 3
COALESCE(
(SELECT businessunitid FROM machines WHERE machinenumber = p.machinenumber AND isactive = 1 LIMIT 1),
1
) AS businessunitid,
(SELECT printerid FROM machines WHERE machinenumber = p.machinenumber AND isactive = 1 LIMIT 1) AS printerid,
(SELECT mapleft FROM machines WHERE machinenumber = p.machinenumber AND isactive = 1 LIMIT 1) AS mapleft,
(SELECT maptop FROM machines WHERE machinenumber = p.machinenumber AND isactive = 1 LIMIT 1) AS maptop,
0 AS isvnc,
0 AS islocationonly,
p.requires_manual_machine_config,
NULL AS machinenotes,
p.isactive,
p.lastupdated,
p.dateadded
FROM pc p
LEFT JOIN temp_pctype_mapping_fixed m ON COALESCE(p.pctypeid, -999) = COALESCE(m.pctypeid, -999)
WHERE p.isactive = 1
AND NOT EXISTS (
SELECT 1 FROM pc_to_machine_id_mapping map WHERE map.pcid = p.pcid
)
AND NOT EXISTS (
-- Don't insert if PC already exists in machines table
SELECT 1 FROM machines mach
WHERE mach.pctypeid IS NOT NULL
AND (
(p.hostname IS NOT NULL AND mach.hostname = p.hostname)
OR
(p.hostname IS NULL AND mach.machinenumber = CONCAT('PC_', p.pcid))
)
);
SELECT CONCAT('✓ Migrated ', ROW_COUNT(), ' additional PCs') AS status;
SELECT '' AS '';
-- =============================================================================
-- STEP 4: Fix NULL pctypeid in machines table
-- =============================================================================
SELECT 'Fixing PCs with NULL pctypeid in machines table...' AS '';
-- Fix PCs that were migrated with NULL pctypeid
UPDATE machines
SET pctypeid = 1 -- Set to Standard (pctypeid 1)
WHERE machinetypeid IN (33, 34, 35)
AND pctypeid IS NULL;
SELECT CONCAT('✓ Fixed ', ROW_COUNT(), ' PCs with NULL pctypeid') AS status;
SELECT '' AS '';
-- =============================================================================
-- STEP 5: Update mapping table
-- =============================================================================
SELECT 'Updating PC to machine ID mapping...' AS '';
INSERT INTO pc_to_machine_id_mapping (pcid, new_machineid, migration_date)
SELECT
p.pcid,
m.machineid,
NOW()
FROM pc p
JOIN machines m ON (
-- Match by hostname (if both have hostname)
(p.hostname IS NOT NULL AND m.hostname = p.hostname)
OR
-- Match by PC_[pcid] pattern for NULL hostname PCs
(p.hostname IS NULL AND m.machinenumber = CONCAT('PC_', p.pcid))
)
WHERE p.isactive = 1
AND m.pctypeid IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM pc_to_machine_id_mapping map WHERE map.pcid = p.pcid
)
AND p.pcid IS NOT NULL;
SELECT CONCAT('✓ Updated mapping table with ', ROW_COUNT(), ' new mappings') AS status;
SELECT '' AS '';
-- =============================================================================
-- STEP 6: Verification
-- =============================================================================
SELECT 'Verifying fix...' AS '';
SELECT '' AS '';
SELECT 'Final counts:' AS '';
SELECT 'Active PCs in pc table' AS category, COUNT(*) AS count FROM pc WHERE isactive = 1
UNION ALL
SELECT 'PCs in mapping table', COUNT(*) FROM pc_to_machine_id_mapping
UNION ALL
SELECT 'PCs in machines table (pctypeid NOT NULL)', COUNT(*) FROM machines WHERE pctypeid IS NOT NULL
UNION ALL
SELECT 'PCs still unmigrated', COUNT(*)
FROM pc p
WHERE p.isactive = 1
AND NOT EXISTS (SELECT 1 FROM pc_to_machine_id_mapping m WHERE m.pcid = p.pcid);
SELECT '' AS '';
-- Check if any PCs still unmigrated
SET @unmigrated_count = (
SELECT COUNT(*)
FROM pc p
WHERE p.isactive = 1
AND NOT EXISTS (SELECT 1 FROM pc_to_machine_id_mapping m WHERE m.pcid = p.pcid)
);
SELECT CASE
WHEN @unmigrated_count = 0 THEN '✓✓✓ ALL PCS MIGRATED SUCCESSFULLY ✓✓✓'
ELSE CONCAT('⚠️ Still ', @unmigrated_count, ' PCs unmigrated - review above')
END AS status;
SELECT '' AS '';
-- Show sample of newly migrated PCs
SELECT 'Sample of newly migrated PCs:' AS '';
SELECT
m.machineid,
m.machinenumber,
m.hostname,
mt.machinetype,
pt.typename AS original_pctype
FROM machines m
JOIN machinetypes mt ON m.machinetypeid = mt.machinetypeid
LEFT JOIN pc p ON m.hostname = p.hostname
LEFT JOIN pctype pt ON p.pctypeid = pt.pctypeid
WHERE m.pctypeid IS NOT NULL
AND m.machineid NOT IN (SELECT new_machineid FROM pc_to_machine_id_mapping WHERE migration_date < NOW() - INTERVAL 1 MINUTE)
LIMIT 10;
SELECT '' AS '';
SELECT CONCAT('Completed at: ', NOW()) AS '';
SELECT '============================================================' AS '';
SET SQL_SAFE_UPDATES = 1;

View File

@@ -0,0 +1,184 @@
-- =============================================================================
-- FIX: Migrate PCs from Old Machine Types to New Machine Types
-- =============================================================================
-- Date: 2025-11-21
-- Purpose: Fix PCs that were migrated to old machine type IDs (36-38) instead
-- of the new Phase 2 machine type IDs (33-35)
--
-- Issue: Production database had old PC machine types:
-- - ID 36: "PC - Standard" (should be ID 33: "Standard PC")
-- - ID 37: "PC - Shopfloor" (should be ID 35: "Shopfloor PC")
-- - ID 38: "PC - Engineer" (should be ID 34: "Engineering PC")
--
-- Impact: 212 of 286 PCs are using old machine type IDs
-- =============================================================================
USE shopdb;
SET SQL_SAFE_UPDATES = 0;
SELECT '============================================================' AS '';
SELECT 'FIX: MIGRATE PCS TO NEW MACHINE TYPE IDS' AS '';
SELECT '============================================================' AS '';
SELECT CONCAT('Start time: ', NOW()) AS '';
SELECT '' AS '';
-- =============================================================================
-- STEP 1: Check current distribution
-- =============================================================================
SELECT 'Current PC distribution across machine types:' AS '';
SELECT '' AS '';
SELECT
mt.machinetypeid,
mt.machinetype,
CASE
WHEN mt.machinetypeid IN (33, 34, 35) THEN 'NEW (Phase 2)'
WHEN mt.machinetypeid IN (36, 37, 38) THEN 'OLD (Phase 1)'
ELSE 'OTHER'
END AS type_status,
COUNT(*) as pc_count
FROM machines m
JOIN machinetypes mt ON m.machinetypeid = mt.machinetypeid
WHERE m.pctypeid IS NOT NULL
GROUP BY mt.machinetypeid, mt.machinetype
ORDER BY mt.machinetypeid;
SELECT '' AS '';
-- =============================================================================
-- STEP 2: Migrate PCs to new machine type IDs
-- =============================================================================
SELECT 'Migrating PCs to new machine type IDs...' AS '';
SELECT '' AS '';
-- Migrate PC - Standard (36) to Standard PC (33)
UPDATE machines
SET machinetypeid = 33
WHERE machinetypeid = 36
AND pctypeid IS NOT NULL;
SELECT CONCAT('✓ Migrated ', ROW_COUNT(), ' PCs from "PC - Standard" (36) to "Standard PC" (33)') AS status;
-- Migrate PC - Engineer (38) to Engineering PC (34)
UPDATE machines
SET machinetypeid = 34
WHERE machinetypeid = 38
AND pctypeid IS NOT NULL;
SELECT CONCAT('✓ Migrated ', ROW_COUNT(), ' PCs from "PC - Engineer" (38) to "Engineering PC" (34)') AS status;
-- Migrate PC - Shopfloor (37) to Shopfloor PC (35)
UPDATE machines
SET machinetypeid = 35
WHERE machinetypeid = 37
AND pctypeid IS NOT NULL;
SELECT CONCAT('✓ Migrated ', ROW_COUNT(), ' PCs from "PC - Shopfloor" (37) to "Shopfloor PC" (35)') AS status;
SELECT '' AS '';
-- =============================================================================
-- STEP 3: Verify migration
-- =============================================================================
SELECT 'Verifying migration...' AS '';
SELECT '' AS '';
SELECT 'PC distribution after migration:' AS '';
SELECT
mt.machinetypeid,
mt.machinetype,
CASE
WHEN mt.machinetypeid IN (33, 34, 35) THEN 'NEW (Phase 2)'
WHEN mt.machinetypeid IN (36, 37, 38) THEN 'OLD (Phase 1)'
ELSE 'OTHER'
END AS type_status,
COUNT(*) as pc_count
FROM machines m
JOIN machinetypes mt ON m.machinetypeid = mt.machinetypeid
WHERE m.pctypeid IS NOT NULL
GROUP BY mt.machinetypeid, mt.machinetype
ORDER BY mt.machinetypeid;
SELECT '' AS '';
-- Check if any PCs still using old types
SET @old_type_count = (
SELECT COUNT(*)
FROM machines
WHERE machinetypeid IN (36, 37, 38)
AND pctypeid IS NOT NULL
);
SELECT CASE
WHEN @old_type_count = 0 THEN '✓✓✓ ALL PCS MIGRATED TO NEW MACHINE TYPES ✓✓✓'
ELSE CONCAT('⚠️ Still ', @old_type_count, ' PCs using old machine types!')
END AS status;
SELECT '' AS '';
-- =============================================================================
-- STEP 4: Summary by PC type
-- =============================================================================
SELECT 'Summary by PC type:' AS '';
SELECT
pt.typename AS pctype,
mt.machinetype,
COUNT(*) as count
FROM machines m
JOIN machinetypes mt ON m.machinetypeid = mt.machinetypeid
JOIN pctype pt ON m.pctypeid = pt.pctypeid
WHERE m.pctypeid IS NOT NULL
GROUP BY pt.typename, mt.machinetype
ORDER BY pt.typename, count DESC;
SELECT '' AS '';
-- =============================================================================
-- STEP 5: Deactivate old machine types (optional - can be done later)
-- =============================================================================
SELECT 'Old machine types status (not deactivated - can be done manually):' AS '';
SELECT machinetypeid, machinetype, isactive
FROM machinetypes
WHERE machinetypeid IN (36, 37, 38)
ORDER BY machinetypeid;
SELECT '' AS '';
SELECT '============================================================' AS '';
SELECT '✓✓✓ PC MACHINE TYPE MIGRATION COMPLETE ✓✓✓' AS '';
SELECT '============================================================' AS '';
SELECT '' AS '';
SELECT 'Final counts:' AS '';
SELECT CONCAT('Total PCs: ', COUNT(*)) AS summary FROM machines WHERE pctypeid IS NOT NULL
UNION ALL
SELECT CONCAT('Standard PCs (ID 33): ', COUNT(*)) FROM machines WHERE machinetypeid = 33 AND pctypeid IS NOT NULL
UNION ALL
SELECT CONCAT('Engineering PCs (ID 34): ', COUNT(*)) FROM machines WHERE machinetypeid = 34 AND pctypeid IS NOT NULL
UNION ALL
SELECT CONCAT('Shopfloor PCs (ID 35): ', COUNT(*)) FROM machines WHERE machinetypeid = 35 AND pctypeid IS NOT NULL;
SELECT '' AS '';
SELECT CONCAT('Completed at: ', NOW()) AS '';
SELECT '============================================================' AS '';
SET SQL_SAFE_UPDATES = 1;
-- =============================================================================
-- NOTES
-- =============================================================================
--
-- Old machine types (36-38) can be deactivated or deleted after verification:
-- UPDATE machinetypes SET isactive = 0 WHERE machinetypeid IN (36, 37, 38);
--
-- Website queries should filter by pctypeid, not machinetypeid for PC types:
-- - All PCs: WHERE pctypeid IS NOT NULL
-- - Shopfloor PCs: WHERE pctypeid = (SELECT pctypeid FROM pctype WHERE typename = 'Shopfloor')
-- - Standard PCs: WHERE pctypeid = (SELECT pctypeid FROM pctype WHERE typename = 'Standard')
-- - Engineer PCs: WHERE pctypeid = (SELECT pctypeid FROM pctype WHERE typename = 'Engineer')
--
-- =============================================================================

View File

@@ -223,6 +223,24 @@ SELECT CONCAT('Time: ', NOW()) AS '';
SELECT '============================================================' AS ''; SELECT '============================================================' AS '';
SELECT '' AS ''; SELECT '' AS '';
-- =====================================================
-- FIX: Migrate PCs from Old Machine Types
-- =====================================================
SELECT '============================================================' AS '';
SELECT 'FIX: MIGRATE PCS FROM OLD MACHINE TYPES' AS '';
SELECT '============================================================' AS '';
SELECT CONCAT('Start time: ', NOW()) AS '';
SELECT '' AS '';
source FIX_pc_machine_types.sql
SELECT '' AS '';
SELECT 'Machine type fix completed' AS '';
SELECT CONCAT('Time: ', NOW()) AS '';
SELECT '============================================================' AS '';
SELECT '' AS '';
-- ===================================================== -- =====================================================
-- VERIFICATION -- VERIFICATION
-- ===================================================== -- =====================================================

View File

@@ -110,22 +110,30 @@ Do While Not rs.EOF
End If End If
End If End If
' Build standard name: CSFName-Location-VendorModel (no dash between vendor and model) ' Determine printer name to use
If csfName <> "" And csfName <> "NONE" And csfName <> "gage lab " Then ' Prefer Windows Name from database if it's already in standardized format (contains dashes)
' Has CSF name ' Otherwise generate standardized name automatically
' Check if CSF name already matches the machine location (avoid duplication) If InStr(printerName, "-") > 0 Then
If cleanMachine <> "" And LCase(csfName) <> LCase(cleanMachine) Then ' Use database Windows Name as-is (user manually set it)
standardName = csfName & "-" & cleanMachine & "-" & vendor & shortDescription standardName = printerName
Else
' CSF name same as location, or no location - just use CSF-VendorModel
standardName = csfName & "-" & vendor & shortDescription
End If
Else Else
' No CSF name - use Location-VendorModel ' Generate standard name: CSFName-Location-VendorModel (no dash between vendor and model)
If cleanMachine <> "" Then If csfName <> "" And csfName <> "NONE" And csfName <> "gage lab " Then
standardName = cleanMachine & "-" & vendor & shortDescription ' Has CSF name
' Check if CSF name already matches the machine location (avoid duplication)
If cleanMachine <> "" And LCase(csfName) <> LCase(cleanMachine) Then
standardName = csfName & "-" & cleanMachine & "-" & vendor & shortDescription
Else
' CSF name same as location, or no location - just use CSF-VendorModel
standardName = csfName & "-" & vendor & shortDescription
End If
Else Else
standardName = "Printer" & rs("printerid") & "-" & vendor & shortDescription ' No CSF name - use Location-VendorModel
If cleanMachine <> "" Then
standardName = cleanMachine & "-" & vendor & shortDescription
Else
standardName = "Printer" & rs("printerid") & "-" & vendor & shortDescription
End If
End If End If
End If End If
standardName = Replace(standardName, """", "\""") standardName = Replace(standardName, """", "\""")

View File

@@ -156,75 +156,21 @@ Else
Response.Write(" echo ERROR: Could not download installer" & vbCrLf) Response.Write(" echo ERROR: Could not download installer" & vbCrLf)
Response.Write(")" & vbCrLf) Response.Write(")" & vbCrLf)
Else Else
' No installer - use universal driver ' No specific installer - use universal PrinterInstaller.exe
Dim driverName, driverInf Response.Write("echo Using universal printer installer..." & vbCrLf)
Select Case UCase(printer("vendor"))
Case "HP"
driverName = "HP Universal Printing PCL 6"
driverInf = "hpcu255u.inf"
Case "XEROX"
driverName = "Xerox Global Print Driver PCL6"
driverInf = "xeroxgpd.inf"
Case "HID"
driverName = "HP Universal Printing PCL 6"
driverInf = "hpcu255u.inf"
Case Else
driverName = "Generic / Text Only"
driverInf = ""
End Select
Response.Write("echo Using universal driver: " & driverName & vbCrLf)
Response.Write("echo." & vbCrLf) Response.Write("echo." & vbCrLf)
Response.Write("echo Downloading PrinterInstaller.exe..." & vbCrLf)
' Generate PowerShell script to install printer Response.Write("powershell -NoProfile -Command """ & _
Response.Write("powershell -NoProfile -ExecutionPolicy Bypass -Command """ & vbCrLf) "$ProgressPreference = 'SilentlyContinue'; " & _
Response.Write(" Write-Host 'Installing printer with universal driver...' -ForegroundColor Cyan;" & vbCrLf) "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; " & _
Response.Write(" " & vbCrLf) "Invoke-WebRequest -Uri 'https://tsgwp00525.rd.ds.ge.com/shopdb/installers/PrinterInstaller.exe' " & _
Response.Write(" $printerName = '" & Replace(printer("name"), "'", "''") & "';" & vbCrLf) "-OutFile '%TEMP%\PrinterInstaller.exe' -UseBasicParsing -UseDefaultCredentials""" & vbCrLf)
Response.Write(" $address = '" & Replace(printer("address"), "'", "''") & "';" & vbCrLf) Response.Write("if exist ""%TEMP%\PrinterInstaller.exe"" (" & vbCrLf)
Response.Write(" $driverName = '" & Replace(driverName, "'", "''") & "';" & vbCrLf) Response.Write(" echo Running installer..." & vbCrLf)
Response.Write(" $portName = 'IP_' + $address;" & vbCrLf) Response.Write(" ""%TEMP%\PrinterInstaller.exe"" ""/PRINTER=" & printer("standardname") & """" & vbCrLf)
Response.Write(" " & vbCrLf) Response.Write(" del ""%TEMP%\PrinterInstaller.exe"" 2>nul" & vbCrLf)
Response.Write(") else (" & vbCrLf)
' Check if driver is installed Response.Write(" echo ERROR: Could not download PrinterInstaller.exe" & vbCrLf)
If driverInf <> "" Then
Response.Write(" # Check if driver exists" & vbCrLf)
Response.Write(" $driver = Get-PrinterDriver -Name $driverName -ErrorAction SilentlyContinue;" & vbCrLf)
Response.Write(" if (-not $driver) {" & vbCrLf)
Response.Write(" Write-Host 'ERROR: Universal driver not found!' -ForegroundColor Red;" & vbCrLf)
Response.Write(" Write-Host 'Please install ' $driverName ' from Windows Update or driver package' -ForegroundColor Yellow;" & vbCrLf)
Response.Write(" exit 1;" & vbCrLf)
Response.Write(" }" & vbCrLf)
Response.Write(" " & vbCrLf)
End If
' Create port
Response.Write(" # Create TCP/IP port" & vbCrLf)
Response.Write(" $port = Get-PrinterPort -Name $portName -ErrorAction SilentlyContinue;" & vbCrLf)
Response.Write(" if (-not $port) {" & vbCrLf)
Response.Write(" Write-Host 'Creating printer port...' -ForegroundColor Yellow;" & vbCrLf)
Response.Write(" Add-PrinterPort -Name $portName -PrinterHostAddress $address -ErrorAction Stop;" & vbCrLf)
Response.Write(" Write-Host 'Port created successfully' -ForegroundColor Green;" & vbCrLf)
Response.Write(" } else {" & vbCrLf)
Response.Write(" Write-Host 'Port already exists' -ForegroundColor Green;" & vbCrLf)
Response.Write(" }" & vbCrLf)
Response.Write(" " & vbCrLf)
' Add printer
Response.Write(" # Add printer" & vbCrLf)
Response.Write(" $existingPrinter = Get-Printer -Name $printerName -ErrorAction SilentlyContinue;" & vbCrLf)
Response.Write(" if (-not $existingPrinter) {" & vbCrLf)
Response.Write(" Write-Host 'Adding printer...' -ForegroundColor Yellow;" & vbCrLf)
Response.Write(" Add-Printer -Name $printerName -DriverName $driverName -PortName $portName -ErrorAction Stop;" & vbCrLf)
Response.Write(" Write-Host 'Printer installed successfully!' -ForegroundColor Green;" & vbCrLf)
Response.Write(" } else {" & vbCrLf)
Response.Write(" Write-Host 'Printer already exists' -ForegroundColor Green;" & vbCrLf)
Response.Write(" }" & vbCrLf)
Response.Write("""" & vbCrLf)
Response.Write("" & vbCrLf)
Response.Write("if %ERRORLEVEL% neq 0 (" & vbCrLf)
Response.Write(" echo ERROR: Failed to install printer" & vbCrLf)
Response.Write(")" & vbCrLf) Response.Write(")" & vbCrLf)
End If End If