Flask + Vue rewrite of the classic-ASP shopdb, built as a plugin framework so sister GE Aerospace sites can adopt it. Product version 0.7.0-pre-0.8.0, plugin contract 0.11.0, 966 backend tests. Key entry points: - docs/INSTALL-WINDOWS-IIS.md - tested Windows + IIS install runbook (own-site and subpath deployment methods) - docs/PILOT-DEPLOY.md - production pilot: stand up + import + verify - docs/IMPORT-API.md - schema-agnostic legacy data import contract - scripts/site_imports/wjf/ - West Jefferson reference import loader - docs/adr/ - twelve accepted architecture decision records
206 lines
8.3 KiB
Python
206 lines
8.3 KiB
Python
"""Equipment -> machines rename, core half
|
|
|
|
Part 1 of the approved equipment -> machines rename (the plugin half lives in
|
|
plugins/machines/migrations/versions/0002_rename_from_equipment.py):
|
|
|
|
1. machinetypes -> modeltypes (+ machinetypeid -> modeltypeid,
|
|
machinetype -> modeltype, models.machinetypeid -> models.modeltypeid).
|
|
The table types the vendor MODELS catalog, not machine instances, so
|
|
the new name is role-accurate and frees "machinetypes" for the plugin.
|
|
2. Data flips: assettypes 'equipment' -> 'machine' (incl pluginname and
|
|
tablename), auditlogs.entitytype 'Equipment' -> 'Machine', settings keys
|
|
identifier_*_equipment_enabled -> identifier_*_machine_enabled,
|
|
search_equipment_enabled -> search_machine_enabled, and permission
|
|
rows equipment.* -> machines.* (role links survive).
|
|
3. alembic_version_equipment -> alembic_version_machines (if present) so
|
|
the renamed plugin's migration chain resumes seamlessly.
|
|
|
|
Idempotent via inspector guards, following the 7c01 pattern. MySQL is the
|
|
only dialect the core chain runs against in practice.
|
|
|
|
Revision ID: 7d17_machines_rename
|
|
Revises: 7d16_directoryemployees
|
|
Create Date: 2026-07-11
|
|
|
|
"""
|
|
from alembic import op
|
|
import sqlalchemy as sa
|
|
|
|
|
|
revision = '7d17_machines_rename'
|
|
down_revision = '7d16_directoryemployees'
|
|
branch_labels = None
|
|
depends_on = None
|
|
|
|
|
|
def _fk_names(insp, table, referred_table):
|
|
# find FK constraint names on table pointing at referred_table
|
|
return [fk['name'] for fk in insp.get_foreign_keys(table)
|
|
if fk.get('referred_table') == referred_table and fk.get('name')]
|
|
|
|
|
|
def upgrade():
|
|
bind = op.get_bind()
|
|
insp = sa.inspect(bind)
|
|
tables = set(insp.get_table_names())
|
|
|
|
# -- 1. machinetypes -> modeltypes ------------------------------------
|
|
if 'machinetypes' in tables and 'modeltypes' not in tables:
|
|
bind.exec_driver_sql("SET FOREIGN_KEY_CHECKS=0")
|
|
|
|
# drop the models -> machinetypes FK and its index before renaming
|
|
for name in _fk_names(insp, 'models', 'machinetypes'):
|
|
bind.exec_driver_sql(f"ALTER TABLE models DROP FOREIGN KEY {name}")
|
|
model_indexes = {ix['name'] for ix in insp.get_indexes('models')}
|
|
if 'machinetypeid' in model_indexes:
|
|
bind.exec_driver_sql("ALTER TABLE models DROP KEY machinetypeid")
|
|
|
|
bind.exec_driver_sql("RENAME TABLE machinetypes TO modeltypes")
|
|
bind.exec_driver_sql(
|
|
"ALTER TABLE modeltypes "
|
|
"CHANGE machinetypeid modeltypeid INT NOT NULL AUTO_INCREMENT, "
|
|
"CHANGE machinetype modeltype VARCHAR(100) NOT NULL, "
|
|
"DROP KEY machinetype, "
|
|
"ADD UNIQUE KEY modeltype (modeltype)"
|
|
)
|
|
bind.exec_driver_sql(
|
|
"ALTER TABLE models "
|
|
"CHANGE machinetypeid modeltypeid INT NULL, "
|
|
"ADD KEY modeltypeid (modeltypeid), "
|
|
"ADD CONSTRAINT fk_models_modeltypeid "
|
|
"FOREIGN KEY (modeltypeid) REFERENCES modeltypes (modeltypeid)"
|
|
)
|
|
bind.exec_driver_sql("SET FOREIGN_KEY_CHECKS=1")
|
|
|
|
# -- 2. data flips ------------------------------------------------------
|
|
if 'assettypes' in tables:
|
|
bind.exec_driver_sql(
|
|
"UPDATE assettypes SET assettype='machine', pluginname='machines', "
|
|
"tablename='machines' WHERE assettype='equipment'"
|
|
)
|
|
if 'auditlogs' in tables:
|
|
bind.exec_driver_sql(
|
|
"UPDATE auditlogs SET entitytype='Machine' "
|
|
"WHERE entitytype='Equipment'"
|
|
)
|
|
if 'settings' in tables:
|
|
_rename_setting_keys(bind, old_marker='_equipment_',
|
|
new_marker='_machine_')
|
|
if 'permissions' in tables:
|
|
_rename_permissions(bind, old_prefix='equipment.',
|
|
new_prefix='machines.',
|
|
old_category='equipment', new_category='machines')
|
|
|
|
# -- 3. plugin version table --------------------------------------------
|
|
if ('alembic_version_equipment' in tables
|
|
and 'alembic_version_machines' not in tables):
|
|
bind.exec_driver_sql(
|
|
"RENAME TABLE alembic_version_equipment TO alembic_version_machines"
|
|
)
|
|
|
|
|
|
def _rename_setting_keys(bind, old_marker, new_marker):
|
|
"""Rename settings keys embedding the assettype value, collision-safe.
|
|
|
|
Covers identifier_<name>_equipment_enabled and search_equipment_enabled.
|
|
If a row with the new key already exists (fresh seed ran on new code),
|
|
the old row is dropped instead of renamed.
|
|
"""
|
|
# broad fetch; the marker replace below filters non-matches
|
|
rows = bind.exec_driver_sql(
|
|
"SELECT settingid, `key` FROM settings"
|
|
).fetchall()
|
|
for settingid, key in rows:
|
|
newkey = key.replace(old_marker, new_marker)
|
|
if newkey == key:
|
|
continue
|
|
exists = bind.exec_driver_sql(
|
|
"SELECT 1 FROM settings WHERE `key` = %s", (newkey,)
|
|
).fetchone()
|
|
if exists:
|
|
bind.exec_driver_sql(
|
|
"DELETE FROM settings WHERE settingid = %s", (settingid,))
|
|
else:
|
|
bind.exec_driver_sql(
|
|
"UPDATE settings SET `key` = %s WHERE settingid = %s",
|
|
(newkey, settingid))
|
|
|
|
|
|
def _rename_permissions(bind, old_prefix, new_prefix, old_category,
|
|
new_category):
|
|
"""Rename permission rows in place so role links survive, collision-safe."""
|
|
rows = bind.exec_driver_sql(
|
|
"SELECT permissionid, name FROM permissions"
|
|
).fetchall()
|
|
for permissionid, name in rows:
|
|
if not name.startswith(old_prefix):
|
|
continue
|
|
newname = new_prefix + name[len(old_prefix):]
|
|
exists = bind.exec_driver_sql(
|
|
"SELECT 1 FROM permissions WHERE name = %s", (newname,)
|
|
).fetchone()
|
|
if exists:
|
|
bind.exec_driver_sql(
|
|
"DELETE FROM permissions WHERE permissionid = %s",
|
|
(permissionid,))
|
|
else:
|
|
bind.exec_driver_sql(
|
|
"UPDATE permissions SET name = %s, category = %s "
|
|
"WHERE permissionid = %s",
|
|
(newname, new_category, permissionid))
|
|
|
|
|
|
def downgrade():
|
|
bind = op.get_bind()
|
|
insp = sa.inspect(bind)
|
|
tables = set(insp.get_table_names())
|
|
|
|
if ('alembic_version_machines' in tables
|
|
and 'alembic_version_equipment' not in tables):
|
|
bind.exec_driver_sql(
|
|
"RENAME TABLE alembic_version_machines TO alembic_version_equipment"
|
|
)
|
|
|
|
if 'settings' in tables:
|
|
_rename_setting_keys(bind, old_marker='_machine_',
|
|
new_marker='_equipment_')
|
|
if 'permissions' in tables:
|
|
_rename_permissions(bind, old_prefix='machines.',
|
|
new_prefix='equipment.',
|
|
old_category='machines', new_category='equipment')
|
|
if 'auditlogs' in tables:
|
|
bind.exec_driver_sql(
|
|
"UPDATE auditlogs SET entitytype='Equipment' "
|
|
"WHERE entitytype='Machine'"
|
|
)
|
|
if 'assettypes' in tables:
|
|
bind.exec_driver_sql(
|
|
"UPDATE assettypes SET assettype='equipment', "
|
|
"pluginname='equipment', tablename='equipment' "
|
|
"WHERE assettype='machine'"
|
|
)
|
|
|
|
if 'modeltypes' in tables and 'machinetypes' not in tables:
|
|
bind.exec_driver_sql("SET FOREIGN_KEY_CHECKS=0")
|
|
for name in _fk_names(insp, 'models', 'modeltypes'):
|
|
bind.exec_driver_sql(f"ALTER TABLE models DROP FOREIGN KEY {name}")
|
|
model_indexes = {ix['name'] for ix in insp.get_indexes('models')}
|
|
if 'modeltypeid' in model_indexes:
|
|
bind.exec_driver_sql("ALTER TABLE models DROP KEY modeltypeid")
|
|
bind.exec_driver_sql("RENAME TABLE modeltypes TO machinetypes")
|
|
bind.exec_driver_sql(
|
|
"ALTER TABLE machinetypes "
|
|
"CHANGE modeltypeid machinetypeid INT NOT NULL AUTO_INCREMENT, "
|
|
"CHANGE modeltype machinetype VARCHAR(100) NOT NULL, "
|
|
"DROP KEY modeltype, "
|
|
"ADD UNIQUE KEY machinetype (machinetype)"
|
|
)
|
|
bind.exec_driver_sql(
|
|
"ALTER TABLE models "
|
|
"CHANGE modeltypeid machinetypeid INT NULL, "
|
|
"ADD KEY machinetypeid (machinetypeid), "
|
|
"ADD CONSTRAINT models_ibfk_1 "
|
|
"FOREIGN KEY (machinetypeid) REFERENCES machinetypes (machinetypeid)"
|
|
)
|
|
bind.exec_driver_sql("SET FOREIGN_KEY_CHECKS=1")
|