100 lines
3.5 KiB
Python
100 lines
3.5 KiB
Python
"""补充单株状态字典 tree_status:初选/重点/保存 三态,幂等。
|
||||
|
|
|
|||
|
|
背景:波次6 状态机要求 tree.status 覆盖完整选育流转
|
|||
|
|
(存活→入选→初选→重点→保存→淘汰),而线上字典仅有
|
|||
|
|
alive(存活)/selected(入选)/eliminated(淘汰) 三值。
|
|||
|
|
本脚本补齐 primary(初选)/key(重点)/preserved(保存),
|
|||
|
|
使导入模板下拉与状态机流转齐备。
|
|||
|
|
|
|||
|
|
用法(backend/ 目录):
|
|||
|
|
ENVIRONMENT=dev "C:/ai/miniconda3/envs/dpb/python.exe" scripts/supplement_tree_status_dict.py --check
|
|||
|
|
ENVIRONMENT=dev "C:/ai/miniconda3/envs/dpb/python.exe" scripts/supplement_tree_status_dict.py
|
|||
|
|
|
|||
|
|
幂等性:目标 dict_value 已存在则跳过;可重复执行。
|
|||
|
|
"""
|
|||
|
|
import argparse
|
|||
|
|
import os
|
|||
|
|
import sys
|
|||
|
|
import uuid
|
|||
|
|
|
|||
|
|
BACKEND_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|||
|
|
if BACKEND_DIR not in sys.path:
|
|||
|
|
sys.path.insert(0, BACKEND_DIR)
|
|||
|
|
|
|||
|
|
from sqlalchemy import create_engine, text # noqa: E402
|
|||
|
|
|
|||
|
|
from app.config.setting import settings # noqa: E402
|
|||
|
|
|
|||
|
|
# (dict_sort, dict_label, dict_value) —— 沿用 alive=1/eliminated=2/selected=3 的序号延续
|
|||
|
|
NEW_ROWS = [
|
|||
|
|
(4, "初选", "primary"),
|
|||
|
|
(5, "重点", "key"),
|
|||
|
|
(6, "保存", "preserved"),
|
|||
|
|
]
|
|||
|
|
DICT_TYPE = "tree_status"
|
|||
|
|
|
|||
|
|
|
|||
|
|
def main() -> None:
|
|||
|
|
parser = argparse.ArgumentParser(description="补充 tree_status 字典三态")
|
|||
|
|
parser.add_argument("--check", action="store_true", help="仅预览将插入的行,不落库")
|
|||
|
|
args = parser.parse_args()
|
|||
|
|
|
|||
|
|
engine = create_engine(settings.DB_URI)
|
|||
|
|
print(f"# 连接: {settings.DB_URI} dict_type={DICT_TYPE} 模式: {'预览' if args.check else '执行'}")
|
|||
|
|
|
|||
|
|
with engine.connect() as conn:
|
|||
|
|
type_row = conn.execute(
|
|||
|
|
text("SELECT id FROM sys_dict_type WHERE dict_type = :dt"),
|
|||
|
|
{"dt": DICT_TYPE},
|
|||
|
|
).first()
|
|||
|
|
if not type_row:
|
|||
|
|
print(f"!! 字典类型 {DICT_TYPE} 不存在,中止")
|
|||
|
|
sys.exit(1)
|
|||
|
|
dict_type_id = type_row[0]
|
|||
|
|
|
|||
|
|
existing = {
|
|||
|
|
row[0]
|
|||
|
|
for row in conn.execute(
|
|||
|
|
text("SELECT dict_value FROM sys_dict_data WHERE dict_type = :dt"),
|
|||
|
|
{"dt": DICT_TYPE},
|
|||
|
|
)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
to_insert = [(sort, label, value) for sort, label, value in NEW_ROWS if value not in existing]
|
|||
|
|
missing = [value for _, _, value in NEW_ROWS if value not in existing]
|
|||
|
|
print(f"# 现有值: {sorted(existing)}")
|
|||
|
|
print(f"# 待补: {missing}")
|
|||
|
|
|
|||
|
|
if args.check:
|
|||
|
|
for sort, label, value in to_insert:
|
|||
|
|
print(f" + (dict_sort={sort}) {label} -> {value}")
|
|||
|
|
return
|
|||
|
|
|
|||
|
|
if not to_insert:
|
|||
|
|
print("# 无新增,幂等退出 ✅")
|
|||
|
|
return
|
|||
|
|
|
|||
|
|
for sort, label, value in to_insert:
|
|||
|
|
conn.execute(
|
|||
|
|
text(
|
|||
|
|
"INSERT INTO sys_dict_data "
|
|||
|
|
"(status, description, dict_sort, dict_label, dict_value, css_class, list_class, "
|
|||
|
|
" is_default, dict_type, dict_type_id, uuid, is_deleted, created_time, updated_time) "
|
|||
|
|
"VALUES (0, '', :sort, :label, :value, '', NULL, false, :dt, :dtid, :uuid, false, now(), now())"
|
|||
|
|
),
|
|||
|
|
{
|
|||
|
|
"sort": sort,
|
|||
|
|
"label": label,
|
|||
|
|
"value": value,
|
|||
|
|
"dt": DICT_TYPE,
|
|||
|
|
"dtid": dict_type_id,
|
|||
|
|
"uuid": str(uuid.uuid4()),
|
|||
|
|
},
|
|||
|
|
)
|
|||
|
|
conn.commit()
|
|||
|
|
print("# 已插入 ✅")
|
|||
|
|
|
|||
|
|
|
|||
|
|
if __name__ == "__main__":
|
|||
|
|
main()
|