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,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()