"""Починка справочника: заменить повреждённые 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"))