- 운반 줄이 띠(bands)·이동(transfers)에서만 만들어져 사토는 잔량(residuals)으로 남아 어디에도 안 실렸음. 그래서 구조물 잔토 126.63㎥ 를 얹어도 덤프가 안 늘었고, 채집석 공제도 사토를 줄이는 값이라 끝까지 금액에 안 나타났음 - 실무에는 서는 줄(울진 대흥 1공구 토적집계 D32 사토 1,281㎥) - 운반표에 `spoil`(물량·거리·근거)을 실어 인계가 「사토 운반」 한 줄을 세움 - 물량은 유토곡선 결과 그대로 — 공제·가산이 끝난 값이라 여기서 또 만지지 않음. 자연방토는 실어 내지 않으므로 뺌 - 거리는 설계 입력 `spoil_site_distance_m` 신설 — 안 정했으면 막고 사유 (품셈이 정하는 값이 아니라 임의 거리가 그대로 금액이 됨) - 지반 갈래는 유토곡선이 안분하지 않아 갈래 없이 한 줄, 그 사실을 근거에 - tmp/tests/test_b08_spoil_haul.py 신설(6건) Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
82 lines
3.5 KiB
Python
82 lines
3.5 KiB
Python
"""사토 — 실어 내는 줄 (2026-09-08).
|
|
|
|
⚠⚠ **유토곡선이 사토를 내는데 아무도 실어 내지 않고 있었다.** 운반 줄은 `blocks[].bands`
|
|
와 `transfers` 에서만 만들어지는데, 사토는 `residuals(kind="spoil")` 로 남아 **어느 쪽에도
|
|
없다.** 그래서 구조물 잔토를 사토에 얹어도(126.63㎥) **덤프 물량이 하나도 안 늘었다** —
|
|
채집석 공제도 사토를 줄이는 값이라 **끝까지 금액에 안 나타났다**.
|
|
|
|
실무에는 서는 줄이다 — 울진 대흥 1공구 토적집계 `D32 사토 1,281㎥`.
|
|
|
|
⚠ **거리는 품셈이 정하지 않는다.** 사토장까지 거리는 설계 입력(`spoil_site_distance_m`)이고,
|
|
안 정했으면 **막고 사유를 낸다** — 임의 거리를 넣으면 그대로 금액이 된다.
|
|
⚠ **지반 갈래를 지어내지 않는다.** 유토곡선이 사토 잔량에 `ea/rr/br` 안분을 안 한다
|
|
(실어 내는 흙이 어느 지반에서 나왔는지 모름). 갈래 없이 한 줄로 세우고 그 사실을 적는다.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import Any
|
|
|
|
from B08_Quantity.B08_Quantity_Engine_Handoff_Mapping import (
|
|
BLOCKED_INPUT_MISSING,
|
|
ORIGIN_HAUL,
|
|
WorkItemMapping,
|
|
)
|
|
|
|
SPOIL_NAME = "사토 운반"
|
|
SPOIL_EQUIPMENT = "dump_truck"
|
|
DISTANCE_MISSING = (
|
|
"사토장까지 운반거리가 저장에 없어 값이 서지 않음 — 품셈이 정하는 값이 아니라 설계 입력임"
|
|
"(임의 거리를 넣으면 그대로 금액이 됨)"
|
|
)
|
|
GROUND_UNKNOWN = "⚠ 사토의 지반 갈래는 유토곡선이 안분하지 않아 갈래 없이 한 줄로 섬"
|
|
|
|
|
|
def spoil_haul_rows(
|
|
haul_table: dict[str, Any] | None, mapping: WorkItemMapping
|
|
) -> list[dict[str, Any]]:
|
|
"""사토를 실어 내는 줄 하나. 사토가 없으면 줄도 없다."""
|
|
spoil = (haul_table or {}).get("spoil") or {}
|
|
volume = float(spoil.get("volume_m3") or 0.0)
|
|
if volume <= 0:
|
|
return []
|
|
distance = spoil.get("distance_m")
|
|
entry = mapping.for_haul(SPOIL_EQUIPMENT) or {}
|
|
code = entry.get("work_item_code")
|
|
blocked = distance is None or float(distance) <= 0
|
|
reason = DISTANCE_MISSING if blocked else ""
|
|
note = spoil.get("note") or ""
|
|
return [
|
|
{
|
|
"work_item_code": code,
|
|
"name": SPOIL_NAME,
|
|
"spec": f"{float(distance):g}m" if not blocked else "",
|
|
"unit": "㎥",
|
|
"quantity": volume,
|
|
"quantity_gross": spoil.get("volume_gross_m3"),
|
|
"application_ratio_pct": None,
|
|
"application_ratio_breakdown": None,
|
|
"quantity_breakdown": None,
|
|
"ground_class": None,
|
|
"haul_distance_m": None if blocked else float(distance),
|
|
"haul_equipment": SPOIL_EQUIPMENT,
|
|
"station_from": None,
|
|
"station_to": None,
|
|
"excavation_method": None,
|
|
"spec_detail": " · ".join(part for part in (note, GROUND_UNKNOWN) if part),
|
|
"composite_parts": None,
|
|
"structure_kind": None,
|
|
"blocked_kind": BLOCKED_INPUT_MISSING if blocked else None,
|
|
"blocked_reason": reason,
|
|
"variant_axis": None,
|
|
"variant_value": None,
|
|
"secondary_axes": None,
|
|
"spec_class": None,
|
|
"spec_class_basis": "",
|
|
"composite_not_ready": None,
|
|
"in_bill": not blocked and code is not None,
|
|
"in_bill_reason": reason,
|
|
"origin": ORIGIN_HAUL,
|
|
}
|
|
]
|