Merge remote-tracking branch 'origin/dev' into sub_laptop_4

This commit is contained in:
2026-09-22 00:03:47 +09:00
4 changed files with 62 additions and 0 deletions
@@ -80,3 +80,46 @@
- 이미 채운 회색 14줄은 나대영 최저가(엄격한 짝) — 다산 지역가와 -10~-29% 벌어짐(전북만 0%): 대구경북 -19% · 경기 -12% · 대전충남 -14% · 광주전남 -17% · 충북 U -29% · 충북 I형 6cm -28% · I형 8cm -10%.
- 사용자 확정 거리: ① 지역별 다산 값(지역 조합가)과 조달청 전지역 나대영가 중 무엇을 기준으로 할지 ② 색은 나대영 U102 · U104 를 적색으로 볼지 ③ 청원 11,110 을 경기 전체에 쓸지.
## 나머지 못 채운 줄 정리 (일감 22 · 채우지 않음 · 사용자 확정 거리)
- 일감 21 뒤 못 채움 112줄 = 소형고압블록 49 · 접속티 4(일감 21에서 null) · 아래 59줄. 이번에 채운 줄 0 — 같은 물건이 확실한 줄이 없음.
- 아래 59줄 = 중온 아스콘 지역 없음 28 + KP 접합부속 17 + 그 밖 14(생태 3 · 본우드 3 · 아스콘 지역 묶음 3 · 전주 중온 3 · 슈퍼셀 1 · 레미콘 1). 세부는 아래.
### ① 중온 아스콘 「지역 없음」 28줄
다산 지역은 시군 묶음이고, 조달청 중온 줄은 조합마다 시군을 다르게 묶음. 등급도 다름(다산은 전부 3등급 · 조달청 중온은 1등급과 3등급이 섞임).
| 다산 지역 묶음 | 못 채운 줄 | 조달청 중온 | 못 채우는 까닭 |
|---|---|---|---|
| 세종시 · 충남(공주 · 천안 · 아산) | 10(BB-2 · 3 · 4 · MC-1 · WC-1~6) | 중온 줄 자체가 없음. 충남은 서남부(당진 · 서산 · 예산 · 홍성 · 태안 · 서천 · 부여 · 청양 · 보령)와 대전 묶음만 있고 세종 · 공주 · 천안 · 아산은 없음 | 지역 없음 |
| 전북(전주 · 완주 · 익산 · 군산) | 6(BB-3 · 4 · WC-1 · 3 · 5 · 6) | 이 시군을 묶은 중온 줄 없음. 전북 중온은 정읍 · 김제 · 고창 · 부안(서남) · 남원 · 무주 · 순창 · 임실 · 장수 · 진안(한길)뿐 | 지역 없음 |
| 전북(정읍 · 김제 · 고창 · 부안) | 6(BB-3 · 4 · WC-1 · 3 · 5 · 6) | 지역은 있음. 그러나 3등급 중온은 BB-2 · MC-1 · WC-2 · WC-4 뿐, BB-3 · WC-1 · WC-3 은 1등급만 있고 BB-4 · WC-5 · WC-6 은 아예 없음 | 지역은 맞고 그 등급 줄이 없음 |
| 전북(남원 · 무주 · 순창 · 임실 · 장수 · 진안) | 6(위와 같음) | 지역 있음 · 3등급은 BB-2 · MC-1 · WC-2 · WC-4 뿐, 1등급은 BB-2 · BB-3 · MC-1 · WC-1 · WC-3 | 같음 |
- 등급이 다른 1등급 줄로 채우면 다른 물건 — 채우지 않음. 현재 까닭 문구 「그 지역의 중온 아스콘 줄이 없음」은 전북 정읍 · 남원 묶음 12줄에는 부정확 → 「그 지역에 그 등급(3등급) 중온 줄이 없음」으로 고칠 것(사용자 확정 뒤 데이터 반영).
### ② KP 접합부속 17줄 (D80~D1200)
- 다산: 관경별 「KP 접합부속」 한 줄(예 D80 17,330 · D150 26,910 · D500 89,770 · D1000 297,290 · D1200 376,620) — 접합 부품을 묶은 세트값으로 보임.
- 조달청에 그 이름의 세트는 없음. 이름이 다른 부품이 따로 있음: 「압륜」(KP메커니컬 · 단위 조) 은 동명주물 DM-80 33,800 · DM-150 45,500 · DM-250 72,500 · DM-500 220,000 · DM-700 414,000 (세계주철 등 다른 제조사 포함) · 「고무링」은 맨홀 부품뿐.
- 압륜 값이 다산 세트값의 1.7~2.5배(D80 33,800 vs 17,330 · D150 45,500 vs 26,910 · D500 220,000 vs 89,770) — 같은 물건이 아니거나 구성이 다름. D900 이상 압륜은 줄 수가 적음.
- 사용자 확정 거리: 다산 「KP 접합부속」이 압륜 한 벌인지 고무링 포함 세트인지.
### ③ 그 밖 14줄 — 줄마다 까닭
| 줄 | 다산 | 조달청 | 까닭 |
|---|---|---|---|
| 아스콘 서울 · 인천 · 경기(강남 · 강동 · 송파 제외) BB-2 · WC-2 · WC-4 3등급 가열 (MT022737 · 47 · 51) | 105,500 · 131,800 · 125,770 | 그 넓은 묶음 줄은 없고 경기 시군 소묶음(조합 · 업체마다)이 많음. BB-2 는 89,590 · 100,520 · 106,670 · 107,350 이 섞여 있음 | 어느 소묶음이 다산 묶음인지 못 가림 · 최저는 다산보다 크게 낮음 |
| 아스콘 전북 전주 · 완주 · 익산 · 군산 중온 BB-2 · MC-1 · WC-2 (MT022869 · 80 · 87) | 119,500 · 134,510 · 147,760 | 그 시군 묶음 없음 · 다른 전북 묶음 값 128,110~156,860 이 +6~8% | 다른 지역 값 + 5% 밖 |
| 생태어소블록 1000×500×400 (MT007440) | 90,100 | 「어소」 품명 없음 · 생태블록은 호안 1000×1000×250(39,820) · 옹벽 1000×670×500(49,610 · 대청) | 품명 · 치수 다름 |
| 생태옹벽블록 500×500×200 · 1000×500×400 (MT007441 · 42) | 100,400 · 90,700 | 생태 옹벽 규격이 500×500 · 1000×500 인 줄 없음 | 치수 다름 |
| 합성목재(본우드) 3000×100×t16 · 3000×76×46 중공 루버 · 1200×100×100 중공 (MT014360~62) | 70,500 · 13,000 · 31,000 | 본우드 5줄 모두 2400×150×25~35 바닥재 솔리드(㎡ 단위) | 치수 · 형 · 단위 다름 |
| 콘크리트보강섬유(슈퍼셀) 셀룰로오스 0.6kg/포 (MT007635) | 14,000 | 「콘크리트보강섬유」는 내진 시트(m · ㎡) 3줄뿐 | 다른 물건 |
| 레미콘 부산 25-3-150 (MT021211) | 122,560 | 25-33-150 이 정확히 122,560(부산 소지역별 여러 제조사) · 25-30-150 은 119,000 | 다산 오기로 보이나 확정 못 함 · 강도 30 · 33 · 35 어느 것인지 다산 글자로 못 가림 · 값이 33 과 정확히 같아 오기 가능성이 큼 |
- 사용자 확정 거리: 레미콘 25-3-150 을 25-33-150(122,560)으로 볼지 · 나머지는 조달청에 같은 물건이 없어 못 채움이 맞음.
### 남은 수
- 108 → 112(일감 21의 접속티 4 추가) → 이번에 채운 것 0 → **112** = 소형고압블록 49 · 중온 아스콘 지역 없음 28 · KP 접합부속 17 · 접속티 4 · 그 밖 14. (충북 소형 회색 MT009987 1줄은 비고 없음 · 별도)
@@ -24,3 +24,8 @@
## 뺀 것 — 검증 도구 자체의 오탐(제품 결함 아님)
GC000996 짝=6·7 — 별칭 값칸 이름이 「그라우팅 믹서(190×2ℓ)」처럼 **띄어쓰기가 든 값칸 키**라, 이번 검증 스크립트가 공백으로 토큰을 가르다 오탐(값칸 이름 자체는 별칭 목록의 실제 값칸과 그대로 같음 — 실제 어긋남 아님, 목록에서 뺌).
## 고친 뒤 (2026-09-21)
원인 — 별칭 이름이 표 열쇠 그대로(`QC001882`)면 식 읽기가 그것을 「요소 열쇠」 로 읽어 이름을 밑이름 풀어쓴 글자로 바꿈. `master_text._elem_name` 이 요소 테이블(LB·EQ·MT·MP·MO)만 이름으로 풀고 그 밖 열쇠(QC·QF…)는 별칭 이름 그대로 두게 고침.
로직 전수 1,291 — 이름 식에 별칭 목록 밖 열쇠·풀어쓴 밑이름이 새는 줄 **0**. 이전 동작과 비교하면 이름 식이 달라지는 로직은 **196**(표본 2건이 아니라 같은 꼴 196). 값 식·계는 그대로. 시험 `test_m01_text.py` 에 GC001008 추가(21 통과).
@@ -19,6 +19,7 @@ import master_formula as mf
PLACES = Decimal("0.0001") # 화면 `formatNumber` 와 같음(소수 넷째 자리까지)
PRICE_TAIL = {"인력": "노임", "기계": "손료"} # 단가 자리의 이름 꼬리(그 밖은 「단가」)
ELEM_KEYS = ("LB", "EQ", "MT", "MP", "MO") # 요소 테이블 — 그 밖의 열쇠(QC · QF …)는 별칭 이름
ELEM_TAIL = {"LB": "노임", "EQ": "손료"} # 식 안 요소 키의 이름 꼬리(그 밖은 「단가」)
_PREC = {"또는": 1, "그리고": 2, "==": 3, "!=": 3, "<": 3, "<=": 3, ">": 3, ">=": 3}
_PREC |= {"+": 4, "-": 4, "*": 5, "/": 5}
@@ -86,6 +87,10 @@ def named(show, real, env: dict, master, depth: int = 0) -> str:
def _elem_name(master, ref: str) -> str:
"""식 안 요소 한 줄의 이름 — 「석공노임」 꼴(같은 이름의 중간 값과 헷갈리지 않게)."""
if (
str(ref)[:2] not in ELEM_KEYS
): # 별칭 이름이 표 열쇠 그대로인 것(QC…) — 밑이름을 풀어쓰지 않음
return ref
try:
name = mc.plain(master.get(ref).get("이름"))
except mf.FormulaError:
+9
View File
@@ -151,3 +151,12 @@ def test_끝수는_줄이_아니라_소계에_붙는다(client: TestClient) -> N
assert group["끝수"] == "원 미만 버림"
assert Decimal(str(group["소계"])) == Decimal(str(group["소계"])).to_integral_value()
assert not any("버림" in one[""] for one in group[""])
def test_이름_꼴_찾기_별칭이_표_열쇠_그대로면_밑이름으로_풀지_않는다(client: TestClient) -> None:
"""GC001008 덧줄 — 별칭 이름이 QC001882 뿐이라 이름 식도 별칭 목록의 그 이름을 씀."""
got, _ = _both(client, "GC001008")
extra = next(one for one in _all_lines(got) if one["이름"].startswith("공구손료"))
assert "QC001882.요율 %" in extra["이름글"]
assert "잔디깎기공구손료" not in extra["이름글"]
assert any(one["이름"] == "QC001882" for one in got["별칭"])