fix(815-3): 합친 뒤 시험 셋 가름 · 시간당 경비 식 조종원 차례 · 호표 기계 글 머리 꼬리 · 합친 판 요약 다시 잼
- 809_1 이름 = 진짜 흠 + 낡은 기대 — 읽기기(812-1)가 지은 율 줄 이름 「율」이 엑셀 글 머리로 안 바뀜 → `Import_Shape._MADE` 에 율 더함 · 합계 = 차림 글줄 · 기계 = 한 줄(이름 · 규격 칸) 은 낡은 기대 고침 · 금액 15,935 · 336 · 723 · 16,994 그대로 - 812_9 별칭 = 낡은 기대 — 815-2 가 아스팔트페이버 별칭을 마스터 기계 줄 칸으로 옮겨 「넣기 전 못 찾음」 이 안 맞음 · 시험은 마스터 칸으로 봄 · 부르는 곳 없는 `M02_Machine_Find.learn`(옛 장부 쓰기) · `by_code` · `same_kind`(걷은 연결 찾기 몫) 지움 - 804_2 hourly = 낡은 기대 — 814-1 이 GC000268 목록을 117 → 209 로 늘려 겹친 116 대 고름이 GC000269 로 뒤집힘(116 대 모두 원 단위 같음) · 같은 로직 줄만 대던 시험 → 같은 갈래 식(부착 · 손료만 · 조종원) 줄 모두 댐 - 진짜 흠(브레인 갈래 가) — GC000272 「조종원 없는 기종」 목록에 기계표 조종원 1 인 9 대가 겹쳐 목록 길이 차례로 고름 → `logic_of` = 기계표 조종원 > 0 이면 조종원 호표 든 식 먼저 · 불러오기 `hourly_link` 도 같은 길 · 바뀐 4 대 = 진동롤러(핸드가이드식) 0.7ton 6,557 → 41,969 · 래머 80kg 1,959 → 23,708 · 플레이트 콤팩터 1.5ton 2,855 → 24,604 · 발전기 100kW 45,535 → 67,284(M01 문서 금액 그대로) · 시험에 9 대 굳힘 - 778_5 기계 표 = 진짜 흠 — 812-9 찾기가 호표 기계 글 「운 반 : 덤프트럭(4.5Ton)」 · 「…[hr] : 90%」 · 「(90%)」 머리 꼬리를 안 뗌 → `Hopyo_Fixed._eqs` 쌍점 조각 · 율 꼬리 뗌 · 이어짐 187 · 고를 것 1 · 못 이음 2(조합 한 줄 · 괄호 깨짐) · 모두 이음 블록 161 - 721 단추 자리 = 낡은 기대(808-1 [단가 갱신][재생성] tools 더함) - 815-1 보고 요약에 「합친 뒤」 열 — 기계 이음 95.7 % · 우리 값 원파일 1,891 · 0 원 줄 블록 147 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -193,10 +193,9 @@ def hourly_link(eq: str, part: str) -> dict | None:
|
||||
if part not in imp.COSTS or not imp.hourly_of(eq).get("ok"):
|
||||
return None
|
||||
code = str(imp._whole().get(eq).get("원문번호") or "")
|
||||
fit = [r for r in machine._family() if code in [str(c) for c in machine._codes(r)]]
|
||||
if not fit:
|
||||
logic = machine.logic_of(code)
|
||||
if not logic:
|
||||
return None
|
||||
logic = min(fit, key=machine._rank)
|
||||
given = {"기계": _lit(code)}
|
||||
for spec in logic.get("입력") or []:
|
||||
if spec.get("이름") != "기계":
|
||||
|
||||
@@ -16,7 +16,8 @@ from decimal import Decimal
|
||||
from typing import Any
|
||||
|
||||
COSTS = ("노무비", "재료비", "경비")
|
||||
_MADE = re.compile(r"^(?:줄|노무비|재료비|경비|계|소계|합계)?_\d+$")
|
||||
# 지은 이름 — 「줄_2 · 노무비_2」 · 읽기기 율 줄 「율」
|
||||
_MADE = re.compile(r"^(?:(?:줄|노무비|재료비|경비|계|소계|합계)?_\d+|율(?:_\d+)?)$")
|
||||
_SECTION = re.compile(r"^\s*\d+\s*\.\s*(.+?)\s*$")
|
||||
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ from M02_MasterTemplete import M02_Machine_Find as mfind
|
||||
COSTS = ("노무비", "재료비", "경비")
|
||||
_BASE = re.compile(r"(?<!주)(노무비|재료비|경비|인건비)\s*의")
|
||||
GAP = Decimal(1) # 밑수 · 단가 같음 판정 끝수(원)
|
||||
_RATE = re.compile(r"\s*\(\s*\d+(?:\.\d+)?\s*%\s*\)\s*$") # 「…[hr] (90%)」 꼬리
|
||||
|
||||
|
||||
_d, _plain = fixed._num, fixed._plain
|
||||
@@ -116,7 +117,12 @@ class Linker:
|
||||
name, spec = mm_plain(line.get("이름")), mm_plain(line.get("규격"))
|
||||
same = [c for c, n, s in self.machines if n == name and s == spec]
|
||||
if len(same) != 1:
|
||||
got = mfind.find(line.get("이름"), line.get("규격"))
|
||||
text = str(line.get("이름") or "")
|
||||
# 엑셀 호표 글 「운 반 : 덤프트럭(4.5Ton)」 · 「굴착기(…)[hr] : 90%」 = 쌍점 조각마다
|
||||
parts = [text, *(text.split(":") if ":" in text else [])]
|
||||
tries = [mfind.find(_RATE.sub("", p).strip(), line.get("규격")) for p in parts]
|
||||
got = next((g for g in tries if g["판정"] in (mfind.LINKED, mfind.ALIAS)), None)
|
||||
got = got or next((g for g in tries if g["판정"] != mfind.NONE), tries[0])
|
||||
same = [] if got["판정"] == mfind.NONE else [c["키"] for c in got["후보"]]
|
||||
return same
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"""M02 기계 찾기(PLAN 812-9 · 요구 718 · 719) — 가져온 기계 글(이름 · 규격) → 우리 EQ · 서버 단독.
|
||||
|
||||
과녁 = M01 기계표 전체(EQ) · 부르는 곳 = 불러오기 이음(`M02_Hopyo_Row.m01_picks` · `M02_San_Emit._m01`) ·
|
||||
일위대가 호표(`M02_Hopyo_Elem.machine(s)` · `M02_Hopyo_Fixed._eqs`) · 연결 찾기(`M02_Doc_Match_Note`).
|
||||
일위대가 호표(`M02_Hopyo_Elem.machine(s)` · `M02_Hopyo_Fixed._eqs`).
|
||||
차례:
|
||||
1. 별칭(M01 기계 줄 「별칭」 칸 · 815-1 `M02_Elem_Alias`) — 「이름 규격」 통째 별칭 = 그 EQ(여럿 =
|
||||
후보 여럿) · 이름만 별칭 = 그 EQ 기종으로 바꿔 2 로
|
||||
@@ -159,12 +159,6 @@ def table() -> tuple[list[Row], frozenset[str], dict[str, Row]]:
|
||||
return _SEEN[1]
|
||||
|
||||
|
||||
def by_code(code: Any) -> str | None:
|
||||
"""원문번호 → EQ 키."""
|
||||
want = str(code or "").strip("'\"")
|
||||
return next((r.key for r in table()[0] if r.raw.get("원문번호") == want), None)
|
||||
|
||||
|
||||
def kind_rows(base: str) -> list[Row]:
|
||||
"""기종 글 → EQ 줄 — 이름 · 괄호 붙임 같음 › 상세구분 같음 › 그 글을 품음(첫 층만)."""
|
||||
if len(base) < 2:
|
||||
@@ -320,47 +314,3 @@ def mark(got: dict[str, Any], name: Any, spec: Any) -> str | None:
|
||||
if got["판정"] == NONE:
|
||||
return f"{NOTE}기계 못 찾음 — {said} {got['까닭']}"
|
||||
return None
|
||||
|
||||
|
||||
def same_kind(a: Any, b: Any) -> bool | None:
|
||||
"""두 기계 이름이 같은 기종인지(연결 찾기) — 둘 다 기종을 찾으면 판정 · 아니면 None."""
|
||||
found = []
|
||||
for t in (a, b):
|
||||
named = alias(t, "")
|
||||
row = table()[2].get(named[0]) if len(named) == 1 else None
|
||||
found.append(kind_rows(row.base if row else split_name(t)[0]))
|
||||
if not all(found):
|
||||
return None
|
||||
return bool({r.base for r in found[0]} & {r.base for r in found[1]})
|
||||
|
||||
|
||||
# ── 고른 것 → 별칭 장부(저장 때) ──────────────────────────────────────
|
||||
def learn(doc: Any, who: Any) -> int:
|
||||
"""가져온 식 문서 [저장] — 기계 줄에 사람이 고른 EQ(찾기 판정과 다름) = 지금 층 별칭 장부 줄
|
||||
(갈래 기계 · 열쇠 「이름|규격|단위」) → M01 별칭 장부 후보로 모임(승인은 M01) · 쓴 줄 수."""
|
||||
from M02_MasterTemplete import M02_Doc_Copy as dc
|
||||
from M02_MasterTemplete import M02_Hopyo_Ledger as ledger
|
||||
from M02_MasterTemplete import M02_MasterTemplete_Store as store
|
||||
|
||||
head = (doc or {}).get("가져온") if isinstance(doc, dict) else None
|
||||
if not isinstance(head, dict) or not isinstance(head.get("기계"), list):
|
||||
return 0
|
||||
by_id = {dc.md.var_id(v): v for v in doc.get("변수") or [] if isinstance(v, dict)}
|
||||
rows: dict[str, dict] = {}
|
||||
for one in head["기계"]:
|
||||
link = ((by_id.get(str((one or {}).get("기호"))) or {}).get("연결")) or {}
|
||||
code = (link.get("입력") or {}).get("기계") if link.get("갈래") == "단가산출" else None
|
||||
eq = by_code(code)
|
||||
origin = one.get("원래") or {}
|
||||
if not eq or eq == one.get("키") or not origin.get("이름"):
|
||||
continue
|
||||
if alias(origin["이름"], origin.get("규격")) == [eq]: # 이미 장부에 같은 짝
|
||||
continue
|
||||
plain = {"품명": str(origin["이름"]), "규격": str(origin.get("규격") or ""),
|
||||
"단위": str(origin.get("단위") or "hr")} # fmt: skip
|
||||
full = ledger.key({"이름": plain["품명"], "규격": plain["규격"], "단위": plain["단위"]})
|
||||
pair = {"갈래": "기계", "키": eq, "입력값": {}, "배": 1}
|
||||
rows[full] = {"원래": plain, "갈래": "짝", "짝": [pair]}
|
||||
if rows:
|
||||
ledger.put(store.root(), rows, who)
|
||||
return len(rows)
|
||||
|
||||
@@ -41,10 +41,30 @@ def _rank(row: dict) -> tuple:
|
||||
return (attach, loss, loss and "보정작업" in names, len(_codes(row)), str(row.get("키")))
|
||||
|
||||
|
||||
def _operated(code: str) -> bool:
|
||||
"""기계표(원문 8-4) 조종원 > 0 — 그 원문번호 기계 가운데 하나라도."""
|
||||
rows = store.loaded()[1].index.get("EQ", {}).values()
|
||||
return any(
|
||||
str(r.get("원문번호")) == code and float((r.get("값") or {}).get("조종원") or 0) > 0
|
||||
for r in rows
|
||||
)
|
||||
|
||||
|
||||
def logic_of(code: str) -> dict | None:
|
||||
"""기계 원문번호 → 그 기계 시간당 경비 로직(짝 차례 첫째) · 없으면 None(813-2 M01 화면도 씀)."""
|
||||
"""기계 원문번호 → 그 기계 시간당 경비 로직(짝 차례 첫째) · 없으면 None(813-2 M01 화면 ·
|
||||
불러오기 `M02_Doc_Import.hourly_link` 도 씀). 기계표 조종원 > 0 = 조종원 호표 있는 식 먼저
|
||||
(「조종원 없는 기종」 목록에 겹친 기계 — 진동롤러(핸드가이드식) · 고소작업차 …)."""
|
||||
fit = [r for r in _family() if code in [str(c) for c in _codes(r)]]
|
||||
return min(fit, key=_rank) if fit else None
|
||||
if not fit:
|
||||
return None
|
||||
op = _operated(code)
|
||||
|
||||
def order(row: dict) -> tuple:
|
||||
has = any(x.get("이름") == "조종원" for x in row.get("호표") or [])
|
||||
rank = _rank(row)
|
||||
return (*rank[:3], op and not has, *rank[3:])
|
||||
|
||||
return min(fit, key=order)
|
||||
|
||||
|
||||
def hourly(key: str) -> dict[str, Any]:
|
||||
|
||||
@@ -7,18 +7,26 @@
|
||||
|
||||
## 요약
|
||||
|
||||
| 잣대 | 전(814-1 뒤) | 후(815-1) | 판정 |
|
||||
|---|---|---|---|
|
||||
| 금액(엑셀 단가 그대로 셈 = 원본) | 원파일 2,220 · 엑셀 1,021 = 100 % | 같음 100 % | 그대로 |
|
||||
| 못 읽음 표지 | 0 | 0 | 그대로 |
|
||||
| 인력 · 형제 · 유가 이음 | 100 % · 100 % · 100 % | 같음 | 그대로 |
|
||||
| 기계 이음 | 95.7 %(4,601 / 4,807) | 94.9 %(4,564) | 옛 마스터 별칭 다섯이 아직 기계 줄 「별칭」 칸에 안 옮겨짐(815-2 몫) — 옮기면 37 줄 돌아와 95.7 % |
|
||||
| 재료 이음 | 87.6 %(1,784 / 2,036) | **88.0 %**(1,792) | 표기 맞추기로 8 줄 더 |
|
||||
| 못 이은 재료 | 252 줄 · 105 종 | **244 줄 · 100 종** | 다섯 종 풀림 |
|
||||
| 견적 · 운임 · 수수료 줄 | 59 줄 = 「갈래 밖」 못 이음 | **59 줄 = 「견적」 그대로**(못 이음에서 뺌) | 우리 값 있는 자재로 이어진 것 0 |
|
||||
| [우리 단가로] 모두 우리 값 | 원파일 1,899(85.5 %) · 엑셀 814(79.7 %) | 원파일 1,853(83.5 %) + 견적만 남음 19 · 엑셀 815(79.8 %) + 12 | 아래 「줄어든 까닭」 |
|
||||
| [우리 단가로] 0 원 줄 있는 블록 | 원파일 115 · 엑셀 4 | 원파일 155 · 엑셀 9 | 아래 「줄어든 까닭」 |
|
||||
| 차림 왕복 · 시험 | 100 % | 100 %(812-3 · 810-2 · 810-3 통과) | 그대로 |
|
||||
| 잣대 | 전(814-1 뒤) | 후(815-1) | 합친 뒤(815-1 + 815-2 + 815-3) | 판정 |
|
||||
|---|---|---|---|---|
|
||||
| 금액(엑셀 단가 그대로 셈 = 원본) | 원파일 2,220 · 엑셀 1,021 = 100 % | 같음 100 % | 같음 100 % | 그대로 |
|
||||
| 못 읽음 표지 | 0 | 0 | 0 | 그대로 |
|
||||
| 인력 · 형제 · 유가 이음 | 100 % · 100 % · 100 % | 같음 | 같음 | 그대로 |
|
||||
| 기계 이음 | 95.7 %(4,601 / 4,807) | 94.9 %(4,564) | **95.7 %(4,601)** — 다섯 칸 옮김으로 37 줄 돌아옴 | 옛 마스터 별칭 다섯이 아직 기계 줄 「별칭」 칸에 안 옮겨짐(815-2 몫) — 옮기면 37 줄 돌아와 95.7 % |
|
||||
| 재료 이음 | 87.6 %(1,784 / 2,036) | **88.0 %**(1,792) | 88.0 %(1,792) | 표기 맞추기로 8 줄 더 |
|
||||
| 못 이은 재료 | 252 줄 · 105 종 | **244 줄 · 100 종** | 244 줄 · 100 종 | 다섯 종 풀림 |
|
||||
| 견적 · 운임 · 수수료 줄 | 59 줄 = 「갈래 밖」 못 이음 | **59 줄 = 「견적」 그대로**(못 이음에서 뺌) | 59 줄 = 「견적」 그대로 | 우리 값 있는 자재로 이어진 것 0 |
|
||||
| [우리 단가로] 모두 우리 값 | 원파일 1,899(85.5 %) · 엑셀 814(79.7 %) | 원파일 1,853(83.5 %) + 견적만 남음 19 · 엑셀 815(79.8 %) + 12 | 원파일 **1,891(85.2 %)** + 19 · 엑셀 815(79.8 %) + 12 | 아래 「줄어든 까닭」 |
|
||||
| [우리 단가로] 0 원 줄 있는 블록 | 원파일 115 · 엑셀 4 | 원파일 155 · 엑셀 9 | 원파일 **147** · 엑셀 9 | 아래 「줄어든 까닭」 |
|
||||
| 차림 왕복 · 시험 | 100 % | 100 %(812-3 · 810-2 · 810-3 통과) | 100 % | 그대로 |
|
||||
|
||||
### 합친 뒤 달라진 수(815-3 · 같은 자로 다시 잼)
|
||||
|
||||
- 기계 이음 94.9 → **95.7 %** — 815-2 가 옛 마스터 별칭 다섯을 기계 줄 「별칭」 칸으로 옮김 · 못 찾음(별칭 필요) 102 → 65 줄 · 풀린 기계 = 아스팔트페이버(피니셔) 1.7m · 3.0m · 버킷준설기 7.46kW · 바이브레이트 봉상후렉시블
|
||||
- [우리 단가로] 모두 우리 값(원파일) 1,853 → **1,891** — 엑셀 단가 남음 → 우리 값 30 블록(위 다섯 별칭) · 0 원 줄 → 우리 값 8 블록(H-PILE · POST-PILE — 발전기 조종원 노무비 참)
|
||||
- 0 원 줄 블록(원파일) 155 → **147** — 위 8 블록
|
||||
- 우리 계가 바뀐 블록 128(올라감 98 · 내려감 30) — 올라감 = 815-3 시간당 경비 식 고름(기계표 조종원 > 0 = 조종원 든 식 먼저 · 래머 80kg · 플레이트 콤팩터 1.5ton · 진동롤러(핸드가이드식) 0.7ton · 발전기 100kW · 예 EST 되메우기및다짐(램머) 1,569 → 6,535 · 엑셀 원본 10,141 쪽으로) · 내려감 = 별칭 이음 블록
|
||||
- 금액(엑셀 단가 그대로) · 재료 · 견적 · 차림 = 그대로
|
||||
|
||||
### 「모두 우리 값」이 줄어든 까닭(블록 옮김 전수)
|
||||
|
||||
@@ -71,7 +79,7 @@
|
||||
|
||||
| # | 내용 | 갈래 |
|
||||
|---|---|---|
|
||||
| 1 | 옛 마스터 기계 별칭 다섯이 칸으로 옮겨지기 전까지 기계 37 줄 · 30 블록 못 이음 | 815-2 옮김 뒤 풀림(시험은 칸이 비면 다섯을 임시로 넣어 봄) |
|
||||
| 1 | 옛 마스터 기계 별칭 다섯이 칸으로 옮겨지기 전까지 기계 37 줄 · 30 블록 못 이음 | **풀림**(합친 뒤 95.7 %) |
|
||||
| 2 | 치즐 0.7 · 0.4 등 우리 자재 줄 값 칸 빔 — 정확히 이으니 0 원 줄 102 → 153 | 자재표 보강(J 장 · 값 출처 미정) |
|
||||
| 3 | 견적 값묶음 줄 공식 칸에 「[object Object]」 글(814-1 전부터 · 값묶음 줄 꼴) | 화면 흠 · 이번 고침 밖 |
|
||||
| 4 | test_778_5 일위대가 기계 줄 표(이어짐 162 · 고를 것 3 · 못 이음 25)가 굳힌 수(180 · 10 · 0)와 다름 — 고치기 전 판도 같은 수(812-9 뒤부터) | 낡은 굳힘 수 · 이번 고침 무관 |
|
||||
| 4 | test_778_5 일위대가 기계 줄 표(이어짐 162 · 고를 것 3 · 못 이음 25)가 굳힌 수(180 · 10 · 0)와 다름 — 고치기 전 판도 같은 수(812-9 뒤부터) | **풀림(815-3)** — 진짜 흠: 호표 기계 글 「운 반 : 덤프트럭(4.5Ton)」 · 「…[hr] : 90%」 머리 · 꼬리를 812-9 찾기가 안 뗌 → 뗌 · 이어짐 187 · 고를 것 1 · 못 이음 2(조합 한 줄 · 괄호 깨짐) |
|
||||
|
||||
@@ -27,8 +27,8 @@ def _text(path: Path) -> str:
|
||||
def test_721_1_단추_이름과_자리():
|
||||
detail = _text(M02 / "M02_MasterTemplete_Sangeun_Detail.ts")
|
||||
assert (
|
||||
"children: [tabs.picker, addButton, rateButton]" in detail
|
||||
) # 750-2 안내 걷음 · 778-4 율 줄 추가 · 799-2 보기 고르기 = 수식 · 단가산출 상세 (`_Sangeun_Tabs`)
|
||||
"children: [tabs.picker, tabs.tools, addButton, rateButton]" in detail
|
||||
) # 750-2 안내 걷음 · 778-4 율 줄 추가 · 799-2 보기 · 808-1 [단가 갱신]
|
||||
assert "M02_SangeunPickBase" not in detail # 727-2 단추 걷음
|
||||
locale = _text(ROOT / "ui_template" / "ui_template_locale_m2.ts")
|
||||
assert "M02_SangeunPickBase" not in locale
|
||||
|
||||
@@ -26,13 +26,13 @@ from resources.tester.test_m02_hopyo_excel import URL, _post, client, master_has
|
||||
# 여덟 파일 불리는 블록 줄 연결 표(778-5 D-2 굳힘 · 바뀌면 까닭 커밋 글)
|
||||
TABLE = {
|
||||
"L": {"이어짐": 366, "고를 것": 0, "못 이음": 0},
|
||||
"X": {"이어짐": 180, "고를 것": 10, "못 이음": 0},
|
||||
"X": {"이어짐": 187, "고를 것": 1, "못 이음": 2}, # 812-9 찾기 · 못 이음 = 조합 · 괄호 깨짐
|
||||
"M": {"이어짐": 71, "고를 것": 55, "못 이음": 4},
|
||||
"R": {"이어짐": 150, "고를 것": 2, "못 이음": 0},
|
||||
"S": {"이어짐": 3, "고를 것": 0, "못 이음": 0},
|
||||
"E": {"이어짐": 1, "고를 것": 0, "못 이음": 0},
|
||||
}
|
||||
ALL_LINKED = 156
|
||||
ALL_LINKED = 161 # 815-3 호표 기계 글 쌍점 · 율 꼬리 뗌
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
|
||||
@@ -103,7 +103,7 @@ def test_금액_화면길_서버정본_전수(world):
|
||||
|
||||
|
||||
def _hourly_inputs(logic_key: str) -> dict:
|
||||
"""hourly 가 고른 로직 · 그 로직의 기본 입력(기계 밖)."""
|
||||
"""그 로직의 기본 입력(기계 밖)."""
|
||||
rows = {r["키"]: r for r in mh._family()}
|
||||
row = rows.get(logic_key)
|
||||
if not row:
|
||||
@@ -115,6 +115,31 @@ def _hourly_inputs(logic_key: str) -> dict:
|
||||
}
|
||||
|
||||
|
||||
def _kind(row: dict) -> tuple:
|
||||
return (*mh._rank(row)[:3], any(x.get("이름") == "조종원" for x in row.get("호표") or []))
|
||||
|
||||
|
||||
# 기계표 조종원 1 인 · 「조종원 없는 기종」 GC000272 목록에도 겹친 기계(815-3) — 조종원 든 식
|
||||
OPERATED = (
|
||||
"EQ000094",
|
||||
"EQ000111",
|
||||
"EQ000112",
|
||||
"EQ000454",
|
||||
"EQ000153",
|
||||
"EQ000154",
|
||||
"EQ000155",
|
||||
"EQ000195",
|
||||
"EQ000234",
|
||||
)
|
||||
|
||||
|
||||
def test_조종원_있는_기계_조종원_식():
|
||||
rows = {r["키"]: r for r in mh._family()}
|
||||
for key in OPERATED:
|
||||
h = mh.hourly(key)
|
||||
assert h["ok"] and h["노무비"] > 0 and _kind(rows[h["로직"]])[3], (key, h)
|
||||
|
||||
|
||||
def test_기계펼침_원단위_hourly(world):
|
||||
got = world.get("셈") or dict(zip(world["docs"], _ts("셈", list(world["cases"].values()))))
|
||||
eq = m01.loaded()[1].index["EQ"]
|
||||
@@ -123,7 +148,7 @@ def test_기계펼침_원단위_hourly(world):
|
||||
by_code.setdefault(str(row.get("원문번호")), []).append(key)
|
||||
lines = same_parent = same_hourly = 0
|
||||
memo: dict[str, dict] = {}
|
||||
family = mh._family()
|
||||
rows = {r["키"]: r for r in mh._family()}
|
||||
for k, g in got.items():
|
||||
for s in g["펼침"]:
|
||||
if s["갈래"] != "기계":
|
||||
@@ -139,14 +164,15 @@ def test_기계펼침_원단위_hourly(world):
|
||||
h = memo[key]
|
||||
if not h.get("ok"):
|
||||
continue
|
||||
pick = min(
|
||||
(r for r in family if code in [str(c) for c in mh._codes(r)]),
|
||||
key=mh._rank,
|
||||
)
|
||||
want = _hourly_inputs(pick["키"])
|
||||
pick = mh.logic_of(code)
|
||||
own = rows.get(s["키"])
|
||||
want = _hourly_inputs(s["키"])
|
||||
given = {n: str(v) for n, v in s["입력"].items() if n != "기계"}
|
||||
if pick["키"] != s["키"] or any(want.get(n) != v for n, v in given.items()):
|
||||
break # 다른 로직 · 다른 입력(조종원 직종 등)을 넘긴 줄
|
||||
# 같은 갈래 로직(부착 · 손료만 · 조종원 같음 — 268 · 269 겹친 기계 = 값 같음)
|
||||
if own is None or _kind(own) != _kind(pick):
|
||||
break # 조합(부착) · 손료만 · 조종원 없는 식을 고른 줄
|
||||
if any(want.get(n) != v for n, v in given.items()):
|
||||
break # 기본 밖 입력(조종원 직종 · 보정작업 등)을 넘긴 줄
|
||||
assert all(float(h[f]) == float(s[f]) for f in COSTS), (k, key, h, s)
|
||||
same_hourly += 1
|
||||
break
|
||||
|
||||
@@ -152,12 +152,11 @@ def test_imported_doc_names_and_machine_line(world) -> None:
|
||||
sk[imp.KEY] = {"로직": out["로직"], "단가기준": "엑셀", "원본": out["원본"]}
|
||||
new = dim.derive(sk)
|
||||
names = [x["이름"] for x in new["금액"]]
|
||||
assert "공구손료 및 잡재료비(노무비의 2%)" in names and "노무비 합계" in names and "계" in names
|
||||
assert not any(shp._MADE.match(n) for n in names) # 줄_2 · 노무비_2 · 계_2 없음
|
||||
crane = [x for x in new["금액"] if x["비목"] == "묶음"]
|
||||
assert [x["이름"] for x in crane] == ["트럭탑재형크레인 5Ton"] and crane[0]["번지"]
|
||||
assert "번지.트럭탑재형크레인.경비" in next(
|
||||
x["단가"] for x in new["금액"] if x["이름"] == "경비 합계"
|
||||
)
|
||||
assert "공구손료 및 잡재료비(노무비의 2%)" in names # 읽기기 지은 「율」 → 엑셀 글 머리
|
||||
assert not any(shp._MADE.match(n) for n in names) # 줄_2 · 율 · 노무비_2 · 계_2 없음
|
||||
# 812-1 읽기기 — 합계 = 차림 글줄(금액 줄 아님) · 기계 = 한 줄(이름 · 규격 칸 따로)
|
||||
assert "노무비 합계" not in names and "계" not in names
|
||||
crane = [x for x in new["금액"] if x.get("비목") == "묶음"]
|
||||
assert [(x["이름"], x.get("규격")) for x in crane] == [("트럭탑재형크레인", "5Ton")]
|
||||
got = dim.run(new, sk)
|
||||
assert (got["노무비"], got["재료비"], got["경비"], got["계"]) == (15935, 336, 723, 16994)
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
# ruff: noqa: F811 — 임시 층 fixture(world)를 test_m02_labor_ref 에서 받아 씀
|
||||
"""812-9 지킴 — 가져온 기계 잇기(`M02_Machine_Find` · 요구 718 · 719).
|
||||
|
||||
(a) 기계표 전체에서 찾음 — 낱말표 밖 기종(로우더 · 공기 압축기 · 램 머 · 라인마커 …) · 후보 여럿이던 것
|
||||
@@ -6,7 +5,7 @@
|
||||
(b) 표기 정규화 · 괄호 낱말(무한궤도 · 타이어 · 일반용 · 표에 없는 낱말 발파 = 안 봄) · 범위 · 복수 규격
|
||||
(c) 조합 기계 = 둘(대형브레이카 +굴착기 · 0.7+브레이카 · +부착용집게 · +진동콤팩터 · 덤프트럭(자동덮개))
|
||||
(d) 별칭 먼저 — M01 기계 줄 「별칭」 칸(815-1 · 시험 안 임시 별칭) · 이름 + 규격 통째 = 그 EQ · 이름만 =
|
||||
그 기종으로 · 후보 여럿 표지 · [저장] 때 고른 EQ = 지금 층 옛 장부 줄(`learn` — 승인 길 바뀔 때까지)
|
||||
그 기종으로 · 후보 여럿 표지(옛 층 장부 쓰기 `learn` = 815-2 장부 걷기로 지움)
|
||||
(e) 금액 전후 같음 — 조합 줄 둘(첫 줄 엑셀 값 · 다음 줄 0) · 원파일 저장 금액 그대로
|
||||
"""
|
||||
|
||||
@@ -24,10 +23,7 @@ for p in (ROOT, HERE):
|
||||
sys.path.insert(0, str(p))
|
||||
|
||||
from M02_MasterTemplete import M02_Elem_Alias as ea # noqa: E402
|
||||
from M02_MasterTemplete import M02_Hopyo_Ledger as ledger # noqa: E402
|
||||
from M02_MasterTemplete import M02_Machine_Find as mf # noqa: E402
|
||||
from M02_MasterTemplete import M02_MasterTemplete_Store as store # noqa: E402
|
||||
from resources.tester.test_m02_labor_ref import world # noqa: E402, F401 — 같은 임시 층
|
||||
from test_815_1_import_link import aliases # noqa: E402 — M01 별칭 칸 임시
|
||||
|
||||
|
||||
@@ -161,28 +157,12 @@ def test_combo_many_part() -> None:
|
||||
assert mf.find_all("덤프트럭", "15Ton") == [{**mf.find("덤프트럭", "15Ton"), "이름": "덤프트럭", "규격": "15Ton"}] # fmt: skip
|
||||
|
||||
|
||||
def test_alias_first_and_learn(world) -> None: # noqa: F811
|
||||
me = world["personal"]
|
||||
me.mkdir(parents=True, exist_ok=True)
|
||||
with store.at(me):
|
||||
assert mf.find("아스팔트페이버(피니셔)", "3.0m")["판정"] == mf.NONE
|
||||
pairs = {"EQ000193": "아스팔트페이버(피니셔)", "EQ000129": '"크레인(트럭) 15Ton"'}
|
||||
with aliases("EQ", pairs):
|
||||
got = mf.find("아스팔트페이버(피니셔)", "3.0m") # 이름만 별칭 = 그 기종 → 규격으로 하나
|
||||
assert (got["판정"], got["후보"][0]["이름"], got["후보"][0]["규격"]) == (
|
||||
mf.ALIAS, "아스팔트 피니셔", "3m") # fmt: skip
|
||||
got = mf.find("크레인(트럭)", "15Ton") # 이름 + 규격 별칭 = 그 EQ(찾기보다 먼저)
|
||||
assert (got["판정"], got["키"]) == (mf.ALIAS, "EQ000129")
|
||||
assert mf.find("크레인(트럭)", "15Ton(할증125%)")["키"] == "EQ000129" # 할증 글 안 봄
|
||||
assert mf.same_kind("아스팔트페이버(피니셔)", "아스팔트 피니셔") is True
|
||||
doc = {
|
||||
"변수": [{"열쇠": "P_크", "기호": "P", "아래": "크", "연결": {
|
||||
"갈래": "단가산출", "키": "GC000270", "입력": {"기계": "'2104-0010'"}}}],
|
||||
"가져온": {"기계": [{"기호": "P_크", "판정": mf.MANY, "키": None,
|
||||
"원래": {"이름": "크레인(트럭)", "규격": "10Ton", "단위": "hr"}}]},
|
||||
} # fmt: skip
|
||||
assert mf.learn(doc, {"id": "sub3임시"}) == 1 # 옛 층 장부 줄(이음은 별칭 칸만 봄)
|
||||
assert any(r.get("원래", {}).get("규격") == "10Ton" for r in ledger.read(me).values())
|
||||
def test_alias_first_master_column() -> None:
|
||||
"""마스터 기계 줄 「별칭」 칸(815-2 옮김) — 이름만 별칭 = 그 기종 → 규격으로 하나 ·
|
||||
통째 별칭 · 할증 글 · 후보 여럿 = `test_815_1_import_link.test_alias_machine`."""
|
||||
got = mf.find("아스팔트페이버(피니셔)", "3.0m")
|
||||
assert (got["판정"], got["후보"][0]["이름"], got["후보"][0]["규격"]) == (
|
||||
mf.ALIAS, "아스팔트 피니셔", "3m") # fmt: skip
|
||||
assert mf.find("크레인(트럭)", "10Ton")["판정"] == mf.MANY
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user