Clean up sql directory after production sync

- Remove 27 completed one-off migration scripts
- Remove old backup file (dev-backup-20251120)
- Remove completed shell scripts for prod import/export
- Archive migration_phase1-4 directories and documentation
- Keep only view_consolidation.sql as active script

All migrations have been applied to production.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
cproudlock
2025-12-11 12:33:49 -05:00
parent 0e3371f458
commit 4cdc2f0742
104 changed files with 0 additions and 5706 deletions

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,747 @@
# Production Database Migration Guide - December 10, 2025
## Overview
This guide covers all database changes made on December 10, 2025 that need to be applied to production. The changes are organized in the order they should be executed.
**Target Environment:**
- Production Server: Windows with IIS
- Database: MySQL 5.6
**Changes Summary:**
1. Table naming convention fix (snake_case to camelCase)
2. Compliance table column rename (snake_case to camelCase)
3. Fix backwards Controls relationships (Equipment->PC to PC->Equipment)
4. Propagate controller assignments to dualpath machines
5. Sync equipment data between dualpath partners
6. ASP filename standardization (remove underscores)
---
## Pre-Deployment Checklist
- [ ] Full database backup completed
- [ ] IIS scheduled for maintenance window
- [ ] All scripts tested on dev environment
- [ ] ASP file changes ready to deploy (pull from Gitea)
- [ ] Rollback plan understood
---
## Step 1: Full Database Backup
**CRITICAL: Do this before any other steps!**
```cmd
REM Windows Command Prompt (as Administrator)
"C:\Program Files\MySQL\MySQL Server 5.6\bin\mysqldump.exe" -u root -p shopdb > C:\backups\shopdb_backup_20251210_pre_migration.sql
```
Or using MySQL Workbench:
- Server > Data Export
- Select `shopdb` database
- Export to Self-Contained File
---
## Step 2: Stop IIS
```cmd
iisreset /stop
```
---
## Step 3: Table Naming Convention Fix
### 3.1 Drop dependent views
```sql
DROP VIEW IF EXISTS vw_active_pcs;
DROP VIEW IF EXISTS vw_dnc_config;
DROP VIEW IF EXISTS vw_engineer_pcs;
DROP VIEW IF EXISTS vw_pc_network_summary;
DROP VIEW IF EXISTS vw_pc_resolved_machines;
DROP VIEW IF EXISTS vw_pcs_by_hardware;
DROP VIEW IF EXISTS vw_shopfloor_comm_config;
DROP VIEW IF EXISTS vw_shopfloor_pcs;
DROP VIEW IF EXISTS vw_standard_pcs;
```
### 3.2 Rename tables
```sql
RENAME TABLE machine_overrides TO machineoverrides;
RENAME TABLE pc_comm_config TO commconfig;
RENAME TABLE pc_dnc_config TO dncconfig;
RENAME TABLE pc_dualpath_assignments TO dualpathassignments;
RENAME TABLE pc_network_interfaces TO networkinterfaces;
RENAME TABLE usb_checkouts TO usbcheckouts;
```
### 3.3 Recreate views
Run the CREATE VIEW statements from `sql/naming_convention_fix/04_drop_and_recreate_views.sql`
Or copy/paste each view below:
```sql
-- vw_active_pcs
CREATE VIEW vw_active_pcs AS
SELECT
pcmap.pcid AS pcid,
m.hostname AS hostname,
m.serialnumber AS serialnumber,
v.vendor AS manufacturer,
md.modelnumber AS model,
m.loggedinuser AS loggedinuser,
m.machinenumber AS machinenumber,
COALESCE(os.operatingsystem,'Unknown') AS operatingsystem,
m.lastupdated AS lastupdated,
pt.typename AS pctype
FROM machines m
JOIN pc_to_machine_id_mapping pcmap ON m.machineid = pcmap.new_machineid
JOIN pctype pt ON m.pctypeid = pt.pctypeid
LEFT JOIN models md ON m.modelnumberid = md.modelnumberid
LEFT JOIN vendors v ON md.vendorid = v.vendorid
LEFT JOIN operatingsystems os ON m.osid = os.osid
WHERE m.lastupdated > (NOW() - INTERVAL 30 DAY)
AND m.pctypeid IS NOT NULL
ORDER BY m.hostname;
-- vw_dnc_config
CREATE VIEW vw_dnc_config AS
SELECT
pcmap.pcid AS pcid,
m.hostname AS hostname,
dc.machineid AS machineid,
dc.dncpath AS dncpath,
dc.dnctype AS dnctype,
dc.isactive AS isactive
FROM dncconfig dc
JOIN machines m ON dc.machineid = m.machineid
JOIN pc_to_machine_id_mapping pcmap ON m.machineid = pcmap.new_machineid
WHERE dc.isactive = 1
ORDER BY m.hostname;
-- vw_engineer_pcs
CREATE VIEW vw_engineer_pcs AS
SELECT
pcmap.pcid AS pcid,
m.hostname AS hostname,
m.serialnumber AS serialnumber,
v.vendor AS manufacturer,
md.modelnumber AS model,
m.loggedinuser AS loggedinuser,
m.machinenumber AS machinenumber,
COALESCE(os.operatingsystem,'Unknown') AS operatingsystem,
m.lastupdated AS lastupdated
FROM machines m
JOIN pc_to_machine_id_mapping pcmap ON m.machineid = pcmap.new_machineid
JOIN pctype pt ON m.pctypeid = pt.pctypeid
LEFT JOIN models md ON m.modelnumberid = md.modelnumberid
LEFT JOIN vendors v ON md.vendorid = v.vendorid
LEFT JOIN operatingsystems os ON m.osid = os.osid
WHERE pt.typename = 'Engineer'
AND m.lastupdated > (NOW() - INTERVAL 30 DAY)
AND m.pctypeid IS NOT NULL
ORDER BY m.hostname;
-- vw_pc_network_summary
CREATE VIEW vw_pc_network_summary AS
SELECT
pcmap.pcid AS pcid,
m.hostname AS hostname,
m.machinenumber AS machinenumber,
COUNT(c.comid) AS interface_count,
GROUP_CONCAT(c.address ORDER BY c.comid ASC SEPARATOR ', ') AS ip_addresses,
GROUP_CONCAT(c.macaddress ORDER BY c.comid ASC SEPARATOR ', ') AS mac_addresses
FROM machines m
JOIN pc_to_machine_id_mapping pcmap ON m.machineid = pcmap.new_machineid
LEFT JOIN communications c ON m.machineid = c.machineid
AND c.comstypeid = (SELECT comstypeid FROM comstypes WHERE typename = 'Network_Interface' LIMIT 1)
AND c.isactive = 1
WHERE m.pctypeid IS NOT NULL
GROUP BY pcmap.pcid, m.hostname, m.machinenumber
ORDER BY m.hostname;
-- vw_pc_resolved_machines
CREATE VIEW vw_pc_resolved_machines AS
SELECT
pcmap.pcid AS pcid,
m.machineid AS machineid,
m.hostname AS hostname,
m.machinenumber AS machinenumber,
pt.typename AS pctype,
COALESCE(mo.machinenumber, m.machinenumber) AS resolved_machinenumber
FROM machines m
JOIN pc_to_machine_id_mapping pcmap ON m.machineid = pcmap.new_machineid
JOIN pctype pt ON m.pctypeid = pt.pctypeid
LEFT JOIN machineoverrides mo ON pcmap.pcid = mo.pcid
WHERE m.pctypeid IS NOT NULL
ORDER BY m.hostname;
-- vw_pcs_by_hardware
CREATE VIEW vw_pcs_by_hardware AS
SELECT
COALESCE(v.vendor,'Unknown') AS manufacturer,
COALESCE(md.modelnumber,'Unknown') AS model,
COUNT(m.machineid) AS count,
GROUP_CONCAT(DISTINCT pt.typename ORDER BY pt.typename ASC SEPARATOR ', ') AS pc_types
FROM machines m
JOIN pc_to_machine_id_mapping pcmap ON m.machineid = pcmap.new_machineid
LEFT JOIN models md ON m.modelnumberid = md.modelnumberid
LEFT JOIN vendors v ON md.vendorid = v.vendorid
LEFT JOIN pctype pt ON m.pctypeid = pt.pctypeid
WHERE m.lastupdated > (NOW() - INTERVAL 30 DAY)
AND m.pctypeid IS NOT NULL
GROUP BY v.vendor, md.modelnumber
ORDER BY COUNT(m.machineid) DESC, v.vendor, md.modelnumber;
-- vw_shopfloor_comm_config
CREATE VIEW vw_shopfloor_comm_config AS
SELECT
pcmap.pcid AS pcid,
m.hostname AS hostname,
m.machinenumber AS machinenumber,
pt.typename AS pctype,
c.address AS ip_address,
c.port AS port_or_socket,
c.baud AS baud,
c.databits AS databits,
c.stopbits AS stopbits,
c.parity AS parity,
ct.typename AS comm_type
FROM machines m
JOIN pc_to_machine_id_mapping pcmap ON m.machineid = pcmap.new_machineid
JOIN pctype pt ON m.pctypeid = pt.pctypeid
LEFT JOIN communications c ON m.machineid = c.machineid AND c.isactive = 1
LEFT JOIN comstypes ct ON c.comstypeid = ct.comstypeid
WHERE pt.typename = 'Shopfloor'
AND m.pctypeid IS NOT NULL
AND ct.typename IN ('IP','Serial')
ORDER BY m.machinenumber, m.hostname;
-- vw_shopfloor_pcs
CREATE VIEW vw_shopfloor_pcs AS
SELECT
pcmap.pcid AS pcid,
m.hostname AS hostname,
m.serialnumber AS serialnumber,
v.vendor AS manufacturer,
md.modelnumber AS model,
m.loggedinuser AS loggedinuser,
COALESCE(CONVERT(mo.machinenumber USING utf8mb4), CONVERT(m.machinenumber USING utf8mb4)) AS machinenumber,
COALESCE(os.operatingsystem,'Unknown') AS operatingsystem,
m.lastupdated AS lastupdated,
m.lastboottime AS lastboottime,
(TO_DAYS(NOW()) - TO_DAYS(m.lastboottime)) AS uptime_days
FROM machines m
JOIN pc_to_machine_id_mapping pcmap ON m.machineid = pcmap.new_machineid
JOIN pctype pt ON m.pctypeid = pt.pctypeid
LEFT JOIN machineoverrides mo ON pcmap.pcid = mo.pcid
LEFT JOIN models md ON m.modelnumberid = md.modelnumberid
LEFT JOIN vendors v ON md.vendorid = v.vendorid
LEFT JOIN operatingsystems os ON m.osid = os.osid
WHERE pt.typename = 'Shopfloor'
AND m.lastupdated > (NOW() - INTERVAL 30 DAY)
AND m.pctypeid IS NOT NULL
ORDER BY COALESCE(CONVERT(mo.machinenumber USING utf8mb4), CONVERT(m.machinenumber USING utf8mb4)), m.hostname;
-- vw_standard_pcs
CREATE VIEW vw_standard_pcs AS
SELECT
pcmap.pcid AS pcid,
m.hostname AS hostname,
m.serialnumber AS serialnumber,
v.vendor AS manufacturer,
md.modelnumber AS model,
m.loggedinuser AS loggedinuser,
m.machinenumber AS machinenumber,
COALESCE(os.operatingsystem,'Unknown') AS operatingsystem,
m.lastupdated AS lastupdated
FROM machines m
JOIN pc_to_machine_id_mapping pcmap ON m.machineid = pcmap.new_machineid
JOIN pctype pt ON m.pctypeid = pt.pctypeid
LEFT JOIN models md ON m.modelnumberid = md.modelnumberid
LEFT JOIN vendors v ON md.vendorid = v.vendorid
LEFT JOIN operatingsystems os ON m.osid = os.osid
WHERE pt.typename = 'Standard'
AND m.lastupdated > (NOW() - INTERVAL 30 DAY)
AND m.pctypeid IS NOT NULL
ORDER BY m.hostname;
```
### 3.4 Verify naming changes
```sql
-- Should show new names
SHOW TABLES LIKE '%config%';
SHOW TABLES LIKE '%override%';
SHOW TABLES LIKE '%checkout%';
-- Should return data
SELECT COUNT(*) FROM vw_shopfloor_pcs;
SELECT COUNT(*) FROM vw_active_pcs;
```
---
## Step 4: Fix Compliance Table Column Names
Rename snake_case columns to camelCase in compliance and compliancescans tables.
Run `sql/naming_convention_fix/07_fix_compliance_columns.sql` or execute:
```sql
-- Drop dependent view
DROP VIEW IF EXISTS vw_compliance_summary;
-- Rename compliance table columns
ALTER TABLE compliance
CHANGE COLUMN scan_date scandate datetime,
CHANGE COLUMN deployment_notes deploymentnotes text,
CHANGE COLUMN is_third_party_managed isthirdpartymanaged enum('Yes','No','NA') DEFAULT 'NA',
CHANGE COLUMN third_party_manager thirdpartymanager varchar(255),
CHANGE COLUMN ot_asset_system otassetsystem varchar(255),
CHANGE COLUMN ot_asset_device otassetdevice varchar(255),
CHANGE COLUMN ot_asset_location otassetlocation varchar(255),
CHANGE COLUMN ot_asset_device_type otassetdevicetype varchar(100),
CHANGE COLUMN ot_asset_category otassetcategory varchar(100),
CHANGE COLUMN ot_asset_last_seen otassetlastseen datetime,
CHANGE COLUMN ot_asset_ip_source otassetipsource varchar(100),
CHANGE COLUMN is_compliant iscompliant tinyint(1),
CHANGE COLUMN compliance_notes compliancenotes text;
-- Rename compliancescans table columns
ALTER TABLE compliancescans
CHANGE COLUMN scan_name scanname varchar(255),
CHANGE COLUMN scan_date scandate datetime NOT NULL,
CHANGE COLUMN scan_result scanresult enum('Pass','Fail','Warning','Info') DEFAULT 'Info',
CHANGE COLUMN scan_details scandetails text;
-- Recreate view with new column names
CREATE VIEW vw_compliance_summary AS
SELECT
m.machineid,
m.machinenumber,
m.hostname,
m.serialnumber,
c.scan,
c.scandate,
c.isthirdpartymanaged,
c.thirdpartymanager,
c.mft,
c.iscompliant,
c.deploymentnotes,
c.otassetsystem,
c.otassetdevice,
c.otassetlocation,
(TO_DAYS(CURDATE()) - TO_DAYS(c.scandate)) AS days_since_scan,
CASE
WHEN c.scandate IS NULL THEN 'Never Scanned'
WHEN c.scandate < (CURDATE() - INTERVAL 90 DAY) THEN 'Scan Overdue'
WHEN c.scandate < (CURDATE() - INTERVAL 30 DAY) THEN 'Scan Due Soon'
ELSE 'Scan Current'
END AS scan_status
FROM machines m
LEFT JOIN compliance c ON m.machineid = c.machineid
WHERE m.isactive = 1;
-- Verify
SHOW COLUMNS FROM compliance;
SHOW COLUMNS FROM compliancescans;
SELECT COUNT(*) FROM vw_compliance_summary;
```
---
## Step 5: Fix Dualpath Controller Relationships
This fixes two issues:
1. Backwards relationship direction (Equipment->Controls->PC should be PC->Controls->Equipment)
2. Missing controller assignments on dualpath partner machines
Run `sql/fix_dualpath_controller_relationships.sql` or execute:
```sql
-- ============================================================================
-- STEP 4.1: Fix incorrectly directed relationships
-- ============================================================================
-- Create temp table to store bad relationships
CREATE TEMPORARY TABLE IF NOT EXISTS temp_bad_controls AS
SELECT
mr.relationshipid,
mr.machineid AS equipment_machineid,
mr.related_machineid AS pc_machineid,
mr.relationshiptypeid
FROM machinerelationships mr
JOIN machines m1 ON mr.machineid = m1.machineid
JOIN machines m2 ON mr.related_machineid = m2.machineid
WHERE mr.relationshiptypeid = (SELECT relationshiptypeid FROM relationshiptypes WHERE relationshiptype = 'Controls')
AND m1.pctypeid IS NULL
AND m2.pctypeid IS NOT NULL
AND mr.isactive = 1;
-- Show what will be fixed
SELECT 'Fixing these backwards relationships:' AS status;
SELECT * FROM temp_bad_controls;
-- Delete the bad relationships
DELETE mr FROM machinerelationships mr
INNER JOIN temp_bad_controls t ON mr.relationshipid = t.relationshipid;
-- Create the correct relationships (PC -> Controls -> Equipment)
INSERT INTO machinerelationships (machineid, related_machineid, relationshiptypeid, isactive)
SELECT
pc_machineid AS machineid,
equipment_machineid AS related_machineid,
relationshiptypeid,
1 AS isactive
FROM temp_bad_controls t
WHERE NOT EXISTS (
SELECT 1 FROM machinerelationships mr2
WHERE mr2.machineid = t.pc_machineid
AND mr2.related_machineid = t.equipment_machineid
AND mr2.relationshiptypeid = t.relationshiptypeid
AND mr2.isactive = 1
);
DROP TEMPORARY TABLE IF EXISTS temp_bad_controls;
-- ============================================================================
-- STEP 4.2: Propagate controllers to dualpath machines
-- ============================================================================
-- Create missing controller relationships for dualpath partners
INSERT INTO machinerelationships (machineid, related_machineid, relationshiptypeid, isactive)
SELECT DISTINCT
pc.machineid AS machineid,
m2.machineid AS related_machineid,
ctrl.relationshiptypeid,
1 AS isactive
FROM machinerelationships ctrl
JOIN machines m1 ON ctrl.related_machineid = m1.machineid
JOIN machines pc ON ctrl.machineid = pc.machineid
JOIN machinerelationships dp ON m1.machineid = dp.machineid
JOIN machines m2 ON dp.related_machineid = m2.machineid
JOIN relationshiptypes rt_ctrl ON ctrl.relationshiptypeid = rt_ctrl.relationshiptypeid
JOIN relationshiptypes rt_dp ON dp.relationshiptypeid = rt_dp.relationshiptypeid
WHERE rt_ctrl.relationshiptype = 'Controls'
AND rt_dp.relationshiptype = 'Dualpath'
AND ctrl.isactive = 1
AND dp.isactive = 1
AND NOT EXISTS (
SELECT 1 FROM machinerelationships ctrl2
WHERE ctrl2.machineid = pc.machineid
AND ctrl2.related_machineid = m2.machineid
AND ctrl2.relationshiptypeid = ctrl.relationshiptypeid
AND ctrl2.isactive = 1
);
-- ============================================================================
-- STEP 4.3: Verify
-- ============================================================================
-- Should show 0 backwards relationships
SELECT
'Backwards relationships remaining:' AS check_type,
COUNT(*) AS count
FROM machinerelationships mr
JOIN machines m1 ON mr.machineid = m1.machineid
JOIN machines m2 ON mr.related_machineid = m2.machineid
JOIN relationshiptypes rt ON mr.relationshiptypeid = rt.relationshiptypeid
WHERE rt.relationshiptype = 'Controls'
AND m1.pctypeid IS NULL
AND m2.pctypeid IS NOT NULL
AND mr.isactive = 1;
SELECT 'Controller relationship fix complete!' AS status;
```
---
## Step 6: Sync Dualpath Equipment Data
This syncs controller type, model, and communication settings between dualpath partners.
Run `sql/sync_dualpath_equipment_data.sql` or execute:
```sql
-- ============================================================================
-- STEP 5.1: Sync controller settings
-- ============================================================================
-- Update controllertypeid where m1 has it and m2 doesn't
UPDATE machines m2
JOIN machinerelationships mr ON m2.machineid = mr.related_machineid
JOIN machines m1 ON mr.machineid = m1.machineid
JOIN relationshiptypes rt ON mr.relationshiptypeid = rt.relationshiptypeid
SET m2.controllertypeid = m1.controllertypeid
WHERE rt.relationshiptype = 'Dualpath'
AND mr.isactive = 1
AND m1.controllertypeid IS NOT NULL
AND m2.controllertypeid IS NULL;
-- Update controllerosid
UPDATE machines m2
JOIN machinerelationships mr ON m2.machineid = mr.related_machineid
JOIN machines m1 ON mr.machineid = m1.machineid
JOIN relationshiptypes rt ON mr.relationshiptypeid = rt.relationshiptypeid
SET m2.controllerosid = m1.controllerosid
WHERE rt.relationshiptype = 'Dualpath'
AND mr.isactive = 1
AND m1.controllerosid IS NOT NULL
AND m2.controllerosid IS NULL;
-- Update modelnumberid
UPDATE machines m2
JOIN machinerelationships mr ON m2.machineid = mr.related_machineid
JOIN machines m1 ON mr.machineid = m1.machineid
JOIN relationshiptypes rt ON mr.relationshiptypeid = rt.relationshiptypeid
SET m2.modelnumberid = m1.modelnumberid
WHERE rt.relationshiptype = 'Dualpath'
AND mr.isactive = 1
AND m1.modelnumberid IS NOT NULL
AND m2.modelnumberid IS NULL;
-- Update serialnumber
UPDATE machines m2
JOIN machinerelationships mr ON m2.machineid = mr.related_machineid
JOIN machines m1 ON mr.machineid = m1.machineid
JOIN relationshiptypes rt ON mr.relationshiptypeid = rt.relationshiptypeid
SET m2.serialnumber = m1.serialnumber
WHERE rt.relationshiptype = 'Dualpath'
AND mr.isactive = 1
AND m1.serialnumber IS NOT NULL AND m1.serialnumber <> ''
AND (m2.serialnumber IS NULL OR m2.serialnumber = '');
-- ============================================================================
-- STEP 5.2: Sync communication settings
-- ============================================================================
SET @ip_comstypeid = (SELECT comstypeid FROM comstypes WHERE typename = 'IP' LIMIT 1);
SET @serial_comstypeid = (SELECT comstypeid FROM comstypes WHERE typename = 'Serial' LIMIT 1);
-- Insert IP comm config for dualpath partners missing it
INSERT INTO communications (machineid, comstypeid, address, port, isactive)
SELECT DISTINCT
m2.machineid,
c1.comstypeid,
c1.address,
c1.port,
1
FROM machinerelationships mr
JOIN machines m1 ON mr.machineid = m1.machineid
JOIN machines m2 ON mr.related_machineid = m2.machineid
JOIN relationshiptypes rt ON mr.relationshiptypeid = rt.relationshiptypeid
JOIN communications c1 ON m1.machineid = c1.machineid AND c1.comstypeid = @ip_comstypeid AND c1.isactive = 1
WHERE rt.relationshiptype = 'Dualpath'
AND mr.isactive = 1
AND NOT EXISTS (
SELECT 1 FROM communications c2
WHERE c2.machineid = m2.machineid
AND c2.comstypeid = @ip_comstypeid
AND c2.isactive = 1
);
-- Insert Serial comm config for dualpath partners missing it
INSERT INTO communications (machineid, comstypeid, address, port, baud, databits, stopbits, parity, isactive)
SELECT DISTINCT
m2.machineid,
c1.comstypeid,
c1.address,
c1.port,
c1.baud,
c1.databits,
c1.stopbits,
c1.parity,
1
FROM machinerelationships mr
JOIN machines m1 ON mr.machineid = m1.machineid
JOIN machines m2 ON mr.related_machineid = m2.machineid
JOIN relationshiptypes rt ON mr.relationshiptypeid = rt.relationshiptypeid
JOIN communications c1 ON m1.machineid = c1.machineid AND c1.comstypeid = @serial_comstypeid AND c1.isactive = 1
WHERE rt.relationshiptype = 'Dualpath'
AND mr.isactive = 1
AND NOT EXISTS (
SELECT 1 FROM communications c2
WHERE c2.machineid = m2.machineid
AND c2.comstypeid = @serial_comstypeid
AND c2.isactive = 1
);
SELECT 'Dualpath data sync complete!' AS status;
```
---
## Step 7: Deploy Updated ASP Files
Pull the latest code from Gitea which includes:
- Updated table names in all ASP files
- New dualpath propagation functions in `includes/db_helpers.asp`
- Updated save pages that call propagation functions
- Renamed ASP files (underscores removed)
```cmd
cd C:\inetpub\wwwroot\shopdb
git pull origin master
```
Or copy files manually from a prepared deployment package.
**IMPORTANT:** After git pull, verify the old underscore files were deleted. If they still exist, remove them manually:
```cmd
REM These old files should no longer exist after git pull
REM If they do, delete them:
del addlink_direct.asp
del addsubnetbackend_direct.asp
del admin_clear_cache.asp
del api_businessunits.asp
del api_printers.asp
del api_shopfloor.asp
del api_usb.asp
del bulk_update_notification_types.asp
del check_duplicate_printers.asp
del check_printer_machines_count.asp
del checkin_usb.asp
del checkout_usb.asp
del cleanup_duplicate_printers_execute.asp
del displaylocation_device.asp
del editapplication_direct.asp
del insert_all_printer_machines.asp
del install_printer.asp
del machine_edit.asp
del machine_map.asp
del machine_map_editor.asp
del network_devices.asp
del network_map.asp
del network_map_debug.asp
del printer_installer_map.asp
del printer_links_generator.asp
del printer_lookup.asp
del quickadd_application.asp
del refresh_zabbix_cache.asp
del save_network_device.asp
del saveapplication_direct.asp
del savecheckin_usb.asp
del savecheckout_usb.asp
del savedevice_direct.asp
del savemachine_direct.asp
del savemodel_direct.asp
del savenotification_direct.asp
del saveprinter_direct.asp
del saveusb_direct.asp
del savevendor_direct.asp
del updatedevice_direct.asp
del updatelink_direct.asp
del updatenotification_direct.asp
del updatepc_direct.asp
del updatesubnet_direct.asp
del usb_history.asp
```
---
## Step 8: Start IIS
```cmd
iisreset /start
```
---
## Step 9: Verify Everything Works
### 8.1 Test key pages in browser:
- http://yourserver/displaypcs.asp - PC listing
- http://yourserver/displaymachines.asp - Equipment listing
- http://yourserver/displayusb.asp - USB checkout
### 8.2 Test a dualpath machine:
1. Find a machine with a dualpath relationship
2. Verify it shows the correct controlling PC
3. Verify both dualpath partners show same controller
### 8.3 Test the API:
```
http://yourserver/api.asp?action=getDashboardData
```
---
## Step 10: Optional Cleanup
After confirming everything works (wait at least a day):
```sql
-- Drop old migration backup tables
DROP TABLE IF EXISTS _backup_equipment_ips_phase1_5;
DROP TABLE IF EXISTS pc_backup_phase2;
```
---
## Rollback Plan
If issues occur, restore from backup:
```cmd
REM Stop IIS
iisreset /stop
REM Restore database
"C:\Program Files\MySQL\MySQL Server 5.6\bin\mysql.exe" -u root -p shopdb < C:\backups\shopdb_backup_20251210_pre_migration.sql
REM Restore ASP files
cd C:\inetpub\wwwroot\shopdb
git checkout HEAD~3 -- .
REM Start IIS
iisreset /start
```
---
## Summary of Changes
| Category | Change | Script |
|----------|--------|--------|
| Naming | Rename 6 tables (snake_case to camelCase) | naming_convention_fix/*.sql |
| Naming | Rename 17 columns in compliance tables | naming_convention_fix/07_*.sql |
| Naming | Recreate 9 views with new table names | naming_convention_fix/04_*.sql |
| Naming | Rename 45 ASP files (remove underscores) | naming_convention_fix/09_*.sh |
| Relationships | Fix backwards Controls relationships | fix_dualpath_controller_relationships.sql |
| Relationships | Propagate controllers to dualpath machines | fix_dualpath_controller_relationships.sql |
| Data Sync | Sync equipment data between dualpath pairs | sync_dualpath_equipment_data.sql |
| ASP Files | Update table references in 10+ ASP files | git pull |
| ASP Files | Add dualpath propagation functions | git pull |
| ASP Files | Delete 6 test/duplicate files | git pull |
---
## Scripts Reference
All scripts are in `/sql/` directory:
| Script | Purpose |
|--------|---------|
| `naming_convention_fix/03_rename_tables.sql` | Table renames |
| `naming_convention_fix/04_drop_and_recreate_views.sql` | View recreation |
| `naming_convention_fix/07_fix_compliance_columns.sql` | Compliance column renames |
| `naming_convention_fix/09_rename_asp_files.sh` | ASP filename renames (Linux) |
| `naming_convention_fix/09_rename_asp_files.ps1` | ASP filename renames (Windows) |
| `fix_dualpath_controller_relationships.sql` | Fix relationship direction + propagate |
| `sync_dualpath_equipment_data.sql` | Sync equipment data between dualpath pairs |
---
## Contact
If issues occur during migration, check:
1. IIS logs: `C:\inetpub\logs\LogFiles\`
2. MySQL error log
3. Gitea issues: http://localhost:3000/cproudlock/shopdb/issues

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,211 @@
# Production Data Import - Process Documentation
**Date Created:** 2025-11-13
**Purpose:** Import notifications, notificationtypes, printers, and knowledgebase from production backup into dev database
## Overview
This process imports the latest production data while avoiding duplicates and preserving any dev-specific test data.
## Files Created
### Extraction Scripts
- `extract_prod_data.sh` - Extracts complete table dumps (structure + data) from production backup
- `extract_prod_data_inserts_only.sh` - Extracts only INSERT statements (no table structure)
### Extracted Data Files
- `prod_notifications.sql` - Full notifications table dump from production
- `prod_notificationtypes.sql` - Full notificationtypes table dump from production
- `prod_printers.sql` - Full printers table dump from production
- `prod_knowledgebase.sql` - Full knowledgebase table dump from production
### INSERT-Only Files (for clean import)
- `prod_notifications_inserts.sql` - Only INSERT statements for notifications (56 rows)
- `prod_notificationtypes_inserts.sql` - Only INSERT statements for notification types (4 rows)
- `prod_printers_inserts.sql` - Only INSERT statements for printers (45 rows)
- `prod_knowledgebase_inserts.sql` - Only INSERT statements for knowledgebase (214 rows)
### Import Scripts
- `import_prod_data.sql` - Original import script (uses SOURCE command, doesn't work with Docker)
- `import_prod_data_execute.sql` - Attempted direct execution (failed due to Docker file access)
- `import_prod_data_direct.sh` - First working version (cleared all data before import)
- `import_prod_data_clean.sh` - Improved version (INSERT-only approach, but syntax errors)
- **`import_prod_data_smart.sh`** - FINAL VERSION (uses REPLACE to handle duplicates intelligently)
### Rollback Script
- `rollback_prod_import.sh` - Restores data from backup tables if import fails or needs to be undone
## Import Strategy
### Approach: Smart Merge with REPLACE
Instead of DELETE + INSERT (which loses everything), we use **REPLACE INTO** which:
1. Inserts new records that don't exist
2. Updates existing records with matching primary keys
3. Preserves the integrity of the data
### Tables Imported
1. **notificationtypes** (lookup table) - 4 types
- Info
- Warning
- Danger
- Success
2. **notifications** - 56 production notifications
- Active notifications for current awareness
- Historical notifications for reference
- Linked to notificationtypes via foreign key
3. **printers** - 45 production printers
- Active printer configurations
- IP addresses, models, locations
- Printer install paths for self-service
4. **knowledgebase** - 214 knowledge base articles
- How-to guides
- Documentation links
- Troubleshooting articles
- Click tracking for popular articles
## Schema Differences Handled
### Issue 1: printers table - `fqdn` column
- **Production:** Has `fqdn` column
- **Dev:** Already has `fqdn` column
- **Resolution:** No change needed, column exists
### Issue 2: Extracted SQL includes table structure
- **Problem:** Full dumps include CREATE TABLE which conflicts with existing tables
- **Solution:** Extract only INSERT statements using grep
### Issue 3: INSERT statement formatting
- **Problem:** Original extraction had syntax errors with multiple INSERT statements
- **Solution:** Ensure proper SQL formatting and statement separation
## Bugs Fixed
### machine_edit.asp (Line 157) - Column Name Mismatch
**Error:** `Item cannot be found in the collection corresponding to the requested name or ordinal`
**Root Cause:** Code was using underscore-separated column names, but database has camelCase names
**Fixed Columns:**
- `is_third_party_managed``isthirdpartymanaged`
- `third_party_manager``thirdpartymanager`
- `ot_asset_system` → (column doesn't exist, removed reference)
- `ot_asset_device_type``dodassettype`
**File:** `/home/camp/projects/windows/shopdb/machine_edit.asp:157-160`
## Usage Instructions
### To Import Production Data
```bash
cd /home/camp/projects/windows/shopdb/sql
bash import_prod_data_smart.sh
```
The script will:
1. Create backup tables with `_backup_20251113` suffix
2. Show current counts (before import)
3. Use REPLACE INTO to merge production data
4. Show new counts (after import)
5. Display sample data for verification
6. Show comparison of before/after counts
### To Rollback Import
If something goes wrong or you need to restore the previous state:
```bash
cd /home/camp/projects/windows/shopdb/sql
bash rollback_prod_import.sh
```
Type `yes` when prompted to confirm rollback.
## Current Dev Database Status
**Before Any Import (baseline):**
- Notifications: 34
- Notification Types: 4
- Printers: 41
- Knowledgebase: 204
**After Failed Import Attempts:**
- Rolled back successfully to baseline counts
**Expected After Successful Smart Import:**
- Notifications: ~56 (replaced with production data)
- Notification Types: 4 (unchanged, same in prod)
- Printers: ~45 (replaced with production data)
- Knowledgebase: ~214 (merged with production data)
## Source Data
**Production Backup File:** `/home/camp/projects/windows/database-backup-11-13-25-eod.sql`
- **Date:** November 13, 2025 (End of Day)
- **Size:** 1.4 MB
- **Database:** shopdb
## Verification Queries
After import, verify data with these queries:
```sql
-- Check counts
SELECT
(SELECT COUNT(*) FROM notifications) AS notifications,
(SELECT COUNT(*) FROM notificationtypes) AS notificationtypes,
(SELECT COUNT(*) FROM printers) AS printers,
(SELECT COUNT(*) FROM knowledgebase) AS knowledgebase;
-- Check active notifications
SELECT notificationid, notification, starttime, endtime, isactive
FROM notifications
WHERE isactive = 1
ORDER BY starttime DESC
LIMIT 10;
-- Check active printers
SELECT printerid, printerwindowsname, ipaddress, isactive
FROM printers
WHERE isactive = 1
LIMIT 10;
-- Check popular knowledge base articles
SELECT linkid, shortdescription, clicks, isactive
FROM knowledgebase
WHERE isactive = 1
ORDER BY clicks DESC
LIMIT 10;
```
## Lessons Learned
1. **Docker MySQL Source Command Limitation:** The SOURCE command in MySQL doesn't work well when MySQL is in a Docker container and files are on the host. Solution: Use cat to pipe SQL into docker exec.
2. **Schema Drift:** Production and dev databases had schema differences. Always check column names match before importing.
3. **Full Dumps vs INSERT-Only:** Extracting full table dumps causes conflicts. Extract only INSERT statements for cleaner imports.
4. **REPLACE vs DELETE+INSERT:** Using REPLACE INTO is safer as it handles duplicates intelligently without losing all data first.
5. **Always Backup First:** Creating backup tables before import is essential for quick rollback capability.
## TODO for Future Improvements
- [ ] Create automated daily/weekly sync script
- [ ] Add validation checks before import (schema comparison)
- [ ] Create migration script to align dev schema with production
- [ ] Add logging of import results to a database table
- [ ] Create web UI for managing imports
## Support
For issues or questions, check:
- IIS Logs: `/home/camp/projects/windows/logs/shopdb/ex*.log`
- This documentation: `/home/camp/projects/windows/shopdb/sql/PROD_IMPORT_README.md`
- Session notes: `/home/camp/projects/windows/shopdb/SESSION_SUMMARY_2025-11-13.md`

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,119 @@
-- =====================================================
-- SCRIPT 01: Create Communications Infrastructure
-- =====================================================
-- Date: 2025-11-06
-- Purpose: Create comstypes and communications tables
-- Status: REVERSIBLE (see ROLLBACK_01)
-- Estimated Time: 2-3 minutes
-- =====================================================
USE shopdb;
SET SQL_SAFE_UPDATES = 0;
-- =====================================================
-- STEP 1: Create comstypes table
-- =====================================================
CREATE TABLE IF NOT EXISTS comstypes (
comstypeid INT(11) PRIMARY KEY AUTO_INCREMENT,
typename VARCHAR(50) NOT NULL UNIQUE,
description VARCHAR(255),
requires_port TINYINT(1) DEFAULT 0,
requires_ipaddress TINYINT(1) DEFAULT 0,
isactive TINYINT(1) DEFAULT 1,
displayorder INT(11) DEFAULT 0,
dateadded DATETIME DEFAULT CURRENT_TIMESTAMP,
KEY idx_isactive (isactive),
KEY idx_displayorder (displayorder)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
COMMENT='Communication types (IP, Serial, Network Interface, etc.)';
-- Insert communication types
INSERT INTO comstypes (typename, description, requires_port, requires_ipaddress, displayorder) VALUES
('IP', 'TCP/IP Network Communication', 0, 1, 1),
('Serial', 'Serial Port Communication (RS-232)', 1, 0, 2),
('Network_Interface', 'Network Interface Card', 0, 1, 3),
('USB', 'USB Connection', 1, 0, 4),
('Parallel', 'Parallel Port Connection', 1, 0, 5),
('VNC', 'Virtual Network Computing', 0, 1, 6),
('FTP', 'File Transfer Protocol', 0, 1, 7),
('DNC', 'Direct Numerical Control', 0, 1, 8);
-- =====================================================
-- STEP 2: Create communications table
-- =====================================================
CREATE TABLE IF NOT EXISTS communications (
comid INT(11) PRIMARY KEY AUTO_INCREMENT,
machineid INT(11) NOT NULL,
comstypeid INT(11) NOT NULL,
-- Generic address field (IP, COM1, USB1, etc.)
address VARCHAR(100),
-- Port/socket information
port INT(11),
portname VARCHAR(20), -- COM1, COM2, LPT1, etc.
-- Network-specific
macaddress VARCHAR(17),
subnetmask VARCHAR(45),
defaultgateway VARCHAR(45),
dnsserver VARCHAR(45),
isdhcp TINYINT(1) DEFAULT 0,
-- Serial-specific
baud INT(11),
databits INT(11),
stopbits VARCHAR(5),
parity VARCHAR(10),
flowcontrol VARCHAR(20),
-- Protocol-specific
protocol VARCHAR(50),
username VARCHAR(100),
password VARCHAR(255),
-- General metadata
interfacename VARCHAR(255),
description VARCHAR(255),
isprimary TINYINT(1) DEFAULT 0,
isactive TINYINT(1) DEFAULT 1,
ismachinenetwork TINYINT(1) DEFAULT 0, -- Machine network vs office network
-- Additional settings as JSON
settings TEXT, -- JSON for VLAN, etc.
-- Audit fields
lastupdated DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
dateadded DATETIME DEFAULT CURRENT_TIMESTAMP,
-- Indexes
KEY idx_machineid (machineid),
KEY idx_comstypeid (comstypeid),
KEY idx_address (address),
KEY idx_isactive (isactive),
KEY idx_isprimary (isprimary),
-- Foreign Keys
CONSTRAINT fk_communications_machineid FOREIGN KEY (machineid) REFERENCES machines(machineid),
CONSTRAINT fk_communications_comstypeid FOREIGN KEY (comstypeid) REFERENCES comstypes(comstypeid)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
COMMENT='Generic communications table for all connection types';
-- =====================================================
-- VERIFICATION
-- =====================================================
SELECT '✓ comstypes table created' AS status, COUNT(*) AS type_count FROM comstypes;
SELECT '✓ communications table created' AS status;
SELECT '✓ Script 01 completed successfully' AS status;
SET SQL_SAFE_UPDATES = 1;
-- =====================================================
-- NOTES
-- =====================================================
-- Next: Run script 02_extend_machines_table.sql
-- Rollback: Run ROLLBACK_01_communications_infrastructure.sql
-- =====================================================

View File

@@ -0,0 +1,96 @@
-- =====================================================
-- SCRIPT 02: Extend Machines Table for PC Data
-- =====================================================
-- Date: 2025-11-06
-- Purpose: Add PC-related columns to machines table
-- Status: REVERSIBLE (see ROLLBACK_02)
-- Estimated Time: 2-3 minutes
-- NOTE: Warranty data goes to separate warranties table (script 04)
-- =====================================================
USE shopdb;
SET SQL_SAFE_UPDATES = 0;
-- =====================================================
-- STEP 1: Add PC-specific fields
-- =====================================================
-- Check current structure
SELECT 'Current machines table structure:' AS info;
SHOW COLUMNS FROM machines;
-- Add PC-specific fields
ALTER TABLE machines
ADD COLUMN hostname VARCHAR(100) AFTER machinenumber,
ADD COLUMN loggedinuser VARCHAR(100) AFTER hostname,
ADD COLUMN serialnumber VARCHAR(100) AFTER modelnumberid;
-- Add OS and status fields
ALTER TABLE machines
ADD COLUMN osid INT(11) AFTER serialnumber,
ADD COLUMN machinestatusid INT(11) AFTER osid,
ADD COLUMN pctypeid INT(11) AFTER machinetypeid;
-- Add controller fields (for CNCs)
ALTER TABLE machines
ADD COLUMN controllertypeid INT(11) AFTER modelnumberid,
ADD COLUMN controllerosid INT(11) AFTER controllertypeid;
-- =====================================================
-- STEP 2: Add configuration flags
-- =====================================================
ALTER TABLE machines
ADD COLUMN requires_manual_machine_config TINYINT(1) DEFAULT 0 AFTER islocationonly;
-- =====================================================
-- STEP 3: Add audit fields
-- =====================================================
ALTER TABLE machines
ADD COLUMN lastupdated DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP AFTER requires_manual_machine_config,
ADD COLUMN dateadded DATETIME DEFAULT CURRENT_TIMESTAMP AFTER lastupdated;
-- =====================================================
-- STEP 4: Create indexes
-- =====================================================
CREATE INDEX idx_machines_hostname ON machines(hostname);
CREATE INDEX idx_machines_serialnumber ON machines(serialnumber);
CREATE INDEX idx_machines_pctypeid ON machines(pctypeid);
CREATE INDEX idx_machines_osid ON machines(osid);
CREATE INDEX idx_machines_machinestatusid ON machines(machinestatusid);
CREATE INDEX idx_machines_lastupdated ON machines(lastupdated);
CREATE INDEX idx_machines_controllertypeid ON machines(controllertypeid);
CREATE INDEX idx_machines_controllerosid ON machines(controllerosid);
-- =====================================================
-- STEP 5: Add foreign keys (will be created after related tables exist)
-- =====================================================
-- NOTE: FK constraints will be added after:
-- - Script 03 creates PC machine types
-- - Script 07 renames pcstatus to machinestatus
-- These will be added in a later script to avoid errors
-- =====================================================
-- VERIFICATION
-- =====================================================
SELECT '✓ Machines table extended with PC fields' AS status;
DESCRIBE machines;
SELECT 'New column count:' AS info, COUNT(*) AS column_count
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = 'shopdb' AND TABLE_NAME = 'machines';
SELECT '✓ Script 02 completed successfully' AS status;
SET SQL_SAFE_UPDATES = 1;
-- =====================================================
-- NOTES
-- =====================================================
-- Next: Run script 03_create_pc_machine_types.sql
-- Rollback: Run ROLLBACK_02_machines_table_extensions.sql
-- =====================================================

View File

@@ -0,0 +1,82 @@
-- =====================================================
-- SCRIPT 03: Create Machine Types for PCs
-- =====================================================
-- Date: 2025-11-06
-- Purpose: Add PC-related machine types to support PC migration
-- Status: REVERSIBLE (see ROLLBACK_03)
-- Estimated Time: 1 minute
-- =====================================================
USE shopdb;
SET SQL_SAFE_UPDATES = 0;
-- =====================================================
-- STEP 1: Ensure functional accounts exist
-- =====================================================
INSERT IGNORE INTO functionalaccounts (functionalaccount, description, isactive)
VALUES
('IT', 'Information Technology', 1),
('MFG', 'Manufacturing', 1),
('ENG', 'Engineering', 1);
-- =====================================================
-- STEP 2: Create PC machine types
-- =====================================================
-- Get functional account IDs
SET @it_id = (SELECT functionalaccountid FROM functionalaccounts WHERE functionalaccount = 'IT' LIMIT 1);
SET @mfg_id = (SELECT functionalaccountid FROM functionalaccounts WHERE functionalaccount = 'MFG' LIMIT 1);
SET @eng_id = (SELECT functionalaccountid FROM functionalaccounts WHERE functionalaccount = 'ENG' LIMIT 1);
-- Insert PC machine types if they don't exist
INSERT INTO machinetypes (machinetype, machinedescription, functionalaccountid, isactive)
SELECT 'PC - Standard', 'Standard office/engineering workstation', @it_id, 1 FROM DUAL
WHERE NOT EXISTS (SELECT 1 FROM machinetypes WHERE machinetype = 'PC - Standard');
INSERT INTO machinetypes (machinetype, machinedescription, functionalaccountid, isactive)
SELECT 'PC - Shopfloor', 'Shopfloor machine control PC', @mfg_id, 1 FROM DUAL
WHERE NOT EXISTS (SELECT 1 FROM machinetypes WHERE machinetype = 'PC - Shopfloor');
INSERT INTO machinetypes (machinetype, machinedescription, functionalaccountid, isactive)
SELECT 'PC - Engineer', 'Engineering workstation', @eng_id, 1 FROM DUAL
WHERE NOT EXISTS (SELECT 1 FROM machinetypes WHERE machinetype = 'PC - Engineer');
INSERT INTO machinetypes (machinetype, machinedescription, functionalaccountid, isactive)
SELECT 'PC - Server', 'Server or VM', @it_id, 1 FROM DUAL
WHERE NOT EXISTS (SELECT 1 FROM machinetypes WHERE machinetype = 'PC - Server');
INSERT INTO machinetypes (machinetype, machinedescription, functionalaccountid, isactive)
SELECT 'PC - Laptop', 'Laptop computer', @it_id, 1 FROM DUAL
WHERE NOT EXISTS (SELECT 1 FROM machinetypes WHERE machinetype = 'PC - Laptop');
-- =====================================================
-- VERIFICATION
-- =====================================================
SELECT '✓ Functional accounts verified' AS status;
SELECT * FROM functionalaccounts WHERE functionalaccount IN ('IT', 'MFG', 'ENG');
SELECT '✓ PC machine types created' AS status;
SELECT machinetypeid, machinetype, machinedescription, functionalaccountid, isactive
FROM machinetypes
WHERE machinetype LIKE 'PC -%'
ORDER BY machinetype;
SELECT '✓ Script 03 completed successfully' AS status;
SET SQL_SAFE_UPDATES = 1;
-- =====================================================
-- NOTES
-- =====================================================
-- Next: Run script 04_create_warranty_infrastructure.sql
-- Rollback: Run ROLLBACK_03_pc_machine_types.sql
--
-- Machine Type Mapping for PC Migration:
-- - pctype 'Standard' → 'PC - Standard'
-- - pctype 'Shopfloor' → 'PC - Shopfloor'
-- - pctype 'Engineer' → 'PC - Engineer'
-- - pctype 'Server' or 'VM' → 'PC - Server'
-- - pctype 'Laptop' → 'PC - Laptop'
-- =====================================================

View File

@@ -0,0 +1,117 @@
-- =====================================================
-- SCRIPT 04: Create Warranty Infrastructure
-- =====================================================
-- Date: 2025-11-06
-- Purpose: Create warranties table for tracking machine warranties
-- Status: REVERSIBLE (see ROLLBACK_04)
-- Estimated Time: 1-2 minutes
-- =====================================================
USE shopdb;
SET SQL_SAFE_UPDATES = 0;
-- =====================================================
-- STEP 1: Create warranties table
-- =====================================================
CREATE TABLE IF NOT EXISTS warranties (
warrantyid INT(11) PRIMARY KEY AUTO_INCREMENT,
machineid INT(11) NOT NULL,
warrantyname VARCHAR(100), -- Dell Basic, HP Premium, etc.
enddate DATE,
servicelevel VARCHAR(100), -- Next Business Day, 4-hour, etc.
lastcheckeddate DATETIME, -- Last time warranty was verified
-- Audit fields
lastupdated DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
dateadded DATETIME DEFAULT CURRENT_TIMESTAMP,
-- Indexes
KEY idx_machineid (machineid),
KEY idx_enddate (enddate),
KEY idx_lastcheckeddate (lastcheckeddate),
-- Foreign Key
CONSTRAINT fk_warranties_machineid FOREIGN KEY (machineid) REFERENCES machines(machineid)
ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
COMMENT='Warranty tracking for machines (PCs, equipment, etc.)';
-- =====================================================
-- STEP 2: Create warranty status view
-- =====================================================
CREATE OR REPLACE VIEW vw_warranty_status AS
SELECT
m.machineid,
m.machinenumber,
m.hostname,
m.serialnumber,
w.warrantyid,
w.warrantyname,
w.enddate AS warrantyenddate,
w.servicelevel AS warrantyservicelevel,
w.lastcheckeddate AS warrantylastchecked,
CASE
WHEN w.enddate IS NULL THEN 'Unknown'
WHEN w.enddate < CURDATE() THEN 'Expired'
WHEN w.enddate < DATE_ADD(CURDATE(), INTERVAL 90 DAY) THEN 'Expiring Soon'
ELSE 'Active'
END AS warrantystatus,
CASE
WHEN w.enddate IS NULL THEN NULL
ELSE DATEDIFF(w.enddate, CURDATE())
END AS warrantydaysremaining
FROM machines m
LEFT JOIN warranties w ON m.machineid = w.machineid
WHERE m.isactive = 1;
-- =====================================================
-- STEP 3: Create expiring warranties view
-- =====================================================
CREATE OR REPLACE VIEW vw_warranties_expiring AS
SELECT
machineid,
machinenumber,
hostname,
serialnumber,
warrantyname,
warrantyenddate,
warrantyservicelevel,
warrantystatus,
warrantydaysremaining
FROM vw_warranty_status
WHERE warrantyenddate IS NOT NULL
AND warrantyenddate >= CURDATE()
AND warrantyenddate <= DATE_ADD(CURDATE(), INTERVAL 90 DAY)
ORDER BY warrantyenddate;
-- =====================================================
-- VERIFICATION
-- =====================================================
SELECT '✓ warranties table created' AS status;
DESCRIBE warranties;
SELECT '✓ Warranty views created' AS status;
SHOW TABLES LIKE 'vw_warrant%';
SELECT '✓ Script 04 completed successfully' AS status;
SET SQL_SAFE_UPDATES = 1;
-- =====================================================
-- NOTES
-- =====================================================
-- Next: Run script 05_create_compliance_infrastructure.sql
-- Rollback: Run ROLLBACK_04_warranty_infrastructure.sql
--
-- Migration Notes:
-- - PC warranty data will be migrated from pc table:
-- - warrantyenddate → warranties.enddate
-- - warrantyservicelevel → warranties.servicelevel
-- - warrantylastchecked → warranties.lastcheckeddate
-- - warrantystatus (computed field, not stored)
-- - warrantydaysremaining (computed field, not stored)
-- =====================================================

View File

@@ -0,0 +1,156 @@
-- =====================================================
-- SCRIPT 05: Create Compliance Infrastructure
-- =====================================================
-- Date: 2025-11-06
-- Purpose: Create compliance and compliancescans tables
-- Status: REVERSIBLE (see ROLLBACK_05)
-- Estimated Time: 2-3 minutes
-- =====================================================
USE shopdb;
SET SQL_SAFE_UPDATES = 0;
-- =====================================================
-- STEP 1: Create compliance table
-- =====================================================
CREATE TABLE IF NOT EXISTS compliance (
complianceid INT(11) PRIMARY KEY AUTO_INCREMENT,
machineid INT(11) NOT NULL,
-- Security Compliance Fields
scan VARCHAR(255), -- Last scan name/ID
scan_date DATETIME, -- Last scan date
deployment_notes TEXT, -- Deployment/configuration notes
-- Third Party Management
is_third_party_managed ENUM('Yes', 'No', 'NA') DEFAULT 'NA',
third_party_manager VARCHAR(255), -- Company name managing the asset
-- File Transfer
mft VARCHAR(100), -- Managed File Transfer tool/status
-- OT Asset Tracking (from inventory.xlsx)
ot_asset_system VARCHAR(255), -- OT Asset System Name
ot_asset_device VARCHAR(255), -- OT Asset Device Name
ot_asset_location VARCHAR(255), -- OT Asset Location
ot_asset_device_type VARCHAR(100), -- OT Asset Device Type
ot_asset_category VARCHAR(100), -- OT Asset Category
ot_asset_last_seen DATETIME, -- OT Asset Last Seen
ot_asset_ip_source VARCHAR(100), -- OT Asset IP Source
-- Compliance Status
is_compliant TINYINT(1) DEFAULT NULL, -- NULL=Unknown, 0=Non-compliant, 1=Compliant
compliance_notes TEXT, -- Additional compliance notes
-- Audit fields
lastupdated DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
dateadded DATETIME DEFAULT CURRENT_TIMESTAMP,
-- Indexes
KEY idx_machineid (machineid),
KEY idx_scan_date (scan_date),
KEY idx_is_third_party_managed (is_third_party_managed),
KEY idx_is_compliant (is_compliant),
KEY idx_ot_asset_system (ot_asset_system(100)),
-- Foreign Key
CONSTRAINT fk_compliance_machineid FOREIGN KEY (machineid) REFERENCES machines(machineid)
ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
COMMENT='Compliance and security tracking for machines';
-- =====================================================
-- STEP 2: Create compliancescans table
-- =====================================================
CREATE TABLE IF NOT EXISTS compliancescans (
scanid INT(11) PRIMARY KEY AUTO_INCREMENT,
machineid INT(11) NOT NULL,
scan_name VARCHAR(255), -- Scan identifier
scan_date DATETIME NOT NULL,
scan_result ENUM('Pass', 'Fail', 'Warning', 'Info') DEFAULT 'Info',
scan_details TEXT, -- Scan findings/details
-- Audit fields
dateadded DATETIME DEFAULT CURRENT_TIMESTAMP,
-- Indexes
KEY idx_machineid (machineid),
KEY idx_scan_date (scan_date),
KEY idx_scan_result (scan_result),
-- Foreign Key
CONSTRAINT fk_compliancescans_machineid FOREIGN KEY (machineid) REFERENCES machines(machineid)
ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
COMMENT='Historical compliance scan records';
-- =====================================================
-- STEP 3: Create compliance summary view
-- =====================================================
CREATE OR REPLACE VIEW vw_compliance_summary AS
SELECT
m.machineid,
m.machinenumber,
m.hostname,
m.serialnumber,
c.scan,
c.scan_date,
c.is_third_party_managed,
c.third_party_manager,
c.mft,
c.is_compliant,
c.deployment_notes,
c.ot_asset_system,
c.ot_asset_device,
c.ot_asset_location,
DATEDIFF(CURDATE(), c.scan_date) AS days_since_scan,
CASE
WHEN c.scan_date IS NULL THEN 'Never Scanned'
WHEN c.scan_date < DATE_SUB(CURDATE(), INTERVAL 90 DAY) THEN 'Scan Overdue'
WHEN c.scan_date < DATE_SUB(CURDATE(), INTERVAL 30 DAY) THEN 'Scan Due Soon'
ELSE 'Scan Current'
END AS scan_status
FROM machines m
LEFT JOIN compliance c ON m.machineid = c.machineid
WHERE m.isactive = 1;
-- =====================================================
-- VERIFICATION
-- =====================================================
SELECT '✓ compliance table created' AS status;
DESCRIBE compliance;
SELECT '✓ compliancescans table created' AS status;
DESCRIBE compliancescans;
SELECT '✓ Compliance views created' AS status;
SHOW TABLES LIKE 'vw_compliance%';
SELECT '✓ Script 05 completed successfully' AS status;
SET SQL_SAFE_UPDATES = 1;
-- =====================================================
-- NOTES
-- =====================================================
-- Next: Run script 06_extend_businessunits_table.sql
-- Rollback: Run ROLLBACK_05_compliance_infrastructure.sql
--
-- Data Migration Sources (from inventory.xlsx):
-- - Column 19 "Scan" → scan
-- - Column 20 "Scan Date" → scan_date
-- - Column 21 "Deployment Notes" → deployment_notes
-- - Column 28 "3rd Party Managed" → is_third_party_managed + third_party_manager
-- - Column 29 "MFT" → mft
-- - Column 30 "OT Asset System Name" → ot_asset_system
-- - Column 31 "OT Asset Device Name" → ot_asset_device
-- - Column 32 "OT Asset Location" → ot_asset_location
-- - Column 33 "OT Asset Device Type" → ot_asset_device_type
-- - Column 34 "OT Asset Category" → ot_asset_category
-- - Column 35 "OT Asset Last Seen" → ot_asset_last_seen
-- - Column 36 "OT Asset IP Source" → ot_asset_ip_source
-- =====================================================

View File

@@ -0,0 +1,47 @@
-- =====================================================
-- SCRIPT 06: Extend Businessunits Table
-- =====================================================
-- Date: 2025-11-06
-- Purpose: Add liaison information to businessunits table
-- Status: REVERSIBLE (see ROLLBACK_06)
-- Estimated Time: 1 minute
-- =====================================================
USE shopdb;
SET SQL_SAFE_UPDATES = 0;
-- =====================================================
-- STEP 1: Add liaison fields
-- =====================================================
ALTER TABLE businessunits
ADD COLUMN liaisonname VARCHAR(100) AFTER businessunit,
ADD COLUMN liaisonsso VARCHAR(50) AFTER liaisonname;
-- =====================================================
-- STEP 2: Create indexes
-- =====================================================
CREATE INDEX idx_businessunits_liaisonsso ON businessunits(liaisonsso);
-- =====================================================
-- VERIFICATION
-- =====================================================
SELECT '✓ businessunits table extended' AS status;
DESCRIBE businessunits;
SELECT '✓ Script 06 completed successfully' AS status;
SET SQL_SAFE_UPDATES = 1;
-- =====================================================
-- NOTES
-- =====================================================
-- Next: Run script 07_rename_pcstatus_to_machinestatus.sql
-- Rollback: Run ROLLBACK_06_businessunits_extensions.sql
--
-- Data Migration Source (from inventory.xlsx):
-- - Column 27 "Liaison" → liaisonname + liaisonsso
-- (Parse "Name (SSO)" format)
-- =====================================================

View File

@@ -0,0 +1,89 @@
-- =====================================================
-- SCRIPT 07: Rename pcstatus to machinestatus
-- =====================================================
-- Date: 2025-11-06
-- Purpose: Rename pcstatus table and columns for generic use
-- Status: REVERSIBLE (see ROLLBACK_07)
-- Estimated Time: 1 minute
-- =====================================================
USE shopdb;
SET SQL_SAFE_UPDATES = 0;
-- =====================================================
-- STEP 1: Check current pcstatus table
-- =====================================================
SELECT '✓ Current pcstatus table:' AS status;
DESCRIBE pcstatus;
SELECT * FROM pcstatus;
-- =====================================================
-- STEP 2: Rename table
-- =====================================================
RENAME TABLE pcstatus TO machinestatus;
-- =====================================================
-- STEP 3: Rename primary key column
-- =====================================================
ALTER TABLE machinestatus
CHANGE COLUMN pcstatusid machinestatusid INT(11) NOT NULL AUTO_INCREMENT;
-- =====================================================
-- STEP 4: Rename status column
-- =====================================================
ALTER TABLE machinestatus
CHANGE COLUMN pcstatus machinestatus VARCHAR(50);
-- =====================================================
-- STEP 5: Update indexes (if needed)
-- =====================================================
-- Check existing indexes
SHOW INDEXES FROM machinestatus;
-- =====================================================
-- STEP 6: Add FK constraint to machines table
-- =====================================================
-- Now that machinestatus exists, add the foreign key
ALTER TABLE machines
ADD CONSTRAINT fk_machines_machinestatusid
FOREIGN KEY (machinestatusid) REFERENCES machinestatus(machinestatusid);
-- =====================================================
-- VERIFICATION
-- =====================================================
SELECT '✓ Table renamed to machinestatus' AS status;
DESCRIBE machinestatus;
SELECT '✓ Machine status values:' AS info;
SELECT * FROM machinestatus ORDER BY machinestatusid;
SELECT '✓ Foreign key added to machines table' AS status;
SELECT '✓ Script 07 completed successfully' AS status;
SET SQL_SAFE_UPDATES = 1;
-- =====================================================
-- NOTES
-- =====================================================
-- Next: Run script 08_create_machine_relationships_infrastructure.sql
-- Rollback: Run ROLLBACK_07_machinestatus_rename.sql
--
-- Table renamed: pcstatus → machinestatus
-- Column renamed: pcstatusid → machinestatusid
-- Column renamed: pcstatus → machinestatus
--
-- Existing status values (typically):
-- - In Use
-- - Spare
-- - Retired
-- - Broken
-- - Unknown
-- =====================================================

View File

@@ -0,0 +1,157 @@
-- =====================================================
-- SCRIPT 08: Create Machine Relationships Infrastructure
-- =====================================================
-- Date: 2025-11-06
-- Purpose: Create relationshiptypes and machinerelationships tables
-- Status: REVERSIBLE (see ROLLBACK_08)
-- Estimated Time: 2 minutes
-- =====================================================
USE shopdb;
SET SQL_SAFE_UPDATES = 0;
-- =====================================================
-- STEP 1: Create relationshiptypes table
-- =====================================================
CREATE TABLE IF NOT EXISTS relationshiptypes (
relationshiptypeid INT(11) PRIMARY KEY AUTO_INCREMENT,
relationshiptype VARCHAR(50) NOT NULL UNIQUE,
description VARCHAR(255),
isactive TINYINT(1) DEFAULT 1,
displayorder INT(11) DEFAULT 0,
dateadded DATETIME DEFAULT CURRENT_TIMESTAMP,
-- Indexes
KEY idx_isactive (isactive),
KEY idx_displayorder (displayorder)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
COMMENT='Types of relationships between machines';
-- Insert relationship types
INSERT INTO relationshiptypes (relationshiptype, description, displayorder) VALUES
('Dualpath', 'Machines sharing the same controller (dualpath configuration)', 1),
('Controlled By', 'PC controls this machine', 2),
('Controls', 'This PC controls another machine', 3),
('Cluster Member', 'Part of a machine cluster', 4),
('Backup For', 'Serves as backup for another machine', 5),
('Master-Slave', 'Master-slave relationship', 6);
-- =====================================================
-- STEP 2: Create machinerelationships table
-- =====================================================
CREATE TABLE IF NOT EXISTS machinerelationships (
relationshipid INT(11) PRIMARY KEY AUTO_INCREMENT,
machineid INT(11) NOT NULL, -- The machine
related_machineid INT(11) NOT NULL, -- Related machine
relationshiptypeid INT(11) NOT NULL, -- Relationship type
relationship_notes TEXT, -- Additional context
isactive TINYINT(1) DEFAULT 1,
-- Audit fields
dateadded DATETIME DEFAULT CURRENT_TIMESTAMP,
lastupdated DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
-- Indexes
KEY idx_machineid (machineid),
KEY idx_related_machineid (related_machineid),
KEY idx_relationshiptypeid (relationshiptypeid),
KEY idx_isactive (isactive),
-- Composite index for common queries
KEY idx_machine_relationship (machineid, relationshiptypeid),
-- Foreign Keys
CONSTRAINT fk_machinerel_machineid FOREIGN KEY (machineid) REFERENCES machines(machineid)
ON DELETE CASCADE,
CONSTRAINT fk_machinerel_related FOREIGN KEY (related_machineid) REFERENCES machines(machineid)
ON DELETE CASCADE,
CONSTRAINT fk_machinerel_type FOREIGN KEY (relationshiptypeid) REFERENCES relationshiptypes(relationshiptypeid)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
COMMENT='Relationships between machines (dualpath, controller, cluster, etc.)';
-- =====================================================
-- STEP 3: Create machine relationships view
-- =====================================================
CREATE OR REPLACE VIEW vw_machine_relationships AS
SELECT
mr.relationshipid,
mr.machineid,
m1.machinenumber AS machine_number,
m1.hostname AS machine_hostname,
mr.related_machineid,
m2.machinenumber AS related_machine_number,
m2.hostname AS related_machine_hostname,
rt.relationshiptype,
rt.description AS relationship_description,
mr.relationship_notes,
mr.isactive
FROM machinerelationships mr
JOIN machines m1 ON mr.machineid = m1.machineid
JOIN machines m2 ON mr.related_machineid = m2.machineid
JOIN relationshiptypes rt ON mr.relationshiptypeid = rt.relationshiptypeid
WHERE mr.isactive = 1;
-- =====================================================
-- STEP 4: Create dualpath management view
-- =====================================================
CREATE OR REPLACE VIEW vw_dualpath_machines AS
SELECT
mr.relationshipid,
m1.machineid AS machine1_id,
m1.machinenumber AS machine1_number,
m1.hostname AS machine1_hostname,
m2.machineid AS machine2_id,
m2.machinenumber AS machine2_number,
m2.hostname AS machine2_hostname,
mr.relationship_notes
FROM machinerelationships mr
JOIN machines m1 ON mr.machineid = m1.machineid
JOIN machines m2 ON mr.related_machineid = m2.machineid
JOIN relationshiptypes rt ON mr.relationshiptypeid = rt.relationshiptypeid
WHERE rt.relationshiptype = 'Dualpath'
AND mr.isactive = 1
ORDER BY m1.machinenumber;
-- =====================================================
-- VERIFICATION
-- =====================================================
SELECT '✓ relationshiptypes table created' AS status;
DESCRIBE relationshiptypes;
SELECT '✓ Relationship types:' AS info;
SELECT * FROM relationshiptypes ORDER BY displayorder;
SELECT '✓ machinerelationships table created' AS status;
DESCRIBE machinerelationships;
SELECT '✓ Relationship views created' AS status;
SHOW TABLES LIKE 'vw_%relationship%';
SHOW TABLES LIKE 'vw_dualpath%';
SELECT '✓ Script 08 completed successfully' AS status;
SET SQL_SAFE_UPDATES = 1;
-- =====================================================
-- NOTES
-- =====================================================
-- Next: Review all 8 scripts, then run ROLLBACK scripts creation
-- Rollback: Run ROLLBACK_08_machine_relationships_infrastructure.sql
--
-- Migration Notes:
-- - pc_dualpath_assignments will migrate to machinerelationships
-- with relationshiptypeid for 'Dualpath'
-- - PC-to-machine control relationships can be added using
-- 'Controlled By' relationship type
--
-- Usage Examples:
-- - Find all dualpath pairs: SELECT * FROM vw_dualpath_machines
-- - Find machines controlled by a PC:
-- SELECT * FROM vw_machine_relationships
-- WHERE relationshiptype = 'Controlled By'
-- =====================================================

View File

@@ -0,0 +1,264 @@
# Phase 1: Database Schema Migration Scripts
**Created:** 2025-11-06
**Status:** Ready for DEV testing
**Estimated Time:** 15-20 minutes
---
## Overview
This directory contains Phase 1 migration scripts for consolidating the `pc` table into the `machines` table. These scripts create new infrastructure tables and extend existing tables to support both PCs and machines in a unified schema.
---
## Scripts Included
### Migration Scripts (Run in Order)
1. **01_create_communications_infrastructure.sql** (2-3 min)
- Creates `comstypes` table (8 communication types)
- Creates `communications` table (generic address field)
2. **02_extend_machines_table.sql** (2-3 min)
- Adds 11 new columns to machines table
- Adds indexes for new columns
3. **03_create_pc_machine_types.sql** (1 min)
- Creates 5 PC machine types (Standard, Shopfloor, Engineer, Server, Laptop)
4. **04_create_warranty_infrastructure.sql** (1-2 min)
- Creates `warranties` table
- Creates warranty status views
5. **05_create_compliance_infrastructure.sql** (2-3 min)
- Creates `compliance` table (15 columns)
- Creates `compliancescans` table
- Creates compliance views
6. **06_extend_businessunits_table.sql** (1 min)
- Adds liaison fields to businessunits
7. **07_rename_pcstatus_to_machinestatus.sql** (1 min)
- Renames pcstatus table and columns
- Adds FK constraint to machines
8. **08_create_machine_relationships_infrastructure.sql** (2 min)
- Creates `relationshiptypes` table
- Creates `machinerelationships` table
- Creates relationship views
### Rollback Scripts (Reverse Order)
- **ROLLBACK_08_machine_relationships_infrastructure.sql**
- **ROLLBACK_07_machinestatus_rename.sql**
- **ROLLBACK_06_businessunits_extensions.sql**
- **ROLLBACK_05_compliance_infrastructure.sql**
- **ROLLBACK_04_warranty_infrastructure.sql**
- **ROLLBACK_03_pc_machine_types.sql**
- **ROLLBACK_02_machines_table_extensions.sql**
- **ROLLBACK_01_communications_infrastructure.sql**
---
## Quick Start
### Option 1: Run All Scripts (Recommended for DEV)
```bash
# Run master script (executes all 8 in order)
docker exec -i dev-mysql mysql -u 570005354 -p570005354 shopdb < RUN_ALL_PHASE1_SCRIPTS.sql
```
### Option 2: Run Individual Scripts
```bash
# Run each script one at a time
docker exec -i dev-mysql mysql -u 570005354 -p570005354 shopdb < 01_create_communications_infrastructure.sql
docker exec -i dev-mysql mysql -u 570005354 -p570005354 shopdb < 02_extend_machines_table.sql
# ... and so on
```
### Option 3: Use MySQL Workbench
1. Connect to database
2. Open script file
3. Execute
4. Review output
5. Repeat for each script
---
## Pre-Execution Checklist
- [ ] **Backup created** - Full database backup exists
- [ ] **Dev environment** - Running on DEV, not production
- [ ] **Dependencies** - All required tables exist (machines, pctype, operatingsystems, etc.)
- [ ] **Disk space** - At least 100MB free
- [ ] **Permissions** - User has CREATE, ALTER, DROP privileges
---
## Execution Steps
### 1. Create Backup
```bash
# Backup current database
docker exec dev-mysql mysqldump -u 570005354 -p570005354 shopdb > /tmp/shopdb-before-phase1-$(date +%Y%m%d).sql
```
### 2. Run Migration Scripts
```bash
cd /home/camp/projects/windows/shopdb/sql/migration_phase1
# Option A: Run all at once
docker exec -i dev-mysql mysql -u 570005354 -p570005354 shopdb < RUN_ALL_PHASE1_SCRIPTS.sql
# Option B: Run individually for better control
for i in {01..08}; do
echo "Running script $i..."
docker exec -i dev-mysql mysql -u 570005354 -p570005354 shopdb < ${i}_*.sql
if [ $? -ne 0 ]; then
echo "ERROR in script $i! Stopping."
exit 1
fi
done
```
### 3. Verify Results
```bash
# Check new tables were created
docker exec dev-mysql mysql -u 570005354 -p570005354 shopdb -e "SHOW TABLES LIKE '%com%'; SHOW TABLES LIKE '%warrant%'; SHOW TABLES LIKE '%compliance%'; SHOW TABLES LIKE '%relationship%';"
# Check machines table structure
docker exec dev-mysql mysql -u 570005354 -p570005354 shopdb -e "DESCRIBE machines;"
# Check machine types
docker exec dev-mysql mysql -u 570005354 -p570005354 shopdb -e "SELECT * FROM machinetypes WHERE machinetype LIKE 'PC -%';"
```
### 4. If Rollback Needed
```bash
# Run rollback scripts in REVERSE order (08 down to 01)
for i in {08..01}; do
echo "Rolling back script $i..."
docker exec -i dev-mysql mysql -u 570005354 -p570005354 shopdb < ROLLBACK_${i}_*.sql
done
```
---
## Tables Created
### New Tables (7)
1. **comstypes** - Communication types (IP, Serial, etc.)
2. **communications** - Generic communications (replaces pc_comm_config + pc_network_interfaces)
3. **warranties** - Warranty tracking
4. **compliance** - Compliance and security tracking
5. **compliancescans** - Historical scan records
6. **relationshiptypes** - Types of machine relationships
7. **machinerelationships** - Machine-to-machine relationships
### Modified Tables (3)
1. **machines** - Added 11 columns (hostname, serialnumber, osid, etc.)
2. **businessunits** - Added 2 columns (liaisonname, liaisonsso)
3. **machinestatus** - Renamed from pcstatus
---
## New Columns in machines Table
1. hostname (VARCHAR 100)
2. loggedinuser (VARCHAR 100)
3. serialnumber (VARCHAR 100)
4. osid (INT 11) - FK to operatingsystems
5. machinestatusid (INT 11) - FK to machinestatus
6. pctypeid (INT 11) - FK to pctype
7. controllertypeid (INT 11) - FK to controllertypes
8. controllerosid (INT 11) - FK to operatingsystems
9. requires_manual_machine_config (TINYINT 1)
10. lastupdated (DATETIME)
11. dateadded (DATETIME)
---
## Views Created
- vw_warranty_status
- vw_warranties_expiring
- vw_compliance_summary
- vw_machine_relationships
- vw_dualpath_machines
---
## Testing Checklist
After running scripts, verify:
- [ ] All 7 new tables exist
- [ ] machines table has 11 new columns
- [ ] 5 PC machine types created
- [ ] machinestatus table exists (pcstatus renamed)
- [ ] All views created successfully
- [ ] No errors in execution
- [ ] Foreign keys in place
- [ ] Indexes created
---
## Common Issues
### Issue: FK constraint fails
**Cause:** Referenced table doesn't exist yet
**Fix:** Run scripts in order (01 through 08)
### Issue: Column already exists
**Cause:** Script already ran
**Fix:** Safe to ignore or run rollback first
### Issue: Permission denied
**Cause:** User lacks privileges
**Fix:** Grant CREATE, ALTER, DROP privileges
---
## Next Steps After Phase 1
1. **Test queries** - Verify new tables work
2. **Phase 2** - Data migration scripts (PC → machines)
3. **Phase 3** - Update views that reference pc table
4. **Phase 4** - Update ASP files
---
## Support
**Documentation:**
- Main design doc: `PC_MACHINES_CONSOLIDATION_PLAN.md`
- Status summary: `MIGRATION_STATUS_SUMMARY.md`
- Quick reference: `MIGRATION_QUICK_REFERENCE.md`
**Questions?**
- Review design documents
- Check CRITICAL_RULES.md
- Test on DEV first!
---
## Notes
- **REVERSIBLE:** All scripts have rollback scripts
- **SAFE:** No data deletion (only schema changes)
- **TESTED:** Design complete, ready for dev testing
- **ESTIMATED TIME:** 15-20 minutes total
**Created:** 2025-11-06
**Last Updated:** 2025-11-06
**Status:** Ready for DEV testing

View File

@@ -0,0 +1,37 @@
-- =====================================================
-- ROLLBACK 01: Remove Communications Infrastructure
-- =====================================================
-- Date: 2025-11-06
-- Purpose: Rollback script 01_create_communications_infrastructure.sql
-- WARNING: This will DELETE all data in communications table
-- =====================================================
USE shopdb;
SET SQL_SAFE_UPDATES = 0;
-- =====================================================
-- STEP 1: Drop tables in correct order (FK constraints)
-- =====================================================
DROP TABLE IF EXISTS communications;
DROP TABLE IF EXISTS comstypes;
-- =====================================================
-- VERIFICATION
-- =====================================================
SELECT '✓ communications table dropped' AS status;
SELECT '✓ comstypes table dropped' AS status;
SELECT '✓ ROLLBACK 01 completed successfully' AS status;
SET SQL_SAFE_UPDATES = 1;
-- =====================================================
-- NOTES
-- =====================================================
-- Tables removed:
-- - communications
-- - comstypes
--
-- To restore: Run 01_create_communications_infrastructure.sql
-- =====================================================

View File

@@ -0,0 +1,81 @@
-- =====================================================
-- ROLLBACK 02: Remove Machines Table Extensions
-- =====================================================
-- Date: 2025-11-06
-- Purpose: Rollback script 02_extend_machines_table.sql
-- WARNING: This will DELETE all data in new columns
-- =====================================================
USE shopdb;
SET SQL_SAFE_UPDATES = 0;
-- =====================================================
-- STEP 1: Drop foreign keys first (if they exist)
-- =====================================================
SET @stmt = (SELECT IF(
(SELECT COUNT(*) FROM information_schema.TABLE_CONSTRAINTS
WHERE CONSTRAINT_SCHEMA = 'shopdb'
AND TABLE_NAME = 'machines'
AND CONSTRAINT_NAME = 'fk_machines_machinestatusid') > 0,
'ALTER TABLE machines DROP FOREIGN KEY fk_machines_machinestatusid',
'SELECT "FK fk_machines_machinestatusid does not exist"'
));
PREPARE stmt FROM @stmt;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- =====================================================
-- STEP 2: Drop indexes
-- =====================================================
DROP INDEX IF EXISTS idx_machines_hostname ON machines;
DROP INDEX IF EXISTS idx_machines_serialnumber ON machines;
DROP INDEX IF EXISTS idx_machines_pctypeid ON machines;
DROP INDEX IF EXISTS idx_machines_osid ON machines;
DROP INDEX IF EXISTS idx_machines_machinestatusid ON machines;
DROP INDEX IF EXISTS idx_machines_lastupdated ON machines;
DROP INDEX IF EXISTS idx_machines_controllertypeid ON machines;
DROP INDEX IF EXISTS idx_machines_controllerosid ON machines;
-- =====================================================
-- STEP 3: Remove columns
-- =====================================================
ALTER TABLE machines
DROP COLUMN IF EXISTS hostname,
DROP COLUMN IF EXISTS loggedinuser,
DROP COLUMN IF EXISTS serialnumber,
DROP COLUMN IF EXISTS osid,
DROP COLUMN IF EXISTS machinestatusid,
DROP COLUMN IF EXISTS pctypeid,
DROP COLUMN IF EXISTS controllertypeid,
DROP COLUMN IF EXISTS controllerosid,
DROP COLUMN IF EXISTS requires_manual_machine_config,
DROP COLUMN IF EXISTS lastupdated,
DROP COLUMN IF EXISTS dateadded;
-- =====================================================
-- VERIFICATION
-- =====================================================
SELECT '✓ Foreign keys dropped' AS status;
SELECT '✓ Indexes dropped' AS status;
SELECT '✓ Columns removed from machines table' AS status;
DESCRIBE machines;
SELECT '✓ ROLLBACK 02 completed successfully' AS status;
SET SQL_SAFE_UPDATES = 1;
-- =====================================================
-- NOTES
-- =====================================================
-- Columns removed:
-- - hostname, loggedinuser, serialnumber
-- - osid, machinestatusid, pctypeid
-- - controllertypeid, controllerosid
-- - requires_manual_machine_config
-- - lastupdated, dateadded
--
-- To restore: Run 02_extend_machines_table.sql
-- =====================================================

View File

@@ -0,0 +1,51 @@
-- =====================================================
-- ROLLBACK 03: Remove PC Machine Types
-- =====================================================
-- Date: 2025-11-06
-- Purpose: Rollback script 03_create_pc_machine_types.sql
-- WARNING: Check for data before running
-- =====================================================
USE shopdb;
SET SQL_SAFE_UPDATES = 0;
-- =====================================================
-- STEP 1: Check if any machines use PC types
-- =====================================================
SELECT 'Machines using PC types:' AS warning,
COUNT(*) AS count
FROM machines m
JOIN machinetypes mt ON m.machinetypeid = mt.machinetypeid
WHERE mt.machinetype LIKE 'PC -%';
-- =====================================================
-- STEP 2: Delete PC machine types
-- =====================================================
DELETE FROM machinetypes WHERE machinetype LIKE 'PC -%';
-- =====================================================
-- VERIFICATION
-- =====================================================
SELECT '✓ PC machine types removed' AS status;
SELECT '✓ ROLLBACK 03 completed successfully' AS status;
SET SQL_SAFE_UPDATES = 1;
-- =====================================================
-- NOTES
-- =====================================================
-- Machine types removed:
-- - PC - Standard
-- - PC - Shopfloor
-- - PC - Engineer
-- - PC - Server
-- - PC - Laptop
--
-- WARNING: If machines were assigned these types,
-- they will now have NULL machinetypeid!
--
-- To restore: Run 03_create_pc_machine_types.sql
-- =====================================================

View File

@@ -0,0 +1,44 @@
-- =====================================================
-- ROLLBACK 04: Remove Warranty Infrastructure
-- =====================================================
-- Date: 2025-11-06
-- Purpose: Rollback script 04_create_warranty_infrastructure.sql
-- WARNING: This will DELETE all warranty data
-- =====================================================
USE shopdb;
SET SQL_SAFE_UPDATES = 0;
-- =====================================================
-- STEP 1: Drop views first
-- =====================================================
DROP VIEW IF EXISTS vw_warranties_expiring;
DROP VIEW IF EXISTS vw_warranty_status;
-- =====================================================
-- STEP 2: Drop warranties table
-- =====================================================
DROP TABLE IF EXISTS warranties;
-- =====================================================
-- VERIFICATION
-- =====================================================
SELECT '✓ Warranty views dropped' AS status;
SELECT '✓ warranties table dropped' AS status;
SELECT '✓ ROLLBACK 04 completed successfully' AS status;
SET SQL_SAFE_UPDATES = 1;
-- =====================================================
-- NOTES
-- =====================================================
-- Removed:
-- - warranties table
-- - vw_warranty_status view
-- - vw_warranties_expiring view
--
-- To restore: Run 04_create_warranty_infrastructure.sql
-- =====================================================

View File

@@ -0,0 +1,45 @@
-- =====================================================
-- ROLLBACK 05: Remove Compliance Infrastructure
-- =====================================================
-- Date: 2025-11-06
-- Purpose: Rollback script 05_create_compliance_infrastructure.sql
-- WARNING: This will DELETE all compliance data
-- =====================================================
USE shopdb;
SET SQL_SAFE_UPDATES = 0;
-- =====================================================
-- STEP 1: Drop views first
-- =====================================================
DROP VIEW IF EXISTS vw_compliance_summary;
-- =====================================================
-- STEP 2: Drop tables in correct order (FK constraints)
-- =====================================================
DROP TABLE IF EXISTS compliancescans;
DROP TABLE IF EXISTS compliance;
-- =====================================================
-- VERIFICATION
-- =====================================================
SELECT '✓ Compliance views dropped' AS status;
SELECT '✓ compliancescans table dropped' AS status;
SELECT '✓ compliance table dropped' AS status;
SELECT '✓ ROLLBACK 05 completed successfully' AS status;
SET SQL_SAFE_UPDATES = 1;
-- =====================================================
-- NOTES
-- =====================================================
-- Removed:
-- - compliance table
-- - compliancescans table
-- - vw_compliance_summary view
--
-- To restore: Run 05_create_compliance_infrastructure.sql
-- =====================================================

View File

@@ -0,0 +1,45 @@
-- =====================================================
-- ROLLBACK 06: Remove Businessunits Extensions
-- =====================================================
-- Date: 2025-11-06
-- Purpose: Rollback script 06_extend_businessunits_table.sql
-- WARNING: This will DELETE liaison data
-- =====================================================
USE shopdb;
SET SQL_SAFE_UPDATES = 0;
-- =====================================================
-- STEP 1: Drop indexes
-- =====================================================
DROP INDEX IF EXISTS idx_businessunits_liaisonsso ON businessunits;
-- =====================================================
-- STEP 2: Remove columns
-- =====================================================
ALTER TABLE businessunits
DROP COLUMN IF EXISTS liaisonname,
DROP COLUMN IF EXISTS liaisonsso;
-- =====================================================
-- VERIFICATION
-- =====================================================
SELECT '✓ Index dropped' AS status;
SELECT '✓ Columns removed from businessunits table' AS status;
DESCRIBE businessunits;
SELECT '✓ ROLLBACK 06 completed successfully' AS status;
SET SQL_SAFE_UPDATES = 1;
-- =====================================================
-- NOTES
-- =====================================================
-- Columns removed:
-- - liaisonname
-- - liaisonsso
--
-- To restore: Run 06_extend_businessunits_table.sql
-- =====================================================

View File

@@ -0,0 +1,70 @@
-- =====================================================
-- ROLLBACK 07: Rename machinestatus back to pcstatus
-- =====================================================
-- Date: 2025-11-06
-- Purpose: Rollback script 07_rename_pcstatus_to_machinestatus.sql
-- =====================================================
USE shopdb;
SET SQL_SAFE_UPDATES = 0;
-- =====================================================
-- STEP 1: Drop FK constraint from machines table
-- =====================================================
SET @stmt = (SELECT IF(
(SELECT COUNT(*) FROM information_schema.TABLE_CONSTRAINTS
WHERE CONSTRAINT_SCHEMA = 'shopdb'
AND TABLE_NAME = 'machines'
AND CONSTRAINT_NAME = 'fk_machines_machinestatusid') > 0,
'ALTER TABLE machines DROP FOREIGN KEY fk_machines_machinestatusid',
'SELECT "FK fk_machines_machinestatusid does not exist"'
));
PREPARE stmt FROM @stmt;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- =====================================================
-- STEP 2: Rename status column back
-- =====================================================
ALTER TABLE machinestatus
CHANGE COLUMN machinestatus pcstatus VARCHAR(50);
-- =====================================================
-- STEP 3: Rename primary key column back
-- =====================================================
ALTER TABLE machinestatus
CHANGE COLUMN machinestatusid pcstatusid INT(11) NOT NULL AUTO_INCREMENT;
-- =====================================================
-- STEP 4: Rename table back
-- =====================================================
RENAME TABLE machinestatus TO pcstatus;
-- =====================================================
-- VERIFICATION
-- =====================================================
SELECT '✓ Table renamed back to pcstatus' AS status;
DESCRIBE pcstatus;
SELECT '✓ Status values:' AS info;
SELECT * FROM pcstatus ORDER BY pcstatusid;
SELECT '✓ ROLLBACK 07 completed successfully' AS status;
SET SQL_SAFE_UPDATES = 1;
-- =====================================================
-- NOTES
-- =====================================================
-- Table renamed: machinestatus → pcstatus
-- Column renamed: machinestatusid → pcstatusid
-- Column renamed: machinestatus → pcstatus
-- FK constraint removed from machines table
--
-- To restore: Run 07_rename_pcstatus_to_machinestatus.sql
-- =====================================================

View File

@@ -0,0 +1,47 @@
-- =====================================================
-- ROLLBACK 08: Remove Machine Relationships Infrastructure
-- =====================================================
-- Date: 2025-11-06
-- Purpose: Rollback script 08_create_machine_relationships_infrastructure.sql
-- WARNING: This will DELETE all relationship data
-- =====================================================
USE shopdb;
SET SQL_SAFE_UPDATES = 0;
-- =====================================================
-- STEP 1: Drop views first
-- =====================================================
DROP VIEW IF EXISTS vw_dualpath_machines;
DROP VIEW IF EXISTS vw_machine_relationships;
-- =====================================================
-- STEP 2: Drop tables in correct order (FK constraints)
-- =====================================================
DROP TABLE IF EXISTS machinerelationships;
DROP TABLE IF EXISTS relationshiptypes;
-- =====================================================
-- VERIFICATION
-- =====================================================
SELECT '✓ Relationship views dropped' AS status;
SELECT '✓ machinerelationships table dropped' AS status;
SELECT '✓ relationshiptypes table dropped' AS status;
SELECT '✓ ROLLBACK 08 completed successfully' AS status;
SET SQL_SAFE_UPDATES = 1;
-- =====================================================
-- NOTES
-- =====================================================
-- Removed:
-- - machinerelationships table
-- - relationshiptypes table
-- - vw_machine_relationships view
-- - vw_dualpath_machines view
--
-- To restore: Run 08_create_machine_relationships_infrastructure.sql
-- =====================================================

View File

@@ -0,0 +1,244 @@
-- =====================================================
-- MASTER SCRIPT: Run All Phase 1 Migration Scripts
-- =====================================================
-- Date: 2025-11-06
-- Purpose: Execute all 8 Phase 1 scripts in correct order
-- Estimated Time: 15-20 minutes
-- WARNING: Creates 7 new tables, modifies 3 existing tables
-- =====================================================
-- =====================================================
-- PRE-FLIGHT CHECKS
-- =====================================================
SELECT '========================================' AS '';
SELECT 'PHASE 1 MIGRATION - MASTER SCRIPT' AS '';
SELECT '========================================' AS '';
SELECT '' AS '';
SELECT CONCAT('Start Time: ', NOW()) AS '';
SELECT CONCAT('Database: ', DATABASE()) AS '';
SELECT CONCAT('User: ', USER()) AS '';
SELECT '' AS '';
-- Check if we're in the right database
SELECT CASE
WHEN DATABASE() = 'shopdb' THEN '✓ Correct database (shopdb)'
ELSE '⚠️ WARNING: Not in shopdb database!'
END AS 'Database Check';
-- Check if pc table exists (needed for later migration)
SELECT CASE
WHEN COUNT(*) > 0 THEN CONCAT('✓ pc table exists (', COUNT(*), ' records)')
ELSE '⚠️ WARNING: pc table not found!'
END AS 'PC Table Check'
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = 'shopdb' AND TABLE_NAME = 'pc';
-- Check if machines table exists
SELECT CASE
WHEN COUNT(*) > 0 THEN '✓ machines table exists'
ELSE '⚠️ ERROR: machines table not found!'
END AS 'Machines Table Check'
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = 'shopdb' AND TABLE_NAME = 'machines';
SELECT '' AS '';
SELECT 'Press Ctrl+C to cancel, or continue executing...' AS '';
SELECT 'Creating backup recommended before proceeding!' AS '';
SELECT '' AS '';
-- Pause (you'll need to manually run each section if you want to pause)
-- =====================================================
-- SCRIPT 01: Communications Infrastructure
-- =====================================================
SELECT '========================================' AS '';
SELECT 'SCRIPT 01: Communications Infrastructure' AS '';
SELECT '========================================' AS '';
SOURCE 01_create_communications_infrastructure.sql;
SELECT '' AS '';
-- =====================================================
-- SCRIPT 02: Extend Machines Table
-- =====================================================
SELECT '========================================' AS '';
SELECT 'SCRIPT 02: Extend Machines Table' AS '';
SELECT '========================================' AS '';
SOURCE 02_extend_machines_table.sql;
SELECT '' AS '';
-- =====================================================
-- SCRIPT 03: Create PC Machine Types
-- =====================================================
SELECT '========================================' AS '';
SELECT 'SCRIPT 03: Create PC Machine Types' AS '';
SELECT '========================================' AS '';
SOURCE 03_create_pc_machine_types.sql;
SELECT '' AS '';
-- =====================================================
-- SCRIPT 04: Warranty Infrastructure
-- =====================================================
SELECT '========================================' AS '';
SELECT 'SCRIPT 04: Warranty Infrastructure' AS '';
SELECT '========================================' AS '';
SOURCE 04_create_warranty_infrastructure.sql;
SELECT '' AS '';
-- =====================================================
-- SCRIPT 05: Compliance Infrastructure
-- =====================================================
SELECT '========================================' AS '';
SELECT 'SCRIPT 05: Compliance Infrastructure' AS '';
SELECT '========================================' AS '';
SOURCE 05_create_compliance_infrastructure.sql;
SELECT '' AS '';
-- =====================================================
-- SCRIPT 06: Extend Businessunits Table
-- =====================================================
SELECT '========================================' AS '';
SELECT 'SCRIPT 06: Extend Businessunits Table' AS '';
SELECT '========================================' AS '';
SOURCE 06_extend_businessunits_table.sql;
SELECT '' AS '';
-- =====================================================
-- SCRIPT 07: Rename pcstatus to machinestatus
-- =====================================================
SELECT '========================================' AS '';
SELECT 'SCRIPT 07: Rename pcstatus to machinestatus' AS '';
SELECT '========================================' AS '';
SOURCE 07_rename_pcstatus_to_machinestatus.sql;
SELECT '' AS '';
-- =====================================================
-- SCRIPT 08: Machine Relationships Infrastructure
-- =====================================================
SELECT '========================================' AS '';
SELECT 'SCRIPT 08: Machine Relationships' AS '';
SELECT '========================================' AS '';
SOURCE 08_create_machine_relationships_infrastructure.sql;
SELECT '' AS '';
-- =====================================================
-- POST-EXECUTION VERIFICATION
-- =====================================================
SELECT '========================================' AS '';
SELECT 'POST-EXECUTION VERIFICATION' AS '';
SELECT '========================================' AS '';
SELECT '' AS '';
-- Count new tables
SELECT 'New Tables Created:' AS '';
SELECT TABLE_NAME, TABLE_ROWS
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = 'shopdb'
AND TABLE_NAME IN ('comstypes', 'communications', 'warranties',
'compliance', 'compliancescans', 'relationshiptypes',
'machinerelationships', 'machinestatus')
ORDER BY TABLE_NAME;
SELECT '' AS '';
-- Count new views
SELECT 'New Views Created:' AS '';
SELECT TABLE_NAME
FROM information_schema.VIEWS
WHERE TABLE_SCHEMA = 'shopdb'
AND TABLE_NAME LIKE 'vw_%warrant%'
OR TABLE_NAME LIKE 'vw_%compliance%'
OR TABLE_NAME LIKE 'vw_%relationship%'
OR TABLE_NAME LIKE 'vw_dualpath%'
ORDER BY TABLE_NAME;
SELECT '' AS '';
-- Check machines table columns
SELECT 'Machines Table Columns:' AS '';
SELECT COLUMN_NAME, DATA_TYPE, IS_NULLABLE
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = 'shopdb'
AND TABLE_NAME = 'machines'
AND COLUMN_NAME IN ('hostname', 'serialnumber', 'osid', 'machinestatusid',
'pctypeid', 'controllertypeid', 'controllerosid',
'lastupdated', 'dateadded', 'requires_manual_machine_config',
'loggedinuser')
ORDER BY ORDINAL_POSITION;
SELECT '' AS '';
-- Check PC machine types
SELECT 'PC Machine Types Created:' AS '';
SELECT machinetypeid, machinetype, machinedescription
FROM machinetypes
WHERE machinetype LIKE 'PC -%'
ORDER BY machinetype;
SELECT '' AS '';
-- =====================================================
-- COMPLETION SUMMARY
-- =====================================================
SELECT '========================================' AS '';
SELECT '✓ PHASE 1 MIGRATION COMPLETE!' AS '';
SELECT '========================================' AS '';
SELECT '' AS '';
SELECT CONCAT('End Time: ', NOW()) AS '';
SELECT '' AS '';
SELECT 'RESULTS:' AS '';
SELECT '- 7 new tables created' AS '';
SELECT '- 3 tables modified' AS '';
SELECT '- 5+ views created' AS '';
SELECT '- 5 PC machine types added' AS '';
SELECT '- 11 columns added to machines table' AS '';
SELECT '- 2 columns added to businessunits table' AS '';
SELECT '' AS '';
SELECT 'NEXT STEPS:' AS '';
SELECT '1. Review verification output above' AS '';
SELECT '2. Test queries on new tables' AS '';
SELECT '3. Proceed to Phase 2 (data migration)' AS '';
SELECT '' AS '';
SELECT 'ROLLBACK:' AS '';
SELECT '- Run ROLLBACK scripts in reverse order (08 down to 01)' AS '';
SELECT '- Or restore from backup' AS '';
SELECT '' AS '';
-- =====================================================
-- NOTES
-- =====================================================
-- This master script executes all 8 Phase 1 scripts.
-- Each script is REVERSIBLE using its corresponding ROLLBACK script.
--
-- To run this script:
-- docker exec -i dev-mysql mysql -u 570005354 -p570005354 shopdb < RUN_ALL_PHASE1_SCRIPTS.sql
--
-- To rollback all changes:
-- Run ROLLBACK scripts in reverse order (08, 07, 06, 05, 04, 03, 02, 01)
-- =====================================================

View File

@@ -0,0 +1,356 @@
-- =====================================================
-- SCRIPT 01: Migrate PC Records to Machines Table
-- =====================================================
-- Date: 2025-11-06
-- Purpose: Migrate all PC records from pc table to machines table
-- Status: REQUIRES TESTING - Creates backup table first
-- Estimated Time: 5-10 minutes
-- Records: ~277 PCs
-- =====================================================
USE shopdb;
SET SQL_SAFE_UPDATES = 0;
-- =====================================================
-- STEP 1: Pre-migration checks
-- =====================================================
SELECT '========================================' AS '';
SELECT 'PC TO MACHINES MIGRATION' AS '';
SELECT '========================================' AS '';
SELECT '' AS '';
-- Count PCs to migrate
SELECT CONCAT('PCs to migrate: ', COUNT(*)) AS info FROM pc WHERE isactive = 1;
SELECT CONCAT('Current machines: ', COUNT(*)) AS info FROM machines WHERE isactive = 1;
-- Show PC type distribution
SELECT 'PC Type Distribution:' AS '';
SELECT pt.typename, COUNT(*) as count
FROM pc p
JOIN pctype pt ON p.pctypeid = pt.pctypeid
WHERE p.isactive = 1
GROUP BY pt.typename
ORDER BY count DESC;
SELECT '' AS '';
-- =====================================================
-- STEP 2: Create mapping between pctype and machine types
-- =====================================================
-- Create temporary mapping table
CREATE TEMPORARY TABLE temp_pctype_mapping (
pctypeid INT,
typename VARCHAR(50),
target_machinetypeid INT
);
-- Map PC types to new machine types
INSERT INTO temp_pctype_mapping (pctypeid, typename, target_machinetypeid)
SELECT
pt.pctypeid,
pt.typename,
CASE pt.typename
WHEN 'Standard' THEN 33 -- Standard PC (Phase 2)
WHEN 'Shopfloor' THEN 35 -- Shopfloor PC (Phase 2)
WHEN 'Engineer' THEN 34 -- Engineering PC (Phase 2)
WHEN 'Server' THEN 33 -- Map to Standard PC
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
FROM pctype pt;
SELECT 'PC Type Mapping Created:' AS '';
SELECT * FROM temp_pctype_mapping;
SELECT '' AS '';
-- =====================================================
-- STEP 3: Create backup of PC data
-- =====================================================
DROP TABLE IF EXISTS pc_backup_phase2;
CREATE TABLE pc_backup_phase2 AS SELECT * FROM pc;
SELECT CONCAT('✓ Backup created: pc_backup_phase2 (', COUNT(*), ' records)') AS status
FROM pc_backup_phase2;
SELECT '' AS '';
-- =====================================================
-- STEP 4: Create temporary table for new machine records
-- =====================================================
DROP TEMPORARY TABLE IF EXISTS temp_new_machines;
CREATE TEMPORARY TABLE temp_new_machines AS
SELECT
NULL AS new_machineid, -- Will be auto-generated
p.pcid AS old_pcid, -- Track source PC
-- Machine type based on PC type
m.target_machinetypeid AS machinetypeid,
-- PC identification fields
COALESCE(p.hostname, CONCAT('PC_', p.pcid)) AS machinenumber, -- Use hostname or generate PC_[id]
p.hostname AS hostname,
COALESCE(p.hostname, CONCAT('PC_', p.pcid)) AS alias, -- Set alias same as machinenumber
p.loggedinuser,
-- Model and vendor
p.modelnumberid,
NULL AS controllertypeid, -- PCs don't have controllers
NULL AS controllerosid, -- PCs don't have controller OS
p.serialnumber,
-- OS and status
p.osid,
CASE
WHEN p.pcstatusid IS NOT NULL THEN p.pcstatusid
ELSE 3 -- Default to 'In Use' (machinestatusid 3)
END AS machinestatusid,
p.pctypeid,
-- Business unit (default to 1 if not set)
COALESCE(
(SELECT businessunitid FROM machines WHERE machinenumber = p.machinenumber AND isactive = 1 LIMIT 1),
1
) AS businessunitid,
-- Printer assignment (if PC has one from existing machines table)
(SELECT printerid FROM machines WHERE machinenumber = p.machinenumber AND isactive = 1 LIMIT 1) AS printerid,
-- Map coordinates (if exists from existing machines table)
(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,
-- VNC (default no)
0 AS isvnc,
-- Location flags
0 AS islocationonly,
p.requires_manual_machine_config,
-- Deprecated IP fields (set to NULL)
NULL AS ipaddress1,
NULL AS ipaddress2,
-- Notes
NULL AS machinenotes,
-- Status and audit
p.isactive,
p.lastupdated,
p.dateadded
FROM pc p
JOIN temp_pctype_mapping m ON p.pctypeid = m.pctypeid
WHERE p.isactive = 1;
SELECT CONCAT('✓ Prepared ', COUNT(*), ' PC records for migration') AS status
FROM temp_new_machines;
SELECT '' AS '';
-- =====================================================
-- STEP 5: Show sample of data to be migrated
-- =====================================================
SELECT 'Sample of PCs to be migrated (first 5):' AS '';
SELECT
old_pcid,
machinenumber,
hostname,
serialnumber,
machinetypeid,
osid,
machinestatusid
FROM temp_new_machines
LIMIT 5;
SELECT '' AS '';
-- =====================================================
-- STEP 6: Insert PC records into machines table
-- =====================================================
SELECT 'Inserting PC records into machines table...' AS '';
INSERT INTO machines (
machinetypeid,
machinenumber,
hostname,
alias,
loggedinuser,
modelnumberid,
controllertypeid,
controllerosid,
serialnumber,
osid,
machinestatusid,
pctypeid,
businessunitid,
printerid,
mapleft,
maptop,
isvnc,
islocationonly,
requires_manual_machine_config,
ipaddress1,
ipaddress2,
machinenotes,
isactive,
lastupdated,
dateadded
)
SELECT
machinetypeid,
machinenumber,
hostname,
alias,
loggedinuser,
modelnumberid,
controllertypeid,
controllerosid,
serialnumber,
osid,
machinestatusid,
pctypeid,
businessunitid,
printerid,
mapleft,
maptop,
isvnc,
islocationonly,
requires_manual_machine_config,
ipaddress1,
ipaddress2,
machinenotes,
isactive,
lastupdated,
dateadded
FROM temp_new_machines;
SELECT CONCAT('✓ Inserted ', ROW_COUNT(), ' PC records into machines table') AS status;
SELECT '' AS '';
-- =====================================================
-- STEP 7: Create mapping table for old pcid to new machineid
-- =====================================================
DROP TABLE IF EXISTS pc_to_machine_id_mapping;
CREATE TABLE pc_to_machine_id_mapping (
pcid INT,
old_hostname VARCHAR(100),
new_machineid INT,
new_machinenumber VARCHAR(255),
migration_date DATETIME DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (pcid),
KEY idx_new_machineid (new_machineid)
) ENGINE=InnoDB COMMENT='Mapping of old PC IDs to new machine IDs for Phase 2 migration';
INSERT INTO pc_to_machine_id_mapping (pcid, old_hostname, new_machineid, new_machinenumber)
SELECT
p.pcid,
p.hostname,
m.machineid,
m.machinenumber
FROM pc p
JOIN machines m ON m.hostname = p.hostname
WHERE p.isactive = 1
AND m.pctypeid IS NOT NULL; -- Only PCs (have pctypeid set)
SELECT CONCAT('✓ Created ID mapping table: ', COUNT(*), ' mappings') AS status
FROM pc_to_machine_id_mapping;
SELECT '' AS '';
-- =====================================================
-- VERIFICATION
-- =====================================================
SELECT '========================================' AS '';
SELECT 'MIGRATION VERIFICATION' AS '';
SELECT '========================================' AS '';
SELECT '' AS '';
-- Count machines before and after
SELECT 'Machine counts:' AS '';
SELECT
'Original PCs (active)' AS category,
COUNT(*) as count
FROM pc WHERE isactive = 1
UNION ALL
SELECT
'New machines with pctypeid' AS category,
COUNT(*) as count
FROM machines WHERE pctypeid IS NOT NULL
UNION ALL
SELECT
'Total active machines now' AS category,
COUNT(*) as count
FROM machines WHERE isactive = 1;
SELECT '' AS '';
-- Show machine type distribution
SELECT 'New machine type distribution:' AS '';
SELECT
mt.machinetype,
COUNT(*) as count
FROM machines m
JOIN machinetypes mt ON m.machinetypeid = mt.machinetypeid
WHERE m.pctypeid IS NOT NULL
GROUP BY mt.machinetype
ORDER BY count DESC;
SELECT '' AS '';
-- Check for missing data
SELECT 'Data quality checks:' AS '';
SELECT
'PCs with NULL hostname' AS check_name,
COUNT(*) as count
FROM machines WHERE pctypeid IS NOT NULL AND hostname IS NULL
UNION ALL
SELECT
'PCs with NULL machinetypeid' AS check_name,
COUNT(*) as count
FROM machines WHERE pctypeid IS NOT NULL AND machinetypeid IS NULL
UNION ALL
SELECT
'PCs with NULL machinestatusid' AS check_name,
COUNT(*) as count
FROM machines WHERE pctypeid IS NOT NULL AND machinestatusid IS NULL;
SELECT '' AS '';
SELECT '✓ Script 01 completed successfully' AS status;
SELECT 'Next: Run script 02_migrate_network_interfaces_to_communications.sql' AS '';
SET SQL_SAFE_UPDATES = 1;
-- =====================================================
-- NOTES
-- =====================================================
-- Backup table created: pc_backup_phase2
-- Mapping table created: pc_to_machine_id_mapping
--
-- PCs migrated with:
-- - machinenumber = hostname
-- - alias = hostname
-- - Machine type based on PC type mapping
-- - All PC-specific fields populated
--
-- Next scripts will migrate:
-- - Network interfaces → communications
-- - Comm config → communications
-- - Warranties → warranties table
-- - Dualpath assignments → machinerelationships
--
-- ROLLBACK: Drop inserted records and restore from pc_backup_phase2
-- =====================================================

View File

@@ -0,0 +1,200 @@
-- =====================================================
-- SCRIPT 02: Migrate Network Interfaces to Communications
-- =====================================================
-- Date: 2025-11-06
-- Purpose: Migrate pc_network_interfaces to communications table
-- Status: REQUIRES TESTING - Depends on Script 01
-- Estimated Time: 3-5 minutes
-- Records: ~705 network interfaces
-- =====================================================
USE shopdb;
SET SQL_SAFE_UPDATES = 0;
-- =====================================================
-- STEP 1: Pre-migration checks
-- =====================================================
SELECT '========================================' AS '';
SELECT 'NETWORK INTERFACES MIGRATION' AS '';
SELECT '========================================' AS '';
SELECT '' AS '';
-- Verify pc_to_machine_id_mapping exists
SELECT CASE
WHEN COUNT(*) > 0 THEN CONCAT('✓ Mapping table exists (', COUNT(*), ' mappings)')
ELSE '⚠️ ERROR: Run script 01 first!'
END AS status
FROM pc_to_machine_id_mapping;
-- Count interfaces to migrate
SELECT CONCAT('Network interfaces to migrate: ', COUNT(*)) AS info
FROM pc_network_interfaces
WHERE isactive = 1;
SELECT '' AS '';
-- =====================================================
-- STEP 2: Get comstypeid for Network_Interface
-- =====================================================
SET @network_interface_type = (SELECT comstypeid FROM comstypes WHERE typename = 'Network_Interface' LIMIT 1);
SELECT CONCAT('✓ Network_Interface comstypeid: ', @network_interface_type) AS status;
SELECT '' AS '';
-- =====================================================
-- STEP 3: Create backup
-- =====================================================
DROP TABLE IF EXISTS pc_network_interfaces_backup_phase2;
CREATE TABLE pc_network_interfaces_backup_phase2 AS
SELECT * FROM pc_network_interfaces;
SELECT CONCAT('✓ Backup created: ', COUNT(*), ' records') AS status
FROM pc_network_interfaces_backup_phase2;
SELECT '' AS '';
-- =====================================================
-- STEP 4: Show sample data
-- =====================================================
SELECT 'Sample network interfaces (first 5):' AS '';
SELECT
ni.interfaceid,
ni.pcid,
m.new_machineid,
ni.interfacename,
ni.ipaddress,
ni.macaddress,
ni.isdhcp
FROM pc_network_interfaces ni
LEFT JOIN pc_to_machine_id_mapping m ON ni.pcid = m.pcid
WHERE ni.isactive = 1
LIMIT 5;
SELECT '' AS '';
-- =====================================================
-- STEP 5: Migrate network interfaces
-- =====================================================
SELECT 'Migrating network interfaces...' AS '';
INSERT INTO communications (
machineid,
comstypeid,
address, -- IP address
macaddress,
subnetmask,
defaultgateway,
dnsserver,
isdhcp,
interfacename,
isprimary,
isactive,
ismachinenetwork,
lastupdated
)
SELECT
m.new_machineid, -- Map to new machine ID
@network_interface_type, -- Network_Interface type
ni.ipaddress AS address, -- IP address in generic address field
ni.macaddress,
ni.subnetmask,
ni.defaultgateway,
NULL AS dnsserver, -- Not in old schema
COALESCE(ni.isdhcp, 0),
ni.interfacename,
0 AS isprimary, -- Default to not primary (can be updated later)
ni.isactive,
COALESCE(ni.ismachinenetwork, 0),
ni.lastupdated
FROM pc_network_interfaces ni
JOIN pc_to_machine_id_mapping m ON ni.pcid = m.pcid
WHERE ni.isactive = 1
AND m.new_machineid IS NOT NULL;
SELECT CONCAT('✓ Migrated ', ROW_COUNT(), ' network interfaces') AS status;
SELECT '' AS '';
-- =====================================================
-- VERIFICATION
-- =====================================================
SELECT '========================================' AS '';
SELECT 'MIGRATION VERIFICATION' AS '';
SELECT '========================================' AS '';
SELECT '' AS '';
-- Count by type
SELECT 'Communications by type:' AS '';
SELECT
ct.typename,
COUNT(*) as count
FROM communications c
JOIN comstypes ct ON c.comstypeid = ct.comstypeid
GROUP BY ct.typename
ORDER BY count DESC;
SELECT '' AS '';
-- Sample migrated data
SELECT 'Sample migrated communications (first 5):' AS '';
SELECT
c.comid,
c.machineid,
m.machinenumber,
m.hostname,
ct.typename,
c.address,
c.macaddress
FROM communications c
JOIN machines m ON c.machineid = m.machineid
JOIN comstypes ct ON c.comstypeid = ct.comstypeid
WHERE ct.typename = 'Network_Interface'
LIMIT 5;
SELECT '' AS '';
-- Check for issues
SELECT 'Data quality checks:' AS '';
SELECT
'Communications with NULL machineid' AS check_name,
COUNT(*) as count
FROM communications WHERE machineid IS NULL
UNION ALL
SELECT
'Communications with NULL address' AS check_name,
COUNT(*) as count
FROM communications WHERE address IS NULL AND comstypeid = @network_interface_type;
SELECT '' AS '';
SELECT '✓ Script 02 completed successfully' AS status;
SELECT 'Next: Run script 03_migrate_comm_config_to_communications.sql' AS '';
SET SQL_SAFE_UPDATES = 1;
-- =====================================================
-- NOTES
-- =====================================================
-- Backup created: pc_network_interfaces_backup_phase2
--
-- Migrated fields:
-- - pcid → machineid (via mapping table)
-- - ipaddress → address (generic field)
-- - macaddress, subnetmask, defaultgateway → direct copy
-- - interfacename → direct copy
-- - isdhcp, isactive, ismachinenetwork → direct copy
-- - comstypeid set to Network_Interface
--
-- NOT migrated (not in old schema):
-- - port, portname, baud, databits (serial fields)
-- - protocol, username, password (protocol fields)
-- - dnsserver (not in old schema)
--
-- ROLLBACK: Delete from communications where comstypeid = Network_Interface
-- =====================================================

View File

@@ -0,0 +1,212 @@
-- =====================================================
-- SCRIPT 03: Migrate Comm Config to Communications
-- =====================================================
-- Date: 2025-11-06
-- Purpose: Migrate pc_comm_config to communications table
-- Status: REQUIRES TESTING - Depends on Script 01
-- Estimated Time: 2-3 minutes
-- =====================================================
USE shopdb;
SET SQL_SAFE_UPDATES = 0;
-- =====================================================
-- STEP 1: Pre-migration checks
-- =====================================================
SELECT '========================================' AS '';
SELECT 'COMM CONFIG MIGRATION' AS '';
SELECT '========================================' AS '';
SELECT '' AS '';
-- Count configs to migrate
SELECT CONCAT('Comm configs to migrate: ', COUNT(*)) AS info
FROM pc_comm_config;
-- Show config types
SELECT 'Config type distribution:' AS '';
SELECT configtype, COUNT(*) as count
FROM pc_comm_config
GROUP BY configtype
ORDER BY count DESC;
SELECT '' AS '';
-- =====================================================
-- STEP 2: Get comstypeid mappings
-- =====================================================
SET @serial_type = (SELECT comstypeid FROM comstypes WHERE typename = 'Serial' LIMIT 1);
SET @ip_type = (SELECT comstypeid FROM comstypes WHERE typename = 'IP' LIMIT 1);
SELECT CONCAT('✓ Serial comstypeid: ', @serial_type) AS status;
SELECT CONCAT('✓ IP comstypeid: ', @ip_type) AS status;
SELECT '' AS '';
-- =====================================================
-- STEP 3: Create backup
-- =====================================================
DROP TABLE IF EXISTS pc_comm_config_backup_phase2;
CREATE TABLE pc_comm_config_backup_phase2 AS
SELECT * FROM pc_comm_config;
SELECT CONCAT('✓ Backup created: ', COUNT(*), ' records') AS status
FROM pc_comm_config_backup_phase2;
SELECT '' AS '';
-- =====================================================
-- STEP 4: Show sample data
-- =====================================================
SELECT 'Sample comm configs (first 5):' AS '';
SELECT
cc.configid,
cc.pcid,
m.new_machineid,
cc.configtype,
cc.portid,
cc.baud,
cc.ipaddress,
cc.socketnumber
FROM pc_comm_config cc
LEFT JOIN pc_to_machine_id_mapping m ON cc.pcid = m.pcid
LIMIT 5;
SELECT '' AS '';
-- =====================================================
-- STEP 5: Migrate comm configs
-- =====================================================
SELECT 'Migrating comm configs...' AS '';
INSERT INTO communications (
machineid,
comstypeid,
address, -- IP address OR port name
port, -- Socket number for IP, NULL for serial
portname, -- COM port name for serial
baud,
databits,
stopbits,
parity,
flowcontrol,
settings, -- Additional settings as text
isactive,
lastupdated
)
SELECT
m.new_machineid,
CASE
WHEN cc.configtype = 'Serial' THEN @serial_type
WHEN cc.configtype = 'IP' THEN @ip_type
ELSE @ip_type -- Default to IP
END AS comstypeid,
CASE
WHEN cc.configtype = 'Serial' THEN cc.portid -- COM1, COM2, etc.
WHEN cc.configtype = 'IP' THEN cc.ipaddress
ELSE cc.ipaddress
END AS address,
cc.socketnumber AS port, -- Port number for IP connections
CASE
WHEN cc.configtype = 'Serial' THEN cc.portid
ELSE NULL
END AS portname,
cc.baud,
cc.databits,
cc.stopbits,
cc.parity,
NULL AS flowcontrol, -- Not in old schema, set CRLF to settings
CONCAT(
CASE WHEN cc.crlf IS NOT NULL THEN CONCAT('CRLF: ', cc.crlf, '; ') ELSE '' END,
CASE WHEN cc.additionalsettings IS NOT NULL THEN cc.additionalsettings ELSE '' END
) AS settings,
1 AS isactive,
cc.lastupdated
FROM pc_comm_config cc
JOIN pc_to_machine_id_mapping m ON cc.pcid = m.pcid
WHERE m.new_machineid IS NOT NULL;
SELECT CONCAT('✓ Migrated ', ROW_COUNT(), ' comm configs') AS status;
SELECT '' AS '';
-- =====================================================
-- VERIFICATION
-- =====================================================
SELECT '========================================' AS '';
SELECT 'MIGRATION VERIFICATION' AS '';
SELECT '========================================' AS '';
SELECT '' AS '';
-- Count by type
SELECT 'Communications by type (all):' AS '';
SELECT
ct.typename,
COUNT(*) as count
FROM communications c
JOIN comstypes ct ON c.comstypeid = ct.comstypeid
GROUP BY ct.typename
ORDER BY count DESC;
SELECT '' AS '';
-- Sample serial configs
SELECT 'Sample serial communications:' AS '';
SELECT
c.comid,
m.hostname,
c.address AS port,
c.portname,
c.baud,
c.databits,
c.stopbits,
c.parity
FROM communications c
JOIN machines m ON c.machineid = m.machineid
JOIN comstypes ct ON c.comstypeid = ct.comstypeid
WHERE ct.typename = 'Serial'
LIMIT 3;
SELECT '' AS '';
-- Sample IP configs
SELECT 'Sample IP communications:' AS '';
SELECT
c.comid,
m.hostname,
c.address AS ipaddress,
c.port AS socket
FROM communications c
JOIN machines m ON c.machineid = m.machineid
JOIN comstypes ct ON c.comstypeid = ct.comstypeid
WHERE ct.typename = 'IP'
LIMIT 3;
SELECT '' AS '';
SELECT '✓ Script 03 completed successfully' AS status;
SELECT 'Next: Run script 04_migrate_warranties.sql' AS '';
SET SQL_SAFE_UPDATES = 1;
-- =====================================================
-- NOTES
-- =====================================================
-- Backup created: pc_comm_config_backup_phase2
--
-- Migrated fields:
-- - Serial configs: address = portid (COM1, COM2, etc.)
-- - IP configs: address = ipaddress, port = socketnumber
-- - baud, databits, stopbits, parity → direct copy
-- - crlf + additionalsettings → combined in settings field
--
-- Mapping:
-- - configtype 'Serial' → comstypeid for 'Serial'
-- - configtype 'IP' → comstypeid for 'IP'
--
-- ROLLBACK: Delete from communications where comstypeid IN (Serial, IP)
-- =====================================================

View File

@@ -0,0 +1,164 @@
-- =====================================================
-- SCRIPT 04: Migrate PC Warranty Data
-- =====================================================
-- Date: 2025-11-06
-- Purpose: Migrate PC warranty data to warranties table
-- Status: REQUIRES TESTING - Depends on Script 01
-- Estimated Time: 2-3 minutes
-- =====================================================
USE shopdb;
SET SQL_SAFE_UPDATES = 0;
-- =====================================================
-- STEP 1: Pre-migration checks
-- =====================================================
SELECT '========================================' AS '';
SELECT 'WARRANTY DATA MIGRATION' AS '';
SELECT '========================================' AS '';
SELECT '' AS '';
-- Count PCs with warranty data
SELECT CONCAT('PCs with warranty end dates: ', COUNT(*)) AS info
FROM pc
WHERE warrantyenddate IS NOT NULL
AND isactive = 1;
-- Show warranty status distribution
SELECT 'Warranty status distribution:' AS '';
SELECT
CASE
WHEN warrantyenddate IS NULL THEN 'No warranty data'
WHEN warrantyenddate < CURDATE() THEN 'Expired'
WHEN warrantyenddate < DATE_ADD(CURDATE(), INTERVAL 90 DAY) THEN 'Expiring soon'
ELSE 'Active'
END AS status,
COUNT(*) as count
FROM pc
WHERE isactive = 1
GROUP BY status
ORDER BY count DESC;
SELECT '' AS '';
-- =====================================================
-- STEP 2: Show sample data
-- =====================================================
SELECT 'Sample warranty data (first 5):' AS '';
SELECT
p.pcid,
p.hostname,
m.new_machineid,
p.warrantyenddate,
p.warrantyservicelevel,
p.warrantylastchecked
FROM pc p
LEFT JOIN pc_to_machine_id_mapping m ON p.pcid = m.pcid
WHERE p.warrantyenddate IS NOT NULL
AND p.isactive = 1
LIMIT 5;
SELECT '' AS '';
-- =====================================================
-- STEP 3: Migrate warranty data
-- =====================================================
SELECT 'Migrating warranty data...' AS '';
INSERT INTO warranties (
machineid,
warrantyname,
enddate,
servicelevel,
lastcheckeddate
)
SELECT
m.new_machineid,
NULL AS warrantyname, -- Not in old PC table, set to NULL
p.warrantyenddate AS enddate,
p.warrantyservicelevel AS servicelevel,
p.warrantylastchecked AS lastcheckeddate
FROM pc p
JOIN pc_to_machine_id_mapping m ON p.pcid = m.pcid
WHERE p.warrantyenddate IS NOT NULL -- Only migrate if warranty date exists
AND p.isactive = 1
AND m.new_machineid IS NOT NULL;
SELECT CONCAT('✓ Migrated ', ROW_COUNT(), ' warranty records') AS status;
SELECT '' AS '';
-- =====================================================
-- VERIFICATION
-- =====================================================
SELECT '========================================' AS '';
SELECT 'MIGRATION VERIFICATION' AS '';
SELECT '========================================' AS '';
SELECT '' AS '';
-- Count warranties
SELECT CONCAT('Total warranty records: ', COUNT(*)) AS info
FROM warranties;
-- Warranty status using view
SELECT 'Warranty status summary:' AS '';
SELECT
warrantystatus,
COUNT(*) as count
FROM vw_warranty_status
WHERE machineid IN (SELECT new_machineid FROM pc_to_machine_id_mapping)
GROUP BY warrantystatus
ORDER BY count DESC;
SELECT '' AS '';
-- Sample migrated warranties
SELECT 'Sample migrated warranties:' AS '';
SELECT
w.warrantyid,
m.hostname,
w.enddate,
w.servicelevel,
DATEDIFF(w.enddate, CURDATE()) as days_remaining
FROM warranties w
JOIN machines m ON w.machineid = m.machineid
WHERE m.pctypeid IS NOT NULL
LIMIT 5;
SELECT '' AS '';
-- Expiring warranties
SELECT 'Warranties expiring in next 90 days:' AS '';
SELECT COUNT(*) as count
FROM vw_warranties_expiring
WHERE machineid IN (SELECT new_machineid FROM pc_to_machine_id_mapping);
SELECT '' AS '';
SELECT '✓ Script 04 completed successfully' AS status;
SELECT 'Next: Run script 05_migrate_dualpath_assignments.sql' AS '';
SET SQL_SAFE_UPDATES = 1;
-- =====================================================
-- NOTES
-- =====================================================
-- Migrated fields from pc table:
-- - warrantyenddate → warranties.enddate
-- - warrantyservicelevel → warranties.servicelevel
-- - warrantylastchecked → warranties.lastcheckeddate
-- - warrantyname → NULL (not in old schema)
--
-- Computed fields (not stored):
-- - warrantystatus (computed in vw_warranty_status view)
-- - warrantydaysremaining (computed in vw_warranty_status view)
--
-- Only migrated PCs with warrantyenddate NOT NULL
--
-- ROLLBACK: DELETE FROM warranties WHERE machineid IN
-- (SELECT new_machineid FROM pc_to_machine_id_mapping)
-- =====================================================

View File

@@ -0,0 +1,177 @@
-- =====================================================
-- SCRIPT 05: Migrate Dualpath Assignments
-- =====================================================
-- Date: 2025-11-06
-- Purpose: Migrate pc_dualpath_assignments to machinerelationships
-- Status: REQUIRES TESTING - Depends on Script 01
-- Estimated Time: 1-2 minutes
-- =====================================================
USE shopdb;
SET SQL_SAFE_UPDATES = 0;
-- =====================================================
-- STEP 1: Pre-migration checks
-- =====================================================
SELECT '========================================' AS '';
SELECT 'DUALPATH ASSIGNMENTS MIGRATION' AS '';
SELECT '========================================' AS '';
SELECT '' AS '';
-- Count dualpath assignments
SELECT CONCAT('Dualpath assignments to migrate: ', COUNT(*)) AS info
FROM pc_dualpath_assignments;
-- Show sample data
SELECT 'Sample dualpath assignments:' AS '';
SELECT
d.dualpathid,
d.pcid,
d.primary_machine,
d.secondary_machine
FROM pc_dualpath_assignments d
LIMIT 3;
SELECT '' AS '';
-- =====================================================
-- STEP 2: Get relationshiptypeid for Dualpath
-- =====================================================
SET @dualpath_type = (SELECT relationshiptypeid FROM relationshiptypes WHERE relationshiptype = 'Dualpath' LIMIT 1);
SELECT CONCAT('✓ Dualpath relationshiptypeid: ', @dualpath_type) AS status;
SELECT '' AS '';
-- =====================================================
-- STEP 3: Create backup
-- =====================================================
DROP TABLE IF EXISTS pc_dualpath_assignments_backup_phase2;
CREATE TABLE pc_dualpath_assignments_backup_phase2 AS
SELECT * FROM pc_dualpath_assignments;
SELECT CONCAT('✓ Backup created: ', COUNT(*), ' records') AS status
FROM pc_dualpath_assignments_backup_phase2;
SELECT '' AS '';
-- =====================================================
-- STEP 4: Migrate dualpath assignments
-- =====================================================
SELECT 'Migrating dualpath assignments...' AS '';
-- Create bidirectional relationships for dualpath machines
-- Machine 1 → Machine 2
INSERT INTO machinerelationships (
machineid,
related_machineid,
relationshiptypeid,
relationship_notes,
isactive
)
SELECT
m1.machineid AS machineid,
m2.machineid AS related_machineid,
@dualpath_type,
CONCAT('Dualpath with ', m2.machinenumber) AS relationship_notes,
1 AS isactive
FROM pc_dualpath_assignments d
JOIN pc_to_machine_id_mapping pcmap ON d.pcid = pcmap.pcid
JOIN machines m1 ON m1.machinenumber = d.primary_machine AND m1.isactive = 1
JOIN machines m2 ON m2.machinenumber = d.secondary_machine AND m2.isactive = 1
WHERE d.primary_machine IS NOT NULL
AND d.secondary_machine IS NOT NULL;
SELECT CONCAT('✓ Created ', ROW_COUNT(), ' dualpath relationships (direction 1)') AS status;
-- Machine 2 → Machine 1 (reverse relationship)
INSERT INTO machinerelationships (
machineid,
related_machineid,
relationshiptypeid,
relationship_notes,
isactive
)
SELECT
m2.machineid AS machineid,
m1.machineid AS related_machineid,
@dualpath_type,
CONCAT('Dualpath with ', m1.machinenumber) AS relationship_notes,
1 AS isactive
FROM pc_dualpath_assignments d
JOIN pc_to_machine_id_mapping pcmap ON d.pcid = pcmap.pcid
JOIN machines m1 ON m1.machinenumber = d.primary_machine AND m1.isactive = 1
JOIN machines m2 ON m2.machinenumber = d.secondary_machine AND m2.isactive = 1
WHERE d.primary_machine IS NOT NULL
AND d.secondary_machine IS NOT NULL;
SELECT CONCAT('✓ Created ', ROW_COUNT(), ' dualpath relationships (direction 2)') AS status;
SELECT '' AS '';
-- =====================================================
-- VERIFICATION
-- =====================================================
SELECT '========================================' AS '';
SELECT 'MIGRATION VERIFICATION' AS '';
SELECT '========================================' AS '';
SELECT '' AS '';
-- Count relationships by type
SELECT 'Relationships by type:' AS '';
SELECT
rt.relationshiptype,
COUNT(*) as count
FROM machinerelationships mr
JOIN relationshiptypes rt ON mr.relationshiptypeid = rt.relationshiptypeid
WHERE mr.isactive = 1
GROUP BY rt.relationshiptype
ORDER BY count DESC;
SELECT '' AS '';
-- Show dualpath pairs using view
SELECT 'Dualpath machine pairs:' AS '';
SELECT
machine1_number,
machine1_hostname,
machine2_number,
machine2_hostname
FROM vw_dualpath_machines
LIMIT 5;
SELECT '' AS '';
-- Count total dualpath relationships
SELECT CONCAT('Total dualpath relationships: ', COUNT(*)) AS info
FROM machinerelationships
WHERE relationshiptypeid = @dualpath_type
AND isactive = 1;
SELECT '' AS '';
SELECT '✓ Script 05 completed successfully' AS status;
SELECT 'Next: Run VERIFY_PHASE2_MIGRATION.sql' AS '';
SET SQL_SAFE_UPDATES = 1;
-- =====================================================
-- NOTES
-- =====================================================
-- Backup created: pc_dualpath_assignments_backup_phase2
--
-- Relationships created bidirectionally:
-- - primary_machine → secondary_machine
-- - secondary_machine → primary_machine
--
-- Both use relationshiptype = 'Dualpath'
--
-- View available: vw_dualpath_machines shows pairs
--
-- ROLLBACK: DELETE FROM machinerelationships
-- WHERE relationshiptypeid = @dualpath_type
-- =====================================================

View File

@@ -0,0 +1,170 @@
-- =====================================================
-- SCRIPT 05b: Migrate PC Controls Relationships
-- =====================================================
-- Date: 2025-11-13
-- Purpose: Create PC-to-Equipment Controls relationships
-- Status: TESTED on DEV - Created 148 relationships
-- Estimated Time: < 1 minute
-- Dependencies:
-- - Script 01 (PCs must be in machines table)
-- - relationshiptypes table (relationshiptypeid = 3 for 'Controls')
-- =====================================================
USE shopdb;
SET SQL_SAFE_UPDATES = 0;
-- =====================================================
-- STEP 1: Pre-migration checks
-- =====================================================
SELECT '========================================' AS '';
SELECT 'PC CONTROLS RELATIONSHIPS MIGRATION' AS '';
SELECT '========================================' AS '';
SELECT '' AS '';
-- Count PCs with machinenumber assignments
SELECT CONCAT('PCs with machine assignments: ', COUNT(*)) AS info
FROM pc
WHERE isactive = 1
AND machinenumber IS NOT NULL
AND machinenumber != '';
-- Show sample data
SELECT 'Sample PC-to-machine assignments (from old pc table):' AS '';
SELECT
p.pcid,
p.hostname AS pc_hostname,
p.machinenumber AS controls_machine
FROM pc p
WHERE p.isactive = 1
AND p.machinenumber IS NOT NULL
AND p.machinenumber != ''
ORDER BY p.machinenumber
LIMIT 10;
-- Check current machinerelationships count
SELECT CONCAT('Existing relationships: ', COUNT(*)) AS info
FROM machinerelationships;
SELECT '' AS '';
-- =====================================================
-- STEP 2: Validate relationshiptypes exists
-- =====================================================
SELECT 'Validating relationship types...' AS '';
-- Check if 'Controls' relationship type exists
SELECT
CASE
WHEN COUNT(*) > 0 THEN '✓ Controls relationship type exists'
ELSE '✗ ERROR: Controls relationship type missing!'
END AS status
FROM relationshiptypes
WHERE relationshiptypeid = 3 AND relationshiptype = 'Controls';
SELECT '' AS '';
-- =====================================================
-- STEP 3: Create Controls relationships
-- =====================================================
SELECT 'Creating PC Controls relationships...' AS '';
-- Insert Controls relationships by matching pc.machinenumber to equipment.machinenumber
-- and pc.hostname to migrated PC hostname
INSERT INTO machinerelationships (machineid, related_machineid, relationshiptypeid, isactive)
SELECT DISTINCT
equipment.machineid AS equipment_machineid,
pc_migrated.machineid AS pc_machineid,
3 AS relationshiptypeid, -- 'Controls' relationship
1 AS isactive
FROM pc old_pc
JOIN machines equipment ON equipment.machinenumber = old_pc.machinenumber
JOIN machines pc_migrated ON pc_migrated.hostname = old_pc.hostname
WHERE old_pc.isactive = 1
AND old_pc.machinenumber IS NOT NULL
AND old_pc.machinenumber != ''
AND equipment.pctypeid IS NULL -- Equipment only (not PCs)
AND pc_migrated.pctypeid IS NOT NULL -- PCs only
AND NOT EXISTS (
SELECT 1 FROM machinerelationships mr
WHERE mr.machineid = equipment.machineid
AND mr.related_machineid = pc_migrated.machineid
AND mr.relationshiptypeid = 3
);
-- Get count
SELECT CONCAT('✓ Created ', ROW_COUNT(), ' Controls relationships') AS result;
SELECT '' AS '';
-- =====================================================
-- STEP 4: Verification
-- =====================================================
SELECT 'Verification Results:' AS '';
SELECT '===================' AS '';
-- Total relationships now
SELECT CONCAT('Total relationships: ', COUNT(*)) AS info
FROM machinerelationships;
-- Breakdown by relationship type
SELECT
rt.relationshiptype,
COUNT(*) AS count
FROM machinerelationships mr
JOIN relationshiptypes rt ON mr.relationshiptypeid = rt.relationshiptypeid
GROUP BY rt.relationshiptype;
-- Sample relationships created
SELECT 'Sample relationships (first 10):' AS '';
SELECT
equipment.machinenumber AS equipment_num,
equipment.alias AS equipment_name,
pc.hostname AS controlling_pc,
rt.relationshiptype
FROM machinerelationships mr
JOIN machines equipment ON mr.machineid = equipment.machineid
JOIN machines pc ON mr.related_machineid = pc.machineid
JOIN relationshiptypes rt ON mr.relationshiptypeid = rt.relationshiptypeid
WHERE rt.relationshiptype = 'Controls'
ORDER BY equipment.machinenumber
LIMIT 10;
-- Check for orphaned equipment (no controlling PC)
SELECT CONCAT('Equipment without PC assignment: ', COUNT(*)) AS warning
FROM machines equipment
WHERE equipment.pctypeid IS NULL
AND equipment.isactive = 1
AND NOT EXISTS (
SELECT 1 FROM machinerelationships mr
JOIN relationshiptypes rt ON mr.relationshiptypeid = rt.relationshiptypeid
WHERE mr.machineid = equipment.machineid
AND rt.relationshiptype = 'Controls'
);
SELECT '' AS '';
SELECT '========================================' AS '';
SELECT 'MIGRATION COMPLETE' AS '';
SELECT '========================================' AS '';
-- =====================================================
-- NOTES
-- =====================================================
--
-- This script creates PC-to-Equipment "Controls" relationships by:
-- 1. Reading pc.machinenumber (which machine the PC controls)
-- 2. Matching to equipment.machinenumber
-- 3. Matching pc.hostname to migrated PC in machines table
-- 4. Creating the relationship in machinerelationships table
--
-- DEV Testing Results:
-- - 142 relationships created from pc.machinenumber
-- - 6 relationships existed from hostname matching
-- - Total: 148 PC-to-Equipment relationships
--
-- Example: Machine 130 (equipment "2001") controlled by PC 390 ("GB07T5X3ESF")
--
-- =====================================================

View File

@@ -0,0 +1,640 @@
-- =====================================================
-- SCRIPT 06: Update Views for PC→Machines Migration
-- =====================================================
-- Date: 2025-11-07
-- Purpose: Update 19 views to query machines table instead of pc table
-- Status: REQUIRES TESTING - Depends on Scripts 01-05
-- Estimated Time: 2-3 minutes
-- =====================================================
USE shopdb;
SET SQL_SAFE_UPDATES = 0;
-- =====================================================
-- STEP 1: Pre-update information
-- =====================================================
SELECT '========================================' AS '';
SELECT 'VIEW UPDATES FOR MACHINES TABLE' AS '';
SELECT '========================================' AS '';
SELECT '' AS '';
SELECT 'Views to update:' AS '';
SELECT COUNT(*) as view_count
FROM INFORMATION_SCHEMA.VIEWS
WHERE TABLE_SCHEMA = 'shopdb'
AND VIEW_DEFINITION LIKE '%`pc`%';
SELECT '' AS '';
-- =====================================================
-- STEP 2: Drop and recreate views
-- =====================================================
-- View 1: vw_active_pcs
-- Purpose: Show active PCs with basic info and warranty status
SELECT 'Updating vw_active_pcs...' AS '';
DROP VIEW IF EXISTS vw_active_pcs;
CREATE VIEW vw_active_pcs AS
SELECT
pcmap.pcid AS pcid,
m.hostname AS hostname,
m.serialnumber AS serialnumber,
COALESCE(v.vendor, 'Unknown') AS manufacturer,
md.modelnumber AS model,
m.loggedinuser AS loggedinuser,
m.machinenumber AS machinenumber,
COALESCE(os.operatingsystem, 'Unknown') AS operatingsystem,
COALESCE(pt.typename, 'Unknown') AS pctype,
COALESCE(pt.description, 'Unknown') AS typedescription,
CASE
WHEN w.enddate IS NULL THEN 'Unknown'
WHEN w.enddate < CURDATE() THEN 'Expired'
WHEN w.enddate < DATE_ADD(CURDATE(), INTERVAL 90 DAY) THEN 'Expiring Soon'
ELSE 'Active'
END AS warrantystatus,
w.enddate AS warrantyenddate,
CASE
WHEN w.enddate IS NULL THEN NULL
ELSE (TO_DAYS(w.enddate) - TO_DAYS(CURDATE()))
END AS warrantydaysremaining,
m.lastupdated AS lastupdated,
(TO_DAYS(NOW()) - TO_DAYS(m.lastupdated)) AS daysold
FROM machines m
JOIN pc_to_machine_id_mapping pcmap ON m.machineid = pcmap.new_machineid
LEFT JOIN models md ON m.modelnumberid = md.modelnumberid
LEFT JOIN vendors v ON md.vendorid = v.vendorid
LEFT JOIN pctype pt ON m.pctypeid = pt.pctypeid
LEFT JOIN operatingsystems os ON m.osid = os.osid
LEFT JOIN warranties w ON m.machineid = w.machineid
WHERE m.lastupdated > (NOW() - INTERVAL 30 DAY)
AND m.pctypeid IS NOT NULL;
SELECT ' ✓ vw_active_pcs updated' AS status;
-- View 2: vw_pc_summary
-- Purpose: Summary statistics of PCs by type
SELECT 'Updating vw_pc_summary...' AS '';
DROP VIEW IF EXISTS vw_pc_summary;
CREATE VIEW vw_pc_summary AS
SELECT
pt.typename AS PCType,
pt.description AS Description,
COUNT(m.machineid) AS Count,
ROUND((COUNT(m.machineid) * 100.0) / NULLIF(
(SELECT COUNT(*) FROM machines
WHERE pctypeid IS NOT NULL
AND lastupdated > (NOW() - INTERVAL 30 DAY)), 0
), 2) AS Percentage
FROM pctype pt
LEFT JOIN machines m ON pt.pctypeid = m.pctypeid
AND m.lastupdated > (NOW() - INTERVAL 30 DAY)
AND m.pctypeid IS NOT NULL
WHERE pt.isactive = '1'
GROUP BY pt.pctypeid, pt.typename, pt.description, pt.displayorder
ORDER BY pt.displayorder;
SELECT ' ✓ vw_pc_summary updated' AS status;
-- View 3: vw_shopfloor_pcs
-- Purpose: Show shopfloor PCs with machine associations
SELECT 'Updating vw_shopfloor_pcs...' AS '';
DROP VIEW IF EXISTS vw_shopfloor_pcs;
CREATE VIEW vw_shopfloor_pcs AS
SELECT
pcmap.pcid AS pcid,
m.hostname AS hostname,
m.serialnumber AS serialnumber,
v.vendor AS manufacturer,
md.modelnumber AS model,
m.loggedinuser AS loggedinuser,
COALESCE(CONVERT(mo.machinenumber USING utf8mb4), CONVERT(m.machinenumber USING utf8mb4)) AS machinenumber,
COALESCE(os.operatingsystem, 'Unknown') AS operatingsystem,
m.lastupdated AS lastupdated
FROM machines m
JOIN pc_to_machine_id_mapping pcmap ON m.machineid = pcmap.new_machineid
JOIN pctype pt ON m.pctypeid = pt.pctypeid
LEFT JOIN machine_overrides mo ON pcmap.pcid = mo.pcid
LEFT JOIN models md ON m.modelnumberid = md.modelnumberid
LEFT JOIN vendors v ON md.vendorid = v.vendorid
LEFT JOIN operatingsystems os ON m.osid = os.osid
WHERE pt.typename = 'Shopfloor'
AND m.lastupdated > (NOW() - INTERVAL 30 DAY)
AND m.pctypeid IS NOT NULL
ORDER BY COALESCE(CONVERT(mo.machinenumber USING utf8mb4), CONVERT(m.machinenumber USING utf8mb4)), m.hostname;
SELECT ' ✓ vw_shopfloor_pcs updated' AS status;
-- View 4: vw_engineer_pcs
-- Purpose: Show engineer PCs
SELECT 'Updating vw_engineer_pcs...' AS '';
DROP VIEW IF EXISTS vw_engineer_pcs;
CREATE VIEW vw_engineer_pcs AS
SELECT
pcmap.pcid AS pcid,
m.hostname AS hostname,
m.serialnumber AS serialnumber,
v.vendor AS manufacturer,
md.modelnumber AS model,
m.loggedinuser AS loggedinuser,
m.machinenumber AS machinenumber,
COALESCE(os.operatingsystem, 'Unknown') AS operatingsystem,
m.lastupdated AS lastupdated
FROM machines m
JOIN pc_to_machine_id_mapping pcmap ON m.machineid = pcmap.new_machineid
JOIN pctype pt ON m.pctypeid = pt.pctypeid
LEFT JOIN models md ON m.modelnumberid = md.modelnumberid
LEFT JOIN vendors v ON md.vendorid = v.vendorid
LEFT JOIN operatingsystems os ON m.osid = os.osid
WHERE pt.typename = 'Engineer'
AND m.lastupdated > (NOW() - INTERVAL 30 DAY)
AND m.pctypeid IS NOT NULL
ORDER BY m.hostname;
SELECT ' ✓ vw_engineer_pcs updated' AS status;
-- View 5: vw_standard_pcs
-- Purpose: Show standard PCs
SELECT 'Updating vw_standard_pcs...' AS '';
DROP VIEW IF EXISTS vw_standard_pcs;
CREATE VIEW vw_standard_pcs AS
SELECT
pcmap.pcid AS pcid,
m.hostname AS hostname,
m.serialnumber AS serialnumber,
v.vendor AS manufacturer,
md.modelnumber AS model,
m.loggedinuser AS loggedinuser,
m.machinenumber AS machinenumber,
COALESCE(os.operatingsystem, 'Unknown') AS operatingsystem,
m.lastupdated AS lastupdated
FROM machines m
JOIN pc_to_machine_id_mapping pcmap ON m.machineid = pcmap.new_machineid
JOIN pctype pt ON m.pctypeid = pt.pctypeid
LEFT JOIN models md ON m.modelnumberid = md.modelnumberid
LEFT JOIN vendors v ON md.vendorid = v.vendorid
LEFT JOIN operatingsystems os ON m.osid = os.osid
WHERE pt.typename = 'Standard'
AND m.lastupdated > (NOW() - INTERVAL 30 DAY)
AND m.pctypeid IS NOT NULL
ORDER BY m.hostname;
SELECT ' ✓ vw_standard_pcs updated' AS status;
-- View 6: vw_pcs_by_hardware
-- Purpose: Group PCs by hardware (vendor/model)
SELECT 'Updating vw_pcs_by_hardware...' AS '';
DROP VIEW IF EXISTS vw_pcs_by_hardware;
CREATE VIEW vw_pcs_by_hardware AS
SELECT
COALESCE(v.vendor, 'Unknown') AS manufacturer,
COALESCE(md.modelnumber, 'Unknown') AS model,
COUNT(m.machineid) AS count,
GROUP_CONCAT(DISTINCT pt.typename ORDER BY pt.typename SEPARATOR ', ') AS pc_types
FROM machines m
JOIN pc_to_machine_id_mapping pcmap ON m.machineid = pcmap.new_machineid
LEFT JOIN models md ON m.modelnumberid = md.modelnumberid
LEFT JOIN vendors v ON md.vendorid = v.vendorid
LEFT JOIN pctype pt ON m.pctypeid = pt.pctypeid
WHERE m.lastupdated > (NOW() - INTERVAL 30 DAY)
AND m.pctypeid IS NOT NULL
GROUP BY v.vendor, md.modelnumber
ORDER BY COUNT(m.machineid) DESC, v.vendor, md.modelnumber;
SELECT ' ✓ vw_pcs_by_hardware updated' AS status;
-- View 7: vw_pc_network_summary
-- Purpose: Show PC network interface summary
SELECT 'Updating vw_pc_network_summary...' AS '';
DROP VIEW IF EXISTS vw_pc_network_summary;
CREATE VIEW vw_pc_network_summary AS
SELECT
pcmap.pcid AS pcid,
m.hostname AS hostname,
m.machinenumber AS machinenumber,
COUNT(c.comid) AS interface_count,
GROUP_CONCAT(c.address ORDER BY c.comid SEPARATOR ', ') AS ip_addresses,
GROUP_CONCAT(c.macaddress ORDER BY c.comid SEPARATOR ', ') AS mac_addresses
FROM machines m
JOIN pc_to_machine_id_mapping pcmap ON m.machineid = pcmap.new_machineid
LEFT JOIN communications c ON m.machineid = c.machineid
AND c.comstypeid = (SELECT comstypeid FROM comstypes WHERE typename = 'Network_Interface' LIMIT 1)
AND c.isactive = 1
WHERE m.pctypeid IS NOT NULL
GROUP BY pcmap.pcid, m.hostname, m.machinenumber
ORDER BY m.hostname;
SELECT ' ✓ vw_pc_network_summary updated' AS status;
-- View 8: vw_dnc_config
-- Purpose: Show DNC configuration for PCs
SELECT 'Updating vw_dnc_config...' AS '';
DROP VIEW IF EXISTS vw_dnc_config;
CREATE VIEW vw_dnc_config AS
SELECT
pcmap.pcid AS pcid,
m.hostname AS hostname,
m.machinenumber AS machinenumber,
c.address AS ip_address,
c.port AS socket,
c.settings AS config_settings,
ct.typename AS comm_type
FROM machines m
JOIN pc_to_machine_id_mapping pcmap ON m.machineid = pcmap.new_machineid
LEFT JOIN communications c ON m.machineid = c.machineid AND c.isactive = 1
LEFT JOIN comstypes ct ON c.comstypeid = ct.comstypeid
WHERE m.pctypeid IS NOT NULL
AND ct.typename IN ('IP', 'Serial')
ORDER BY m.hostname, ct.typename;
SELECT ' ✓ vw_dnc_config updated' AS status;
-- View 9: vw_shopfloor_comm_config
-- Purpose: Communication config for shopfloor PCs
SELECT 'Updating vw_shopfloor_comm_config...' AS '';
DROP VIEW IF EXISTS vw_shopfloor_comm_config;
CREATE VIEW vw_shopfloor_comm_config AS
SELECT
pcmap.pcid AS pcid,
m.hostname AS hostname,
m.machinenumber AS machinenumber,
pt.typename AS pctype,
c.address AS ip_address,
c.port AS port_or_socket,
c.baud AS baud,
c.databits AS databits,
c.stopbits AS stopbits,
c.parity AS parity,
ct.typename AS comm_type
FROM machines m
JOIN pc_to_machine_id_mapping pcmap ON m.machineid = pcmap.new_machineid
JOIN pctype pt ON m.pctypeid = pt.pctypeid
LEFT JOIN communications c ON m.machineid = c.machineid AND c.isactive = 1
LEFT JOIN comstypes ct ON c.comstypeid = ct.comstypeid
WHERE pt.typename = 'Shopfloor'
AND m.pctypeid IS NOT NULL
AND ct.typename IN ('IP', 'Serial')
ORDER BY m.machinenumber, m.hostname;
SELECT ' ✓ vw_shopfloor_comm_config updated' AS status;
-- View 10: vw_machine_type_stats
-- Purpose: Statistics by machine type (includes PCs)
SELECT 'Updating vw_machine_type_stats...' AS '';
DROP VIEW IF EXISTS vw_machine_type_stats;
CREATE VIEW vw_machine_type_stats AS
SELECT
mt.machinetypeid,
mt.machinetype AS machine_type,
COUNT(m.machineid) AS total_count,
SUM(CASE WHEN m.pctypeid IS NOT NULL THEN 1 ELSE 0 END) AS pc_count,
SUM(CASE WHEN m.pctypeid IS NULL THEN 1 ELSE 0 END) AS equipment_count,
SUM(CASE WHEN m.lastupdated > (NOW() - INTERVAL 30 DAY) THEN 1 ELSE 0 END) AS active_count
FROM machinetypes mt
LEFT JOIN machines m ON mt.machinetypeid = m.machinetypeid AND m.isactive = 1
WHERE mt.isactive = 1
GROUP BY mt.machinetypeid, mt.machinetype
ORDER BY COUNT(m.machineid) DESC;
SELECT ' ✓ vw_machine_type_stats updated' AS status;
-- View 11: vw_vendor_summary
-- Purpose: Vendor summary including PCs
SELECT 'Updating vw_vendor_summary...' AS '';
DROP VIEW IF EXISTS vw_vendor_summary;
CREATE VIEW vw_vendor_summary AS
SELECT
v.vendorid,
v.vendor AS vendor_name,
COUNT(DISTINCT md.modelnumberid) AS model_count,
COUNT(m.machineid) AS machine_count,
SUM(CASE WHEN m.pctypeid IS NOT NULL THEN 1 ELSE 0 END) AS pc_count,
SUM(CASE WHEN m.pctypeid IS NULL THEN 1 ELSE 0 END) AS equipment_count,
v.ismachine,
v.isactive
FROM vendors v
LEFT JOIN models md ON v.vendorid = md.vendorid AND md.isactive = 1
LEFT JOIN machines m ON md.modelnumberid = m.modelnumberid AND m.isactive = 1
WHERE v.isactive = 1
GROUP BY v.vendorid, v.vendor, v.ismachine, v.isactive
ORDER BY COUNT(m.machineid) DESC, v.vendor;
SELECT ' ✓ vw_vendor_summary updated' AS status;
-- View 12: vw_dualpath_management
-- Purpose: Dualpath machine management view
SELECT 'Updating vw_dualpath_management...' AS '';
DROP VIEW IF EXISTS vw_dualpath_management;
CREATE VIEW vw_dualpath_management AS
SELECT
m1.machineid AS machine1_id,
m1.machinenumber AS machine1_number,
m1.hostname AS machine1_hostname,
mr.relationshipid,
rt.relationshiptype,
m2.machineid AS machine2_id,
m2.machinenumber AS machine2_number,
m2.hostname AS machine2_hostname,
mr.relationship_notes,
mr.isactive
FROM machinerelationships mr
JOIN machines m1 ON mr.machineid = m1.machineid
JOIN machines m2 ON mr.related_machineid = m2.machineid
JOIN relationshiptypes rt ON mr.relationshiptypeid = rt.relationshiptypeid
WHERE rt.relationshiptype = 'Dualpath'
AND mr.isactive = 1
ORDER BY m1.machinenumber, m2.machinenumber;
SELECT ' ✓ vw_dualpath_management updated' AS status;
-- View 13: vw_machine_assignments
-- Purpose: Show machine-to-PC assignments (controls/controlled by)
SELECT 'Updating vw_machine_assignments...' AS '';
DROP VIEW IF EXISTS vw_machine_assignments;
CREATE VIEW vw_machine_assignments AS
SELECT
m1.machineid AS machine_id,
m1.machinenumber AS machine_number,
m1.hostname AS machine_hostname,
rt.relationshiptype,
m2.machineid AS related_machine_id,
m2.machinenumber AS related_machine_number,
m2.hostname AS related_hostname,
CASE WHEN m2.pctypeid IS NOT NULL THEN 'PC' ELSE 'Equipment' END AS related_type,
mr.relationship_notes,
mr.isactive
FROM machinerelationships mr
JOIN machines m1 ON mr.machineid = m1.machineid
JOIN machines m2 ON mr.related_machineid = m2.machineid
JOIN relationshiptypes rt ON mr.relationshiptypeid = rt.relationshiptypeid
WHERE mr.isactive = 1
AND rt.relationshiptype IN ('Controlled By', 'Controls')
ORDER BY m1.machinenumber, rt.relationshiptype;
SELECT ' ✓ vw_machine_assignments updated' AS status;
-- View 14: vw_machine_assignment_status
-- Purpose: Machine assignment status summary
SELECT 'Updating vw_machine_assignment_status...' AS '';
DROP VIEW IF EXISTS vw_machine_assignment_status;
CREATE VIEW vw_machine_assignment_status AS
SELECT
m.machineid,
m.machinenumber,
m.hostname,
CASE WHEN m.pctypeid IS NOT NULL THEN 'PC' ELSE 'Equipment' END AS machine_type,
COUNT(mr.relationshipid) AS relationship_count,
GROUP_CONCAT(DISTINCT rt.relationshiptype ORDER BY rt.relationshiptype SEPARATOR ', ') AS relationships,
m.isactive
FROM machines m
LEFT JOIN machinerelationships mr ON m.machineid = mr.machineid AND mr.isactive = 1
LEFT JOIN relationshiptypes rt ON mr.relationshiptypeid = rt.relationshiptypeid
WHERE m.isactive = 1
GROUP BY m.machineid, m.machinenumber, m.hostname, m.pctypeid, m.isactive
ORDER BY COUNT(mr.relationshipid) DESC, m.machinenumber;
SELECT ' ✓ vw_machine_assignment_status updated' AS status;
-- View 15: vw_multi_pc_machines
-- Purpose: Show machines with multiple PCs assigned
SELECT 'Updating vw_multi_pc_machines...' AS '';
DROP VIEW IF EXISTS vw_multi_pc_machines;
CREATE VIEW vw_multi_pc_machines AS
SELECT
m.machineid,
m.machinenumber,
m.hostname AS machine_hostname,
COUNT(DISTINCT mr.related_machineid) AS pc_count,
GROUP_CONCAT(DISTINCT m2.hostname ORDER BY m2.hostname SEPARATOR ', ') AS pc_hostnames
FROM machines m
JOIN machinerelationships mr ON m.machineid = mr.machineid
JOIN relationshiptypes rt ON mr.relationshiptypeid = rt.relationshiptypeid
JOIN machines m2 ON mr.related_machineid = m2.machineid
WHERE m.pctypeid IS NULL
AND m2.pctypeid IS NOT NULL
AND rt.relationshiptype = 'Controls'
AND mr.isactive = 1
GROUP BY m.machineid, m.machinenumber, m.hostname
HAVING COUNT(DISTINCT mr.related_machineid) > 1
ORDER BY COUNT(DISTINCT mr.related_machineid) DESC, m.machinenumber;
SELECT ' ✓ vw_multi_pc_machines updated' AS status;
-- View 16: vw_pc_resolved_machines
-- Purpose: Resolve PC to their assigned machines
SELECT 'Updating vw_pc_resolved_machines...' AS '';
DROP VIEW IF EXISTS vw_pc_resolved_machines;
CREATE VIEW vw_pc_resolved_machines AS
SELECT
pcmap.pcid AS pcid,
m1.machineid AS pc_machineid,
m1.hostname AS pc_hostname,
m1.machinenumber AS pc_machinenumber,
m2.machineid AS assigned_machine_id,
m2.machinenumber AS assigned_machine_number,
m2.hostname AS assigned_machine_hostname,
rt.relationshiptype
FROM machines m1
JOIN pc_to_machine_id_mapping pcmap ON m1.machineid = pcmap.new_machineid
LEFT JOIN machinerelationships mr ON m1.machineid = mr.machineid AND mr.isactive = 1
LEFT JOIN relationshiptypes rt ON mr.relationshiptypeid = rt.relationshiptypeid AND rt.relationshiptype = 'Controlled By'
LEFT JOIN machines m2 ON mr.related_machineid = m2.machineid
WHERE m1.pctypeid IS NOT NULL
ORDER BY m1.hostname;
SELECT ' ✓ vw_pc_resolved_machines updated' AS status;
-- View 17: vw_ge_machines
-- Purpose: Show GE network machines (specific to organization)
SELECT 'Updating vw_ge_machines...' AS '';
DROP VIEW IF EXISTS vw_ge_machines;
CREATE VIEW vw_ge_machines AS
SELECT
m.machineid,
m.machinenumber,
m.hostname,
CASE WHEN m.pctypeid IS NOT NULL THEN 'PC' ELSE 'Equipment' END AS machine_type,
c.address AS ipaddress,
c.macaddress,
v.vendor AS manufacturer,
md.modelnumber AS model,
m.lastupdated
FROM machines m
LEFT JOIN communications c ON m.machineid = c.machineid
AND c.comstypeid = (SELECT comstypeid FROM comstypes WHERE typename = 'Network_Interface' LIMIT 1)
AND c.isactive = 1
LEFT JOIN models md ON m.modelnumberid = md.modelnumberid
LEFT JOIN vendors v ON md.vendorid = v.vendorid
WHERE m.isactive = 1
AND (c.address LIKE '10.%' OR c.address LIKE '192.168.%')
ORDER BY c.address, m.machinenumber;
SELECT ' ✓ vw_ge_machines updated' AS status;
-- View 18: vw_recent_updates
-- Purpose: Show recently updated machines (PCs and equipment)
SELECT 'Updating vw_recent_updates...' AS '';
DROP VIEW IF EXISTS vw_recent_updates;
CREATE VIEW vw_recent_updates AS
SELECT
m.machineid,
m.machinenumber,
m.hostname,
CASE
WHEN m.pctypeid IS NOT NULL THEN CONCAT('PC - ', pt.typename)
ELSE mt.machinetype
END AS machine_type,
v.vendor AS manufacturer,
md.modelnumber AS model,
m.lastupdated,
(TO_DAYS(NOW()) - TO_DAYS(m.lastupdated)) AS days_since_update
FROM machines m
LEFT JOIN models md ON m.modelnumberid = md.modelnumberid
LEFT JOIN vendors v ON md.vendorid = v.vendorid
LEFT JOIN machinetypes mt ON m.machinetypeid = mt.machinetypeid
LEFT JOIN pctype pt ON m.pctypeid = pt.pctypeid
WHERE m.isactive = 1
AND m.lastupdated > (NOW() - INTERVAL 7 DAY)
ORDER BY m.lastupdated DESC
LIMIT 100;
SELECT ' ✓ vw_recent_updates updated' AS status;
-- View 19: vw_shopfloor_applications_summary
-- Purpose: Summary of shopfloor applications (may use PC data)
SELECT 'Updating vw_shopfloor_applications_summary...' AS '';
DROP VIEW IF EXISTS vw_shopfloor_applications_summary;
CREATE VIEW vw_shopfloor_applications_summary AS
SELECT
m.machineid,
m.machinenumber,
m.hostname,
COUNT(DISTINCT mr.related_machineid) AS connected_pc_count,
GROUP_CONCAT(DISTINCT m2.hostname ORDER BY m2.hostname SEPARATOR ', ') AS connected_pcs,
COUNT(DISTINCT c.comid) AS comm_config_count
FROM machines m
LEFT JOIN machinerelationships mr ON m.machineid = mr.machineid
AND mr.isactive = 1
AND mr.relationshiptypeid = (SELECT relationshiptypeid FROM relationshiptypes WHERE relationshiptype = 'Controls' LIMIT 1)
LEFT JOIN machines m2 ON mr.related_machineid = m2.machineid AND m2.pctypeid IS NOT NULL
LEFT JOIN communications c ON m.machineid = c.machineid AND c.isactive = 1
WHERE m.isactive = 1
AND m.pctypeid IS NULL
AND m.machinetypeid = (SELECT machinetypeid FROM machinetypes WHERE machinetype LIKE '%Shopfloor%' LIMIT 1)
GROUP BY m.machineid, m.machinenumber, m.hostname
ORDER BY m.machinenumber;
SELECT ' ✓ vw_shopfloor_applications_summary updated' AS status;
SELECT '' AS '';
-- =====================================================
-- VERIFICATION
-- =====================================================
SELECT '========================================' AS '';
SELECT 'VIEW UPDATE VERIFICATION' AS '';
SELECT '========================================' AS '';
SELECT '' AS '';
-- Count updated views
SELECT 'Updated views:' AS '';
SELECT COUNT(*) as view_count
FROM INFORMATION_SCHEMA.VIEWS
WHERE TABLE_SCHEMA = 'shopdb'
AND TABLE_NAME IN (
'vw_active_pcs', 'vw_dnc_config', 'vw_dualpath_management',
'vw_engineer_pcs', 'vw_ge_machines', 'vw_machine_assignments',
'vw_machine_assignment_status', 'vw_machine_type_stats',
'vw_multi_pc_machines', 'vw_pcs_by_hardware', 'vw_pc_network_summary',
'vw_pc_resolved_machines', 'vw_pc_summary', 'vw_recent_updates',
'vw_shopfloor_applications_summary', 'vw_shopfloor_comm_config',
'vw_shopfloor_pcs', 'vw_standard_pcs', 'vw_vendor_summary'
);
SELECT '' AS '';
-- Test each view by selecting 1 row
SELECT 'Testing views (selecting 1 row from each):' AS '';
SELECT 'vw_active_pcs' AS view_name, COUNT(*) AS row_count FROM vw_active_pcs;
SELECT 'vw_pc_summary' AS view_name, COUNT(*) AS row_count FROM vw_pc_summary;
SELECT 'vw_shopfloor_pcs' AS view_name, COUNT(*) AS row_count FROM vw_shopfloor_pcs;
SELECT 'vw_engineer_pcs' AS view_name, COUNT(*) AS row_count FROM vw_engineer_pcs;
SELECT 'vw_standard_pcs' AS view_name, COUNT(*) AS row_count FROM vw_standard_pcs;
SELECT 'vw_pcs_by_hardware' AS view_name, COUNT(*) AS row_count FROM vw_pcs_by_hardware;
SELECT 'vw_pc_network_summary' AS view_name, COUNT(*) AS row_count FROM vw_pc_network_summary;
SELECT 'vw_dnc_config' AS view_name, COUNT(*) AS row_count FROM vw_dnc_config;
SELECT 'vw_shopfloor_comm_config' AS view_name, COUNT(*) AS row_count FROM vw_shopfloor_comm_config;
SELECT 'vw_machine_type_stats' AS view_name, COUNT(*) AS row_count FROM vw_machine_type_stats;
SELECT 'vw_vendor_summary' AS view_name, COUNT(*) AS row_count FROM vw_vendor_summary;
SELECT 'vw_dualpath_management' AS view_name, COUNT(*) AS row_count FROM vw_dualpath_management;
SELECT 'vw_machine_assignments' AS view_name, COUNT(*) AS row_count FROM vw_machine_assignments;
SELECT 'vw_machine_assignment_status' AS view_name, COUNT(*) AS row_count FROM vw_machine_assignment_status;
SELECT 'vw_multi_pc_machines' AS view_name, COUNT(*) AS row_count FROM vw_multi_pc_machines;
SELECT 'vw_pc_resolved_machines' AS view_name, COUNT(*) AS row_count FROM vw_pc_resolved_machines;
SELECT 'vw_ge_machines' AS view_name, COUNT(*) AS row_count FROM vw_ge_machines;
SELECT 'vw_recent_updates' AS view_name, COUNT(*) AS row_count FROM vw_recent_updates;
SELECT 'vw_shopfloor_applications_summary' AS view_name, COUNT(*) AS row_count FROM vw_shopfloor_applications_summary;
SELECT '' AS '';
SELECT '✓ Script 06 completed successfully' AS status;
SELECT 'All 19 views updated to use machines table' AS '';
SELECT 'Views maintain backward compatibility with pcid references' AS '';
SET SQL_SAFE_UPDATES = 1;
-- =====================================================
-- NOTES
-- =====================================================
-- All views updated to query machines table instead of pc table
--
-- Key changes:
-- 1. JOIN to pc_to_machine_id_mapping to maintain pcid references
-- 2. Query machines table with filter: pctypeid IS NOT NULL for PCs
-- 3. Warranty data now from warranties table (LEFT JOIN)
-- 4. All output column names preserved for backward compatibility
--
-- Views maintain same output structure for ASP application compatibility
--
-- ROLLBACK: Re-run old view definitions from backup
-- =====================================================

View File

@@ -0,0 +1,169 @@
-- =====================================================
-- SCRIPT 07: Cleanup Phase 2 Migration Tables
-- =====================================================
-- Date: 2025-11-13
-- Purpose: Drop unused backup and migration tables after Phase 2 completion
-- Status: READY FOR TESTING
-- Estimated Time: < 1 minute
-- Dependencies:
-- - Phase 2 migration must be complete
-- - All ASP files must be updated to use new schema
-- - Verification that old tables are no longer in use
-- =====================================================
USE shopdb;
SET SQL_SAFE_UPDATES = 0;
-- =====================================================
-- STEP 1: Pre-cleanup verification
-- =====================================================
SELECT '========================================' AS '';
SELECT 'PHASE 2 MIGRATION CLEANUP' AS '';
SELECT '========================================' AS '';
SELECT '' AS '';
SELECT 'Tables to be dropped:' AS '';
SELECT '' AS '';
-- Show backup tables
SELECT 'Backup Tables:' AS '';
SELECT TABLE_NAME, TABLE_ROWS, ROUND(((DATA_LENGTH + INDEX_LENGTH) / 1024 / 1024), 2) AS 'Size_MB'
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = 'shopdb'
AND (TABLE_NAME LIKE '%backup%phase2%' OR TABLE_NAME = 'pc_model_backup')
ORDER BY TABLE_NAME;
SELECT '' AS '';
-- Show mapping tables
SELECT 'Mapping Tables:' AS '';
SELECT TABLE_NAME, TABLE_ROWS, ROUND(((DATA_LENGTH + INDEX_LENGTH) / 1024 / 1024), 2) AS 'Size_MB'
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = 'shopdb'
AND TABLE_NAME IN ('pc_to_machine_id_mapping', 'machine_pc_relationships')
ORDER BY TABLE_NAME;
SELECT '' AS '';
-- =====================================================
-- STEP 2: Confirm Phase 2 migration completion
-- =====================================================
SELECT 'Verifying Phase 2 migration status...' AS '';
SELECT '' AS '';
-- Check machines table has PCs
SELECT CONCAT('✓ PCs in machines table: ', COUNT(*)) AS status
FROM machines
WHERE pctypeid IS NOT NULL;
-- Check communications table has data
SELECT CONCAT('✓ Network interfaces in communications: ', COUNT(*)) AS status
FROM communications;
-- Check machinerelationships has data
SELECT CONCAT('✓ Relationships in machinerelationships: ', COUNT(*)) AS status
FROM machinerelationships;
SELECT '' AS '';
-- =====================================================
-- STEP 3: Drop backup tables
-- =====================================================
SELECT 'Dropping backup tables...' AS '';
-- Backup tables created during Phase 2 migration
DROP TABLE IF EXISTS pc_backup_phase2;
SELECT '✓ Dropped pc_backup_phase2' AS status;
DROP TABLE IF EXISTS pc_network_interfaces_backup_phase2;
SELECT '✓ Dropped pc_network_interfaces_backup_phase2' AS status;
DROP TABLE IF EXISTS pc_comm_config_backup_phase2;
SELECT '✓ Dropped pc_comm_config_backup_phase2' AS status;
DROP TABLE IF EXISTS pc_dualpath_assignments_backup_phase2;
SELECT '✓ Dropped pc_dualpath_assignments_backup_phase2' AS status;
DROP TABLE IF EXISTS pc_model_backup;
SELECT '✓ Dropped pc_model_backup' AS status;
SELECT '' AS '';
-- =====================================================
-- STEP 4: Drop mapping tables
-- =====================================================
SELECT 'Dropping mapping/helper tables...' AS '';
-- Mapping table used during migration (no longer needed)
DROP TABLE IF EXISTS pc_to_machine_id_mapping;
SELECT '✓ Dropped pc_to_machine_id_mapping' AS status;
-- Unused relationship table (replaced by machinerelationships)
DROP TABLE IF EXISTS machine_pc_relationships;
SELECT '✓ Dropped machine_pc_relationships' AS status;
SELECT '' AS '';
-- =====================================================
-- STEP 5: Verification
-- =====================================================
SELECT 'Verifying cleanup...' AS '';
SELECT '' AS '';
-- Check that essential tables still exist
SELECT CONCAT('✓ machines table exists: ', COUNT(*), ' records') AS status
FROM machines;
SELECT CONCAT('✓ communications table exists: ', COUNT(*), ' records') AS status
FROM communications;
SELECT CONCAT('✓ machinerelationships table exists: ', COUNT(*), ' records') AS status
FROM machinerelationships;
SELECT '' AS '';
-- Show remaining tables
SELECT 'Remaining migration-related tables:' AS '';
SELECT TABLE_NAME
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = 'shopdb'
AND (TABLE_NAME LIKE 'pc%' OR TABLE_NAME LIKE '%backup%' OR TABLE_NAME LIKE '%mapping%')
ORDER BY TABLE_NAME;
SELECT '' AS '';
SELECT '========================================' AS '';
SELECT 'CLEANUP COMPLETE' AS '';
SELECT '========================================' AS '';
SET SQL_SAFE_UPDATES = 1;
-- =====================================================
-- NOTES
-- =====================================================
--
-- Tables dropped in this script:
-- 1. pc_backup_phase2 (276 rows) - Backup of old pc table
-- 2. pc_network_interfaces_backup_phase2 (705 rows) - Backup of network interfaces
-- 3. pc_comm_config_backup_phase2 (502 rows) - Backup of comm config
-- 4. pc_dualpath_assignments_backup_phase2 (33 rows) - Backup of dualpath assignments
-- 5. pc_model_backup (206 rows) - Backup of pc models
-- 6. pc_to_machine_id_mapping (221 rows) - Migration mapping table
-- 7. machine_pc_relationships (0 rows) - Unused relationship table
--
-- Old tables NOT dropped (still may be in use):
-- - pc (old PC table - may still be referenced for historical data)
-- - pc_network_interfaces (old network interfaces)
-- - pc_comm_config (old communication config)
-- - pc_dualpath_assignments (old dualpath assignments)
-- - pc_dnc_config (DNC configuration)
--
-- ROLLBACK: If you need to restore, you must restore from database backup
-- taken BEFORE running this script. These tables cannot be recovered
-- after deletion.
--
-- =====================================================

View File

@@ -0,0 +1,117 @@
-- ============================================================================
-- PHASE 2 MIGRATION - SCRIPT 08: Update Schema for API Compatibility
-- ============================================================================
-- Purpose: Rename pcid columns to machineid in tables still using old naming
-- Required for: api.asp to work correctly with Phase 2 schema
-- Run after: 01-07 migration scripts
-- ============================================================================
USE shopdb;
-- ============================================================================
-- STEP 1: Rename pcid to machineid in pc_comm_config
-- ============================================================================
-- Check if column exists first
SET @column_exists = (
SELECT COUNT(*)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = 'shopdb'
AND TABLE_NAME = 'pc_comm_config'
AND COLUMN_NAME = 'pcid'
);
-- Only rename if pcid column exists
SET @sql = IF(@column_exists > 0,
'ALTER TABLE pc_comm_config CHANGE COLUMN pcid machineid INT(11)',
'SELECT "pc_comm_config already has machineid column" AS status'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- Add index for performance (MySQL 5.6 compatible)
SET @index_exists = (
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;
-- ============================================================================
-- STEP 2: Rename pcid to machineid in pc_dnc_config
-- ============================================================================
-- Check if column exists first
SET @column_exists = (
SELECT COUNT(*)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = 'shopdb'
AND TABLE_NAME = 'pc_dnc_config'
AND COLUMN_NAME = 'pcid'
);
-- Only rename if pcid column exists
SET @sql = IF(@column_exists > 0,
'ALTER TABLE pc_dnc_config CHANGE COLUMN pcid machineid INT(11)',
'SELECT "pc_dnc_config already has machineid column" AS status'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- Add index for performance (MySQL 5.6 compatible)
SET @index_exists = (
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;
-- ============================================================================
-- STEP 3: Verification
-- ============================================================================
-- Show table structures
SELECT 'pc_comm_config structure:' AS info;
DESCRIBE pc_comm_config;
SELECT 'pc_dnc_config structure:' AS info;
DESCRIBE pc_dnc_config;
-- Count records
SELECT
(SELECT COUNT(*) FROM pc_comm_config) AS comm_config_records,
(SELECT COUNT(*) FROM pc_dnc_config) AS dnc_config_records;
-- ============================================================================
-- COMPLETE
-- ============================================================================
SELECT '✅ Schema update complete - api.asp ready' AS status;

View File

@@ -0,0 +1,118 @@
-- ============================================================================
-- PHASE 2 MIGRATION - SCRIPT 08: Update Schema for API Compatibility
-- ============================================================================
-- Purpose: Rename pcid columns to machineid in tables still using old naming
-- Required for: api.asp to work correctly with Phase 2 schema
-- Run after: 01-07 migration scripts
-- Fixed for MySQL 5.6 compatibility
-- ============================================================================
USE shopdb;
-- ============================================================================
-- STEP 1: Rename pcid to machineid in pc_comm_config
-- ============================================================================
-- Check if column exists first
SET @column_exists = (
SELECT COUNT(*)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = 'shopdb'
AND TABLE_NAME = 'pc_comm_config'
AND COLUMN_NAME = 'pcid'
);
-- Only rename if pcid column exists
SET @sql = IF(@column_exists > 0,
'ALTER TABLE pc_comm_config CHANGE COLUMN pcid machineid INT(11)',
'SELECT "pc_comm_config already has machineid column" AS status'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- Add index for performance (check if exists first)
SET @index_exists = (
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;
-- ============================================================================
-- STEP 2: Rename pcid to machineid in pc_dnc_config
-- ============================================================================
-- Check if column exists first
SET @column_exists = (
SELECT COUNT(*)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = 'shopdb'
AND TABLE_NAME = 'pc_dnc_config'
AND COLUMN_NAME = 'pcid'
);
-- Only rename if pcid column exists
SET @sql = IF(@column_exists > 0,
'ALTER TABLE pc_dnc_config CHANGE COLUMN pcid machineid INT(11)',
'SELECT "pc_dnc_config already has machineid column" AS status'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- Add index for performance (check if exists first)
SET @index_exists = (
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;
-- ============================================================================
-- STEP 3: Verification
-- ============================================================================
-- Show table structures
SELECT 'pc_comm_config structure:' AS info;
DESCRIBE pc_comm_config;
SELECT 'pc_dnc_config structure:' AS info;
DESCRIBE pc_dnc_config;
-- Count records
SELECT
(SELECT COUNT(*) FROM pc_comm_config) AS comm_config_records,
(SELECT COUNT(*) FROM pc_dnc_config) AS dnc_config_records;
-- ============================================================================
-- COMPLETE
-- ============================================================================
SELECT '✅ Schema update complete - api.asp ready' AS status;

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

@@ -0,0 +1,499 @@
# Phase 2: PC Data Migration
## Overview
**Phase 2** migrates all PC data from the legacy `pc` table and related tables into the new unified schema created in Phase 1. This phase handles the actual data migration of **277 active PCs** and their associated records.
**Status**: Ready for testing on DEV environment
**Estimated Time**: 10-15 minutes
**Dependencies**: Phase 1 must be completed first
## What This Phase Does
Phase 2 migrates data from these legacy tables:
- `pc` (277 records) → `machines` table
- `pc_network_interfaces` (705 records) → `communications` table
- `pc_comm_config``communications` table
- `pc` warranty fields → `warranties` table
- `pc_dualpath_assignments``machinerelationships` table
## Migration Scripts
### Script Execution Order
Run scripts in this exact order:
| Script | Purpose | Records | Time |
|--------|---------|---------|------|
| **01_migrate_pcs_to_machines.sql** | Migrate PC records to machines table | ~277 PCs | 5-10 min |
| **02_migrate_network_interfaces_to_communications.sql** | Migrate network interfaces | ~705 interfaces | 3-5 min |
| **03_migrate_comm_config_to_communications.sql** | Migrate serial/IP comm configs | Variable | 2-3 min |
| **04_migrate_warranties.sql** | Migrate PC warranty data | Variable | 1-2 min |
| **05_migrate_dualpath_assignments.sql** | Migrate dualpath machine relationships | Variable | 1-2 min |
| **VERIFY_PHASE2_MIGRATION.sql** | Comprehensive verification | N/A | 1-2 min |
### Script Details
#### 01_migrate_pcs_to_machines.sql
**Critical Script - All other scripts depend on this**
Migrates all active PC records from `pc` table to `machines` table:
- Creates `pc_to_machine_id_mapping` table for tracking old→new IDs
- Maps PC types to new machine types:
- Standard → PC - Standard
- Shopfloor → PC - Shopfloor
- Engineer → PC - Engineer
- Server/VM → PC - Server
- Laptop → PC - Laptop
- Sets `machinenumber` = `hostname` for PCs
- Creates backup: `pc_backup_phase2`
**Key Fields Migrated**:
- hostname, loggedinuser, serialnumber
- modelnumberid, osid, machinestatusid, pctypeid
- requires_manual_machine_config
- businessunitid, printerid (if exists)
- mapleft, maptop (if exists)
#### 02_migrate_network_interfaces_to_communications.sql
Migrates PC network interfaces to the unified `communications` table:
- Uses `comstypeid` for 'Network_Interface'
- Maps `ipaddress``address` field
- Preserves: macaddress, subnetmask, defaultgateway
- Preserves: interfacename, isdhcp, ismachinenetwork
- Creates backup: `pc_network_interfaces_backup_phase2`
#### 03_migrate_comm_config_to_communications.sql
Migrates serial and IP communication configs:
- Maps Serial configs: `portid``address`, preserves baud/databits/stopbits/parity
- Maps IP configs: `ipaddress``address`, `socketnumber``port`
- Combines `crlf` + `additionalsettings` into `settings` field
- Creates backup: `pc_comm_config_backup_phase2`
#### 04_migrate_warranties.sql
Migrates warranty data from PC table to normalized `warranties` table:
- Only migrates PCs with `warrantyenddate` NOT NULL
- Maps fields:
- `warrantyenddate``enddate`
- `warrantyservicelevel``servicelevel`
- `warrantylastchecked``lastcheckeddate`
- `warrantyname` set to NULL (not in old schema)
#### 05_migrate_dualpath_assignments.sql
Migrates dualpath machine relationships:
- Creates **bidirectional** relationships:
- primary_machine → secondary_machine
- secondary_machine → primary_machine
- Uses `relationshiptype` = 'Dualpath'
- Joins on `machinenumber` (hostname) to find machine IDs
- Creates backup: `pc_dualpath_assignments_backup_phase2`
#### VERIFY_PHASE2_MIGRATION.sql
Comprehensive verification script with 9 sections:
1. PC to machines migration verification
2. Network interfaces migration verification
3. Comm config migration verification
4. Warranties migration verification
5. Dualpath assignments verification
6. Overall communications summary
7. Relationship summary
8. Backup table verification
9. Final summary and critical issues check
All checks should show status with 0 critical issues.
## How to Run
### Option A: Run Individual Scripts (Recommended for Testing)
```bash
# Connect to MySQL
mysql -u root -p shopdb
# Run scripts in order
source 01_migrate_pcs_to_machines.sql
source 02_migrate_network_interfaces_to_communications.sql
source 03_migrate_comm_config_to_communications.sql
source 04_migrate_warranties.sql
source 05_migrate_dualpath_assignments.sql
# Verify migration
source VERIFY_PHASE2_MIGRATION.sql
```
### Option B: Run All Scripts at Once
```bash
# Run all scripts and capture output
mysql -u root -p shopdb < 01_migrate_pcs_to_machines.sql > /tmp/phase2_01.log 2>&1
mysql -u root -p shopdb < 02_migrate_network_interfaces_to_communications.sql > /tmp/phase2_02.log 2>&1
mysql -u root -p shopdb < 03_migrate_comm_config_to_communications.sql > /tmp/phase2_03.log 2>&1
mysql -u root -p shopdb < 04_migrate_warranties.sql > /tmp/phase2_04.log 2>&1
mysql -u root -p shopdb < 05_migrate_dualpath_assignments.sql > /tmp/phase2_05.log 2>&1
mysql -u root -p shopdb < VERIFY_PHASE2_MIGRATION.sql > /tmp/phase2_verify.log 2>&1
# Review logs
cat /tmp/phase2_*.log
```
## Prerequisites
### Phase 1 Must Be Complete
Before running Phase 2, verify Phase 1 is complete:
```sql
-- Should return 8 tables
SELECT COUNT(*) FROM information_schema.tables
WHERE table_schema = 'shopdb'
AND table_name IN (
'comstypes', 'communications', 'warranties', 'compliance',
'relationshiptypes', 'machinerelationships', 'machinestatus'
);
-- Should return rows
SELECT COUNT(*) FROM comstypes;
SELECT COUNT(*) FROM relationshiptypes;
-- machines table should have new columns
DESCRIBE machines; -- Check for hostname, osid, pctypeid, etc.
```
### Database Backup
**CRITICAL**: Create a full database backup before running Phase 2:
```bash
# Create backup
mysqldump -u root -p shopdb > /tmp/shopdb-before-phase2-$(date +%Y%m%d-%H%M%S).sql
# Verify backup
ls -lh /tmp/shopdb-before-phase2-*.sql
```
## What Gets Created
### New Records
- **277 new machine records** (PCs migrated to machines table)
- **~705 communication records** (network interfaces)
- **Variable communication records** (serial/IP configs)
- **Variable warranty records** (PCs with warranty dates)
- **Variable relationship records** (dualpath assignments × 2)
### Mapping Tables
- **pc_to_machine_id_mapping**: Maps old `pcid` to new `machineid`
- Used by scripts 02-05
- Used by Phase 3 view updates
- Used by Phase 4 application updates
- **DO NOT DELETE** until migration fully complete
### Backup Tables
Phase 2 creates these backup tables:
- `pc_backup_phase2` (277 records)
- `pc_network_interfaces_backup_phase2` (~705 records)
- `pc_comm_config_backup_phase2`
- `pc_dualpath_assignments_backup_phase2`
## Verification Checklist
After running all scripts, verify:
### 1. Record Counts Match
```sql
-- PCs migrated
SELECT COUNT(*) FROM pc WHERE isactive = 1; -- Original count
SELECT COUNT(*) FROM machines WHERE pctypeid IS NOT NULL; -- Should match
-- Network interfaces migrated
SELECT COUNT(*) FROM pc_network_interfaces WHERE isactive = 1; -- Original
SELECT COUNT(*) FROM communications c
JOIN comstypes ct ON c.comstypeid = ct.comstypeid
WHERE ct.typename = 'Network_Interface'; -- Should match
-- Mapping table populated
SELECT COUNT(*) FROM pc_to_machine_id_mapping; -- Should equal PC count
```
### 2. No NULL Values in Critical Fields
```sql
-- Check for data quality issues
SELECT COUNT(*) FROM machines
WHERE pctypeid IS NOT NULL
AND (hostname IS NULL OR machinetypeid IS NULL); -- Should be 0
SELECT COUNT(*) FROM communications
WHERE machineid IS NULL OR comstypeid IS NULL; -- Should be 0
```
### 3. Dualpath Relationships Bidirectional
```sql
-- Check for one-way relationships (should be 0)
SELECT COUNT(*) FROM machinerelationships mr1
JOIN relationshiptypes rt ON mr1.relationshiptypeid = rt.relationshiptypeid
WHERE rt.relationshiptype = 'Dualpath'
AND NOT EXISTS (
SELECT 1 FROM machinerelationships mr2
WHERE mr2.machineid = mr1.related_machineid
AND mr2.related_machineid = mr1.machineid
AND mr2.relationshiptypeid = mr1.relationshiptypeid
);
```
### 4. All Backup Tables Created
```sql
-- Should return 4 rows
SELECT table_name, table_rows
FROM information_schema.tables
WHERE table_schema = 'shopdb'
AND table_name LIKE '%_backup_phase2';
```
### 5. Run Full Verification
```bash
mysql -u root -p shopdb < VERIFY_PHASE2_MIGRATION.sql
```
Review output for:
- All checks showing status
- Critical issues count = 0
- Record counts matching expected values
## Rollback Procedures
### Full Rollback
If Phase 2 needs to be completely rolled back:
```sql
-- 1. Delete migrated PC records from machines
DELETE FROM machines WHERE pctypeid IS NOT NULL;
-- 2. Delete communications from PCs
DELETE FROM communications
WHERE machineid IN (SELECT new_machineid FROM pc_to_machine_id_mapping);
-- 3. Delete warranties for PCs
DELETE FROM warranties
WHERE machineid IN (SELECT new_machineid FROM pc_to_machine_id_mapping);
-- 4. Delete dualpath relationships
DELETE FROM machinerelationships
WHERE relationshiptypeid = (
SELECT relationshiptypeid FROM relationshiptypes
WHERE relationshiptype = 'Dualpath'
);
-- 5. Drop mapping table
DROP TABLE IF EXISTS pc_to_machine_id_mapping;
-- 6. Verify original data intact
SELECT COUNT(*) FROM pc WHERE isactive = 1;
SELECT COUNT(*) FROM pc_network_interfaces WHERE isactive = 1;
SELECT COUNT(*) FROM pc_comm_config;
```
### Restore from Database Backup
If full rollback needed:
```bash
# Stop applications using database
# ...
# Restore from backup
mysql -u root -p shopdb < /tmp/shopdb-before-phase2-YYYYMMDD-HHMMSS.sql
# Verify restoration
mysql -u root -p shopdb -e "SELECT COUNT(*) FROM pc; SELECT COUNT(*) FROM machines;"
```
## Known Issues and Considerations
### 1. Hostname as Machine Number
PCs use `hostname` as `machinenumber` in the machines table. This differs from other equipment that uses numeric machine numbers (e.g., "M-1234").
**Rationale**: PCs are identified by hostname in the organization. Using hostname preserves this convention.
### 2. NULL Warranty Names
The old `pc` table didn't have a `warrantyname` field, so migrated PC warranties will have `warrantyname = NULL`. This is expected and correct.
### 3. Business Unit Assignment
Script 01 attempts to preserve existing `businessunitid` if the PC already exists in machines table. Otherwise defaults to businessunitid = 1.
**Post-migration**: Review and update business unit assignments as needed.
### 4. Communication Type Mapping
The old schema used string-based `configtype` ('Serial', 'IP'). The new schema uses foreign keys to `comstypes` table. Mapping is:
- `configtype = 'Serial'` → comstypeid for 'Serial'
- `configtype = 'IP'` → comstypeid for 'IP'
- Network interfaces → comstypeid for 'Network_Interface'
### 5. MySQL 5.6 Compatibility
All scripts are tested and compatible with MySQL 5.6. Phase 1 script 03 was updated to use `FROM DUAL` syntax for MySQL 5.6 compatibility.
## Testing Recommendations
### DEV Environment Testing
1. **Create backup** before testing
2. **Run Phase 2 scripts** individually
3. **Review each script output** for errors
4. **Run verification script**
5. **Test application** (check PC pages still work)
6. **Test rollback** procedure
7. **Restore from backup** to test restoration
8. **Document any issues** found
### Application Testing
After Phase 2, test these application areas:
- PC list pages
- PC detail pages
- Network interface displays
- Warranty reports
- Dualpath machine displays
- Any reports using PC data
**Note**: Application code still uses old `pc` table. Phase 3 and 4 will update views and application code.
## Timeline
### Phase 2 Execution Timeline
- **Script execution**: 10-15 minutes
- **Verification**: 5-10 minutes
- **Application testing**: 1-2 hours
- **Total**: ~2-3 hours
### Overall Migration Timeline
- **Phase 1**: Schema changes (COMPLETE)
- **Phase 2**: Data migration (CURRENT - Ready for testing)
- **Phase 3**: View updates (Pending)
- **Phase 4**: Application code updates (Pending)
**Estimated total**: 20-30 days from design to production deployment
## Support and Troubleshooting
### Common Issues
#### Issue: Script 01 fails with mapping error
**Symptom**: Error joining pc to machines on machinenumber
**Cause**: Duplicate hostnames in pc or machines tables
**Fix**: Investigate duplicates:
```sql
-- Find duplicate hostnames in pc
SELECT hostname, COUNT(*)
FROM pc WHERE isactive = 1
GROUP BY hostname HAVING COUNT(*) > 1;
-- Find duplicate hostnames in machines
SELECT hostname, COUNT(*)
FROM machines WHERE isactive = 1
GROUP BY hostname HAVING COUNT(*) > 1;
```
#### Issue: Communications migration shows wrong counts
**Symptom**: Verification shows fewer communications than expected
**Cause**: Missing `pc_to_machine_id_mapping` entries
**Fix**: Check mapping table:
```sql
-- Find unmapped PCs
SELECT p.pcid, p.hostname
FROM pc p
WHERE p.isactive = 1
AND NOT EXISTS (
SELECT 1 FROM pc_to_machine_id_mapping m WHERE m.pcid = p.pcid
);
```
#### Issue: Dualpath relationships not bidirectional
**Symptom**: Verification shows one-way relationships
**Cause**: Script 05 only ran first INSERT, not second
**Fix**: Manually run second INSERT block from script 05
### Getting Help
- Review VERIFY_PHASE2_MIGRATION.sql output
- Check backup tables for data comparison
- Review script comments and NOTES sections
- Consult PC_MACHINES_CONSOLIDATION_PLAN.md for design rationale
## Next Steps
After Phase 2 is complete and verified:
1. **Phase 3**: Update 19 views that reference `pc` table
- Views need to query `machines` table instead
- Some views may need UNION with both tables during transition
2. **Phase 4**: Update ASP application files (50+ files estimated)
- Update queries to use `machines` table
- Update stored procedures
- Update reports
3. **Production Deployment**
- Schedule maintenance window
- Execute on production database
- Monitor application performance
## File Manifest
```
migration_phase2/
├── README.md (this file)
├── 01_migrate_pcs_to_machines.sql (354 lines)
├── 02_migrate_network_interfaces_to_communications.sql (201 lines)
├── 03_migrate_comm_config_to_communications.sql (213 lines)
├── 04_migrate_warranties.sql (165 lines)
├── 05_migrate_dualpath_assignments.sql (178 lines)
└── VERIFY_PHASE2_MIGRATION.sql (562 lines)
Total: 7 files, 1,673 lines
```
## Change Log
| Date | Version | Changes |
|------|---------|---------|
| 2025-11-06 | 1.0 | Initial Phase 2 scripts created |
---
**Author**: Database Migration Team
**Date**: 2025-11-06
**Status**: Ready for DEV testing
**Next Review**: After DEV testing complete

View File

@@ -0,0 +1,410 @@
-- =====================================================
-- RUN ALL PHASE 2 MIGRATION SCRIPTS
-- =====================================================
-- Date: 2025-11-06
-- Purpose: Execute all Phase 2 data migration scripts in sequence
-- Status: Ready for DEV testing
-- Estimated Time: 10-15 minutes
-- =====================================================
--
-- PREREQUISITES:
-- 1. Phase 1 must be complete (schema changes)
-- 2. Database backup created
-- 3. Verify Phase 1 completion:
-- SELECT COUNT(*) FROM comstypes; -- Should have records
-- SELECT COUNT(*) FROM relationshiptypes; -- Should have records
-- DESCRIBE machines; -- Should show new columns
--
-- USAGE:
-- mysql -u root -p shopdb < RUN_ALL_PHASE2_SCRIPTS.sql | tee /tmp/phase2_migration.log
--
-- Or run interactively:
-- mysql -u root -p shopdb
-- source RUN_ALL_PHASE2_SCRIPTS.sql
--
-- =====================================================
USE shopdb;
SELECT '============================================================' AS '';
SELECT 'PHASE 2: PC DATA MIGRATION' AS '';
SELECT '============================================================' AS '';
SELECT 'Starting Phase 2 data migration...' AS '';
SELECT CONCAT('Start time: ', NOW()) AS '';
SELECT '' AS '';
-- Store start time
SET @phase2_start_time = NOW();
-- =====================================================
-- PRE-MIGRATION CHECKS
-- =====================================================
SELECT '============================================================' AS '';
SELECT 'PRE-MIGRATION CHECKS' AS '';
SELECT '============================================================' AS '';
SELECT '' AS '';
-- Check Phase 1 completion
SELECT 'Verifying Phase 1 completion...' AS '';
SET @phase1_tables_count = (
SELECT COUNT(*) FROM information_schema.tables
WHERE table_schema = 'shopdb'
AND table_name IN (
'comstypes', 'communications', 'warranties', 'compliance',
'relationshiptypes', 'machinerelationships', 'machinestatus'
)
);
SELECT CASE
WHEN @phase1_tables_count = 7 THEN '✓ Phase 1 tables found'
ELSE '⚠️ ERROR: Phase 1 incomplete - run Phase 1 scripts first!'
END AS status;
-- Check for required columns in machines table
SET @machines_columns = (
SELECT COUNT(*) FROM information_schema.columns
WHERE table_schema = 'shopdb'
AND table_name = 'machines'
AND column_name IN ('hostname', 'osid', 'pctypeid', 'machinestatusid')
);
SELECT CASE
WHEN @machines_columns = 4 THEN '✓ Machines table extended'
ELSE '⚠️ ERROR: Machines table not extended - run Phase 1 scripts first!'
END AS status;
-- Check comstypes populated
SET @comstypes_count = (SELECT COUNT(*) FROM comstypes);
SELECT CASE
WHEN @comstypes_count >= 3 THEN CONCAT('✓ Comstypes populated (', @comstypes_count, ' types)')
ELSE '⚠️ ERROR: Comstypes not populated - run Phase 1 scripts first!'
END AS status;
-- Check relationshiptypes populated
SET @relationshiptypes_count = (SELECT COUNT(*) FROM relationshiptypes);
SELECT CASE
WHEN @relationshiptypes_count >= 3 THEN CONCAT('✓ Relationship types populated (', @relationshiptypes_count, ' types)')
ELSE '⚠️ ERROR: Relationship types not populated - run Phase 1 scripts first!'
END AS status;
SELECT '' AS '';
-- Show current state
SELECT 'Current state:' AS '';
SELECT
'Active PCs to migrate' AS category,
COUNT(*) as count
FROM pc WHERE isactive = 1
UNION ALL
SELECT
'Current machines (before migration)',
COUNT(*)
FROM machines WHERE isactive = 1
UNION ALL
SELECT
'Network interfaces to migrate',
COUNT(*)
FROM pc_network_interfaces WHERE isactive = 1
UNION ALL
SELECT
'Comm configs to migrate',
COUNT(*)
FROM pc_comm_config
UNION ALL
SELECT
'PCs with warranty data',
COUNT(*)
FROM pc WHERE warrantyenddate IS NOT NULL AND isactive = 1
UNION ALL
SELECT
'Dualpath assignments to migrate',
COUNT(*)
FROM pc_dualpath_assignments;
SELECT '' AS '';
SELECT '============================================================' AS '';
SELECT '' AS '';
-- Pause to allow review
SELECT 'Pre-migration checks complete. Proceeding with migration...' AS '';
SELECT '' AS '';
-- =====================================================
-- SCRIPT 01: Migrate PCs to Machines
-- =====================================================
SELECT '============================================================' AS '';
SELECT 'SCRIPT 01: MIGRATE PCS TO MACHINES' AS '';
SELECT '============================================================' AS '';
SELECT CONCAT('Start time: ', NOW()) AS '';
SELECT '' AS '';
source 01_migrate_pcs_to_machines.sql
SELECT '' AS '';
SELECT 'Script 01 completed' AS '';
SELECT CONCAT('Time: ', NOW()) AS '';
SELECT '============================================================' AS '';
SELECT '' AS '';
-- =====================================================
-- SCRIPT 02: Migrate Network Interfaces
-- =====================================================
SELECT '============================================================' AS '';
SELECT 'SCRIPT 02: MIGRATE NETWORK INTERFACES' AS '';
SELECT '============================================================' AS '';
SELECT CONCAT('Start time: ', NOW()) AS '';
SELECT '' AS '';
source 02_migrate_network_interfaces_to_communications.sql
SELECT '' AS '';
SELECT 'Script 02 completed' AS '';
SELECT CONCAT('Time: ', NOW()) AS '';
SELECT '============================================================' AS '';
SELECT '' AS '';
-- =====================================================
-- SCRIPT 03: Migrate Comm Config
-- =====================================================
SELECT '============================================================' AS '';
SELECT 'SCRIPT 03: MIGRATE COMM CONFIG' AS '';
SELECT '============================================================' AS '';
SELECT CONCAT('Start time: ', NOW()) AS '';
SELECT '' AS '';
source 03_migrate_comm_config_to_communications.sql
SELECT '' AS '';
SELECT 'Script 03 completed' AS '';
SELECT CONCAT('Time: ', NOW()) AS '';
SELECT '============================================================' AS '';
SELECT '' AS '';
-- =====================================================
-- SCRIPT 04: Migrate Warranties
-- =====================================================
SELECT '============================================================' AS '';
SELECT 'SCRIPT 04: MIGRATE WARRANTIES' AS '';
SELECT '============================================================' AS '';
SELECT CONCAT('Start time: ', NOW()) AS '';
SELECT '' AS '';
source 04_migrate_warranties.sql
SELECT '' AS '';
SELECT 'Script 04 completed' AS '';
SELECT CONCAT('Time: ', NOW()) AS '';
SELECT '============================================================' AS '';
SELECT '' AS '';
-- =====================================================
-- SCRIPT 05: Migrate Dualpath Assignments
-- =====================================================
SELECT '============================================================' AS '';
SELECT 'SCRIPT 05: MIGRATE DUALPATH ASSIGNMENTS' AS '';
SELECT '============================================================' AS '';
SELECT CONCAT('Start time: ', NOW()) AS '';
SELECT '' AS '';
source 05_migrate_dualpath_assignments.sql
SELECT '' AS '';
SELECT 'Script 05 completed' AS '';
SELECT CONCAT('Time: ', NOW()) 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
-- =====================================================
SELECT '============================================================' AS '';
SELECT 'RUNNING VERIFICATION' AS '';
SELECT '============================================================' AS '';
SELECT CONCAT('Start time: ', NOW()) AS '';
SELECT '' AS '';
source VERIFY_PHASE2_MIGRATION.sql
SELECT '' AS '';
SELECT '============================================================' AS '';
SELECT '' AS '';
-- =====================================================
-- FINAL SUMMARY
-- =====================================================
SELECT '============================================================' AS '';
SELECT 'PHASE 2 MIGRATION COMPLETE' AS '';
SELECT '============================================================' AS '';
SELECT '' AS '';
-- Calculate elapsed time
SELECT CONCAT('Start time: ', @phase2_start_time) AS '';
SELECT CONCAT('End time: ', NOW()) AS '';
SELECT CONCAT('Elapsed time: ', TIMESTAMPDIFF(MINUTE, @phase2_start_time, NOW()), ' minutes') AS '';
SELECT '' AS '';
-- Final counts
SELECT 'Final migration statistics:' AS '';
SELECT
'PCs migrated to machines' AS category,
COUNT(*) as count
FROM machines WHERE pctypeid IS NOT NULL
UNION ALL
SELECT
'Network interfaces migrated',
COUNT(*)
FROM communications c
JOIN comstypes ct ON c.comstypeid = ct.comstypeid
WHERE ct.typename = 'Network_Interface'
UNION ALL
SELECT
'Serial/IP configs migrated',
COUNT(*)
FROM communications c
JOIN comstypes ct ON c.comstypeid = ct.comstypeid
WHERE ct.typename IN ('Serial', 'IP')
UNION ALL
SELECT
'Warranty records created',
COUNT(*)
FROM warranties w
WHERE w.machineid IN (SELECT new_machineid FROM pc_to_machine_id_mapping)
UNION ALL
SELECT
'Dualpath relationships created',
COUNT(*)
FROM machinerelationships mr
JOIN relationshiptypes rt ON mr.relationshiptypeid = rt.relationshiptypeid
WHERE rt.relationshiptype = 'Dualpath'
UNION ALL
SELECT
'Mapping records created',
COUNT(*)
FROM pc_to_machine_id_mapping
UNION ALL
SELECT
'Backup tables created',
COUNT(*)
FROM information_schema.tables
WHERE table_schema = 'shopdb'
AND table_name LIKE '%_backup_phase2';
SELECT '' AS '';
-- Critical issues check
SELECT 'Final critical issues check:' AS '';
SET @critical_issues = 0;
-- Check unmapped PCs
SET @unmapped_pcs = (
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)
);
-- Check NULL machineids in communications
SET @null_machineids = (
SELECT COUNT(*) FROM communications WHERE machineid IS NULL
);
-- Check unmapped interfaces
SET @unmapped_interfaces = (
SELECT COUNT(*) FROM pc_network_interfaces ni
WHERE ni.isactive = 1
AND NOT EXISTS (
SELECT 1 FROM communications c
JOIN pc_to_machine_id_mapping m ON c.machineid = m.new_machineid
WHERE m.pcid = ni.pcid
)
);
-- Check unmapped configs
SET @unmapped_configs = (
SELECT COUNT(*) FROM pc_comm_config cc
WHERE NOT EXISTS (
SELECT 1 FROM communications c
JOIN pc_to_machine_id_mapping m ON c.machineid = m.new_machineid
WHERE m.pcid = cc.pcid
)
);
SET @critical_issues = @unmapped_pcs + @null_machineids + @unmapped_interfaces + @unmapped_configs;
SELECT
@unmapped_pcs as unmapped_pcs,
@unmapped_interfaces as unmapped_interfaces,
@unmapped_configs as unmapped_configs,
@null_machineids as null_machineids,
@critical_issues as total_critical_issues;
SELECT '' AS '';
SELECT CASE
WHEN @critical_issues = 0 THEN '✓✓✓ PHASE 2 MIGRATION SUCCESSFUL ✓✓✓'
ELSE '⚠️⚠️⚠️ MIGRATION COMPLETED WITH ISSUES - REVIEW ABOVE ⚠️⚠️⚠️'
END AS status;
SELECT '' AS '';
-- Next steps
SELECT '============================================================' AS '';
SELECT 'NEXT STEPS' AS '';
SELECT '============================================================' AS '';
SELECT '' AS '';
SELECT '1. Review verification results above for any warnings' AS '';
SELECT '2. Test application functionality with migrated data' AS '';
SELECT '3. Check backup tables exist and contain expected data' AS '';
SELECT '4. If issues found, use rollback procedures in README.md' AS '';
SELECT '5. If successful, proceed to Phase 3 (view updates)' AS '';
SELECT '' AS '';
SELECT 'Backup tables created (for rollback if needed):' AS '';
SELECT ' - pc_backup_phase2' AS '';
SELECT ' - pc_network_interfaces_backup_phase2' AS '';
SELECT ' - pc_comm_config_backup_phase2' AS '';
SELECT ' - pc_dualpath_assignments_backup_phase2' AS '';
SELECT '' AS '';
SELECT 'Mapping table created (DO NOT DELETE until migration complete):' AS '';
SELECT ' - pc_to_machine_id_mapping' AS '';
SELECT '' AS '';
SELECT '============================================================' AS '';
SELECT 'For detailed information, see migration_phase2/README.md' AS '';
SELECT '============================================================' AS '';
-- =====================================================
-- END OF PHASE 2 MIGRATION
-- =====================================================

View File

@@ -0,0 +1,558 @@
-- =====================================================
-- VERIFY PHASE 2 MIGRATION
-- =====================================================
-- Date: 2025-11-06
-- Purpose: Comprehensive verification of Phase 2 data migration
-- Status: Run after all Phase 2 scripts complete
-- =====================================================
USE shopdb;
-- =====================================================
-- SECTION 1: PC TO MACHINES MIGRATION
-- =====================================================
SELECT '========================================' AS '';
SELECT 'PHASE 2 MIGRATION VERIFICATION' AS '';
SELECT '========================================' AS '';
SELECT '' AS '';
SELECT '========================================' AS '';
SELECT '1. PC TO MACHINES MIGRATION' AS '';
SELECT '========================================' AS '';
SELECT '' AS '';
-- Compare counts
SELECT 'Record counts:' AS '';
SELECT
'Original active PCs' AS category,
COUNT(*) as count
FROM pc WHERE isactive = 1
UNION ALL
SELECT
'New machines with pctypeid' AS category,
COUNT(*) as count
FROM machines WHERE pctypeid IS NOT NULL
UNION ALL
SELECT
'Mapping table records' AS category,
COUNT(*) as count
FROM pc_to_machine_id_mapping;
SELECT '' AS '';
-- Check for unmapped PCs
SELECT 'Unmapped PCs (should be 0):' AS '';
SELECT COUNT(*) as unmapped_pcs
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 '';
-- Machine type distribution
SELECT 'Machine type distribution:' AS '';
SELECT
mt.machinetype,
COUNT(*) as count
FROM machines m
JOIN machinetypes mt ON m.machinetypeid = mt.machinetypeid
WHERE m.pctypeid IS NOT NULL
GROUP BY mt.machinetype
ORDER BY count DESC;
SELECT '' AS '';
-- Data quality checks
SELECT 'Data quality checks:' AS '';
SELECT
'Machines with NULL hostname' AS check_name,
COUNT(*) as count,
CASE WHEN COUNT(*) = 0 THEN '' ELSE '⚠️' END as status
FROM machines WHERE pctypeid IS NOT NULL AND hostname IS NULL
UNION ALL
SELECT
'Machines with NULL machinetypeid',
COUNT(*),
CASE WHEN COUNT(*) = 0 THEN '' ELSE '⚠️' END
FROM machines WHERE pctypeid IS NOT NULL AND machinetypeid IS NULL
UNION ALL
SELECT
'Machines with NULL machinestatusid',
COUNT(*),
CASE WHEN COUNT(*) = 0 THEN '' ELSE '⚠️' END
FROM machines WHERE pctypeid IS NOT NULL AND machinestatusid IS NULL;
SELECT '' AS '';
-- =====================================================
-- SECTION 2: NETWORK INTERFACES MIGRATION
-- =====================================================
SELECT '========================================' AS '';
SELECT '2. NETWORK INTERFACES MIGRATION' AS '';
SELECT '========================================' AS '';
SELECT '' AS '';
-- Count comparison
SELECT 'Network interface counts:' AS '';
SELECT
'Original pc_network_interfaces (active)' AS category,
COUNT(*) as count
FROM pc_network_interfaces WHERE isactive = 1
UNION ALL
SELECT
'Migrated to communications (Network_Interface type)' AS category,
COUNT(*) as count
FROM communications c
JOIN comstypes ct ON c.comstypeid = ct.comstypeid
WHERE ct.typename = 'Network_Interface';
SELECT '' AS '';
-- Check for unmapped interfaces
SELECT 'Unmapped network interfaces (should be 0):' AS '';
SELECT COUNT(*) as unmapped_interfaces
FROM pc_network_interfaces ni
WHERE ni.isactive = 1
AND NOT EXISTS (
SELECT 1 FROM communications c
JOIN comstypes ct ON c.comstypeid = ct.comstypeid
JOIN pc_to_machine_id_mapping m ON c.machineid = m.new_machineid
WHERE m.pcid = ni.pcid
AND ct.typename = 'Network_Interface'
AND c.address = ni.ipaddress
);
SELECT '' AS '';
-- Sample migrated data
SELECT 'Sample migrated network interfaces (first 3):' AS '';
SELECT
c.comid,
m.hostname,
c.address AS ipaddress,
c.macaddress,
c.interfacename,
c.isdhcp
FROM communications c
JOIN machines m ON c.machineid = m.machineid
JOIN comstypes ct ON c.comstypeid = ct.comstypeid
WHERE ct.typename = 'Network_Interface'
LIMIT 3;
SELECT '' AS '';
-- =====================================================
-- SECTION 3: COMM CONFIG MIGRATION
-- =====================================================
SELECT '========================================' AS '';
SELECT '3. COMM CONFIG MIGRATION' AS '';
SELECT '========================================' AS '';
SELECT '' AS '';
-- Count by type
SELECT 'Comm config counts by type:' AS '';
SELECT
'Original pc_comm_config' AS category,
COUNT(*) as count
FROM pc_comm_config
UNION ALL
SELECT
'Migrated Serial configs' AS category,
COUNT(*) as count
FROM communications c
JOIN comstypes ct ON c.comstypeid = ct.comstypeid
WHERE ct.typename = 'Serial'
UNION ALL
SELECT
'Migrated IP configs' AS category,
COUNT(*) as count
FROM communications c
JOIN comstypes ct ON c.comstypeid = ct.comstypeid
WHERE ct.typename = 'IP';
SELECT '' AS '';
-- Check for unmapped configs
SELECT 'Unmapped comm configs (should be 0):' AS '';
SELECT COUNT(*) as unmapped_configs
FROM pc_comm_config cc
WHERE NOT EXISTS (
SELECT 1 FROM communications c
JOIN pc_to_machine_id_mapping m ON c.machineid = m.new_machineid
WHERE m.pcid = cc.pcid
);
SELECT '' AS '';
-- Sample serial configs
SELECT 'Sample serial communications (first 2):' AS '';
SELECT
c.comid,
m.hostname,
c.address AS port,
c.baud,
c.databits,
c.stopbits,
c.parity
FROM communications c
JOIN machines m ON c.machineid = m.machineid
JOIN comstypes ct ON c.comstypeid = ct.comstypeid
WHERE ct.typename = 'Serial'
LIMIT 2;
SELECT '' AS '';
-- Sample IP configs
SELECT 'Sample IP communications (first 2):' AS '';
SELECT
c.comid,
m.hostname,
c.address AS ipaddress,
c.port AS socket
FROM communications c
JOIN machines m ON c.machineid = m.machineid
JOIN comstypes ct ON c.comstypeid = ct.comstypeid
WHERE ct.typename = 'IP'
LIMIT 2;
SELECT '' AS '';
-- =====================================================
-- SECTION 4: WARRANTIES MIGRATION
-- =====================================================
SELECT '========================================' AS '';
SELECT '4. WARRANTIES MIGRATION' AS '';
SELECT '========================================' AS '';
SELECT '' AS '';
-- Count comparison
SELECT 'Warranty counts:' AS '';
SELECT
'Original PCs with warranty dates' AS category,
COUNT(*) as count
FROM pc WHERE warrantyenddate IS NOT NULL AND isactive = 1
UNION ALL
SELECT
'Migrated warranty records' AS category,
COUNT(*) as count
FROM warranties w
WHERE w.machineid IN (SELECT new_machineid FROM pc_to_machine_id_mapping);
SELECT '' AS '';
-- Warranty status distribution
SELECT 'Warranty status distribution:' AS '';
SELECT
warrantystatus,
COUNT(*) as count
FROM vw_warranty_status
WHERE machineid IN (SELECT new_machineid FROM pc_to_machine_id_mapping)
GROUP BY warrantystatus
ORDER BY count DESC;
SELECT '' AS '';
-- Warranties expiring soon
SELECT 'Warranties expiring in next 90 days:' AS '';
SELECT COUNT(*) as expiring_soon
FROM vw_warranties_expiring
WHERE machineid IN (SELECT new_machineid FROM pc_to_machine_id_mapping);
SELECT '' AS '';
-- Sample warranties
SELECT 'Sample migrated warranties (first 3):' AS '';
SELECT
w.warrantyid,
m.hostname,
w.enddate,
w.servicelevel,
DATEDIFF(w.enddate, CURDATE()) as days_remaining
FROM warranties w
JOIN machines m ON w.machineid = m.machineid
WHERE m.pctypeid IS NOT NULL
LIMIT 3;
SELECT '' AS '';
-- =====================================================
-- SECTION 5: DUALPATH ASSIGNMENTS MIGRATION
-- =====================================================
SELECT '========================================' AS '';
SELECT '5. DUALPATH ASSIGNMENTS MIGRATION' AS '';
SELECT '========================================' AS '';
SELECT '' AS '';
-- Count comparison
SELECT 'Dualpath assignment counts:' AS '';
SELECT
'Original pc_dualpath_assignments' AS category,
COUNT(*) as count
FROM pc_dualpath_assignments
UNION ALL
SELECT
'Dualpath relationships (total)' AS category,
COUNT(*) as count
FROM machinerelationships mr
JOIN relationshiptypes rt ON mr.relationshiptypeid = rt.relationshiptypeid
WHERE rt.relationshiptype = 'Dualpath'
AND mr.isactive = 1
UNION ALL
SELECT
'Expected dualpath relationships (assignments × 2)' AS category,
COUNT(*) * 2 as count
FROM pc_dualpath_assignments
WHERE primary_machine IS NOT NULL
AND secondary_machine IS NOT NULL;
SELECT '' AS '';
-- Check bidirectional consistency
SELECT 'Bidirectional relationship check:' AS '';
SELECT
'One-way relationships (should be 0)' AS check_name,
COUNT(*) as count,
CASE WHEN COUNT(*) = 0 THEN '' ELSE '⚠️' END as status
FROM machinerelationships mr1
JOIN relationshiptypes rt ON mr1.relationshiptypeid = rt.relationshiptypeid
WHERE rt.relationshiptype = 'Dualpath'
AND mr1.isactive = 1
AND NOT EXISTS (
SELECT 1 FROM machinerelationships mr2
WHERE mr2.machineid = mr1.related_machineid
AND mr2.related_machineid = mr1.machineid
AND mr2.relationshiptypeid = mr1.relationshiptypeid
AND mr2.isactive = 1
);
SELECT '' AS '';
-- Sample dualpath pairs
SELECT 'Sample dualpath machine pairs (first 3):' AS '';
SELECT
machine1_number,
machine1_hostname,
machine2_number,
machine2_hostname
FROM vw_dualpath_machines
LIMIT 3;
SELECT '' AS '';
-- =====================================================
-- SECTION 6: OVERALL COMMUNICATIONS SUMMARY
-- =====================================================
SELECT '========================================' AS '';
SELECT '6. OVERALL COMMUNICATIONS SUMMARY' AS '';
SELECT '========================================' AS '';
SELECT '' AS '';
-- Communications by type
SELECT 'Communications by type (all):' AS '';
SELECT
ct.typename,
COUNT(*) as count
FROM communications c
JOIN comstypes ct ON c.comstypeid = ct.comstypeid
WHERE c.isactive = 1
GROUP BY ct.typename
ORDER BY count DESC;
SELECT '' AS '';
-- Communications data quality
SELECT 'Communications data quality:' AS '';
SELECT
'Communications with NULL machineid' AS check_name,
COUNT(*) as count,
CASE WHEN COUNT(*) = 0 THEN '' ELSE '⚠️' END as status
FROM communications WHERE machineid IS NULL
UNION ALL
SELECT
'Communications with NULL comstypeid' AS check_name,
COUNT(*) as count,
CASE WHEN COUNT(*) = 0 THEN '' ELSE '⚠️' END as status
FROM communications WHERE comstypeid IS NULL
UNION ALL
SELECT
'Network interfaces without IP address' AS check_name,
COUNT(*) as count,
CASE WHEN COUNT(*) = 0 THEN '' ELSE '⚠️' END as status
FROM communications c
JOIN comstypes ct ON c.comstypeid = ct.comstypeid
WHERE ct.typename = 'Network_Interface'
AND (c.address IS NULL OR c.address = '');
SELECT '' AS '';
-- =====================================================
-- SECTION 7: RELATIONSHIP SUMMARY
-- =====================================================
SELECT '========================================' AS '';
SELECT '7. RELATIONSHIP SUMMARY' AS '';
SELECT '========================================' AS '';
SELECT '' AS '';
-- Relationships by type
SELECT 'Relationships by type:' AS '';
SELECT
rt.relationshiptype,
COUNT(*) as count
FROM machinerelationships mr
JOIN relationshiptypes rt ON mr.relationshiptypeid = rt.relationshiptypeid
WHERE mr.isactive = 1
GROUP BY rt.relationshiptype
ORDER BY count DESC;
SELECT '' AS '';
-- =====================================================
-- SECTION 8: BACKUP TABLE VERIFICATION
-- =====================================================
SELECT '========================================' AS '';
SELECT '8. BACKUP TABLE VERIFICATION' AS '';
SELECT '========================================' AS '';
SELECT '' AS '';
-- Verify all backup tables exist
SELECT 'Backup tables created:' AS '';
SELECT
'pc_backup_phase2' AS backup_table,
COUNT(*) as record_count,
CASE WHEN COUNT(*) > 0 THEN '' ELSE '⚠️' END as status
FROM pc_backup_phase2
UNION ALL
SELECT
'pc_network_interfaces_backup_phase2' AS backup_table,
COUNT(*) as record_count,
CASE WHEN COUNT(*) > 0 THEN '' ELSE '⚠️' END as status
FROM pc_network_interfaces_backup_phase2
UNION ALL
SELECT
'pc_comm_config_backup_phase2' AS backup_table,
COUNT(*) as record_count,
CASE WHEN COUNT(*) > 0 THEN '' ELSE '⚠️' END as status
FROM pc_comm_config_backup_phase2
UNION ALL
SELECT
'pc_dualpath_assignments_backup_phase2' AS backup_table,
COUNT(*) as record_count,
CASE WHEN COUNT(*) > 0 THEN '' ELSE '⚠️' END as status
FROM pc_dualpath_assignments_backup_phase2;
SELECT '' AS '';
-- =====================================================
-- SECTION 9: FINAL SUMMARY
-- =====================================================
SELECT '========================================' AS '';
SELECT 'MIGRATION SUMMARY' AS '';
SELECT '========================================' AS '';
SELECT '' AS '';
-- Overall migration statistics
SELECT 'Overall migration statistics:' AS '';
SELECT
CONCAT('PCs migrated: ', COUNT(*)) AS statistic
FROM machines WHERE pctypeid IS NOT NULL
UNION ALL
SELECT
CONCAT('Network interfaces migrated: ', COUNT(*))
FROM communications c
JOIN comstypes ct ON c.comstypeid = ct.comstypeid
WHERE ct.typename = 'Network_Interface'
UNION ALL
SELECT
CONCAT('Serial/IP configs migrated: ', COUNT(*))
FROM communications c
JOIN comstypes ct ON c.comstypeid = ct.comstypeid
WHERE ct.typename IN ('Serial', 'IP')
UNION ALL
SELECT
CONCAT('Warranty records migrated: ', COUNT(*))
FROM warranties w
WHERE w.machineid IN (SELECT new_machineid FROM pc_to_machine_id_mapping)
UNION ALL
SELECT
CONCAT('Dualpath relationships created: ', COUNT(*))
FROM machinerelationships mr
JOIN relationshiptypes rt ON mr.relationshiptypeid = rt.relationshiptypeid
WHERE rt.relationshiptype = 'Dualpath'
AND mr.isactive = 1;
SELECT '' AS '';
-- Critical issues check
SELECT 'Critical issues (should all be 0):' AS '';
SELECT
COUNT(*) as unmapped_pcs,
(SELECT COUNT(*) FROM pc_network_interfaces ni
WHERE ni.isactive = 1
AND NOT EXISTS (
SELECT 1 FROM communications c
JOIN pc_to_machine_id_mapping m ON c.machineid = m.new_machineid
WHERE m.pcid = ni.pcid
)) as unmapped_interfaces,
(SELECT COUNT(*) FROM pc_comm_config cc
WHERE NOT EXISTS (
SELECT 1 FROM communications c
JOIN pc_to_machine_id_mapping m ON c.machineid = m.new_machineid
WHERE m.pcid = cc.pcid
)) as unmapped_configs,
(SELECT COUNT(*) FROM communications WHERE machineid IS NULL) as null_machineids
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 '';
SELECT '========================================' AS '';
SELECT '✓ PHASE 2 VERIFICATION COMPLETE' AS '';
SELECT '========================================' AS '';
SELECT '' AS '';
-- Next steps
SELECT 'Next steps:' AS '';
SELECT '1. Review verification results above' AS '';
SELECT '2. Check for any warnings (⚠️) or non-zero critical issues' AS '';
SELECT '3. If all checks pass, proceed to Phase 3 (view updates)' AS '';
SELECT '4. If issues found, investigate using backup tables' AS '';
-- =====================================================
-- NOTES
-- =====================================================
-- This script provides comprehensive verification of Phase 2 migration
--
-- Sections verified:
-- 1. PC to machines migration (277 PCs)
-- 2. Network interfaces to communications
-- 3. Comm config to communications (Serial/IP)
-- 4. Warranty data migration
-- 5. Dualpath assignments to machine relationships
-- 6. Overall communications summary
-- 7. Relationship types summary
-- 8. Backup table verification
-- 9. Final summary and critical issues
--
-- All checks should show ✓ status
-- Critical issues count should be 0
--
-- If any issues found, use backup tables:
-- - pc_backup_phase2
-- - pc_network_interfaces_backup_phase2
-- - pc_comm_config_backup_phase2
-- - pc_dualpath_assignments_backup_phase2
-- =====================================================

View File

@@ -0,0 +1,231 @@
#!/usr/bin/env python3
"""
Fix Equipment Data from Equipment Names
Extracts correct vendor/model/type from Equipment_Name column instead of PC/Controller columns
"""
import csv
import re
import pymysql
DB_CONFIG = {
'host': 'localhost',
'user': '570005354',
'password': '570005354',
'database': 'shopdb',
'charset': 'utf8mb4',
'cursorclass': pymysql.cursors.DictCursor
}
# Vendor/Model extraction from equipment names
EQUIPMENT_PATTERNS = [
# OKUMA machines
{
'pattern': r'(?i)OKUMA\s+(&\s+HOWA\s+)?2SP\s+V\d+',
'vendor': 'Okuma',
'model': '2SP V80',
'type': 'Vertical Lathe'
},
{
'pattern': r'(?i)OKUMA\s+VTM\s+\d+',
'vendor': 'Okuma',
'model': 'VTM 100',
'type': 'Vertical Lathe'
},
{
'pattern': r'(?i)OKUMA\s+LOC\s+650.*4.?Axis.*SimulTurn',
'vendor': 'Okuma',
'model': 'LOC 650',
'type': 'Mill Turn'
},
{
'pattern': r'(?i)OKUMA\s+LB\s*\d+',
'vendor': 'Okuma',
'model_extract': r'LB\s*\d+[A-Z]*',
'type': 'Lathe'
},
# HWACHEON machines
{
'pattern': r'(?i)HWACHEON\s+VT[L]?\s*\d+',
'vendor': 'Hwacheon',
'model_extract': r'VT[L]?\s*\d+[A-Z]*',
'type': 'Vertical Lathe'
},
# HEXAGON/Brown&Sharpe CMMs
{
'pattern': r'(?i)(Brown.?Sharpe|HEXAGON).*CMM',
'vendor': 'Hexagon Metrology',
'model_extract': r'(?:GLOBAL\s+)?(?:ADVANTAGE\s+)?(?:FX\s+)?[\d\s\.]+(?:SF)?',
'type': 'CMM'
},
# Mitutoyo CMMs
{
'pattern': r'(?i)Mitutoyo\s+C\s*\d+',
'vendor': 'Mitutoyo',
'model': 'C 4500',
'type': 'CMM'
},
# KEYENCE Vision Systems
{
'pattern': r'(?i)KEYENCE\s+(VHX|VR)\s*\d+',
'vendor': 'KEYENCE',
'model_extract': r'V[HR]X?\s*\d+',
'type': 'Measuring Machine'
},
# OKK Mills
{
'pattern': r'(?i)OKK\s+VP\d+.*5.*AXIS',
'vendor': 'OKK',
'model_extract': r'VP\d+',
'type': '5-axis Mill'
},
]
def connect_db():
conn = pymysql.connect(**DB_CONFIG)
print(f"✓ Connected to database: {DB_CONFIG['database']}")
return conn
def get_or_create_vendor(cursor, vendor_name):
if not vendor_name:
return None
cursor.execute("SELECT vendorid FROM vendors WHERE vendor = %s", (vendor_name,))
result = cursor.fetchone()
if result:
return result['vendorid']
cursor.execute("INSERT INTO vendors (vendor, isactive, ismachine) VALUES (%s, 1, 1)", (vendor_name,))
return cursor.lastrowid
def get_or_create_model(cursor, model_name, vendor_id):
if not model_name or not vendor_id:
return None
cursor.execute("SELECT modelnumberid FROM models WHERE modelnumber = %s AND vendorid = %s", (model_name, vendor_id))
result = cursor.fetchone()
if result:
return result['modelnumberid']
cursor.execute("INSERT INTO models (modelnumber, vendorid, isactive) VALUES (%s, %s, 1)", (model_name, vendor_id))
return cursor.lastrowid
def get_machine_type_id(cursor, machine_type_name):
cursor.execute("SELECT machinetypeid FROM machinetypes WHERE machinetype = %s", (machine_type_name,))
result = cursor.fetchone()
return result['machinetypeid'] if result else None
def extract_equipment_info(equipment_name):
"""Extract vendor, model, and type from equipment name"""
if not equipment_name:
return None, None, None
for pattern_info in EQUIPMENT_PATTERNS:
match = re.search(pattern_info['pattern'], equipment_name)
if match:
vendor = pattern_info.get('vendor')
# Extract model
if 'model_extract' in pattern_info:
model_match = re.search(pattern_info['model_extract'], equipment_name, re.IGNORECASE)
model = model_match.group(0).strip() if model_match else pattern_info.get('model')
else:
model = pattern_info.get('model')
machine_type = pattern_info.get('type')
return vendor, model, machine_type
return None, None, None
def main():
print("="*70)
print("FIX EQUIPMENT FROM EQUIPMENT NAMES")
print("="*70)
conn = connect_db()
cursor = conn.cursor()
# Read inventory
with open('/tmp/inventory_restructured.csv', 'r', encoding='utf-8') as f:
reader = csv.DictReader(f)
equipment_rows = [row for row in reader if row.get('Row_Type') == 'Equipment']
print(f"✓ Found {len(equipment_rows)} equipment records\n")
updates = 0
skipped = 0
for row in equipment_rows:
machine_number = row.get('Machine_Number', '').strip()
equipment_name = row.get('Equipment_Name', '').strip()
if not machine_number or not equipment_name:
continue
# Check if machine exists
cursor.execute("SELECT machineid, machinetypeid FROM machines WHERE machinenumber = %s", (machine_number,))
machine = cursor.fetchone()
if not machine:
continue
# Extract equipment info from name
vendor_name, model_name, machine_type_name = extract_equipment_info(equipment_name)
if not vendor_name:
skipped += 1
continue
# Get/create vendor and model
vendor_id = get_or_create_vendor(cursor, vendor_name)
model_id = get_or_create_model(cursor, model_name, vendor_id) if model_name else None
type_id = get_machine_type_id(cursor, machine_type_name) if machine_type_name else None
# Build UPDATE
update_parts = []
values = []
if model_id:
update_parts.append("modelnumberid = %s")
values.append(model_id)
if type_id:
update_parts.append("machinetypeid = %s")
values.append(type_id)
if update_parts:
update_parts.append("lastupdated = NOW()")
values.append(machine['machineid'])
sql = f"UPDATE machines SET {', '.join(update_parts)} WHERE machineid = %s"
cursor.execute(sql, tuple(values))
conn.commit()
print(f"{machine_number}: {equipment_name[:50]}")
print(f" Vendor: {vendor_name}, Model: {model_name}, Type: {machine_type_name}")
updates += 1
else:
skipped += 1
# Summary
print("\n" + "="*70)
print("SUMMARY")
print("="*70)
print(f"Equipment updated: {updates}")
print(f"Equipment skipped: {skipped}")
# Show LocationOnly count
cursor.execute("""
SELECT COUNT(*) as count FROM machines m
JOIN machinetypes mt ON m.machinetypeid = mt.machinetypeid
WHERE mt.machinetype = 'LocationOnly' AND m.isactive = 1
""")
location_only = cursor.fetchone()['count']
print(f"\nLocationOnly remaining: {location_only}")
cursor.close()
conn.close()
print("\n✓ Complete!")
if __name__ == '__main__':
main()

View File

@@ -0,0 +1,246 @@
#!/usr/bin/env python3
"""
Fix Machine Types from Inventory Data
Updates machines with incorrect machinetypeid based on equipment names/descriptions
"""
import csv
import re
import pymysql
# Database connection settings
DB_CONFIG = {
'host': 'localhost',
'user': '570005354',
'password': '570005354',
'database': 'shopdb',
'charset': 'utf8mb4',
'cursorclass': pymysql.cursors.DictCursor
}
# Machine type mapping rules based on equipment names/keywords
MACHINE_TYPE_RULES = [
# CMMs (Coordinate Measuring Machines)
(r'(?i)(CMM|Hexagon|Brown.?Sharpe|Mitutoyo C\s*\d+)', 'CMM'),
# Vertical Lathes (expanded patterns for OKUMA machines)
(r'(?i)(VT\s*\d+|VTL\s*\d+|VT\s*5502|Vertical.*Lathe|Hwacheon.*V|2SP.*V\d+|VTM\s*\d+|OKUMA.*V\d+)', 'Vertical Lathe'),
# Regular Lathes
(r'(?i)((?<!Vertical\s)Lathe|Turning|LB\s*\d+)', 'Lathe'),
# Mill Turn
(r'(?i)(Mill.*Turn|Multitasking)', 'Mill Turn'),
# 5-axis Mills
(r'(?i)(5.?axis|Five.?axis)', '5-axis Mill'),
# Grinders
(r'(?i)(Grind|Surface.*Grind)', 'Grinder'),
# Part Washers
(r'(?i)(Washer|Wash.*Station|Cleaning)', 'Part Washer'),
# Furnaces
(r'(?i)(Furnace|Oven|Heat.*Treat)', 'Furnace'),
# EDM/Eddy Current
(r'(?i)(EDM|Eddy.*Current)', 'Eddy Current'),
# Welders
(r'(?i)(Weld|Intertia)', 'Intertia Welder'),
# Measuring Machines (generic)
(r'(?i)(Measur|Inspect.*Machine)', 'Measuring Machine'),
# Keyence Vision Systems
(r'(?i)(Keyence|VHX|VR\s*\d+)', 'Measuring Machine'),
# Hobbing
(r'(?i)(Hobb|Gear.*Cut)', 'Hobbing Machine'),
# Deburring
(r'(?i)(Deburr|Polish)', 'Robotic Deburring'),
# Shot Peen
(r'(?i)(Shot.?peen|Peen)', 'Shotpeen'),
# Broach
(r'(?i)(Broach)', 'Broach'),
]
def connect_db():
"""Connect to MySQL database"""
try:
conn = pymysql.connect(**DB_CONFIG)
print(f"✓ Connected to database: {DB_CONFIG['database']}")
return conn
except Exception as e:
print(f"✗ Database connection failed: {e}")
return None
def get_machine_type_id(cursor, machine_type_name):
"""Get machine type ID by name"""
cursor.execute(
"SELECT machinetypeid FROM machinetypes WHERE machinetype = %s",
(machine_type_name,)
)
result = cursor.fetchone()
return result['machinetypeid'] if result else None
def determine_machine_type(equipment_name):
"""Determine correct machine type based on equipment name"""
if not equipment_name:
return None
# Check each rule
for pattern, machine_type in MACHINE_TYPE_RULES:
if re.search(pattern, equipment_name):
return machine_type
return None
def update_machine_type_from_inventory(cursor, conn):
"""Update machine types based on inventory data"""
# Read inventory CSV
csv_file = '/tmp/inventory_restructured.csv'
print(f"\n📄 Reading inventory: {csv_file}")
with open(csv_file, 'r', encoding='utf-8') as f:
reader = csv.DictReader(f)
equipment_rows = [row for row in reader if row.get('Row_Type') == 'Equipment']
print(f"✓ Found {len(equipment_rows)} equipment records")
# Get LocationOnly machine type ID
location_only_id = get_machine_type_id(cursor, 'LocationOnly')
print(f"✓ LocationOnly machine type ID: {location_only_id}")
updates_made = 0
skipped = 0
errors = 0
print("\n" + "="*70)
print("UPDATING MACHINE TYPES")
print("="*70)
for row in equipment_rows:
machine_number = row.get('Machine_Number', '').strip()
equipment_name = row.get('Equipment_Name', '').strip()
if not machine_number or not equipment_name:
continue
# Check if machine exists and is LocationOnly
cursor.execute(
"""SELECT m.machineid, m.machinetypeid, mt.machinetype, m.alias
FROM machines m
JOIN machinetypes mt ON m.machinetypeid = mt.machinetypeid
WHERE m.machinenumber = %s AND m.isactive = 1""",
(machine_number,)
)
machine = cursor.fetchone()
if not machine:
continue
# Determine correct machine type from equipment name
correct_type_name = determine_machine_type(equipment_name)
if not correct_type_name:
skipped += 1
continue
correct_type_id = get_machine_type_id(cursor, correct_type_name)
if not correct_type_id:
print(f" ⚠️ Machine type '{correct_type_name}' not found in database")
errors += 1
continue
# Only update if currently LocationOnly or wrong type
if machine['machinetypeid'] == location_only_id or machine['machinetypeid'] != correct_type_id:
print(f"\n🔧 Machine {machine_number}: {equipment_name}")
print(f" Current: {machine['machinetype']} (ID: {machine['machinetypeid']})")
print(f" New: {correct_type_name} (ID: {correct_type_id})")
cursor.execute(
"UPDATE machines SET machinetypeid = %s, lastupdated = NOW() WHERE machineid = %s",
(correct_type_id, machine['machineid'])
)
conn.commit()
updates_made += 1
print(f" ✓ Updated")
else:
skipped += 1
return updates_made, skipped, errors
def main():
"""Main process"""
print("="*70)
print("MACHINE TYPE CORRECTION SCRIPT")
print("="*70)
conn = connect_db()
if not conn:
return
cursor = conn.cursor()
# Show current LocationOnly count
cursor.execute(
"""SELECT COUNT(*) as count FROM machines m
JOIN machinetypes mt ON m.machinetypeid = mt.machinetypeid
WHERE mt.machinetype = 'LocationOnly' AND m.isactive = 1"""
)
before_count = cursor.fetchone()['count']
print(f"\n📊 Current LocationOnly machines: {before_count}")
# Update machine types from inventory
updates, skipped, errors = update_machine_type_from_inventory(cursor, conn)
# Show after count
cursor.execute(
"""SELECT COUNT(*) as count FROM machines m
JOIN machinetypes mt ON m.machinetypeid = mt.machinetypeid
WHERE mt.machinetype = 'LocationOnly' AND m.isactive = 1"""
)
after_count = cursor.fetchone()['count']
# Summary
print("\n" + "="*70)
print("SUMMARY")
print("="*70)
print(f"LocationOnly machines before: {before_count}")
print(f"LocationOnly machines after: {after_count}")
print(f"Machines updated: {updates}")
print(f"Machines skipped: {skipped}")
print(f"Errors: {errors}")
print(f"Net reduction: {before_count - after_count}")
# Show breakdown by machine type now
print("\n" + "="*70)
print("MACHINE TYPE DISTRIBUTION (Top 15)")
print("="*70)
cursor.execute(
"""SELECT mt.machinetype, COUNT(*) as count
FROM machines m
JOIN machinetypes mt ON m.machinetypeid = mt.machinetypeid
WHERE m.isactive = 1
GROUP BY m.machinetypeid
ORDER BY count DESC
LIMIT 15"""
)
for row in cursor.fetchall():
print(f"{row['machinetype']:30} {row['count']:4}")
cursor.close()
conn.close()
print("\n✓ Complete!")
if __name__ == '__main__':
main()

View File

@@ -0,0 +1,414 @@
#!/usr/bin/env python3
"""
Import and Update Script for inventory_restructured.ods
Imports equipment and PC data from spreadsheet into shopdb database
This script will:
1. Import/update vendors and models
2. Import/update controller types and operating systems
3. Update existing machines with correct vendor/model/controller data
4. Update existing PCs with correct data
5. Import business unit information
6. Import compliance/security data
"""
import csv
import sys
import pymysql
from datetime import datetime
# Database connection settings
DB_CONFIG = {
'host': 'localhost',
'user': '570005354',
'password': '570005354',
'database': 'shopdb',
'charset': 'utf8mb4',
'cursorclass': pymysql.cursors.DictCursor
}
def connect_db():
"""Connect to the MySQL database"""
try:
conn = pymysql.connect(**DB_CONFIG)
print(f"✓ Connected to database: {DB_CONFIG['database']}")
return conn
except Exception as e:
print(f"✗ Database connection failed: {e}")
sys.exit(1)
def get_or_create_vendor(cursor, vendor_name):
"""Get vendor ID or create if doesn't exist"""
if not vendor_name or vendor_name.strip() == '':
return None
vendor_name = vendor_name.strip()
# Check if vendor exists
cursor.execute("SELECT vendorid FROM vendors WHERE vendor = %s", (vendor_name,))
result = cursor.fetchone()
if result:
return result['vendorid']
# Create new vendor
cursor.execute(
"INSERT INTO vendors (vendor, isactive) VALUES (%s, 1)",
(vendor_name,)
)
vendor_id = cursor.lastrowid
print(f" + Created new vendor: {vendor_name} (ID: {vendor_id})")
return vendor_id
def get_or_create_model(cursor, model_name, vendor_id):
"""Get model ID or create if doesn't exist"""
if not model_name or model_name.strip() == '':
return None
model_name = model_name.strip()
# Check if model exists for this vendor
cursor.execute(
"SELECT modelnumberid FROM models WHERE modelnumber = %s AND vendorid = %s",
(model_name, vendor_id)
)
result = cursor.fetchone()
if result:
return result['modelnumberid']
# Create new model
cursor.execute(
"INSERT INTO models (modelnumber, vendorid, isactive) VALUES (%s, %s, 1)",
(model_name, vendor_id)
)
model_id = cursor.lastrowid
print(f" + Created new model: {model_name} (ID: {model_id})")
return model_id
def get_or_create_os(cursor, os_name):
"""Get operating system ID or create if doesn't exist"""
if not os_name or os_name.strip() == '':
return None
os_name = os_name.strip()
# Check if OS exists
cursor.execute("SELECT osid FROM operatingsystems WHERE operatingsystem = %s", (os_name,))
result = cursor.fetchone()
if result:
return result['osid']
# Create new OS (no isactive column in this table)
cursor.execute(
"INSERT INTO operatingsystems (operatingsystem) VALUES (%s)",
(os_name,)
)
os_id = cursor.lastrowid
print(f" + Created new OS: {os_name} (ID: {os_id})")
return os_id
def get_or_create_controller_type(cursor, controller_name, vendor_id=None):
"""Get controller type ID or create if doesn't exist"""
if not controller_name or controller_name.strip() == '':
return None
controller_name = controller_name.strip()
# Check if controller type exists
cursor.execute(
"SELECT controllertypeid FROM controllertypes WHERE controllertype = %s",
(controller_name,)
)
result = cursor.fetchone()
if result:
return result['controllertypeid']
# Create new controller type (without vendorid for now)
cursor.execute(
"INSERT INTO controllertypes (controllertype, isactive) VALUES (%s, 1)",
(controller_name,)
)
controller_id = cursor.lastrowid
print(f" + Created new controller type: {controller_name} (ID: {controller_id})")
return controller_id
def get_business_unit_id(cursor, business_unit_name):
"""Get business unit ID by name"""
if not business_unit_name or business_unit_name.strip() == '':
return None
cursor.execute(
"SELECT businessunitid FROM businessunits WHERE businessunit = %s",
(business_unit_name.strip(),)
)
result = cursor.fetchone()
return result['businessunitid'] if result else None
def update_machine(cursor, row, conn):
"""Update existing machine with inventory data"""
machine_number = row.get('Machine_Number', '').strip()
if not machine_number:
return False
# Get vendor and model
vendor_name = row.get('Manufacturer', '').strip()
model_name = row.get('Model', '').strip()
vendor_id = get_or_create_vendor(cursor, vendor_name) if vendor_name else None
model_id = get_or_create_model(cursor, model_name, vendor_id) if model_name and vendor_id else None
# Get controller info
controller_name = row.get('Controller_Type1', '').strip()
controller_os_name = row.get('Controller_OS1', '').strip()
controller_id = get_or_create_controller_type(cursor, controller_name, vendor_id) if controller_name else None
controller_os_id = get_or_create_os(cursor, controller_os_name) if controller_os_name else None
# Get business unit
business_unit_name = row.get('Business_Unit', '').strip()
business_unit_id = get_business_unit_id(cursor, business_unit_name) if business_unit_name else None
# Get serial number
serial_number = row.get('Serial #', '').strip()
# Get IP addresses
ip_address1 = row.get('IP Address', '').strip()
ip_address2 = row.get('IP Address (interface 2)', '').strip()
# Check if machine exists
cursor.execute(
"SELECT machineid FROM machines WHERE machinenumber = %s",
(machine_number,)
)
result = cursor.fetchone()
if not result:
print(f" ⚠️ Machine {machine_number} not found in database")
return False
machine_id = result['machineid']
# Update machine
update_fields = []
update_values = []
# Note: machines table doesn't have vendorid, it has modelnumberid which links to models (which has vendorid)
if model_id:
update_fields.append("modelnumberid = %s")
update_values.append(model_id)
if controller_id:
update_fields.append("controllertypeid = %s")
update_values.append(controller_id)
if controller_os_id:
update_fields.append("controllerosid = %s")
update_values.append(controller_os_id)
if business_unit_id:
update_fields.append("businessunitid = %s")
update_values.append(business_unit_id)
if serial_number:
update_fields.append("serialnumber = %s")
update_values.append(serial_number)
if ip_address1:
update_fields.append("ipaddress1 = %s")
update_values.append(ip_address1)
if ip_address2:
update_fields.append("ipaddress2 = %s")
update_values.append(ip_address2)
update_fields.append("lastupdated = NOW()")
if update_fields:
update_values.append(machine_id)
sql = f"UPDATE machines SET {', '.join(update_fields)} WHERE machineid = %s"
cursor.execute(sql, tuple(update_values))
conn.commit()
return True
return False
def update_pc(cursor, row, conn):
"""Update existing PC (now in machines table) with inventory data"""
hostname = row.get('Hostname', '').strip()
if not hostname:
return False
# Get vendor and model
vendor_name = row.get('Manufacturer', '').strip()
model_name = row.get('Model', '').strip()
vendor_id = get_or_create_vendor(cursor, vendor_name) if vendor_name else None
model_id = get_or_create_model(cursor, model_name, vendor_id) if model_name and vendor_id else None
# Get OS info
os_name = row.get('OS Name', '').strip()
os_id = get_or_create_os(cursor, os_name) if os_name else None
# Get business unit
business_unit_name = row.get('Business_Unit', '').strip()
business_unit_id = get_business_unit_id(cursor, business_unit_name) if business_unit_name else None
# Get serial number
serial_number = row.get('Serial #', '').strip()
# Get logged in user (if available)
logged_in_user = row.get('Logged_In_User', '').strip()
# Find machine by hostname (PCs were migrated with hostname as machinenumber)
cursor.execute(
"SELECT machineid FROM machines WHERE machinenumber = %s OR hostname = %s",
(hostname, hostname)
)
result = cursor.fetchone()
if not result:
print(f" ⚠️ PC {hostname} not found in machines table")
return False
machine_id = result['machineid']
# Update machine (PC)
update_fields = []
update_values = []
# Note: machines table doesn't have vendorid, it has modelnumberid which links to models (which has vendorid)
if model_id:
update_fields.append("modelnumberid = %s")
update_values.append(model_id)
if os_id:
update_fields.append("osid = %s")
update_values.append(os_id)
if business_unit_id:
update_fields.append("businessunitid = %s")
update_values.append(business_unit_id)
if serial_number:
update_fields.append("serialnumber = %s")
update_values.append(serial_number)
if logged_in_user:
update_fields.append("loggedinuser = %s")
update_values.append(logged_in_user)
update_fields.append("lastupdated = NOW()")
if update_fields:
update_values.append(machine_id)
sql = f"UPDATE machines SET {', '.join(update_fields)} WHERE machineid = %s"
cursor.execute(sql, tuple(update_values))
conn.commit()
return True
return False
def main():
"""Main import process"""
print("="*70)
print("INVENTORY DATA IMPORT - Phase 2 Enhancement")
print("="*70)
print()
# Connect to database
conn = connect_db()
cursor = conn.cursor()
# Read CSV file
csv_file = '/tmp/inventory_restructured.csv'
print(f"📄 Reading inventory file: {csv_file}")
try:
with open(csv_file, 'r', encoding='utf-8') as f:
reader = csv.DictReader(f)
rows = list(reader)
print(f"✓ Loaded {len(rows)} rows from inventory")
print()
except Exception as e:
print(f"✗ Failed to read CSV file: {e}")
conn.close()
sys.exit(1)
# Separate PCs and Equipment
pcs = [row for row in rows if row.get('Row_Type') == 'PC']
equipment = [row for row in rows if row.get('Row_Type') == 'Equipment']
print(f"📊 Inventory breakdown:")
print(f" - PCs: {len(pcs)}")
print(f" - Equipment: {len(equipment)}")
print()
# Process Equipment (Machines)
print("="*70)
print("UPDATING EQUIPMENT (MACHINES)")
print("="*70)
equipment_updated = 0
equipment_failed = 0
for idx, row in enumerate(equipment, 1):
machine_number = row.get('Machine_Number', '').strip()
equipment_name = row.get('Equipment_Name', '').strip()
if machine_number:
print(f"[{idx}/{len(equipment)}] Processing: {machine_number} - {equipment_name}")
if update_machine(cursor, row, conn):
equipment_updated += 1
print(f" ✓ Updated machine: {machine_number}")
else:
equipment_failed += 1
print()
# Process PCs
print("="*70)
print("UPDATING PCs")
print("="*70)
pcs_updated = 0
pcs_failed = 0
for idx, row in enumerate(pcs, 1):
hostname = row.get('Hostname', '').strip()
if hostname:
print(f"[{idx}/{len(pcs)}] Processing PC: {hostname}")
if update_pc(cursor, row, conn):
pcs_updated += 1
print(f" ✓ Updated PC: {hostname}")
else:
pcs_failed += 1
print()
# Summary
print("="*70)
print("IMPORT SUMMARY")
print("="*70)
print(f"Equipment:")
print(f" ✓ Updated: {equipment_updated}")
print(f" ✗ Failed: {equipment_failed}")
print()
print(f"PCs:")
print(f" ✓ Updated: {pcs_updated}")
print(f" ✗ Failed: {pcs_failed}")
print()
print(f"Total records processed: {len(rows)}")
print(f"Total records updated: {equipment_updated + pcs_updated}")
print()
# Close connection
cursor.close()
conn.close()
print("✓ Import complete!")
if __name__ == '__main__':
main()

View File

@@ -0,0 +1,440 @@
#!/usr/bin/env python3
"""
Enhanced Inventory Import Script
Imports additional data from inventory_restructured.ods:
- MAC addresses (to communications table)
- PC-to-machine control relationships
- Asset criticality and compliance data
- VLAN, location, security scan data
"""
import csv
import sys
import pymysql
from datetime import datetime
DB_CONFIG = {
'host': 'localhost',
'user': '570005354',
'password': '570005354',
'database': 'shopdb',
'charset': 'utf8mb4',
'cursorclass': pymysql.cursors.DictCursor
}
def connect_db():
"""Connect to MySQL database"""
try:
conn = pymysql.connect(**DB_CONFIG)
print(f"✓ Connected to database: {DB_CONFIG['database']}")
return conn
except Exception as e:
print(f"✗ Database connection failed: {e}")
sys.exit(1)
def get_comtype_id(cursor, typename):
"""Get communication type ID"""
cursor.execute("SELECT comstypeid FROM comstypes WHERE typename = %s", (typename,))
result = cursor.fetchone()
return result['comstypeid'] if result else None
def get_relationship_type_id(cursor, relationship_type):
"""Get relationship type ID or create if doesn't exist"""
cursor.execute("SELECT relationshiptypeid FROM relationshiptypes WHERE relationshiptype = %s", (relationship_type,))
result = cursor.fetchone()
if result:
return result['relationshiptypeid']
# Create new relationship type
cursor.execute("INSERT INTO relationshiptypes (relationshiptype, isactive) VALUES (%s, 1)", (relationship_type,))
return cursor.lastrowid
def import_mac_addresses(cursor, conn, rows):
"""Import MAC addresses for equipment into communications table"""
print("\n" + "="*70)
print("IMPORTING MAC ADDRESSES")
print("="*70)
network_interface_type = get_comtype_id(cursor, 'Network_Interface')
if not network_interface_type:
print("✗ Network_Interface communication type not found!")
return 0
imported = 0
skipped = 0
for row in rows:
if row.get('Row_Type') != 'Equipment':
continue
machine_number = row.get('Machine_Number', '').strip()
if not machine_number:
continue
# Get machine ID
cursor.execute("SELECT machineid FROM machines WHERE machinenumber = %s", (machine_number,))
machine = cursor.fetchone()
if not machine:
continue
machine_id = machine['machineid']
# Get IP and MAC addresses from inventory
ip1 = row.get('IP Address', '').strip()
ip2 = row.get('IP Address (interface 2)', '').strip()
ip3 = row.get('IP Address (Interface 3)', '').strip()
mac1 = row.get('MAC Address (interface1)', '').strip()
mac2 = row.get('MAC address (Interface 2)', '').strip()
mac3 = row.get('MAC Address (Interface 3)', '').strip()
# Create communications records for each interface with data
interfaces = [
(ip1, mac1, 'Interface 1'),
(ip2, mac2, 'Interface 2'),
(ip3, mac3, 'Interface 3')
]
for ip_addr, mac_addr, interface_name in interfaces:
if ip_addr or mac_addr: # Only create if we have at least IP or MAC
# Check if communication already exists for this machine/IP
cursor.execute(
"""SELECT comid FROM communications
WHERE machineid = %s AND address = %s AND comstypeid = %s""",
(machine_id, ip_addr or '', network_interface_type)
)
existing = cursor.fetchone()
if not existing:
# Insert new communication record
cursor.execute(
"""INSERT INTO communications
(machineid, comstypeid, address, macaddress, interfacename, isactive)
VALUES (%s, %s, %s, %s, %s, 1)""",
(machine_id, network_interface_type, ip_addr or None, mac_addr or None,
interface_name)
)
conn.commit()
if imported < 10: # Show first 10
print(f"{machine_number}: {interface_name} - IP: {ip_addr or 'N/A'}, MAC: {mac_addr or 'N/A'}")
imported += 1
else:
skipped += 1
if imported > 10:
print(f"... and {imported - 10} more")
print(f"\n✓ Imported {imported} communication records, skipped {skipped} existing")
return imported
def import_pc_machine_relationships(cursor, conn, rows):
"""Import PC-to-machine control relationships"""
print("\n" + "="*70)
print("IMPORTING PC-TO-MACHINE CONTROL RELATIONSHIPS")
print("="*70)
controls_type_id = get_relationship_type_id(cursor, 'Controls')
print(f"✓ Relationship type 'Controls' ID: {controls_type_id}")
imported = 0
skipped = 0
errors = 0
for row in rows:
if row.get('Row_Type') != 'Equipment':
continue
machine_number = row.get('Machine_Number', '').strip()
pc_hostname = row.get('Associated_PC_Hostname', '').strip()
if not machine_number or not pc_hostname:
continue
# Get equipment machine ID
cursor.execute("SELECT machineid FROM machines WHERE machinenumber = %s", (machine_number,))
equipment = cursor.fetchone()
if not equipment:
continue
equipment_id = equipment['machineid']
# Find PC by hostname (could be in hostname OR machinenumber for PCs)
cursor.execute(
"""SELECT machineid FROM machines
WHERE (hostname = %s OR machinenumber = %s)
AND pctypeid IS NOT NULL""",
(pc_hostname, pc_hostname)
)
pc = cursor.fetchone()
if not pc:
errors += 1
if errors <= 5:
print(f" ⚠️ PC '{pc_hostname}' not found for machine {machine_number}")
continue
pc_id = pc['machineid']
# Check if relationship already exists
cursor.execute(
"""SELECT relationshipid FROM machinerelationships
WHERE machineid = %s AND related_machineid = %s AND relationshiptypeid = %s""",
(pc_id, equipment_id, controls_type_id)
)
existing = cursor.fetchone()
if not existing:
# Create relationship: PC controls Equipment
cursor.execute(
"""INSERT INTO machinerelationships
(machineid, related_machineid, relationshiptypeid, isactive)
VALUES (%s, %s, %s, 1)""",
(pc_id, equipment_id, controls_type_id)
)
conn.commit()
if imported < 10:
print(f"{pc_hostname} controls {machine_number}")
imported += 1
else:
skipped += 1
if imported > 10:
print(f"... and {imported - 10} more")
if errors > 5:
print(f" ⚠️ ... and {errors - 5} more PCs not found")
print(f"\n✓ Imported {imported} control relationships, skipped {skipped} existing, {errors} errors")
return imported
def import_compliance_data(cursor, conn, rows):
"""Import compliance and asset criticality data"""
print("\n" + "="*70)
print("IMPORTING COMPLIANCE DATA")
print("="*70)
imported = 0
updated = 0
for row in rows:
if row.get('Row_Type') != 'Equipment':
continue
machine_number = row.get('Machine_Number', '').strip()
if not machine_number:
continue
# Get machine ID
cursor.execute("SELECT machineid FROM machines WHERE machinenumber = %s", (machine_number,))
machine = cursor.fetchone()
if not machine:
continue
machine_id = machine['machineid']
# Get compliance data from inventory
third_party_managed = row.get('3rd Party (Other) Managed (Y/N)', '').strip()
third_party_manager = row.get('3rd Party Manager', '').strip()
ot_environment = row.get('OT Environment', '').strip()
dod_asset_type = row.get('DoD Asset Type', '').strip()
# Map third party managed to enum
third_party_enum = None
if third_party_managed.upper() == 'Y':
third_party_enum = 'Yes'
elif third_party_managed.upper() == 'N':
third_party_enum = 'No'
else:
third_party_enum = 'NA'
# Check if compliance record exists
cursor.execute("SELECT complianceid FROM compliance WHERE machineid = %s", (machine_id,))
existing = cursor.fetchone()
if existing:
# Update existing record
cursor.execute(
"""UPDATE compliance SET
is_third_party_managed = %s,
third_party_manager = %s,
ot_asset_system = %s,
ot_asset_device_type = %s,
lastupdated = NOW()
WHERE complianceid = %s""",
(third_party_enum, third_party_manager or None,
ot_environment or None, dod_asset_type or None,
existing['complianceid'])
)
updated += 1
else:
# Insert new compliance record
cursor.execute(
"""INSERT INTO compliance
(machineid, is_third_party_managed, third_party_manager,
ot_asset_system, ot_asset_device_type)
VALUES (%s, %s, %s, %s, %s)""",
(machine_id, third_party_enum, third_party_manager or None,
ot_environment or None, dod_asset_type or None)
)
imported += 1
conn.commit()
print(f"✓ Imported {imported} new compliance records, updated {updated} existing")
return imported + updated
def import_security_scans(cursor, conn, rows):
"""Import security scan data"""
print("\n" + "="*70)
print("IMPORTING SECURITY SCAN DATA")
print("="*70)
imported = 0
for row in rows:
if row.get('Row_Type') != 'Equipment':
continue
machine_number = row.get('Machine_Number', '').strip()
scan_date_str = row.get('Security_Scan_Date', '').strip()
scan_result = row.get('Security_Scan_Result', '').strip()
if not machine_number or not scan_date_str:
continue
# Get machine ID
cursor.execute("SELECT machineid FROM machines WHERE machinenumber = %s", (machine_number,))
machine = cursor.fetchone()
if not machine:
continue
machine_id = machine['machineid']
# Parse scan date
try:
scan_date = datetime.strptime(scan_date_str, '%Y-%m-%d')
except:
try:
scan_date = datetime.strptime(scan_date_str, '%m/%d/%Y')
except:
continue
# Map scan result to enum
result_map = {
'PASS': 'Pass',
'FAIL': 'Fail',
'WARNING': 'Warning',
'INFO': 'Info'
}
mapped_result = result_map.get(scan_result.upper(), 'Info') if scan_result else 'Info'
# Check if this scan already exists
cursor.execute(
"""SELECT scanid FROM compliancescans
WHERE machineid = %s AND scan_date = %s""",
(machine_id, scan_date)
)
existing = cursor.fetchone()
if not existing:
# Insert new scan record
cursor.execute(
"""INSERT INTO compliancescans
(machineid, scan_date, scan_result, scan_details, scan_name)
VALUES (%s, %s, %s, %s, %s)""",
(machine_id, scan_date, mapped_result,
f"Imported from inventory on {datetime.now().strftime('%Y-%m-%d')}",
'Inventory Import Scan')
)
conn.commit()
imported += 1
print(f"✓ Imported {imported} security scan records")
return imported
def main():
"""Main import process"""
print("="*70)
print("ENHANCED INVENTORY DATA IMPORT")
print("Importing: MAC addresses, PC-to-machine relationships,")
print(" compliance data, and security scans")
print("="*70)
print()
# Connect to database
conn = connect_db()
cursor = conn.cursor()
# Read CSV file
csv_file = '/tmp/inventory_restructured.csv'
print(f"📄 Reading inventory file: {csv_file}")
try:
with open(csv_file, 'r', encoding='utf-8') as f:
reader = csv.DictReader(f)
rows = list(reader)
print(f"✓ Loaded {len(rows)} rows from inventory")
print()
except Exception as e:
print(f"✗ Failed to read CSV file: {e}")
conn.close()
sys.exit(1)
# Import each data type
mac_count = import_mac_addresses(cursor, conn, rows)
relationship_count = import_pc_machine_relationships(cursor, conn, rows)
compliance_count = import_compliance_data(cursor, conn, rows)
scan_count = import_security_scans(cursor, conn, rows)
# Summary
print("\n" + "="*70)
print("IMPORT SUMMARY")
print("="*70)
print(f"MAC addresses imported: {mac_count}")
print(f"PC-to-machine relationships: {relationship_count}")
print(f"Compliance records: {compliance_count}")
print(f"Security scan records: {scan_count}")
print(f"Total records created: {mac_count + relationship_count + compliance_count + scan_count}")
print()
# Final verification queries
print("="*70)
print("VERIFICATION")
print("="*70)
cursor.execute(
"""SELECT COUNT(*) as count FROM communications c
JOIN machines m ON c.machineid = m.machineid
WHERE m.pctypeid IS NULL"""
)
equipment_comms = cursor.fetchone()['count']
print(f"Equipment with communications: {equipment_comms}")
cursor.execute(
"""SELECT COUNT(*) as count FROM machinerelationships mr
JOIN relationshiptypes rt ON mr.relationshiptypeid = rt.relationshiptypeid
WHERE rt.relationshiptype = 'Controls'"""
)
control_relationships = cursor.fetchone()['count']
print(f"PC control relationships: {control_relationships}")
cursor.execute("SELECT COUNT(*) as count FROM compliance WHERE is_third_party_managed IS NOT NULL")
third_party_count = cursor.fetchone()['count']
print(f"Machines with compliance data: {third_party_count}")
cursor.execute("SELECT COUNT(*) as count FROM compliancescans")
total_scans = cursor.fetchone()['count']
print(f"Total security scans: {total_scans}")
print()
# Close connection
cursor.close()
conn.close()
print("✓ Enhanced import complete!")
if __name__ == '__main__':
main()

View File

@@ -0,0 +1,94 @@
-- =====================================================
-- SCRIPT 01: Create Network Device Machine Types
-- =====================================================
-- Date: 2025-11-10
-- Purpose: Add machinetypes for network infrastructure devices
-- Part of: Phase 3 Migration (Network Devices → machines table)
-- Status: REVERSIBLE (see ROLLBACK script)
-- Estimated Time: < 1 minute
-- =====================================================
USE shopdb;
SET SQL_SAFE_UPDATES = 0;
-- =====================================================
-- STEP 1: Add Network Device Machine Types
-- =====================================================
SELECT '========================================' AS '';
SELECT 'Phase 3 Migration - Script 01' AS '';
SELECT 'Creating Network Device Machine Types' AS '';
SELECT '========================================' AS '';
-- Insert new machinetypes for network infrastructure
-- Skipping machinetypeid 30-36 if they already exist
INSERT INTO machinetypes (machinetypeid, machinetype, machinedescription, isactive)
VALUES
(30, 'Server', 'Physical or virtual server', 1),
(31, 'Switch', 'Network switch', 1),
(32, 'Camera', 'IP camera or security camera', 1),
(33, 'Access Point', 'Wireless access point', 1),
(34, 'IDF', 'Intermediate Distribution Frame / Network closet', 1),
(35, 'Router', 'Network router', 1),
(36, 'Firewall', 'Network firewall / Security appliance', 1)
ON DUPLICATE KEY UPDATE
machinetype = VALUES(machinetype),
machinedescription = VALUES(machinedescription);
-- =====================================================
-- STEP 2: Verify Creation
-- =====================================================
SELECT '✓ Network device machinetypes created' AS status;
SELECT
machinetypeid,
machinetype,
machinedescription,
isactive
FROM machinetypes
WHERE machinetypeid BETWEEN 30 AND 36
ORDER BY machinetypeid;
-- =====================================================
-- STEP 3: Show Full Machine Type Structure
-- =====================================================
SELECT '========================================' AS '';
SELECT 'Current Machine Type Structure:' AS '';
SELECT '========================================' AS '';
SELECT
CASE
WHEN machinetypeid BETWEEN 1 AND 24 THEN '1. Equipment'
WHEN machinetypeid BETWEEN 25 AND 29 THEN '2. PCs'
WHEN machinetypeid BETWEEN 30 AND 36 THEN '3. Network Devices'
ELSE '4. Other'
END AS group_name,
COUNT(*) AS type_count
FROM machinetypes
WHERE isactive = 1
GROUP BY group_name
ORDER BY group_name;
SELECT '========================================' AS '';
SELECT '✓ Script 01 completed successfully' AS status;
SELECT 'Next: Run 02_migrate_servers_to_machines.sql' AS next_step;
SELECT '========================================' AS '';
SET SQL_SAFE_UPDATES = 1;
-- =====================================================
-- NOTES
-- =====================================================
-- Machine Type ID Ranges:
-- 1-24: Equipment (CNC machines, mills, lathes, etc.)
-- 25-29: PCs (Standard, Shopfloor, Engineer, Server, Laptop)
-- 30-36: Network Devices (Server, Switch, Camera, AP, IDF, Router, Firewall)
--
-- Filtering Examples:
-- - All equipment: WHERE pctypeid IS NULL AND machinetypeid BETWEEN 1 AND 24
-- - All PCs: WHERE pctypeid IS NOT NULL
-- - All network: WHERE pctypeid IS NULL AND machinetypeid BETWEEN 30 AND 36
-- - All servers: WHERE machinetypeid = 30
-- =====================================================

View File

@@ -0,0 +1,198 @@
-- =====================================================
-- SCRIPT 02: Migrate Servers to machines Table
-- =====================================================
-- Date: 2025-11-10
-- Purpose: Migrate all servers from servers table to machines table
-- Part of: Phase 3 Migration (Network Devices → machines table)
-- Status: REVERSIBLE (see ROLLBACK script)
-- Estimated Time: 1-2 minutes
-- =====================================================
USE shopdb;
SET SQL_SAFE_UPDATES = 0;
-- =====================================================
-- STEP 1: Pre-Migration Verification
-- =====================================================
SELECT '========================================' AS '';
SELECT 'Phase 3 Migration - Script 02' AS '';
SELECT 'Migrating Servers to machines Table' AS '';
SELECT '========================================' AS '';
-- Count servers to migrate
SELECT 'Pre-migration server count:' AS status, COUNT(*) AS server_count
FROM servers
WHERE isactive = 1;
-- Check for any conflicts
SELECT 'Checking for conflicts...' AS status;
SELECT COUNT(*) AS potential_conflicts
FROM servers s
WHERE EXISTS (
SELECT 1 FROM machines m
WHERE m.serialnumber = s.serialnumber
AND m.machinetypeid = 30
);
-- If conflicts found, show them
SELECT s.serverid, s.serialnumber, s.description
FROM servers s
WHERE EXISTS (
SELECT 1 FROM machines m
WHERE m.serialnumber = s.serialnumber
AND m.machinetypeid = 30
)
LIMIT 10;
-- =====================================================
-- STEP 2: Create Temporary Mapping Table
-- =====================================================
SELECT 'Creating server mapping table...' AS status;
CREATE TEMPORARY TABLE IF NOT EXISTS temp_server_mapping (
old_serverid INT,
new_machineid INT,
PRIMARY KEY (old_serverid)
);
-- =====================================================
-- STEP 3: Migrate Servers to machines Table
-- =====================================================
SELECT 'Migrating servers to machines table...' AS status;
INSERT INTO machines (
machinenumber,
alias,
modelnumberid,
machinetypeid,
pctypeid,
serialnumber,
machinenotes,
mapleft,
maptop,
isactive,
dateadded,
lastupdated
)
SELECT
-- Generate machinenumber: SERVER-{serverid} or use description
CASE
WHEN s.description IS NOT NULL AND s.description != ''
THEN CONCAT('SVR-', LPAD(s.serverid, 4, '0'))
ELSE CONCAT('SERVER-', s.serverid)
END AS machinenumber,
-- alias from description
COALESCE(s.description, '') AS alias,
-- modelnumberid
s.modelid AS modelnumberid,
-- machinetypeid = 30 (Server)
30 AS machinetypeid,
-- pctypeid = NULL (not a PC)
NULL AS pctypeid,
-- serialnumber
s.serialnumber,
-- machinenotes (empty for now)
'' AS machinenotes,
-- map coordinates (servers table doesn't have map fields)
NULL AS mapleft,
NULL AS maptop,
-- isactive
s.isactive,
-- dateadded - servers table doesn't have this column
NOW() AS dateadded,
-- lastupdated
NOW() AS lastupdated
FROM servers s
WHERE s.isactive = 1
AND NOT EXISTS (
-- Avoid duplicates if script run multiple times
SELECT 1 FROM machines m
WHERE m.serialnumber = s.serialnumber
AND m.machinetypeid = 30
);
-- =====================================================
-- STEP 4: Create Mapping from Old to New IDs
-- =====================================================
SELECT 'Creating ID mapping...' AS status;
INSERT INTO temp_server_mapping (old_serverid, new_machineid)
SELECT
s.serverid,
m.machineid
FROM servers s
JOIN machines m ON m.serialnumber = s.serialnumber AND m.machinetypeid = 30
WHERE s.isactive = 1;
-- =====================================================
-- STEP 5: Verification
-- =====================================================
SELECT '========================================' AS '';
SELECT 'Migration Verification:' AS '';
SELECT '========================================' AS '';
-- Count migrated servers
SELECT 'Servers in machines table:' AS status, COUNT(*) AS migrated_count
FROM machines
WHERE machinetypeid = 30;
-- Show sample of migrated servers
SELECT 'Sample migrated servers:' AS status;
SELECT
m.machineid,
m.machinenumber,
m.alias,
m.serialnumber,
mo.modelnumber,
v.vendor
FROM machines m
LEFT JOIN models mo ON m.modelnumberid = mo.modelnumberid
LEFT JOIN vendors v ON mo.vendorid = v.vendorid
WHERE m.machinetypeid = 30
ORDER BY m.machineid
LIMIT 10;
-- Show mapping stats
SELECT 'ID mapping created:' AS status, COUNT(*) AS mapping_count
FROM temp_server_mapping;
SELECT '========================================' AS '';
SELECT '✓ Script 02 completed successfully' AS status;
SELECT 'Next: Run 03_migrate_switches_to_machines.sql' AS next_step;
SELECT '========================================' AS '';
SET SQL_SAFE_UPDATES = 1;
-- =====================================================
-- NOTES
-- =====================================================
-- Old servers table is NOT dropped - kept for rollback safety
-- Mapping table temp_server_mapping persists for this session
-- Will be used by later scripts to migrate communications and relationships
--
-- To verify a specific server migrated:
-- SELECT * FROM machines WHERE machinetypeid = 30 AND serialnumber = 'YOUR_SERIAL';
--
-- To see old vs new:
-- SELECT s.*, m.machineid, m.machinenumber
-- FROM servers s
-- JOIN machines m ON s.serialnumber = m.serialnumber AND m.machinetypeid = 30
-- WHERE s.serverid = YOUR_SERVERID;
-- =====================================================

View File

@@ -0,0 +1,190 @@
-- =====================================================
-- SCRIPT 03: Migrate Switches to machines Table
-- =====================================================
-- Date: 2025-11-10
-- Purpose: Migrate all switches from switches table to machines table
-- Part of: Phase 3 Migration (Network Devices → machines table)
-- Status: REVERSIBLE (see ROLLBACK script)
-- Estimated Time: 1-2 minutes
-- =====================================================
USE shopdb;
SET SQL_SAFE_UPDATES = 0;
-- =====================================================
-- STEP 1: Pre-Migration Verification
-- =====================================================
SELECT '========================================' AS '';
SELECT 'Phase 3 Migration - Script 03' AS '';
SELECT 'Migrating Switches to machines Table' AS '';
SELECT '========================================' AS '';
-- Count switches to migrate
SELECT 'Pre-migration switch count:' AS status, COUNT(*) AS switch_count
FROM switches
WHERE isactive = 1;
-- Check for any conflicts
SELECT 'Checking for conflicts...' AS status;
SELECT COUNT(*) AS potential_conflicts
FROM switches s
WHERE EXISTS (
SELECT 1 FROM machines m
WHERE m.serialnumber = s.serialnumber
AND m.machinetypeid = 31
);
-- =====================================================
-- STEP 2: Create Temporary Mapping Table
-- =====================================================
SELECT 'Creating switch mapping table...' AS status;
CREATE TEMPORARY TABLE IF NOT EXISTS temp_switch_mapping (
old_switchid INT,
new_machineid INT,
PRIMARY KEY (old_switchid)
);
-- =====================================================
-- STEP 3: Migrate Switches to machines Table
-- =====================================================
SELECT 'Migrating switches to machines table...' AS status;
INSERT INTO machines (
machinenumber,
alias,
modelnumberid,
machinetypeid,
pctypeid,
serialnumber,
machinenotes,
mapleft,
maptop,
isactive,
dateadded,
lastupdated
)
SELECT
-- Generate machinenumber: SW-{switchid} or use description
CASE
WHEN s.description IS NOT NULL AND s.description != ''
THEN CONCAT('SW-', LPAD(s.switchid, 4, '0'))
ELSE CONCAT('SWITCH-', s.switchid)
END AS machinenumber,
-- alias from description
COALESCE(s.description, '') AS alias,
-- modelnumberid
s.modelid AS modelnumberid,
-- machinetypeid = 31 (Switch)
31 AS machinetypeid,
-- pctypeid = NULL (not a PC)
NULL AS pctypeid,
-- serialnumber
s.serialnumber,
-- machinenotes (empty for now)
'' AS machinenotes,
-- map coordinates
COALESCE(s.mapleft, 50) AS mapleft,
COALESCE(s.maptop, 50) AS maptop,
-- isactive
s.isactive,
-- dateadded - preserve or use current time
NOW() AS dateadded,
-- lastupdated
NOW() AS lastupdated
FROM switches s
WHERE s.isactive = 1
AND NOT EXISTS (
-- Avoid duplicates if script run multiple times
SELECT 1 FROM machines m
WHERE m.serialnumber = s.serialnumber
AND m.machinetypeid = 31
);
-- =====================================================
-- STEP 4: Create Mapping from Old to New IDs
-- =====================================================
SELECT 'Creating ID mapping...' AS status;
INSERT INTO temp_switch_mapping (old_switchid, new_machineid)
SELECT
s.switchid,
m.machineid
FROM switches s
JOIN machines m ON m.serialnumber = s.serialnumber AND m.machinetypeid = 31
WHERE s.isactive = 1;
-- =====================================================
-- STEP 5: Verification
-- =====================================================
SELECT '========================================' AS '';
SELECT 'Migration Verification:' AS '';
SELECT '========================================' AS '';
-- Count migrated switches
SELECT 'Switches in machines table:' AS status, COUNT(*) AS migrated_count
FROM machines
WHERE machinetypeid = 31;
-- Show sample of migrated switches
SELECT 'Sample migrated switches:' AS status;
SELECT
m.machineid,
m.machinenumber,
m.alias,
m.serialnumber,
mo.modelnumber,
v.vendor
FROM machines m
LEFT JOIN models mo ON m.modelnumberid = mo.modelnumberid
LEFT JOIN vendors v ON mo.vendorid = v.vendorid
WHERE m.machinetypeid = 31
ORDER BY m.machineid
LIMIT 10;
-- Show mapping stats
SELECT 'ID mapping created:' AS status, COUNT(*) AS mapping_count
FROM temp_switch_mapping;
-- Summary of all network devices so far
SELECT 'Current network device totals:' AS status;
SELECT
mt.machinetype,
COUNT(*) AS count
FROM machines m
JOIN machinetypes mt ON m.machinetypeid = mt.machinetypeid
WHERE mt.machinetypeid BETWEEN 30 AND 36
GROUP BY mt.machinetype
ORDER BY mt.machinetypeid;
SELECT '========================================' AS '';
SELECT '✓ Script 03 completed successfully' AS status;
SELECT 'Next: Run 04_migrate_cameras_to_machines.sql' AS next_step;
SELECT '========================================' AS '';
SET SQL_SAFE_UPDATES = 1;
-- =====================================================
-- NOTES
-- =====================================================
-- Old switches table is NOT dropped - kept for rollback safety
-- Mapping table temp_switch_mapping persists for this session
-- Will be used by later scripts to migrate communications and relationships
-- =====================================================

View File

@@ -0,0 +1,191 @@
-- =====================================================
-- SCRIPT 04: Migrate Cameras to machines Table
-- =====================================================
-- Date: 2025-11-10
-- Purpose: Migrate all cameras from cameras table to machines table
-- Part of: Phase 3 Migration (Network Devices → machines table)
-- Status: REVERSIBLE (see ROLLBACK script)
-- Estimated Time: 1-2 minutes
-- =====================================================
USE shopdb;
SET SQL_SAFE_UPDATES = 0;
-- =====================================================
-- STEP 1: Pre-Migration Verification
-- =====================================================
SELECT '========================================' AS '';
SELECT 'Phase 3 Migration - Script 04' AS '';
SELECT 'Migrating Cameras to machines Table' AS '';
SELECT '========================================' AS '';
-- Count cameras to migrate
SELECT 'Pre-migration camera count:' AS status, COUNT(*) AS camera_count
FROM cameras
WHERE isactive = 1;
-- Check for any conflicts
SELECT 'Checking for conflicts...' AS status;
SELECT COUNT(*) AS potential_conflicts
FROM cameras c
WHERE EXISTS (
SELECT 1 FROM machines m
WHERE m.serialnumber = c.serialnumber
AND m.machinetypeid = 32
);
-- =====================================================
-- STEP 2: Create Temporary Mapping Table
-- =====================================================
SELECT 'Creating camera mapping table...' AS status;
CREATE TEMPORARY TABLE IF NOT EXISTS temp_camera_mapping (
old_cameraid INT,
new_machineid INT,
PRIMARY KEY (old_cameraid)
);
-- =====================================================
-- STEP 3: Migrate Cameras to machines Table
-- =====================================================
SELECT 'Migrating cameras to machines table...' AS status;
INSERT INTO machines (
machinenumber,
alias,
modelnumberid,
machinetypeid,
pctypeid,
serialnumber,
machinenotes,
mapleft,
maptop,
isactive,
dateadded,
lastupdated
)
SELECT
-- Generate machinenumber: CAM-{cameraid} or use description
CASE
WHEN c.description IS NOT NULL AND c.description != ''
THEN CONCAT('CAM-', LPAD(c.cameraid, 4, '0'))
ELSE CONCAT('CAMERA-', c.cameraid)
END AS machinenumber,
-- alias from description
COALESCE(c.description, '') AS alias,
-- modelnumberid
c.modelid AS modelnumberid,
-- machinetypeid = 32 (Camera)
32 AS machinetypeid,
-- pctypeid = NULL (not a PC)
NULL AS pctypeid,
-- serialnumber
c.serialnumber,
-- machinenotes (empty for now)
'' AS machinenotes,
-- map coordinates
COALESCE(c.mapleft, 50) AS mapleft,
COALESCE(c.maptop, 50) AS maptop,
-- isactive
c.isactive,
-- dateadded - preserve or use current time
NOW() AS dateadded,
-- lastupdated
NOW() AS lastupdated
FROM cameras c
WHERE c.isactive = 1
AND NOT EXISTS (
-- Avoid duplicates if script run multiple times
SELECT 1 FROM machines m
WHERE m.serialnumber = c.serialnumber
AND m.machinetypeid = 32
);
-- =====================================================
-- STEP 4: Create Mapping from Old to New IDs
-- =====================================================
SELECT 'Creating ID mapping...' AS status;
INSERT INTO temp_camera_mapping (old_cameraid, new_machineid)
SELECT
c.cameraid,
m.machineid
FROM cameras c
JOIN machines m ON m.serialnumber = c.serialnumber AND m.machinetypeid = 32
WHERE c.isactive = 1;
-- =====================================================
-- STEP 5: Verification
-- =====================================================
SELECT '========================================' AS '';
SELECT 'Migration Verification:' AS '';
SELECT '========================================' AS '';
-- Count migrated cameras
SELECT 'Cameras in machines table:' AS status, COUNT(*) AS migrated_count
FROM machines
WHERE machinetypeid = 32;
-- Show sample of migrated cameras
SELECT 'Sample migrated cameras:' AS status;
SELECT
m.machineid,
m.machinenumber,
m.alias,
m.serialnumber,
mo.modelnumber,
v.vendor
FROM machines m
LEFT JOIN models mo ON m.modelnumberid = mo.modelnumberid
LEFT JOIN vendors v ON mo.vendorid = v.vendorid
WHERE m.machinetypeid = 32
ORDER BY m.machineid
LIMIT 10;
-- Show mapping stats
SELECT 'ID mapping created:' AS status, COUNT(*) AS mapping_count
FROM temp_camera_mapping;
-- Summary of all network devices so far
SELECT 'Current network device totals:' AS status;
SELECT
mt.machinetype,
COUNT(*) AS count
FROM machines m
JOIN machinetypes mt ON m.machinetypeid = mt.machinetypeid
WHERE mt.machinetypeid BETWEEN 30 AND 36
GROUP BY mt.machinetype
ORDER BY mt.machinetypeid;
SELECT '========================================' AS '';
SELECT '✓ Script 04 completed successfully' AS status;
SELECT 'Next: Run 07_migrate_network_communications.sql' AS next_step;
SELECT 'Note: Skipping 05/06 if accesspoints/idfs tables do not exist' AS note;
SELECT '========================================' AS '';
SET SQL_SAFE_UPDATES = 1;
-- =====================================================
-- NOTES
-- =====================================================
-- Old cameras table is NOT dropped - kept for rollback safety
-- Mapping table temp_camera_mapping persists for this session
-- Will be used by later scripts to migrate communications and relationships
-- =====================================================

View File

@@ -0,0 +1,219 @@
-- =====================================================
-- SCRIPT 07: Migrate Network Communications
-- =====================================================
-- Date: 2025-11-10
-- Purpose: Migrate IP addresses from device tables to communications table
-- Part of: Phase 3 Migration (Network Devices → machines table)
-- Status: REVERSIBLE (see ROLLBACK script)
-- Estimated Time: 1-2 minutes
-- =====================================================
USE shopdb;
SET SQL_SAFE_UPDATES = 0;
-- =====================================================
-- STEP 1: Pre-Migration Verification
-- =====================================================
SELECT '========================================' AS '';
SELECT 'Phase 3 Migration - Script 07' AS '';
SELECT 'Migrating Network Device Communications' AS '';
SELECT '========================================' AS '';
-- Count devices with IP addresses
SELECT 'Servers with IPs:' AS device_type, COUNT(*) AS count
FROM servers WHERE ipaddress IS NOT NULL AND ipaddress != ''
UNION ALL
SELECT 'Switches with IPs:', COUNT(*)
FROM switches WHERE ipaddress IS NOT NULL AND ipaddress != ''
UNION ALL
SELECT 'Cameras with IPs:', COUNT(*)
FROM cameras WHERE ipaddress IS NOT NULL AND ipaddress != '';
-- =====================================================
-- STEP 2: Migrate Server IP Addresses
-- =====================================================
SELECT 'Migrating server IP addresses...' AS status;
INSERT INTO communications (
machineid,
comstypeid,
address,
macaddress,
isprimary,
isactive,
description
)
SELECT
m.machineid,
1 AS comstypeid, -- IP type
s.ipaddress AS address,
NULL AS macaddress, -- Servers table doesn't have MAC
1 AS isprimary,
1 AS isactive,
'Migrated from servers table' AS description
FROM servers s
JOIN machines m ON m.serialnumber = s.serialnumber AND m.machinetypeid = 30
WHERE s.ipaddress IS NOT NULL
AND s.ipaddress != ''
AND s.isactive = 1
AND NOT EXISTS (
-- Avoid duplicates
SELECT 1 FROM communications c
WHERE c.machineid = m.machineid
AND c.address = s.ipaddress
);
SELECT 'Server IPs migrated:' AS status, ROW_COUNT() AS migrated_count;
-- =====================================================
-- STEP 3: Migrate Switch IP Addresses
-- =====================================================
SELECT 'Migrating switch IP addresses...' AS status;
INSERT INTO communications (
machineid,
comstypeid,
address,
macaddress,
isprimary,
isactive,
description
)
SELECT
m.machineid,
1 AS comstypeid, -- IP type
s.ipaddress AS address,
NULL AS macaddress, -- Switches table doesn't have MAC
1 AS isprimary,
1 AS isactive,
'Migrated from switches table' AS description
FROM switches s
JOIN machines m ON m.serialnumber = s.serialnumber AND m.machinetypeid = 31
WHERE s.ipaddress IS NOT NULL
AND s.ipaddress != ''
AND s.isactive = 1
AND NOT EXISTS (
-- Avoid duplicates
SELECT 1 FROM communications c
WHERE c.machineid = m.machineid
AND c.address = s.ipaddress
);
SELECT 'Switch IPs migrated:' AS status, ROW_COUNT() AS migrated_count;
-- =====================================================
-- STEP 4: Migrate Camera IP Addresses
-- =====================================================
SELECT 'Migrating camera IP addresses...' AS status;
INSERT INTO communications (
machineid,
comstypeid,
address,
macaddress,
isprimary,
isactive,
description
)
SELECT
m.machineid,
1 AS comstypeid, -- IP type
c.ipaddress AS address,
NULL AS macaddress, -- Cameras table doesn't have MAC
1 AS isprimary,
1 AS isactive,
'Migrated from cameras table' AS description
FROM cameras c
JOIN machines m ON m.serialnumber = c.serialnumber AND m.machinetypeid = 32
WHERE c.ipaddress IS NOT NULL
AND c.ipaddress != ''
AND c.isactive = 1
AND NOT EXISTS (
-- Avoid duplicates
SELECT 1 FROM communications comm
WHERE comm.machineid = m.machineid
AND comm.address = c.ipaddress
);
SELECT 'Camera IPs migrated:' AS status, ROW_COUNT() AS migrated_count;
-- =====================================================
-- STEP 5: Verification
-- =====================================================
SELECT '========================================' AS '';
SELECT 'Migration Verification:' AS '';
SELECT '========================================' AS '';
-- Count communications by device type
SELECT 'Communications by device type:' AS status;
SELECT
mt.machinetype,
COUNT(DISTINCT m.machineid) AS total_devices,
COUNT(DISTINCT c.machineid) AS devices_with_ip,
COUNT(c.comid) AS total_communications
FROM machines m
JOIN machinetypes mt ON m.machinetypeid = mt.machinetypeid
LEFT JOIN communications c ON m.machineid = c.machineid AND c.comstypeid = 1
WHERE mt.machinetypeid BETWEEN 30 AND 36
GROUP BY mt.machinetype
ORDER BY mt.machinetypeid;
-- Show sample communications
SELECT 'Sample network device communications:' AS status;
SELECT
m.machinenumber,
mt.machinetype,
c.address AS ip_address,
c.isprimary,
c.description
FROM machines m
JOIN machinetypes mt ON m.machinetypeid = mt.machinetypeid
JOIN communications c ON m.machineid = c.machineid
WHERE mt.machinetypeid BETWEEN 30 AND 36
AND c.comstypeid = 1
ORDER BY mt.machinetypeid, m.machinenumber
LIMIT 20;
-- Check for devices without IPs (expected for some)
SELECT 'Devices without IP addresses:' AS status;
SELECT
mt.machinetype,
COUNT(*) AS count_without_ip
FROM machines m
JOIN machinetypes mt ON m.machinetypeid = mt.machinetypeid
WHERE mt.machinetypeid BETWEEN 30 AND 36
AND NOT EXISTS (
SELECT 1 FROM communications c
WHERE c.machineid = m.machineid
AND c.comstypeid = 1
)
GROUP BY mt.machinetype;
SELECT '========================================' AS '';
SELECT '✓ Script 07 completed successfully' AS status;
SELECT 'Next: Run 08_create_network_relationship_types.sql' AS next_step;
SELECT '========================================' AS '';
SET SQL_SAFE_UPDATES = 1;
-- =====================================================
-- NOTES
-- =====================================================
-- All IP addresses migrated to communications table with comstypeid = 1 (IP)
-- isprimary = 1 for all migrated IPs (assumed primary interface)
-- MAC addresses not migrated (old tables don't have them)
--
-- To verify a specific device's IP:
-- SELECT m.machinenumber, c.address
-- FROM machines m
-- JOIN communications c ON m.machineid = c.machineid
-- WHERE m.machinetypeid = 30 AND m.machinenumber = 'SVR-0001';
-- =====================================================

View File

@@ -0,0 +1,125 @@
-- =====================================================
-- SCRIPT 08: Create Network Relationship Types
-- =====================================================
-- Date: 2025-11-10
-- Purpose: Add new relationship types for network infrastructure
-- Part of: Phase 3 Migration (Network Devices → machines table)
-- Status: REVERSIBLE (see ROLLBACK script)
-- Estimated Time: < 1 minute
-- =====================================================
USE shopdb;
SET SQL_SAFE_UPDATES = 0;
-- =====================================================
-- STEP 1: Show Existing Relationship Types
-- =====================================================
SELECT '========================================' AS '';
SELECT 'Phase 3 Migration - Script 08' AS '';
SELECT 'Creating Network Relationship Types' AS '';
SELECT '========================================' AS '';
SELECT 'Existing relationship types:' AS status;
SELECT
relationshiptypeid,
relationshiptype,
description,
displayorder
FROM relationshiptypes
WHERE isactive = 1
ORDER BY relationshiptypeid;
-- =====================================================
-- STEP 2: Add New Network Relationship Types
-- =====================================================
SELECT 'Adding new network relationship types...' AS status;
-- Insert new relationship types
-- Using explicit IDs to maintain consistency
INSERT INTO relationshiptypes (relationshiptype, description, isactive)
VALUES
('Connected To', 'Device physically connected to network infrastructure', 1),
('Powered By', 'Device powered by this power source', 1),
('Mounted In', 'Device mounted in this rack or cabinet', 1),
('Feeds Video To', 'Camera feeds video stream to this server/NVR', 1),
('Provides Network', 'Infrastructure provides network connectivity to device', 1)
ON DUPLICATE KEY UPDATE
description = VALUES(description);
-- =====================================================
-- STEP 3: Verification
-- =====================================================
SELECT '========================================' AS '';
SELECT 'Relationship Types After Migration:' AS '';
SELECT '========================================' AS '';
SELECT
relationshiptypeid,
relationshiptype,
description,
displayorder,
CASE
WHEN relationshiptypeid <= 6 THEN 'Legacy'
ELSE 'Network (New)'
END AS category
FROM relationshiptypes
WHERE isactive = 1
ORDER BY relationshiptypeid;
-- Show counts
SELECT 'Total relationship types:' AS status, COUNT(*) AS total_count
FROM relationshiptypes
WHERE isactive = 1;
SELECT '========================================' AS '';
SELECT '✓ Script 08 completed successfully' AS status;
SELECT 'Next: Run 09_update_views_for_network_devices.sql' AS next_step;
SELECT '========================================' AS '';
SET SQL_SAFE_UPDATES = 1;
-- =====================================================
-- NOTES
-- =====================================================
-- New Relationship Types Added:
--
-- 1. Connected To (directional)
-- - Use for: Camera → Switch, Switch → IDF, etc.
-- - Example: CAM-0001 is Connected To SW-Core-01
--
-- 2. Powered By (directional)
-- - Use for: Device → Power Source
-- - Example: SW-Floor-01 Powered By UPS-Room-A
--
-- 3. Mounted In (directional)
-- - Use for: Device → Rack/Cabinet
-- - Example: SVR-0001 Mounted In Rack-A-01
--
-- 4. Feeds Video To (directional)
-- - Use for: Camera → Server/NVR
-- - Example: CAM-Shop-01 Feeds Video To SVR-Security-01
--
-- 5. Provides Network (directional)
-- - Use for: Infrastructure → Device
-- - Example: IDF-Building-A Provides Network to SW-Floor-02
--
-- Usage Examples:
--
-- Camera connected to switch:
-- INSERT INTO machinerelationships (machineid, related_machineid, relationshiptypeid)
-- SELECT
-- (SELECT machineid FROM machines WHERE machinenumber = 'CAM-Shop-01'),
-- (SELECT machineid FROM machines WHERE machinenumber = 'SW-Core-01'),
-- (SELECT relationshiptypeid FROM relationshiptypes WHERE relationshiptype = 'Connected To');
--
-- Switch connected to IDF:
-- INSERT INTO machinerelationships (machineid, related_machineid, relationshiptypeid)
-- SELECT
-- (SELECT machineid FROM machines WHERE machinenumber = 'SW-Core-01'),
-- (SELECT machineid FROM machines WHERE machinenumber = 'IDF-Building-A'),
-- (SELECT relationshiptypeid FROM relationshiptypes WHERE relationshiptype = 'Connected To');
-- =====================================================

View File

@@ -0,0 +1,231 @@
-- =====================================================
-- SCRIPT 09: Update Views for Network Devices
-- =====================================================
-- Date: 2025-11-10
-- Purpose: Create/update views to include network devices
-- Part of: Phase 3 Migration (Network Devices → machines table)
-- Status: REVERSIBLE (see ROLLBACK script)
-- Estimated Time: < 1 minute
-- =====================================================
USE shopdb;
SET SQL_SAFE_UPDATES = 0;
-- =====================================================
-- STEP 1: Create Unified Infrastructure View
-- =====================================================
SELECT '========================================' AS '';
SELECT 'Phase 3 Migration - Script 09' AS '';
SELECT 'Creating/Updating Views for Network Devices' AS '';
SELECT '========================================' AS '';
SELECT 'Creating vw_all_infrastructure view...' AS status;
-- Drop if exists
DROP VIEW IF EXISTS vw_all_infrastructure;
-- Create comprehensive view of all infrastructure
CREATE VIEW vw_all_infrastructure AS
SELECT
m.machineid,
m.machinenumber,
m.alias,
mt.machinetype,
mo.modelnumber,
v.vendor,
m.serialnumber,
c.address AS ipaddress,
c.macaddress,
m.mapleft,
m.maptop,
m.dateadded,
m.lastupdated,
CASE
WHEN m.pctypeid IS NOT NULL THEN 'PC'
WHEN mt.machinetypeid BETWEEN 30 AND 36 THEN 'Network Device'
WHEN mt.machinetypeid BETWEEN 1 AND 24 THEN 'Equipment'
ELSE 'Other'
END AS device_category,
m.isactive
FROM machines m
LEFT JOIN machinetypes mt ON m.machinetypeid = mt.machinetypeid
LEFT JOIN models mo ON m.modelnumberid = mo.modelnumberid
LEFT JOIN vendors v ON mo.vendorid = v.vendorid
LEFT JOIN communications c ON m.machineid = c.machineid AND c.isprimary = 1 AND c.comstypeid = 1
WHERE m.isactive = 1;
SELECT '✓ vw_all_infrastructure created' AS status;
-- =====================================================
-- STEP 2: Create Network Devices Summary View
-- =====================================================
SELECT 'Creating vw_network_devices_summary view...' AS status;
-- Drop if exists
DROP VIEW IF EXISTS vw_network_devices_summary;
-- Create network devices specific view
CREATE VIEW vw_network_devices_summary AS
SELECT
m.machineid,
m.machinenumber,
m.alias,
mt.machinetype,
mo.modelnumber,
v.vendor,
m.serialnumber,
c.address AS ipaddress,
m.mapleft,
m.maptop,
-- Count relationships
(SELECT COUNT(*)
FROM machinerelationships mr
WHERE mr.machineid = m.machineid AND mr.isactive = 1
) AS outgoing_relationships,
(SELECT COUNT(*)
FROM machinerelationships mr
WHERE mr.related_machineid = m.machineid AND mr.isactive = 1
) AS incoming_relationships,
m.isactive
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.comstypeid = 1
WHERE mt.machinetypeid BETWEEN 30 AND 36
AND m.isactive = 1;
SELECT '✓ vw_network_devices_summary created' AS status;
-- =====================================================
-- STEP 3: Create Network Topology View
-- =====================================================
SELECT 'Creating vw_network_topology view...' AS status;
-- Drop if exists
DROP VIEW IF EXISTS vw_network_topology;
-- Create topology view showing device connections
CREATE VIEW vw_network_topology AS
SELECT
m1.machineid AS source_machineid,
m1.machinenumber AS source_device,
mt1.machinetype AS source_type,
m2.machineid AS target_machineid,
m2.machinenumber AS target_device,
mt2.machinetype AS target_type,
rt.relationshiptype,
mr.relationship_notes,
c1.address AS source_ip,
c2.address AS target_ip
FROM machinerelationships mr
JOIN relationshiptypes rt ON mr.relationshiptypeid = rt.relationshiptypeid
JOIN machines m1 ON mr.machineid = m1.machineid
JOIN machines m2 ON mr.related_machineid = m2.machineid
JOIN machinetypes mt1 ON m1.machinetypeid = mt1.machinetypeid
JOIN machinetypes mt2 ON m2.machinetypeid = mt2.machinetypeid
LEFT JOIN communications c1 ON m1.machineid = c1.machineid AND c1.isprimary = 1
LEFT JOIN communications c2 ON m2.machineid = c2.machineid AND c2.isprimary = 1
WHERE mr.isactive = 1
AND (mt1.machinetypeid BETWEEN 30 AND 36 OR mt2.machinetypeid BETWEEN 30 AND 36);
SELECT '✓ vw_network_topology created' AS status;
-- =====================================================
-- STEP 4: Verification - Show View Samples
-- =====================================================
SELECT '========================================' AS '';
SELECT 'View Verification:' AS '';
SELECT '========================================' AS '';
-- Sample from all infrastructure view
SELECT 'Sample from vw_all_infrastructure:' AS status;
SELECT
machinenumber,
machinetype,
device_category,
vendor,
modelnumber,
ipaddress
FROM vw_all_infrastructure
LIMIT 15;
-- Sample from network devices summary
SELECT 'Sample from vw_network_devices_summary:' AS status;
SELECT
machinenumber,
machinetype,
vendor,
ipaddress,
outgoing_relationships,
incoming_relationships
FROM vw_network_devices_summary
LIMIT 10;
-- Device category counts
SELECT 'Device counts by category:' AS status;
SELECT
device_category,
COUNT(*) AS device_count
FROM vw_all_infrastructure
GROUP BY device_category
ORDER BY device_count DESC;
-- Network device counts by type
SELECT 'Network devices by type:' AS status;
SELECT
machinetype,
COUNT(*) AS count
FROM vw_network_devices_summary
GROUP BY machinetype
ORDER BY count DESC;
SELECT '========================================' AS '';
SELECT '✓ Script 09 completed successfully' AS status;
SELECT 'Next: Run VERIFY_PHASE3_MIGRATION.sql' AS next_step;
SELECT '========================================' AS '';
SET SQL_SAFE_UPDATES = 1;
-- =====================================================
-- NOTES
-- =====================================================
-- Views Created:
--
-- 1. vw_all_infrastructure
-- - Shows ALL machines (equipment, PCs, network devices)
-- - Includes device_category field for easy filtering
-- - Primary IP address included
--
-- 2. vw_network_devices_summary
-- - Network devices only (machinetypeid 30-36)
-- - Includes relationship counts
-- - Useful for network inventory
--
-- 3. vw_network_topology
-- - Shows all relationships involving network devices
-- - Includes both source and target device info
-- - Useful for network diagrams and topology mapping
--
-- Usage Examples:
--
-- All network devices:
-- SELECT * FROM vw_network_devices_summary;
--
-- All cameras with IPs:
-- SELECT * FROM vw_network_devices_summary WHERE machinetype = 'Camera';
--
-- Network connections:
-- SELECT * FROM vw_network_topology WHERE relationshiptype = 'Connected To';
--
-- All infrastructure by vendor:
-- SELECT vendor, device_category, COUNT(*) as count
-- FROM vw_all_infrastructure
-- GROUP BY vendor, device_category
-- ORDER BY vendor, device_category;
-- =====================================================

View File

@@ -0,0 +1,315 @@
# Phase 3 Migration: Network Devices to machines Table
**Created:** 2025-11-10
**Status:** Ready for Testing
**Follows:** Phase 2 (PC Migration - Completed Successfully)
---
## Overview
This migration consolidates all network infrastructure devices (servers, switches, cameras, access points, IDFs) into the unified `machines` table, completing the infrastructure unification started with Phase 2.
### What Gets Migrated:
- **Servers** → machines (machinetypeid 30)
- **Switches** → machines (machinetypeid 31)
- **Cameras** → machines (machinetypeid 32)
- **Access Points** → machines (machinetypeid 33) *if table exists*
- **IDFs** → machines (machinetypeid 34) *if table exists*
### What Stays Separate:
- **Printers** → Remain in printers table (by design)
---
## Migration Scripts
```
01_create_network_machinetypes.sql Creates machinetypes 30-36
02_migrate_servers_to_machines.sql Migrates servers table
03_migrate_switches_to_machines.sql Migrates switches table
04_migrate_cameras_to_machines.sql Migrates cameras table
07_migrate_network_communications.sql Migrates IP addresses
08_create_network_relationship_types.sql Creates new relationship types
09_update_views_for_network_devices.sql Creates/updates views
VERIFY_PHASE3_MIGRATION.sql Comprehensive verification
RUN_ALL_PHASE3_SCRIPTS.sql Executes all scripts in order
ROLLBACK_PHASE3.sql Emergency rollback
```
---
## Quick Start
### Prerequisites:
```bash
# 1. Backup database
mysqldump -u root -p shopdb > shopdb_backup_$(date +%Y%m%d).sql
# 2. Verify Phase 2 is stable
mysql -u root -p shopdb < ../VERIFY_PHASE2.sql # if available
# 3. Check current state
mysql -u root -p shopdb -e "SELECT COUNT(*) FROM servers; SELECT COUNT(*) FROM switches; SELECT COUNT(*) FROM cameras;"
```
### Test on Backup First:
```bash
# 1. Create test database
mysql -u root -p -e "CREATE DATABASE shopdb_test;"
mysql -u root -p shopdb_test < shopdb_backup_YYYYMMDD.sql
# 2. Run migration on test
mysql -u root -p shopdb_test < RUN_ALL_PHASE3_SCRIPTS.sql
# 3. Review results
mysql -u root -p shopdb_test < VERIFY_PHASE3_MIGRATION.sql
```
### Production Migration:
```bash
# Only after successful test!
mysql -u root -p shopdb < RUN_ALL_PHASE3_SCRIPTS.sql
```
---
## Expected Results
### Before Migration:
```
servers: 50 records
switches: 20 records
cameras: 30 records
Total: 100 devices
```
### After Migration:
```
machines (machinetypeid 30): 50 servers
machines (machinetypeid 31): 20 switches
machines (machinetypeid 32): 30 cameras
Total: 100 devices
communications: 100+ IP addresses
relationshiptypes: +5 new types
views: 3 new views created
```
---
## Verification Checklist
Run `VERIFY_PHASE3_MIGRATION.sql` and check for:
- [ ] All record counts match (old vs new tables)
- [ ] All 7 machinetypes created (30-36)
- [ ] No NULL required fields
- [ ] All IP addresses migrated
- [ ] 5 new relationship types created
- [ ] 3 views created successfully
- [ ] No duplicate serial numbers
- [ ] No duplicate machinenumbers
- [ ] Old tables preserved (rollback safety)
- [ ] All tests show "PASS"
---
## Relationship Examples
### Camera → Switch → IDF
```sql
-- Camera connected to switch
INSERT INTO machinerelationships (machineid, related_machineid, relationshiptypeid)
SELECT
(SELECT machineid FROM machines WHERE machinenumber = 'CAM-Shop-01'),
(SELECT machineid FROM machines WHERE machinenumber = 'SW-Core-01'),
(SELECT relationshiptypeid FROM relationshiptypes WHERE relationshiptype = 'Connected To');
-- Switch connected to IDF
INSERT INTO machinerelationships (machineid, related_machineid, relationshiptypeid)
SELECT
(SELECT machineid FROM machines WHERE machinenumber = 'SW-Core-01'),
(SELECT machineid FROM machines WHERE machinenumber = 'IDF-Building-A'),
(SELECT relationshiptypeid FROM relationshiptypes WHERE relationshiptype = 'Connected To');
```
### Query Network Topology
```sql
-- Show all cameras and their connections
SELECT
cam.machinenumber AS camera,
sw.machinenumber AS switch,
idf.machinenumber AS idf,
cam_ip.address AS camera_ip
FROM machines cam
-- Camera to Switch
JOIN machinerelationships mr1 ON cam.machineid = mr1.machineid
JOIN relationshiptypes rt1 ON mr1.relationshiptypeid = rt1.relationshiptypeid AND rt1.relationshiptype = 'Connected To'
JOIN machines sw ON mr1.related_machineid = sw.machineid AND sw.machinetypeid = 31
-- Switch to IDF
LEFT JOIN machinerelationships mr2 ON sw.machineid = mr2.machineid
LEFT JOIN relationshiptypes rt2 ON mr2.relationshiptypeid = rt2.relationshiptypeid AND rt2.relationshiptype = 'Connected To'
LEFT JOIN machines idf ON mr2.related_machineid = idf.machineid AND idf.machinetypeid = 34
-- IP address
LEFT JOIN communications cam_ip ON cam.machineid = cam_ip.machineid AND cam_ip.isprimary = 1
WHERE cam.machinetypeid = 32;
```
---
## Useful Queries
### All Network Devices
```sql
SELECT * FROM vw_network_devices_summary;
```
### All Infrastructure (Equipment + PCs + Network)
```sql
SELECT * FROM vw_all_infrastructure
WHERE device_category = 'Network Device';
```
### Network Devices on Specific Subnet
```sql
SELECT m.machinenumber, mt.machinetype, c.address
FROM machines m
JOIN machinetypes mt ON m.machinetypeid = mt.machinetypeid
JOIN communications c ON m.machineid = c.machineid
WHERE mt.machinetypeid BETWEEN 30 AND 36
AND c.address LIKE '192.168.1.%';
```
### Network Topology
```sql
SELECT * FROM vw_network_topology
WHERE relationshiptype = 'Connected To';
```
---
## Troubleshooting
### Migration Fails:
1. Review error message
2. Check if old tables exist
3. Run VERIFY script to identify issue
4. Run ROLLBACK if needed
5. Fix issue and retry
### Rollback:
```bash
# 1. Open ROLLBACK script
# 2. Uncomment rollback steps
# 3. Run rollback
mysql -u root -p shopdb < ROLLBACK_PHASE3.sql
# 4. Verify rollback
mysql -u root -p shopdb -e "SELECT COUNT(*) FROM machines WHERE machinetypeid BETWEEN 30 AND 36;"
# Should return 0
```
### Emergency Restore:
```bash
# If rollback doesn't work, restore from backup
mysql -u root -p shopdb < shopdb_backup_YYYYMMDD.sql
```
---
## Post-Migration Tasks
### Immediate (After Successful Migration):
1. Run verification script
2. Test application pages
3. Verify relationships display correctly
4. Check all device types accessible
### Short-Term (1-7 Days):
1. Update displaymachines.asp (add network device filters)
2. Update machine_edit.asp (if needed)
3. Test adding new network devices
4. Monitor for issues
### Long-Term (30+ Days):
1. Confirm migration stable
2. Drop old tables:
```sql
DROP TABLE servers;
DROP TABLE switches;
DROP TABLE cameras;
```
3. Update documentation
4. Celebrate!
---
## Important Notes
### Data Preserved:
- All serial numbers
- All IP addresses
- All descriptions
- All map coordinates
- All models/vendors
- All active/inactive states
### Data Generated:
- `machinenumber`: Generated as SVR-XXXX, SW-XXXX, CAM-XXXX
- `alias`: Populated from description field
- `pctypeid`: Set to NULL (not PCs)
- `machinetypeid`: Set to 30-36 based on device type
### Not Migrated (Old Tables Don't Have):
- MAC addresses (would be NULL)
- Business units (not applicable)
- Detailed notes (field empty in old tables)
---
## 📞 Support
### Issues?
1. Check VERIFY_PHASE3_MIGRATION.sql results
2. Review error logs
3. Check old tables still exist
4. Run ROLLBACK if needed
5. Contact database administrator
### Questions?
- Review docs/PHASE3_NETWORK_DEVICES_MIGRATION_PLAN.md
- Check SESSION_SUMMARY_2025-11-10.md
- Review Phase 2 migration (similar pattern)
---
## ✨ Benefits After Migration
### Unified Data Model:
- Single query for all infrastructure
- Consistent filtering and searching
- Better reporting capabilities
### Powerful Relationships:
- Camera → Switch → IDF topology
- Network device dependencies
- Better visualization options
### Better Maintenance:
- Less code duplication
- Easier to add new device types
- Consistent UI/UX
- CMDB-style asset management
---
**Ready to migrate? Start with testing on backup database!**
```bash
# Test first!
mysql -u root -p shopdb_test < RUN_ALL_PHASE3_SCRIPTS.sql
```
**Good luck! **

View File

@@ -0,0 +1,270 @@
-- =====================================================
-- ROLLBACK: Phase 3 Migration
-- =====================================================
-- Date: 2025-11-10
-- Purpose: Rollback Phase 3 migration (Network Devices)
-- USE WITH CAUTION: This will delete migrated data
-- =====================================================
--
-- IMPORTANT: READ BEFORE RUNNING
-- =====================================================
-- 1. This script removes all network devices from machines table
-- 2. Old tables (servers, switches, cameras) must still exist
-- 3. Only run if migration failed or issues found
-- 4. Backup database before rollback!
-- 5. Cannot rollback if old tables were dropped
-- =====================================================
USE shopdb;
SET SQL_SAFE_UPDATES = 0;
SELECT '============================================================' AS '';
SELECT 'PHASE 3 MIGRATION ROLLBACK' AS '';
SELECT '============================================================' AS '';
SELECT 'Start Time:' AS '', NOW() AS timestamp;
SELECT '' AS '';
-- =====================================================
-- STEP 1: Verification - Check Old Tables Exist
-- =====================================================
SELECT '------------------------------------------------------------' AS '';
SELECT 'Step 1: Verifying old tables still exist' AS '';
SELECT '------------------------------------------------------------' AS '';
-- Check if old tables exist
SELECT
CASE
WHEN COUNT(*) = 3 THEN 'PASS - All old tables exist'
ELSE 'FAIL - Some old tables missing! Cannot rollback safely.'
END AS status,
COUNT(*) AS tables_found
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = 'shopdb'
AND TABLE_NAME IN ('servers', 'switches', 'cameras');
-- Show old table record counts
SELECT 'Old table record counts:' AS status;
SELECT 'servers' AS table_name, COUNT(*) AS record_count FROM servers
UNION ALL
SELECT 'switches', COUNT(*) FROM switches
UNION ALL
SELECT 'cameras', COUNT(*) FROM cameras;
-- =====================================================
-- STEP 2: Show What Will Be Deleted
-- =====================================================
SELECT '------------------------------------------------------------' AS '';
SELECT 'Step 2: Records that will be removed from machines table' AS '';
SELECT '------------------------------------------------------------' AS '';
SELECT
mt.machinetype AS device_type,
COUNT(*) AS records_to_delete
FROM machines m
JOIN machinetypes mt ON m.machinetypeid = mt.machinetypeid
WHERE mt.machinetypeid BETWEEN 30 AND 36
GROUP BY mt.machinetype
ORDER BY mt.machinetypeid;
-- Show sample records to be deleted
SELECT 'Sample records to be deleted:' AS status;
SELECT
m.machineid,
m.machinenumber,
mt.machinetype,
m.serialnumber
FROM machines m
JOIN machinetypes mt ON m.machinetypeid = mt.machinetypeid
WHERE mt.machinetypeid BETWEEN 30 AND 36
LIMIT 10;
-- =====================================================
-- STEP 3: Confirmation Prompt
-- =====================================================
SELECT '' AS '';
SELECT '============================================================' AS '';
SELECT 'CONFIRMATION REQUIRED' AS '';
SELECT '============================================================' AS '';
SELECT 'This will DELETE all network devices from machines table' AS '';
SELECT 'Old data in servers/switches/cameras tables will remain' AS '';
SELECT '' AS '';
SELECT 'To proceed, uncomment the rollback steps below' AS '';
SELECT 'and run this script again.' AS '';
SELECT '============================================================' AS '';
-- =====================================================
-- STEP 4: Delete Communications for Network Devices
-- =====================================================
-- UNCOMMENT TO EXECUTE ROLLBACK
/*
SELECT '------------------------------------------------------------' AS '';
SELECT 'Step 4: Deleting communications for network devices' AS '';
SELECT '------------------------------------------------------------' AS '';
DELETE c
FROM communications c
JOIN machines m ON c.machineid = m.machineid
WHERE m.machinetypeid BETWEEN 30 AND 36;
SELECT 'Communications deleted:' AS status, ROW_COUNT() AS deleted_count;
*/
-- =====================================================
-- STEP 5: Delete Relationships Involving Network Devices
-- =====================================================
-- UNCOMMENT TO EXECUTE ROLLBACK
/*
SELECT '------------------------------------------------------------' AS '';
SELECT 'Step 5: Deleting relationships involving network devices' AS '';
SELECT '------------------------------------------------------------' AS '';
DELETE FROM machinerelationships
WHERE machineid IN (
SELECT machineid FROM machines WHERE machinetypeid BETWEEN 30 AND 36
)
OR related_machineid IN (
SELECT machineid FROM machines WHERE machinetypeid BETWEEN 30 AND 36
);
SELECT 'Relationships deleted:' AS status, ROW_COUNT() AS deleted_count;
*/
-- =====================================================
-- STEP 6: Delete Network Devices from machines Table
-- =====================================================
-- UNCOMMENT TO EXECUTE ROLLBACK
/*
SELECT '------------------------------------------------------------' AS '';
SELECT 'Step 6: Deleting network devices from machines table' AS '';
SELECT '------------------------------------------------------------' AS '';
DELETE FROM machines
WHERE machinetypeid BETWEEN 30 AND 36;
SELECT 'Machines deleted:' AS status, ROW_COUNT() AS deleted_count;
*/
-- =====================================================
-- STEP 7: Remove Network Relationship Types
-- =====================================================
-- UNCOMMENT TO EXECUTE ROLLBACK
/*
SELECT '------------------------------------------------------------' AS '';
SELECT 'Step 7: Removing network relationship types' AS '';
SELECT '------------------------------------------------------------' AS '';
DELETE FROM relationshiptypes
WHERE relationshiptype IN (
'Connected To',
'Powered By',
'Mounted In',
'Feeds Video To',
'Provides Network'
);
SELECT 'Relationship types deleted:' AS status, ROW_COUNT() AS deleted_count;
*/
-- =====================================================
-- STEP 8: Drop Views
-- =====================================================
-- UNCOMMENT TO EXECUTE ROLLBACK
/*
SELECT '------------------------------------------------------------' AS '';
SELECT 'Step 8: Dropping network device views' AS '';
SELECT '------------------------------------------------------------' AS '';
DROP VIEW IF EXISTS vw_all_infrastructure;
DROP VIEW IF EXISTS vw_network_devices_summary;
DROP VIEW IF EXISTS vw_network_topology;
SELECT 'Views dropped' AS status;
*/
-- =====================================================
-- STEP 9: Remove Network Machine Types
-- =====================================================
-- OPTIONAL: Usually safe to keep these for future use
-- UNCOMMENT TO EXECUTE ROLLBACK
/*
SELECT '------------------------------------------------------------' AS '';
SELECT 'Step 9: Removing network machine types (OPTIONAL)' AS '';
SELECT '------------------------------------------------------------' AS '';
DELETE FROM machinetypes
WHERE machinetypeid BETWEEN 30 AND 36;
SELECT 'Machine types deleted:' AS status, ROW_COUNT() AS deleted_count;
*/
-- =====================================================
-- STEP 10: Verification After Rollback
-- =====================================================
-- UNCOMMENT TO EXECUTE ROLLBACK
/*
SELECT '============================================================' AS '';
SELECT 'ROLLBACK VERIFICATION' AS '';
SELECT '============================================================' AS '';
-- Verify machines table cleaned up
SELECT 'Network devices remaining in machines:' AS test,
CASE
WHEN COUNT(*) = 0 THEN 'SUCCESS - All network devices removed'
ELSE CONCAT('WARNING - ', COUNT(*), ' network devices still remain')
END AS result
FROM machines
WHERE machinetypeid BETWEEN 30 AND 36;
-- Verify old tables still intact
SELECT 'Old tables status:' AS status;
SELECT 'servers' AS table_name, COUNT(*) AS record_count FROM servers
UNION ALL
SELECT 'switches', COUNT(*) FROM switches
UNION ALL
SELECT 'cameras', COUNT(*) FROM cameras;
SELECT '' AS '';
SELECT '✓ Rollback complete' AS status;
SELECT 'Old tables remain intact for re-migration' AS note;
*/
-- =====================================================
-- COMPLETION
-- =====================================================
SELECT '' AS '';
SELECT '============================================================' AS '';
SELECT 'End Time:' AS '', NOW() AS timestamp;
SELECT '============================================================' AS '';
SET SQL_SAFE_UPDATES = 1;
-- =====================================================
-- POST-ROLLBACK STEPS
-- =====================================================
-- After successful rollback:
-- 1. Review what caused the need for rollback
-- 2. Fix issues in migration scripts
-- 3. Test on backup database
-- 4. Re-run migration when ready
--
-- To re-run migration:
-- SOURCE RUN_ALL_PHASE3_SCRIPTS.sql;
-- =====================================================
-- =====================================================
-- EMERGENCY RESTORE (if old tables were dropped)
-- =====================================================
-- If old tables were dropped, restore from backup:
-- mysql -u root -p shopdb < shopdb_backup_before_phase3.sql
-- =====================================================

View File

@@ -0,0 +1,192 @@
-- =====================================================
-- RUN ALL: Phase 3 Migration Scripts
-- =====================================================
-- Date: 2025-11-10
-- Purpose: Execute all Phase 3 migration scripts in sequence
-- Part of: Phase 3 Migration (Network Devices → machines table)
-- Estimated Time: 5-10 minutes total
-- =====================================================
--
-- IMPORTANT: READ BEFORE RUNNING
-- =====================================================
-- 1. BACKUP YOUR DATABASE FIRST!
-- mysqldump -u root -p shopdb > shopdb_backup_before_phase3.sql
--
-- 2. Test on a backup database first!
--
-- 3. Schedule during maintenance window
--
-- 4. Monitor console output for errors
--
-- 5. If any script fails, STOP and review
--
-- 6. Keep old tables for 30 days (rollback safety)
-- =====================================================
USE shopdb;
-- Enable detailed error reporting
SET SQL_MODE='TRADITIONAL';
SET SQL_SAFE_UPDATES = 0;
SELECT '============================================================' AS '';
SELECT 'PHASE 3 MIGRATION - NETWORK DEVICES TO MACHINES TABLE' AS '';
SELECT '============================================================' AS '';
SELECT 'Start Time:' AS '', NOW() AS timestamp;
SELECT '' AS '';
-- =====================================================
-- SCRIPT 01: Create Network Machine Types
-- =====================================================
SELECT '------------------------------------------------------------' AS '';
SELECT 'Running Script 01: Create Network Machine Types' AS '';
SELECT '------------------------------------------------------------' AS '';
SOURCE 01_create_network_machinetypes.sql;
SELECT '' AS '';
SELECT '✓ Script 01 complete' AS status;
SELECT '' AS '';
-- Pause to allow review (in manual execution)
-- UNCOMMENT IF RUNNING MANUALLY: SELECT 'Press Enter to continue...' AS ''; PROMPT;
-- =====================================================
-- SCRIPT 02: Migrate Servers
-- =====================================================
SELECT '------------------------------------------------------------' AS '';
SELECT 'Running Script 02: Migrate Servers to machines Table' AS '';
SELECT '------------------------------------------------------------' AS '';
SOURCE 02_migrate_servers_to_machines.sql;
SELECT '' AS '';
SELECT '✓ Script 02 complete' AS status;
SELECT '' AS '';
-- =====================================================
-- SCRIPT 03: Migrate Switches
-- =====================================================
SELECT '------------------------------------------------------------' AS '';
SELECT 'Running Script 03: Migrate Switches to machines Table' AS '';
SELECT '------------------------------------------------------------' AS '';
SOURCE 03_migrate_switches_to_machines.sql;
SELECT '' AS '';
SELECT '✓ Script 03 complete' AS status;
SELECT '' AS '';
-- =====================================================
-- SCRIPT 04: Migrate Cameras
-- =====================================================
SELECT '------------------------------------------------------------' AS '';
SELECT 'Running Script 04: Migrate Cameras to machines Table' AS '';
SELECT '------------------------------------------------------------' AS '';
SOURCE 04_migrate_cameras_to_machines.sql;
SELECT '' AS '';
SELECT '✓ Script 04 complete' AS status;
SELECT '' AS '';
-- =====================================================
-- SCRIPT 07: Migrate Network Communications
-- =====================================================
SELECT '------------------------------------------------------------' AS '';
SELECT 'Running Script 07: Migrate Network Communications' AS '';
SELECT '------------------------------------------------------------' AS '';
SOURCE 07_migrate_network_communications.sql;
SELECT '' AS '';
SELECT '✓ Script 07 complete' AS status;
SELECT '' AS '';
-- =====================================================
-- SCRIPT 08: Create Network Relationship Types
-- =====================================================
SELECT '------------------------------------------------------------' AS '';
SELECT 'Running Script 08: Create Network Relationship Types' AS '';
SELECT '------------------------------------------------------------' AS '';
SOURCE 08_create_network_relationship_types.sql;
SELECT '' AS '';
SELECT '✓ Script 08 complete' AS status;
SELECT '' AS '';
-- =====================================================
-- SCRIPT 09: Update Views
-- =====================================================
SELECT '------------------------------------------------------------' AS '';
SELECT 'Running Script 09: Update Views for Network Devices' AS '';
SELECT '------------------------------------------------------------' AS '';
SOURCE 09_update_views_for_network_devices.sql;
SELECT '' AS '';
SELECT '✓ Script 09 complete' AS status;
SELECT '' AS '';
-- =====================================================
-- VERIFICATION
-- =====================================================
SELECT '============================================================' AS '';
SELECT 'RUNNING VERIFICATION' AS '';
SELECT '============================================================' AS '';
SOURCE VERIFY_PHASE3_MIGRATION.sql;
-- =====================================================
-- COMPLETION SUMMARY
-- =====================================================
SELECT '' AS '';
SELECT '============================================================' AS '';
SELECT 'PHASE 3 MIGRATION COMPLETE' AS '';
SELECT '============================================================' AS '';
SELECT 'End Time:' AS '', NOW() AS timestamp;
SELECT '' AS '';
-- Summary of migrated devices
SELECT 'Migration Summary:' AS status;
SELECT
mt.machinetype AS device_type,
COUNT(*) AS migrated_count
FROM machines m
JOIN machinetypes mt ON m.machinetypeid = mt.machinetypeid
WHERE mt.machinetypeid BETWEEN 30 AND 36
GROUP BY mt.machinetype
ORDER BY mt.machinetypeid;
SELECT '' AS '';
SELECT '============================================================' AS '';
SELECT 'NEXT STEPS:' AS '';
SELECT '============================================================' AS '';
SELECT '1. Review verification results above for any FAIL messages' AS step;
SELECT '2. Test application pages (displaymachines.asp, etc.)' AS step;
SELECT '3. Update application code to use new schema' AS step;
SELECT '4. Monitor for 30 days' AS step;
SELECT '5. Drop old tables only after confirming stability:' AS step;
SELECT ' DROP TABLE servers;' AS '';
SELECT ' DROP TABLE switches;' AS '';
SELECT ' DROP TABLE cameras;' AS '';
SELECT '============================================================' AS '';
SET SQL_SAFE_UPDATES = 1;
-- =====================================================
-- ROLLBACK INSTRUCTIONS (if needed)
-- =====================================================
-- If migration fails or issues found:
-- SOURCE ROLLBACK_PHASE3.sql;
-- =====================================================

View File

@@ -0,0 +1,326 @@
-- =====================================================
-- VERIFICATION: Phase 3 Migration
-- =====================================================
-- Date: 2025-11-10
-- Purpose: Comprehensive verification of Phase 3 migration
-- Part of: Phase 3 Migration (Network Devices → machines table)
-- Run After: All migration scripts (01-09)
-- =====================================================
USE shopdb;
SELECT '============================================================' AS '';
SELECT 'PHASE 3 MIGRATION VERIFICATION' AS '';
SELECT 'Network Devices Consolidation into machines Table' AS '';
SELECT '============================================================' AS '';
-- =====================================================
-- TEST 1: Record Count Verification
-- =====================================================
SELECT '' AS '';
SELECT '══════════════════════════════════════════════════════' AS '';
SELECT 'TEST 1: Record Count Verification' AS '';
SELECT '══════════════════════════════════════════════════════' AS '';
-- Count old table records
SELECT 'Source Tables (Before Migration):' AS status;
SELECT 'servers' AS table_name, COUNT(*) AS record_count FROM servers WHERE isactive = 1
UNION ALL
SELECT 'switches', COUNT(*) FROM switches WHERE isactive = 1
UNION ALL
SELECT 'cameras', COUNT(*) FROM cameras WHERE isactive = 1;
-- Count new table records
SELECT 'Target Table (After Migration):' AS status;
SELECT
mt.machinetype,
COUNT(*) AS record_count
FROM machines m
JOIN machinetypes mt ON m.machinetypeid = mt.machinetypeid
WHERE mt.machinetypeid BETWEEN 30 AND 36
GROUP BY mt.machinetype
ORDER BY mt.machinetypeid;
-- =====================================================
-- TEST 2: Machine Types Verification
-- =====================================================
SELECT '' AS '';
SELECT '══════════════════════════════════════════════════════' AS '';
SELECT 'TEST 2: Machine Types Exist' AS '';
SELECT '══════════════════════════════════════════════════════' AS '';
SELECT
machinetypeid,
machinetype,
category,
CASE WHEN isactive = 1 THEN 'Active' ELSE 'Inactive' END AS status
FROM machinetypes
WHERE machinetypeid BETWEEN 30 AND 36
ORDER BY machinetypeid;
-- Check for missing machinetypes
SELECT 'Missing machinetypes:' AS status,
CASE
WHEN COUNT(*) = 7 THEN 'PASS - All 7 network machinetypes exist'
ELSE CONCAT('FAIL - Only ', COUNT(*), ' of 7 machinetypes exist')
END AS result
FROM machinetypes
WHERE machinetypeid BETWEEN 30 AND 36;
-- =====================================================
-- TEST 3: Data Integrity - No NULL Required Fields
-- =====================================================
SELECT '' AS '';
SELECT '══════════════════════════════════════════════════════' AS '';
SELECT 'TEST 3: Data Integrity - Required Fields' AS '';
SELECT '══════════════════════════════════════════════════════' AS '';
-- Check for NULL machinetypeid
SELECT 'Devices with NULL machinetypeid:' AS test,
CASE
WHEN COUNT(*) = 0 THEN 'PASS - No NULL machinetypeids'
ELSE CONCAT('FAIL - ', COUNT(*), ' devices with NULL machinetypeid')
END AS result
FROM machines
WHERE machinetypeid BETWEEN 30 AND 36
AND machinetypeid IS NULL;
-- Check for NULL machinenumber
SELECT 'Devices with NULL machinenumber:' AS test,
CASE
WHEN COUNT(*) = 0 THEN 'PASS - No NULL machinenumbers'
ELSE CONCAT('FAIL - ', COUNT(*), ' devices with NULL machinenumber')
END AS result
FROM machines
WHERE machinetypeid BETWEEN 30 AND 36
AND machinenumber IS NULL;
-- Check for incorrect pctypeid (should be NULL for network devices)
SELECT 'Network devices with non-NULL pctypeid:' AS test,
CASE
WHEN COUNT(*) = 0 THEN 'PASS - All network devices have pctypeid = NULL'
ELSE CONCAT('FAIL - ', COUNT(*), ' network devices with incorrect pctypeid')
END AS result
FROM machines
WHERE machinetypeid BETWEEN 30 AND 36
AND pctypeid IS NOT NULL;
-- =====================================================
-- TEST 4: Communications Migration
-- =====================================================
SELECT '' AS '';
SELECT '══════════════════════════════════════════════════════' AS '';
SELECT 'TEST 4: Communications (IP Addresses) Migration' AS '';
SELECT '══════════════════════════════════════════════════════' AS '';
-- Count IPs in old tables
SELECT 'IP addresses in source tables:' AS status;
SELECT 'servers' AS table_name, COUNT(*) AS ip_count
FROM servers WHERE ipaddress IS NOT NULL AND ipaddress != '' AND isactive = 1
UNION ALL
SELECT 'switches', COUNT(*)
FROM switches WHERE ipaddress IS NOT NULL AND ipaddress != '' AND isactive = 1
UNION ALL
SELECT 'cameras', COUNT(*)
FROM cameras WHERE ipaddress IS NOT NULL AND ipaddress != '' AND isactive = 1;
-- Count IPs in communications table
SELECT 'IP addresses in communications table:' AS status;
SELECT
mt.machinetype,
COUNT(DISTINCT c.comid) AS ip_count
FROM machines m
JOIN machinetypes mt ON m.machinetypeid = mt.machinetypeid
JOIN communications c ON m.machineid = c.machineid AND c.comstypeid = 1
WHERE mt.machinetypeid BETWEEN 30 AND 36
GROUP BY mt.machinetype
ORDER BY mt.machinetypeid;
-- =====================================================
-- TEST 5: Relationship Types
-- =====================================================
SELECT '' AS '';
SELECT '══════════════════════════════════════════════════════' AS '';
SELECT 'TEST 5: New Relationship Types' AS '';
SELECT '══════════════════════════════════════════════════════' AS '';
SELECT 'Network relationship types:' AS status;
SELECT
relationshiptype,
description,
CASE WHEN isbidirectional = 1 THEN 'Yes' ELSE 'No' END AS bidirectional
FROM relationshiptypes
WHERE relationshiptype IN ('Connected To', 'Powered By', 'Mounted In', 'Feeds Video To', 'Provides Network')
ORDER BY relationshiptype;
-- Check if all expected relationship types exist
SELECT 'Expected relationship types:' AS test,
CASE
WHEN COUNT(*) >= 5 THEN 'PASS - All network relationship types exist'
ELSE CONCAT('FAIL - Only ', COUNT(*), ' of 5 relationship types exist')
END AS result
FROM relationshiptypes
WHERE relationshiptype IN ('Connected To', 'Powered By', 'Mounted In', 'Feeds Video To', 'Provides Network');
-- =====================================================
-- TEST 6: Views Verification
-- =====================================================
SELECT '' AS '';
SELECT '══════════════════════════════════════════════════════' AS '';
SELECT 'TEST 6: Views Created Successfully' AS '';
SELECT '══════════════════════════════════════════════════════' AS '';
-- Check if views exist
SELECT 'Views status:' AS test;
SELECT
TABLE_NAME AS view_name,
'EXISTS' AS status
FROM INFORMATION_SCHEMA.VIEWS
WHERE TABLE_SCHEMA = 'shopdb'
AND TABLE_NAME IN ('vw_all_infrastructure', 'vw_network_devices_summary', 'vw_network_topology');
-- Check view record counts
SELECT 'Records in vw_all_infrastructure:' AS test, COUNT(*) AS record_count FROM vw_all_infrastructure;
SELECT 'Records in vw_network_devices_summary:' AS test, COUNT(*) AS record_count FROM vw_network_devices_summary;
SELECT 'Records in vw_network_topology:' AS test, COUNT(*) AS record_count FROM vw_network_topology;
-- =====================================================
-- TEST 7: Sample Data Verification
-- =====================================================
SELECT '' AS '';
SELECT '══════════════════════════════════════════════════════' AS '';
SELECT 'TEST 7: Sample Migrated Data' AS '';
SELECT '══════════════════════════════════════════════════════' AS '';
SELECT 'Sample network devices:' AS status;
SELECT
m.machinenumber,
mt.machinetype,
mo.modelnumber,
v.vendor,
c.address AS ipaddress,
m.isactive
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
WHERE mt.machinetypeid BETWEEN 30 AND 36
ORDER BY mt.machinetypeid, m.machinenumber
LIMIT 15;
-- =====================================================
-- TEST 8: Duplicate Detection
-- =====================================================
SELECT '' AS '';
SELECT '══════════════════════════════════════════════════════' AS '';
SELECT 'TEST 8: Duplicate Detection' AS '';
SELECT '══════════════════════════════════════════════════════' AS '';
-- Check for duplicate serial numbers within network devices
SELECT 'Duplicate serial numbers:' AS test,
CASE
WHEN COUNT(*) = 0 THEN 'PASS - No duplicates found'
ELSE CONCAT('WARNING - ', COUNT(*), ' duplicate serial numbers found')
END AS result
FROM (
SELECT serialnumber, COUNT(*) as cnt
FROM machines
WHERE machinetypeid BETWEEN 30 AND 36
AND serialnumber IS NOT NULL
AND serialnumber != ''
GROUP BY serialnumber
HAVING cnt > 1
) AS duplicates;
-- Check for duplicate machinenumbers within network devices
SELECT 'Duplicate machinenumbers:' AS test,
CASE
WHEN COUNT(*) = 0 THEN 'PASS - No duplicates found'
ELSE CONCAT('FAIL - ', COUNT(*), ' duplicate machinenumbers found')
END AS result
FROM (
SELECT machinenumber, COUNT(*) as cnt
FROM machines
WHERE machinetypeid BETWEEN 30 AND 36
GROUP BY machinenumber
HAVING cnt > 1
) AS duplicates;
-- =====================================================
-- TEST 9: Old Table Preservation
-- =====================================================
SELECT '' AS '';
SELECT '══════════════════════════════════════════════════════' AS '';
SELECT 'TEST 9: Old Tables Preserved (Rollback Safety)' AS '';
SELECT '══════════════════════════════════════════════════════' AS '';
SELECT 'Old tables status:' AS test;
SELECT 'servers' AS table_name, COUNT(*) AS record_count FROM servers
UNION ALL
SELECT 'switches', COUNT(*) FROM switches
UNION ALL
SELECT 'cameras', COUNT(*) FROM cameras;
-- =====================================================
-- FINAL SUMMARY
-- =====================================================
SELECT '' AS '';
SELECT '============================================================' AS '';
SELECT 'VERIFICATION SUMMARY' AS '';
SELECT '============================================================' AS '';
SELECT
'Total Network Devices' AS metric,
COUNT(*) AS value
FROM machines
WHERE machinetypeid BETWEEN 30 AND 36
UNION ALL
SELECT
'Devices with IP Addresses',
COUNT(DISTINCT m.machineid)
FROM machines m
JOIN communications c ON m.machineid = c.machineid AND c.comstypeid = 1
WHERE m.machinetypeid BETWEEN 30 AND 36
UNION ALL
SELECT
'New Relationship Types',
COUNT(*)
FROM relationshiptypes
WHERE relationshiptype IN ('Connected To', 'Powered By', 'Mounted In', 'Feeds Video To', 'Provides Network')
UNION ALL
SELECT
'Views Created',
COUNT(*)
FROM INFORMATION_SCHEMA.VIEWS
WHERE TABLE_SCHEMA = 'shopdb'
AND TABLE_NAME IN ('vw_all_infrastructure', 'vw_network_devices_summary', 'vw_network_topology');
SELECT '' AS '';
SELECT '✓ Phase 3 migration verification complete' AS status;
SELECT 'Review results above for any FAIL messages' AS note;
SELECT '============================================================' AS '';
-- =====================================================
-- NOTES
-- =====================================================
-- If all tests show PASS:
-- - Migration successful
-- - Safe to update application code
-- - Monitor for 30 days before dropping old tables
--
-- If any tests show FAIL:
-- - Review specific failures
-- - Consider running ROLLBACK script
-- - Fix issues and re-run migration
-- =====================================================

View File

@@ -0,0 +1,62 @@
-- =====================================================
-- SCRIPT 01: Create Application Versions Infrastructure
-- =====================================================
-- Date: 2025-11-25
-- Purpose: Create appversions table for tracking application versions
-- Status: REVERSIBLE (see ROLLBACK_01)
-- Estimated Time: < 1 minute
-- =====================================================
USE shopdb;
SET SQL_SAFE_UPDATES = 0;
-- =====================================================
-- STEP 1: Create appversions table
-- =====================================================
CREATE TABLE IF NOT EXISTS appversions (
appversionid INT(11) PRIMARY KEY AUTO_INCREMENT,
appid TINYINT(4) NOT NULL,
version VARCHAR(50) NOT NULL,
releasedate DATE NULL,
notes VARCHAR(255) NULL,
isactive BIT(1) DEFAULT b'1',
dateadded DATETIME DEFAULT CURRENT_TIMESTAMP,
-- Indexes
KEY idx_appid (appid),
KEY idx_version (version),
KEY idx_isactive (isactive),
-- Unique constraint: one version string per application
UNIQUE KEY uk_app_version (appid, version),
-- Foreign Key
CONSTRAINT fk_appversions_appid FOREIGN KEY (appid) REFERENCES applications(appid)
ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8
COMMENT='Application version tracking for installed software';
-- =====================================================
-- VERIFICATION
-- =====================================================
SELECT '✓ appversions table created' AS status;
SELECT
TABLE_NAME,
ENGINE,
TABLE_ROWS,
TABLE_COMMENT
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = 'shopdb' AND TABLE_NAME = 'appversions';
SELECT '✓ Script 01 completed successfully' AS status;
SET SQL_SAFE_UPDATES = 1;
-- =====================================================
-- NOTES
-- =====================================================
-- Next: Run script 02_add_appversionid_to_installedapps.sql
-- Rollback: Run ROLLBACK_01_appversions_table.sql
-- =====================================================

View File

@@ -0,0 +1,102 @@
-- =====================================================
-- SCRIPT 02: Add appversionid to installedapps
-- =====================================================
-- Date: 2025-11-25
-- Purpose: Add version tracking column to installedapps table
-- Status: REVERSIBLE (see ROLLBACK_02)
-- Estimated Time: < 1 minute
-- =====================================================
USE shopdb;
SET SQL_SAFE_UPDATES = 0;
-- =====================================================
-- STEP 1: Add appversionid column to installedapps
-- =====================================================
-- Check if column exists before adding
SET @column_exists = (
SELECT COUNT(*)
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = 'shopdb'
AND TABLE_NAME = 'installedapps'
AND COLUMN_NAME = 'appversionid'
);
SET @sql = IF(@column_exists = 0,
'ALTER TABLE installedapps ADD COLUMN appversionid INT(11) NULL AFTER appid',
'SELECT "Column appversionid already exists" AS status'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- =====================================================
-- STEP 2: Add foreign key constraint
-- =====================================================
-- Check if FK exists before adding
SET @fk_exists = (
SELECT COUNT(*)
FROM information_schema.TABLE_CONSTRAINTS
WHERE TABLE_SCHEMA = 'shopdb'
AND TABLE_NAME = 'installedapps'
AND CONSTRAINT_NAME = 'fk_installedapps_appversionid'
);
SET @sql = IF(@fk_exists = 0,
'ALTER TABLE installedapps ADD CONSTRAINT fk_installedapps_appversionid FOREIGN KEY (appversionid) REFERENCES appversions(appversionid) ON DELETE SET NULL ON UPDATE CASCADE',
'SELECT "FK fk_installedapps_appversionid already exists" AS status'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- =====================================================
-- STEP 3: Add index for performance
-- =====================================================
SET @idx_exists = (
SELECT COUNT(*)
FROM information_schema.STATISTICS
WHERE TABLE_SCHEMA = 'shopdb'
AND TABLE_NAME = 'installedapps'
AND INDEX_NAME = 'idx_appversionid'
);
SET @sql = IF(@idx_exists = 0,
'ALTER TABLE installedapps ADD INDEX idx_appversionid (appversionid)',
'SELECT "Index idx_appversionid already exists" AS status'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- =====================================================
-- VERIFICATION
-- =====================================================
SELECT '✓ installedapps table updated' AS status;
SELECT
COLUMN_NAME,
DATA_TYPE,
IS_NULLABLE,
COLUMN_DEFAULT
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = 'shopdb'
AND TABLE_NAME = 'installedapps'
ORDER BY ORDINAL_POSITION;
SELECT '✓ Script 02 completed successfully' AS status;
SET SQL_SAFE_UPDATES = 1;
-- =====================================================
-- NOTES
-- =====================================================
-- Existing installedapps records will have appversionid = NULL
-- PowerShell API will need updating to populate this field
-- Next: Run script 03_add_appid_to_notifications.sql
-- Rollback: Run ROLLBACK_02_installedapps_appversionid.sql
-- =====================================================

View File

@@ -0,0 +1,102 @@
-- =====================================================
-- SCRIPT 03: Add optional appid to notifications
-- =====================================================
-- Date: 2025-11-25
-- Purpose: Allow notifications to be optionally linked to an application
-- Status: REVERSIBLE (see ROLLBACK_03)
-- Estimated Time: < 1 minute
-- =====================================================
USE shopdb;
SET SQL_SAFE_UPDATES = 0;
-- =====================================================
-- STEP 1: Add appid column to notifications
-- =====================================================
-- Check if column exists before adding
SET @column_exists = (
SELECT COUNT(*)
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = 'shopdb'
AND TABLE_NAME = 'notifications'
AND COLUMN_NAME = 'appid'
);
SET @sql = IF(@column_exists = 0,
'ALTER TABLE notifications ADD COLUMN appid TINYINT(4) NULL AFTER businessunitid',
'SELECT "Column appid already exists" AS status'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- =====================================================
-- STEP 2: Add foreign key constraint
-- =====================================================
-- Check if FK exists before adding
SET @fk_exists = (
SELECT COUNT(*)
FROM information_schema.TABLE_CONSTRAINTS
WHERE TABLE_SCHEMA = 'shopdb'
AND TABLE_NAME = 'notifications'
AND CONSTRAINT_NAME = 'fk_notifications_appid'
);
SET @sql = IF(@fk_exists = 0,
'ALTER TABLE notifications ADD CONSTRAINT fk_notifications_appid FOREIGN KEY (appid) REFERENCES applications(appid) ON DELETE SET NULL ON UPDATE CASCADE',
'SELECT "FK fk_notifications_appid already exists" AS status'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- =====================================================
-- STEP 3: Add index for performance
-- =====================================================
SET @idx_exists = (
SELECT COUNT(*)
FROM information_schema.STATISTICS
WHERE TABLE_SCHEMA = 'shopdb'
AND TABLE_NAME = 'notifications'
AND INDEX_NAME = 'idx_notifications_appid'
);
SET @sql = IF(@idx_exists = 0,
'ALTER TABLE notifications ADD INDEX idx_notifications_appid (appid)',
'SELECT "Index idx_notifications_appid already exists" AS status'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- =====================================================
-- VERIFICATION
-- =====================================================
SELECT '✓ notifications table updated' AS status;
SELECT
COLUMN_NAME,
DATA_TYPE,
IS_NULLABLE,
COLUMN_DEFAULT
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = 'shopdb'
AND TABLE_NAME = 'notifications'
ORDER BY ORDINAL_POSITION;
SELECT '✓ Script 03 completed successfully' AS status;
SET SQL_SAFE_UPDATES = 1;
-- =====================================================
-- NOTES
-- =====================================================
-- appid is optional (NULL allowed) - most notifications won't be app-specific
-- Use case: "PC-DMIS upgrade scheduled" notification linked to PC-DMIS app
-- Next: Run VERIFY_PHASE4_MIGRATION.sql
-- Rollback: Run ROLLBACK_03_notifications_appid.sql
-- =====================================================

View File

@@ -0,0 +1,177 @@
# Phase 4 Migration: Application Versions
**Date:** 2025-11-25
**Status:** Ready for deployment
## Overview
This migration adds application version tracking to ShopDB:
1. **`appversions` table** - Stores version strings for each application
2. **`installedapps.appversionid`** - Links installed apps to specific versions
3. **`notifications.appid`** - Optional link from notifications to applications
## Schema Changes
### New Table: appversions
```sql
CREATE TABLE appversions (
appversionid INT PRIMARY KEY AUTO_INCREMENT,
appid TINYINT(4) NOT NULL, -- FK to applications
version VARCHAR(50) NOT NULL, -- Version string (e.g., "2.1.0.45")
releasedate DATE NULL, -- Optional release date
notes VARCHAR(255) NULL, -- Optional notes
isactive BIT(1) DEFAULT 1,
dateadded DATETIME DEFAULT NOW(),
UNIQUE KEY (appid, version) -- One entry per app+version combo
);
```
### Modified Table: installedapps
```sql
-- Added column:
appversionid INT NULL -- FK to appversions (NULL for legacy records)
```
### Modified Table: notifications
```sql
-- Added column:
appid TINYINT(4) NULL -- FK to applications (optional app association)
```
## Files
| File | Purpose |
|------|---------|
| `01_create_appversions_table.sql` | Creates the appversions table |
| `02_add_appversionid_to_installedapps.sql` | Adds version FK to installedapps |
| `03_add_appid_to_notifications.sql` | Adds app FK to notifications |
| `VERIFY_PHASE4_MIGRATION.sql` | Verifies all changes |
| `RUN_ALL_PHASE4_SCRIPTS.sql` | Runs all scripts in order |
| `ROLLBACK_01_appversions_table.sql` | Drops appversions table |
| `ROLLBACK_02_installedapps_appversionid.sql` | Removes installedapps column |
| `ROLLBACK_03_notifications_appid.sql` | Removes notifications column |
## Deployment Instructions
### Prerequisites
1. Create database backup:
```bash
mysqldump -u root -p shopdb > shopdb_backup_$(date +%Y%m%d_%H%M%S).sql
```
2. Verify current schema:
```bash
mysql -u root -p shopdb -e "DESCRIBE installedapps; DESCRIBE notifications;"
```
### Run Migration
**Option A: Run all scripts at once**
```bash
cd /path/to/sql/migration_phase4
mysql -u root -p shopdb < RUN_ALL_PHASE4_SCRIPTS.sql
```
**Option B: Run scripts individually**
```bash
mysql -u root -p shopdb < 01_create_appversions_table.sql
mysql -u root -p shopdb < 02_add_appversionid_to_installedapps.sql
mysql -u root -p shopdb < 03_add_appid_to_notifications.sql
mysql -u root -p shopdb < VERIFY_PHASE4_MIGRATION.sql
```
### Verify Success
```bash
mysql -u root -p shopdb < VERIFY_PHASE4_MIGRATION.sql
```
All checks should show ` PASS`.
## Rollback Instructions
If you need to rollback, run scripts in reverse order:
```bash
mysql -u root -p shopdb < ROLLBACK_03_notifications_appid.sql
mysql -u root -p shopdb < ROLLBACK_02_installedapps_appversionid.sql
mysql -u root -p shopdb < ROLLBACK_01_appversions_table.sql
```
**Warning:** Rolling back `ROLLBACK_01` will delete all version data.
## Post-Migration: Code Changes Required
### 1. api.asp - Update GetOrCreateApplication()
The function needs to:
- Look up or create the application in `applications`
- Look up or create the version in `appversions`
- Return `appversionid` to store in `installedapps`
### 2. api.asp - Update UpdateInstalledApps()
Change INSERT to include `appversionid`:
```sql
INSERT INTO installedapps (machineid, appid, appversionid, isactive)
VALUES (?, ?, ?, ?)
```
### 3. Notification forms (addnotification.asp, editnotification.asp)
Add optional application dropdown to link notifications to apps.
### 4. Display pages
- `displayinstalledapps.asp` - Show version column
- `displaynotifications.asp` - Show linked app name
## Example Queries
### Get installed apps with versions
```sql
SELECT
m.hostname,
a.appname,
av.version,
ia.isactive
FROM installedapps ia
JOIN machines m ON ia.machineid = m.machineid
JOIN applications a ON ia.appid = a.appid
LEFT JOIN appversions av ON ia.appversionid = av.appversionid
WHERE m.pctypeid IS NOT NULL
ORDER BY m.hostname, a.appname;
```
### Get notifications with linked apps
```sql
SELECT
n.notification,
n.starttime,
n.endtime,
a.appname AS related_app
FROM notifications n
LEFT JOIN applications a ON n.appid = a.appid
WHERE n.isactive = 1
ORDER BY n.starttime DESC;
```
### Find all versions of a specific app
```sql
SELECT
a.appname,
av.version,
av.releasedate,
COUNT(ia.machineid) AS install_count
FROM applications a
JOIN appversions av ON a.appid = av.appid
LEFT JOIN installedapps ia ON av.appversionid = ia.appversionid
WHERE a.appname LIKE '%PC-DMIS%'
GROUP BY a.appid, av.appversionid
ORDER BY av.version DESC;
```

View File

@@ -0,0 +1,34 @@
-- =====================================================
-- ROLLBACK 01: Remove appversions table
-- =====================================================
-- Date: 2025-11-25
-- Purpose: Rollback script for 01_create_appversions_table.sql
-- WARNING: This will delete all version data!
-- =====================================================
USE shopdb;
SET SQL_SAFE_UPDATES = 0;
-- Must remove FK from installedapps first (if it exists)
SET @fk_exists = (
SELECT COUNT(*)
FROM information_schema.TABLE_CONSTRAINTS
WHERE TABLE_SCHEMA = 'shopdb'
AND TABLE_NAME = 'installedapps'
AND CONSTRAINT_NAME = 'fk_installedapps_appversionid'
);
SET @sql = IF(@fk_exists > 0,
'ALTER TABLE installedapps DROP FOREIGN KEY fk_installedapps_appversionid',
'SELECT "FK does not exist" AS status'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- Drop appversions table
DROP TABLE IF EXISTS appversions;
SELECT '✓ appversions table dropped' AS status;
SET SQL_SAFE_UPDATES = 1;

View File

@@ -0,0 +1,64 @@
-- =====================================================
-- ROLLBACK 02: Remove appversionid from installedapps
-- =====================================================
-- Date: 2025-11-25
-- Purpose: Rollback script for 02_add_appversionid_to_installedapps.sql
-- =====================================================
USE shopdb;
SET SQL_SAFE_UPDATES = 0;
-- Drop FK first
SET @fk_exists = (
SELECT COUNT(*)
FROM information_schema.TABLE_CONSTRAINTS
WHERE TABLE_SCHEMA = 'shopdb'
AND TABLE_NAME = 'installedapps'
AND CONSTRAINT_NAME = 'fk_installedapps_appversionid'
);
SET @sql = IF(@fk_exists > 0,
'ALTER TABLE installedapps DROP FOREIGN KEY fk_installedapps_appversionid',
'SELECT "FK does not exist" AS status'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- Drop index
SET @idx_exists = (
SELECT COUNT(*)
FROM information_schema.STATISTICS
WHERE TABLE_SCHEMA = 'shopdb'
AND TABLE_NAME = 'installedapps'
AND INDEX_NAME = 'idx_appversionid'
);
SET @sql = IF(@idx_exists > 0,
'ALTER TABLE installedapps DROP INDEX idx_appversionid',
'SELECT "Index does not exist" AS status'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- Drop column
SET @column_exists = (
SELECT COUNT(*)
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = 'shopdb'
AND TABLE_NAME = 'installedapps'
AND COLUMN_NAME = 'appversionid'
);
SET @sql = IF(@column_exists > 0,
'ALTER TABLE installedapps DROP COLUMN appversionid',
'SELECT "Column does not exist" AS status'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SELECT '✓ appversionid removed from installedapps' AS status;
SET SQL_SAFE_UPDATES = 1;

View File

@@ -0,0 +1,64 @@
-- =====================================================
-- ROLLBACK 03: Remove appid from notifications
-- =====================================================
-- Date: 2025-11-25
-- Purpose: Rollback script for 03_add_appid_to_notifications.sql
-- =====================================================
USE shopdb;
SET SQL_SAFE_UPDATES = 0;
-- Drop FK first
SET @fk_exists = (
SELECT COUNT(*)
FROM information_schema.TABLE_CONSTRAINTS
WHERE TABLE_SCHEMA = 'shopdb'
AND TABLE_NAME = 'notifications'
AND CONSTRAINT_NAME = 'fk_notifications_appid'
);
SET @sql = IF(@fk_exists > 0,
'ALTER TABLE notifications DROP FOREIGN KEY fk_notifications_appid',
'SELECT "FK does not exist" AS status'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- Drop index
SET @idx_exists = (
SELECT COUNT(*)
FROM information_schema.STATISTICS
WHERE TABLE_SCHEMA = 'shopdb'
AND TABLE_NAME = 'notifications'
AND INDEX_NAME = 'idx_notifications_appid'
);
SET @sql = IF(@idx_exists > 0,
'ALTER TABLE notifications DROP INDEX idx_notifications_appid',
'SELECT "Index does not exist" AS status'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- Drop column
SET @column_exists = (
SELECT COUNT(*)
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = 'shopdb'
AND TABLE_NAME = 'notifications'
AND COLUMN_NAME = 'appid'
);
SET @sql = IF(@column_exists > 0,
'ALTER TABLE notifications DROP COLUMN appid',
'SELECT "Column does not exist" AS status'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SELECT '✓ appid removed from notifications' AS status;
SET SQL_SAFE_UPDATES = 1;

View File

@@ -0,0 +1,75 @@
-- =====================================================
-- RUN ALL PHASE 4 SCRIPTS: Application Versions
-- =====================================================
-- Date: 2025-11-25
-- Purpose: Execute all Phase 4 migration scripts in order
--
-- USAGE:
-- mysql -u root -p shopdb < RUN_ALL_PHASE4_SCRIPTS.sql
--
-- OR run each script individually:
-- 1. 01_create_appversions_table.sql
-- 2. 02_add_appversionid_to_installedapps.sql
-- 3. 03_add_appid_to_notifications.sql
-- 4. VERIFY_PHASE4_MIGRATION.sql
--
-- ROLLBACK ORDER (if needed):
-- 1. ROLLBACK_03_notifications_appid.sql
-- 2. ROLLBACK_02_installedapps_appversionid.sql
-- 3. ROLLBACK_01_appversions_table.sql
-- =====================================================
USE shopdb;
SELECT '=================================================' AS '';
SELECT 'PHASE 4 MIGRATION: Application Versions' AS '';
SELECT 'Started at: ' AS '', NOW() AS timestamp;
SELECT '=================================================' AS '';
-- =====================================================
-- PRE-MIGRATION BACKUP REMINDER
-- =====================================================
SELECT 'REMINDER: Ensure you have a database backup before proceeding!' AS '';
SELECT '' AS '';
-- =====================================================
-- SCRIPT 1: Create appversions table
-- =====================================================
SELECT '--- Running Script 01: Create appversions table ---' AS '';
SOURCE 01_create_appversions_table.sql;
-- =====================================================
-- SCRIPT 2: Add appversionid to installedapps
-- =====================================================
SELECT '--- Running Script 02: Add appversionid to installedapps ---' AS '';
SOURCE 02_add_appversionid_to_installedapps.sql;
-- =====================================================
-- SCRIPT 3: Add appid to notifications
-- =====================================================
SELECT '--- Running Script 03: Add appid to notifications ---' AS '';
SOURCE 03_add_appid_to_notifications.sql;
-- =====================================================
-- VERIFICATION
-- =====================================================
SELECT '--- Running Verification ---' AS '';
SOURCE VERIFY_PHASE4_MIGRATION.sql;
-- =====================================================
-- COMPLETE
-- =====================================================
SELECT '=================================================' AS '';
SELECT 'PHASE 4 MIGRATION COMPLETE' AS '';
SELECT 'Finished at: ' AS '', NOW() AS timestamp;
SELECT '=================================================' AS '';
SELECT '' AS '';
SELECT 'NEXT STEPS:' AS '';
SELECT '1. Update api.asp to use appversions table' AS '';
SELECT '2. Update PowerShell script to send version data' AS '';
SELECT '3. Update notification forms to allow app selection' AS '';
SELECT '=================================================' AS '';

View File

@@ -0,0 +1,127 @@
-- =====================================================
-- VERIFY PHASE 4 MIGRATION: Application Versions
-- =====================================================
-- Date: 2025-11-25
-- Purpose: Verify all Phase 4 schema changes are in place
-- Run this after all migration scripts complete
-- =====================================================
USE shopdb;
SELECT '=================================================' AS '';
SELECT 'PHASE 4 MIGRATION VERIFICATION' AS '';
SELECT '=================================================' AS '';
-- =====================================================
-- CHECK 1: appversions table exists
-- =====================================================
SELECT '--- CHECK 1: appversions table ---' AS '';
SELECT
CASE WHEN COUNT(*) > 0 THEN '✓ PASS' ELSE '✗ FAIL' END AS appversions_table_exists
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = 'shopdb' AND TABLE_NAME = 'appversions';
SELECT
COLUMN_NAME,
DATA_TYPE,
IS_NULLABLE,
COLUMN_KEY
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = 'shopdb' AND TABLE_NAME = 'appversions'
ORDER BY ORDINAL_POSITION;
-- =====================================================
-- CHECK 2: installedapps.appversionid column exists
-- =====================================================
SELECT '--- CHECK 2: installedapps.appversionid column ---' AS '';
SELECT
CASE WHEN COUNT(*) > 0 THEN '✓ PASS' ELSE '✗ FAIL' END AS appversionid_column_exists
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = 'shopdb'
AND TABLE_NAME = 'installedapps'
AND COLUMN_NAME = 'appversionid';
-- Check FK
SELECT
CASE WHEN COUNT(*) > 0 THEN '✓ PASS' ELSE '✗ FAIL' END AS installedapps_fk_exists
FROM information_schema.TABLE_CONSTRAINTS
WHERE TABLE_SCHEMA = 'shopdb'
AND TABLE_NAME = 'installedapps'
AND CONSTRAINT_NAME = 'fk_installedapps_appversionid';
-- =====================================================
-- CHECK 3: notifications.appid column exists
-- =====================================================
SELECT '--- CHECK 3: notifications.appid column ---' AS '';
SELECT
CASE WHEN COUNT(*) > 0 THEN '✓ PASS' ELSE '✗ FAIL' END AS notifications_appid_column_exists
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = 'shopdb'
AND TABLE_NAME = 'notifications'
AND COLUMN_NAME = 'appid';
-- Check FK
SELECT
CASE WHEN COUNT(*) > 0 THEN '✓ PASS' ELSE '✗ FAIL' END AS notifications_appid_fk_exists
FROM information_schema.TABLE_CONSTRAINTS
WHERE TABLE_SCHEMA = 'shopdb'
AND TABLE_NAME = 'notifications'
AND CONSTRAINT_NAME = 'fk_notifications_appid';
-- =====================================================
-- CHECK 4: Foreign key relationships
-- =====================================================
SELECT '--- CHECK 4: Foreign key relationships ---' AS '';
SELECT
CONSTRAINT_NAME,
TABLE_NAME,
REFERENCED_TABLE_NAME
FROM information_schema.REFERENTIAL_CONSTRAINTS
WHERE CONSTRAINT_SCHEMA = 'shopdb'
AND (
CONSTRAINT_NAME LIKE '%appversion%'
OR (TABLE_NAME = 'notifications' AND CONSTRAINT_NAME LIKE '%appid%')
);
-- =====================================================
-- SUMMARY: Current record counts
-- =====================================================
SELECT '--- SUMMARY: Record counts ---' AS '';
SELECT
'applications' AS table_name,
COUNT(*) AS record_count
FROM applications
UNION ALL
SELECT
'appversions' AS table_name,
COUNT(*) AS record_count
FROM appversions
UNION ALL
SELECT
'installedapps' AS table_name,
COUNT(*) AS record_count
FROM installedapps
UNION ALL
SELECT
'installedapps (with version)' AS table_name,
COUNT(*) AS record_count
FROM installedapps WHERE appversionid IS NOT NULL
UNION ALL
SELECT
'notifications' AS table_name,
COUNT(*) AS record_count
FROM notifications
UNION ALL
SELECT
'notifications (app-linked)' AS table_name,
COUNT(*) AS record_count
FROM notifications WHERE appid IS NOT NULL;
SELECT '=================================================' AS '';
SELECT 'PHASE 4 VERIFICATION COMPLETE' AS '';
SELECT '=================================================' AS '';

View File

@@ -0,0 +1,32 @@
-- ============================================================================
-- Migration: Add Specialized PC Machine Types
-- Date: 2025-12-03
-- Purpose: Add PC types for CMM, Wax Trace, and Measuring Tool PCs
--
-- These PC types allow categorization of PCs based on installed software:
-- - PC - CMM: PCs running PC-DMIS for CMM measurement
-- - PC - Wax Trace: PCs running Formtracepak for wax trace inspection
-- - PC - Measuring Tool: PCs running Keyence/Genspect for measurement
--
-- This enables proper PC-to-Equipment relationships:
-- - PC - CMM (41) <-> CMM equipment (machinetypeid 3)
-- - PC - Wax Trace (42) <-> Wax Trace equipment (machinetypeid 5)
-- - PC - Measuring Tool (43) <-> Measuring Machine equipment (machinetypeid 23)
-- ============================================================================
-- Add new specialized PC machine types
INSERT INTO machinetypes (machinetypeid, machinetype, isactive, functionalaccountid, bgcolor, machinedescription)
VALUES
(41, 'PC - CMM', 1, NULL, NULL, 'PC running PC-DMIS for CMM measurement'),
(42, 'PC - Wax Trace', 1, NULL, NULL, 'PC running Formtracepak for wax trace inspection'),
(43, 'PC - Measuring Tool', 1, NULL, NULL, 'PC running Keyence/Genspect for measurement')
ON DUPLICATE KEY UPDATE
machinetype = VALUES(machinetype),
machinedescription = VALUES(machinedescription),
isactive = 1;
-- Verify the changes
SELECT machinetypeid, machinetype, machinedescription, isactive
FROM machinetypes
WHERE machinetypeid IN (41, 42, 43)
ORDER BY machinetypeid;

View File

@@ -0,0 +1,33 @@
-- TV Dashboard Slides Management
-- Run this script to create the tables for TV slide management
-- Table to store slide presentations/folders
CREATE TABLE IF NOT EXISTS tv_presentations (
presentationid INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
folder_path VARCHAR(500) NOT NULL COMMENT 'Full path or subfolder name under base path',
interval_seconds INT DEFAULT 10 COMMENT 'Seconds between slides',
isactive TINYINT(1) DEFAULT 0 COMMENT 'Only one should be active at a time',
created_date DATETIME DEFAULT CURRENT_TIMESTAMP,
lastupdated DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
notes VARCHAR(500)
);
-- Table to store individual slides (optional - for when you want to manage slides in DB)
CREATE TABLE IF NOT EXISTS tv_slides (
slideid INT AUTO_INCREMENT PRIMARY KEY,
presentationid INT NOT NULL,
filename VARCHAR(255) NOT NULL,
display_order INT DEFAULT 0,
isactive TINYINT(1) DEFAULT 1,
created_date DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (presentationid) REFERENCES tv_presentations(presentationid) ON DELETE CASCADE
);
-- Insert default presentation
INSERT INTO tv_presentations (name, folder_path, interval_seconds, isactive, notes)
VALUES ('Default', 'S:\\ProcessData\\CommDisplay\\ShopSS', 10, 1, 'Default presentation folder');
-- Example: Add a holiday presentation (inactive by default)
-- INSERT INTO tv_presentations (name, folder_path, interval_seconds, isactive, notes)
-- VALUES ('Christmas 2025', 'Christmas2025', 10, 0, 'Holiday slides - subfolder of base path');