feat(M02): 집계 항목 복사본을 구조물마다 — templates/structures/{구조물 id} · 옛 항목 폴더 옮겨 받기 · 재적용(덮임 알림) · 개인에 저장 · 프로젝트에서 새 항목 · 지정 바꿈 · 삭제 때 고친 것은 _지난 (PLAN 26-2b)
- 같은 항목을 고른 구조물 둘도 도면 · 면적 · 재료 · 자재조합 · 일위대가 · 입력연결 · 입력값 · 고른자재 · 단가를 따로 가짐 · 폴더 = structure_id 또는 pipe@측점
- 옛 templates/items/{층}_{주인}_{키} 는 읽을 때 그 항목을 쓰는 구조물마다 복사(고친 값 유지) · 안 쓰이고 고친 것은 structures/_지난
- 길: 미리 가져오기 {structure, layer, owner, key} · POST …/{폴더}/reapply(refresh 옛 이름) · …/save-as {to, 경로, 이름} · …/items/new {structure, 경로, 이름, 단위} · 회사 없음 409
- manifest 원본에 경로(26-1 · 경로 칸 우선 · 옛 종류 · 분류는 건너뛰며 받음) · 원본이 바뀌거나 지워져도 복사본 · 계산 그대로(목록 마스터바뀜 · 원본없음)
- 채움(M02_Table_Fill)은 구조물 복사본의 열 정의를 읽음
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BU9gbNE3aWFUvE61pS2WGt
This commit is contained in:
@@ -88,13 +88,15 @@ def collect_items(
|
||||
) -> list[dict[str, Any]]:
|
||||
"""설계 정본 → 구조물 목록.
|
||||
|
||||
한 건 = `{type_id, placement, chainage_m, start_m, end_m, options, 관연장}`.
|
||||
한 건 = `{type_id, placement, chainage_m, start_m, end_m, options, 관연장, summary_item,
|
||||
복사본}` ·
|
||||
`복사본` = 그 구조물 집계 항목 복사본 폴더의 구조물 id(관 지점은 `pipe@측점` · 26-2b).
|
||||
"""
|
||||
types = types or structure_type_map()
|
||||
lengths = pipe_lengths or {}
|
||||
items: list[dict[str, Any]] = []
|
||||
_, structures = load_structures(str(project_root))
|
||||
for item in structures:
|
||||
for index, item in enumerate(structures):
|
||||
definition = types.get(item.type_id)
|
||||
if definition is not None and definition.managed_by:
|
||||
continue # 관 지점 정본이 주인 — 옛 저장분이 남아 있어도 두 번 안 셈
|
||||
@@ -107,6 +109,7 @@ def collect_items(
|
||||
"end_m": item.end_m,
|
||||
"options": _with_defaults(definition, dict(item.options or {})),
|
||||
"summary_item": item.summary_item,
|
||||
"복사본": item.structure_id or f"#{index}",
|
||||
}
|
||||
)
|
||||
for point in read_pipe_points_file(pipe_points_path_in(Path(project_root))):
|
||||
@@ -122,6 +125,7 @@ def collect_items(
|
||||
"options": _with_defaults(types.get(type_id), dict(point.options or {})),
|
||||
"관연장": _nearest(lengths, chainage) if type_id == "pipe" else None,
|
||||
"summary_item": point.summary_item,
|
||||
"복사본": f"pipe@{round(chainage, 3)}",
|
||||
}
|
||||
)
|
||||
return items
|
||||
@@ -593,7 +597,8 @@ def assign_items(
|
||||
"""지정 항목 모드 준비 — 구조물마다 스냅샷 열 정의로 고른 열을 정함(PLAN 21-0 · 21-3).
|
||||
|
||||
- 미지정 · 스냅샷 없음 = 표에 안 넣음(자동 맞춤 없음) · 알림 한 줄씩
|
||||
- 시스템 층 항목 = 같은 id 열 자리에 스냅샷 열 정의(원본이 바뀌어도 지정한 때 값)
|
||||
- 열 정의 = 그 구조물 복사본의 것(26-2b · 원본이 바뀌거나 지워져도 지정한 때 값)
|
||||
- 시스템 층 항목 = 같은 id 열 자리
|
||||
- 회사 · 개인 층 항목 = `열id@스냅샷폴더` 새 열(시스템 열과 id · 묶음이 안 겹치게)
|
||||
돌려주는 것 = (열을 맞춘 문서, `열` · `열묶음` 을 단 구조물, 알림).
|
||||
"""
|
||||
@@ -606,7 +611,8 @@ def assign_items(
|
||||
unassigned = missing = 0
|
||||
for item in items:
|
||||
chosen = item.get("summary_item")
|
||||
column = (read_snapshot(project_root, chosen) or {}).get("열") if chosen else None
|
||||
owner = item.get("복사본")
|
||||
column = (read_snapshot(project_root, owner) or {}).get("열") if chosen and owner else None
|
||||
if not chosen or not isinstance(column, dict) or not column.get("id"):
|
||||
unassigned += not chosen
|
||||
missing += bool(chosen)
|
||||
|
||||
Reference in New Issue
Block a user