diff --git a/M02_MasterTemplete/M02_Machine_Hourly.py b/M02_MasterTemplete/M02_Machine_Hourly.py index 0e4fb4952..f7b76b2cf 100644 --- a/M02_MasterTemplete/M02_Machine_Hourly.py +++ b/M02_MasterTemplete/M02_Machine_Hourly.py @@ -136,8 +136,6 @@ def why(row: dict, logic: dict | None) -> str: return f"주연료 「{vals['주연료']}」 — 수 아님" if float(vals.get("조종원") or 0) > 0 and not vals.get("조종원직종"): return "조종원직종 없음" - if vals.get("주연료") and vals.get("전력"): - return "주연료 · 전력 둘 다 — 식 없음" return "손료 계수 셋(상각 · 정비 · 관리) 없음" text = " ".join(str(x.get(k)) for k in ("식", "수량") for p in ("중간", "호표", "덧줄") for x in logic.get(p) or []) # fmt: skip diff --git a/M02_MasterTemplete/M02_MyMachine.py b/M02_MasterTemplete/M02_MyMachine.py index af0326b21..1187be642 100644 --- a/M02_MasterTemplete/M02_MyMachine.py +++ b/M02_MasterTemplete/M02_MyMachine.py @@ -12,6 +12,7 @@ 이 색인을 읽음 — 층을 모르는 길(`/api/m02/logic-lib/machine-hourly` 등)은 M01 만. 식 고름(채운 칸 · `logic_key` — M01 기계 목록 밖 줄도 같은 규칙 · 822-2) = 연료 + 조종원 GC000268(직종 없음 GC000275) · 연료만 GC000272(손료계수 한 칸 GC001198) · 조종원만 GC000276 · 전력 GC001196(+ 조종원 GC001197) · +연료 + 전력 GC001200(+ 조종원 GC001201 · 822-2b 경쟁사 기계) · 없음 GC000273 · 직접 GC001199(시간당 값 = 셈 꼴 값 칸 노무비 · 재료비 · 경비). 권한(본인 개인 층 · 맡은 회사 관리자)은 길(`M02_MyMachine_Router`) 몫. """ @@ -46,6 +47,7 @@ LOGIC = {(True, True): "GC000268", (True, False): "GC000272", (False, True): "GC000276", (False, False): "GC000273"} # fmt: skip JOB_IN, ONE_FUEL = "GC000275", "GC001198" # 직종 입력 · 손료계수 한 칸 연료 POWER, POWER_CREW, DIRECT_KEY = "GC001196", "GC001197", "GC001199" +FUEL_POWER, FUEL_POWER_CREW = "GC001200", "GC001201" # 연료 + 전력(+ 조종원) — 경쟁사 구성(822-2b) def mine(key: Any) -> bool: @@ -136,7 +138,7 @@ def _pos(v: Any) -> bool: def logic_key(row: dict) -> str | None: - """꼴(채운 칸) → 시간당 경비 식 키 · 못 고름(직종 없는 조종원만 · 연료 + 전력 · 수 아닌 연료 글) = None · + """꼴(채운 칸) → 시간당 경비 식 키 · 못 고름(직종 없는 조종원 · 수 아닌 연료 글) = None · 계수 셋(상각 · 정비 · 관리) 없음 = 손료계수 한 칸 식(연료만) · 그 밖은 그 식 + 모자란 칸 까닭.""" if row.get("방식") == DIRECT: return DIRECT_KEY @@ -144,8 +146,10 @@ def logic_key(row: dict) -> str | None: fuel, crew, power = (_pos(vals.get(k)) for k in ("주연료", "조종원", "전력")) job = bool(vals.get("조종원직종")) three = all(vals.get(k) is not None for k in COEFS) - if vals.get("주연료") not in (None, "", 0) and not fuel or fuel and power: + if vals.get("주연료") not in (None, "", 0) and not fuel: return None + if fuel and power: + return FUEL_POWER_CREW if crew and job else None if crew else FUEL_POWER if power: return POWER_CREW if crew and job else None if crew else POWER if fuel and not crew: @@ -181,7 +185,7 @@ def hourly(row: dict, index: Any) -> dict[str, Any]: mf = m01.cm.mf key = logic_key(row) if key is None: - return {"ok": False, **head, "reason": "식 없음 — 연료 · 전력은 하나만"} + return {"ok": False, **head, "reason": "식 없음 — 조종원직종 없음"} logic = index.logic(key) given = {i["이름"]: (i.get("고르기") or [""])[0] for i in logic.get("입력") or []} given["기계"] = str(row.get("원문번호")) @@ -239,8 +243,6 @@ def clean(raw: Any) -> dict[str, Any]: need = ("가격", "손료계수") if how == EASY else ("가격", *RATIOS) if lost := [k for k in need if not vals.get(k)]: raise _bad(f"빈 칸 — {' · '.join(lost)}") - if vals.get("주연료") and vals.get("전력"): - raise _bad("주연료 · 전력은 하나만(원문 운전경비 표 한 칸)") drop = (*RATIOS, *COEFS) if how == EASY else () vals = {k: v for k, v in vals.items() if k not in drop} if how == BOOK: diff --git a/docs/raw/요구_1104/_목록_802-2_변환대조.xlsx b/docs/raw/요구_1104/_목록_802-2_변환대조.xlsx index ada56c156..49ffa570f 100644 Binary files a/docs/raw/요구_1104/_목록_802-2_변환대조.xlsx and b/docs/raw/요구_1104/_목록_802-2_변환대조.xlsx differ diff --git a/resources/master_data/_키대장.json b/resources/master_data/_키대장.json index 1d30cd486..ca4e86c1a 100644 --- a/resources/master_data/_키대장.json +++ b/resources/master_data/_키대장.json @@ -1,5 +1,5 @@ { - "다음": {"LB": 409, "EQ": 669, "RT": 20, "MN": 7000, "MT": 30719, "MO": 74, "MP": 364, "FX": 6, "CF": 159, "QF": 477, "GF": 338, "CC": 528, "GC": 1200, "QC": 2060, "GX": 5, "UA": 38}, + "다음": {"LB": 409, "EQ": 669, "RT": 20, "MN": 7000, "MT": 30719, "MO": 74, "MP": 364, "FX": 6, "CF": 159, "QF": 477, "GF": 338, "CC": 528, "GC": 1202, "QC": 2060, "GX": 5, "UA": 38}, "폐기": {"MT000001": "자재품목 휘발유 — 값이 비고 글뿐 · 유가 테이블로 감", "MT000002": "자재품목 경유 — 값이 비고 글뿐 · 유가 테이블로 감", "MT000003": "자재품목 선박용경유 — 값이 비고 글뿐 · 유가 테이블로 감", "MT000004": "자재품목 중유 — 값이 비고 글뿐 · 유가 테이블로 감", "MT000005": "자재품목 등유 — 값이 비고 글뿐 · 유가 테이블로 감", "LB000399": "이름 「〃」 — 직종이 아니라 되풀이 기호 · 소요량 13-6-9 에서 윗줄 직종으로 바로잡음", "MN": "재료_나라장터자재 — old 로 옮김 · 로직은 자재품목·품셈재료로 갈아 끼움", "LB000372": "미확보 고급기능사 — 측량노임 항공사진고급기능사 옛이름으로 옮김", "LB000393": "미확보 리베팅공 — 건설노임 철골공 옛이름으로 옮김(2010 통합표 연번10)", "LB000405": "미확보 Belt Conveyor 설치공 — 품셈 13-10-1 주② 배분으로 다섯 직종에 나눔", "MT000006": "자재품목 전력 — 재료_유가전력 전력 줄로 감", "MT000007": "자재품목 전력 — 재료_유가전력 전력 줄로 감", "LB000368": "미확보 기술사 — 기술사(건설) 옛이름으로 옮김", "LB000369": "미확보 특급기술자 — 특급기술자(건설) 옛이름으로 옮김", "LB000370": "미확보 고급기술자 — 고급기술자(건설) 옛이름으로 옮김", "LB000361": "미확보 중급기술자 — 중급기술자(건설) 옛이름으로 옮김", "LB000364": "미확보 초급기술자 — 초급기술자(건설) 옛이름으로 옮김", "LB000365": "미확보 고급숙련기술자 — 고급숙련기술자(건설) 옛이름으로 옮김", "LB000366": "미확보 중급숙련기술자 — 중급숙련기술자(건설) 옛이름으로 옮김", "LB000367": "미확보 초급숙련기술자 — 초급숙련기술자(건설) 옛이름으로 옮김", "LB000389": "미확보 기계기사 — 초급기술자(기계·설비) 옛이름으로 옮김", "LB000388": "미확보 기계산업기사 — 초급숙련기술자(기계·설비) 옛이름으로 옮김", "MO000055": {"원문번호": "주택용저압:기본_200이하", "파일": "재료_유가전력.json"}, "MO000056": {"원문번호": "주택용저압:기본_201~400", "파일": "재료_유가전력.json"}, "MO000057": {"원문번호": "주택용저압:기본_400초과", "파일": "재료_유가전력.json"}, "MO000059": {"원문번호": "주택용저압:전력량_다음200", "파일": "재료_유가전력.json"}, "MO000060": {"원문번호": "주택용저압:전력량_400초과", "파일": "재료_유가전력.json"}, "MO000061": {"원문번호": "주택용저압:월간최저요금", "파일": "재료_유가전력.json"}, "MO000062": {"원문번호": "일반용갑I저압:기본", "파일": "재료_유가전력.json"}, "MO000063": {"원문번호": "일반용갑I저압:전력량_여름철", "파일": "재료_유가전력.json"}, "MO000064": {"원문번호": "일반용갑I저압:전력량_봄가을철", "파일": "재료_유가전력.json"}, "MO000065": {"원문번호": "일반용갑I저압:전력량_겨울철", "파일": "재료_유가전력.json"}, "MO000066": {"원문번호": "산업용갑I저압:기본", "파일": "재료_유가전력.json"}, "MO000067": {"원문번호": "산업용갑I저압:전력량_여름철", "파일": "재료_유가전력.json"}, "MO000068": {"원문번호": "산업용갑I저압:전력량_봄가을철", "파일": "재료_유가전력.json"}, "MO000069": {"원문번호": "산업용갑I저압:전력량_겨울철", "파일": "재료_유가전력.json"}, "MO000070": {"원문번호": "임시전력갑:기본요금적용", "파일": "재료_유가전력.json"}, "MO000071": {"원문번호": "임시전력갑:전력량요금적용", "파일": "재료_유가전력.json"}, "MO000072": {"원문번호": "임시전력갑:월간최저요금", "파일": "재료_유가전력.json"}, "GC001145": "작업량당 기계경비 — 부르는 곳 0 · 필요하면 단가산출에 기계 하나 넣어 만듦(요구 734-4 · 735-4 · 813-2)", "GC001148": "작업량당 기계경비 — 부르는 곳 0 · 필요하면 단가산출에 기계 하나 넣어 만듦(요구 734-4 · 735-4 · 813-2)", "GC001151": "작업량당 기계경비 — 부르는 곳 0 · 필요하면 단가산출에 기계 하나 넣어 만듦(요구 734-4 · 735-4 · 813-2)", "GC001156": "작업량당 기계경비 — 부르는 곳 0 · 필요하면 단가산출에 기계 하나 넣어 만듦(요구 734-4 · 735-4 · 813-2)", "GC001159": "작업량당 기계경비 — 부르는 곳 0 · 필요하면 단가산출에 기계 하나 넣어 만듦(요구 734-4 · 735-4 · 813-2)", "GC001166": "작업량당 기계경비 — 부르는 곳 0 · 필요하면 단가산출에 기계 하나 넣어 만듦(요구 734-4 · 735-4 · 813-2)", "EQ000656": "자체 발전기 5.5㎾ — 품셈에 없는 기계 = 사용자 내 기계(요구서 796 · 821-4) · 결번", "EQ000657": "자체 발전기 7㎾ — 품셈에 없는 기계 = 사용자 내 기계(요구서 796 · 821-4) · 결번", "EQ000658": "자체 발전기 10㎾ — 품셈에 없는 기계 = 사용자 내 기계(요구서 796 · 821-4) · 결번", "EQ000659": "자체 대형 브레이커 0.18㎥ — 품셈에 없는 기계 = 사용자 내 기계(요구서 796 · 821-4) · 결번", "EQ000660": "자체 에어 호스 1.91㎝ — 품셈에 없는 기계 = 사용자 내 기계(요구서 796 · 821-4) · 결번", "EQ000661": "자체 모노펌프 5-20㎥/hr — 품셈에 없는 기계 = 사용자 내 기계(요구서 796 · 821-4) · 결번", "EQ000662": "자체 파워트로웰 3.73㎾ — 품셈에 없는 기계 = 사용자 내 기계(요구서 796 · 821-4) · 결번", "EQ000663": "자체 콘크리트펌프용 파이프 150㎜×1m — 품셈에 없는 기계 = 사용자 내 기계(요구서 796 · 821-4) · 결번", "EQ000664": "자체 콘크리트펌프용 파이프 150㎜×2m — 품셈에 없는 기계 = 사용자 내 기계(요구서 796 · 821-4) · 결번", "EQ000665": "자체 콘크리트펌프용 파이프 150㎜×3m — 품셈에 없는 기계 = 사용자 내 기계(요구서 796 · 821-4) · 결번", "EQ000666": "자체 콘크리트펌프용 파이프 곡관 150㎜ 45° — 품셈에 없는 기계 = 사용자 내 기계(요구서 796 · 821-4) · 결번", "EQ000667": "자체 콘크리트펌프용 파이프 곡관 150㎜ 60° — 품셈에 없는 기계 = 사용자 내 기계(요구서 796 · 821-4) · 결번", "EQ000668": "자체 콘크리트펌프용 파이프 곡관 150㎜ 90° — 품셈에 없는 기계 = 사용자 내 기계(요구서 796 · 821-4) · 결번", "GC001195": "공통 8 파워트로웰 시간당 경비 — 품셈에 없는 기계 = 사용자 내 기계(요구서 796 · 821-4) · 결번"}, "키": { "CC000001": {"원문번호": "공통 1-3-1 콘크리트 및 포장용 재료", "파일": "계수_건설품셈_01장_적용기준.json"}, @@ -2539,6 +2539,8 @@ "GC001197": {"원문번호": "공통 8 기계 시간당 경비(전력 조종원)", "파일": "로직_건설품셈_08장_건설기계.json"}, "GC001198": {"원문번호": "공통 8 기계 시간당 경비(손료계수 한 칸)", "파일": "로직_건설품셈_08장_건설기계.json"}, "GC001199": {"원문번호": "공통 8 기계 시간당 경비(직접 값)", "파일": "로직_건설품셈_08장_건설기계.json"}, + "GC001200": {"원문번호": "공통 8 기계 시간당 경비(연료 전력)", "파일": "로직_건설품셈_08장_건설기계.json"}, + "GC001201": {"원문번호": "공통 8 기계 시간당 경비(연료 전력 조종원)", "파일": "로직_건설품셈_08장_건설기계.json"}, "GF000001": {"원문번호": "3-1 경계표시", "파일": "로직_산림품셈_03장_작업장_관리.json"}, "GF000002": {"원문번호": "3-3 작업로 설치", "파일": "로직_산림품셈_03장_작업장_관리.json"}, "GF000003": {"원문번호": "3-4-2 임산물 운반로 신설 작업량", "파일": "로직_산림품셈_03장_작업장_관리.json"}, diff --git a/resources/master_data/로직_건설품셈_08장_건설기계.json b/resources/master_data/로직_건설품셈_08장_건설기계.json index abb927060..ffa3f53be 100644 --- a/resources/master_data/로직_건설품셈_08장_건설기계.json +++ b/resources/master_data/로직_건설품셈_08장_건설기계.json @@ -3599,6 +3599,114 @@ ], "끝수": null, "변수표": { "기계": { "기호": "S", "아래": "기계" } } + }, + { + "키": "GC001200", + "원문번호": "8", + "구분": "건설품셈 공통", + "상세구분": "08장 건설기계", + "결과단위": "원/시간", + "출처": "건설품셈 공통 8-1-5 · 8-1-6 · 8-1-6 3 가", + "부품": { "갈래": "기계경비식" }, + "소유": "공용", + "이름": "기계 시간당 기계경비(연료 · 전력 기종)", + "비고": "자체 — 주연료와 전력이 둘 다 있는 기계(경쟁사 불러오기 내 기계 · 파워트로웰 등) — 주연료비 + 전력비 + 잡재료((주연료비 + 전력비)의 %)", + "입력": [ + { "이름": "기계", "고르기": [] }, + { + "이름": "지역", + "고르기": ["전국평균", "전국", "서울", "경기", "강원", "충북", "충남", "전북", "경북", "경남", "부산", "제주", "대구", "인천", "대전", "울산", "세종", "전남광주"], + "출처": "건설품셈 공통 8-1-7 5" + }, + { "이름": "전력 계약종별", "고르기": ["일반용(갑)Ⅰ 저압", "주택용 저압"], "출처": "유가전력 한전 전기요금표 2025-01-01", "비고": "품셈·계약예규에 계약종별 규정 없음(전력비는 실비 계상) — 기본 = 불러오기 기본값" } + ], + "중간": [ + { "이름": "손료", "식": "버림(EQ:{기계}.가격 * 1000 * EQ:{기계}.손료계수 / 10000000, 0)", "출처": "건설품셈 공통 8-1-5 12 · 8-1-6 4" }, + { "이름": "연료", "식": "EQ:{기계}.주연료종류", "출처": "건설품셈 공통 8-4 주①㉰" } + ], + "호표": [ + { "종류": "재료", "요소": "MO:{연료}:{지역}", "이름": "주연료", "단위": "ℓ", "수량": "EQ:{기계}.주연료", "비목": "재료비", "출처": "건설품셈 공통 8-4-8" }, + { + "종류": "재료", + "요소": { "이름": "전력량요금", "계약종별": "입력" }, + "이름": "전력", + "단위": "㎾h", + "수량": "EQ:{기계}.전력", + "비목": "재료비", + "출처": "건설품셈 공통 8-1-6 3 가", + "비고": "기계 줄 전력(㎾) 그대로 — 전동기 부하율 규정 없음" + } + ], + "덧줄": [{ "이름": "잡재료비", "식": "재료비 * EQ:{기계}.잡재료율 / 100", "비목": "재료비", "출처": "건설품셈 공통 8-4 주②" }, { "이름": "기계손료", "식": "손료", "비목": "경비", "출처": "건설품셈 공통 8-1-6 2" }], + "끝수": "손료 원 미만 버림(건설품셈 공통 8-1-5 12) · 합계 원문 규정 없음", + "변수표": { + "기계": { "기호": "S", "아래": "기계" }, + "지역": { "기호": "S", "아래": "지역" }, + "전력 계약종별": { "기호": "S", "아래": "전력계약종별" }, + "손료": { "기호": "C", "아래": "손료" }, + "연료": { "기호": "S", "아래": "연료" } + } + }, + { + "키": "GC001201", + "원문번호": "8", + "구분": "건설품셈 공통", + "상세구분": "08장 건설기계", + "결과단위": "원/시간", + "출처": "건설품셈 공통 8-1-5 · 8-1-6 · 8-1-6 3 가", + "부품": { "갈래": "기계경비식" }, + "소유": "공용", + "이름": "기계 시간당 기계경비(연료 · 전력 · 조종원 기종)", + "비고": "자체 — 주연료 · 전력 · 조종원이 다 있는 기계(경쟁사 불러오기 내 기계) — 주연료비 + 전력비 + 잡재료((주연료비 + 전력비)의 %) + 조종원", + "입력": [ + { "이름": "기계", "고르기": [] }, + { + "이름": "지역", + "고르기": ["전국평균", "전국", "서울", "경기", "강원", "충북", "충남", "전북", "경북", "경남", "부산", "제주", "대구", "인천", "대전", "울산", "세종", "전남광주"], + "출처": "건설품셈 공통 8-1-7 5" + }, + { "이름": "전력 계약종별", "고르기": ["일반용(갑)Ⅰ 저압", "주택용 저압"], "출처": "유가전력 한전 전기요금표 2025-01-01", "비고": "품셈·계약예규에 계약종별 규정 없음(전력비는 실비 계상) — 기본 = 불러오기 기본값" } + ], + "중간": [ + { "이름": "손료", "식": "버림(EQ:{기계}.가격 * 1000 * EQ:{기계}.손료계수 / 10000000, 0)", "출처": "건설품셈 공통 8-1-5 12 · 8-1-6 4" }, + { "이름": "연료", "식": "EQ:{기계}.주연료종류", "출처": "건설품셈 공통 8-4 주①㉰" }, + { "이름": "직종", "식": "EQ:{기계}.조종원직종", "출처": "건설품셈 공통 8-1-3 5" }, + { "이름": "시간환산", "식": "찾기(CC000336, 구분='시간환산').분자 / 찾기(CC000336, 구분='시간환산').분모", "출처": "건설품셈 공통 1-1-3 2(일일 작업시간 8시간)" } + ], + "호표": [ + { "종류": "재료", "요소": "MO:{연료}:{지역}", "이름": "주연료", "단위": "ℓ", "수량": "EQ:{기계}.주연료", "비목": "재료비", "출처": "건설품셈 공통 8-4-8" }, + { + "종류": "재료", + "요소": { "이름": "전력량요금", "계약종별": "입력" }, + "이름": "전력", + "단위": "㎾h", + "수량": "EQ:{기계}.전력", + "비목": "재료비", + "출처": "건설품셈 공통 8-1-6 3 가", + "비고": "기계 줄 전력(㎾) 그대로 — 전동기 부하율 규정 없음" + }, + { + "종류": "인력", + "요소": "LB:{직종}", + "이름": "조종원", + "단위": "인", + "수량": "EQ:{기계}.조종원 * 시간환산", + "비목": "노무비", + "출처": "건설품셈 공통 8-1-3 6", + "비고": "하루 노임 × 1/8(1일 8시간 · 건설품셈 공통 1-1-3 2)" + } + ], + "덧줄": [{ "이름": "잡재료비", "식": "재료비 * EQ:{기계}.잡재료율 / 100", "비목": "재료비", "출처": "건설품셈 공통 8-4 주②" }, { "이름": "기계손료", "식": "손료", "비목": "경비", "출처": "건설품셈 공통 8-1-6 2" }], + "끝수": "손료 원 미만 버림(건설품셈 공통 8-1-5 12) · 합계 원문 규정 없음", + "변수표": { + "기계": { "기호": "S", "아래": "기계" }, + "지역": { "기호": "S", "아래": "지역" }, + "전력 계약종별": { "기호": "S", "아래": "전력계약종별" }, + "손료": { "기호": "C", "아래": "손료" }, + "연료": { "기호": "S", "아래": "연료" }, + "직종": { "기호": "S", "아래": "직종" }, + "시간환산": { "기호": "Q", "아래": "시간환산" } + } } ] } diff --git a/resources/master_data/수식문서/수식_건설품셈_08장_건설기계.json b/resources/master_data/수식문서/수식_건설품셈_08장_건설기계.json index 59a932359..57886345c 100644 --- a/resources/master_data/수식문서/수식_건설품셈_08장_건설기계.json +++ b/resources/master_data/수식문서/수식_건설품셈_08장_건설기계.json @@ -2352,6 +2352,92 @@ "비목": {"방법": "버림", "자리": 0}, "끝전": "비목버림" } + }, + { + "꼴": "수식문서", + "판": 1, + "키": "GC001200", + "이름": "기계 시간당 기계경비(연료 · 전력 기종)", + "결과단위": "원/시간", + "출처": "건설품셈 공통 8-1-5 · 8-1-6 · 8-1-6 3 가", + "부품": { + "갈래": "기계경비식" + }, + "변수": [ + {"열쇠": "기계", "기호": "S", "아래": "기계", "위": "", "이름": "기계", "단위": "", "연결": {"갈래": "선택", "목록": [], "값": 0}}, + {"열쇠": "지역", "기호": "S", "아래": "지역", "위": "", "이름": "지역", "단위": "", "출처": "건설품셈 공통 8-1-7 5", "연결": {"갈래": "선택", "목록": ["전국평균", "전국", "서울", "경기", "강원", "충북", "충남", "전북", "경북", "경남", "부산", "제주", "대구", "인천", "대전", "울산", "세종", "전남광주"], "값": "전국평균"}}, + {"열쇠": "전력 계약종별", "기호": "S", "아래": "전력계약종별", "위": "", "이름": "전력 계약종별", "단위": "", "출처": "유가전력 한전 전기요금표 2025-01-01", "연결": {"갈래": "선택", "목록": ["일반용(갑)Ⅰ 저압", "주택용 저압"], "값": "일반용(갑)Ⅰ 저압"}}, + {"열쇠": "손료", "기호": "C", "아래": "손료", "위": "", "이름": "손료", "단위": "", "출처": "건설품셈 공통 8-1-5 12 · 8-1-6 4", "연결": {"갈래": "식"}}, + {"열쇠": "연료", "기호": "S", "아래": "연료", "위": "", "이름": "연료", "단위": "", "출처": "건설품셈 공통 8-4 주①㉰", "연결": {"갈래": "요소", "키": "EQ:{S_기계}", "칸": "주연료종류", "계약종별": "S_전력계약종별"}}, + {"열쇠": "P_EQ기계", "기호": "P", "아래": "EQ기계", "위": "", "이름": "EQ:{기계}", "단위": "", "연결": {"갈래": "요소", "키": "EQ:{S_기계}", "칸": "가격", "계약종별": "S_전력계약종별"}}, + {"열쇠": "P_EQ기계2", "기호": "P", "아래": "EQ기계2", "위": "", "이름": "EQ:{기계}", "단위": "", "연결": {"갈래": "요소", "키": "EQ:{S_기계}", "칸": "손료계수", "계약종별": "S_전력계약종별"}}, + {"열쇠": "P_EQ기계3", "기호": "P", "아래": "EQ기계3", "위": "", "이름": "EQ:{기계}", "단위": "", "연결": {"갈래": "요소", "키": "EQ:{S_기계}", "칸": "주연료", "계약종별": "S_전력계약종별"}}, + {"열쇠": "P_MO연료지역", "기호": "P", "아래": "MO연료지역", "위": "", "이름": "MO:{연료}:{지역}", "단위": "", "연결": {"갈래": "요소", "키": "MO:{S_연료}:{S_지역}", "계약종별": "S_전력계약종별"}}, + {"열쇠": "P_EQ기계4", "기호": "P", "아래": "EQ기계4", "위": "", "이름": "EQ:{기계}", "단위": "", "연결": {"갈래": "요소", "키": "EQ:{S_기계}", "칸": "전력", "계약종별": "S_전력계약종별"}}, + {"열쇠": "P_전력", "기호": "P", "아래": "전력", "위": "", "이름": "전력단가", "단위": "", "연결": {"갈래": "요소", "재료": {"이름": "전력량요금", "계약종별": "입력"}, "단위": "㎾h", "계약종별": "S_전력계약종별"}}, + {"열쇠": "P_EQ기계5", "기호": "P", "아래": "EQ기계5", "위": "", "이름": "EQ:{기계}", "단위": "", "연결": {"갈래": "요소", "키": "EQ:{S_기계}", "칸": "잡재료율", "계약종별": "S_전력계약종별"}} + ], + "식": [ + {"기호": "C_손료", "식": "버림(P_EQ기계 × 1000 × P_EQ기계2 ÷ 10000000, 0)"} + ], + "금액": [ + {"이름": "주연료", "단위": "ℓ", "비목": "재료비", "수량": "P_EQ기계3", "단가": "P_MO연료지역", "출처": "건설품셈 공통 8-4-8"}, + {"이름": "전력", "단위": "㎾h", "비목": "재료비", "수량": "P_EQ기계4", "단가": "P_전력", "출처": "건설품셈 공통 8-1-6 3 가"}, + {"이름": "잡재료비", "단위": "식", "비목": "재료비", "단가": "재료비 × P_EQ기계5 ÷ 100", "출처": "건설품셈 공통 8-4 주②"}, + {"이름": "기계손료", "단위": "식", "비목": "경비", "단가": "C_손료", "출처": "건설품셈 공통 8-1-6 2"} + ], + "끝수": { + "줄": {"방법": "버림", "자리": 1}, + "비목": {"방법": "버림", "자리": 0}, + "끝전": "비목버림" + } + }, + { + "꼴": "수식문서", + "판": 1, + "키": "GC001201", + "이름": "기계 시간당 기계경비(연료 · 전력 · 조종원 기종)", + "결과단위": "원/시간", + "출처": "건설품셈 공통 8-1-5 · 8-1-6 · 8-1-6 3 가", + "부품": { + "갈래": "기계경비식" + }, + "변수": [ + {"열쇠": "기계", "기호": "S", "아래": "기계", "위": "", "이름": "기계", "단위": "", "연결": {"갈래": "선택", "목록": [], "값": 0}}, + {"열쇠": "지역", "기호": "S", "아래": "지역", "위": "", "이름": "지역", "단위": "", "출처": "건설품셈 공통 8-1-7 5", "연결": {"갈래": "선택", "목록": ["전국평균", "전국", "서울", "경기", "강원", "충북", "충남", "전북", "경북", "경남", "부산", "제주", "대구", "인천", "대전", "울산", "세종", "전남광주"], "값": "전국평균"}}, + {"열쇠": "전력 계약종별", "기호": "S", "아래": "전력계약종별", "위": "", "이름": "전력 계약종별", "단위": "", "출처": "유가전력 한전 전기요금표 2025-01-01", "연결": {"갈래": "선택", "목록": ["일반용(갑)Ⅰ 저압", "주택용 저압"], "값": "일반용(갑)Ⅰ 저압"}}, + {"열쇠": "손료", "기호": "C", "아래": "손료", "위": "", "이름": "손료", "단위": "", "출처": "건설품셈 공통 8-1-5 12 · 8-1-6 4", "연결": {"갈래": "식"}}, + {"열쇠": "연료", "기호": "S", "아래": "연료", "위": "", "이름": "연료", "단위": "", "출처": "건설품셈 공통 8-4 주①㉰", "연결": {"갈래": "요소", "키": "EQ:{S_기계}", "칸": "주연료종류", "계약종별": "S_전력계약종별"}}, + {"열쇠": "직종", "기호": "S", "아래": "직종", "위": "", "이름": "직종", "단위": "", "출처": "건설품셈 공통 8-1-3 5", "연결": {"갈래": "요소", "키": "EQ:{S_기계}", "칸": "조종원직종", "계약종별": "S_전력계약종별"}}, + {"열쇠": "시간환산", "기호": "Q", "아래": "시간환산", "위": "", "이름": "시간환산", "단위": "", "출처": "건설품셈 공통 1-1-3 2(일일 작업시간 8시간)", "연결": {"갈래": "식"}}, + {"열쇠": "P_EQ기계", "기호": "P", "아래": "EQ기계", "위": "", "이름": "EQ:{기계}", "단위": "", "연결": {"갈래": "요소", "키": "EQ:{S_기계}", "칸": "가격", "계약종별": "S_전력계약종별"}}, + {"열쇠": "P_EQ기계2", "기호": "P", "아래": "EQ기계2", "위": "", "이름": "EQ:{기계}", "단위": "", "연결": {"갈래": "요소", "키": "EQ:{S_기계}", "칸": "손료계수", "계약종별": "S_전력계약종별"}}, + {"열쇠": "Q_분자^표", "기호": "Q", "아래": "분자", "위": "표", "이름": "분자", "단위": "", "연결": {"갈래": "표", "표": "CC000336", "조건": {"구분": "'시간환산'"}, "칸": "분자"}}, + {"열쇠": "Q_분모^표", "기호": "Q", "아래": "분모", "위": "표", "이름": "분모", "단위": "", "연결": {"갈래": "표", "표": "CC000336", "조건": {"구분": "'시간환산'"}, "칸": "분모"}}, + {"열쇠": "P_EQ기계3", "기호": "P", "아래": "EQ기계3", "위": "", "이름": "EQ:{기계}", "단위": "", "연결": {"갈래": "요소", "키": "EQ:{S_기계}", "칸": "주연료", "계약종별": "S_전력계약종별"}}, + {"열쇠": "P_MO연료지역", "기호": "P", "아래": "MO연료지역", "위": "", "이름": "MO:{연료}:{지역}", "단위": "", "연결": {"갈래": "요소", "키": "MO:{S_연료}:{S_지역}", "계약종별": "S_전력계약종별"}}, + {"열쇠": "P_EQ기계4", "기호": "P", "아래": "EQ기계4", "위": "", "이름": "EQ:{기계}", "단위": "", "연결": {"갈래": "요소", "키": "EQ:{S_기계}", "칸": "전력", "계약종별": "S_전력계약종별"}}, + {"열쇠": "P_전력", "기호": "P", "아래": "전력", "위": "", "이름": "전력단가", "단위": "", "연결": {"갈래": "요소", "재료": {"이름": "전력량요금", "계약종별": "입력"}, "단위": "㎾h", "계약종별": "S_전력계약종별"}}, + {"열쇠": "P_EQ기계5", "기호": "P", "아래": "EQ기계5", "위": "", "이름": "EQ:{기계}", "단위": "", "연결": {"갈래": "요소", "키": "EQ:{S_기계}", "칸": "조종원", "계약종별": "S_전력계약종별"}}, + {"열쇠": "P_LB직종", "기호": "P", "아래": "LB직종", "위": "", "이름": "LB:{직종}", "단위": "", "연결": {"갈래": "요소", "키": "LB:{S_직종}", "계약종별": "S_전력계약종별"}}, + {"열쇠": "P_EQ기계6", "기호": "P", "아래": "EQ기계6", "위": "", "이름": "EQ:{기계}", "단위": "", "연결": {"갈래": "요소", "키": "EQ:{S_기계}", "칸": "잡재료율", "계약종별": "S_전력계약종별"}} + ], + "식": [ + {"기호": "C_손료", "식": "버림(P_EQ기계 × 1000 × P_EQ기계2 ÷ 10000000, 0)"}, + {"기호": "Q_시간환산", "식": "Q_분자^표 ÷ Q_분모^표"} + ], + "금액": [ + {"이름": "주연료", "단위": "ℓ", "비목": "재료비", "수량": "P_EQ기계3", "단가": "P_MO연료지역", "출처": "건설품셈 공통 8-4-8"}, + {"이름": "전력", "단위": "㎾h", "비목": "재료비", "수량": "P_EQ기계4", "단가": "P_전력", "출처": "건설품셈 공통 8-1-6 3 가"}, + {"이름": "조종원", "단위": "인", "비목": "노무비", "수량": "P_EQ기계5 × Q_시간환산", "단가": "P_LB직종", "출처": "건설품셈 공통 8-1-3 6"}, + {"이름": "잡재료비", "단위": "식", "비목": "재료비", "단가": "재료비 × P_EQ기계6 ÷ 100", "출처": "건설품셈 공통 8-4 주②"}, + {"이름": "기계손료", "단위": "식", "비목": "경비", "단가": "C_손료", "출처": "건설품셈 공통 8-1-6 2"} + ], + "끝수": { + "줄": {"방법": "버림", "자리": 1}, + "비목": {"방법": "버림", "자리": 0}, + "끝전": "비목버림" + } } ] } diff --git a/resources/tester/test_821_4_import_my_machine.py b/resources/tester/test_821_4_import_my_machine.py index 5b0910e21..21441b831 100644 --- a/resources/tester/test_821_4_import_my_machine.py +++ b/resources/tester/test_821_4_import_my_machine.py @@ -206,7 +206,9 @@ def test_cleanup_820_1() -> None: assert "자체 발전기" not in text and "자체 콘크리트펌프용" not in text led = json.loads((ROOT / "resources/master_data/_키대장.json").read_text("utf-8")) assert all(k in led["폐기"] and k not in led["키"] for k in [*GONE, "GC001195"]) - assert led["다음"]["EQ"] == 669 and led["다음"]["GC"] == 1196 # 결번 · 재사용 안 함 + for pre in ("EQ", "GC"): # 결번 · 재사용 안 함 — 다음 번호가 쓴 · 버린 번호 모두보다 뒤 + used = [int(k[2:]) for k in [*led["키"], *led["폐기"]] if k.startswith(pre)] + assert led["다음"][pre] > max(used) alias = [r for r in eq.values() if r.get("별칭")] assert len(alias) >= 10 diff --git a/resources/tester/test_822_2_machine_hourly_all.py b/resources/tester/test_822_2_machine_hourly_all.py index 6194dbbbe..a728bafc2 100644 --- a/resources/tester/test_822_2_machine_hourly_all.py +++ b/resources/tester/test_822_2_machine_hourly_all.py @@ -4,7 +4,7 @@ ① 모든 기계 = 식 있음 또는 까닭 글(「셀 자료가 없음」 0) ② 식 고름 = 목록 › 꼴(채운 칸) 한 함수 ③ M01 [새 기계] 저장 = 꼴 식 목록 등록 · 지우면 목록에서 뺌 · 로직 파일 글 그대로(임시 마스터) ④ 직접 값 식(GC001199) — 내 기계 「직접」 시간당 · 줄 쌓기 식 ⑤ 전력 줄 — 점보드릴 135㎾ × 전력 단가 + -잡재료 6 % + 손료 + 조종원 · 계약종별 바꿈 · 내 기계 전력 ⑥ 옮긴 기계 견본(아스팔트 믹싱플랜트 · 타워크레인 · +잡재료 6 % + 손료 + 조종원 · 계약종별 바꿈 · 내 기계 전력 · 연료 + 전력(822-2b GC001200 · + 조종원 GC001201) ⑥ 옮긴 기계 견본(아스팔트 믹싱플랜트 · 타워크레인 · 직종 입력 = 아스팔트 스프레어) ⑦ 미리보기 = 서버 값 ⑧ 안 옮긴 기계 금액 그대로 ⑨ POWER TROWEL 이름. """ @@ -36,6 +36,7 @@ import master_machine_coef as mc # noqa: E402 MACHINE, LOGIC = "기계.json", "로직_건설품셈_08장_건설기계.json" POWER, POWER_CREW, ONE_FUEL, DIRECT = "GC001196", "GC001197", "GC001198", "GC001199" +FUEL_POWER, FUEL_POWER_CREW = "GC001200", "GC001201" NAME = "sub1임시기계822" # 안 옮긴 기계 — 822-2 전 금액(전국평균 · 기본 옵션) KEEP = {"EQ000001": 68550, "EQ000022": 108958} @@ -87,7 +88,10 @@ def test_pick_listed_then_shape(): assert shape({"값": {**full, "전력": 5, "조종원": 1, "조종원직종": "1048"}}) == POWER_CREW assert shape({"값": full}) == "GC000273" assert shape({"방식": "직접", "값": {}}) == DIRECT - assert shape({"값": {**full, "주연료": 1, "전력": 5}}) is None + assert shape({"값": {**full, "주연료": 1, "전력": 5}}) == FUEL_POWER + both = {**full, "주연료": 1, "전력": 5, "조종원": 1} + assert shape({"값": {**both, "조종원직종": "1048"}}) == FUEL_POWER_CREW + assert shape({"값": both}) is None # 직종 없는 조종원 — 까닭 assert shape({"값": {**full, "조종원": 1}}) is None # 직종 없는 조종원만 — 까닭 assert shape({"값": {**full, "주연료": "73.7+"}}) is None @@ -138,7 +142,9 @@ def test_new_machine_registers_and_unregisters(copy: Path): _save(client, [{"op": "delete", "key": key}]) assert "9999-0822" not in _codes("GC000268") assert (copy / LOGIC).read_text(encoding="utf-8") == logic_text - _save(client, [{"op": "add", "row": {**row, "원문번호": ""}}]) # 빈 원문번호 = 「자체 EQ…」 받을 키 + _save( + client, [{"op": "add", "row": {**row, "원문번호": ""}}] + ) # 빈 원문번호 = 「자체 EQ…」 받을 키 key = max(k for k, r in _rows().items() if r["이름"] == NAME) assert _rows()[key]["원문번호"] == f"자체 {key}" and f"자체 {key}" in _codes("GC000268") _save(client, [{"op": "delete", "key": key}]) @@ -213,8 +219,18 @@ def test_power_my_machine(world): assert hour["로직"] == POWER want = mc.preview({"가격": 1000, "손료계수": 2000, "전력": 10, "잡재료율": 5}, 0, 0, 114.4) assert (hour["재료비"], hour["경비"]) == (want["재료비"], want["경비"]) == (1201, 200) - with pytest.raises(store.StoreError): - _at(me, mym.create, {**body, "값": {**body["값"], "주연료": 1, "주연료종류": "경유"}}) + # 822-2b 연료 + 전력 둘 다(경쟁사 파워트로웰 꼴) — 손료 + 주연료 + 잡품(둘의 %) + 전력 = 미리보기 + vals = {**body["값"], "주연료": 1, "주연료종류": "휘발유"} + both = _at(me, mym.create, {**body, "규격": "연료전력", "값": vals})["시간당"] + oil = float(m01.loaded()[1].numbers["MO"]["휘발유:전국평균"]["값"]) + want = mc.preview(vals, oil, 0, 114.4) + assert both["로직"] == FUEL_POWER and want["주연료"] > 0 and want["전력"] > 0 + assert (both["재료비"], both["경비"], both["계"]) == (want["재료비"], want["경비"], want["계"]) + vals |= {"조종원": 1, "조종원직종": "1048"} # + 조종원 = GC001201 + crew = _at(me, mym.create, {**body, "규격": "연료전력조종원", "값": vals})["시간당"] + want = mc.preview(vals, oil, float(_wage("1048")), 114.4) + assert crew["로직"] == FUEL_POWER_CREW and crew["노무비"] == want["노무비"] > 0 + assert (crew["재료비"], crew["경비"], crew["계"]) == (want["재료비"], want["경비"], want["계"]) # ⑥ · ⑦ 옮긴 기계 견본 ─────────────────────────────────────────────────