feat(804-3): 줄 쌓기 수정 1차 — 표 값 고르기 · 산출근거 들여쓰기 · 찾아 넣기 창 · 짝 강조 · 기계 이름
- 표 값(요구 678-1): 「표」 꼬리표가 글뿐이라 눌러도 안 열림 → [표 · 고른 줄 · 칸 ▾] 단추 = 품셈 표 창(값 칸 누름 = 그 줄 · 칸) 옵션에 매인 조건(폼타이규격 등) = 그 줄만 고름 · 다른 줄 막힘 + 「위 옵션에서 고름」 안내 · M02 길 표 값 글 수도 고름 - 산출근거 들여쓰기(678-2): 머리 0 · 항목 1 · 가나다 2 · 줄 = 항목 + 1 · 펼친 블록 = 그 줄 + 1(수준 = stackLevels) - 찾아 넣기(678-3): [+ 줄] 인력 · 재료 · 기계 · 다른 단가산출 = M02 [항목 추가] 창 그대로(그 종류만) · 고르면 줄 생김(닫으면 없음) 있는 줄 = [찾아 바꾸기](같은 로직 기계 = 지역 · 보정작업 넘김 그대로) · 옛 찾기 칸 + 고름 목록 · 기종 코드 고르개 걷음 빈 틀 = [찾아 넣기](돈 아닌 단가산출 결과만 — Find_Pick results) - 짝 강조(679-1): 오른쪽 줄 누름 = 왼쪽 카드 강조 + 보이는 자리로 · 왼쪽 누름 = 오른쪽 같은 줄 강조 - 기계 이름(679-2): 기계 줄 = 기종 이름 · 규격 · machine-hourly 답에 로직 키 · 원문번호 더함(기존 칸 그대로) - 모델 common_util_line_stack_pick.ts(boundConds · currentRow · pickCell · addPicked · repick · stackLevels) - 시험 test_804_2 넓힘 3(표 고름 = 값 + 출처 · 서버 셈 같음 · 찾아 넣기 넷 = 요소 키 · 서버 금액 · 다시 고름 · 수준) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -227,3 +227,115 @@ def test_화면_이음():
|
||||
assert lic == "MIT"
|
||||
for f in (ROOT / "A00_Common").glob("line_stack*.ts"):
|
||||
assert len(f.read_text(encoding="utf-8").splitlines()) <= 700, f.name
|
||||
|
||||
|
||||
# ── 804-3 줄 쌓기 수정 1차(요구 678) ──
|
||||
def _tbl(world, key, **kw):
|
||||
return _ts("표고름", [{**world["cases"][key], **kw}])[0]
|
||||
|
||||
|
||||
def _calc(world, doc):
|
||||
return dc.mc.calc(
|
||||
json.loads(json.dumps(doc), parse_float=Decimal, parse_int=Decimal), world["links"]
|
||||
)
|
||||
|
||||
|
||||
def test_표고름_값_출처(world):
|
||||
# 옵션에 매인 조건(규격 = S_폼타이규격) — 줄은 옵션 그대로 · 칸만 바뀜
|
||||
a = _tbl(world, "GC000211", 기호="Q_3t^표", 줄=1, 칸="4t/㎡")
|
||||
assert a["묶임"] == {"규격": ["폼타이규격"]} and a["전줄"] == 2
|
||||
assert a["연결"] == {
|
||||
"갈래": "표",
|
||||
"표": "QC000429",
|
||||
"조건": {"규격": "S_폼타이규격"},
|
||||
"칸": "4t/㎡",
|
||||
}
|
||||
assert a["값"] == 0.72 and a["후줄"] == 2 # 12.7㎜ 줄 · 4t/㎡
|
||||
# 옵션에 안 매인 조건 — 고른 줄 값이 조건으로 · 값 = 표 칸 · 서버 셈 같음
|
||||
b = _tbl(
|
||||
world,
|
||||
"GC000211",
|
||||
기호="Q_시공^표",
|
||||
줄=4,
|
||||
칸="시공량",
|
||||
앞=[{"기호": "Q_시공^표", "조건": {"유형": "'보통'"}}],
|
||||
)
|
||||
assert b["묶임"] == {} and b["전줄"] == 3
|
||||
assert b["연결"]["조건"] == {"유형": "'간단'"} and b["연결"]["표"] == "QC000431"
|
||||
assert b["값"] == 50 and b["후줄"] == 4
|
||||
py = _calc(world, b["문서"])
|
||||
assert [_num(py.get(f)) for f in COSTS] == [b[f] for f in COSTS]
|
||||
assert b["계"] != world["py"]["GC000211"]["계"] # 시공량 20 → 50 = 금액 바뀜
|
||||
# 조건 없는 표(한 줄) — 칸만
|
||||
c = _tbl(world, "GC000211", 기호="Q_합판2^표", 줄=0, 칸="각재")
|
||||
assert (
|
||||
c["연결"] == {"갈래": "표", "표": "QC000427", "조건": {}, "칸": "각재"} and c["값"] == 0.038
|
||||
)
|
||||
|
||||
|
||||
def test_찾아넣기_요소키_금액(world):
|
||||
h = mh.hourly("EQ000016")
|
||||
assert h["ok"] and h["로직"] and h["원문번호"] == "0201-0012"
|
||||
picks = [
|
||||
{"갈래": "인력", "고른": {"키": "LB000002", "이름": "보통인부", "단위": "인"}},
|
||||
{"갈래": "재료", "고른": {"키": "MT000018", "이름": "합판(내수), 서울", "규격": "12t×1220×2440mm", "단위": "㎡"}},
|
||||
{"갈래": "기계", "고른": {"키": h["로직"], "이름": "굴착기(무한궤도)", "규격": "0.12㎥", "입력": {"기계": "'0201-0012'"}}},
|
||||
{"갈래": "단가산출", "고른": {"키": "GF000099", "이름": "측구터파기 토사", "단위": "㎥"}},
|
||||
] # fmt: skip
|
||||
got = _ts("넣기", [{"문서": world["docs"]["GC000211"], "넣을": picks}])[0]
|
||||
assert got["갈래"] == ["인력", "재료", "기계", "단가산출"]
|
||||
doc = got["문서"]
|
||||
links = {v["기호"] + ("_" + v["아래"] if v.get("아래") else ""): v["연결"] for v in doc["변수"]}
|
||||
assert [links[i] for i in got["기호"]] == [
|
||||
{"갈래": "요소", "키": "LB000002"},
|
||||
{"갈래": "요소", "키": "MT000018"},
|
||||
{"갈래": "단가산출", "키": h["로직"], "입력": {"기계": "'0201-0012'"}},
|
||||
{"갈래": "단가산출", "키": "GF000099", "입력": {}},
|
||||
]
|
||||
new = doc["금액"][got["처음"] :]
|
||||
assert [(m["단위"], m["비목"], m["수량"]) for m in new] == [
|
||||
("인", "노무비", "1"),
|
||||
("㎡", "재료비", "1"),
|
||||
("hr", "묶음", "1"),
|
||||
("㎥", "묶음", "1"),
|
||||
]
|
||||
# 금액 = 서버 정본 셈 — 넣은 넷 = 노임 + 자재 + 기계 한 시간(hourly) + 단가산출 계
|
||||
before, after = world["py"]["GC000211"], _calc(world, doc)
|
||||
want = 172068 + 11354 + float(h["계"]) + float(world["py"]["GF000099"]["계"])
|
||||
assert float(after["계"]) - float(before["계"]) == pytest.approx(want, abs=2)
|
||||
ts = _ts("셈", [{"문서": doc, "연결": _record(world, doc)}])[0]
|
||||
assert not ts["누락"], ts
|
||||
assert [ts[f] for f in COSTS] == [_num(after.get(f)) for f in COSTS]
|
||||
# 다시 고름 — 키 · 이름만 바뀜
|
||||
again = _ts(
|
||||
"넣기",
|
||||
[{"문서": world["docs"]["GC000211"], "넣을": picks[:1], "바꿈": [{"차례": 0, "고른": {"키": "LB000007", "이름": "형틀목공"}}]}],
|
||||
)[0] # fmt: skip
|
||||
m = again["문서"]["금액"][again["처음"]]
|
||||
assert m["이름"] == "형틀목공" and m["수량"] == "1"
|
||||
assert any(v["연결"] == {"갈래": "요소", "키": "LB000007"} for v in again["문서"]["변수"])
|
||||
# 기계 다시 고름(같은 로직) — 기종만 바뀌고 지역 · 보정작업 넘김 그대로
|
||||
gf = world["docs"]["GF000099"]
|
||||
i = next(k for k, m in enumerate(gf["금액"]) if m["단가"] == "P_굴착기무한궤")
|
||||
one = _ts("바꿈", [{"문서": gf, "줄": i, "기호": "P_굴착기무한궤", "갈래": "기계", "고른": picks[2]["고른"]}])[0] # fmt: skip
|
||||
link = next(v["연결"] for v in one["변수"] if v.get("아래") == "굴착기무한궤")
|
||||
assert link["입력"] == {"기계": "'0201-0012'", "지역": "S_지역", "보정작업": "S_보정작업"}
|
||||
assert one["금액"][i]["이름"] == "굴착기(무한궤도)" and one["금액"][i]["규격"] == "0.12㎥"
|
||||
|
||||
|
||||
def _record(world, doc):
|
||||
rec = mr.Rec(world["links"])
|
||||
d = json.loads(json.dumps(doc), parse_float=Decimal, parse_int=Decimal)
|
||||
rec.prefetch(d)
|
||||
dc.mc.calc(d, rec) # 요소 값은 셈하며 기록됨(화면 미리 셈과 같은 길)
|
||||
return rec.out()
|
||||
|
||||
|
||||
def test_들여쓰기_수준():
|
||||
got = _ts("넣기", [{"문서": {"금액": [], "변수": []}, "넣을": []}])[0]
|
||||
assert got["수준"] == [{"item": 2, "line": 3}] # 가나다 항목 = 2 · 줄 3
|
||||
out = _src("A00_Common/line_stack_out.ts")
|
||||
assert "stackLevels(items)" in out and '"--lstk-depth", String(r.lv)' in out
|
||||
assert "rows(sub, got, h, depth + 1, path, lv + 1)" in out # 펼친 블록 = 그 줄 + 1
|
||||
edit = _src("A00_Common/line_stack_edit.ts")
|
||||
assert "openStackPick" in edit and "/links" not in edit and "Machine" not in edit
|
||||
|
||||
Reference in New Issue
Block a user