5 Commits
Author SHA1 Message Date
eomsangdon d54d52b6eb Merge remote-tracking branch 'origin/sub_desktop_1' into sub_laptop_1 2026-09-15 03:33:27 +09:00
eomsangdon 9f1adeab49 Merge remote-tracking branch 'origin/dev' into sub_laptop_1 2026-09-15 03:33:26 +09:00
eomsangdonandClaude Opus 5 05e88998c1 chore(plan): 임시 창별 계획서 — PLAN_데스크탑서브.md
까닭 — 2026-09-15 시놀로지가 두 PC 의 PLAN.md 를 번갈아 덮어 계획서를 거듭 잃음.
PLAN.md 가 git 밖이라 이력이 없어 되살릴 곳이 없었음. 창마다 제 파일을 git 에 두면
PC 사이를 git 이 건너가고 이력이 남으며 파일이 달라 서로 안 지움(브레인 지시).

⚠ 사용자 지침(PLAN.md 는 git 밖 · 한 파일로만 운영)을 어기는 임시 조치임.
   파일 머리에 「임시 · 사용자 확인 전」을 적어 둠 · .gitignore 는 안 건드림 ·
   합친 뒤 지움.

담은 것 — 닫은 일곱(커밋 해시째) · 재기만 한 셋([저장]·[확정] · BOX암거 셋 가름 ·
12-19 밑수) · 남은 것(UnitPrice.py 1403줄 쪼개기 · 판정 대기 넷).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Prk9BCHG1EMAywk9k8wegA
2026-09-15 03:31:33 +09:00
eomsangdonandClaude Opus 5 0781e6c379 chore(plan): 임시 창별 계획서 — 랩탑 서브(시놀로지 덮어쓰기 때문 · 사용자 확인 전 · 브레인 지시)
공유 PLAN.md 가 03:22:27 데스크탑 판으로 덮여 사라진 줄을 대화 기록에서 옮김 · PLAN.md 는 읽기만

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016VBGFXB9AbJBwXP19z75Qq
2026-09-15 03:31:18 +09:00
eomsangdonandClaude Opus 5 15551b9ea1 fix(b08): BOX 비계 단위 ㎡→㎥(공㎥) — 원단위 성분·묶음 조각 FP-12-19 · 사유 「비계 폭 1.0m 관측(울진)」(브레인 승인)
울진 단위 칸 「공/m3」 · 시종점 식의 ×1.00 은 연장일 수 없어 폭 1.0m 로 역산 · 값은 그대로(면 × 1.0) · B09 12-19 쪽은 안 건드림

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016VBGFXB9AbJBwXP19z75Qq
2026-09-15 03:14:25 +09:00
5 changed files with 135 additions and 3 deletions
@@ -41,6 +41,8 @@ NOTE_SHORING_SCAFFOLD = (
"(울진 2×2 「강재 3개월」) — 품셈 12-20 강관동바리 · 12-19 강관비계로 이음 ·" "(울진 2×2 「강재 3개월」) — 품셈 12-20 강관동바리 · 12-19 강관비계로 이음 ·"
" 시종점 두 면은 개소당 한 번(원문은 m당 칸)" " 시종점 두 면은 개소당 한 번(원문은 m당 칸)"
) )
#: 비계는 공㎥(품셈 12-19 밑수) = 면 × 폭 — 울진 단위 칸 「공/m3」 · 시종점 식 ×1.00 은 연장일 수 없음.
SCAFFOLD_NOTE = "비계 폭 1.0m 관측(울진)"
NOTE_WING = "날개벽 수량 근거 없음(교본·실무 모두 · 판정 ⑤) — 날개벽 줄 안 섬" NOTE_WING = "날개벽 수량 근거 없음(교본·실무 모두 · 판정 ⑤) — 날개벽 줄 안 섬"
NOTE_RUBBLE = ( NOTE_RUBBLE = (
"기초잡석 — 근거 둘(예제·울진 집계표)에는 잡석 줄이 없음 — 사용자 확정 3차 ② 로 세움" "기초잡석 — 근거 둘(예제·울진 집계표)에는 잡석 줄이 없음 — 사용자 확정 3차 ② 로 세움"
@@ -104,7 +106,7 @@ def box_culvert(options: dict[str, Any]) -> tuple[list[Component], list[str]]:
f"{width:g}×{height:g} {haunch:g}²÷2×4", f"{width:g}×{height:g} {haunch:g}²÷2×4",
"", "",
), ),
("비계", "", 2 * outer_h, f"외벽 양면 {outer_h:g}×2", ""), ("비계", "", 2 * outer_h, f"외벽 양면 {outer_h:g}×2 × 폭 1.0({SCAFFOLD_NOTE})", ""),
] ]
notes: list[str] = [SOURCES, NOTE_FORMWORK, NOTE_SHORING_SCAFFOLD, NOTE_WING, NOTE_RUBBLE] notes: list[str] = [SOURCES, NOTE_FORMWORK, NOTE_SHORING_SCAFFOLD, NOTE_WING, NOTE_RUBBLE]
if math.isclose(width, 2.0) and math.isclose(height, 2.0): if math.isclose(width, 2.0) and math.isclose(height, 2.0):
+85
View File
@@ -0,0 +1,85 @@
# PLAN — 데스크탑 서브 (B09 원가계산서)
> **임시 · 2026-09-15 시놀로지 덮어쓰기 때문 · 사용자 확인 전.**
> `PLAN.md` 는 두 PC 가 번갈아 덮어 창마다 제 파일에 적기로 함(브레인 지시).
> 나중에 브레인이 넷을 합쳐 `PLAN.md` 한 벌로 되돌림. `PLAN.md` 는 **읽기만** 함.
>
> ⚠ **사용자 지침을 어기는 자리**임 — 지침은 「`PLAN.md` 는 git 밖」·「한 파일로만 운영」인데
> 이 파일은 **git 안**이고 창마다 따로임. 오늘 밤 계획서를 거듭 잃은 까닭이 **git 밖이라 이력이
> 없어서**라 임시로 이렇게 둠. 사용자가 깨면 「PLAN 을 아예 git 으로 옮길지」를 브레인이 물음 —
> 합치고 나면 이 파일은 지움. `.gitignore` 는 사용자 파일이라 **안 건드림**.
## 닫은 것 — 2026-09-14 ~ 15
- [X] **골든셋을 원가계산서까지 넓힘** (`deac8200`) — 새 `resources/tester/test_b09_golden_cost_sheet.py`.
실무 6건 「공사원가계산서」 시트를 우리 엔진으로 되풂 · **요율은 원본 비고에서 뽑아 그 원본 전용 판**을 지어
「요율이 달라서 틀림」을 없앰 · 제비율 줄마다 **54자리 전수 일치**(안전관리비 A·B·채택 포함) ·
사슬은 온전한 셋(봉화·영월·울진 공통) **33자리 일치** · 이윤은 자동절사가 맞춘 둘(봉화 339·영월 632)과
설계자 조정 하나(울진 905,980) · 영월 도급공사비 차 762,000 = 원본에만 있는 국가지점번호판검증수수료.
검증완료(전체 1782)
- [X] **총액 1,000원 미만 버림을 기본으로 켬 · 절사 진동 고침 · 고정값 벌 이관** (`aeb18266`) —
근거 산림청고시 제2025-82호 「금액의 단위표준」 · 실무 6건이 여섯 다 `000` ·
**조용히 안 깎음**(이윤 조정액 줄·메모에 고시 번호와 「11 에서 끌 수 있음」) ·
끄는 값을 `none` 으로 바꿈(빈 값은 저장이 안 돼 끌 수가 없었음) ·
진동은 걸음마다 ÷1.1 로 고침 · `tmp/tests/test_b09_cost_fixtures.py``resources/tester/` 이관(사본은 안 지움).
검증완료(전체 1782)
- [X] **안전관리비 B 절사 자리를 STmate 실증본 쪽으로 · SA 안전관리비 별도내역 · 고시 대조 벌** (`00919e86`) —
1.2배의 대상을 **호별 산정이 끝난 금액**으로(고시 제4조① 단서 문언 + 영월 2024 B 20,330,639 → **20,330,638**) ·
SA 「확인 대기」 → 별도내역 · 새 `test_b09_safety_notice.py`(별표1 표를 **원문 md 에서 읽어** 16칸 전수 대조).
**두 실증본이 갈림** — 거창 2025(STmate 출력 아님)는 옛 셈이라 B 가 1원 위, 사유로만 남기고 채택 안 함.
검증완료(전체 1911)
- [X] **제3조 적용 하한을 엔진이 읽게 함 · 1.2배 차례와 관급 ÷1.1 사유 명기** (`5a016979`) —
「총공사금액 2천만 원 이상」 미달이면 **줄 자체를 안 만듦**(A·B 곁줄도 · 0 원으로 안 채움) ·
견주는 값은 규모 기준액(고시의 「총공사금액」과 딱 같은 말은 아니나 계산 차례상 그것뿐) ·
관급 ÷1.1 은 고시에 없고 **실무 6건 공통**임을 두 자리에 적음. 검증완료(전체 1952)
- [X] **기계 수송비 회수(대수 × 왕복) 설계 입력 칸** (`1400b7b7`) —
산림품셈 10-4 · 건설품셈 8-1-3 이 **회당 단가 산출식만** 주고 대수·횟수를 안 정함(전수 확인) ·
`parse_trips`(비거나 0 이면 없음 · 기본값 안 둠) · `transport_amount`(곱 하나뿐) · `TRIPS_NOTE` ·
도는 자리 넷(저장·산출조건·화면·못 채운 자리). 검증완료(전체 1976)
- [X] **절사 자동보정을 이분으로 앉힘** (`47196780`) —
이윤 1원이 총공사비 1~2원이라 ÷1.1 어림이 지나쳐 거창 꼴 40 자리 중 16 이 끝자리 999 로 남았음 ·
목표를 못 박고 **가장 작은 보정액을 이분으로** 찾음 · 못 밟는 배수면 한 칸 아래(실측 0건) ·
40/40 앉음 · 깎인 몫 356~423원으로 늘 한 칸 안쪽 · 실무 6건 보정액 그대로. 검증완료(전체 2043)
- [X] **B09 700줄 넘은 모듈 둘 쪼갬** (`e0c5e364`) — **순수 분리**, 그 김에 아무것도 안 고침 ·
`BillOfQuantities.py` **733 → 597** + 새 `_BillOfQuantities_Input.py` 162 ·
`Engine_Cost.py` **725 → 609** + 새 `_Engine_Cost_Input.py` 136 ·
쓰던 이름은 본 모듈이 다시 내보내 그대로 돎. 검증완료(전체 **2102** · 두 번 돌려 같음 · B09 부분 398)
## 재기만 한 것 (고치는 것은 배정 대기)
- [X] **[저장]·[확정] 때 B09 서버 재계산** — 큰 그림은 규칙대로임. **저장물이 없고** 쓰기 열 자리가 전부
**입력만** 저장, 금액은 GET 마다 서버가 다시 계산. 브라우저 금액을 받아 적는 자리 **없음**.
-**결함 하나**`GET /estimation/cost-sheet``settings` 가 **엔진이 푼 값**이고 화면이 그대로
되돌려 보내 [저장] 한 번에 **23칸 중 22칸**이 박힘(안 고른 `cut_basis` · `vat_mode` · `duration_days` 까지).
기본값 판정이 바뀌어도 그 프로젝트엔 **안 닿음**. 계약·실행·기성은 `stored` 를 줘서 이 병이 없음.
고치는 법 두 갈래 — ㉠ GET 이 `stored` 를 draft 로 · ㉡ 화면이 기본값과 같은 칸을 안 보냄. **판정 대기**
-**[확정]은 아무것도 다시 계산 안 함**(stage 만 COMPLETE) — 「반만 계산해 덮음」 병은 없으나
**확정 시점 값이 안 박힘**. 둘 것인지 박을 것인지 **판정 대기**
- [X] **BOX암거 막힘 셋 가름****정말 막힌 것은 하나뿐**.
- 12-01-01 — 막힘 아님. 호표가 **세 갈래 다 섬**(무근 58,635 · 철근 65,826 · 소형 117,270 원/㎥).
갈래 없이 부르면 제목이 없어 「일위대가 없음」으로 적힌 것
- 12-38 유로폼 — 막힘 아님. 설치·해체는 이미 섬 · 안 선 자리는 `12-38-02` 자재비 하나 ·
「자재 단가」 탭에 **패널+내부 패널(손료)** 또는 **임대료 ㎡당** 중 **하나**만 넣으면 섬
- ⭐ 12-19 강관비계 — 정말 막힘(아래)
- [X] **12-19 강관비계 밑수** — 원문에 **이미 적혀 있었고 못 읽은 쪽은 우리**였음.
- ① 고시 6612줄 `(단위: 공㎥당)` — 파서가 그 줄 꼴은 읽으나 **「공㎥」를 공종 단위로 안 받아**
(`_QUANTITY_UNITS``㎥` 만) `unit_of('FP-12-19')=None` · 원문 전체에서 「공㎥」는 **이 한 절뿐**
-**부피 못 냄** — B08 이 비계를 **㎡** 로 보냄(외벽 양면 + 시종점 두 면 · 울진 18.72㎡/m).
동바리는 이미 ㎥ 이고 12-20 도 `(단위: ㎥당)` 이라 **그쪽은 맞음**
- ③ 12-19 [주]는 「공사기간 손율」뿐 **폭 규정 없음** ⇒ 설계 입력 칸 필요
- **갈래 판정 대기** — ㉠ B08 이 공㎥로 보냄 / ㉡ B09 가 「비계 폭(m)」 칸으로 **단가**를 환산
(수량은 B08 정본 그대로 · `BORROWED_BASIS_PER` 꼴)
- 곁 — 12-19·12-20 [주] **「공사기간에 따른 손율」을 지금 안 걸고 있음**(유로폼 사용횟수와 다른 자리)
## 남은 것
- [ ] **`UnitPrice.py` 1403줄** — 700줄 규칙 밖. 쪼개기 **따로 배정 필요**
- [ ] 위 「판정 대기」 넷 — 기준 입력판 기본값 박힘 · 확정 못 박기 · 12-19 갈래 · 12-19/12-20 공사기간 손율
+39
View File
@@ -0,0 +1,39 @@
# PLAN — 랩탑 서브
임시 · 2026-09-15 시놀로지 덮어쓰기 때문 · 사용자 확인 전 (브레인 지시 · git 에 명시 커밋 · 브레인이 나중에 PLAN.md 한 벌로 합침 · PLAN.md 는 읽기만)
## 12장 — B08 훑기 고칠 차례 이어 (PLAN.md 12장 「고칠 차례(브레인 2026-09-14)」)
- [X] ㉳ (가) 미교차 측점 지반 샘플을 지표면 끝까지 넓힘(+5m 씩 · 상한 = 지표면 끝) 8bf24c26. 검증완료
- ⚠ 사용자에게 올릴 거리 — 금액 129,498,518 → 154,857,626(+19.6%) · 미교차를 고쳐 성토가 늘어난 것(방향은 맞음)
- [X] ㉳ (나) 성토사면 길이 5m 초과 경고 줄 — 요약 한 줄 + 측점 목록 · 벽 선 쪽만 뺌(좌·우 갈라) · 경고만(브레인 승인 문구) b34eb546. 검증완료
- [X] 브레인 ① 유토 배분 수량은 거르지 않은 계획 · 잔진동 거르기는 그림에만(그림 손질이 수량에 닿지 않게) 20597071. 검증완료
- [X] 브레인 ② B07 횡단도 [확정]은 설계 상태만 올림 — 다시 계산한 값으로 정본을 덮던 것 걷음 · 62측점 전후 같음 41914890. 검증완료
- [X] ㉴ 준비공 상태 칸 「입력이 필요함」과 「값을 낼 근거가 없음」을 가름 · 인계 막힘 갈래도 상태를 따름 364c28a7. 검증완료
- [X] 부대시설 셋째 상태 「품셈 공종 없음 — 단가를 직접 넣어야 함」 · 「자재 단가」 탭 통로 490cfe1d. 검증완료
- 국가지점번호판 개소 — 임도규정 §26⑤ 500m 제안 · 사유에 「임도기술교본 11-6 은 1㎞」 병기 → 12장 D 표지로 묶음
- [X] ㉰㉵ 내역 표시 흠 — 운반 줄 장비 키 · 덤프 거리 14자리 · 규격 갈래 두 번 7dd5dda9. 검증완료
## 12장 D — 표 식 자체 없음 이어 (PLAN.md 12장 「D 표 식 자체 없음」)
- [X] BOX암거·세월교 (브레인 판정 ①~⑥) — ⚠ 교본 그림 3-18~3-20 은 배치 모식도(치수 없음)
- 등록부 두께·연장 칸(예제 벽 0.3 · 판 0.25 · KDS 300㎜ 병기) · m당 × 연장 전개식(산림과임업기술 5장 예제 · 울진 기번3 2×2 집계표) · 철근은 2×2 관측만 · 세월교·날개벽은 근거 없음 사유 a314ac12. 검증완료
- 구체 터파기 — 평균 터파기고 칸 하나 · 토공 축으로만 · 기초잡석 사유 「근거 둘에는 잡석 줄이 없음 — 사용자 확정 3차 ② 로 세움」 e40f4c9f. 검증완료
- 원문끼리 다름(울진은 잔토에 구체 전체 · 되메우기 한쪽) — 옹벽 식(터파기 − 든 것)으로 통일
- 비계 ㎡ → ㎥(공㎥) — 울진 단위 칸 「공/m3」 · 시종점 식 ×1.00 으로 폭 1.0m 역산 · 사유 「비계 폭 1.0m 관측(울진)」 · B08 만 15551b9e
- 남은 막힘(B09 · 데스크탑 서브 몫) — 12-01-01 호표 없음 · 12-19 밑수 공㎥ · 12-38 은 유로폼 패널 단가가 들어가면 섬
- ⚠ 사용자에게 알릴 것 — BOX 두께 「세월교 승계」(2026-08-25 사용자 확정) 걷고 등록부 칸으로 옮김
- [ ] 포장 둘 — 임도기술교본 3-2 p.54(콘크리트 폭 3.0m·두께 0.2m) · 10-1 p.203~207(쇄석 사전터파기 0.10m·다짐후 0.20m 이하) (브레인 승인)
- 판정 ①~⑨ (브레인 2026-09-15) — 원문(교본)이 기준 · 실무는 사유로 병기 · 다른 데서 아는 값은 자동으로 잇고 칸으로 덮어씀
① 폭 — B06 노폭을 따라감이 기본 · 교본 3.0 은 그 아래 제안 · 사유 「실무 관측 3.5~4.0」
② 두께 제안 20㎝(교본) ③ 수축줄눈 간격 제안 6m(교본 부록 4~6m · 소광 관측 6m)
④ 확폭 — B06 곡선 확폭 자동 + 칸 덮어쓰기(실무 「별산」은 표시 방식)
⑤ 비닐·철망 — 고르기(있음/없음) · 기본값 없음 · 안 고르면 사유 · 소광 「철망포함」 관측 사유
⑥ 혼합석 면적 — B06 비포장 측점 자동 + 칸
⑦ 혼합석 두께 — 교본 「다짐 후 0.10」 완성 두께 · 자재는 ÷C×L 환산 · 소광 「다짐전 0.10」 사유 병기
⑧ 쇄석 사전 터파기 0.10 — 토공 축으로만
⑨ 다짐 품 — 원문 확인 먼저 · 없으면 사유(지어내지 않음)
- [ ] 녹화 — 교본 7-1 · 그림 7-8~7-12 「표준도」가 모식도인지 먼저
- [ ] 소단 — 임도 조문(사면길이 2~3m 마다 폭 50~100㎝) · 사방 기준 아님
- [ ] 개소형 — 대피소·작업장·차돌림곳·노출형 횡단수로
- [ ] 부대 — 가드레일·반사경·표지(그림 11-6~11-8 표준도 확인 · 번호판 500m 제안)
@@ -478,8 +478,9 @@
{ {
"code": "FP-12-19", "code": "FP-12-19",
"name": "강관비계", "name": "강관비계",
"unit": "", "unit": "",
"from_components": ["비계"] "from_components": ["비계"],
"why": "12-19 밑수는 공㎥ — 울진 기번3 단위 칸 「공/m3」 · 시종점 식의 ×1.00 은 연장일 수 없어(끝면은 연장과 무관) 비계 폭 1.0m 관측(울진)으로 면 × 1.0 = 공㎥"
}, },
{ {
"code": "FP-12-25", "code": "FP-12-25",
@@ -49,6 +49,9 @@ def test_울진_2x2_m당_값을_연장에_곱한다() -> None:
assert got[("동바리", "")] == pytest.approx(3.92 * 10) assert got[("동바리", "")] == pytest.approx(3.92 * 10)
# 비계 — 벽체 m당 5.2 × 연장 + 시종점 두 면 13.52 는 한 번(원문은 m당에 넣었음 · 사유). # 비계 — 벽체 m당 5.2 × 연장 + 시종점 두 면 13.52 는 한 번(원문은 m당에 넣었음 · 사유).
assert got[("비계", "")] == pytest.approx(5.2 * 10 + 13.52) assert got[("비계", "")] == pytest.approx(5.2 * 10 + 13.52)
# 비계는 공㎥(12-19 밑수) — 울진 단위 칸 「공/m3」 · 시종점 식 ×1.00 은 연장일 수 없어 폭 1.0m.
scaffold = next(c for c in result.components if c.name == "비계")
assert scaffold.unit == "" and "비계 폭 1.0m 관측(울진)" in scaffold.basis
assert (result.billing_unit, result.billing_quantity) == ("m", 10.0) assert (result.billing_unit, result.billing_quantity) == ("m", 10.0)
text = " ".join(notes) text = " ".join(notes)
assert "관측" in text and "날개벽" in text assert "관측" in text and "날개벽" in text
@@ -129,3 +132,5 @@ def test_인계_묶음이_조각을_세운다() -> None:
assert {"FP-12-01-01", "FP-12-04", "FP-12-38", "FP-12-03", "FP-12-20", "FP-12-19"} <= set(parts) assert {"FP-12-01-01", "FP-12-04", "FP-12-38", "FP-12-03", "FP-12-20", "FP-12-19"} <= set(parts)
assert parts["FP-12-03"]["quantity"] == pytest.approx((179 + 157) * 10 / 1000) assert parts["FP-12-03"]["quantity"] == pytest.approx((179 + 157) * 10 / 1000)
assert parts["FP-12-20"]["quantity"] == pytest.approx(3.92 * 10) assert parts["FP-12-20"]["quantity"] == pytest.approx(3.92 * 10)
assert parts["FP-12-19"]["unit"] == ""
assert parts["FP-12-19"]["quantity"] == pytest.approx(5.2 * 10 + 13.52)