From 385f5c303d1626712bd034de73473b4443b056e6 Mon Sep 17 00:00:00 2001 From: umsangdon Date: Tue, 8 Sep 2026 14:18:06 +0900 Subject: [PATCH] =?UTF-8?q?fix(B08):=20=EC=94=A8=EC=95=97=EB=BF=9C?= =?UTF-8?q?=EC=96=B4=EB=B6=99=EC=9D=B4=EA=B8=B0=20=EB=B0=91=EC=88=98=20?= =?UTF-8?q?=E3=8E=A1=20=EC=B6=94=EA=B0=80=20+=20=EC=8B=9C=EA=B3=B5?= =?UTF-8?q?=EB=9F=89=20=EB=AA=A8=EC=96=91=EC=9D=84=20=EB=B0=91=EC=88=98?= =?UTF-8?q?=EB=A1=9C=20=EC=95=88=20=EB=B0=9B=EA=B2=8C=20=EB=A7=89=EC=9D=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ⚠ 아홉 중 여덟째 — FP-05-24 는 원문 L2769·L2794 절 머리 아래 「(㎡당)」인데 「단위:」 글자 없이 **괄호만** 있어 마스터가 못 읽던 자리(원문 열어 확인). ⚠ 그리고 매핑 밑수 칸은 **사람이 손으로 적는 자리**라, 품셈에 섞여 있는 「(㎥/1대, 1일)」 같은 **시공량**을 적을 수 있음 — 그것은 밑수의 **역수**라 받으면 그 공종이 조용히 뒤집힌 단위를 가짐. `is_quantity_unit()` 으로 좁게 막음 (나눗셈·쉼표가 있거나 「일당·조·인」이면 안 받음). 애매하면 안 받는 쪽 — 안 받으면 대조가 없을 뿐이고, 잘못 받으면 틀린 단위로 검사를 통과시킴. 시험 741 통과 (B05 코리도 1건 기존 깨짐, 무관). Co-Authored-By: Claude Opus 5 (1M context) --- .../B08_Quantity_Engine_Handoff_Mapping.py | 22 ++++++++++++++++++- .../work_item_mapping_2026-01-01.json | 4 +++- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/B08_Quantity/B08_Quantity_Engine_Handoff_Mapping.py b/B08_Quantity/B08_Quantity_Engine_Handoff_Mapping.py index 7bdc944e..19f2c66c 100644 --- a/B08_Quantity/B08_Quantity_Engine_Handoff_Mapping.py +++ b/B08_Quantity/B08_Quantity_Engine_Handoff_Mapping.py @@ -148,6 +148,26 @@ def _latest_dataset_path(directory: Path | None = None) -> Path | None: return files[-1] if files else None +#: ⚠ **공종 수량 단위가 아닌 것** — 품셈 절 머리에 섞여 있는 모양들이다(2026-09-08 B09 전수). +#: `(㎥/1대, 1일)` 는 **시공량**이라 「1대가 하루에 몇 ㎥」이고, 밑수(「1㎥ 에 얼마」)의 +#: **역수**다. 그대로 밑수로 받으면 그 공종이 조용히 뒤집힌 단위를 갖는다. +#: `(일당)`·`(조)`·`(인)` 은 **품의 단위**이지 공종 단위가 아니다. +NON_QUANTITY_UNITS = frozenset({"일당", "조", "인", "일", "대", "인당"}) + + +def is_quantity_unit(unit: str) -> bool: + """그 글자가 **공종 수량의 밑수 단위**로 쓸 수 있는가. + + ⚠ **좁게 본다** — 애매하면 안 받는다. 안 받으면 대조가 없을 뿐이고, 잘못 받으면 + **틀린 단위로 검사를 통과시킨다**(그쪽이 더 나쁘다). + """ + text = str(unit or "").strip() + if not text or text in NON_QUANTITY_UNITS: + return False + # 「㎥/1대, 1일」처럼 나눗셈·쉼표가 있으면 시공량이거나 밑수가 둘이다. + return "/" not in text and "," not in text + + @dataclass class WorkItemMapping: """수량 줄 → 공종 마스터 코드. 못 찾으면 `None` 을 돌려주고 부른 쪽이 목록에 남긴다.""" @@ -173,7 +193,7 @@ class WorkItemMapping: found: dict[str, str] = {} for row in (*self.earthwork, *self.haul, *self.structure): code, unit = row.get("work_item_code"), row.get("basis_unit") - if code and unit: + if code and unit and is_quantity_unit(str(unit)): found[str(code)] = str(unit) return found diff --git a/resources/data_work_item_mapping/work_item_mapping_2026-01-01.json b/resources/data_work_item_mapping/work_item_mapping_2026-01-01.json index bba043fc..61f3a127 100644 --- a/resources/data_work_item_mapping/work_item_mapping_2026-01-01.json +++ b/resources/data_work_item_mapping/work_item_mapping_2026-01-01.json @@ -101,7 +101,9 @@ { "group": "초류종자살포", "work_item_code": "FP-05-24", - "master_name": "씨앗뿜어붙이기" + "master_name": "씨앗뿜어붙이기", + "basis_unit": "㎡", + "basis_source": "산림사업 표준품셈(고시 2025-82) 원문 L2769·L2794 — 5-24-1·5-24-2 절 머리 바로 아래 「(㎡당)」. ⚠ 「단위:」 글자 없이 **괄호만** 적힌 모양이라 마스터가 못 읽은 자리(2026-09-08 원문 대조)." }, { "group": "되메우기",