Merge remote-tracking branch 'origin/dev' into sub_laptop_1

This commit is contained in:
2026-09-14 09:11:15 +09:00
6 changed files with 59 additions and 8 deletions
@@ -288,9 +288,28 @@ def _haul_rows(
"origin": ORIGIN_HAUL,
}
)
if equipment == "dump_truck" and in_bill:
# 덤프 운반은 **싣는 일이 따로** — 산림품셈 10-12 「1. 적재」
# (굴착기 0.7㎥ · ㎝ 22초·180°).
# 흙깎기 9-3-2(㎝ 20초·135°, 깎아 옆에 둠)에 안 들어 있어 운반과 한 벌로 짝 줄을 냄
# (2026-09-14 브레인 판정). 거리와 무관 · 수량은 운반량 그대로.
rows.append(
{
**rows[-1],
"name": "덤프 적재",
"haul_distance_m": None,
"haul_equipment": LOADING_EQUIPMENT,
"spec_detail": f"{state_note} · 덤프 운반량만큼 싣기(10-12 「1. 적재」)",
}
)
return rows, unmatched
#: 인계 「덤프 적재」 짝 줄의 수단 표지 —
#: B09 `MachineProductivity_Dump.LOADING_EQUIPMENT` 와 같은 글.
LOADING_EQUIPMENT = "dump_loading"
def blocked_of(
structure: dict[str, Any], class_basis: str = "", has_code: bool = False
) -> tuple[str | None, str]:
@@ -628,7 +628,15 @@ def build_bill(
),
_ZERO,
)
haul_total = sum((item.quantity for item in work_items if item.haul_equipment), _ZERO)
# 「덤프 적재」 짝 줄은 운반이 아니라 싣기 — 같은 흙을 운반량으로 두 번 세지 않게 뺌.
haul_total = sum(
(
item.quantity
for item in work_items
if item.haul_equipment and item.haul_equipment != "dump_loading"
),
_ZERO,
)
if cut_total > 0 and haul_total > 0:
check_haul_volume_within_cut(
haul_volume_total_m3=haul_total,
@@ -358,7 +358,7 @@ B08 인계본 `ground_class_aliases` — **B09 가 안 읽음**)을 한 벌로
| 종목 | 단위 | 지위 | 비고 | 우리 실측과 |
| --- | --- | --- | --- | --- |
| 설계서의 **총액** | 원 | **1,000** | 미만버림 | ⚠ **아직 확인 안 됨** — 데스크탑 서브가 재는 중 |
| 설계서의 **총액** | 원 | **1,000** | 미만버림 | ⚠ **우리는 안 버리고 있었음** — 실무 6건은 여섯 다 `000`, 우리는 `373·695·578·654·341·639`. 기본을 켜는 것으로 판정(2026-09-14) |
| 설계서의 소계 | 원 | 1 | 미만버림 | ✅ |
| 설계서의 **금액란** | 원 | 1 | 미만버림 | ✅ 「내역에 실릴 때 정수 절사」와 같음 |
| **일위대가표의 계금** | 원 | 1 | 미만버림 | ✅ 「호표 안 성분 소계 절사」와 같음 |
@@ -366,6 +366,15 @@ B08 인계본 `ground_class_aliases` — **B09 가 안 읽음**)을 한 벌로
**STmate 를 재서 얻은 규칙이 법 조문이었음.** 경쟁사를 베낀 것이 아니라 둘 다 같은 고시를 따른 것임.
**총액 줄만 우리가 안 따르고 있었음** (2026-09-14 데스크탑 서브 실측). 기본값이 꺼져 있어(`cut_basis=""`)
실무 6건의 총공사비 끝 세 자리가 우리 엔진에서만 남음. **기본을 켜되 화면에 근거를 보일 것**
2026-09-08 「조용히 깎지 않음」 합의는 근거가 없을 때 정한 것이고, 지금은 고시가 근거임.
곁에 버그 하나 — 절사 자동보정이 둘째 걸음부터 ÷1.1 을 안 해 경계를 지나쳐 **진동**함
(울진 신설 `654→999→900→910→909…`). 다섯 건은 첫 걸음에 앉아 안 드러났음.
⚠ 「설계서의 소계 1원 미만버림」과 우리 「집계표 행 금액 `ROUND`(279/279)」는 **다른 자리**로 봄 —
집계표는 설계서 소계가 아님. 같은 자리로 읽을 근거가 나오면 다시 잴 것.
**같은 고시 1-2-2 「1. 수량의 단위표준」 [주]**:
```
+10 -3
View File
@@ -188,6 +188,11 @@ def test_무대는_넘기되_내역에는_안_섬() -> None:
assert dump["in_bill"] is True
assert dump["work_item_code"] == "FP-10-12"
assert dump["haul_distance_m"] == pytest.approx(1200.0)
# 2026-09-14 — 덤프 운반마다 「덤프 적재」 짝 줄(10-12 「1. 적재」) · 거리 없음 · 수량 같음
loading = (handoff, "덤프 적재")
assert loading["haul_equipment"] == "dump_loading" and loading["haul_distance_m"] is None
assert loading["quantity"] == dump["quantity"] and loading["variant_value"] == "토사"
assert not any(r["name"] == "덤프 적재" and r["spec"] != "토사" for r in handoff["work_items"])
def test_합계_줄은_내역에_안_섬() -> None:
@@ -600,9 +605,11 @@ def 운반표() -> dict:
def test_운반계획이_있으면_네_줄이_실림() -> None:
handoff = build_handoff(haul_table=운반표())
haul_rows = [row for row in handoff["work_items"] if row["origin"] == "haul"]
assert len(haul_rows) == 4
# 운반 넷 + 덤프 운반 둘의 적재 짝 줄 둘(2026-09-14 · 10-12 「1. 적재」 — 거리 없음)
moves = [row for row in haul_rows if row["haul_equipment"] != "dump_loading"]
assert len(moves) == 4 and len(haul_rows) == 6
assert all(row["haul_equipment"] for row in haul_rows)
assert all(row["haul_distance_m"] for row in haul_rows)
assert all(row["haul_distance_m"] for row in moves)
def test_무대가_함께_와야_운반_검산이_걸림() -> None:
@@ -612,7 +619,7 @@ def test_무대가_함께_와야_운반_검산이_걸림() -> None:
assert free["in_bill"] is False
assert free["quantity"] == pytest.approx(871.0)
assert handoff["excluded_row_count"] == 1
assert handoff["bill_row_count"] == 3
assert handoff["bill_row_count"] == 5 # 도자 · 덤프 운반 둘 · 덤프 적재 짝 줄 둘
def test_운반계획이_없으면_줄이_없음() -> None:
+7 -3
View File
@@ -53,10 +53,14 @@ def test_v16_불도저_운반이_갈래마다_금액으로_선다() -> None:
assert build.book.resolve(code).total > 0, code
def test_v16_덤프_운반은_아직_안_선다() -> None:
"""⚠ 안 서는 것도 사실대로 못 박는다 — 운반거리(설계 입력)를 기다리는 자리다."""
def test_v16_덤프_운반은_거리가_와야_선다() -> None:
"""⚠ 안 서는 것도 사실대로 못 박는다 — 운반은 운반거리(설계 입력)가 와야 선다.
2026-09-14 적재(10-12 1. 적재) 거리 무관이라 서고, 운반(`#L…m`)은 거리가 온 조립에만.
"""
build = cached_build()
assert not [code for code in build.book.titles if code.startswith("B-FP-10-12")]
dump = [code for code in build.book.titles if code.startswith("B-FP-10-12")]
assert dump and all(code.endswith("#적재") for code in dump)
# ── V-17 ────────────────────────────────────────────────────────────
@@ -23,6 +23,10 @@ def test_단가표_갈래_제목은_전부_마스터_갈래_키에_있다() -> N
for code in cached_build().book.titles:
if not code.startswith("B-") or "#" not in code:
continue
if code.startswith("B-FP-10-12-"):
# 덤프 운반·적재(10-12)는 **표가 아니라 본문 식**이라 마스터 표에 갈래가 없음 —
# 갈래(`#적재`·`#L…m`)는 식이 냄(2026-09-14 · `MachineProductivity_Dump`).
continue
work_item, variant = code[2:].split("#", 1)
keys = {
normalize_variant_key(k) for k in nodes.get(work_item, {}).get("variant_keys") or []