fix(dict): чистые service_id вместо Excel #REF! в справочнике
720 услуг имели #REF! в каноническом service_id (Excel-ошибка из исходного справочника протекала в живой /search). Миграция scripts/fix_ref_ids.py генерирует чистые id и каскадно обновляет price_item (service_id, suggested_service_id) и learned_synonym. matched сохранён (11899), имена целы. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -34,3 +34,4 @@ extend-immutable-calls = ["fastapi.File", "fastapi.Query", "fastapi.Depends"]
|
|||||||
# Разведочные скрипты этапа разбора форматов — черновики, не часть продукта.
|
# Разведочные скрипты этапа разбора форматов — черновики, не часть продукта.
|
||||||
"scripts/proof/*" = ["E402", "E501", "E741", "B007"]
|
"scripts/proof/*" = ["E402", "E501", "E741", "B007"]
|
||||||
"scripts/gen_fixtures.py" = ["E402", "E501", "E741"]
|
"scripts/gen_fixtures.py" = ["E402", "E501", "E741"]
|
||||||
|
"scripts/fix_ref_ids.py" = ["E501"] # одноразовая миграция, SQL-строки длиннее 100
|
||||||
|
|||||||
@@ -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 <db_path>
|
||||||
|
"""
|
||||||
|
|
||||||
|
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"))
|
||||||
Reference in New Issue
Block a user