feat(E): 단계 차례 보고서 맨 뒤 · DB 단계 행 여섯 · 체인 단계 상태 함수 (PLAN 565-1)

- 차례 = 지반 · 2D · 3D · 암반 · 광역 · 보고서 — STAB_STEP_ROUTES · 단계 막대 이름 · 아이콘 · 대시보드 요약 이름 같은 차례
- 단계 행 STABILITY 여섯(STAB_AREA 더함) · 022_stab_stages_six.sql = 옛 행 열쇠로 번호만 바꿈 · 없는 광역 행 NOT_STARTED · 다시 돌려도 같음
- mark_stab_step(project_id, step, state, message) — 체인 낱말(ground · 2d · 3d · rock · area · report × run · done · skip · error · cancel) → 단계 행 상태 · 열쇠로 찾음 · 실패 까닭만 남김
- E05 빈 상태 글 = E02 [해석 시작] · 보고서 안내에 암반 · 확률
- 시험 528 단계 여섯 · 상태 함수 · 280_2 가짜 차례 여섯 + 진짜 차례 끝 = E05

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-27 20:23:16 +09:00
co-authored by Claude Opus 5.5
parent 6e4a987ead
commit 0909db020f
11 changed files with 178 additions and 14 deletions
+10 -1
View File
@@ -119,7 +119,15 @@ const STUBS = {
ROUTES,
API_BASE_URL: "",
PLAN_STEP_ROUTES: ["d02-plan-base", "d03-plan-analysis", "d04-plan-confirm"],
STAB_STEP_ROUTES: ["e02-stab-ground", "e03-stab-section", "e04-stab-3d", "e05-stab-report"],
// 565-1 — 보고서(E05) 맨 뒤
STAB_STEP_ROUTES: [
"e02-stab-ground",
"e03-stab-section",
"e04-stab-3d",
"e06-stab-rock",
"e07-stab-area",
"e05-stab-report",
],
},
"./ui_template_locale": { t: (key) => key },
"./ui_template_modal": { openModal: () => undefined },
@@ -202,6 +210,7 @@ const ALL = [
"d04-plan-confirm",
"e01-stab-register",
"e02-stab-ground",
"e07-stab-area",
"e05-stab-report",
];
const rows = {};
+8
View File
@@ -43,6 +43,14 @@ def test_529_1_D_E_묶음_안에서만_앞뒤(results):
assert rows["d04-plan-confirm"]["plain"]["disabled"][:3] == [False, False, True]
assert rows["e02-stab-ground"]["plain"]["disabled"][:3] == [False, True, False]
assert rows["e05-stab-report"]["plain"]["disabled"][:3] == [False, False, True]
# 565-1 — 광역(E07) 뒤에 보고서 · 진짜 차례도 E05 가 끝
assert rows["e07-stab-area"]["plain"]["disabled"][:3] == [False, False, False]
config = (ROOT / "config" / "config_frontend.ts").read_text(encoding="utf-8")
stab = config.split("export const STAB_STEP_ROUTES = [")[1].split("]")[0]
assert [s.strip() for s in stab.split(",") if s.strip()][-2:] == [
"ROUTES.E07_STAB_AREA",
"ROUTES.E05_STAB_REPORT",
]
@pytest.mark.parametrize("shape", ["helpRow", "plain"])
+32 -2
View File
@@ -19,7 +19,12 @@ from A07_Register.A07_Register_Schema import RegisterRequest
from common_util import common_util_auth as auth
from common_util import common_util_auth_repository as auth_repo
from common_util.common_util_project_kind import KIND_STAGE_DIRS, init_kind_storage
from common_util.common_util_workflow_state import initialize_project_stages
from common_util.common_util_workflow_state import (
STAB_STEP_STAGE_KEYS,
STAGE_KEYS_BY_KIND,
initialize_project_stages,
mark_stab_step,
)
from config.config_system import PROJECT_STORAGE_STAGE_DIRS
from D01_PlanRegister import D01_PlanRegister_Router as d01
from E01_StabRegister import E01_StabRegister_Router as e01
@@ -261,13 +266,38 @@ def test_register_ignores_sent_company():
assert "company_name" not in data
@pytest.mark.parametrize("kind,count", [("ROAD", 7), ("PLAN", 3), ("STABILITY", 5)])
@pytest.mark.parametrize("kind,count", [("ROAD", 7), ("PLAN", 3), ("STABILITY", 6)])
def test_stage_seed_by_kind(kind, count):
log = []
asyncio.run(initialize_project_stages(FakeCursor({}, log), "p1", kind))
assert len(log) == count
if kind == "PLAN":
assert [a[2] for _, a in log] == ["PLAN_BASE", "PLAN_ANALYSIS", "PLAN_CONFIRM"]
if kind == "STABILITY": # 565-1 — 보고서 맨 뒤
assert [a[2] for _, a in log][3:] == ["STAB_ROCK", "STAB_AREA", "STAB_REPORT"]
def test_565_1_stab_step_marks_by_key():
"""체인 낱말 → 행 상태 · 열쇠로 찾음 · 실패 까닭만 남김 · 모르는 낱말 거절."""
log = []
for step, state, message in (
("3d", "run", None),
("3d", "skip", None),
("area", "error", "x" * 300),
("report", "cancel", None),
):
asyncio.run(mark_stab_step("p1", step, state, message, FakeCursor({}, log)))
rows = [(args[0], args[3], args[-1]) for _, args in log]
assert rows == [
("IN_PROGRESS", None, "STAB_3D"),
("COMPLETE", None, "STAB_3D"),
("FAILED", "x" * 200, "STAB_AREA"),
("STALE", None, "STAB_REPORT"),
]
assert all("stage_key = %s" in sql for sql, _ in log)
assert set(STAB_STEP_STAGE_KEYS.values()) == set(STAGE_KEYS_BY_KIND["STABILITY"])
with pytest.raises(KeyError):
asyncio.run(mark_stab_step("p1", "2d", "weird", None, FakeCursor({}, log)))
def test_storage_dirs_allowed():