diff --git a/pyproject.toml b/pyproject.toml index ff5ffd2..2f57554 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -34,3 +34,4 @@ extend-immutable-calls = ["fastapi.File", "fastapi.Query", "fastapi.Depends"] # Разведочные скрипты этапа разбора форматов — черновики, не часть продукта. "scripts/proof/*" = ["E402", "E501", "E741", "B007"] "scripts/gen_fixtures.py" = ["E402", "E501", "E741"] +"scripts/fix_ref_ids.py" = ["E501"] # одноразовая миграция, SQL-строки длиннее 100 diff --git a/scripts/fix_ref_ids.py b/scripts/fix_ref_ids.py new file mode 100644 index 0000000..5022a70 --- /dev/null +++ b/scripts/fix_ref_ids.py @@ -0,0 +1,49 @@ +"""Починка справочника: заменить повреждённые Excel-ошибкой service_id (#REF!) на чистые. + +В исходном справочнике у части услуг код тарификатора пришёл как Excel `#REF!`, и это +протекло в канонический service_id (напр. `#REF!-#REF!#459`) — видно в живом /search. +Имена услуг при этом корректны. Скрипт генерирует чистые уникальные id и каскадно +обновляет ссылки в price_item (service_id и suggested_service_id) и learned_synonym. + +Запуск: python scripts/fix_ref_ids.py +""" + +import sqlite3 +import sys + + +def fix(db_path: str) -> dict: + conn = sqlite3.connect(db_path) + existing = {r[0] for r in conn.execute("SELECT service_id FROM service")} + bad = [r[0] for r in conn.execute("SELECT service_id FROM service WHERE service_id LIKE '%#REF!%'")] + + mapping: dict[str, str] = {} + i = 0 + for old in bad: + while True: + new = f"d{i:04d}" + i += 1 + if new not in existing: + break + existing.add(new) + mapping[old] = new + + # learned_synonym ссылается на service_id? обновим, если колонка есть. + cols = {r[1] for r in conn.execute("PRAGMA table_info(learned_synonym)")} + for old, new in mapping.items(): + conn.execute("UPDATE service SET service_id=? WHERE service_id=?", [new, old]) + conn.execute("UPDATE price_item SET service_id=? WHERE service_id=?", [new, old]) + conn.execute("UPDATE price_item SET suggested_service_id=? WHERE suggested_service_id=?", [new, old]) + if "service_id" in cols: + conn.execute("UPDATE learned_synonym SET service_id=? WHERE service_id=?", [new, old]) + conn.commit() + + left = conn.execute("SELECT COUNT(*) FROM service WHERE service_id LIKE '%#REF!%'").fetchone()[0] + left_pi = conn.execute("SELECT COUNT(*) FROM price_item WHERE service_id LIKE '%#REF!%'").fetchone()[0] + matched = conn.execute("SELECT COUNT(*) FROM price_item WHERE service_id IS NOT NULL").fetchone()[0] + conn.close() + return {"fixed_services": len(mapping), "ref_left_service": left, "ref_left_price_item": left_pi, "matched_total": matched} + + +if __name__ == "__main__": + print(fix(sys.argv[1] if len(sys.argv) > 1 else "data/medarchive.db"))