fix(528-6): D · E 생성 가볍게 — B 양식(10.76 MB) 복사 · B0x 빈 폴더 없음(D = D0x + B04_PreProcess · E = E0x) · 경로 풀이가 D · E 루트에 B 폴더를 다시 만들던 것 막음 · ROAD 그대로 · 시험(종류 저장소 · ROAD 배치 · 풀이 건너뜀)(요구 351)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-25 23:27:02 +09:00
co-authored by Claude Opus 5.5
parent 9a17db3d6c
commit 292dfc9e37
3 changed files with 55 additions and 10 deletions
+12 -9
View File
@@ -1,25 +1,24 @@
"""종류별 프로젝트 행 만들기 — D 예정노선 · E 안정성평가(요구 345).
임도설계(ROAD)는 B02 그대로. 저장소 경로 · 초기 폴더는 B02 함수를 그대로 씀.
임도설계(ROAD)는 B02 그대로. 저장소 경로는 B02 함수를 씀 · 초기 폴더는 종류 단계만
(B 양식 복사 · B0x 빈 폴더 없음 · D 는 지형 배치 B04_PreProcess 더함).
"""
from __future__ import annotations
from datetime import datetime
from pathlib import Path
from typing import Any
from uuid import uuid4
from B02_ProjRegister.B02_ProjRegister_Repository import (
_build_project_storage,
_initialize_project_storage,
)
from B02_ProjRegister.B02_ProjRegister_Repository import _build_project_storage
from common_util.common_util_audit import record_audit
from common_util.common_util_storage import get_project_stage_path
from common_util.common_util_workflow_state import initialize_project_stages
from config.config_db import get_db_pool
KIND_STAGE_DIRS = {
"PLAN": ("D02_PlanBase", "D03_PlanAnalysis", "D04_PlanConfirm"),
"PLAN": ("D02_PlanBase", "D03_PlanAnalysis", "D04_PlanConfirm", "B04_PreProcess"),
"STABILITY": (
"E02_StabGround",
"E03_StabSection",
@@ -31,6 +30,12 @@ KIND_STAGE_DIRS = {
}
def init_kind_storage(project_root: Path, kind: str) -> None:
"""종류 단계 폴더만 — B 양식 · B0x 빈 폴더 · workflow · manifest 없음."""
for stage_dir in KIND_STAGE_DIRS[kind]:
get_project_stage_path(str(project_root), stage_dir)
async def create_kind_project(
*,
request: Any | None,
@@ -99,9 +104,7 @@ async def create_kind_project(
resource_ref=project_id,
request=request,
)
_initialize_project_storage(project_root, project_id)
for stage_dir in KIND_STAGE_DIRS[kind]:
get_project_stage_path(str(project_root), stage_dir)
init_kind_storage(project_root, kind)
await connection.commit()
except Exception:
await connection.rollback()
+8 -1
View File
@@ -20,6 +20,8 @@ PROJECT_STORAGE_LAYOUT_V2 = (
("B08_Quantity", "quantities"),
("B09_Estimation", "v1"),
)
#: D · E 프로젝트 표지 — 생성 때 만드는 단계 폴더(common_util_project_kind)
KIND_STAGE_MARKERS = tuple(sorted(s for s in PROJECT_STORAGE_STAGE_DIRS if s[0] in "DE"))
def get_project_stage_path(project_root: str, stage: str) -> str:
@@ -37,8 +39,13 @@ def get_project_stage_path(project_root: str, stage: str) -> str:
def ensure_project_storage_layout(project_root: str) -> None:
"""신규 워크플로우 저장소 하위 폴더를 누락분만 생성한다."""
"""신규 워크플로우 저장소 하위 폴더를 누락분만 생성한다.
D · E 프로젝트(D0x · E0x 단계 폴더가 있는 루트)는 B 폴더를 만들지 않음 — 쓰는 곳이 스스로 만듦.
"""
root = os.path.abspath(project_root)
if any(os.path.isdir(os.path.join(root, stage)) for stage in KIND_STAGE_MARKERS):
return
for stage, subdir in PROJECT_STORAGE_LAYOUT_V2:
if stage not in PROJECT_STORAGE_STAGE_DIRS:
raise ValueError(f"허용되지 않은 프로젝트 저장 단계입니다: {stage}")
@@ -6,6 +6,7 @@
- 공유 판정 — 지정 회사 GET 200 · PUT 403 · 미지정 403 · 같은 회사 그대로
- 가입 — go.kr = 회사 「산림청」 · ACTIVE · 화면이 보낸 회사 값 무시 · 다른 메일 = NO_COMPANY
- 종류별 단계 시드 · storage 허용 목록
- 528-6 D · E 저장소 = 종류 단계만(B 양식 · B0x 빈 폴더 없음 · D 는 B04_PreProcess) · ROAD 그대로
"""
import asyncio
@@ -17,6 +18,7 @@ from A07_Register import A07_Register_Router as reg_router
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 config.config_system import PROJECT_STORAGE_STAGE_DIRS
from D01_PlanRegister import D01_PlanRegister_Router as d01
@@ -269,3 +271,36 @@ def test_stage_seed_by_kind(kind, count):
def test_storage_dirs_allowed():
for name in ("D02_PlanBase", "D04_PlanConfirm", "E02_StabGround", "E05_StabReport"):
assert name in PROJECT_STORAGE_STAGE_DIRS
@pytest.mark.parametrize("kind", ["PLAN", "STABILITY"])
def test_kind_storage_light(tmp_path, kind):
init_kind_storage(tmp_path, kind)
names = {p.name for p in tmp_path.iterdir()}
assert names == set(KIND_STAGE_DIRS[kind])
assert ("B04_PreProcess" in names) == (kind == "PLAN")
assert not [p for p in tmp_path.rglob("*") if p.is_file()]
def test_road_storage_unchanged(tmp_path, monkeypatch):
from B02_ProjRegister import B02_ProjRegister_Repository as b02
seeded = []
monkeypatch.setattr(b02, "seed_project", seeded.append)
b02._initialize_project_storage(tmp_path, "p1")
assert seeded == [tmp_path]
assert (tmp_path / "B09_Estimation" / "v1").is_dir()
assert (tmp_path / "project_manifest.json").is_file()
@pytest.mark.parametrize("kind", ["PLAN", "STABILITY", None])
def test_resolve_layout_skips_kind(tmp_path, kind):
from common_util.common_util_storage import ensure_project_storage_layout
if kind:
init_kind_storage(tmp_path, kind)
before = {p.name for p in tmp_path.iterdir()}
ensure_project_storage_layout(str(tmp_path))
after = {p.name for p in tmp_path.iterdir()}
assert (after == before) == bool(kind)
assert ("B09_Estimation" in after) == (kind is None)