Initial commit: Shop Database Flask Application
Flask backend with Vue 3 frontend for shop floor machine management. Includes database schema export for MySQL shopdb_flask database. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
581
scripts/import_from_mysql.py
Normal file
581
scripts/import_from_mysql.py
Normal file
@@ -0,0 +1,581 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Import data from legacy MySQL ShopDB to new Flask ShopDB.
|
||||
|
||||
Usage:
|
||||
cd /home/camp/projects/shopdb-flask
|
||||
source venv/bin/activate
|
||||
python scripts/import_from_mysql.py
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import pymysql
|
||||
from datetime import datetime
|
||||
from dotenv import load_dotenv
|
||||
|
||||
# Add parent directory to path for imports
|
||||
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
|
||||
# Load environment variables
|
||||
load_dotenv(os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), '.env'))
|
||||
|
||||
# MySQL connection settings
|
||||
MYSQL_CONFIG = {
|
||||
'host': '127.0.0.1',
|
||||
'port': 3306,
|
||||
'user': 'root',
|
||||
'password': 'rootpassword',
|
||||
'database': 'shopdb',
|
||||
'charset': 'utf8mb4',
|
||||
'cursorclass': pymysql.cursors.DictCursor
|
||||
}
|
||||
|
||||
|
||||
def get_mysql_connection():
|
||||
"""Get MySQL connection."""
|
||||
return pymysql.connect(**MYSQL_CONFIG)
|
||||
|
||||
|
||||
def import_vendors(mysql_conn, db, Vendor):
|
||||
"""Import vendors from MySQL."""
|
||||
print("Importing vendors...")
|
||||
cursor = mysql_conn.cursor()
|
||||
cursor.execute("SELECT * FROM vendors WHERE isactive = 1")
|
||||
vendors = cursor.fetchall()
|
||||
|
||||
count = 0
|
||||
for v in vendors:
|
||||
existing = Vendor.query.filter_by(vendor=v['vendor']).first()
|
||||
if not existing:
|
||||
vendor = Vendor(
|
||||
vendor=v['vendor'],
|
||||
isactive=True
|
||||
)
|
||||
db.session.add(vendor)
|
||||
count += 1
|
||||
|
||||
db.session.commit()
|
||||
print(f" Imported {count} vendors")
|
||||
return count
|
||||
|
||||
|
||||
def import_machinetypes(mysql_conn, db, MachineType):
|
||||
"""Import machine types from MySQL with category mapping."""
|
||||
print("Importing machine types...")
|
||||
cursor = mysql_conn.cursor()
|
||||
cursor.execute("SELECT * FROM machinetypes WHERE isactive = 1")
|
||||
types = cursor.fetchall()
|
||||
|
||||
# Category mapping based on machinetype name
|
||||
pc_types = ['PC']
|
||||
network_types = ['Access Point', 'IDF', 'Switch', 'Server', 'Camera']
|
||||
printer_types = ['Printer']
|
||||
|
||||
count = 0
|
||||
for t in types:
|
||||
existing = MachineType.query.filter_by(machinetype=t['machinetype']).first()
|
||||
if not existing:
|
||||
# Determine category
|
||||
if t['machinetype'] in pc_types:
|
||||
category = 'PC'
|
||||
elif t['machinetype'] in network_types:
|
||||
category = 'Network'
|
||||
elif t['machinetype'] in printer_types:
|
||||
category = 'Printer'
|
||||
else:
|
||||
category = 'Equipment'
|
||||
|
||||
mt = MachineType(
|
||||
machinetype=t['machinetype'],
|
||||
category=category,
|
||||
description=t.get('machinedescription'),
|
||||
isactive=True
|
||||
)
|
||||
db.session.add(mt)
|
||||
count += 1
|
||||
|
||||
db.session.commit()
|
||||
print(f" Imported {count} machine types")
|
||||
return count
|
||||
|
||||
|
||||
def import_pctypes(mysql_conn, db, PCType):
|
||||
"""Import PC types from MySQL."""
|
||||
print("Importing PC types...")
|
||||
cursor = mysql_conn.cursor()
|
||||
cursor.execute("SELECT * FROM pctype WHERE isactive = '1'")
|
||||
types = cursor.fetchall()
|
||||
|
||||
count = 0
|
||||
for t in types:
|
||||
existing = PCType.query.filter_by(pctype=t['typename']).first()
|
||||
if not existing:
|
||||
pctype = PCType(
|
||||
pctype=t['typename'],
|
||||
description=t.get('description'),
|
||||
isactive=True
|
||||
)
|
||||
db.session.add(pctype)
|
||||
count += 1
|
||||
|
||||
db.session.commit()
|
||||
print(f" Imported {count} PC types")
|
||||
return count
|
||||
|
||||
|
||||
def import_businessunits(mysql_conn, db, BusinessUnit):
|
||||
"""Import business units from MySQL."""
|
||||
print("Importing business units...")
|
||||
cursor = mysql_conn.cursor()
|
||||
cursor.execute("SELECT * FROM businessunits WHERE isactive = 1")
|
||||
units = cursor.fetchall()
|
||||
|
||||
count = 0
|
||||
for bu in units:
|
||||
existing = BusinessUnit.query.filter_by(businessunit=bu['businessunit']).first()
|
||||
if not existing:
|
||||
unit = BusinessUnit(
|
||||
businessunit=bu['businessunit'],
|
||||
isactive=True
|
||||
)
|
||||
db.session.add(unit)
|
||||
count += 1
|
||||
|
||||
db.session.commit()
|
||||
print(f" Imported {count} business units")
|
||||
return count
|
||||
|
||||
|
||||
def import_statuses(mysql_conn, db, MachineStatus):
|
||||
"""Import machine statuses from MySQL."""
|
||||
print("Importing machine statuses...")
|
||||
cursor = mysql_conn.cursor()
|
||||
cursor.execute("SELECT * FROM machinestatus WHERE isactive = 1")
|
||||
statuses = cursor.fetchall()
|
||||
|
||||
count = 0
|
||||
for s in statuses:
|
||||
existing = MachineStatus.query.filter_by(status=s['machinestatus']).first()
|
||||
if not existing:
|
||||
status = MachineStatus(
|
||||
status=s['machinestatus'],
|
||||
description=s.get('statusdescription'),
|
||||
isactive=True
|
||||
)
|
||||
db.session.add(status)
|
||||
count += 1
|
||||
|
||||
db.session.commit()
|
||||
print(f" Imported {count} statuses")
|
||||
return count
|
||||
|
||||
|
||||
def import_operatingsystems(mysql_conn, db, OperatingSystem):
|
||||
"""Import operating systems from MySQL."""
|
||||
print("Importing operating systems...")
|
||||
cursor = mysql_conn.cursor()
|
||||
cursor.execute("SELECT * FROM operatingsystems")
|
||||
os_list = cursor.fetchall()
|
||||
|
||||
count = 0
|
||||
for os_item in os_list:
|
||||
os_name = os_item.get('operatingsystem') or os_item.get('osname')
|
||||
if not os_name:
|
||||
continue
|
||||
|
||||
existing = OperatingSystem.query.filter_by(osname=os_name).first()
|
||||
if not existing:
|
||||
os_obj = OperatingSystem(
|
||||
osname=os_name,
|
||||
osversion=os_item.get('osversion'),
|
||||
isactive=True
|
||||
)
|
||||
db.session.add(os_obj)
|
||||
count += 1
|
||||
|
||||
db.session.commit()
|
||||
print(f" Imported {count} operating systems")
|
||||
return count
|
||||
|
||||
|
||||
def import_models(mysql_conn, db, Model, Vendor, MachineType):
|
||||
"""Import models from MySQL."""
|
||||
print("Importing models...")
|
||||
cursor = mysql_conn.cursor()
|
||||
cursor.execute("""
|
||||
SELECT m.*, v.vendor as vendor_name, mt.machinetype as type_name
|
||||
FROM models m
|
||||
LEFT JOIN vendors v ON m.vendorid = v.vendorid
|
||||
LEFT JOIN machinetypes mt ON m.machinetypeid = mt.machinetypeid
|
||||
WHERE m.isactive = 1
|
||||
""")
|
||||
models = cursor.fetchall()
|
||||
|
||||
count = 0
|
||||
for m in models:
|
||||
existing = Model.query.filter_by(modelnumber=m['modelnumber']).first()
|
||||
if not existing:
|
||||
# Find vendor and machinetype in new db
|
||||
vendor = Vendor.query.filter_by(vendor=m['vendor_name']).first() if m['vendor_name'] else None
|
||||
machinetype = MachineType.query.filter_by(machinetype=m['type_name']).first() if m['type_name'] else None
|
||||
|
||||
model = Model(
|
||||
modelnumber=m['modelnumber'],
|
||||
vendorid=vendor.vendorid if vendor else None,
|
||||
machinetypeid=machinetype.machinetypeid if machinetype else None,
|
||||
notes=m.get('notes'),
|
||||
isactive=True
|
||||
)
|
||||
db.session.add(model)
|
||||
count += 1
|
||||
|
||||
db.session.commit()
|
||||
print(f" Imported {count} models")
|
||||
return count
|
||||
|
||||
|
||||
def import_relationshiptypes(mysql_conn, db, RelationshipType):
|
||||
"""Import relationship types from MySQL."""
|
||||
print("Importing relationship/connection types...")
|
||||
cursor = mysql_conn.cursor()
|
||||
cursor.execute("SELECT * FROM relationshiptypes WHERE isactive = 1")
|
||||
types = cursor.fetchall()
|
||||
|
||||
count = 0
|
||||
for rt in types:
|
||||
existing = RelationshipType.query.filter_by(relationshiptype=rt['relationshiptype']).first()
|
||||
if not existing:
|
||||
rel_type = RelationshipType(
|
||||
relationshiptype=rt['relationshiptype'],
|
||||
description=rt.get('description'),
|
||||
isactive=True
|
||||
)
|
||||
db.session.add(rel_type)
|
||||
count += 1
|
||||
|
||||
db.session.commit()
|
||||
print(f" Imported {count} relationship types")
|
||||
return count
|
||||
|
||||
|
||||
def import_machines(mysql_conn, db, Machine, MachineType, MachineStatus,
|
||||
Vendor, Model, BusinessUnit, OperatingSystem, Location,
|
||||
Communication, CommunicationType, PCType):
|
||||
"""Import machines (Equipment and PCs) from MySQL."""
|
||||
print("Importing machines...")
|
||||
cursor = mysql_conn.cursor()
|
||||
|
||||
# Get machines with related data
|
||||
cursor.execute("""
|
||||
SELECT m.*,
|
||||
mt.machinetype as type_name,
|
||||
ms.machinestatus as status_name,
|
||||
v.vendor as vendor_name,
|
||||
mdl.modelnumber as model_name,
|
||||
bu.businessunit as bu_name,
|
||||
os.operatingsystem as os_name,
|
||||
pt.typename as pctype_name
|
||||
FROM machines m
|
||||
LEFT JOIN machinetypes mt ON m.machinetypeid = mt.machinetypeid
|
||||
LEFT JOIN machinestatus ms ON m.machinestatusid = ms.machinestatusid
|
||||
LEFT JOIN models mdl ON m.modelnumberid = mdl.modelnumberid
|
||||
LEFT JOIN vendors v ON mdl.vendorid = v.vendorid
|
||||
LEFT JOIN businessunits bu ON m.businessunitid = bu.businessunitid
|
||||
LEFT JOIN operatingsystems os ON m.osid = os.osid
|
||||
LEFT JOIN pctype pt ON m.pctypeid = pt.pctypeid
|
||||
WHERE m.isactive = 1
|
||||
""")
|
||||
machines = cursor.fetchall()
|
||||
|
||||
# Get or create IP communication type
|
||||
ip_comtype = CommunicationType.query.filter_by(comtype='IP').first()
|
||||
if not ip_comtype:
|
||||
ip_comtype = CommunicationType(comtype='IP', description='IP Network')
|
||||
db.session.add(ip_comtype)
|
||||
db.session.flush()
|
||||
|
||||
# Build lookup maps
|
||||
type_map = {t.machinetype: t for t in MachineType.query.all()}
|
||||
status_map = {s.status: s for s in MachineStatus.query.all()}
|
||||
vendor_map = {v.vendor: v for v in Vendor.query.all()}
|
||||
model_map = {m.modelnumber: m for m in Model.query.all()}
|
||||
bu_map = {b.businessunit: b for b in BusinessUnit.query.all()}
|
||||
os_map = {o.osname: o for o in OperatingSystem.query.all()}
|
||||
pctype_map = {p.pctype: p for p in PCType.query.all()}
|
||||
|
||||
# Track old->new ID mapping for relationships
|
||||
machine_id_map = {}
|
||||
|
||||
count = 0
|
||||
comm_count = 0
|
||||
skipped = 0
|
||||
for m in machines:
|
||||
# Skip machines without a machinenumber
|
||||
if not m.get('machinenumber'):
|
||||
skipped += 1
|
||||
continue
|
||||
|
||||
# Check if already exists
|
||||
existing = Machine.query.filter_by(machinenumber=m['machinenumber']).first()
|
||||
if existing:
|
||||
machine_id_map[m['machineid']] = existing.machineid
|
||||
continue
|
||||
|
||||
# Get related objects
|
||||
machinetype = type_map.get(m['type_name'])
|
||||
status = status_map.get(m['status_name'])
|
||||
vendor = vendor_map.get(m['vendor_name'])
|
||||
model = model_map.get(m['model_name'])
|
||||
bu = bu_map.get(m['bu_name'])
|
||||
os_obj = os_map.get(m['os_name'])
|
||||
pctype = pctype_map.get(m['pctype_name'])
|
||||
|
||||
machine = Machine(
|
||||
machinenumber=m['machinenumber'],
|
||||
alias=m.get('alias'),
|
||||
hostname=m.get('hostname'),
|
||||
serialnumber=m.get('serialnumber'),
|
||||
machinetypeid=machinetype.machinetypeid if machinetype else None,
|
||||
pctypeid=pctype.pctypeid if pctype else None,
|
||||
statusid=status.statusid if status else None,
|
||||
vendorid=vendor.vendorid if vendor else None,
|
||||
modelnumberid=model.modelnumberid if model else None,
|
||||
businessunitid=bu.businessunitid if bu else None,
|
||||
osid=os_obj.osid if os_obj else None,
|
||||
mapleft=m.get('mapleft'),
|
||||
maptop=m.get('maptop'),
|
||||
isvnc=bool(m.get('isvnc')),
|
||||
iswinrm=bool(m.get('iswinrm')),
|
||||
islocationonly=bool(m.get('islocationonly')),
|
||||
loggedinuser=m.get('loggedinuser'),
|
||||
notes=m.get('machinenotes'),
|
||||
isactive=True
|
||||
)
|
||||
db.session.add(machine)
|
||||
db.session.flush() # Get the new ID
|
||||
|
||||
machine_id_map[m['machineid']] = machine.machineid
|
||||
count += 1
|
||||
|
||||
# Import IP addresses
|
||||
if m.get('ipaddress1'):
|
||||
comm = Communication(
|
||||
machineid=machine.machineid,
|
||||
comtypeid=ip_comtype.comtypeid,
|
||||
ipaddress=m['ipaddress1'],
|
||||
isprimary=True
|
||||
)
|
||||
db.session.add(comm)
|
||||
comm_count += 1
|
||||
|
||||
if m.get('ipaddress2'):
|
||||
comm = Communication(
|
||||
machineid=machine.machineid,
|
||||
comtypeid=ip_comtype.comtypeid,
|
||||
ipaddress=m['ipaddress2'],
|
||||
isprimary=False
|
||||
)
|
||||
db.session.add(comm)
|
||||
comm_count += 1
|
||||
|
||||
db.session.commit()
|
||||
print(f" Imported {count} machines with {comm_count} IP addresses (skipped {skipped} invalid)")
|
||||
return machine_id_map
|
||||
|
||||
|
||||
def import_relationships(mysql_conn, db, MachineRelationship, RelationshipType, machine_id_map):
|
||||
"""Import machine relationships from MySQL."""
|
||||
print("Importing machine relationships...")
|
||||
cursor = mysql_conn.cursor()
|
||||
cursor.execute("""
|
||||
SELECT mr.*, rt.relationshiptype
|
||||
FROM machinerelationships mr
|
||||
JOIN relationshiptypes rt ON mr.relationshiptypeid = rt.relationshiptypeid
|
||||
WHERE mr.isactive = 1
|
||||
""")
|
||||
relationships = cursor.fetchall()
|
||||
|
||||
# Build relationship type map
|
||||
type_map = {t.relationshiptype: t for t in RelationshipType.query.all()}
|
||||
|
||||
count = 0
|
||||
skipped = 0
|
||||
for r in relationships:
|
||||
# Map old IDs to new IDs
|
||||
parent_id = machine_id_map.get(r['machineid'])
|
||||
child_id = machine_id_map.get(r['related_machineid'])
|
||||
|
||||
if not parent_id or not child_id:
|
||||
skipped += 1
|
||||
continue
|
||||
|
||||
rel_type = type_map.get(r['relationshiptype'])
|
||||
if not rel_type:
|
||||
skipped += 1
|
||||
continue
|
||||
|
||||
# Check if already exists
|
||||
existing = MachineRelationship.query.filter_by(
|
||||
parentmachineid=parent_id,
|
||||
childmachineid=child_id,
|
||||
relationshiptypeid=rel_type.relationshiptypeid
|
||||
).first()
|
||||
|
||||
if not existing:
|
||||
relationship = MachineRelationship(
|
||||
parentmachineid=parent_id,
|
||||
childmachineid=child_id,
|
||||
relationshiptypeid=rel_type.relationshiptypeid,
|
||||
notes=r.get('relationship_notes')
|
||||
)
|
||||
db.session.add(relationship)
|
||||
count += 1
|
||||
|
||||
db.session.commit()
|
||||
print(f" Imported {count} relationships (skipped {skipped})")
|
||||
return count
|
||||
|
||||
|
||||
def import_printers(mysql_conn, db, Machine, MachineType, Model, Vendor,
|
||||
Communication, CommunicationType):
|
||||
"""Import printers from MySQL."""
|
||||
print("Importing printers...")
|
||||
|
||||
# First, ensure we have a Printer machine type
|
||||
printer_type = MachineType.query.filter_by(machinetype='Printer').first()
|
||||
if not printer_type:
|
||||
printer_type = MachineType(machinetype='Printer', category='Printer')
|
||||
db.session.add(printer_type)
|
||||
db.session.flush()
|
||||
|
||||
# Get or create IP communication type
|
||||
ip_comtype = CommunicationType.query.filter_by(comtype='IP').first()
|
||||
if not ip_comtype:
|
||||
ip_comtype = CommunicationType(comtype='IP', description='IP Network')
|
||||
db.session.add(ip_comtype)
|
||||
db.session.flush()
|
||||
|
||||
cursor = mysql_conn.cursor()
|
||||
cursor.execute("""
|
||||
SELECT p.*, m.modelnumber, v.vendor as vendor_name
|
||||
FROM printers p
|
||||
LEFT JOIN models m ON p.modelid = m.modelnumberid
|
||||
LEFT JOIN vendors v ON m.vendorid = v.vendorid
|
||||
WHERE p.isactive = 1
|
||||
""")
|
||||
printers = cursor.fetchall()
|
||||
|
||||
# Build lookup maps
|
||||
model_map = {m.modelnumber: m for m in Model.query.all()}
|
||||
vendor_map = {v.vendor: v for v in Vendor.query.all()}
|
||||
|
||||
count = 0
|
||||
comm_count = 0
|
||||
for p in printers:
|
||||
# Use windows name as machine number
|
||||
machine_number = p.get('printerwindowsname') or f"Printer_{p['printerid']}"
|
||||
|
||||
existing = Machine.query.filter_by(machinenumber=machine_number).first()
|
||||
if existing:
|
||||
continue
|
||||
|
||||
model = model_map.get(p.get('modelnumber'))
|
||||
vendor = vendor_map.get(p.get('vendor_name'))
|
||||
|
||||
machine = Machine(
|
||||
machinenumber=machine_number,
|
||||
alias=p.get('printercsfname'),
|
||||
hostname=p.get('fqdn'),
|
||||
serialnumber=p.get('serialnumber'),
|
||||
machinetypeid=printer_type.machinetypeid,
|
||||
vendorid=vendor.vendorid if vendor else None,
|
||||
modelnumberid=model.modelnumberid if model else None,
|
||||
mapleft=p.get('mapleft'),
|
||||
maptop=p.get('maptop'),
|
||||
notes=p.get('printernotes'),
|
||||
isactive=True
|
||||
)
|
||||
db.session.add(machine)
|
||||
db.session.flush()
|
||||
count += 1
|
||||
|
||||
# Import IP address
|
||||
if p.get('ipaddress'):
|
||||
comm = Communication(
|
||||
machineid=machine.machineid,
|
||||
comtypeid=ip_comtype.comtypeid,
|
||||
ipaddress=p['ipaddress'],
|
||||
isprimary=True
|
||||
)
|
||||
db.session.add(comm)
|
||||
comm_count += 1
|
||||
|
||||
db.session.commit()
|
||||
print(f" Imported {count} printers with {comm_count} IP addresses")
|
||||
return count
|
||||
|
||||
|
||||
def main():
|
||||
"""Main import function."""
|
||||
print("=" * 60)
|
||||
print("ShopDB MySQL to Flask Migration")
|
||||
print("=" * 60)
|
||||
|
||||
# Initialize Flask app
|
||||
from shopdb import create_app
|
||||
from shopdb.extensions import db
|
||||
from shopdb.core.models import (
|
||||
Machine, MachineType, MachineStatus, Vendor, Model,
|
||||
BusinessUnit, OperatingSystem, Location, PCType
|
||||
)
|
||||
from shopdb.core.models.communication import Communication, CommunicationType
|
||||
from shopdb.core.models.relationship import MachineRelationship, RelationshipType
|
||||
|
||||
app = create_app()
|
||||
|
||||
with app.app_context():
|
||||
# Connect to MySQL
|
||||
print("\nConnecting to MySQL...")
|
||||
mysql_conn = get_mysql_connection()
|
||||
print(" Connected!")
|
||||
|
||||
try:
|
||||
# Import reference data
|
||||
print("\n--- Reference Data ---")
|
||||
import_vendors(mysql_conn, db, Vendor)
|
||||
import_machinetypes(mysql_conn, db, MachineType)
|
||||
import_pctypes(mysql_conn, db, PCType)
|
||||
import_businessunits(mysql_conn, db, BusinessUnit)
|
||||
import_statuses(mysql_conn, db, MachineStatus)
|
||||
import_operatingsystems(mysql_conn, db, OperatingSystem)
|
||||
import_models(mysql_conn, db, Model, Vendor, MachineType)
|
||||
import_relationshiptypes(mysql_conn, db, RelationshipType)
|
||||
|
||||
# Import machines
|
||||
print("\n--- Machines ---")
|
||||
machine_id_map = import_machines(
|
||||
mysql_conn, db, Machine, MachineType, MachineStatus,
|
||||
Vendor, Model, BusinessUnit, OperatingSystem, Location,
|
||||
Communication, CommunicationType, PCType
|
||||
)
|
||||
|
||||
# Import relationships
|
||||
print("\n--- Relationships ---")
|
||||
import_relationships(mysql_conn, db, MachineRelationship, RelationshipType, machine_id_map)
|
||||
|
||||
# Import printers
|
||||
print("\n--- Printers ---")
|
||||
import_printers(mysql_conn, db, Machine, MachineType, Model, Vendor,
|
||||
Communication, CommunicationType)
|
||||
|
||||
print("\n" + "=" * 60)
|
||||
print("Import complete!")
|
||||
print("=" * 60)
|
||||
|
||||
finally:
|
||||
mysql_conn.close()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Reference in New Issue
Block a user