143 lines
5.7 KiB
Python
143 lines
5.7 KiB
Python
import argparse
|
|
import os
|
|
import sqlite3
|
|
from typing import Dict, Any, List, Optional
|
|
|
|
|
|
def find_col(columns: List[str], candidates: List[str]) -> Optional[str]:
|
|
lowered = {c.lower(): c for c in columns}
|
|
for name in candidates:
|
|
if name.lower() in lowered:
|
|
return lowered[name.lower()]
|
|
return None
|
|
|
|
|
|
def main() -> None:
|
|
parser = argparse.ArgumentParser(description="Import fault codes into local data.db from external SQLite table")
|
|
parser.add_argument("--src-db", default="fault_codes.db", help="source sqlite file path")
|
|
parser.add_argument("--src-table", default="fault_code_list", help="source table name")
|
|
parser.add_argument("--manufacturer", default="woojin", help="manufacturer slug (woojin|rotem)")
|
|
parser.add_argument("--default-section", default="fault", help="default section if missing (fault|tcms|emergency)")
|
|
parser.add_argument("--truncate", action="store_true", help="delete existing faults for manufacturer before import")
|
|
|
|
args = parser.parse_args()
|
|
|
|
# destination DB (our app)
|
|
try:
|
|
from app import DATABASE_PATH # type: ignore
|
|
except Exception:
|
|
DATABASE_PATH = os.path.join(os.path.dirname(__file__), "..", "data.db")
|
|
|
|
dest_path = os.path.abspath(DATABASE_PATH)
|
|
src_path = os.path.abspath(args.src_db)
|
|
|
|
if not os.path.exists(src_path):
|
|
raise SystemExit(f"Source DB not found: {src_path}")
|
|
|
|
src = sqlite3.connect(src_path)
|
|
src.row_factory = sqlite3.Row
|
|
dst = sqlite3.connect(dest_path)
|
|
dst.row_factory = sqlite3.Row
|
|
dst.execute("PRAGMA foreign_keys = ON")
|
|
|
|
cur = src.execute(f"SELECT * FROM {args.src_table}")
|
|
rows = cur.fetchall()
|
|
if not rows:
|
|
print("No rows in source table.")
|
|
return
|
|
|
|
columns = rows[0].keys()
|
|
code_col = find_col(columns, ["code", "Code", "fault_code", "고장코드", "CODE"]) or "code"
|
|
title_col = find_col(columns, ["title", "name", "f.Name", "f_name", "고장명", "fName"]) or None
|
|
details_col = find_col(columns, ["details", "detail", "고장상세", "desc", "설명"]) # optional
|
|
action_col = find_col(columns, ["action", "조치", "응급조치", "response", "반응"]) # optional
|
|
cond_col = find_col(columns, ["condition", "검지조건", "조건"]) # optional
|
|
category_col = find_col(columns, ["category", "cat", "장치분류", "system", "type"]) # optional
|
|
section_col = find_col(columns, ["section", "섹션", "tab", "kind"]) # optional
|
|
|
|
print("Column mapping:")
|
|
print(" code ->", code_col)
|
|
print(" title ->", title_col)
|
|
print(" details ->", details_col)
|
|
print(" action ->", action_col)
|
|
print(" condition ->", cond_col)
|
|
print(" category ->", category_col)
|
|
print(" section ->", section_col, f"(default={args.default_section})")
|
|
|
|
# manufacturer ensure
|
|
m = dst.execute("SELECT id FROM manufacturer WHERE slug=?", (args.manufacturer.lower(),)).fetchone()
|
|
if not m:
|
|
name = "우진" if args.manufacturer.lower() == "woojin" else "로템"
|
|
dst.execute("INSERT INTO manufacturer (slug, name) VALUES (?, ?)", (args.manufacturer.lower(), name))
|
|
m_id = dst.execute("SELECT last_insert_rowid() AS id").fetchone()[0]
|
|
else:
|
|
m_id = m["id"]
|
|
|
|
if args.truncate:
|
|
dst.execute("DELETE FROM fault WHERE manufacturer_id=?", (m_id,))
|
|
dst.execute("DELETE FROM category WHERE manufacturer_id=?", (m_id,))
|
|
|
|
# existing categories map
|
|
cat_map: Dict[str, int] = {}
|
|
for r in dst.execute("SELECT id, name FROM category WHERE manufacturer_id=?", (m_id,)):
|
|
cat_map[r["name"]] = r["id"]
|
|
|
|
def ensure_category(name: Optional[str]) -> Optional[int]:
|
|
if not name:
|
|
return None
|
|
name = str(name).strip()
|
|
if name == "":
|
|
return None
|
|
if name in cat_map:
|
|
return cat_map[name]
|
|
dst.execute("INSERT INTO category (manufacturer_id, name) VALUES (?, ?)", (m_id, name))
|
|
cid = dst.execute("SELECT last_insert_rowid() AS id").fetchone()[0]
|
|
cat_map[name] = cid
|
|
return cid
|
|
|
|
def get_value(r: sqlite3.Row, key: Optional[str]):
|
|
if not key:
|
|
return None
|
|
for k in r.keys():
|
|
if k.lower() == key.lower():
|
|
return r[k]
|
|
return None
|
|
|
|
batch: List[tuple] = []
|
|
for row in rows:
|
|
code = str(get_value(row, code_col) or "").strip()
|
|
title = str(get_value(row, title_col) or "").strip()
|
|
details = str(get_value(row, details_col) or "").strip()
|
|
action = str(get_value(row, action_col) or "").strip()
|
|
cond = str(get_value(row, cond_col) or "").strip()
|
|
category_val = get_value(row, category_col)
|
|
category_val = (str(category_val).strip() if category_val is not None else None)
|
|
section_val = get_value(row, section_col)
|
|
section = (str(section_val).strip().lower() if section_val is not None else args.default_section)
|
|
if section not in ("fault", "tcms", "emergency"):
|
|
section = args.default_section
|
|
|
|
cat_id = ensure_category(category_val)
|
|
batch.append((m_id, cat_id, section, code, title, details, action, cond))
|
|
|
|
dst.executemany(
|
|
"INSERT INTO fault (manufacturer_id, category_id, section, code, title, details, action, condition) VALUES (?, ?, ?, ?, ?, ?, ?, ?)",
|
|
batch,
|
|
)
|
|
|
|
# bump meta version
|
|
dst.execute("UPDATE meta SET version = version + 1, updated_at = datetime('now') WHERE id = 1")
|
|
if dst.total_changes == 0:
|
|
dst.execute("INSERT OR REPLACE INTO meta (id, version, updated_at) VALUES (1, 1, datetime('now'))")
|
|
|
|
dst.commit()
|
|
src.close()
|
|
dst.close()
|
|
print(f"Imported {len(batch)} rows into {dest_path} for manufacturer '{args.manufacturer.lower()}'.")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|
|
|
|
|