knowledge(마스터): 엔산법 등급 적용 · 상태 「추정」 들임 — 미확보 28 → 9

- 기술사·특급~초급기술자·고급~초급숙련기술자·기계기사·기계산업기사 열 줄을 엔지니어링 현행 줄 옛이름으로 옮김(부문은 일반값 · 기계기사류는 기계·설비) · 로직 참조 326 곳 갈아 끼우고 호표에 「옛이름: ○○」
- 상태 「추정」 신설 — 구분은 대응 직종 것 · 값은 비움 · 준용에 대응 직종 키 · 호표 출처 「준용: ○○(추정)」 · M01 고르기에서 거름
- 추정 아홉 — 제관공·마킹공·현도공·산소절단공 → 플랜트제관공 · 제도공 → CAD설계사(기계) · 공작기계공 → 선반기조작원 · 옵셋인쇄공 → 종이및합성수지인쇄기계조작원 · 정보처리기사 → 초급기술자(정보통신) · 시험사1급 → 비파괴시험공
- 원문이 대응을 정하지 않은 아홉(절단공 · 사진제판공 · 사진식자공 · 측량조수 · 시공측량조수 · 시공측량기사 · 측량기사 · 측량사 · 특수운전공)은 미확보 그대로

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JgUhN55Z3BCYhUJTjwTNfj
This commit is contained in:
2026-09-20 19:29:47 +09:00
co-authored by Claude Opus 5
parent 76ee8acb4b
commit a367f2afe1
18 changed files with 1027 additions and 802 deletions
+20 -11
View File
@@ -390,7 +390,7 @@ def test_자체_직종으로_세운_절(faked):
# 3-11-1 조립 1일 + 해체 1일 — 인 × 2
got = qty("GC000132", {}) # 공통 3-11-1 머신 가이던스(MG) 굴착기 장비조립・해체
assert [got[w] for w in ("고급기술자", "중급기술자", "용접공")] == [2, 2, 2]
assert [got[w] for w in ("고급기술자(건설)", "중급기술자(건설)", "용접공")] == [2, 2, 2]
# 5-1-3 주① 제작도 — 박스거더 0.4인/톤 × 본체 보정계수 1.31
given = {
"형식": "박스거더",
@@ -405,7 +405,7 @@ def test_자체_직종으로_세운_절(faked):
"제작도": "이 품에 포함",
}
# 토목 5-1-1 기본제작공수
assert qty("GC000373", given)["중급숙련기술자"] == Decimal("0.4") * Decimal("1.31")
assert qty("GC000373", given)["중급숙련기술자(건설)"] == Decimal("0.4") * Decimal("1.31")
def test_토목_배송관_철거_크레인_규격(whole):
@@ -437,7 +437,7 @@ def test_토목_보링_심도_가산():
given = {"층": "점토층", "규격": "BX", "깊이": 35, "심도가산율": 5}
got = mf.run(mf.Master(files), "GC000431", given)
qty = {x["이름"]: x["수량"] for x in got["줄"]}
assert qty["중급기술자"] == Decimal("0.16") * Decimal("1.1")
assert qty["중급기술자(건설)"] == Decimal("0.16") * Decimal("1.1")
assert qty["싱글코아바렐"] == Decimal("0.01")
assert qty["쵸핑비트"] == 0
@@ -451,7 +451,8 @@ def test_토목_측량_계산예():
master = mf.Master(files)
given = {"구하는점": 6, "주어진점": 4, "지형": "산지"}
got = {x["이름"]: x["수량"] for x in mf.run(master, "GC000453", given)["줄"]}
assert [round(got[w], 2) for w in ("특급기술자", "고급기술자", "중급기술자", "인부")] == [
names = ("특급기술자(건설)", "고급기술자(건설)", "중급기술자(건설)", "인부")
assert [round(got[w], 2) for w in names] == [
Decimal("2.52"),
Decimal("20.58"),
Decimal("33.60"),
@@ -459,7 +460,7 @@ def test_토목_측량_계산예():
]
given = {"도로연장": 10, "지형": "그 외 지역"}
got = {x["이름"]: x["수량"] for x in mf.run(master, "GC000482", given)["줄"]}
assert got["특급기술자"] == 17 and got["중급기술자"] == 198
assert got["특급기술자(건설)"] == 17 and got["중급기술자(건설)"] == 198
def test_범위_입력은_막음(whole):
@@ -611,8 +612,8 @@ def test_미공표_준용():
got = mf.run(mf.Master(files), "GX999999", {})
assert got["줄"][0]["출처"] == "준용: 보통인부"
assert got["노무비"] == 2 * Decimal(172068)
lines[0]["요소"] = "LB:기술사" # 공표 노임에 없는 직종(미확보) — 준용을 골라야 값이 섬
alias = mf.Master(files).get("LB:기술사")
lines[0]["요소"] = "LB:절단공" # 공표 노임에 없는 직종(미확보) — 준용을 골라야 값이 섬
alias = mf.Master(files).get("LB:절단공")
assert alias["값"] is None and alias["준용"] is None and alias["구분"] == "미확보"
with pytest.raises(mf.FormulaError):
mf.run(mf.Master(files), "GX999999", {})
@@ -624,6 +625,14 @@ def test_미공표_준용():
assert mf.Master(files).get("LB:1003")["옛이름"] == ["갱부"]
def test_추정은_준용_값에_표시(whole):
"""추정 = 원문이 이름을 맞대지 않아 작업 범위로 짐작한 대응 — 값은 비우고 준용 직종 값 · 출처에 「(추정)」."""
row = whole.get("LB:제관공")
assert row["상태"] == "추정" and row["값"] is None and row["구분"] == "건설업"
assert row["비고"].startswith("추정: ") and row["옛이름"] == []
assert whole.value("LB:제관공") == (whole.get("LB:1057")["값"], "준용: 플랜트제관공(추정)")
def test_노임_갈래_파일_원문_대조():
"""인력 한 테이블 — 구분별 줄 수 · 이름 표본 · 열 한 벌 · 상세구분 · 일시간."""
files = cm.load()
@@ -631,14 +640,14 @@ def test_노임_갈래_파일_원문_대조():
rows = data["줄"]
count = {b: sum(r["구분"] == b for r in rows) for b in data["구분"]}
assert count == {
"건설업": 132,
"제조업": 129,
"엔지니어링": 56,
"건설업": 137, # 추정 5 = 제관공·마킹공·현도공·산소절단공·시험사1급
"제조업": 132, # 추정 3 = 제도공·공작기계공·옵셋인쇄공
"엔지니어링": 57, # 추정 1 = 정보처리기사
"측량": 20,
"건설사업관리": 4,
"SW": 17,
"산림": 2,
"미확보": 28, # 고급기능사·리베팅공·Belt Conveyor 설치공은 적용해 뺌
"미확보": 9, # 원문이 대응을 정하지 않은 직종만 남김
}
assert {tuple(r) for r in rows} == {cm.LABOR_COLS}
# 「미공표」 는 남지 않음 — 건설·제조 미공표 직종은 모두 「산정」(원 미만 버림)