125 lines
5.0 KiB
Python
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()
|