2026-08-24 19:32:41 +08:00
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
"""数据库种子脚本(非运行态)—— 在迁移后、启动应用前执行。
|
|
|
|
|
|
|
|
|
|
用法:uv run python scripts/db/seed.py
|
|
|
|
|
职责:灌入平台/园区/培训的基础种子数据(角色、权限、用户、默认园区、培训事件课程等)。
|
|
|
|
|
全部幂等(按标记行判断,重跑安全)。禁止在应用启动时调用本逻辑。
|
|
|
|
|
"""
|
|
|
|
|
from __future__ import annotations
|
|
|
|
|
|
|
|
|
|
import asyncio
|
|
|
|
|
import logging
|
|
|
|
|
import sys
|
|
|
|
|
import os
|
|
|
|
|
from pathlib import Path
|
|
|
|
|
|
|
|
|
|
sys.path.insert(0, str(Path(__file__).resolve().parent.parent.parent))
|
|
|
|
|
|
|
|
|
|
from app.infrastructure.repositories import Database
|
|
|
|
|
from app.infrastructure.seed import seed_data as platform_seed
|
|
|
|
|
from app import config
|
|
|
|
|
|
|
|
|
|
logging.basicConfig(level=logging.INFO, format="%(levelname)s %(name)s: %(message)s")
|
|
|
|
|
log = logging.getLogger("db.seed")
|
|
|
|
|
|
|
|
|
|
|
2026-08-24 20:31:57 +08:00
|
|
|
def _seed_training() -> None:
|
|
|
|
|
"""培训种子(唯一总库 app.db):超管账号 + 排期 + 在线课程(幂等)。"""
|
|
|
|
|
import sqlite3
|
|
|
|
|
import json
|
|
|
|
|
from app.training import db as tdb
|
|
|
|
|
conn = sqlite3.connect(tdb.DB_PATH)
|
|
|
|
|
conn.row_factory = sqlite3.Row
|
|
|
|
|
try:
|
|
|
|
|
if conn.execute("SELECT COUNT(*) AS c FROM accounts").fetchone()["c"] == 0:
|
|
|
|
|
from app.training.auth import hash_password
|
|
|
|
|
conn.execute("INSERT INTO accounts (id,username,password,name,identities,created_at) VALUES (?,?,?,?,?,?)",
|
|
|
|
|
("U-PINE", "pine", hash_password("123456"), "Pine", json.dumps(["admin"]), tdb.now_iso()))
|
|
|
|
|
if conn.execute("SELECT COUNT(*) AS c FROM events").fetchone()["c"] == 0:
|
|
|
|
|
for e in tdb.SEED_EVENTS:
|
|
|
|
|
conn.execute("INSERT INTO events (id,type,mode,title,subtitle,desc,location,host,image,link,start_at,duration_min,capacity,status) VALUES (:id,:type,:mode,:title,:subtitle,:desc,:location,:host,:image,:link,:start_at,:duration_min,:capacity,:status)", e)
|
|
|
|
|
if conn.execute("SELECT COUNT(*) AS c FROM courses").fetchone()["c"] == 0:
|
|
|
|
|
for c in tdb.SEED_COURSES:
|
|
|
|
|
conn.execute("INSERT INTO courses (id,category,level,title,subtitle,desc,price,status,start_at,end_at,venue,quota,image,host,created_at) VALUES (:id,:category,:level,:title,:subtitle,:desc,:price,:status,:start_at,:end_at,:venue,:quota,:image,:host,:created_at)", c)
|
|
|
|
|
conn.commit()
|
|
|
|
|
log.info("培训种子完成(账号/排期/课程)")
|
|
|
|
|
finally:
|
|
|
|
|
conn.close()
|
|
|
|
|
|
|
|
|
|
|
2026-08-24 19:32:41 +08:00
|
|
|
async def run() -> None:
|
|
|
|
|
db = Database()
|
|
|
|
|
try:
|
|
|
|
|
await platform_seed(db.session)
|
|
|
|
|
await db.session.commit()
|
|
|
|
|
log.info("平台种子完成:%s", config.DATABASE_URL)
|
2026-08-24 20:31:57 +08:00
|
|
|
_seed_training()
|
2026-08-24 19:32:41 +08:00
|
|
|
except Exception as e: # noqa: BLE001
|
|
|
|
|
await db.session.rollback()
|
|
|
|
|
log.error("种子失败:%s", e)
|
|
|
|
|
raise
|
|
|
|
|
finally:
|
|
|
|
|
await db.close()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
|
asyncio.run(run())
|