#!/usr/bin/env python3 """Demo data seed script — called by cli.py, not part of application code.""" from __future__ import annotations import sqlite3 import sys from datetime import datetime from pathlib import Path BACKEND_DIR = Path(__file__).resolve().parent.parent / "backend" sys.path.insert(0, str(BACKEND_DIR)) from app.core.security import hash_password # noqa: E402 from app.services.repository import create_event, init_db # noqa: E402 _now = datetime.now().strftime("%Y-%m-%d %H:%M:%S") def run(db_path: str, force: bool = False) -> None: conn = sqlite3.connect(db_path) conn.row_factory = sqlite3.Row try: init_db(conn) if force: conn.executescript(""" DELETE FROM feedback; DELETE FROM order_events; DELETE FROM attachments; DELETE FROM saved_addresses; DELETE FROM repair_orders; DELETE FROM sessions; DELETE FROM users; """) conn.commit() existing = conn.execute("SELECT COUNT(*) AS count FROM repair_orders").fetchone()["count"] if existing > 0: print("Orders already exist, skipping. Use --force to overwrite.") return conn.executemany( "INSERT OR IGNORE INTO users " "(username, password_hash, role, display_name, created_at) " "VALUES (?, ?, ?, ?, ?)", [ ("student01", hash_password("Student123"), "student", "张同学", _now), ("admin01", hash_password("Admin123"), "admin", "宿管老师", _now), ], ) student = conn.execute("SELECT id FROM users WHERE username = 'student01'").fetchone() if student is None: conn.commit() return conn.execute( "INSERT OR IGNORE INTO saved_addresses " "(student_id, campus, building, room, last_used_at) " "VALUES (?, ?, ?, ?, ?)", (student["id"], "西海岸校区", "听海苑999号楼", "404", _now), ) orders = [ { "order_no": "DR20260601001", "category": "给排水 / 水龙头类", "raw_description": "卫生间水龙头关不严,一直滴水。", "structured_summary": "给排水,建议管道处理。卫生间水龙头关不严持续滴水;洗手池位置;影响日常用水。", "urgency": "中", "status": "已提交", "allow_room_entry": 0, "assignee_name": None, "expected_date": None, "expected_time_segment": None, "expected_arrival_at": None, "admin_note": None, "rework_reason": None, }, { "order_no": "DR20260601002", "category": "电路照明 / 照明故障", "raw_description": "宿舍顶灯一直闪烁,还有轻微焦味。", "structured_summary": "电路照明,建议电工处理。顶灯闪烁有焦味;门口位置;影响整间照明;有轻微焦糊味。", "urgency": "紧急", "status": "待处理", "allow_room_entry": 0, "assignee_name": "王师傅", "expected_date": "2026-06-02", "expected_time_segment": "09:00-11:00", "expected_arrival_at": "明天上午", "admin_note": "已派电工王师傅,请提前清理顶灯下方区域。", "rework_reason": None, }, { "order_no": "DR20260601003", "category": "空调设备 / 制冷制热异常", "raw_description": "空调开到16度还是不制冷,出风口感觉是自然风。", "structured_summary": ( "空调设备,建议空调维修处理。空调16度不制冷;出风口常温风;已持续两天影响休息。" ), "urgency": "高", "status": "处理中", "allow_room_entry": 1, "assignee_name": "赵师傅", "expected_date": "2026-06-02", "expected_time_segment": "14:00-16:00", "expected_arrival_at": "今天下午", "admin_note": "已安排空调维修赵师傅上门检测,可能与制冷剂泄漏有关。", "rework_reason": None, }, { "order_no": "DR20260601004", "category": "门窗锁具 / 门锁钥匙", "raw_description": "宿舍门锁很难拧开,偶尔会卡住。", "structured_summary": ( "门窗锁具,建议门窗处理。门锁难拧开偶尔卡住;门口锁芯位置;影响进出;锁芯磨损严重。" ), "urgency": "中", "status": "待上门", "allow_room_entry": 0, "assignee_name": "李师傅", "expected_date": "2026-06-03", "expected_time_segment": "14:00-16:00", "expected_arrival_at": "6月3日下午", "admin_note": "已安排门窗维修李师傅上门更换锁芯,请当天留人在宿舍。", "rework_reason": None, }, { "order_no": "DR20260528001", "category": "网络弱电 / 网口异常", "raw_description": "宿舍网口插上网线没反应,灯不亮。", "structured_summary": "网络弱电,建议弱电维修处理。网口插网线无反应灯不亮;书桌下方;影响上网学习。", "urgency": "中", "status": "返工申请中", "allow_room_entry": 1, "assignee_name": "孙师傅", "expected_date": None, "expected_time_segment": None, "expected_arrival_at": None, "admin_note": "孙师傅已上门维修并更换网口面板,但学生反映问题仍存在,已进入返工流程。", "rework_reason": "维修后网口仍无法使用,指示灯依然不亮,请重新排查线路问题。", }, { "order_no": "DR20260525003", "category": "门窗锁具 / 窗户五金", "raw_description": "宿舍窗户关不严,冬天漏风严重。", "structured_summary": "门窗锁具,建议门窗处理。窗户关不严有缝隙;推拉窗轨道变形;冬天漏风影响室温。", "urgency": "中", "status": "已完成", "allow_room_entry": 1, "assignee_name": "李师傅", "expected_date": "2026-05-24", "expected_time_segment": "09:00-11:00", "expected_arrival_at": "5月24日上午", "admin_note": "已更换窗户密封条并调整轨道,请学生确认。", "rework_reason": None, }, { "order_no": "DR20260520001", "category": "家具设施 / 桌椅维修", "raw_description": "书桌抽屉轨道坏了,拉出来会掉。", "structured_summary": "家具设施,建议木工维修处理。抽屉轨道损坏拉出脱落;右侧抽屉;影响日常存放。", "urgency": "低", "status": "已确认", "allow_room_entry": 0, "assignee_name": "刘师傅", "expected_date": "2026-05-20", "expected_time_segment": "14:00-16:00", "expected_arrival_at": "5月20日下午", "admin_note": "已更换抽屉轨道,学生已确认维修结果。", "rework_reason": None, }, { "order_no": "DR20260515001", "category": "给排水 / 下水疏通类", "raw_description": "洗手池下水很慢,水会积在池子里。", "structured_summary": "给排水,建议管道疏通处理。洗手池下水缓慢积水;卫生间洗手池;影响日常洗漱。", "urgency": "中", "status": "已取消", "allow_room_entry": 0, "assignee_name": None, "expected_date": None, "expected_time_segment": None, "expected_arrival_at": None, "admin_note": None, "rework_reason": None, }, ] for o in orders: cur = conn.execute( "INSERT INTO repair_orders (" "order_no, student_id, campus, building, room, category, " "raw_description, structured_summary, urgency, status, " "allow_room_entry, assignee_name, expected_date, " "expected_time_segment, expected_arrival_at, admin_note, " "rework_reason, diagnosis_session_id, created_at, updated_at" ") VALUES (" "?, ?, ?, ?, ?, ?, ?, ?, ?, ?, " "?, ?, ?, ?, ?, ?, ?, ?, ?, ?" ")", ( o["order_no"], student["id"], "西海岸校区", "听海苑999号楼", "404", o["category"], o["raw_description"], o["structured_summary"], o["urgency"], o["status"], o["allow_room_entry"], o["assignee_name"], o["expected_date"], o["expected_time_segment"], o["expected_arrival_at"], o["admin_note"], o["rework_reason"], None, _now, _now, ), ) oid = cur.lastrowid create_event( conn, oid, "student", "张同学", "created", "学生提交报修", o["raw_description"], None, "已提交", ) if o["status"] != "已提交": create_event( conn, oid, "admin", "宿管老师", "status_updated", "管理员更新工单状态", o["admin_note"], "已提交", o["status"], ) if o["status"] == "待上门": expected_info = f"预计 {o['expected_date'] or ''} {o['expected_time_segment'] or ''}" create_event( conn, oid, "admin", "宿管老师", "scheduled", "管理员安排上门时间", expected_info, o["status"], o["status"], ) if o["status"] == "返工申请中": create_event( conn, oid, "student", "张同学", "rework_requested", "学生申请返工", o["rework_reason"], "已完成", o["status"], ) if o["status"] == "已确认": create_event( conn, oid, "student", "张同学", "confirmed", "学生确认维修完成", "维修结果满意,确认工单完成。", "已完成", o["status"], ) if o["status"] == "已取消": create_event( conn, oid, "student", "张同学", "cancelled", "学生取消工单", "问题已自行解决,取消报修。", o["status"], o["status"], ) if o["status"] in ("已完成", "已确认"): conn.execute( "INSERT INTO feedback (order_id, rating, comment, created_at) VALUES (?, ?, ?, ?)", (oid, 5, "维修很快,问题已经解决。", _now), ) conn.commit() print("Seed complete.") finally: conn.close() if __name__ == "__main__": import argparse p = argparse.ArgumentParser() p.add_argument("--db", type=str, default=str(BACKEND_DIR / "data" / "dorm_repair.sqlite3")) p.add_argument("--force", action="store_true") args = p.parse_args() run(args.db, args.force)