"""baseline schema

Revision ID: 68b3947ae14f
Revises: 
Create Date: 2026-05-08 17:53:08.342776

"""
from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision = '68b3947ae14f'
down_revision = None
branch_labels = None
depends_on = None


def upgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.create_table('appowners',
    sa.Column('appownerid', sa.Integer(), nullable=False),
    sa.Column('appowner', sa.String(length=100), nullable=False),
    sa.Column('sso', sa.String(length=50), nullable=True),
    sa.Column('email', sa.String(length=100), nullable=True),
    sa.Column('createddate', sa.DateTime(), nullable=False),
    sa.Column('modifieddate', sa.DateTime(), nullable=False),
    sa.Column('isactive', sa.Boolean(), nullable=False),
    sa.PrimaryKeyConstraint('appownerid')
    )
    op.create_table('assetstatuses',
    sa.Column('statusid', sa.Integer(), nullable=False),
    sa.Column('status', sa.String(length=50), nullable=False),
    sa.Column('description', sa.Text(), nullable=True),
    sa.Column('color', sa.String(length=20), nullable=True, comment='CSS color for UI'),
    sa.Column('createddate', sa.DateTime(), nullable=False),
    sa.Column('modifieddate', sa.DateTime(), nullable=False),
    sa.Column('isactive', sa.Boolean(), nullable=False),
    sa.PrimaryKeyConstraint('statusid'),
    sa.UniqueConstraint('status')
    )
    op.create_table('assettypes',
    sa.Column('assettypeid', sa.Integer(), nullable=False),
    sa.Column('assettype', sa.String(length=50), nullable=False, comment='Category name: equipment, computer, network_device, printer'),
    sa.Column('pluginname', sa.String(length=100), nullable=True, comment='Plugin that owns this type'),
    sa.Column('tablename', sa.String(length=100), nullable=True, comment='Extension table name for this type'),
    sa.Column('description', sa.Text(), nullable=True),
    sa.Column('icon', sa.String(length=50), nullable=True, comment='Icon name for UI'),
    sa.Column('createddate', sa.DateTime(), nullable=False),
    sa.Column('modifieddate', sa.DateTime(), nullable=False),
    sa.Column('isactive', sa.Boolean(), nullable=False),
    sa.PrimaryKeyConstraint('assettypeid'),
    sa.UniqueConstraint('assettype')
    )
    op.create_table('businessunits',
    sa.Column('businessunitid', sa.Integer(), nullable=False),
    sa.Column('businessunit', sa.String(length=100), nullable=False),
    sa.Column('code', sa.String(length=20), nullable=True, comment='Short code'),
    sa.Column('description', sa.Text(), nullable=True),
    sa.Column('parentid', sa.Integer(), nullable=True),
    sa.Column('createddate', sa.DateTime(), nullable=False),
    sa.Column('modifieddate', sa.DateTime(), nullable=False),
    sa.Column('isactive', sa.Boolean(), nullable=False),
    sa.ForeignKeyConstraint(['parentid'], ['businessunits.businessunitid'], ),
    sa.PrimaryKeyConstraint('businessunitid'),
    sa.UniqueConstraint('businessunit'),
    sa.UniqueConstraint('code')
    )
    op.create_table('communicationtypes',
    sa.Column('comtypeid', sa.Integer(), nullable=False),
    sa.Column('comtype', sa.String(length=50), nullable=False),
    sa.Column('description', sa.Text(), nullable=True),
    sa.Column('createddate', sa.DateTime(), nullable=False),
    sa.Column('modifieddate', sa.DateTime(), nullable=False),
    sa.Column('isactive', sa.Boolean(), nullable=False),
    sa.PrimaryKeyConstraint('comtypeid'),
    sa.UniqueConstraint('comtype')
    )
    op.create_table('computertypes',
    sa.Column('computertypeid', sa.Integer(), nullable=False),
    sa.Column('computertype', sa.String(length=100), nullable=False),
    sa.Column('description', sa.Text(), nullable=True),
    sa.Column('icon', sa.String(length=50), nullable=True, comment='Icon name for UI'),
    sa.Column('createddate', sa.DateTime(), nullable=False),
    sa.Column('modifieddate', sa.DateTime(), nullable=False),
    sa.Column('isactive', sa.Boolean(), nullable=False),
    sa.PrimaryKeyConstraint('computertypeid'),
    sa.UniqueConstraint('computertype')
    )
    op.create_table('equipmenttypes',
    sa.Column('equipmenttypeid', sa.Integer(), nullable=False),
    sa.Column('equipmenttype', sa.String(length=100), nullable=False),
    sa.Column('description', sa.Text(), nullable=True),
    sa.Column('icon', sa.String(length=50), nullable=True, comment='Icon name for UI'),
    sa.Column('createddate', sa.DateTime(), nullable=False),
    sa.Column('modifieddate', sa.DateTime(), nullable=False),
    sa.Column('isactive', sa.Boolean(), nullable=False),
    sa.PrimaryKeyConstraint('equipmenttypeid'),
    sa.UniqueConstraint('equipmenttype')
    )
    op.create_table('locations',
    sa.Column('locationid', sa.Integer(), nullable=False),
    sa.Column('locationname', sa.String(length=100), nullable=False),
    sa.Column('building', sa.String(length=100), nullable=True),
    sa.Column('floor', sa.String(length=50), nullable=True),
    sa.Column('room', sa.String(length=50), nullable=True),
    sa.Column('description', sa.Text(), nullable=True),
    sa.Column('mapimage', sa.String(length=500), nullable=True, comment='Path to floor map image'),
    sa.Column('mapwidth', sa.Integer(), nullable=True),
    sa.Column('mapheight', sa.Integer(), nullable=True),
    sa.Column('createddate', sa.DateTime(), nullable=False),
    sa.Column('modifieddate', sa.DateTime(), nullable=False),
    sa.Column('isactive', sa.Boolean(), nullable=False),
    sa.PrimaryKeyConstraint('locationid'),
    sa.UniqueConstraint('locationname')
    )
    op.create_table('machinestatuses',
    sa.Column('statusid', sa.Integer(), nullable=False),
    sa.Column('status', sa.String(length=50), nullable=False),
    sa.Column('description', sa.Text(), nullable=True),
    sa.Column('color', sa.String(length=20), nullable=True, comment='CSS color for UI'),
    sa.Column('createddate', sa.DateTime(), nullable=False),
    sa.Column('modifieddate', sa.DateTime(), nullable=False),
    sa.Column('isactive', sa.Boolean(), nullable=False),
    sa.PrimaryKeyConstraint('statusid'),
    sa.UniqueConstraint('status')
    )
    op.create_table('machinetypes',
    sa.Column('machinetypeid', sa.Integer(), nullable=False),
    sa.Column('machinetype', sa.String(length=100), nullable=False),
    sa.Column('category', sa.String(length=50), nullable=False, comment='Equipment, PC, Network, or Printer'),
    sa.Column('description', sa.Text(), nullable=True),
    sa.Column('icon', sa.String(length=50), nullable=True, comment='Icon name for UI'),
    sa.Column('createddate', sa.DateTime(), nullable=False),
    sa.Column('modifieddate', sa.DateTime(), nullable=False),
    sa.Column('isactive', sa.Boolean(), nullable=False),
    sa.PrimaryKeyConstraint('machinetypeid'),
    sa.UniqueConstraint('machinetype')
    )
    op.create_table('networkdevicetypes',
    sa.Column('networkdevicetypeid', sa.Integer(), nullable=False),
    sa.Column('networkdevicetype', sa.String(length=100), nullable=False),
    sa.Column('description', sa.Text(), nullable=True),
    sa.Column('icon', sa.String(length=50), nullable=True, comment='Icon name for UI'),
    sa.Column('createddate', sa.DateTime(), nullable=False),
    sa.Column('modifieddate', sa.DateTime(), nullable=False),
    sa.Column('isactive', sa.Boolean(), nullable=False),
    sa.PrimaryKeyConstraint('networkdevicetypeid'),
    sa.UniqueConstraint('networkdevicetype')
    )
    op.create_table('notificationtypes',
    sa.Column('notificationtypeid', sa.Integer(), nullable=False),
    sa.Column('typename', sa.String(length=50), nullable=False),
    sa.Column('typedescription', sa.Text(), nullable=True),
    sa.Column('typecolor', sa.String(length=20), nullable=True),
    sa.Column('isactive', sa.Boolean(), nullable=True),
    sa.PrimaryKeyConstraint('notificationtypeid')
    )
    op.create_table('operatingsystems',
    sa.Column('osid', sa.Integer(), nullable=False),
    sa.Column('osname', sa.String(length=100), nullable=False),
    sa.Column('osversion', sa.String(length=50), nullable=True),
    sa.Column('architecture', sa.String(length=20), nullable=True, comment='x86, x64, ARM'),
    sa.Column('endoflife', sa.Date(), nullable=True, comment='End of support date'),
    sa.Column('createddate', sa.DateTime(), nullable=False),
    sa.Column('modifieddate', sa.DateTime(), nullable=False),
    sa.Column('isactive', sa.Boolean(), nullable=False),
    sa.PrimaryKeyConstraint('osid'),
    sa.UniqueConstraint('osname', 'osversion', name='uq_os_name_version')
    )
    op.create_table('pctypes',
    sa.Column('pctypeid', sa.Integer(), nullable=False),
    sa.Column('pctype', sa.String(length=100), nullable=False),
    sa.Column('description', sa.Text(), nullable=True),
    sa.Column('createddate', sa.DateTime(), nullable=False),
    sa.Column('modifieddate', sa.DateTime(), nullable=False),
    sa.Column('isactive', sa.Boolean(), nullable=False),
    sa.PrimaryKeyConstraint('pctypeid'),
    sa.UniqueConstraint('pctype')
    )
    op.create_table('permissions',
    sa.Column('permissionid', sa.Integer(), nullable=False),
    sa.Column('name', sa.String(length=50), nullable=False),
    sa.Column('description', sa.String(length=255), nullable=True),
    sa.Column('category', sa.String(length=50), nullable=True),
    sa.PrimaryKeyConstraint('permissionid'),
    sa.UniqueConstraint('name')
    )
    op.create_table('printertypes',
    sa.Column('printertypeid', sa.Integer(), nullable=False),
    sa.Column('printertype', sa.String(length=100), nullable=False),
    sa.Column('description', sa.Text(), nullable=True),
    sa.Column('icon', sa.String(length=50), nullable=True, comment='Icon name for UI'),
    sa.Column('createddate', sa.DateTime(), nullable=False),
    sa.Column('modifieddate', sa.DateTime(), nullable=False),
    sa.Column('isactive', sa.Boolean(), nullable=False),
    sa.PrimaryKeyConstraint('printertypeid'),
    sa.UniqueConstraint('printertype')
    )
    op.create_table('relationshiptypes',
    sa.Column('relationshiptypeid', sa.Integer(), nullable=False),
    sa.Column('relationshiptype', sa.String(length=50), nullable=False),
    sa.Column('description', sa.Text(), nullable=True),
    sa.Column('createddate', sa.DateTime(), nullable=False),
    sa.Column('modifieddate', sa.DateTime(), nullable=False),
    sa.Column('isactive', sa.Boolean(), nullable=False),
    sa.PrimaryKeyConstraint('relationshiptypeid'),
    sa.UniqueConstraint('relationshiptype')
    )
    op.create_table('roles',
    sa.Column('roleid', sa.Integer(), nullable=False),
    sa.Column('rolename', sa.String(length=50), nullable=False),
    sa.Column('description', sa.Text(), nullable=True),
    sa.Column('createddate', sa.DateTime(), nullable=False),
    sa.Column('modifieddate', sa.DateTime(), nullable=False),
    sa.Column('isactive', sa.Boolean(), nullable=False),
    sa.PrimaryKeyConstraint('roleid'),
    sa.UniqueConstraint('rolename')
    )
    op.create_table('settings',
    sa.Column('settingid', sa.Integer(), autoincrement=True, nullable=False),
    sa.Column('key', sa.String(length=100), nullable=False),
    sa.Column('value', sa.Text(), nullable=True),
    sa.Column('valuetype', sa.String(length=20), nullable=True),
    sa.Column('category', sa.String(length=50), nullable=True),
    sa.Column('description', sa.String(length=255), nullable=True),
    sa.Column('createddate', sa.DateTime(), nullable=True),
    sa.Column('modifieddate', sa.DateTime(), nullable=True),
    sa.PrimaryKeyConstraint('settingid')
    )
    with op.batch_alter_table('settings', schema=None) as batch_op:
        batch_op.create_index(batch_op.f('ix_settings_key'), ['key'], unique=True)

    op.create_table('usbdevicetypes',
    sa.Column('usbdevicetypeid', sa.Integer(), nullable=False),
    sa.Column('typename', sa.String(length=50), nullable=False),
    sa.Column('description', sa.Text(), nullable=True),
    sa.Column('icon', sa.String(length=50), nullable=True, comment='Icon name for UI'),
    sa.Column('createddate', sa.DateTime(), nullable=False),
    sa.Column('modifieddate', sa.DateTime(), nullable=False),
    sa.Column('isactive', sa.Boolean(), nullable=False),
    sa.PrimaryKeyConstraint('usbdevicetypeid'),
    sa.UniqueConstraint('typename')
    )
    op.create_table('users',
    sa.Column('userid', sa.Integer(), nullable=False),
    sa.Column('username', sa.String(length=100), nullable=False),
    sa.Column('email', sa.String(length=255), nullable=False),
    sa.Column('passwordhash', sa.String(length=255), nullable=False),
    sa.Column('firstname', sa.String(length=100), nullable=True),
    sa.Column('lastname', sa.String(length=100), nullable=True),
    sa.Column('lastlogindate', sa.DateTime(), nullable=True),
    sa.Column('failedlogins', sa.Integer(), nullable=True),
    sa.Column('lockeduntil', sa.DateTime(), nullable=True),
    sa.Column('createddate', sa.DateTime(), nullable=False),
    sa.Column('modifieddate', sa.DateTime(), nullable=False),
    sa.Column('isactive', sa.Boolean(), nullable=False),
    sa.PrimaryKeyConstraint('userid'),
    sa.UniqueConstraint('email')
    )
    with op.batch_alter_table('users', schema=None) as batch_op:
        batch_op.create_index(batch_op.f('ix_users_username'), ['username'], unique=True)

    op.create_table('vendors',
    sa.Column('vendorid', sa.Integer(), nullable=False),
    sa.Column('vendor', sa.String(length=100), nullable=False),
    sa.Column('description', sa.Text(), nullable=True),
    sa.Column('website', sa.String(length=255), nullable=True),
    sa.Column('supportphone', sa.String(length=50), nullable=True),
    sa.Column('supportemail', sa.String(length=100), nullable=True),
    sa.Column('notes', sa.Text(), nullable=True),
    sa.Column('createddate', sa.DateTime(), nullable=False),
    sa.Column('modifieddate', sa.DateTime(), nullable=False),
    sa.Column('isactive', sa.Boolean(), nullable=False),
    sa.PrimaryKeyConstraint('vendorid'),
    sa.UniqueConstraint('vendor')
    )
    op.create_table('vlans',
    sa.Column('vlanid', sa.Integer(), nullable=False),
    sa.Column('vlannumber', sa.Integer(), nullable=False, comment='VLAN ID number'),
    sa.Column('name', sa.String(length=100), nullable=False, comment='VLAN name'),
    sa.Column('description', sa.Text(), nullable=True),
    sa.Column('vlantype', sa.String(length=50), nullable=True, comment='Type: data, voice, management, guest, etc.'),
    sa.Column('createddate', sa.DateTime(), nullable=False),
    sa.Column('modifieddate', sa.DateTime(), nullable=False),
    sa.Column('isactive', sa.Boolean(), nullable=False),
    sa.PrimaryKeyConstraint('vlanid'),
    sa.UniqueConstraint('vlannumber')
    )
    with op.batch_alter_table('vlans', schema=None) as batch_op:
        batch_op.create_index('idx_vlan_number', ['vlannumber'], unique=False)

    op.create_table('assets',
    sa.Column('assetid', sa.Integer(), nullable=False),
    sa.Column('assetnumber', sa.String(length=50), nullable=False, comment='Business identifier (e.g., CMM01, G5QX1GT3ESF)'),
    sa.Column('name', sa.String(length=100), nullable=True, comment='Display name/alias'),
    sa.Column('serialnumber', sa.String(length=100), nullable=True, comment='Hardware serial number'),
    sa.Column('assettypeid', sa.Integer(), nullable=False),
    sa.Column('statusid', sa.Integer(), nullable=True, comment='In Use, Spare, Retired, etc.'),
    sa.Column('locationid', sa.Integer(), nullable=True),
    sa.Column('businessunitid', sa.Integer(), nullable=True),
    sa.Column('mapleft', sa.Integer(), nullable=True, comment='X coordinate on floor map'),
    sa.Column('maptop', sa.Integer(), nullable=True, comment='Y coordinate on floor map'),
    sa.Column('notes', sa.Text(), nullable=True),
    sa.Column('createddate', sa.DateTime(), nullable=False),
    sa.Column('modifieddate', sa.DateTime(), nullable=False),
    sa.Column('isactive', sa.Boolean(), nullable=False),
    sa.Column('deleteddate', sa.DateTime(), nullable=True),
    sa.Column('deletedby', sa.String(length=100), nullable=True),
    sa.Column('createdby', sa.String(length=100), nullable=True),
    sa.Column('modifiedby', sa.String(length=100), nullable=True),
    sa.ForeignKeyConstraint(['assettypeid'], ['assettypes.assettypeid'], ),
    sa.ForeignKeyConstraint(['businessunitid'], ['businessunits.businessunitid'], ),
    sa.ForeignKeyConstraint(['locationid'], ['locations.locationid'], ),
    sa.ForeignKeyConstraint(['statusid'], ['assetstatuses.statusid'], ),
    sa.PrimaryKeyConstraint('assetid')
    )
    with op.batch_alter_table('assets', schema=None) as batch_op:
        batch_op.create_index('idx_asset_active', ['isactive'], unique=False)
        batch_op.create_index('idx_asset_location', ['locationid'], unique=False)
        batch_op.create_index('idx_asset_status', ['statusid'], unique=False)
        batch_op.create_index('idx_asset_type_bu', ['assettypeid', 'businessunitid'], unique=False)
        batch_op.create_index(batch_op.f('ix_assets_assetnumber'), ['assetnumber'], unique=True)
        batch_op.create_index(batch_op.f('ix_assets_serialnumber'), ['serialnumber'], unique=False)

    op.create_table('auditlogs',
    sa.Column('auditlogid', sa.Integer(), nullable=False),
    sa.Column('userid', sa.Integer(), nullable=True),
    sa.Column('username', sa.String(length=100), nullable=True),
    sa.Column('timestamp', sa.DateTime(), nullable=False),
    sa.Column('ipaddress', sa.String(length=45), nullable=True),
    sa.Column('useragent', sa.String(length=255), nullable=True),
    sa.Column('action', sa.String(length=20), nullable=False),
    sa.Column('entitytype', sa.String(length=50), nullable=False),
    sa.Column('entityid', sa.Integer(), nullable=True),
    sa.Column('entityname', sa.String(length=255), nullable=True),
    sa.Column('changes', sa.Text(), nullable=True),
    sa.Column('details', sa.Text(), nullable=True),
    sa.ForeignKeyConstraint(['userid'], ['users.userid'], ),
    sa.PrimaryKeyConstraint('auditlogid')
    )
    with op.batch_alter_table('auditlogs', schema=None) as batch_op:
        batch_op.create_index(batch_op.f('ix_auditlogs_action'), ['action'], unique=False)
        batch_op.create_index(batch_op.f('ix_auditlogs_entitytype'), ['entitytype'], unique=False)
        batch_op.create_index(batch_op.f('ix_auditlogs_timestamp'), ['timestamp'], unique=False)

    op.create_table('models',
    sa.Column('modelnumberid', sa.Integer(), nullable=False),
    sa.Column('modelnumber', sa.String(length=100), nullable=False),
    sa.Column('machinetypeid', sa.Integer(), nullable=True),
    sa.Column('vendorid', sa.Integer(), nullable=True),
    sa.Column('description', sa.Text(), nullable=True),
    sa.Column('imageurl', sa.String(length=500), nullable=True, comment='URL to product image'),
    sa.Column('documentationurl', sa.String(length=500), nullable=True, comment='URL to documentation'),
    sa.Column('notes', sa.Text(), nullable=True),
    sa.Column('createddate', sa.DateTime(), nullable=False),
    sa.Column('modifieddate', sa.DateTime(), nullable=False),
    sa.Column('isactive', sa.Boolean(), nullable=False),
    sa.ForeignKeyConstraint(['machinetypeid'], ['machinetypes.machinetypeid'], ),
    sa.ForeignKeyConstraint(['vendorid'], ['vendors.vendorid'], ),
    sa.PrimaryKeyConstraint('modelnumberid'),
    sa.UniqueConstraint('modelnumber', 'vendorid', name='uq_model_vendor')
    )
    op.create_table('notifications',
    sa.Column('notificationid', sa.Integer(), nullable=False),
    sa.Column('notificationtypeid', sa.Integer(), nullable=True),
    sa.Column('businessunitid', sa.Integer(), nullable=True),
    sa.Column('appid', sa.Integer(), nullable=True),
    sa.Column('notification', sa.Text(), nullable=False, comment='The message content'),
    sa.Column('starttime', sa.DateTime(), nullable=True),
    sa.Column('endtime', sa.DateTime(), nullable=True),
    sa.Column('ticketnumber', sa.String(length=50), nullable=True),
    sa.Column('link', sa.String(length=500), nullable=True),
    sa.Column('isactive', sa.Boolean(), nullable=True),
    sa.Column('isshopfloor', sa.Boolean(), nullable=True),
    sa.Column('employeesso', sa.String(length=100), nullable=True),
    sa.Column('employeename', sa.String(length=100), nullable=True),
    sa.ForeignKeyConstraint(['notificationtypeid'], ['notificationtypes.notificationtypeid'], ),
    sa.PrimaryKeyConstraint('notificationid')
    )
    op.create_table('rolepermissions',
    sa.Column('roleid', sa.Integer(), nullable=False),
    sa.Column('permissionid', sa.Integer(), nullable=False),
    sa.ForeignKeyConstraint(['permissionid'], ['permissions.permissionid'], ),
    sa.ForeignKeyConstraint(['roleid'], ['roles.roleid'], ),
    sa.PrimaryKeyConstraint('roleid', 'permissionid')
    )
    op.create_table('subnets',
    sa.Column('subnetid', sa.Integer(), nullable=False),
    sa.Column('cidr', sa.String(length=18), nullable=False, comment='CIDR notation (e.g., 10.1.1.0/24)'),
    sa.Column('name', sa.String(length=100), nullable=False, comment='Subnet name'),
    sa.Column('description', sa.Text(), nullable=True),
    sa.Column('gatewayip', sa.String(length=15), nullable=True, comment='Default gateway IP address'),
    sa.Column('subnetmask', sa.String(length=15), nullable=True, comment='Subnet mask (e.g., 255.255.255.0)'),
    sa.Column('networkaddress', sa.String(length=15), nullable=True, comment='Network address (e.g., 10.1.1.0)'),
    sa.Column('broadcastaddress', sa.String(length=15), nullable=True, comment='Broadcast address (e.g., 10.1.1.255)'),
    sa.Column('vlanid', sa.Integer(), nullable=True),
    sa.Column('subnettype', sa.String(length=50), nullable=True, comment='Type: production, development, management, dmz, etc.'),
    sa.Column('locationid', sa.Integer(), nullable=True),
    sa.Column('dhcpenabled', sa.Boolean(), nullable=True, comment='DHCP enabled for this subnet'),
    sa.Column('dhcprangestart', sa.String(length=15), nullable=True, comment='DHCP range start IP'),
    sa.Column('dhcprangeend', sa.String(length=15), nullable=True, comment='DHCP range end IP'),
    sa.Column('dns1', sa.String(length=15), nullable=True, comment='Primary DNS server'),
    sa.Column('dns2', sa.String(length=15), nullable=True, comment='Secondary DNS server'),
    sa.Column('createddate', sa.DateTime(), nullable=False),
    sa.Column('modifieddate', sa.DateTime(), nullable=False),
    sa.Column('isactive', sa.Boolean(), nullable=False),
    sa.ForeignKeyConstraint(['locationid'], ['locations.locationid'], ),
    sa.ForeignKeyConstraint(['vlanid'], ['vlans.vlanid'], ),
    sa.PrimaryKeyConstraint('subnetid'),
    sa.UniqueConstraint('cidr')
    )
    with op.batch_alter_table('subnets', schema=None) as batch_op:
        batch_op.create_index('idx_subnet_cidr', ['cidr'], unique=False)
        batch_op.create_index('idx_subnet_location', ['locationid'], unique=False)
        batch_op.create_index('idx_subnet_vlan', ['vlanid'], unique=False)

    op.create_table('supportteams',
    sa.Column('supportteamid', sa.Integer(), nullable=False),
    sa.Column('teamname', sa.String(length=100), nullable=False),
    sa.Column('teamurl', sa.String(length=255), nullable=True),
    sa.Column('appownerid', sa.Integer(), nullable=True),
    sa.Column('createddate', sa.DateTime(), nullable=False),
    sa.Column('modifieddate', sa.DateTime(), nullable=False),
    sa.Column('isactive', sa.Boolean(), nullable=False),
    sa.ForeignKeyConstraint(['appownerid'], ['appowners.appownerid'], ),
    sa.PrimaryKeyConstraint('supportteamid')
    )
    op.create_table('usbdevices',
    sa.Column('usbdeviceid', sa.Integer(), nullable=False),
    sa.Column('serialnumber', sa.String(length=100), nullable=False),
    sa.Column('label', sa.String(length=100), nullable=True, comment='Human-readable label'),
    sa.Column('assetnumber', sa.String(length=50), nullable=True, comment='Optional asset tag'),
    sa.Column('usbdevicetypeid', sa.Integer(), nullable=True),
    sa.Column('capacitygb', sa.Integer(), nullable=True, comment='Capacity in GB'),
    sa.Column('vendorid', sa.String(length=10), nullable=True, comment='USB Vendor ID (hex)'),
    sa.Column('productid', sa.String(length=10), nullable=True, comment='USB Product ID (hex)'),
    sa.Column('manufacturer', sa.String(length=100), nullable=True),
    sa.Column('productname', sa.String(length=100), nullable=True),
    sa.Column('ischeckedout', sa.Boolean(), nullable=True),
    sa.Column('currentuserid', sa.String(length=50), nullable=True, comment='SSO of current user'),
    sa.Column('currentusername', sa.String(length=100), nullable=True, comment='Name of current user'),
    sa.Column('currentcheckoutdate', sa.DateTime(), nullable=True),
    sa.Column('storagelocation', sa.String(length=200), nullable=True, comment='Where device is stored when not checked out'),
    sa.Column('pin', sa.String(length=50), nullable=True, comment='PIN for encrypted devices'),
    sa.Column('notes', sa.Text(), nullable=True),
    sa.Column('createddate', sa.DateTime(), nullable=False),
    sa.Column('modifieddate', sa.DateTime(), nullable=False),
    sa.Column('isactive', sa.Boolean(), nullable=False),
    sa.Column('createdby', sa.String(length=100), nullable=True),
    sa.Column('modifiedby', sa.String(length=100), nullable=True),
    sa.ForeignKeyConstraint(['usbdevicetypeid'], ['usbdevicetypes.usbdevicetypeid'], ),
    sa.PrimaryKeyConstraint('usbdeviceid'),
    sa.UniqueConstraint('serialnumber')
    )
    with op.batch_alter_table('usbdevices', schema=None) as batch_op:
        batch_op.create_index('idx_usb_checkedout', ['ischeckedout'], unique=False)
        batch_op.create_index('idx_usb_currentuser', ['currentuserid'], unique=False)
        batch_op.create_index('idx_usb_serial', ['serialnumber'], unique=False)
        batch_op.create_index('idx_usb_type', ['usbdevicetypeid'], unique=False)

    op.create_table('userroles',
    sa.Column('userid', sa.Integer(), nullable=False),
    sa.Column('roleid', sa.Integer(), nullable=False),
    sa.ForeignKeyConstraint(['roleid'], ['roles.roleid'], ),
    sa.ForeignKeyConstraint(['userid'], ['users.userid'], ),
    sa.PrimaryKeyConstraint('userid', 'roleid')
    )
    op.create_table('applications',
    sa.Column('appid', sa.Integer(), nullable=False),
    sa.Column('appname', sa.String(length=100), nullable=False),
    sa.Column('appdescription', sa.String(length=255), nullable=True),
    sa.Column('supportteamid', sa.Integer(), nullable=True),
    sa.Column('isinstallable', sa.Boolean(), nullable=True),
    sa.Column('applicationnotes', sa.Text(), nullable=True),
    sa.Column('installpath', sa.String(length=255), nullable=True),
    sa.Column('applicationlink', sa.String(length=512), nullable=True),
    sa.Column('documentationpath', sa.String(length=512), nullable=True),
    sa.Column('ishidden', sa.Boolean(), nullable=True),
    sa.Column('isprinter', sa.Boolean(), nullable=True),
    sa.Column('islicenced', sa.Boolean(), nullable=True),
    sa.Column('image', sa.String(length=255), nullable=True),
    sa.Column('createddate', sa.DateTime(), nullable=False),
    sa.Column('modifieddate', sa.DateTime(), nullable=False),
    sa.Column('isactive', sa.Boolean(), nullable=False),
    sa.ForeignKeyConstraint(['supportteamid'], ['supportteams.supportteamid'], ),
    sa.PrimaryKeyConstraint('appid'),
    sa.UniqueConstraint('appname')
    )
    op.create_table('assetrelationships',
    sa.Column('relationshipid', sa.Integer(), nullable=False),
    sa.Column('sourceassetid', sa.Integer(), nullable=False),
    sa.Column('targetassetid', sa.Integer(), nullable=False),
    sa.Column('relationshiptypeid', sa.Integer(), nullable=False),
    sa.Column('notes', sa.Text(), nullable=True),
    sa.Column('createddate', sa.DateTime(), nullable=False),
    sa.Column('modifieddate', sa.DateTime(), nullable=False),
    sa.Column('isactive', sa.Boolean(), nullable=False),
    sa.ForeignKeyConstraint(['relationshiptypeid'], ['relationshiptypes.relationshiptypeid'], ),
    sa.ForeignKeyConstraint(['sourceassetid'], ['assets.assetid'], ),
    sa.ForeignKeyConstraint(['targetassetid'], ['assets.assetid'], ),
    sa.PrimaryKeyConstraint('relationshipid'),
    sa.UniqueConstraint('sourceassetid', 'targetassetid', 'relationshiptypeid', name='uq_asset_relationship')
    )
    with op.batch_alter_table('assetrelationships', schema=None) as batch_op:
        batch_op.create_index('idx_asset_rel_source', ['sourceassetid'], unique=False)
        batch_op.create_index('idx_asset_rel_target', ['targetassetid'], unique=False)

    op.create_table('computers',
    sa.Column('computerid', sa.Integer(), nullable=False),
    sa.Column('assetid', sa.Integer(), nullable=False),
    sa.Column('computertypeid', sa.Integer(), nullable=True),
    sa.Column('hostname', sa.String(length=100), nullable=True, comment='Network hostname'),
    sa.Column('osid', sa.Integer(), nullable=True),
    sa.Column('loggedinuser', sa.String(length=100), nullable=True),
    sa.Column('lastreporteddate', sa.DateTime(), nullable=True),
    sa.Column('lastboottime', sa.DateTime(), nullable=True),
    sa.Column('isvnc', sa.Boolean(), nullable=True, comment='VNC remote access enabled'),
    sa.Column('iswinrm', sa.Boolean(), nullable=True, comment='WinRM enabled'),
    sa.Column('isshopfloor', sa.Boolean(), nullable=True, comment='Shopfloor PC (vs office PC)'),
    sa.Column('createddate', sa.DateTime(), nullable=False),
    sa.Column('modifieddate', sa.DateTime(), nullable=False),
    sa.Column('isactive', sa.Boolean(), nullable=False),
    sa.ForeignKeyConstraint(['assetid'], ['assets.assetid'], ondelete='CASCADE'),
    sa.ForeignKeyConstraint(['computertypeid'], ['computertypes.computertypeid'], ),
    sa.ForeignKeyConstraint(['osid'], ['operatingsystems.osid'], ),
    sa.PrimaryKeyConstraint('computerid')
    )
    with op.batch_alter_table('computers', schema=None) as batch_op:
        batch_op.create_index('idx_computer_hostname', ['hostname'], unique=False)
        batch_op.create_index('idx_computer_os', ['osid'], unique=False)
        batch_op.create_index('idx_computer_type', ['computertypeid'], unique=False)
        batch_op.create_index(batch_op.f('ix_computers_assetid'), ['assetid'], unique=True)
        batch_op.create_index(batch_op.f('ix_computers_hostname'), ['hostname'], unique=False)

    op.create_table('equipment',
    sa.Column('equipmentid', sa.Integer(), nullable=False),
    sa.Column('assetid', sa.Integer(), nullable=False),
    sa.Column('equipmenttypeid', sa.Integer(), nullable=True),
    sa.Column('vendorid', sa.Integer(), nullable=True),
    sa.Column('modelnumberid', sa.Integer(), nullable=True),
    sa.Column('requiresmanualconfig', sa.Boolean(), nullable=True, comment='Multi-PC machine needs manual configuration'),
    sa.Column('islocationonly', sa.Boolean(), nullable=True, comment='Virtual location marker (not actual equipment)'),
    sa.Column('lastmaintenancedate', sa.DateTime(), nullable=True),
    sa.Column('nextmaintenancedate', sa.DateTime(), nullable=True),
    sa.Column('maintenanceintervaldays', sa.Integer(), nullable=True),
    sa.Column('controllervendorid', sa.Integer(), nullable=True, comment='Controller vendor (e.g., FANUC)'),
    sa.Column('controllermodelid', sa.Integer(), nullable=True, comment='Controller model (e.g., 31B)'),
    sa.Column('createddate', sa.DateTime(), nullable=False),
    sa.Column('modifieddate', sa.DateTime(), nullable=False),
    sa.Column('isactive', sa.Boolean(), nullable=False),
    sa.ForeignKeyConstraint(['assetid'], ['assets.assetid'], ondelete='CASCADE'),
    sa.ForeignKeyConstraint(['controllermodelid'], ['models.modelnumberid'], ),
    sa.ForeignKeyConstraint(['controllervendorid'], ['vendors.vendorid'], ),
    sa.ForeignKeyConstraint(['equipmenttypeid'], ['equipmenttypes.equipmenttypeid'], ),
    sa.ForeignKeyConstraint(['modelnumberid'], ['models.modelnumberid'], ),
    sa.ForeignKeyConstraint(['vendorid'], ['vendors.vendorid'], ),
    sa.PrimaryKeyConstraint('equipmentid')
    )
    with op.batch_alter_table('equipment', schema=None) as batch_op:
        batch_op.create_index('idx_equipment_type', ['equipmenttypeid'], unique=False)
        batch_op.create_index('idx_equipment_vendor', ['vendorid'], unique=False)
        batch_op.create_index(batch_op.f('ix_equipment_assetid'), ['assetid'], unique=True)

    op.create_table('machines',
    sa.Column('machineid', sa.Integer(), nullable=False),
    sa.Column('machinenumber', sa.String(length=50), nullable=False, comment='Business identifier (e.g., CMM01, G5QX1GT3ESF)'),
    sa.Column('alias', sa.String(length=100), nullable=True, comment='Friendly name'),
    sa.Column('hostname', sa.String(length=100), nullable=True, comment='Network hostname (for PCs)'),
    sa.Column('serialnumber', sa.String(length=100), nullable=True, comment='Hardware serial number'),
    sa.Column('machinetypeid', sa.Integer(), nullable=False),
    sa.Column('pctypeid', sa.Integer(), nullable=True, comment='Set for PCs, NULL for equipment'),
    sa.Column('businessunitid', sa.Integer(), nullable=True),
    sa.Column('modelnumberid', sa.Integer(), nullable=True),
    sa.Column('vendorid', sa.Integer(), nullable=True),
    sa.Column('statusid', sa.Integer(), nullable=True, comment='In Use, Spare, Retired, etc.'),
    sa.Column('locationid', sa.Integer(), nullable=True),
    sa.Column('mapleft', sa.Integer(), nullable=True, comment='X coordinate on floor map'),
    sa.Column('maptop', sa.Integer(), nullable=True, comment='Y coordinate on floor map'),
    sa.Column('islocationonly', sa.Boolean(), nullable=True, comment='Virtual location marker (not actual machine)'),
    sa.Column('osid', sa.Integer(), nullable=True),
    sa.Column('loggedinuser', sa.String(length=100), nullable=True),
    sa.Column('lastreporteddate', sa.DateTime(), nullable=True),
    sa.Column('lastboottime', sa.DateTime(), nullable=True),
    sa.Column('isvnc', sa.Boolean(), nullable=True, comment='VNC remote access enabled'),
    sa.Column('iswinrm', sa.Boolean(), nullable=True, comment='WinRM enabled'),
    sa.Column('isshopfloor', sa.Boolean(), nullable=True, comment='Shopfloor PC'),
    sa.Column('requiresmanualconfig', sa.Boolean(), nullable=True, comment='Multi-PC machine needs manual configuration'),
    sa.Column('notes', sa.Text(), nullable=True),
    sa.Column('createddate', sa.DateTime(), nullable=False),
    sa.Column('modifieddate', sa.DateTime(), nullable=False),
    sa.Column('isactive', sa.Boolean(), nullable=False),
    sa.Column('deleteddate', sa.DateTime(), nullable=True),
    sa.Column('deletedby', sa.String(length=100), nullable=True),
    sa.Column('createdby', sa.String(length=100), nullable=True),
    sa.Column('modifiedby', sa.String(length=100), nullable=True),
    sa.ForeignKeyConstraint(['businessunitid'], ['businessunits.businessunitid'], ),
    sa.ForeignKeyConstraint(['locationid'], ['locations.locationid'], ),
    sa.ForeignKeyConstraint(['machinetypeid'], ['machinetypes.machinetypeid'], ),
    sa.ForeignKeyConstraint(['modelnumberid'], ['models.modelnumberid'], ),
    sa.ForeignKeyConstraint(['osid'], ['operatingsystems.osid'], ),
    sa.ForeignKeyConstraint(['pctypeid'], ['pctypes.pctypeid'], ),
    sa.ForeignKeyConstraint(['statusid'], ['machinestatuses.statusid'], ),
    sa.ForeignKeyConstraint(['vendorid'], ['vendors.vendorid'], ),
    sa.PrimaryKeyConstraint('machineid')
    )
    with op.batch_alter_table('machines', schema=None) as batch_op:
        batch_op.create_index('idx_machine_active', ['isactive'], unique=False)
        batch_op.create_index('idx_machine_hostname', ['hostname'], unique=False)
        batch_op.create_index('idx_machine_location', ['locationid'], unique=False)
        batch_op.create_index('idx_machine_type_bu', ['machinetypeid', 'businessunitid'], unique=False)
        batch_op.create_index(batch_op.f('ix_machines_hostname'), ['hostname'], unique=False)
        batch_op.create_index(batch_op.f('ix_machines_machinenumber'), ['machinenumber'], unique=True)
        batch_op.create_index(batch_op.f('ix_machines_serialnumber'), ['serialnumber'], unique=False)

    op.create_table('networkdevices',
    sa.Column('networkdeviceid', sa.Integer(), nullable=False),
    sa.Column('assetid', sa.Integer(), nullable=False),
    sa.Column('networkdevicetypeid', sa.Integer(), nullable=True),
    sa.Column('vendorid', sa.Integer(), nullable=True),
    sa.Column('hostname', sa.String(length=100), nullable=True, comment='Network hostname'),
    sa.Column('firmwareversion', sa.String(length=100), nullable=True),
    sa.Column('portcount', sa.Integer(), nullable=True, comment='Number of ports (for switches)'),
    sa.Column('ispoe', sa.Boolean(), nullable=True, comment='Power over Ethernet capable'),
    sa.Column('ismanaged', sa.Boolean(), nullable=True, comment='Managed device (SNMP, web interface, etc.)'),
    sa.Column('rackunit', sa.String(length=20), nullable=True, comment='Rack unit position (e.g., U1, U5)'),
    sa.Column('createddate', sa.DateTime(), nullable=False),
    sa.Column('modifieddate', sa.DateTime(), nullable=False),
    sa.Column('isactive', sa.Boolean(), nullable=False),
    sa.ForeignKeyConstraint(['assetid'], ['assets.assetid'], ondelete='CASCADE'),
    sa.ForeignKeyConstraint(['networkdevicetypeid'], ['networkdevicetypes.networkdevicetypeid'], ),
    sa.ForeignKeyConstraint(['vendorid'], ['vendors.vendorid'], ),
    sa.PrimaryKeyConstraint('networkdeviceid')
    )
    with op.batch_alter_table('networkdevices', schema=None) as batch_op:
        batch_op.create_index('idx_netdev_hostname', ['hostname'], unique=False)
        batch_op.create_index('idx_netdev_type', ['networkdevicetypeid'], unique=False)
        batch_op.create_index('idx_netdev_vendor', ['vendorid'], unique=False)
        batch_op.create_index(batch_op.f('ix_networkdevices_assetid'), ['assetid'], unique=True)
        batch_op.create_index(batch_op.f('ix_networkdevices_hostname'), ['hostname'], unique=False)

    op.create_table('printers',
    sa.Column('printerid', sa.Integer(), nullable=False),
    sa.Column('assetid', sa.Integer(), nullable=False),
    sa.Column('printertypeid', sa.Integer(), nullable=True),
    sa.Column('vendorid', sa.Integer(), nullable=True),
    sa.Column('modelnumberid', sa.Integer(), nullable=True),
    sa.Column('hostname', sa.String(length=100), nullable=True, comment='Network hostname'),
    sa.Column('windowsname', sa.String(length=255), nullable=True, comment='Windows printer name (e.g., \\\\server\\printer)'),
    sa.Column('sharename', sa.String(length=100), nullable=True, comment='CSF/share name'),
    sa.Column('iscsf', sa.Boolean(), nullable=True, comment='Is CSF printer'),
    sa.Column('installpath', sa.String(length=255), nullable=True, comment='Driver install path'),
    sa.Column('pin', sa.String(length=20), nullable=True),
    sa.Column('iscolor', sa.Boolean(), nullable=True, comment='Color capable'),
    sa.Column('isduplex', sa.Boolean(), nullable=True, comment='Duplex capable'),
    sa.Column('isnetwork', sa.Boolean(), nullable=True, comment='Network connected'),
    sa.Column('createddate', sa.DateTime(), nullable=False),
    sa.Column('modifieddate', sa.DateTime(), nullable=False),
    sa.Column('isactive', sa.Boolean(), nullable=False),
    sa.ForeignKeyConstraint(['assetid'], ['assets.assetid'], ondelete='CASCADE'),
    sa.ForeignKeyConstraint(['modelnumberid'], ['models.modelnumberid'], ),
    sa.ForeignKeyConstraint(['printertypeid'], ['printertypes.printertypeid'], ),
    sa.ForeignKeyConstraint(['vendorid'], ['vendors.vendorid'], ),
    sa.PrimaryKeyConstraint('printerid')
    )
    with op.batch_alter_table('printers', schema=None) as batch_op:
        batch_op.create_index('idx_printer_hostname', ['hostname'], unique=False)
        batch_op.create_index('idx_printer_type', ['printertypeid'], unique=False)
        batch_op.create_index('idx_printer_windowsname', ['windowsname'], unique=False)
        batch_op.create_index(batch_op.f('ix_printers_assetid'), ['assetid'], unique=True)
        batch_op.create_index(batch_op.f('ix_printers_hostname'), ['hostname'], unique=False)

    op.create_table('usbcheckouts',
    sa.Column('checkoutid', sa.Integer(), nullable=False),
    sa.Column('usbdeviceid', sa.Integer(), nullable=True),
    sa.Column('machineid', sa.Integer(), nullable=False),
    sa.Column('sso', sa.String(length=20), nullable=False, comment='SSO of user'),
    sa.Column('checkoutname', sa.String(length=100), nullable=True, comment='Name of user'),
    sa.Column('checkouttime', sa.DateTime(), nullable=False),
    sa.Column('checkintime', sa.DateTime(), nullable=True),
    sa.Column('checkoutreason', sa.Text(), nullable=True, comment='Reason for checkout'),
    sa.Column('checkinnotes', sa.Text(), nullable=True),
    sa.Column('waswiped', sa.Boolean(), nullable=True, comment='Was device wiped after return'),
    sa.Column('createddate', sa.DateTime(), nullable=False),
    sa.Column('modifieddate', sa.DateTime(), nullable=False),
    sa.Column('isactive', sa.Boolean(), nullable=False),
    sa.ForeignKeyConstraint(['usbdeviceid'], ['usbdevices.usbdeviceid'], ondelete='CASCADE'),
    sa.PrimaryKeyConstraint('checkoutid')
    )
    op.create_table('appversions',
    sa.Column('appversionid', sa.Integer(), nullable=False),
    sa.Column('appid', sa.Integer(), nullable=False),
    sa.Column('version', sa.String(length=50), nullable=False),
    sa.Column('releasedate', sa.Date(), nullable=True),
    sa.Column('notes', sa.String(length=255), nullable=True),
    sa.Column('dateadded', sa.DateTime(), nullable=True),
    sa.Column('isactive', sa.Boolean(), nullable=True),
    sa.ForeignKeyConstraint(['appid'], ['applications.appid'], ),
    sa.PrimaryKeyConstraint('appversionid'),
    sa.UniqueConstraint('appid', 'version', name='uq_app_version')
    )
    op.create_table('communications',
    sa.Column('communicationid', sa.Integer(), nullable=False),
    sa.Column('assetid', sa.Integer(), nullable=True, comment='FK to assets table (new architecture)'),
    sa.Column('machineid', sa.Integer(), nullable=True, comment='DEPRECATED: FK to machines table - use assetid instead'),
    sa.Column('comtypeid', sa.Integer(), nullable=False),
    sa.Column('ipaddress', sa.String(length=50), nullable=True),
    sa.Column('subnetmask', sa.String(length=50), nullable=True),
    sa.Column('gateway', sa.String(length=50), nullable=True),
    sa.Column('dns1', sa.String(length=50), nullable=True),
    sa.Column('dns2', sa.String(length=50), nullable=True),
    sa.Column('macaddress', sa.String(length=50), nullable=True),
    sa.Column('isdhcp', sa.Boolean(), nullable=True),
    sa.Column('comport', sa.String(length=20), nullable=True),
    sa.Column('baudrate', sa.Integer(), nullable=True),
    sa.Column('databits', sa.Integer(), nullable=True),
    sa.Column('stopbits', sa.String(length=10), nullable=True),
    sa.Column('parity', sa.String(length=20), nullable=True),
    sa.Column('flowcontrol', sa.String(length=20), nullable=True),
    sa.Column('port', sa.Integer(), nullable=True),
    sa.Column('username', sa.String(length=100), nullable=True),
    sa.Column('pathname', sa.String(length=255), nullable=True),
    sa.Column('pathname2', sa.String(length=255), nullable=True, comment='Secondary path for dualpath'),
    sa.Column('isprimary', sa.Boolean(), nullable=True, comment='Primary communication method'),
    sa.Column('ismachinenetwork', sa.Boolean(), nullable=True, comment='On machine network vs office network'),
    sa.Column('notes', sa.Text(), nullable=True),
    sa.Column('createddate', sa.DateTime(), nullable=False),
    sa.Column('modifieddate', sa.DateTime(), nullable=False),
    sa.Column('isactive', sa.Boolean(), nullable=False),
    sa.ForeignKeyConstraint(['assetid'], ['assets.assetid'], ),
    sa.ForeignKeyConstraint(['comtypeid'], ['communicationtypes.comtypeid'], ),
    sa.ForeignKeyConstraint(['machineid'], ['machines.machineid'], ),
    sa.PrimaryKeyConstraint('communicationid')
    )
    with op.batch_alter_table('communications', schema=None) as batch_op:
        batch_op.create_index('idx_comm_asset', ['assetid'], unique=False)
        batch_op.create_index('idx_comm_ip', ['ipaddress'], unique=False)
        batch_op.create_index('idx_comm_machine', ['machineid'], unique=False)
        batch_op.create_index(batch_op.f('ix_communications_assetid'), ['assetid'], unique=False)

    op.create_table('knowledgebase',
    sa.Column('linkid', sa.Integer(), nullable=False),
    sa.Column('appid', sa.Integer(), nullable=True),
    sa.Column('shortdescription', sa.String(length=500), nullable=False),
    sa.Column('linkurl', sa.String(length=2000), nullable=True),
    sa.Column('keywords', sa.String(length=500), nullable=True),
    sa.Column('clicks', sa.Integer(), nullable=True),
    sa.Column('lastupdated', sa.DateTime(), nullable=True),
    sa.Column('createddate', sa.DateTime(), nullable=False),
    sa.Column('modifieddate', sa.DateTime(), nullable=False),
    sa.Column('isactive', sa.Boolean(), nullable=False),
    sa.ForeignKeyConstraint(['appid'], ['applications.appid'], ),
    sa.PrimaryKeyConstraint('linkid')
    )
    op.create_table('machinerelationships',
    sa.Column('relationshipid', sa.Integer(), nullable=False),
    sa.Column('parentmachineid', sa.Integer(), nullable=False),
    sa.Column('childmachineid', sa.Integer(), nullable=False),
    sa.Column('relationshiptypeid', sa.Integer(), nullable=False),
    sa.Column('notes', sa.Text(), nullable=True),
    sa.Column('createddate', sa.DateTime(), nullable=False),
    sa.Column('modifieddate', sa.DateTime(), nullable=False),
    sa.Column('isactive', sa.Boolean(), nullable=False),
    sa.ForeignKeyConstraint(['childmachineid'], ['machines.machineid'], ),
    sa.ForeignKeyConstraint(['parentmachineid'], ['machines.machineid'], ),
    sa.ForeignKeyConstraint(['relationshiptypeid'], ['relationshiptypes.relationshiptypeid'], ),
    sa.PrimaryKeyConstraint('relationshipid'),
    sa.UniqueConstraint('parentmachineid', 'childmachineid', 'relationshiptypeid', name='uq_machine_relationship')
    )
    op.create_table('printerdata',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('machineid', sa.Integer(), nullable=False),
    sa.Column('windowsname', sa.String(length=255), nullable=True, comment='Windows printer name (e.g., \\\\server\\printer)'),
    sa.Column('sharename', sa.String(length=100), nullable=True, comment='CSF/share name'),
    sa.Column('iscsf', sa.Boolean(), nullable=True, comment='Is CSF printer'),
    sa.Column('installpath', sa.String(length=255), nullable=True, comment='Driver install path'),
    sa.Column('pin', sa.String(length=20), nullable=True),
    sa.Column('createddate', sa.DateTime(), nullable=False),
    sa.Column('modifieddate', sa.DateTime(), nullable=False),
    sa.Column('isactive', sa.Boolean(), nullable=False),
    sa.ForeignKeyConstraint(['machineid'], ['machines.machineid'], ondelete='CASCADE'),
    sa.PrimaryKeyConstraint('id')
    )
    with op.batch_alter_table('printerdata', schema=None) as batch_op:
        batch_op.create_index('idx_printerdata_windowsname', ['windowsname'], unique=False)
        batch_op.create_index(batch_op.f('ix_printerdata_machineid'), ['machineid'], unique=True)

    op.create_table('computerinstalledapps',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('computerid', sa.Integer(), nullable=False),
    sa.Column('appid', sa.Integer(), nullable=False),
    sa.Column('appversionid', sa.Integer(), nullable=True),
    sa.Column('isactive', sa.Boolean(), nullable=False),
    sa.Column('installeddate', sa.DateTime(), nullable=True),
    sa.ForeignKeyConstraint(['appid'], ['applications.appid'], ),
    sa.ForeignKeyConstraint(['appversionid'], ['appversions.appversionid'], ),
    sa.ForeignKeyConstraint(['computerid'], ['computers.computerid'], ondelete='CASCADE'),
    sa.PrimaryKeyConstraint('id'),
    sa.UniqueConstraint('computerid', 'appid', name='uq_computer_app')
    )
    with op.batch_alter_table('computerinstalledapps', schema=None) as batch_op:
        batch_op.create_index('idx_compapp_app', ['appid'], unique=False)
        batch_op.create_index('idx_compapp_computer', ['computerid'], unique=False)

    op.create_table('installedapps',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('machineid', sa.Integer(), nullable=False),
    sa.Column('appid', sa.Integer(), nullable=False),
    sa.Column('appversionid', sa.Integer(), nullable=True),
    sa.Column('isactive', sa.Boolean(), nullable=False),
    sa.Column('installeddate', sa.DateTime(), nullable=True),
    sa.ForeignKeyConstraint(['appid'], ['applications.appid'], ),
    sa.ForeignKeyConstraint(['appversionid'], ['appversions.appversionid'], ),
    sa.ForeignKeyConstraint(['machineid'], ['machines.machineid'], ),
    sa.PrimaryKeyConstraint('id'),
    sa.UniqueConstraint('machineid', 'appid', name='uq_machine_app')
    )
    # ### end Alembic commands ###


def downgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_table('installedapps')
    with op.batch_alter_table('computerinstalledapps', schema=None) as batch_op:
        batch_op.drop_index('idx_compapp_computer')
        batch_op.drop_index('idx_compapp_app')

    op.drop_table('computerinstalledapps')
    with op.batch_alter_table('printerdata', schema=None) as batch_op:
        batch_op.drop_index(batch_op.f('ix_printerdata_machineid'))
        batch_op.drop_index('idx_printerdata_windowsname')

    op.drop_table('printerdata')
    op.drop_table('machinerelationships')
    op.drop_table('knowledgebase')
    with op.batch_alter_table('communications', schema=None) as batch_op:
        batch_op.drop_index(batch_op.f('ix_communications_assetid'))
        batch_op.drop_index('idx_comm_machine')
        batch_op.drop_index('idx_comm_ip')
        batch_op.drop_index('idx_comm_asset')

    op.drop_table('communications')
    op.drop_table('appversions')
    op.drop_table('usbcheckouts')
    with op.batch_alter_table('printers', schema=None) as batch_op:
        batch_op.drop_index(batch_op.f('ix_printers_hostname'))
        batch_op.drop_index(batch_op.f('ix_printers_assetid'))
        batch_op.drop_index('idx_printer_windowsname')
        batch_op.drop_index('idx_printer_type')
        batch_op.drop_index('idx_printer_hostname')

    op.drop_table('printers')
    with op.batch_alter_table('networkdevices', schema=None) as batch_op:
        batch_op.drop_index(batch_op.f('ix_networkdevices_hostname'))
        batch_op.drop_index(batch_op.f('ix_networkdevices_assetid'))
        batch_op.drop_index('idx_netdev_vendor')
        batch_op.drop_index('idx_netdev_type')
        batch_op.drop_index('idx_netdev_hostname')

    op.drop_table('networkdevices')
    with op.batch_alter_table('machines', schema=None) as batch_op:
        batch_op.drop_index(batch_op.f('ix_machines_serialnumber'))
        batch_op.drop_index(batch_op.f('ix_machines_machinenumber'))
        batch_op.drop_index(batch_op.f('ix_machines_hostname'))
        batch_op.drop_index('idx_machine_type_bu')
        batch_op.drop_index('idx_machine_location')
        batch_op.drop_index('idx_machine_hostname')
        batch_op.drop_index('idx_machine_active')

    op.drop_table('machines')
    with op.batch_alter_table('equipment', schema=None) as batch_op:
        batch_op.drop_index(batch_op.f('ix_equipment_assetid'))
        batch_op.drop_index('idx_equipment_vendor')
        batch_op.drop_index('idx_equipment_type')

    op.drop_table('equipment')
    with op.batch_alter_table('computers', schema=None) as batch_op:
        batch_op.drop_index(batch_op.f('ix_computers_hostname'))
        batch_op.drop_index(batch_op.f('ix_computers_assetid'))
        batch_op.drop_index('idx_computer_type')
        batch_op.drop_index('idx_computer_os')
        batch_op.drop_index('idx_computer_hostname')

    op.drop_table('computers')
    with op.batch_alter_table('assetrelationships', schema=None) as batch_op:
        batch_op.drop_index('idx_asset_rel_target')
        batch_op.drop_index('idx_asset_rel_source')

    op.drop_table('assetrelationships')
    op.drop_table('applications')
    op.drop_table('userroles')
    with op.batch_alter_table('usbdevices', schema=None) as batch_op:
        batch_op.drop_index('idx_usb_type')
        batch_op.drop_index('idx_usb_serial')
        batch_op.drop_index('idx_usb_currentuser')
        batch_op.drop_index('idx_usb_checkedout')

    op.drop_table('usbdevices')
    op.drop_table('supportteams')
    with op.batch_alter_table('subnets', schema=None) as batch_op:
        batch_op.drop_index('idx_subnet_vlan')
        batch_op.drop_index('idx_subnet_location')
        batch_op.drop_index('idx_subnet_cidr')

    op.drop_table('subnets')
    op.drop_table('rolepermissions')
    op.drop_table('notifications')
    op.drop_table('models')
    with op.batch_alter_table('auditlogs', schema=None) as batch_op:
        batch_op.drop_index(batch_op.f('ix_auditlogs_timestamp'))
        batch_op.drop_index(batch_op.f('ix_auditlogs_entitytype'))
        batch_op.drop_index(batch_op.f('ix_auditlogs_action'))

    op.drop_table('auditlogs')
    with op.batch_alter_table('assets', schema=None) as batch_op:
        batch_op.drop_index(batch_op.f('ix_assets_serialnumber'))
        batch_op.drop_index(batch_op.f('ix_assets_assetnumber'))
        batch_op.drop_index('idx_asset_type_bu')
        batch_op.drop_index('idx_asset_status')
        batch_op.drop_index('idx_asset_location')
        batch_op.drop_index('idx_asset_active')

    op.drop_table('assets')
    with op.batch_alter_table('vlans', schema=None) as batch_op:
        batch_op.drop_index('idx_vlan_number')

    op.drop_table('vlans')
    op.drop_table('vendors')
    with op.batch_alter_table('users', schema=None) as batch_op:
        batch_op.drop_index(batch_op.f('ix_users_username'))

    op.drop_table('users')
    op.drop_table('usbdevicetypes')
    with op.batch_alter_table('settings', schema=None) as batch_op:
        batch_op.drop_index(batch_op.f('ix_settings_key'))

    op.drop_table('settings')
    op.drop_table('roles')
    op.drop_table('relationshiptypes')
    op.drop_table('printertypes')
    op.drop_table('permissions')
    op.drop_table('pctypes')
    op.drop_table('operatingsystems')
    op.drop_table('notificationtypes')
    op.drop_table('networkdevicetypes')
    op.drop_table('machinetypes')
    op.drop_table('machinestatuses')
    op.drop_table('locations')
    op.drop_table('equipmenttypes')
    op.drop_table('computertypes')
    op.drop_table('communicationtypes')
    op.drop_table('businessunits')
    op.drop_table('assettypes')
    op.drop_table('assetstatuses')
    op.drop_table('appowners')
    # ### end Alembic commands ###
