JhHardwareWRS_BackPoint/scripts/migrate_mold_locks.py
2026-06-24 15:19:14 +08:00

125 lines
5.0 KiB
Python

from pathlib import Path
import sys
from sqlalchemy import text
ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(ROOT))
from app.database import engine # noqa: E402
def column_exists(conn, table_name: str, column_name: str) -> bool:
return bool(
conn.execute(
text(
"""
SELECT COUNT(1)
FROM information_schema.columns
WHERE table_schema = DATABASE()
AND table_name = :table_name
AND column_name = :column_name
"""
),
{"table_name": table_name, "column_name": column_name},
).scalar()
)
def index_exists(conn, table_name: str, index_name: str) -> bool:
return bool(
conn.execute(
text(
"""
SELECT COUNT(1)
FROM information_schema.statistics
WHERE table_schema = DATABASE()
AND table_name = :table_name
AND index_name = :index_name
"""
),
{"table_name": table_name, "index_name": index_name},
).scalar()
)
def main() -> None:
with engine.begin() as conn:
if not column_exists(conn, "work_session_devices", "released_at"):
conn.execute(text("ALTER TABLE work_session_devices ADD COLUMN released_at DATETIME NULL AFTER sort_order"))
if not column_exists(conn, "work_session_devices", "released_by"):
conn.execute(text("ALTER TABLE work_session_devices ADD COLUMN released_by VARCHAR(20) NULL AFTER released_at"))
if not column_exists(conn, "work_session_devices", "release_reason"):
conn.execute(text("ALTER TABLE work_session_devices ADD COLUMN release_reason VARCHAR(120) NULL AFTER released_by"))
if not index_exists(conn, "work_session_devices", "idx_session_devices_release"):
conn.execute(text("CREATE INDEX idx_session_devices_release ON work_session_devices (released_at)"))
conn.execute(
text(
"""
CREATE TABLE IF NOT EXISTS mold_lock_feedbacks (
id BIGINT NOT NULL AUTO_INCREMENT,
attendance_point_name VARCHAR(128) NOT NULL DEFAULT '',
mold_name VARCHAR(255) NOT NULL,
process_name VARCHAR(128) NOT NULL DEFAULT '',
session_device_id BIGINT NOT NULL,
reporter_phone VARCHAR(20) NOT NULL,
occupied_phone VARCHAR(20) NOT NULL,
status VARCHAR(32) NOT NULL DEFAULT 'pending',
read_at DATETIME NULL,
handled_at DATETIME NULL,
handled_by VARCHAR(20) NULL,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id),
KEY idx_mold_lock_feedback_point_read (attendance_point_name, read_at, created_at),
KEY idx_mold_lock_feedback_status (status, created_at),
KEY idx_mold_lock_feedback_device (session_device_id),
CONSTRAINT fk_mold_lock_feedback_device
FOREIGN KEY (session_device_id) REFERENCES work_session_devices (id),
CONSTRAINT fk_mold_lock_feedback_reporter
FOREIGN KEY (reporter_phone) REFERENCES personnel (phone),
CONSTRAINT fk_mold_lock_feedback_occupied
FOREIGN KEY (occupied_phone) REFERENCES personnel (phone),
CONSTRAINT fk_mold_lock_feedback_handler
FOREIGN KEY (handled_by) REFERENCES personnel (phone)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
"""
)
)
conn.execute(
text(
"""
UPDATE work_session_devices d
JOIN work_sessions s ON s.id = d.session_id
SET d.released_at = COALESCE(s.end_at, s.updated_at, NOW()),
d.release_reason = '历史非活动记录迁移释放占用'
WHERE d.released_at IS NULL
AND s.status NOT IN ('active', 'reporting')
"""
)
)
conn.execute(
text(
"""
UPDATE work_session_devices d
JOIN work_sessions s ON s.id = d.session_id
JOIN (
SELECT session_id, MAX(sort_order) AS max_sort_order
FROM work_session_devices
GROUP BY session_id
) latest ON latest.session_id = d.session_id
SET d.released_at = NOW(),
d.release_reason = '历史切换记录迁移释放占用'
WHERE d.released_at IS NULL
AND s.status = 'active'
AND d.sort_order < latest.max_sort_order
"""
)
)
print("mold lock columns and feedback table migrated")
if __name__ == "__main__":
main()