fix(761-5): 복제 · 바꿔 넣기 뒤 노선 · 지표면 id 박힌 storage 파일 새 id 로

- common_util_project_copy.rekey_id_files: 코리도 이름 corridor_{노선 id:04d} → 새 노선 id(겹침 대비 임시 이름 거침) · 짝 없는 옛 코리도 지움 · B06_Section/sampling.json surface_model_id → 새 지표면 id
- _insert_rows · _insert_full 이 (지표면 · 노선) id 짝을 함께 돌려줌 · full 복제 · --replace · --storage-only 셋 다 _fix_files 에서 rekey
- id_maps_by_order: 이미 복제된 두 프로젝트의 id 짝(차례 · 행 수 다르면 ValueError) — storage-only 가 씀
- storage 경로 함수 전수: id 박힌 이름 = 코리도뿐(B08 이정표 그림 이름 = 거래처 상자 id · 추천 저장본 = 해시) · 내용 = sampling.json 지표면 id(초기값 스냅샷 지표면 id 는 종전대로)
- 지킴 시험 test_761_2: 노선 id 짝 단정 · rekey(이름 겹침 · 짝 없음 지움 · sampling)
- 바꿔 넣은 B 13 개 고침(tmp 스크립트 · 차례 짝 + 내용 칸 대조): 코리도 셋씩 새 id · corridor_0370 지움 · sampling 911 → 각 새 id

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-11-03 13:38:20 +09:00
co-authored by Claude Opus 5.5
parent 47f9d90f97
commit a2b2ae57b2
3 changed files with 111 additions and 25 deletions
+32 -1
View File
@@ -3,6 +3,7 @@
- 유지 칸: 대상 id · 이름 · 주인 · 회사 · 종류 · 저장 자리 · 담당자는 대상 값 · 나머지는 원본
- 지우는 표 목록 = 복제 표 목록(projects · project_members 뺌)과 같음 — 표가 늘면 여기서 빨강
- id 다시 잇기: 새 행이 새 노선 · 새 지표면 · 새 입력 파일 id 를 가리킴 · 단계 설정 id 도
- 노선 · 지표면 id 가 박힌 storage 파일(코리도 이름 · sampling.json) → 새 id · 짝 없는 코리도 지움(761-5)
"""
import asyncio
@@ -98,7 +99,7 @@ def test_insert_rows_relinks_ids():
**{table: [] for table in cp._PLAN_ALL},
}
cursor = _Cursor()
model_map = asyncio.run(cp._insert_rows(cursor, rows, "dst"))
model_map, route_map = asyncio.run(cp._insert_rows(cursor, rows, "dst"))
new = {table: row for table, row in cursor.inserts}
assert [table for table, _ in cursor.inserts][0] == "input_files"
assert "projects" not in new and "project_members" not in new
@@ -112,7 +113,37 @@ def test_insert_rows_relinks_ids():
assert new["terrain_layers"]["surface_model_id"] == model_id
assert new["routes"]["surface_model_id"] == model_id
route_id = 1005
assert route_map == {5: route_id}
assert new["route_points"]["route_id"] == route_id
assert new["longitudinal_sections"]["route_id"] == route_id
params = json.loads(new["project_workflow_stages"]["params"])
assert params == {"input_file_id": str(file_id), "surface_model_id": model_id}
def test_rekey_id_files_moves_route_and_model_ids(tmp_path):
corridor = tmp_path / "B05_Profile" / "corridor"
corridor.mkdir(parents=True)
# 옛 1068 → 새 1069 · 옛 1069 → 새 1091 (이름 겹침) · 0370 = 짝 없음
for old in (370, 1068, 1069):
(corridor / f"corridor_{old:04d}.json").write_text(str(old), encoding="utf-8")
(corridor / "corridor_x.json").write_text("x", encoding="utf-8")
sampling = tmp_path / "B06_Section" / "sampling.json"
sampling.parent.mkdir(parents=True)
sampling.write_text(json.dumps({"filter_key": "classification", "surface_model_id": 911}))
report = cp.rekey_id_files(tmp_path, {911: 952}, {1068: 1069, 1069: 1091})
names = {path.name: path.read_text(encoding="utf-8") for path in corridor.iterdir()}
assert names == {
"corridor_1069.json": "1068",
"corridor_1091.json": "1069",
"corridor_x.json": "x",
}
assert report["corridor_removed"] == ["corridor_0370.json"]
assert json.loads(sampling.read_text())["surface_model_id"] == 952
# 폴더 없음 = 빈 보고
assert cp.rekey_id_files(tmp_path / "없음", {}, {}) == {
"corridor": {},
"corridor_removed": [],
"sampling": None,
}