diff --git a/M02_MasterTemplete/M02_Doc_Import.py b/M02_MasterTemplete/M02_Doc_Import.py index fd2053e67..a019b1b44 100644 --- a/M02_MasterTemplete/M02_Doc_Import.py +++ b/M02_MasterTemplete/M02_Doc_Import.py @@ -196,7 +196,7 @@ def hourly_link(eq: str, part: str) -> dict | None: logic = machine.logic_of(code) if not logic: return None - given = {"기계": _lit(code)} + given = {"기계": _lit(code)} if machine.takes_machine(logic) else {} for spec in logic.get("입력") or []: if spec.get("이름") != "기계": given[spec["이름"]] = _lit((spec.get("고르기") or [""])[0]) diff --git a/M02_MasterTemplete/M02_Doc_Take.py b/M02_MasterTemplete/M02_Doc_Take.py index 71693255b..e3a29d2a8 100644 --- a/M02_MasterTemplete/M02_Doc_Take.py +++ b/M02_MasterTemplete/M02_Doc_Take.py @@ -140,7 +140,7 @@ def _fixed(fx: dict, qty: str | None, rates: list[dict]) -> list[dict]: got = mh.hourly(str(link["기계"])) if not got.get("ok") or not got.get("로직"): return [_warn(f"기계 「{name}」 — {got.get('reason') or '시간당 경비 못 셈'}")] - machine = {"기계": f"'{got['원문번호']}'"} + machine = {"기계": f"'{got['원문번호']}'"} if mh.takes_machine(mh.logic_of(got["원문번호"]) or {}) else {} # fmt: skip return _pick("기계", qty, 키=got["로직"], 이름=name, 규격=spec, 입력=machine) price = fx.get("단가") or {} costs = [c for c in COSTS if Decimal(str(price.get(c) or 0))] or ["재료비"] diff --git a/M02_MasterTemplete/M02_Machine_Hourly.py b/M02_MasterTemplete/M02_Machine_Hourly.py index 957969d8b..343bbef9c 100644 --- a/M02_MasterTemplete/M02_Machine_Hourly.py +++ b/M02_MasterTemplete/M02_Machine_Hourly.py @@ -56,7 +56,7 @@ def logic_of(code: str) -> dict | None: (「조종원 없는 기종」 목록에 겹친 기계 — 진동롤러(핸드가이드식) · 고소작업차 …).""" fit = [r for r in _family() if code in [str(c) for c in _codes(r)]] if not fit: - return None + return _own(code) op = _operated(code) def order(row: dict) -> tuple: @@ -67,6 +67,25 @@ def logic_of(code: str) -> dict | None: return min(fit, key=order) +def _own(code: str) -> dict | None: + """그 기계만의 시간당 경비 식(816-1 · 4륜구동 1톤 덤프트럭 = GF000145) — 「기계」 입력 없는 + 기계경비식이 그 원문번호 기계 줄 가격(`EQ….가격`)을 읽으면 그 식 · 없으면 None.""" + rows = store.loaded()[1].index.get("EQ", {}).values() + prices = [f"{r.get('키')}.가격" for r in rows if code and str(r.get("원문번호")) == code] + for data in store.loaded()[0].values(): + for row in data.get("줄") or [] if data.get("그룹") == "로직" else []: + if (row.get("부품") or {}).get("갈래") != "기계경비식" or takes_machine(row): + continue + if any(p in str(row.get("중간")) for p in prices): + return row + return None + + +def takes_machine(logic: dict) -> bool: + """식이 「기계」 입력(원문번호 고르기)을 받는지 — 안 받는 식(GF000145)엔 기계='…' 를 안 넘김.""" + return any(i.get("이름") == "기계" for i in logic.get("입력") or []) + + def hourly(key: str) -> dict[str, Any]: """`{ok, 이름, 규격, 로직, 원문번호, 노무비, 재료비, 경비, 계}` · 못 셈 = `{ok: False, reason}`.""" if not key.startswith("EQ"): @@ -84,7 +103,8 @@ def hourly(key: str) -> dict[str, Any]: for i in logic.get("입력") or [] if i.get("이름") != "기계" ) - call = f"로직({logic['키']}, 기계='{code}'{args})" + mine = f", 기계='{code}'" if takes_machine(logic) else "" + call = f"로직({logic['키']}{mine}{args})" line = {"종류": "로직", "요소": call, "이름": "기계", "단위": "시간", "수량": "1"} holder = { "키": "", "원문번호": "", "이름": "기계 시간", "결과단위": "원/식", "출처": "자체", diff --git a/docs/raw/요구_1104/_과녁_773_자재표기.tsv b/docs/raw/요구_1104/_과녁_773_자재표기.tsv new file mode 100644 index 000000000..bf88925c1 --- /dev/null +++ b/docs/raw/요구_1104/_과녁_773_자재표기.tsv @@ -0,0 +1,101 @@ +행 가져온 이름 가져온 규격 쓰임 기대 우리 키 우리 이름 우리 규격 확신 +1 접착제 11 후보 사람이 고름 — 틀린 줄에 자동으로 잇지 않음 +2 패널(유로폼) 600*1200mm 10 이음 MT000467 유로폼패널 600×1200㎜ 표기만 다름 +3 각재 외송 8 이음 MT000393 각 재(외송) 30×30×3600mm 눈으로 추정 +4 요소 8 이음 MT006763 요 소 N:46% 눈으로 추정 +5 내부코너패널(유로폼) (100x200)x1200mm 7 이음 MT000470 내부코너패널 100×200×1200㎜ 표기만 다름 +6 결속선(철선) #20 , 0.9M/M 7 후보 사람이 고름 — 틀린 줄에 자동으로 잇지 않음 +7 각재 (외송) 6 이음 MT000393 각 재(외송) 30×30×3600mm 눈으로 추정 +8 파형강관 별도계상 6 잇지 않음 별도계상 +9 금강사 5 잇지 않음 우리 표에 없음 +10 고무테이프 0.5mm×19mm×10m 5 이음 MT009202 절연 면고무테이프 0.5mm×19mm×10m 눈으로 추정 +11 낙석방지책 H2500×W2000(표준) 5 후보 사람이 고름 — 틀린 줄에 자동으로 잇지 않음 +12 낙석방지책 H2500×W2000(단부) 5 후보 사람이 고름 — 틀린 줄에 자동으로 잇지 않음 +13 종자 초본류 5 후보 1 순위 MT006646 종 자 초본위주형 좁힘(자동 이음 아님) +14 종자 목본류 5 후보 1 순위 MT006648 종 자 목본군락형 좁힘(자동 이음 아님) +15 어닐링철선(결속선) #20 0.9mm 200.4m/kg 5 이음 MT000209 어닐링철선(결속선),서울 #20, 0.9mm 표기만 다름 +16 내수합판1급 12mmx1220x2440 4 이음 MT000018 합판(내수), 서울 12t×1220×2440mm 표기만 다름 +17 어닐링철선(결속선) #20 0.9M/M 4 이음 MT000209 어닐링철선(결속선),서울 #20, 0.9mm 표기만 다름 +18 유로폼(패널) 600*1200 4 이음 MT000467 유로폼패널 600×1200㎜ 표기만 다름 +19 내부코너패널 (200+200)*1200 4 이음 MT000472 내부코너패널 (200+200)×1200㎜ 표기만 다름 +20 합판(내수) 12×1220×2440 4 이음 MT000018 합판(내수), 서울 12t×1220×2440mm 표기만 다름 +21 조임철물 (직교자재) 4 이음 MT000499 조임철물,서울 직교,자재 표기만 다름 +22 에폭시수지 YD-128 4 후보 사람이 고름 — 틀린 줄에 자동으로 잇지 않음 +23 종자 생태복원형,초본류 3 후보 1 순위 MT006646 종 자 초본위주형 좁힘(자동 이음 아님) +24 종자 생태복원형,목본류 3 후보 1 순위 MT006648 종 자 목본군락형 좁힘(자동 이음 아님) +25 내부코너패널(유로폼) (100+200)*1200mm 3 이음 MT000470 내부코너패널 100×200×1200㎜ 표기만 다름 +26 유로폼(패널) 600×1200 3 이음 MT000467 유로폼패널 600×1200㎜ 표기만 다름 +27 콘테이너하우스 창고용(3.0m×6.0m×2.6m) 3 이음 MT007111 콘테이너(창고) 6.0*3.0*2.6m 표기만 다름 +28 전기뇌관(MS) 3.5m×500개(하이데토) 2 이음 MT005677 전기뇌관 3.5m 눈으로 추정 +29 BUTTON BIT Ø38×76㎜ 2 후보 사람이 고름 — 틀린 줄에 자동으로 잇지 않음 +30 유압드릴샹크 T38×CM470 2 후보 사람이 고름 — 틀린 줄에 자동으로 잇지 않음 +31 유압식드릴스리브 T38×190mm 2 이음 MT005687 유압드릴스리브 T38×190mm 표기만 다름 +32 미송(판재) 2 후보 사람이 고름 — 틀린 줄에 자동으로 잇지 않음 +33 산림종자 참싸리(박피) 2 이음 MT006664 산림종자 참싸리(풍화암,강마사토) 눈으로 추정 +34 유기질퇴비 2 후보 사람이 고름 — 틀린 줄에 자동으로 잇지 않음 +35 PVC지수판 200x5T KSM3805 2 이음 MT006544 PVC지수판 200×5T 표기만 다름 +36 PVC용접봉 Ø3.2 (국산) 2 후보 사람이 고름 — 틀린 줄에 자동으로 잇지 않음 +37 PVC파이프(일반용VG2) 50㎜ × 4m 2 이음 MT002926 PVC파이프(일반관),서울 D=50mm(VG2) 표기만 다름 +38 혼합골재 영월 2 후보 사람이 고름 — 틀린 줄에 자동으로 잇지 않음 +39 이형철근 별도계상 2 잇지 않음 별도계상 +40 안전표지판 삼각,D=900 2 이음 MT003202 교통안전표지판 900,삼각(고휘도) 눈으로 추정 +41 표지판지주 D=76.3mm, 3.5M 2 후보 사람이 고름 — 틀린 줄에 자동으로 잇지 않음 +42 블레이드(커터) "d=320 400mm 14""xt3.2" 2 이음 MT005749 블레이드 "14""×3.2mm" 표기만 다름 +43 떼 2 잇지 않음 우리 표에 없음 +44 강관비계 φ48.6m/m×2.3mm 2 이음 MT000481 강관비계,서울 Φ48.6*2.3*4.0m 표기만 다름 +45 철물 2 후보 사람이 고름 — 틀린 줄에 자동으로 잇지 않음 +46 각재(말뚝) Φ60 2 후보 사람이 고름 — 틀린 줄에 자동으로 잇지 않음 +47 강관써포트 V4 2600-4000mm 14.3kg 2 이음 MT000487 강관동바리,서울 Φ48.6*2.4,L=2.6~4.0 눈으로 추정 +48 안고초 2 이음 MT006667 산림종자 안고초 표기만 다름 +49 비수리 2 이음 MT006665 산림종자 비수리 표기만 다름 +50 내수합판1급 12m/m 1220×2440 2 이음 MT000018 합판(내수), 서울 12t×1220×2440mm 표기만 다름 +51 각재(외송) 3.6×3.0×3.0 2 이음 MT000393 각 재(외송) 30×30×3600mm 눈으로 추정 +52 내수합판1급 12mm 1220×2440 2 이음 MT000018 합판(내수), 서울 12t×1220×2440mm 표기만 다름 +53 각재(거푸집용,외송) 3.6×3.0×3.0 2 이음 MT000393 각 재(외송) 30×30×3600mm 눈으로 추정 +54 다이아몬드톱날 "Ø14""×3.2t(콘크리트용)" 2 이음 MT005749 블레이드 "14""×3.2mm" 눈으로 추정 +55 아세틸렌 용접용 2 이음 MT003163 아세틸렌 98% (용접용) 표기만 다름 +56 산소 고압가스 2 이음 MT003166 산 소 고압상태 눈으로 추정 +57 신나 KSM6060 2종(조합페인트류) 2 이음 MT003398 신너(조합페인트용) KSM-6060(2종) 표기만 다름 +58 초류종자(국내산) 참싸리,비수리,낭아초등 1 후보 사람이 고름 — 틀린 줄에 자동으로 잇지 않음 +59 종 자 초본형 1 후보 1 순위 MT006646 종 자 초본위주형 좁힘(자동 이음 아님) +60 소나무우드칩(멀칭재) 1 후보 사람이 고름 — 틀린 줄에 자동으로 잇지 않음 +61 3단코어비트 "5""(125mm)" 1 후보 사람이 고름 — 틀린 줄에 자동으로 잇지 않음 +62 P V C PIPE Φ50M/M,VG1 1 이음 MT002861 PVC파이프(일반관),서울 D=50mm(VG1) 표기만 다름 +63 콘테이너(창 고) 3×6×2.6 1 이음 MT007111 콘테이너(창고) 6.0*3.0*2.6m 표기만 다름 +64 강관비계 48.6mm×2.3mm×6m 1 후보 사람이 고름 — 틀린 줄에 자동으로 잇지 않음 +65 철물 직교자재 1 이음 MT000499 조임철물,서울 직교,자재 눈으로 추정 +66 문양거푸집(ABS코팅품) 600×1200 1 이음 MT000453 문양거푸집(플라스틱 ABS코팅폼) 600×1200 표기만 다름 +67 와이어매쉬 #6 100×100 1 이음 MT007130 와이어메쉬(용접철망)관급 #6, 100×100 표기만 다름 +68 지수판 T5×200 1 이음 MT006544 PVC지수판 200×5T 표기만 다름 +69 용접봉(연강용) 3.2m/m 1 후보 사람이 고름 — 틀린 줄에 자동으로 잇지 않음 +70 어닐링철선 (결속선) #6 4.0mm 10.1m/kg 1 후보 사람이 고름 — 틀린 줄에 자동으로 잇지 않음 +71 구역화물자동차(4.5Ton) 80km이내 1 이음 MT023493 구역화물 4.5톤, 80km 표기만 다름 +72 구역화물자동차(4.5Ton) 60km이내 1 이음 MT023491 구역화물 4.5톤, 60km 표기만 다름 +73 산소(6000ℓ) 99%,120kg/㎠ 1 이음 MT003165 산 소 6000ℓ/병 표기만 다름 +74 아세칠렌 AC 98%,용접용 1 이음 MT003163 아세틸렌 98% (용접용) 표기만 다름 +75 서비스볼트(고장력볼트) M20×60 1 이음 MT002536 고장력볼트 M20*60mm 표기만 다름 +76 보조강재(열연강판) T=9-12 1 후보 사람이 고름 — 틀린 줄에 자동으로 잇지 않음 +77 구역화물자동차(8Ton) 10km이내 1 이음 MT023654 구역화물 8.0톤, 10km 표기만 다름 +78 구역화물자동차(8Ton) 20km이내 1 이음 MT023655 구역화물 8.0톤, 20km 표기만 다름 +79 참싸리(박피) 1 이음 MT006664 산림종자 참싸리(풍화암,강마사토) 눈으로 추정 +80 부산물비료 20kg/포 1 후보 사람이 고름 — 틀린 줄에 자동으로 잇지 않음 +81 참싸리 박피 1 이음 MT006664 산림종자 참싸리(풍화암,강마사토) 눈으로 추정 +82 복합비료 21-17-17 20kg/포 1 이음 MT006490 복합비료 21-17-17 표기만 다름 +83 퇴비(천연부엽토) 20㎏/포 1 이음 MT006788 천연부엽토 20kg/포 눈으로 추정 +84 문양거푸집(ABS코팅폼) 600×1200×20~30mm 1 이음 MT000453 문양거푸집(플라스틱 ABS코팅폼) 600×1200 표기만 다름 +85 P.V.C PIPE VG1(50mm) 1 이음 MT002861 PVC파이프(일반관),서울 D=50mm(VG1) 표기만 다름 +86 다웰바(DOWEL BAR) Ø32×1,000 1 이음 MT006540 다 웰 바 Φ32*1000 표기만 다름 +87 P.V.C PIPE VG1(35mm) 1 이음 MT002859 PVC파이프(일반관),서울 D=35mm(VG1) 표기만 다름 +88 휠라 T=15mm,1000×1000mm 1 후보 사람이 고름 — 틀린 줄에 자동으로 잇지 않음 +89 측구수로관 300×300×2000×120,앵글포함 1 이음 MT015883 측구수로관(앵글부착) 300×300×120 표기만 다름 +90 중하중그레이팅 395×995×52 1 이음 MT007025 스틸그레이팅(중하중용) 395×995×52 표기만 다름 +91 측구수로관 500×500×2000×150,앵글포함 1 이음 MT015887 측구수로관(앵글부착) 500×500×150 표기만 다름 +92 중하중그레이팅 595×995×67 1 이음 MT007032 스틸그레이팅(중하중용) 595×995×67 표기만 다름 +93 잔디 0.18×0.18×0.01 1 후보 사람이 고름 — 틀린 줄에 자동으로 잇지 않음 +94 강관비계 4000×48.6mm×2.3mm 1 이음 MT000481 강관비계,서울 Φ48.6*2.3*4.0m 표기만 다름 +95 삼각표지판 삼각,900mm 1 이음 MT003202 교통안전표지판 900,삼각(고휘도) 눈으로 추정 +96 표지판지주 D=76.3mm×3.0m 1 이음 MT003241 표지판지주 Φ76.3×3000 표기만 다름 +97 공사안내표지판 300×1500 1 후보 사람이 고름 — 틀린 줄에 자동으로 잇지 않음 +98 공사안전PE드럼 500×800 1 이음 MT003311 PE드럼(일체형) Φ500×800 표기만 다름 +99 윙카호스 10cm 1 후보 사람이 고름 — 틀린 줄에 자동으로 잇지 않음 +100 조합페인트 KSM6020 2급,백색 1 이음 MT003372 조합페인트 KSM-6020 2급(백색) 표기만 다름 diff --git a/docs/raw/요구_1104/_방향_불러오기.md b/docs/raw/요구_1104/_방향_불러오기.md index 2ca3a689c..017a8b950 100644 --- a/docs/raw/요구_1104/_방향_불러오기.md +++ b/docs/raw/요구_1104/_방향_불러오기.md @@ -160,3 +160,25 @@ - M2 고침(안): 가름의 잣대 = 금액(노 · 재 · 경 · 계)보다 **구성 줄(손료계수 · 주연료량 · 조종원 — 품셈 값)** — 원파일은 구성 표 · 엑셀은 「기계경비」 시트(산출근거 줄)에 있음 · 가격 · 유가는 값이라 잣대에서 뺌. - M1 = PLAN 816-1 로 진행(요구 770-1). + +## O. 구글 시트 「수동연결(자재)」 · 「수동연결(기계)」 검토(요구 772 · 시트 = AISLO_이슈관리대장 · 읽기 = 드라이브 커넥터로 xlsx 받아 `tmp/q772_sheet.xlsx`) + +기계 30 줄(사용자 메모 대조): + +| 갈래 | 줄 | 내용 | +|---|---|---| +| 이미 이어짐(목록이 옛 것 — 815-2 별칭 다섯 합치기 전에 뜬 목록) | 4 | 바이브레이트 → EQ000248 · 버킷준설기 → EQ000425 · 아스팔트페이버(피니셔) 3.0m → EQ000193 · 1.7m → EQ000192 | +| 816 에서 처리 중 | 8 | 덤프트럭 1.0Ton · 굴착기 1.0 · 0.6㎥ · 굴삭기(1.0m3) 둘 · 크레인(트럭) 10 · 15Ton · 엔진톱 18" | +| 메모 글 검색으로 바로 나옴(별칭만 넣으면 됨) | 3 | 덤프자동덮개 15톤 → EQ000078 덤프트럭 자동덮개시설 15톤용 · 24톤 → EQ000080 · 트럭트랙터및트레일러 20톤 → EQ000183 트럭 트랙터 및 평판트레일러 20ton | +| 확인 필요 | 2 | 커터(콘크리트 및 아스팔트용) 320-440mm ↔ EQ000234 320~400(규격 범위 다름) · 크로울러드릴 탑승유압식 ↔ EQ000337 110㎾ / EQ000338 150㎾(가져온 쪽 규격 없음) | +| 우리 표 · 현행 품셈에 없음 | 13 | 발전기 5.5 · 7 · 10kW · 브레이카 0.18㎥ · 모노펌프 · 에어 호스 · 파워트로웰 · 콘크리트펌프용 파이프 여섯(EST 는 기계 손료로 둠) | + +- 크레인(트럭) 10 · 15Ton: 사용자 메모 = 트럭탑재형 크레인 · EST 구성 줄 = 크레인(타이어)와 같은 값(2,298 · 136,400 천원 · 3.8ℓ — 트럭탑재형 10ton 은 2,598 · 91,593 천원 · 10.3ℓ) → 사용자 판단 대기. + +자재 100 줄(브레인이 한 줄씩 읽음 · 사용자 메모 칸은 비어 있음): + +- 우리 줄 하나로 또렷(표기만 다름 — 별칭만 넣으면 됨) 65 줄: 2 · 18 · 26 → MT000467 / 5 · 25 → MT000470 / 19 → MT000472 / 15 · 17 → MT000209 / 16 · 50 · 52 · 20 → MT000018 / 21 · 65 → MT000499 / 3 · 7 · 51 · 53 → MT000393 / 10 → MT009202 / 27 · 63 → MT007111 / 28 → MT005677 / 31 → MT005687 / 35 · 68 → MT006544 / 37 → MT002926 / 62 · 85 → MT002861 / 87 → MT002859 / 40 · 95 → MT003202 / 96 → MT003241 / 42 · 54 → MT005749 / 44 · 94 → MT000481 / 47 → MT000487 / 55 · 74 → MT003163 / 73 → MT003165 / 56 → MT003166 / 66 · 84 → MT000453 / 67 → MT007130 / 71 → MT023493 / 72 → MT023491 / 77 → MT023654 / 78 → MT023655 / 75 → MT002536 / 82 → MT006490 / 86 → MT006540 / 89 → MT015883 / 91 → MT015887 / 90 → MT007025 / 92 → MT007032 / 98 → MT003311 / 100 → MT003372 / 57 → MT003398 / 4 → MT006763 / 49 → MT006665 / 48 → MT006667 / 33 · 79 · 81 → MT006664 / 83 → MT006788 (번호 = 시트 행 차례 · 머리 뺀 1 ~ 100) +- 사람이 골라야 함(우리 줄 여럿 · 규격이 조금 다름) 31 줄: 1 접착제 · 6 결속선(보통철선 대 어닐링철선) · 13 · 14 · 23 · 24 · 58 · 59 종자 · 32 미송(판재) · 45 철물 · 70 어닐링철선 #6 · 36 PVC용접봉 · 69 용접봉(연강용) · 29 BUTTON BIT · 41 표지판지주 3.5M · 64 강관비계 6m · 93 잔디 · 22 에폭시수지 · 46 각재(말뚝) · 76 보조강재 · 97 공사안내표지판 · 99 윙카호스 · 11 · 12 낙석방지책 · 38 혼합골재 · 61 코어비트 · 30 샹크 · 34 유기질퇴비 · 60 우드칩 · 80 부산물비료 · 88 휠라 +- 잇지 않음 · 없음 4 줄: 8 파형강관 · 39 이형철근(「별도계상」 = 자리만) · 9 금강사 · 43 떼 +- 못 이은 까닭 = 정확 일치만 잇는 규칙(이름 낱말 차례 「유로폼(패널)」 ↔ 「유로폼패널」 · 「내수합판1급」 ↔ 「합판(내수)」 · 규격 표기 12mm ↔ 12t · 차례 뒤집힘 T5×200 ↔ 200×5T · 덧글 KSM · 국산 · 지역 꼬리) · 가까운 줄 제안이 틀린 것도 있음(신나 → 신나무 · 중하중그레이팅 → 다른 치수). +- 구글 시트 직접 쓰기 토큰 만료(invalid_grant) — 사용자가 데스크탑에 있어 랩탑 로그인 창을 못 누름 · 읽기는 드라이브 커넥터로 됨. diff --git a/docs/raw/요구_1104/사용자요구_1104.md b/docs/raw/요구_1104/사용자요구_1104.md index 90a6becbb..5e0688e2a 100644 --- a/docs/raw/요구_1104/사용자요구_1104.md +++ b/docs/raw/요구_1104/사용자요구_1104.md @@ -902,3 +902,18 @@ b3 품셈 원문에 있는데 누락된 것만 추가하면 된다는거지? 1. 다음으로 너가 공유해준 엑셀파일을 구글 스프레드 시트로 가져와 수동연결(자재)탭과 수동연결(기계)탭으로 넣었고 기계와 관련해서는 해당 행의 메모에 의견을 작성해 뒀음. 이때 벌써 별칭으로 연결된 정보도 있었고 간단한 텍스트 검색으로도 분류가 되는 경우가 있어. 확인해봐. 2. 재료에 대한 메모 의견은 다시 한번 너도 직접 일어봐봐. 읽어보고 대화하자. 대부분 연결되는 것글이 많은 것같은데? + +## 요구 773 (11-11 · 사용자 · 1 크롤러드릴 기본 110kW · 2 커터 320~440 인정 → 우리 320~400 · 3 크레인(트럭) = 크레인(타이어) · 값 비교로 잇지 말고 로직으로 판단 · 4 콘크리트펌프용 파이프 = 손료 — 어떤 장비 손료인지 확인 · 5 자재: 표기 다름은 분석 엔진 개선 · 종자는 로직 개선으로 찾을 수 있을 듯(종자 & 초본류 조회) · 별도계상은 단가산출 뒤 연결) + +1. 크롤러는 기본 110kw로 지정 +2. 커터는 320~440 인정, 우리 자료의 320~400으로 지정 +3. 그럼 크레인 타이어가 맞지. (대신 값을 비교해서 연결하면 문제가 됨. 값은 업데이트 되기때문 과거 자료일수록 더 값이 안맞음. 그러니 로직으로 판단하게 되어야함. 굴삭기가 그렇게 되어 있을것으로 판단됨. ) +4. 콘크리트펌프용 파이프는 손료가 맞는것같음. 어떤 장비의 손료인지. 확인 +5. 자재에서 + - 표기 다름은 잘 찾도록 분석엔진 개선 + - 사람이 골라야하는 정보들 중 종자 같은건 로직 개선치 찾을 수 있을것 같음. 종자 & 초본류로 조회해봐. + - 별도계상은 단가산출에서는 원가를 합산하지는 않지만 나중에 프로젝트 내부에서는 연결이 되어야함. 그러니 별도계상은 항목도 연결이 불가능에 가까움. 사용자가 별도계상하더라도 옵션은 단가산출을 만든 후 연결하게 해야함. 벌써 반영되어 있을것으로 예상 + +## 요구 774 (11-11 · 사용자 · 별칭은 사용자가 지정 · 브레인은 분석 엔진 업데이트에 집중) + +그리고 별칭은 내가 지정할거야. 너는 분석 엔진 업데이트에 집중해줘. diff --git a/resources/master_data/_키대장.json b/resources/master_data/_키대장.json index fedf6f6d6..84f61f7b8 100644 --- a/resources/master_data/_키대장.json +++ b/resources/master_data/_키대장.json @@ -1,5 +1,5 @@ { - "다음": {"LB": 409, "EQ": 655, "RT": 20, "MN": 7000, "MT": 30719, "MO": 74, "MP": 364, "FX": 6, "CF": 159, "QF": 477, "GF": 337, "CC": 528, "GC": 1195, "QC": 2060, "GX": 5, "UA": 38}, + "다음": {"LB": 409, "EQ": 656, "RT": 20, "MN": 7000, "MT": 30719, "MO": 74, "MP": 364, "FX": 6, "CF": 159, "QF": 477, "GF": 337, "CC": 528, "GC": 1195, "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)"}, "키": { "CC000001": {"원문번호": "공통 1-3-1 콘크리트 및 포장용 재료", "파일": "계수_건설품셈_01장_적용기준.json"}, @@ -1341,6 +1341,7 @@ "EQ000652": {"원문번호": "2-2-11 부착용집게(0.2~0.8㎥)", "파일": "기계.json"}, "EQ000653": {"원문번호": "2-2-11 트럭탑재형크레인", "파일": "기계.json"}, "EQ000654": {"원문번호": "2-2-11 타이어형크레인", "파일": "기계.json"}, + "EQ000655": {"원문번호": "10-9 덤프트럭(4륜구동) 1ton", "파일": "기계.json"}, "FX000001": {"원문번호": "0000001", "파일": "환율_한국은행환율.json"}, "FX000002": {"원문번호": "0000002", "파일": "환율_한국은행환율.json"}, "FX000003": {"원문번호": "0000003", "파일": "환율_한국은행환율.json"}, diff --git a/resources/master_data/기계.json b/resources/master_data/기계.json index 0377d698a..651076b64 100644 --- a/resources/master_data/기계.json +++ b/resources/master_data/기계.json @@ -39697,6 +39697,25 @@ "값": {}, "출처": {}, "비고": "「건설공사 표준품셈 공통부문, 8-3-3 [20]운반 및 하역기계, (2104)크레인(타이어)(2025)」 적용" + }, + { + "키": "EQ000655", + "원문번호": "10-9", + "원문": "산림품셈", + "구분": "임업기계", + "상세구분": "덤프트럭", + "이름": "덤프트럭(4륜구동)", + "규격": "1ton", + "단위": { + "가격": "천원" + }, + "값": { + "가격": 28000 + }, + "출처": { + "가격": "산림품셈 10-9" + }, + "비고": "원문 이름: 4륜구동 1톤 덤프트럭 · 중기가격 = 조달청 등재가격(기본값 28,000 천원 = EST 2026-07 「덤프트럭 1.0Ton」 · 바꿀 수 있음) · 작업량은 건설품셈 · 손료 및 운전경비 = 2.5톤 덤프트럭(0602-0025) · 주 연료 = 2.5톤의 80% · 시간당 경비 = GF000145" } ] } diff --git a/resources/master_data/로직_산림품셈_10장_자재․장비_운반.json b/resources/master_data/로직_산림품셈_10장_자재․장비_운반.json index 9bad8e51b..d507f13ad 100644 --- a/resources/master_data/로직_산림품셈_10장_자재․장비_운반.json +++ b/resources/master_data/로직_산림품셈_10장_자재․장비_운반.json @@ -522,7 +522,7 @@ "부품": { "갈래": "기계경비식" }, "개정": [2026], "소유": "공용", - "비고": "손료·운전경비는 2.5톤(0602-0025) · 주연료 2.5톤의 80% · 중기가격 조달청 등재가격은 요소 없음 · 작업량(건설품셈 덤프트럭 식)·10-9-1 운반량 쓰는 식 요소 없음 · 주② 제잡비 비율 원문에 없음", + "비고": "손료·운전경비는 2.5톤(0602-0025) · 주연료 2.5톤의 80% · 중기가격 조달청 등재가격 = 기계표 EQ000655 덤프트럭(4륜구동) 1ton 가격 · 작업량(건설품셈 덤프트럭 식)·10-9-1 운반량 쓰는 식 요소 없음 · 주② 제잡비 비율 원문에 없음", "입력": [ { "이름": "지역", @@ -531,7 +531,7 @@ } ], "중간": [ - { "이름": "손료", "식": "버림(EQ000069.가격 * 1000 * (EQ000069.상각비계수 + EQ000069.정비비계수 + EQ000069.관리비계수) / 10000000, 0)", "출처": "산림품셈 10-9 · 건설품셈 공통 8-1-5 12" }, + { "이름": "손료", "식": "버림(EQ000655.가격 * 1000 * (EQ000069.상각비계수 + EQ000069.정비비계수 + EQ000069.관리비계수) / 10000000, 0)", "출처": "산림품셈 10-9 · 건설품셈 공통 8-1-5 12" }, { "이름": "비율", "식": "찾기(QF000330, 구분='2.5톤 덤프 주 연료 대비').비율", "출처": "산림품셈 10-9" }, { "이름": "직종", "식": "EQ000069.조종원직종" }, { "이름": "시간환산", "식": "찾기(CC000336, 구분='시간환산').분자 / 찾기(CC000336, 구분='시간환산').분모", "출처": "건설품셈 공통 1-1-3 2(일일 작업시간 8시간)" } diff --git a/resources/master_data/수식문서/수식_산림품셈_10장_자재․장비_운반.json b/resources/master_data/수식문서/수식_산림품셈_10장_자재․장비_운반.json index 793a302ac..4b28f9a92 100644 --- a/resources/master_data/수식문서/수식_산림품셈_10장_자재․장비_운반.json +++ b/resources/master_data/수식문서/수식_산림품셈_10장_자재․장비_운반.json @@ -482,7 +482,7 @@ {"열쇠": "비율", "기호": "r", "아래": "비율", "위": "", "이름": "비율", "단위": "", "출처": "산림품셈 10-9", "연결": {"갈래": "표", "표": "QF000330", "조건": {"구분": "'2.5톤 덤프 주 연료 대비'"}, "칸": "비율"}}, {"열쇠": "직종", "기호": "S", "아래": "직종", "위": "", "이름": "직종", "단위": "", "연결": {"갈래": "요소", "키": "EQ000069", "칸": "조종원직종"}}, {"열쇠": "시간환산", "기호": "Q", "아래": "시간환산", "위": "", "이름": "시간환산", "단위": "", "출처": "건설품셈 공통 1-1-3 2(일일 작업시간 8시간)", "연결": {"갈래": "식"}}, - {"열쇠": "P_덤프트럭", "기호": "P", "아래": "덤프트럭", "위": "", "이름": "EQ000069.가격", "단위": "", "연결": {"갈래": "요소", "키": "EQ000069", "칸": "가격"}}, + {"열쇠": "P_덤프트럭", "기호": "P", "아래": "덤프트럭", "위": "", "이름": "EQ000655.가격", "단위": "", "연결": {"갈래": "요소", "키": "EQ000655", "칸": "가격"}}, {"열쇠": "k_덤프트럭", "기호": "k", "아래": "덤프트럭", "위": "", "이름": "EQ000069.상각비계수", "단위": "", "연결": {"갈래": "요소", "키": "EQ000069", "칸": "상각비계수"}}, {"열쇠": "k_덤프트럭2", "기호": "k", "아래": "덤프트럭2", "위": "", "이름": "EQ000069.정비비계수", "단위": "", "연결": {"갈래": "요소", "키": "EQ000069", "칸": "정비비계수"}}, {"열쇠": "k_덤프트럭3", "기호": "k", "아래": "덤프트럭3", "위": "", "이름": "EQ000069.관리비계수", "단위": "", "연결": {"갈래": "요소", "키": "EQ000069", "칸": "관리비계수"}}, diff --git a/resources/tester/test_812_9_machine_link.py b/resources/tester/test_812_9_machine_link.py index 036778072..cf0985253 100644 --- a/resources/tester/test_812_9_machine_link.py +++ b/resources/tester/test_812_9_machine_link.py @@ -1,7 +1,7 @@ """812-9 지킴 — 가져온 기계 잇기(`M02_Machine_Find` · 요구 718 · 719). (a) 기계표 전체에서 찾음 — 낱말표 밖 기종(로우더 · 공기 압축기 · 램 머 · 라인마커 …) · 후보 여럿이던 것 - (물탱크 · 크레인(무한궤도) · 머캐덤 · 콘크리트 펌프차 …) · 지어 맞추기 없음(1.0Ton = 우리 표에 없음) + (물탱크 · 크레인(무한궤도) · 머캐덤 · 콘크리트 펌프차 …) · 지어 맞추기 없음(3.0Ton = 우리 표에 없음) (b) 표기 정규화 · 괄호 낱말(무한궤도 · 타이어 · 일반용 · 표에 없는 낱말 발파 = 안 봄) · 범위 · 복수 규격 (c) 조합 기계 = 둘(대형브레이카 +굴착기 · 0.7+브레이카 · +부착용집게 · +진동콤팩터 · 덤프트럭(자동덮개)) (d) 별칭 먼저 — M01 기계 줄 「별칭」 칸(815-1 · 시험 안 임시 별칭) · 이름 + 규격 통째 = 그 EQ · 이름만 = @@ -104,7 +104,7 @@ def test_master_alias(name: str, spec: str, eq: str) -> None: def test_no_guess() -> None: """우리 표에 없는 규격 = 못 찾음(가까운 규격으로 안 이음) · 기종 모름 = 별칭 몫 · 여럿 = 여럿.""" - got = mf.find("덤프트럭", "1.0Ton") + got = mf.find("덤프트럭", "3.0Ton") assert got["판정"] == mf.NONE and got["까닭"] == "우리 표에 없음(규격)" and got["키"] is None assert got["후보"][0]["규격"] == "2.5ton" # 보여주기만 — 가까운 규격 먼저 for name, spec in (("에어 호스", "1.91cm"), ("모노펌프", "5-20㎥/hr")): # 승인 전 = 별칭 몫 @@ -113,7 +113,7 @@ def test_no_guess() -> None: got = mf.find("크레인(트럭)", "10Ton") # 「트럭」 = 기계표 괄호에 없는 낱말 → 안 봄 assert got["판정"] == mf.MANY and got["수"] == 2 assert mf.mark(got, "크레인(트럭)", "10Ton").startswith("참고 · 기계 후보 2 — 고르기") - assert "기계 못 찾음" in mf.mark(mf.find("덤프트럭", "1.0Ton"), "덤프트럭", "1.0Ton") + assert "기계 못 찾음" in mf.mark(mf.find("덤프트럭", "3.0Ton"), "덤프트럭", "3.0Ton") assert mf.mark(mf.find("물탱크", "5500ℓ"), "물탱크", "5500ℓ") is None diff --git a/resources/tester/test_816_1_dump_1ton.py b/resources/tester/test_816_1_dump_1ton.py new file mode 100644 index 000000000..2d60b8358 --- /dev/null +++ b/resources/tester/test_816_1_dump_1ton.py @@ -0,0 +1,85 @@ +"""816-1 지킴 — 기계표 「덤프트럭(4륜구동) 1ton」(산림품셈 10-9 · 요구 769-1 · 770-1). + +(a) 기계표 줄 · 값 — 원문 산림품셈 10-9 · 가격 28,000 천원(조달청 등재가격 기본값) · 키대장 +(b) GF000145(4륜구동 1톤 덤프트럭 시간당 기계경비)가 그 줄 가격을 읽음 · 계수 · 연료 · 조종원은 2.5 ton +(c) 잇기 — 가져온 「덤프트럭 1.0Ton · 1톤 · 1ton」 → 새 줄 · 「덤프트럭 2.5ton」 → EQ000069 그대로 +(d) 시간당 경비 한 길 — `M02_Machine_Hourly.hourly` · `M02_Doc_Import.hourly_link` = GF000145 +""" + +from __future__ import annotations + +import importlib +import sys +from decimal import Decimal +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[2] +for p in (ROOT, ROOT / "resources/master_data/scripts"): + if str(p) not in sys.path: + sys.path.insert(0, str(p)) + +from M01_MasterData import M01_MasterData_Store as m01 # noqa: E402 +from M02_MasterTemplete import M02_Doc_Import as di # noqa: E402 +from M02_MasterTemplete import M02_Machine_Find as mf # noqa: E402 +from M02_MasterTemplete import M02_Machine_Hourly as mh # noqa: E402 + +ml = importlib.import_module("master_doc_link") +mc = importlib.import_module("master_doc_calc") +NEW, OLD = "EQ000655", "EQ000069" + + +def _whole(): + return m01.loaded()[1] + + +def _docs() -> dict: + return ml.load_all() + + +def test_row() -> None: + row = _whole().get(NEW) + assert (row["원문"], row["원문번호"], row["상세구분"]) == ("산림품셈", "10-9", "덤프트럭") + assert (row["이름"], row["규격"]) == ("덤프트럭(4륜구동)", "1ton") + assert row["값"] == {"가격": 28000} and row["출처"]["가격"] == "산림품셈 10-9" + assert "4륜구동 1톤 덤프트럭" in row["비고"] + + +def test_gf145_reads_price() -> None: + doc = _docs()["GF000145"] + reads = {(v["연결"].get("키"), v["연결"].get("칸")) for v in doc["변수"]} + assert (NEW, "가격") in reads and (OLD, "가격") not in reads + assert { + (OLD, c) for c in ("상각비계수", "정비비계수", "관리비계수", "주연료", "조종원") + } <= reads + got = mc.calc(doc, ml.Links(_whole(), _docs())) + old = _whole().get(OLD)["값"] + loss = int(Decimal(28000 * 1000) * sum(Decimal(str(old[k])) for k in ("상각비계수", "정비비계수", "관리비계수")) / Decimal(10**7)) # fmt: skip + assert got["셈됨"] and got["경비"] == loss == 8307 + + +def test_find() -> None: + for spec in ("1.0Ton", "1톤", "1ton"): + got = mf.find("덤프트럭", spec) + assert got["키"] == NEW and got["판정"] == mf.LINKED, spec + assert mf.find("덤프트럭", "2.5ton")["키"] == OLD + assert mf.find("덤프트럭", "15Ton")["키"] == "EQ000074" + + +def test_hourly_one_way() -> None: + assert mh.logic_of("10-9")["키"] == "GF000145" + assert mh.logic_of("0602-0025")["키"] != "GF000145" # 2.5 ton = 일반 식 그대로 + got = mh.hourly(NEW) + doc = mc.calc(_docs()["GF000145"], ml.Links(_whole(), _docs())) + assert got["ok"] and got["로직"] == "GF000145" + assert [got[k] for k in ("노무비", "재료비", "경비", "계")] == [float(doc[k]) for k in ("노무비", "재료비", "경비", "계")] # fmt: skip + link = di.hourly_link(NEW, "경비") + assert link["키"] == "GF000145" and "기계" not in link["입력"] and link["칸"] == "경비" + + +def test_gf283_option() -> None: + """10-9-1 덤프트럭 운반 「1톤 4륜구동」 옵션 = GF000145 값으로 셈.""" + links = ml.Links(_whole(), _docs()) + one = mc.calc(_docs()["GF000283"], links, {"덤프트럭": "1톤 4륜구동"}) + big = mc.calc(_docs()["GF000283"], links, {"덤프트럭": "0602-0025"}) + assert one["셈됨"] and big["셈됨"] and one["노무비"] == big["노무비"] # 조종원 = 2.5 ton + assert one["경비"] > big["경비"] # 손료 = 1 톤 가격 28,000 > 2.5 ton 21,982