Merge remote-tracking branch 'origin/dev' into sub_laptop_1
This commit is contained in:
@@ -178,6 +178,18 @@ def parse_toc(rows: list[list[str]]) -> list[dict[str, Any]]:
|
||||
return nodes
|
||||
|
||||
|
||||
def _is_section_title(section: str, by_number: dict[str, dict[str, Any]]) -> bool:
|
||||
"""진짜 절 제목인가 — 「번호. 이름」, 또는 마침표 없이 번호 뒤 글이 목차 절 이름과 같음."""
|
||||
if re.match(r"^\s*\d+(?:-\d+){0,3}\.\s", section):
|
||||
return True
|
||||
number = section_number(section)
|
||||
node = by_number.get(number) if number else None
|
||||
if node is None:
|
||||
return False
|
||||
tail = section.strip()[len(number) :]
|
||||
return "".join(tail.split()) == "".join(str(node.get("name") or "").split())
|
||||
|
||||
|
||||
def section_number(section: str) -> str | None:
|
||||
"""`"9-3-1. 인력"` → `"9-3-1"`. 번호가 없으면 `None`."""
|
||||
m = re.match(r"^\s*(\d+(?:-\d+){0,3})[.\s]", section + " ")
|
||||
@@ -598,10 +610,19 @@ def build() -> dict[str, Any]:
|
||||
orphans: list[dict[str, Any]] = []
|
||||
undetermined: list[dict[str, Any]] = []
|
||||
|
||||
last_section = ""
|
||||
for table in tables:
|
||||
if table["table_id"] == "F0001":
|
||||
continue # 목차 자신은 공종이 아니다.
|
||||
section = norm(table.get("section"))
|
||||
# ⚠ 원본 자료가 [주] 문장 조각을 절 제목으로 읽은 표가 있음 — 「12-2 표면 마무리를 따른다.」
|
||||
# (12-17-1 펌프카 타설 [주]) 가 표 7장을 12-2 에 붙여 가짜 갈래가 섰음(2026-09-14).
|
||||
# 절 제목은 「번호. 이름」 이거나(마침표 없는 원문 제목 「7-15-2 숲가꾸기, …」 도 있음)
|
||||
# 번호 뒤 글이 **목차의 그 절 이름과 같음** — 둘 다 아니면 문장 조각이라 앞 절을 이어받음.
|
||||
if _is_section_title(section, by_number):
|
||||
last_section = section
|
||||
elif last_section:
|
||||
section = last_section
|
||||
number = section_number(section)
|
||||
chapter = number.split("-")[0] if number else None
|
||||
form, why = detect_form(table, chapter)
|
||||
|
||||
@@ -67,7 +67,10 @@ FORM_JUDGMENTS: dict[str, tuple[str, str, str]] = {
|
||||
"F0216": ("8-2-4", "reference", "위와 같은 선정약제 목록"),
|
||||
"F0218": ("8-2-5", "reference", "위와 같은 선정약제 목록"),
|
||||
"F0453": (
|
||||
"8-2-3",
|
||||
# 2026-09-14 절 8-2-3 → 14-2 — 원본이 [주] 「…8-2-3 굴착기(2025)」…」 를 절로 읽던 것을
|
||||
# 앞 절 이어받기로 고치자 부록 앞 마지막 절(14-2)로 옮겨 감. 부록엔 절 번호가 없어 여전히
|
||||
# 제자리가 아님 — 참고표라 값에 안 닿음.
|
||||
"14-2",
|
||||
"reference",
|
||||
"〔부록 2〕 산림사업별 적용 가능 공종 목록 — 절 경계가 밀려 붙음",
|
||||
),
|
||||
@@ -103,8 +106,10 @@ FORM_JUDGMENTS: dict[str, tuple[str, str, str]] = {
|
||||
),
|
||||
# ── 제11·12장 ───────────────────────────────────────────────────
|
||||
"F0328": ("11-4", "coefficient", "행이 q·k·f·E — [주]① Q=3600×q×k×f×E/Cm"),
|
||||
"F0358": ("12-2", "reference", "시설유형 Type-Ⅰ~Ⅳ 적용 기준 설명"),
|
||||
"F0360": ("12-2", "reference", "현장조건 Type-Ⅰ~Ⅲ 적용 기준 설명"),
|
||||
# 2026-09-14 절 12-2 → 12-17-1 — 원본이 펌프카 타설 [주] 「…12-2 표면 마무리를 따른다.」 를
|
||||
# 절 제목으로 읽어 12-2 에 붙어 있던 표(빌더가 앞 절 이어받기로 고침). 형태 판정은 그대로.
|
||||
"F0358": ("12-17-1", "reference", "시설유형 Type-Ⅰ~Ⅳ 적용 기준 설명"),
|
||||
"F0360": ("12-17-1", "reference", "현장조건 Type-Ⅰ~Ⅲ 적용 기준 설명"),
|
||||
"F0388": ("12-34-4", "reference", "「재료비 JOINT FILLER」 항목만 — 값이 없는 구성 안내"),
|
||||
"F0390": ("12-36", "reference", "제작비·운송비·설치비 「견적처리」"),
|
||||
"F0392": ("12-38-1", "coefficient", "사용횟수별 잔존율(12회 25%·25회 10%)"),
|
||||
|
||||
@@ -20,8 +20,11 @@ CHISEL_CODE = "AR-M-a2926452"
|
||||
#: 치즐을 붙이는 기계 — 대형브레이커(분류 0230).
|
||||
BREAKER_PREFIX = "0230-"
|
||||
CHISEL_MISSING = "치즐소모량(본/hr) — 치즐 단가 없음(「자재 단가」 탭에서 넣으면 붙음)"
|
||||
#: ⚠ 선례를 함께 적음(2026-09-14 브레인 판정) — 사용자가 「같은 방식으로 유추할지」를 스스로 고르게.
|
||||
CHISEL_AVERAGE_NOT_GIVEN = (
|
||||
"치즐(평균 갈래) — 원문 [주]① 은 Q 평균만 정하고 치즐 평균은 안 줌(지어내지 않음)"
|
||||
"치즐(평균 갈래) — 원문 9-4-1 [주]① 은 Q 평균만 정하고 치즐 평균은 안 줌(지어내지 않음)"
|
||||
" · 참고 선례: 9-12-3 발파암 표는 같은 자리에서 치즐 평균"
|
||||
" 「(0.006+0.02+0.03)/3 = 0.018」 을 스스로 적음 — 같은 방식으로 볼지는 판정 대기"
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -44,6 +44,14 @@ KNOWN_GAPS: dict[str, tuple[str, str]] = {
|
||||
"ⓘ 커플링밴드는 값이 표에 없지만 [주]① 이 「**1EA/6m**」를 줍니다 — 자재가 서면 "
|
||||
"m 당 1/6 EA 로 셀 수 있습니다(다만 「필요시 별도 산정」이라 조건이 하나 더 붙습니다).",
|
||||
),
|
||||
# 2026-09-14 브레인 — 조용히 틀린 값이 이미 서 있어 **표 모양 본작업보다 사유를 먼저** 닮.
|
||||
"FP-09-19-01": (
|
||||
"값 불완전",
|
||||
"⚠ 이 값은 **불완전**합니다 — 원문 9-19-1 은 표 둘"
|
||||
"(① 절토면 고르기: 토질 6갈래 × 보통인부·공기압축기·소형브레이커·굴착기, 10㎡당"
|
||||
" · ② 성토면 고르기: 인력 2갈래·기계 1갈래)인데 지금은 두 표가 섞여 보통인부 한 줄만"
|
||||
" 섰습니다. 토질·절토/성토 갈래 읽기 전에는 이 값을 쓰지 말 것.",
|
||||
),
|
||||
"FP-12-25": (
|
||||
"운반거리 미정",
|
||||
"⚠ 이 값에는 **운반 몫이 빠져 있습니다** — 품셈 12-25 는 「운반 | 덤프트럭(15ton)」 줄을 "
|
||||
@@ -88,6 +96,13 @@ def known_gap_note(code: str | None) -> str:
|
||||
for prefix, note in CONDITIONAL_INCLUDED.items():
|
||||
if plain.startswith(prefix):
|
||||
parts.append(note)
|
||||
# 다른 품셈에서 빌린 밑수(사용자 확정) — 교차 참조와 실무 어긋남을 값 옆에(2026-09-14 · 종전엔
|
||||
# 고르기형 표 안내가 「못 붙은 줄」로 섰고 이 문구는 아무 데서도 안 불렸음).
|
||||
from B09_Estimation.B09_Estimation_WorkItemUnit import borrowed_unit_note
|
||||
|
||||
borrowed = borrowed_unit_note(plain)
|
||||
if borrowed:
|
||||
parts.append(f"ⓘ {borrowed}")
|
||||
return " / ".join(parts)
|
||||
|
||||
|
||||
|
||||
@@ -17,7 +17,8 @@
|
||||
|
||||
⚠ **못 따라가는 참조는 따라간 척하지 않는다.**
|
||||
· **자기 자신을 가리키는 것** — 9-13-14 가 「육상 발파암(1~2m)와 동일」이라 적었는데
|
||||
그 절이 곧 육상 발파암(1~2m)이다(원문 오기로 보이나 **고쳐 읽지 않는다**).
|
||||
그 절이 곧 육상 발파암(1~2m)이다. ⭐ 2026-09-14 브레인 승인으로 **그 두 절만** 고쳐 읽음
|
||||
(`READ_AS` — 고른 값·버린 값을 근거 줄에 나란히). 나머지 자기 참조는 여전히 빈 채로.
|
||||
· **가리키는 절을 못 찾는 것 · 그 절도 계수가 없는 것.**
|
||||
이 셋은 사유를 남기고 **빈 채로 둔다.**
|
||||
"""
|
||||
@@ -35,6 +36,21 @@ _NAMED = re.compile(r"^(?P<name>.+?)\s*(?:와|과)\s*동일$")
|
||||
#: 「육상과동일」 — 이름이 아니라 **한 낱말만 바꾸라**는 지시다(용수 → 육상).
|
||||
_SWAP_WORDS = (("용수", "육상"),)
|
||||
|
||||
#: 원문 참조가 풀 수 없게 적힌 자리를 **사람이 판정해** 고쳐 읽음 — 공종 → (읽을 이름, 사유).
|
||||
#: ⚠ 넓히지 말 것. 판정마다 근거(같은 절 형제들의 표기)를 사유에 적고 브레인·사용자 승인을 받음.
|
||||
READ_AS: dict[str, tuple[str, str]] = {
|
||||
"FP-09-13-14": (
|
||||
"육상 발파암(0~1m)",
|
||||
"원문 표기 「육상 발파암(1~2m)와 동일」(고시 2025-82 5189줄)은 자기 참조라 풀 수 없어"
|
||||
" 0~1m(9-13-13)로 읽음 — 같은 절 암절취(1~2m·2~3m)·용수 발파암이 모두 「(0~1m)와 동일」",
|
||||
),
|
||||
"FP-09-13-15": (
|
||||
"육상 발파암(0~1m)",
|
||||
"원문 표기 「육상 발파암(1~2m)와 동일」(고시 2025-82 5201줄)이 가리키는 9-13-14 가 자기"
|
||||
" 참조라 끝이 없어 0~1m(9-13-13)로 읽음 — 같은 절 형제들이 모두 「(0~1m)와 동일」",
|
||||
),
|
||||
}
|
||||
|
||||
#: 이 이름들만 계수로 본다. 참조가 가리키는 것도 결국 이 넷이다.
|
||||
_FACTOR_HEADS = {
|
||||
"k": "K",
|
||||
@@ -156,6 +172,9 @@ def reference_factor_values(
|
||||
if found is None:
|
||||
return own, [], ""
|
||||
target_name, raw_text = found
|
||||
read_as = READ_AS.get(code)
|
||||
if read_as:
|
||||
target_name = read_as[0]
|
||||
matches = [m for m in by_name.get(_normalize_name(target_name), []) if m != code]
|
||||
if not matches:
|
||||
return own, [], f"「{raw_text}」가 가리키는 절을 못 찾았습니다"
|
||||
@@ -172,6 +191,8 @@ def reference_factor_values(
|
||||
if missing:
|
||||
return own, [], f"「{raw_text}」를 따라갔으나 계수가 없습니다 — {', '.join(missing)}"
|
||||
step = f"「{raw_text}」 → {nodes[target].get('name', target)}"
|
||||
if read_as:
|
||||
step += f" ⚠ {read_as[1]}"
|
||||
return merged, [step, *path], ""
|
||||
|
||||
for code, node in nodes.items():
|
||||
|
||||
@@ -574,8 +574,10 @@ def match_table(
|
||||
# 정상 자원이 조용히 사라진다(2026-09-07 실측 — 부분일치 필터가 매칭 14건을
|
||||
# 지우고 있었음). 카탈로그에 있는 이름은 **정의상 자원**이다.
|
||||
# 범위 별칭 — 그 공종 범위 안에서만 카탈로그 쪽 이름으로 바꾼다(「화약공」 → 화약취급공).
|
||||
# 별칭이 코드를 적었으면 그 항목으로 곧장(규격이 조인 키인 기계가 다시 흐려지지 않게).
|
||||
entry = scoped_alias_entry(catalog, name_cell, node["work_item_code"])
|
||||
name_cell = apply_scoped_alias(catalog, name_cell, node["work_item_code"])
|
||||
entry = _resolve_cell(catalog, name_cell, [name_cell, *value_cells])
|
||||
entry = entry or _resolve_cell(catalog, name_cell, [name_cell, *value_cells])
|
||||
if entry is None:
|
||||
if is_non_resource_label(name_cell):
|
||||
continue # 머리글·소계 — 못 맞춘 목록에도 안 올린다
|
||||
@@ -699,6 +701,7 @@ from B09_Estimation.B09_Estimation_ResourceAxis_Sources import ( # noqa: E402
|
||||
from B09_Estimation.B09_Estimation_ResourceAxis_Join import ( # noqa: E402
|
||||
apply_scoped_alias,
|
||||
pick_by_spec,
|
||||
scoped_alias_entry,
|
||||
resolve_family,
|
||||
text_spec_candidates,
|
||||
unmatched_reason,
|
||||
|
||||
@@ -191,6 +191,10 @@ def match_choose_one_machine_table(
|
||||
|
||||
if made == 0:
|
||||
return False
|
||||
if per != 1:
|
||||
# 밑수를 사용자가 정해 빌려 온 표(확정 5차 6번 제근) — 안내 글은 「못 붙은 줄」이 아니라
|
||||
# 내역·본표 비고(`KnownGaps.known_gap_note` ← `borrowed_unit_note`)로 뜸(2026-09-14).
|
||||
return True
|
||||
result.unmatched.append(
|
||||
UnmatchedRow(
|
||||
work_item_code=work_item_code,
|
||||
|
||||
@@ -107,6 +107,22 @@ def load_scoped_aliases() -> list[dict[str, str]]:
|
||||
return load_aliases("resource")
|
||||
|
||||
|
||||
def scoped_alias_entry(
|
||||
catalog: ResourceCatalog, name_cell: str, work_item_code: str
|
||||
) -> CatalogEntry | None:
|
||||
"""범위 별칭이 가리키는 **항목 그 자체**(코드로 곧장) — 없으면 `None`.
|
||||
|
||||
⚠ 이름만 돌려주면 규격이 조인 키인 기계(소형브레이커 공압식 넷)는 다시 「규격 미정」 으로
|
||||
흐려짐 — 별칭이 코드를 적었으면 그 코드가 곧 답(2026-09-14 · 9-19-3 소형브레이커).
|
||||
"""
|
||||
wanted = _normalize(name_cell)
|
||||
for row in catalog.scoped_aliases:
|
||||
if _normalize(row["from"]) != wanted or not in_scope(work_item_code, row["scope"]):
|
||||
continue
|
||||
return next((entry for entry in catalog.entries if entry.code == row["to"]), None)
|
||||
return None
|
||||
|
||||
|
||||
def apply_scoped_alias(catalog: ResourceCatalog, name_cell: str, work_item_code: str) -> str:
|
||||
"""범위 안이면 카탈로그 쪽 **이름**으로 바꾼다. 범위 밖이거나 대상 코드가 없으면 원문 그대로."""
|
||||
wanted = _normalize(name_cell)
|
||||
|
||||
@@ -11,6 +11,14 @@
|
||||
"pum_edition": "2026-01-01",
|
||||
"basis": "노임 표준 직종명은 「화약취급공」(노임 카탈로그 1016) — 품셈 9-5 표가 줄여 적음. 2026-09-13 사용자 위임 판정(브레인)"
|
||||
},
|
||||
{
|
||||
"axis": "resource",
|
||||
"from": "소형브레이커",
|
||||
"to": "5210-0010",
|
||||
"scope": "FP-09-19-03",
|
||||
"pum_edition": "2026-01-01",
|
||||
"basis": "9-19-3 비탈면 고르기(발파암) 표가 규격을 안 적음 — 그 값 「(2.45+3.05)/2/10㎡」 은 9-19-1 토사면 고르기 표(연암 2.45·보통암+경암 3.05)에서 왔고 9-19-1 [주]① 「소형브레이커는 1㎥/분」 → 소형브레이커(공압식) 1.0㎥/min(9-19-3 ← 9-19-1 표 ← [주]①, 값의 출처가 규격을 정함). 2026-09-14 브레인 승인"
|
||||
},
|
||||
{
|
||||
"axis": "variant",
|
||||
"from": "리핑암",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"schema_version": "1.0",
|
||||
"dataset_id": "data_work_item_master_manifest",
|
||||
"generated_at": "2026-09-13T23:03:27+09:00",
|
||||
"generated_at": "2026-09-14T13:07:44+09:00",
|
||||
"built_by": "B08_Quantity/B08_Quantity_Build_WorkItemMaster.py",
|
||||
"source": {
|
||||
"dataset_id": "pum_forest",
|
||||
@@ -12,13 +12,13 @@
|
||||
"files": [
|
||||
{
|
||||
"file": "work_item_master_2026-01-01.json",
|
||||
"sha256": "1463ea14ec2d3d45ec18b3a7e4810333de8e5fc40aaeb0dd329c68f85c863e33",
|
||||
"size_bytes": 835659
|
||||
"sha256": "83efe531a6956f15696a4042dde1e13f37e25b26597e128b946d3f051b600fb6",
|
||||
"size_bytes": 837285
|
||||
},
|
||||
{
|
||||
"file": "form_undetermined_2026-01-01.json",
|
||||
"sha256": "c835699596bf57ffbda9f72a773a72116ebe48c2a2f79ae232ba5784ec9842c7",
|
||||
"size_bytes": 6447
|
||||
"sha256": "6b3476810ddee395856b997fa524a0410a5001fe47511b989c1db2feb82dccd2",
|
||||
"size_bytes": 6789
|
||||
},
|
||||
{
|
||||
"file": "basis_missing_2026-01-01.json",
|
||||
|
||||
@@ -139,7 +139,7 @@
|
||||
},
|
||||
{
|
||||
"pum_table_id": "F0248",
|
||||
"section": "8-2-13 대형브레이커(2025)」, 「건설공사 표준품셈 공통부문, 1-2-3 토질. 3. 체적환산계수적용(2025)」 참조",
|
||||
"section": "9-7-1. T=30㎝ 미만",
|
||||
"headers": [
|
||||
"구 분",
|
||||
"적 용"
|
||||
@@ -156,6 +156,31 @@
|
||||
],
|
||||
"reason": "헤더·첫 행에 단위·밑수·직종 표지 없음"
|
||||
},
|
||||
{
|
||||
"pum_table_id": "F0257",
|
||||
"section": "9-11-1. 콘크리트(기계)",
|
||||
"headers": [
|
||||
"구 분",
|
||||
"단 위",
|
||||
"적 용",
|
||||
"비 고"
|
||||
],
|
||||
"first_rows": [
|
||||
[
|
||||
"거리(L)",
|
||||
"km",
|
||||
"0.1",
|
||||
"N=(V×T)/(120×L+V.t)= 회/일 Q = N×q = ℓ/일"
|
||||
],
|
||||
[
|
||||
"운반속도(V)",
|
||||
"km/hr",
|
||||
"2.5",
|
||||
""
|
||||
]
|
||||
],
|
||||
"reason": "헤더·첫 행에 단위·밑수·직종 표지 없음"
|
||||
},
|
||||
{
|
||||
"pum_table_id": "F0304",
|
||||
"section": "10-6-3. 기타 임업자재",
|
||||
@@ -348,7 +373,7 @@
|
||||
},
|
||||
{
|
||||
"pum_table_id": "F0356",
|
||||
"section": "12-2 표면 마무리를 따른다.",
|
||||
"section": "12-17-1. 펌프카 타설",
|
||||
"headers": [
|
||||
"슬 럼 프",
|
||||
"기준 시공량"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -46,6 +46,7 @@ def test_칸을_채우면_치즐_못_붙은_줄이_풀린다() -> None:
|
||||
"FP-09-04-01": [left["FP-09-04-01"][0]]
|
||||
}
|
||||
assert "평균" in left["FP-09-04-01"][0]
|
||||
assert "9-12-3" in left["FP-09-04-01"][0] and "0.018" in left["FP-09-04-01"][0] # 선례
|
||||
whole = [code for code in CHISEL_ITEMS if not filled.unattached.get(code)]
|
||||
assert len(whole) >= 12, (
|
||||
whole
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
"""표 읽기 ②(2026-09-14 · PLAN 1장) — 「못 붙은 줄」 로 잘못 서던 자리를 **상태가 움직이는지**로 잼.
|
||||
|
||||
9-21 제근 고르기형 표 안내 글이 `unmatched` 에 들어가 못 붙은 줄로 섬 — 밑수는 사용자 확정
|
||||
(건설품셈 1,000㎡당 빌림)이라 안내는 비고(`known_gap_note`)로 옮김(사유는 안 사라짐)
|
||||
12-2 표면 마무리 원본이 12-17-1 [주] 문장을 절 제목으로 읽어 표 7장·가짜 갈래 #설치·#철거 가 붙음
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from B09_Estimation.B09_Estimation_KnownGaps import known_gap_note
|
||||
from B09_Estimation.B09_Estimation_ResourceAxis import load_work_item_master
|
||||
from B09_Estimation.B09_Estimation_UnitPrice import cached_build
|
||||
|
||||
|
||||
def test_제근은_못_붙은_줄이_아니고_교차참조_사유는_비고에_남음() -> None:
|
||||
build = cached_build()
|
||||
assert not build.unattached.get("FP-09-21"), build.unattached.get("FP-09-21")
|
||||
assert sum(1 for code in build.book.titles if code.startswith("B-FP-09-21#")) == 6
|
||||
note = known_gap_note("FP-09-21")
|
||||
assert "교차 참조" in note and "1,000㎡당" in note
|
||||
|
||||
|
||||
def test_표면_마무리엔_미장공_표만_있고_가짜_갈래가_없음() -> None:
|
||||
nodes = {n["work_item_code"]: n for n in load_work_item_master()["work_items"]}
|
||||
assert [t["pum_table_id"] for t in nodes["FP-12-02"]["tables"]] == ["F0334"]
|
||||
assert "F0356" in [t["pum_table_id"] for t in nodes["FP-12-17-01"]["tables"]]
|
||||
build = cached_build()
|
||||
assert [c for c in build.book.titles if c.startswith("B-FP-12-02")] == ["B-FP-12-02"]
|
||||
assert not build.unattached.get("FP-12-02")
|
||||
|
||||
|
||||
def test_육상_발파암_1_3m_들어내기는_0_1m_로_읽고_고른_값_버린_값을_사유에() -> None:
|
||||
"""③ 원문 「육상 발파암(1~2m)와 동일」(고시 5189·5201줄)은 9-13-14 자기 참조 — 같은 절 암절취·
|
||||
용수 발파암이 모두 「(0~1m)와 동일」 이라 0~1m(9-13-13)로 읽음(2026-09-14 브레인 승인)."""
|
||||
build = cached_build()
|
||||
for code in ("FP-09-13-14", "FP-09-13-15"):
|
||||
assert code not in build.partial_ratio and code not in build.component_gaps, code
|
||||
# 들어내기 참조 줄은 풀림 — 남는 것은 치즐뿐(기본 조립엔 치즐 단가가 없어 종전대로)
|
||||
left = [label for label in build.unattached.get(code, []) if "치즐" not in label]
|
||||
assert not left, left
|
||||
source = build.factor_sources.get(code, "")
|
||||
assert "육상 발파암(0~1m)" in source and "자기 참조" in source, source
|
||||
|
||||
|
||||
def test_비탈면_고르기_발파암_소형브레이커는_1_0_규격으로_코드에_이어짐() -> None:
|
||||
"""④ 9-19-3 값 「(2.45+3.05)/2/10㎡」 ← 9-19-1 표 ← [주]① 「소형브레이커는 1㎥/분」 —
|
||||
값의 출처가 규격을 정함(2026-09-14 브레인 승인). 범위 별칭이 **코드로** 곧장 이음(이름만
|
||||
돌려주면 규격 후보 넷이 다시 흐려짐). 「어어호스」 는 원문 오기 + 카탈로그에 호스 없음."""
|
||||
from B09_Estimation.B09_Estimation_ResourceAxis import (
|
||||
build_resource_axis,
|
||||
load_combined_catalog,
|
||||
)
|
||||
|
||||
axis = build_resource_axis(load_work_item_master(), load_combined_catalog())
|
||||
rows = [
|
||||
(r.resource_code, str(r.amount)) for r in axis.rows if r.work_item_code == "FP-09-19-03"
|
||||
]
|
||||
assert ("5210-0010", "0.275") in rows, rows
|
||||
left = [u.cell for u in axis.unmatched if u.work_item_code == "FP-09-19-03"]
|
||||
assert left == ["어어호스(3/4인치)"], left
|
||||
|
||||
|
||||
def test_토사면_고르기는_두_표가_섞여_값이_불완전하다고_먼저_말함() -> None:
|
||||
"""⑤ 사유 먼저(2026-09-14 브레인) — 원문은 절토면·성토면 두 표인데 지금은 섞여 보통인부 한 줄만
|
||||
섬(조용히 틀린 값). 표 모양 본작업 전에 누가 그 값을 믿고 쓰지 않게 비고·본표에 뜸."""
|
||||
from B09_Estimation.B09_Estimation_UnitPrice import detail_of
|
||||
|
||||
note = known_gap_note("FP-09-19-01")
|
||||
assert "절토면" in note and "성토면" in note and "불완전" in note
|
||||
assert "불완전" in detail_of(cached_build(), "B-FP-09-19-01")["known_gap_note"]
|
||||
Reference in New Issue
Block a user