feat(830-10): 재료 표 지역 열 분리 · 남은 상하차 글 판독 — 이름 · 규격의 지역 글을 단위 뒤 지역 칸으로
- 지역 칸 = 단위 바로 뒤 · 상하차 앞 · 적힌 지역 글 그대로(꼴 일곱 F1 ~ F6 · 6,604 줄 · 242 종) · 없음 = -(17,423 줄) - 이름 꼴: 레미콘(서울)-사급 → 레미콘-사급 · 레미콘(관급)-경상북도(칠곡군) → 레미콘(관급) · 이형철근(SD400,제주)-관급 → 이형철근(SD400)-관급 · 모래(건조상태·전국) → 모래(건조상태) · 관급 · 사급 글은 남김 - 지역 아님은 그대로: 업체 · 산지(농산개발(홍성) · 보령웅천석) · 수종 · 상표 - EST 이름 칸 30 자에서 잘린 지역 글 30 줄 = 잘린 그대로 · 비고 「지역 글 잘림」 - 상하차: 폐기물운반비(상차포함) = 상차 · (상차제외) = - · 글은 이름에서 뺌(상차 125 → 135) - 줄 · 키 · 차례 · 물가지 값 · 면수 · 출처 그대로(24,027) · 새 겹침 0(겹침 422 묶음 = 830-9 때부터) - 손 값(지역 · 상하차 · 일반가격) 빌더가 이어 받음 · 「-」 은 손 값 아님 - check_master 지역 빈 칸 검사 · test_830_2 기대를 지역 칸 꼴로 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,12 +1,12 @@
|
||||
"""상용 적산 자료(ESTX 2026-07) 자재 → 재료_자재품목.json — 개발용 · 배포 전 판권 구매 뒤 갱신.
|
||||
|
||||
ESTX 자재 표 = StuffcDat(칸 뜻: 다산소프트/ESTX_값사전_자재노무기계.md).
|
||||
열 한 벌 = material_merge.COLUMNS(키 · 구분 · 상세구분 · 이름 · 규격 · 단위 · 상하차 · 조달청 · 물가자료 · 유통물가 · 물가정보 · 거래가격 · 일반가격 · 출처 · 비고 · 면수).
|
||||
열 한 벌 = material_merge.COLUMNS(키 · 구분 · 상세구분 · 이름 · 규격 · 단위 · 지역 · 상하차 · 조달청 · 물가자료 · 유통물가 · 물가정보 · 거래가격 · 일반가격 · 출처 · 비고 · 면수).
|
||||
Cost2..5 = 물가지 넷 · Page2..5 = 면수. TC(채택) · Cost6(견적가)는 마스터 아님 — 뺌.
|
||||
Cost1(가격정보 = 관급 정보)은 넣지 않음 — 「조달청」 열은 자리만 두고 비움(요구 827 · 830) · 비고에도 안 적음.
|
||||
「일반가격」 = 시스템 관리자가 M01 에서 넣는 칸 · 손 값(상하차 · 일반가격)은 원문번호로 이어 받음.
|
||||
「일반가격」 = 시스템 관리자가 M01 에서 넣는 칸 · 손 값(지역 · 상하차 · 일반가격)은 원문번호로 이어 받음.
|
||||
Cost1 출처 표기로 가린 재료 아닌 줄은 뺌(요구 832) — 「2026(경북)」 품질시험 수수료 · 「~26.10.16」 일반 도로용 블록.
|
||||
줄 목록 = EST 그대로 — 지역 · 관급 · 사급 줄을 합치지 않음(요구 834) · 상하차 칸 = material_merge.place.
|
||||
줄 목록 = EST 그대로 — 지역 · 관급 · 사급 줄을 합치지 않음(요구 834) · 지역 · 상하차 칸 = material_merge.place(요구 839).
|
||||
0 · 미저장 = 값 없음(null). 이름·규격은 원문 그대로(띄어쓰기·오자 포함). 코드 없는 빈 줄은 뺌.
|
||||
ESTX 에 대·중분류 칸이 없어 구분·상세구분은 build_자재품목_분류.py 가 품명 글자 규칙으로 채움(빌더 끝에서 부름).
|
||||
조달청 줄 · 조달청 관급 값은 넣지 않음(요구 822 — EST 그대로) · update_관급단가*.py 는 지금 정본에 적용 안 함.
|
||||
@@ -63,7 +63,7 @@ def dropped(r: dict) -> str | None:
|
||||
|
||||
|
||||
def own_prices() -> dict[str, dict]:
|
||||
"""지금 정본의 손 값(상하차 · 일반가격) — 원문번호 → {칸: 값}."""
|
||||
"""지금 정본의 손 값(지역 · 상하차 · 일반가격) — 원문번호 → {칸: 값}."""
|
||||
if not OUT.is_file():
|
||||
return {}
|
||||
book = mk.load_book()["키"]
|
||||
@@ -90,6 +90,7 @@ def build(rows: list[dict], own: dict | None = None) -> list[dict]:
|
||||
"이름": r.get("Name", ""),
|
||||
"규격": r.get("Size", ""),
|
||||
"단위": r.get("Unite", ""),
|
||||
mm.REGION: own.get(code, {}).get(mm.REGION),
|
||||
mm.LOAD: own.get(code, {}).get(mm.LOAD),
|
||||
mm.GOVT: None,
|
||||
**{slot: num(r.get(f"Cost{i}")) for i, slot in enumerate(MARKET, 2)},
|
||||
@@ -127,7 +128,7 @@ def prune() -> int:
|
||||
|
||||
|
||||
def check(rows: list[dict]) -> None:
|
||||
"""원본 대조 — 줄 수(원본 − 재료 아닌 줄) · 줄마다 이름 · 규격(인도 조건 글 뺌) · 단위 · 물가지 넷 · 면수가 원본 그 줄 것 · 조달청 칸 빔."""
|
||||
"""원본 대조 — 줄 수(원본 − 재료 아닌 줄) · 줄마다 이름 · 규격(인도 조건 · 지역 글 뺌) · 단위 · 물가지 넷 · 면수가 원본 그 줄 것 · 조달청 칸 빔."""
|
||||
data = json.loads(OUT.read_text(encoding="utf-8"))
|
||||
raw = {r["Code"]: r for r in rows if r.get("Code") and r["Code"] not in DROP}
|
||||
out = sum(1 for r in raw.values() if dropped(r))
|
||||
@@ -139,6 +140,7 @@ def check(rows: list[dict]) -> None:
|
||||
for g in got:
|
||||
r = raw[g["출처"].removeprefix("자재품목 ")]
|
||||
name, spec, _, _ = mm.split_load({"이름": r.get("Name", ""), "규격": r.get("Size", "")})
|
||||
name, spec, _ = mm.split_region(name, spec)
|
||||
assert (g["이름"], g["규격"], g["단위"]) == (name, spec, r.get("Unite", "")), g["출처"]
|
||||
for i, slot in enumerate(MARKET, 2):
|
||||
assert (g[slot] or 0) == (r.get(f"Cost{i}") or 0), (g["출처"], slot)
|
||||
@@ -152,6 +154,10 @@ def check(rows: list[dict]) -> None:
|
||||
print(" 줄마다 이름 · 규격 · 단위 · 물가지 넷 · 면수 = 원본 그 줄 · 조달청 칸 빔 · 열 한 벌")
|
||||
load = {v: sum(1 for r in data["줄"] if r[mm.LOAD] == v) for v in mm.LOADS}
|
||||
print(f" {mm.LOAD}:", " · ".join(f"{k} {n}" for k, n in load.items()))
|
||||
assert all(r[mm.REGION] for r in data["줄"])
|
||||
print(
|
||||
f" {mm.REGION}: 있음 {sum(1 for r in data['줄'] if r[mm.REGION] != mm.NONE)} · - {sum(1 for r in data['줄'] if r[mm.REGION] == mm.NONE)}"
|
||||
)
|
||||
|
||||
|
||||
def main():
|
||||
@@ -173,7 +179,8 @@ def main():
|
||||
"유류·전력은 뺌 — 유가·전기요금은 재료_유가전력(유류는 값이 비고 글뿐 · 중유는 받지 않음)",
|
||||
"원문번호(다산소프트 품번) 칸 없음 — 대조는 _키대장.json 에만",
|
||||
"조달청 칸 = 자리만 둠 · 값 없음 — 원문 「가격정보」(관급 정보) 값은 넣지 않음(요구 827 · 830)",
|
||||
"상하차 = 상차 · 하차 · -(기본 · 모름) · 단위 바로 뒤 — 이름 · 규격 끝 인도 조건 글(도착도 · 하차도 = 하차 · 채취장상차 · 하치장 상차도 = 상차)을 떼어 이 칸으로(요구 828 · 831 · 836) · 값이 아닌 표지",
|
||||
"지역 = 단위 바로 뒤 — 이름 · 규격에 적힌 지역 글을 그대로 떼어 이 칸으로(꼴 일곱 · 관급 · 사급 글은 이름에 남김 · 없음 = -)(요구 839) · 값이 아닌 표지",
|
||||
"상하차 = 상차 · 하차 · -(기본 · 모름) · 지역 바로 뒤 — 이름 · 규격 끝 인도 조건 글(도착도 · 하차도 = 하차 · 채취장상차 · 하치장 상차도 · 상차포함 = 상차 · 상차제외 = -)을 떼어 이 칸으로(요구 828 · 831 · 836 · 839) · 값이 아닌 표지",
|
||||
"줄 목록 = EST 그대로 — 지역 · 관급 · 사급 · 제조사 · 조합 줄을 합치지 않음(요구 834)",
|
||||
"재료 아닌 줄은 뺌 — 품질시험 수수료(가격정보 출처 「2026(경북)」) · 일반 도로용 블록(「~26.10.16」)(요구 832)",
|
||||
"조달청 줄 · 조달청 관급 값은 넣지 않음 — EST 그대로(요구 822)",
|
||||
|
||||
@@ -303,6 +303,8 @@ def check_form(name: str, data: dict) -> list[str]:
|
||||
out.append(f"{where} · 열이 한 벌이 아님 — 「{' · '.join(cols)}」")
|
||||
if book == "자재품목" and row.get(mm.LOAD) not in mm.LOADS:
|
||||
out.append(f"{where} · 「{mm.LOAD}」 는 {' · '.join(mm.LOADS)} 가운데 하나")
|
||||
if book == "자재품목" and not str(row.get(mm.REGION) or "").strip():
|
||||
out.append(f"{where} · 「{mm.REGION}」 빈 칸 — 모르면 「{mm.NONE}」")
|
||||
if kind == "품셈재료":
|
||||
out += _check_linked(where, row)
|
||||
if kind == "요소" and isinstance(row.get("값"), dict):
|
||||
|
||||
@@ -1,23 +1,29 @@
|
||||
"""재료 자재품목 열 한 벌 · 상하차(요구 828 · 830 · 831 · 834 · 836 · 837 · PLAN 830-9).
|
||||
"""재료 자재품목 열 한 벌 · 지역 · 상하차(요구 828 · 830 · 831 · 834 · 836 · 837 · 839 · PLAN 830-10).
|
||||
build_재료_자재품목 이 부름 · 시험 = test_830_2_material_merge.
|
||||
|
||||
줄 목록 = EST 그대로(지역 · 관급 · 사급 · 제조사 · 조합 글이 든 원래 이름 · 줄마다 따로) — 합치지 않음.
|
||||
열 한 벌 = COLUMNS — 상하차 = 단위 바로 뒤 · 가격 열 = 조달청(관급) · 물가지 넷 · 일반가격(사급).
|
||||
줄 목록 = EST 그대로(지역 · 관급 · 사급 · 제조사 · 조합 줄마다 따로) — 합치지 않음.
|
||||
열 한 벌 = COLUMNS — 지역 · 상하차 = 단위 바로 뒤 · 가격 열 = 조달청(관급) · 물가지 넷 · 일반가격(사급).
|
||||
지역 칸 = 이름 · 규격에 적힌 지역 글 그대로(`split_region` 꼴 일곱 · 표기 안 고침 · 없음 = -) — 그 글은 이름 · 규격에서 뺌
|
||||
· 관급 · 사급 글은 이름에 남김 · 상표 · 산지 · 수종 글(「보령웅천석」 · 「농산개발(홍성)」)은 지역 아님
|
||||
· EST 이름 칸 30 자에서 잘린 지역 글은 잘린 그대로 · 비고에 CUT.
|
||||
사급 / 관급 고르기는 재료 표 열이 아님 — 단가산출 쪽 몫(요구 837).
|
||||
상하차 칸 = 상차 · 하차 · -(기본 · 모름) — 이름 · 규격 끝 인도 조건 글로 채우고 그 글은 이름 · 규격에서 뺌(요구 836)
|
||||
「도착도」 · 「하차도」 = 하차 · 「채취장상차(도)」 · 「하치장 · 생산공장 상차도」 · 「(상차도)」 = 상차
|
||||
「도착도」 · 「하차도」 = 하차 · 「채취장상차(도)」 · 「하치장 · 생산공장 상차도」 · 「(상차도)」 = 상차 ·
|
||||
「(상차포함)」 = 상차 · 「(상차제외)」 = -(포함 안 됨 · 같은 이름의 상차 줄과 상하차 칸으로 갈림)
|
||||
조달청 칸 값은 모두 비움(EST 「가격정보」 — 요구 827 · 831) · 일반가격 = 시스템 관리자가 넣는 칸.
|
||||
상하차 · 일반가격 손 값은 빌더가 이어 받음.
|
||||
지역 · 상하차 · 일반가격 손 값은 빌더가 이어 받음(지역 · 상하차 「-」 = 손 값 아님 — 판독 값).
|
||||
"""
|
||||
|
||||
import re
|
||||
|
||||
MARKET = ("물가자료", "유통물가", "물가정보", "거래가격")
|
||||
REGION = "지역" # 표지 칸 — 적힌 지역 글 그대로 · 없음 = NONE
|
||||
NONE = "-"
|
||||
LOAD = "상하차" # 표지 칸(값 칸 아님)
|
||||
LOADS = ("-", "상차", "하차") # 첫째 = 기본(모름)
|
||||
GOVT = "조달청" # 관급 가격 칸 — 가장 낮은 값 고르기에 안 넣음(요구 826 · 830)
|
||||
OWN = "일반가격" # 시스템 관리자 손 입력 칸(사급)
|
||||
HAND = (LOAD, OWN) # 빌더가 이어 받는 손 값 칸
|
||||
HAND = (REGION, LOAD, OWN) # 빌더가 이어 받는 손 값 칸
|
||||
COLUMNS = ( # 열 한 벌 · 차례(요구 830 · 831)
|
||||
"키",
|
||||
"구분",
|
||||
@@ -25,6 +31,7 @@ COLUMNS = ( # 열 한 벌 · 차례(요구 830 · 831)
|
||||
"이름",
|
||||
"규격",
|
||||
"단위",
|
||||
REGION,
|
||||
LOAD,
|
||||
GOVT,
|
||||
*MARKET,
|
||||
@@ -33,7 +40,9 @@ COLUMNS = ( # 열 한 벌 · 차례(요구 830 · 831)
|
||||
"비고",
|
||||
"면수",
|
||||
)
|
||||
NAME_LOAD = re.compile(r",\s*(도착도|하차도|채취장상차도|채취장상차)$") # 모 래, 서울, 도착도
|
||||
NAME_LOAD = re.compile(
|
||||
r",\s*(도착도|하차도|채취장상차도|채취장상차)$|\(((?:상|하)차(?:포함|제외))\)$"
|
||||
) # 모 래, 서울, 도착도 · 폐기물운반비(상차포함)
|
||||
SPEC_LOAD = re.compile(
|
||||
r"\s*(?:\((상차도)\)|((?:하치장|생산공장)\s*상차도))$"
|
||||
) # HD=10mm 하치장 상차도
|
||||
@@ -44,7 +53,9 @@ def split_load(row: dict) -> tuple[str, str, str, str | None]:
|
||||
name, spec = row.get("이름") or "", row.get("규격") or ""
|
||||
m = NAME_LOAD.search(name)
|
||||
if m:
|
||||
name, text = name[: m.start()], m[1]
|
||||
name, text = name[: m.start()], m[1] or m[2]
|
||||
if text.endswith("제외"):
|
||||
return name, spec, LOADS[0], text
|
||||
else:
|
||||
m = SPEC_LOAD.search(spec)
|
||||
if not m:
|
||||
@@ -54,14 +65,72 @@ def split_load(row: dict) -> tuple[str, str, str, str | None]:
|
||||
|
||||
|
||||
def place(row: dict) -> dict:
|
||||
"""COLUMNS 차례의 줄 — 첫 칸(열쇠 · 키)은 그대로 · 인도 조건 글은 상하차 칸으로 ·
|
||||
손 값(상하차)이 있으면 그 값 · 조달청 = 빔 · 옛 칸(관급)은 뺌."""
|
||||
"""COLUMNS 차례의 줄 — 첫 칸(열쇠 · 키)은 그대로 · 인도 조건 글은 상하차 칸 · 지역 글은 지역 칸으로 ·
|
||||
손 값(지역 · 상하차 — 「-」 아님)이 있으면 그 값 · 조달청 = 빔 · 옛 칸(관급)은 뺌."""
|
||||
name, spec, load, _ = split_load(row)
|
||||
name, spec, region = split_region(name, spec)
|
||||
first = next(iter(row))
|
||||
note = row.get("비고")
|
||||
if (
|
||||
region != NONE
|
||||
and len(row.get("이름") or "") >= 30
|
||||
and region.count("(") > region.count(")")
|
||||
):
|
||||
note = " · ".join(x for x in (note, CUT) if x)
|
||||
fix = {
|
||||
"이름": name,
|
||||
"규격": spec,
|
||||
LOAD: row.get(LOAD) or load,
|
||||
REGION: row.get(REGION) if row.get(REGION) not in (None, "", NONE) else region,
|
||||
LOAD: row.get(LOAD) if row.get(LOAD) not in (None, "", NONE) else load,
|
||||
GOVT: None,
|
||||
"비고": note,
|
||||
}
|
||||
return {first: row[first], **{c: fix[c] if c in fix else row.get(c) for c in COLUMNS[1:]}}
|
||||
|
||||
|
||||
# ── 지역 글(요구 839 · 조사 818 2 절 꼴 일곱) ─────────────────────────────
|
||||
CUT = "지역 글 잘림 — EST 이름 칸 30 자"
|
||||
PLACES = frozenset(
|
||||
"""전국 서울 부산 대구 인천 광주 대전 울산 세종 제주 경기 강원 충북 충남 전북 전남 경북 경남
|
||||
청주 전주 포항 창원 춘천 충주 강릉 천안 원주 여수 구미 순천 수원 목포 금산 영천 논산 삼척 홍성
|
||||
익산 청도 양양 남원 공주 군산 김천 가평 용인 포천 경주 아산 제천 여주 보령 부여 당진 청원 음성
|
||||
서산 영동 진천 예산 장성 고흥 고창 광양 고령 성주 영주 안동 칠곡 상주 문경 합천 화성 경산""".split()
|
||||
) # 콤마 · 괄호 꼴에 적힌 지역 낱말(자료에서) — 관급 꼬리(F3)는 낱말 표 없이 꼬리 전부
|
||||
_P = "|".join(sorted(PLACES, key=len, reverse=True))
|
||||
_F2 = re.compile(rf"^(.*?)\(({_P})\)-사급$") # 레미콘(서울)-사급
|
||||
_F4 = re.compile(rf"^(.*?)\((SD\d+),({_P})\)-관급$") # 이형철근(SD400,제주)-관급
|
||||
_F3 = re.compile(
|
||||
r"^(.*?\(관급\))-(?!거양|SD\d)(.+)$"
|
||||
) # 레미콘(관급)-경상북도(칠곡군) · 거양 = 제조사
|
||||
_F1 = re.compile(rf"^({_P})\s*(\(관급\))?$") # 이름 콤마 조각 「, 서울」 · 「, 제주 (관급)」
|
||||
_F5 = re.compile(
|
||||
rf"\((?:([^()·]+)·)?((?:{_P})(?:지역)?)(,관급)?\)"
|
||||
) # (서울) · (건조상태·전국) · (충남지역,관급)
|
||||
_F6 = re.compile(
|
||||
rf"(?<![가-힣])\s?\(((?:{_P})(?:지역)?)\)"
|
||||
) # 규격 42C (서울) · 0.7M(제주지역) · 「농산개발(홍성)」 = 업체 · 지역 아님
|
||||
|
||||
|
||||
def split_region(name: str, spec: str) -> tuple[str, str, str]:
|
||||
"""(지역 글을 뺀 이름, 규격, 지역 글 | NONE) — 꼴 일곱(F1 이름 끝 콤마 · F2 (지역)-사급 · F3 (관급)-꼬리 ·
|
||||
F4 (강종,지역)-관급 · F5 이름 속 괄호 · F6 규격 속 괄호 · F7 규격 전체) · 관급 · 사급 글은 남김."""
|
||||
name, spec = name or "", spec or ""
|
||||
if m := _F2.match(name):
|
||||
return f"{m[1]}-사급", spec, m[2]
|
||||
if m := _F4.match(name):
|
||||
return f"{m[1]}({m[2]})-관급", spec, m[3]
|
||||
if m := _F3.match(name):
|
||||
return m[1], spec, m[2]
|
||||
parts = name.split(",")
|
||||
for i, part in enumerate(parts[1:], 1):
|
||||
if m := _F1.match(part.strip()):
|
||||
rest = ",".join(parts[:i] + parts[i + 1 :])
|
||||
return (rest.rstrip() + m[2] if m[2] else rest), spec, m[1]
|
||||
if m := _F5.search(name):
|
||||
inner = ",".join(x for x in (m[1], (m[3] or "")[1:]) if x)
|
||||
return name[: m.start()] + (f"({inner})" if inner else "") + name[m.end() :], spec, m[2]
|
||||
if m := _F6.search(spec):
|
||||
return name, spec[: m.start()] + spec[m.end() :], m[1]
|
||||
if spec.strip() in PLACES:
|
||||
return name, "", spec.strip()
|
||||
return name, spec, NONE
|
||||
|
||||
+24029
-24028
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
||||
"""830-2 · 830-9 재료 표 — 가격 열 재정의(요구 827 ~ 832) · 항목 목록 = EST 그대로(요구 834) 지킴.
|
||||
"""830-2 · 830-9 · 830-10 재료 표 — 가격 열 재정의(요구 827 ~ 832) · 항목 목록 = EST 그대로(요구 834) 지킴.
|
||||
|
||||
열 한 벌(상하차 = 단위 뒤 · 조달청 · 물가지 넷 · 일반가격) · 조달청 값 0 · 일반가격 빈칸 ·
|
||||
이름 EST 그대로(지역 · 관급 · 사급 줄 따로) · 상하차 = 인도 조건 글 판독 · 그 글은 이름에서 뺌(요구 836) ·
|
||||
열 한 벌(지역 · 상하차 = 단위 뒤 · 조달청 · 물가지 넷 · 일반가격) · 조달청 값 0 · 일반가격 빈칸 ·
|
||||
이름 = EST 이름에서 지역 · 인도 조건 글만 뺌(지역 · 관급 · 사급 줄 따로 · 요구 836 · 839) · 상하차 = 인도 조건 글 판독 ·
|
||||
사급 / 관급 열 없음(요구 837) · 재료 아닌 줄 0 ·
|
||||
치즐 값 없음 · 줄 · 키 · 이름 · 규격 · 단위 · 물가지 값 = EST 원본 그 줄 · 빌더 = 정본 · 가장 낮은 값이 조달청 칸을 안 봄.
|
||||
"""
|
||||
@@ -30,6 +30,7 @@ COLS = (
|
||||
"이름",
|
||||
"규격",
|
||||
"단위",
|
||||
"지역",
|
||||
"상하차",
|
||||
"조달청",
|
||||
"물가자료",
|
||||
@@ -75,7 +76,8 @@ def test_조달청_빔_일반가격_빔(rows):
|
||||
def test_이름_EST_그대로_지역_관급_사급_줄_따로(rows):
|
||||
remi = [r["이름"] for r in rows if r["이름"].startswith("레미콘")]
|
||||
assert [n for n in remi if "관급" in n] and [n for n in remi if "사급" in n]
|
||||
assert "레미콘(서울)-사급" in remi and "레미콘(포항)-사급" in remi
|
||||
sa = {r["지역"] for r in rows if r["이름"] == "레미콘-사급"} # 지역은 지역 칸(요구 839)
|
||||
assert {"서울", "포항"} <= sa
|
||||
assert not [r for r in rows if "통합:" in str(r["비고"] or "")]
|
||||
|
||||
|
||||
@@ -98,7 +100,7 @@ def test_상하차_인도_조건_글_칸으로_이름에서_뺌(rows):
|
||||
assert not [r for r in rows if mm.split_load(r)[3]] # 이름 · 규격에 인도 조건 글 0
|
||||
rebar = [r for r in rows if r["이름"].startswith("이형철근") and r["규격"].startswith("HD=")]
|
||||
assert [r for r in rebar if r["상하차"] == "상차"]
|
||||
assert {r["상하차"] for r in rows if r["이름"].startswith("모 래, ")} >= {"하차"}
|
||||
assert {r["상하차"] for r in rows if r["이름"] == "모 래" and r["지역"] != "-"} >= {"하차"}
|
||||
assert mm.split_load({"이름": "모 래, 서울, 도착도", "규격": ""}) == (
|
||||
"모 래, 서울",
|
||||
"",
|
||||
@@ -124,6 +126,7 @@ def test_빌더_정본_줄_키_EST_그대로(rows, raw):
|
||||
for r in est:
|
||||
s = src[code[r["키"]]]
|
||||
name, spec, _, _ = mm.split_load({"이름": s.get("Name", ""), "규격": s.get("Size", "")})
|
||||
name, spec, _ = mm.split_region(name, spec)
|
||||
assert (r["이름"], r["규격"], r["단위"]) == (name, spec, s.get("Unite", ""))
|
||||
assert [r[c] or 0 for c in mm.MARKET] == [s.get(f"Cost{i}") or 0 for i in range(2, 6)]
|
||||
built = [mm.place(r) for r in builder.build(raw, builder.own_prices()) + builder.carried()]
|
||||
|
||||
Reference in New Issue
Block a user