refactor(B05/B06): 유토곡선 일원화 — 보는 노선·횡단 재계산 창구·낡음 판정 통합
같은 데이터를 두 화면에 보여 주는 기능인데 세 곳이 갈려 값이 달랐다(실측: 절토(자연) B06 3,704.6㎥ ↔ B05 4,526.8㎥). ① 보는 노선 — B05는 최신 경로, B06은 최신 **확정** 경로를 열어 노선을 다시 탐색한 프로젝트에서 서로 다른 노선을 봤다(route 126 DRAFT ↔ 125 CONFIRMED, 같은 20m 측점 성토 4.82㎡ ↔ 85.9㎡). `get_workflow_route_context()`(최신 경로) 신설해 B06 화면 context가 그것을 쓴다. 납품 도면(B07)이 쓰는 확정 전용 창구는 그대로 둔다. ② 횡단 재계산 — 호출이 두 벌이라 인자가 갈렸다(B06만 표준 단면값·암 경계 오프셋 전달, 보존하는 사용자 부속값도 2개 ↔ 7개). `B06_Section_Cross_Refresh.refreshCrossDesigns()` 한 창구로 모으고 세션 편집값은 저장소에서 직접 읽어 패널 없는 B05도 같은 값을 보낸다. ③ 낡음 판정 — 「옛 암 2단계 필드 누락」 조건이 B06 페이지에만 있어 B05는 재계산을 건너뛰었다. 공용 `staleDesignChainages()` 안으로 옮겨 두 화면이 같은 시점에 같은 조치를 한다. 검증 — 공용 브라우저 실측: 두 화면 모두 route 126, 요약줄 문자열 완전 일치 (`절토(자연) 4,526.8㎥ · 성토 14,881.8㎥ · 토취 10,213.3㎥ · 최종 누가토량 −10,213.3㎥`). pytest 370 passed·17 skipped(일원화 검사 4건 신설), typecheck·prettier·ruff 통과. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -25,17 +25,18 @@ def _validate_stage_path(relative_path: str) -> str:
|
||||
return normalized.as_posix()
|
||||
|
||||
|
||||
async def get_confirmed_route_context(
|
||||
connection: aiomysql.Connection, project_id: UUID
|
||||
async def _route_context(
|
||||
connection: aiomysql.Connection, project_id: UUID, confirmed_only: bool
|
||||
) -> dict[str, Any] | None:
|
||||
"""프로젝트의 최신 확정 경로와 연결된 지표면 좌표계를 조회한다.
|
||||
"""경로 하나와 연결된 지표면 좌표계를 조회한다(정렬은 최신 우선).
|
||||
|
||||
surface_models.crs_epsg가 NULL이면(분석에 사용한 입력 파일에 좌표계가
|
||||
없던 경우) 같은 프로젝트 input_files의 감지된 좌표계로 폴백한다.
|
||||
"""
|
||||
status_filter = "AND r.status = 'CONFIRMED'" if confirmed_only else ""
|
||||
async with connection.cursor(aiomysql.DictCursor) as cursor:
|
||||
await cursor.execute(
|
||||
"""
|
||||
f"""
|
||||
SELECT r.id AS route_id,
|
||||
COALESCE(
|
||||
sm.crs_epsg,
|
||||
@@ -47,7 +48,7 @@ async def get_confirmed_route_context(
|
||||
) AS crs_epsg
|
||||
FROM routes r
|
||||
LEFT JOIN surface_models sm ON sm.id = r.surface_model_id
|
||||
WHERE r.project_id = %s AND r.status = 'CONFIRMED'
|
||||
WHERE r.project_id = %s {status_filter}
|
||||
ORDER BY r.computed_at DESC, r.id DESC
|
||||
LIMIT 1
|
||||
""",
|
||||
@@ -62,6 +63,26 @@ async def get_confirmed_route_context(
|
||||
}
|
||||
|
||||
|
||||
async def get_confirmed_route_context(
|
||||
connection: aiomysql.Connection, project_id: UUID
|
||||
) -> dict[str, Any] | None:
|
||||
"""최신 **확정** 경로 — 납품 도면(B07)처럼 확정본만 봐야 하는 곳이 쓴다."""
|
||||
return await _route_context(connection, project_id, confirmed_only=True)
|
||||
|
||||
|
||||
async def get_workflow_route_context(
|
||||
connection: aiomysql.Connection, project_id: UUID
|
||||
) -> dict[str, Any] | None:
|
||||
"""워크플로 화면이 보는 경로 = **최신 경로**(확정 여부 무관).
|
||||
|
||||
B05는 `get_latest_route()`로 최신 경로를 열고, B06은 확정 경로만 열어서 노선을 다시
|
||||
탐색한 프로젝트에서 두 화면이 **다른 노선**을 봤다(2026-09-03 실측: B05 route 126
|
||||
DRAFT / B06 route 125 CONFIRMED — 같은 20m 측점의 성토가 4.82㎡ ↔ 85.9㎡). 같은
|
||||
데이터를 두 창으로 보여 주는 구조이므로 경로 선택 규칙을 최신 경로 하나로 맞춘다.
|
||||
"""
|
||||
return await _route_context(connection, project_id, confirmed_only=False)
|
||||
|
||||
|
||||
async def get_latest_section_options(
|
||||
connection: aiomysql.Connection, project_id: UUID
|
||||
) -> dict[str, Any] | None:
|
||||
|
||||
Reference in New Issue
Block a user