# -*- 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") 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() async def run() -> None: db = Database() try: await platform_seed(db.session) await db.session.commit() log.info("平台种子完成:%s", config.DATABASE_URL) _seed_training() 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())