From ac1961c0a3c3fc237db737f2f8e5fcf0704697d6 Mon Sep 17 00:00:00 2001 From: umsangdon Date: Sat, 10 Oct 2026 08:34:28 +0900 Subject: [PATCH] =?UTF-8?q?fix(ui):=20=ED=99=94=EB=A9=B4=20=EA=B8=80=20?= =?UTF-8?q?=E3=80=8C=EC=86=90=EC=9E=85=EB=A0=A5=20=C2=B7=20=EC=86=90=20?= =?UTF-8?q?=EC=9E=85=EB=A0=A5=20=C2=B7=20=EC=86=90=20=EC=A4=84=E3=80=8D=20?= =?UTF-8?q?=E2=86=92=20=E3=80=8C=EC=88=98=EA=B8=B0=20=EC=9E=85=EB=A0=A5=20?= =?UTF-8?q?=C2=B7=20=EC=88=98=EA=B8=B0=20=EC=A4=84=E3=80=8D=20=EC=A0=84?= =?UTF-8?q?=EC=97=AD(171-1)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 화면 글 10 자리(8 파일) — 세월교 힌트 · B08 재료 엑셀 알림 · B09 내역 수기 줄 까닭(거울 둘) · 산근 쓰는 곳 · 단가 힌트 · 총괄 수기 입력 칸 · 로케일 둘 - 저장 키 · 주석 · 손료는 그대로 · 로케일 줄 수 그대로 - 걸린 시험 셋 글 맞춤 · 새 시험 test_171_1 Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_015KYZ2HWWdUwZWYnn3tQz7X --- .../design/design_structure_ford_calc.ts | 2 +- B08_Quantity/B08_Quantity_UI_Material.ts | 4 +- B09_Estimation/B09_Estimation_Calc_Bill.py | 2 +- B09_Estimation/B09_Estimation_Calc_Bill.ts | 2 +- B09_Estimation/B09_Estimation_Sangeun.py | 2 +- B09_Estimation/B09_Estimation_UI_Tabs_Base.ts | 2 +- .../B09_Estimation_UI_Tabs_Total.ts | 4 +- .../tester/test_160_4_b08_concrete_columns.py | 2 +- resources/tester/test_166_2_b09_bill_hand.py | 2 +- .../tester/test_171_1_manual_input_label.py | 52 +++++++++++++++++++ .../tester/test_52_4_structure_spec_ford.py | 6 ++- ui_template/ui_template_locale_b2.ts | 4 +- 12 files changed, 71 insertions(+), 13 deletions(-) create mode 100644 resources/tester/test_171_1_manual_input_label.py diff --git a/A00_Common/design/design_structure_ford_calc.ts b/A00_Common/design/design_structure_ford_calc.ts index 83ed21f4f..5a7f1963e 100644 --- a/A00_Common/design/design_structure_ford_calc.ts +++ b/A00_Common/design/design_structure_ford_calc.ts @@ -27,5 +27,5 @@ export function fordHeightM(designFlowM3s: number | null, widthM: number): numbe export function fordHeightHint(designFlowM3s: number | null, widthM: number): string { const need = fordHeightM(designFlowM3s, widthM); if (need !== null) return `필요 수심 ${need.toFixed(2)} 이상`; - return designFlowM3s ? "월류 폭을 넣으면 셈" : "설계유량 없음 — 손 입력"; + return designFlowM3s ? "월류 폭을 넣으면 셈" : "설계유량 없음 — 수기 입력"; } diff --git a/B08_Quantity/B08_Quantity_UI_Material.ts b/B08_Quantity/B08_Quantity_UI_Material.ts index 0d4ca77f4..f569f58be 100644 --- a/B08_Quantity/B08_Quantity_UI_Material.ts +++ b/B08_Quantity/B08_Quantity_UI_Material.ts @@ -188,7 +188,9 @@ function excelDiffs(s: MaterialSheets): string { if (want != null && (row.surcharge ?? 0) !== want) out.push(`${row.spec} 할증 ${row.surcharge ?? 0}%(엑셀 ${want}%)`); } - return out.length ? `2공구 엑셀 손값과 다름 — ${out.join(" · ")} · 지금 값 = 품셈 근거` : ""; + return out.length + ? `2공구 엑셀 수기 입력값과 다름 — ${out.join(" · ")} · 지금 값 = 품셈 근거` + : ""; } /** 콘크리트소요 원천 = 콘크리트(기계) · 모르터 1:3 열 + 그 둘에 맞는 사본 자재 열(짝 계산 `matched` 그대로) */ diff --git a/B09_Estimation/B09_Estimation_Calc_Bill.py b/B09_Estimation/B09_Estimation_Calc_Bill.py index 92ff613a7..8ecc2ff6f 100644 --- a/B09_Estimation/B09_Estimation_Calc_Bill.py +++ b/B09_Estimation/B09_Estimation_Calc_Bill.py @@ -119,7 +119,7 @@ def _material_items(inputs: dict[str, Any], compare: list[dict[str, Any]]) -> li PriceOf = Callable[[str], dict[str, Any] | None] -WHY_HAND = "손 줄 — 연결 없음(우클릭 [연결])" +WHY_HAND = "수기 줄 — 연결 없음(우클릭 [연결])" WHY_LOGIC = "새 산근 — [저장] 뒤 단가(서버 셈)" diff --git a/B09_Estimation/B09_Estimation_Calc_Bill.ts b/B09_Estimation/B09_Estimation_Calc_Bill.ts index 5f6f5fa9a..c1065cf0b 100644 --- a/B09_Estimation/B09_Estimation_Calc_Bill.ts +++ b/B09_Estimation/B09_Estimation_Calc_Bill.ts @@ -108,7 +108,7 @@ function materialItems(inputs: Row, compare: Row[]): Row[] { /** 사본 주인 id → 대가 1 단위 단가(145-2 `daegaPrice`) */ export type PriceOf = (owner: string) => Row | null; -const WHY_HAND = "손 줄 — 연결 없음(우클릭 [연결])"; +const WHY_HAND = "수기 줄 — 연결 없음(우클릭 [연결])"; const WHY_LOGIC = "새 산근 — [저장] 뒤 단가(서버 셈)"; /** 연결 → 1 단위 단가 {no, key, labor, material, expense, sum} — 없으면 null */ diff --git a/B09_Estimation/B09_Estimation_Sangeun.py b/B09_Estimation/B09_Estimation_Sangeun.py index 6e3f8d857..e8c05bcf9 100644 --- a/B09_Estimation/B09_Estimation_Sangeun.py +++ b/B09_Estimation/B09_Estimation_Sangeun.py @@ -483,7 +483,7 @@ def hand_sources(user: dict[str, Any] | None) -> list[tuple[str, str, dict[str, continue src = {"code": str(ref["code"]), "given": _clean_given(ref.get("given")), "rate": ref.get("rate"), "picks": ref.get("picks")} # fmt: skip - out.append((row["key"], f"손 줄 {row.get('name') or row['key']}", src)) + out.append((row["key"], f"수기 줄 {row.get('name') or row['key']}", src)) return out diff --git a/B09_Estimation/B09_Estimation_UI_Tabs_Base.ts b/B09_Estimation/B09_Estimation_UI_Tabs_Base.ts index a86daea13..90935c418 100644 --- a/B09_Estimation/B09_Estimation_UI_Tabs_Base.ts +++ b/B09_Estimation/B09_Estimation_UI_Tabs_Base.ts @@ -157,7 +157,7 @@ export const buildCompare: TabBuild = ({ sheets, user, setUser }): TabTable => { ], rows: out, frozen: 2, - hint: "적용 단가 = 출처 중 최저(0 · 빈칸 뺌 · 견적 포함) 자동 · 칸에 넣으면 사용자 값 · 지우면 다시 최저 · 「출처」 칸 누름 = 고를 출처 돌림(값 있는 출처 · 견적이 높아도 고름) · 견적 단가 · 면 = 손입력 · 「관급 · 별도」 칸 누름 = 없음 → 관급 → 별도 · 「견적서」 칸 누름 = 파일 올리기 · 보기", + hint: "적용 단가 = 출처 중 최저(0 · 빈칸 뺌 · 견적 포함) 자동 · 칸에 넣으면 사용자 값 · 지우면 다시 최저 · 「출처」 칸 누름 = 고를 출처 돌림(값 있는 출처 · 견적이 높아도 고름) · 견적 단가 · 면 = 수기 입력 · 「관급 · 별도」 칸 누름 = 없음 → 관급 → 별도 · 「견적서」 칸 누름 = 파일 올리기 · 보기", editable: (_i, key) => key === "applied" || key === "p:견적" || key === "g:견적", onEdit: (i, key, value) => { const row = out[i]; diff --git a/B09_Estimation/B09_Estimation_UI_Tabs_Total.ts b/B09_Estimation/B09_Estimation_UI_Tabs_Total.ts index 4eccc4440..e0256392b 100644 --- a/B09_Estimation/B09_Estimation_UI_Tabs_Total.ts +++ b/B09_Estimation/B09_Estimation_UI_Tabs_Total.ts @@ -191,7 +191,7 @@ export const buildTotal: TabBuild = (ctx): TabTable => { money("material", "재료비"), money("expense", "경비"), qty("rate", "요율(%)", 5), - money("hand", "손입력", undefined, 2), + money("hand", "수기 입력", undefined, 2), text("note", "산식", 320), text("candidate", "요율 출처", 260), ], @@ -200,7 +200,7 @@ export const buildTotal: TabBuild = (ctx): TabTable => { hint: "요율 = M01 조달청 제비율에서 자동(맨 위 고르는 값 · 공종 토목) — 칸에 적으면 사용자 값이 앞섬 · 지우거나 출처 칸 누르면 자동 · " + "2024 엑셀 요율과 연도 차로 다를 수 있음 · 자동도 없으면 그 줄 · 그 줄을 쓰는 소계 빈칸 · 끝수 = 엑셀 그대로(줄마다 원 버림 · 관급 천원 올림) · " + - "손입력 = 안전관리비 기초액(빈칸 = 자동 구간 기초액) · 이윤 보정 · 부가세 조정 · 조달수수료율(빈칸 = 0) · " + + "수기 입력 = 안전관리비 기초액(빈칸 = 자동 구간 기초액) · 이윤 보정 · 부가세 조정 · 조달수수료율(빈칸 = 0) · " + "공종 제목 줄은 설계내역서(145-3)가 들어오면 붙음", editable: (i, key) => (key === "rate" && RATE_KEYS.has(String(rows[i]?.key))) || diff --git a/resources/tester/test_160_4_b08_concrete_columns.py b/resources/tester/test_160_4_b08_concrete_columns.py index 863182704..7b3c7ffa0 100644 --- a/resources/tester/test_160_4_b08_concrete_columns.py +++ b/resources/tester/test_160_4_b08_concrete_columns.py @@ -41,7 +41,7 @@ def test_엑셀_검산_시멘트_모래_자갈_레미콘(): def test_엑셀_손값과_다른_상수는_알림만(): ui = (ROOT / "B08_Quantity" / "B08_Quantity_UI_Material.ts").read_text(encoding="utf-8") - assert "2공구 엑셀 손값과 다름" in ui and "b08MaterialExcel" in ui + assert "2공구 엑셀 수기 입력값과 다름" in ui and "b08MaterialExcel" in ui # 기본 배합은 품셈 근거 그대로(124) per = {r["key"]: r["per"] for r in compute(SUMMARY, clean_overrides({}))["concrete"]["rows"]} assert per["c40"] == {"cement": 323, "sand": 0.456, "gravel": 0.612} diff --git a/resources/tester/test_166_2_b09_bill_hand.py b/resources/tester/test_166_2_b09_bill_hand.py index 0b0398f19..ec00b9bfe 100644 --- a/resources/tester/test_166_2_b09_bill_hand.py +++ b/resources/tester/test_166_2_b09_bill_hand.py @@ -177,7 +177,7 @@ def test_새_산근_사본_뒤_번호_호표_탭_집계표(tmp_path): base = compute_base(prices.build_inputs(None, keys), {}) got = sg.collect([("s1", a)], base, sg.hand_sources(user)) listed = [(r["no"], r["logic"], r["uses"]) for r in got["sg_list"]] - assert listed == [(1, NET, ["s1", "손 줄 새 산근"]), (2, STONE, ["손 줄 메쌓기"])] + assert listed == [(1, NET, ["s1", "수기 줄 새 산근"]), (2, STONE, ["수기 줄 메쌓기"])] assert got["sg_hand"] == { "hand:c": got["sg_list"][1]["key"], "hand:d": got["sg_list"][0]["key"], diff --git a/resources/tester/test_171_1_manual_input_label.py b/resources/tester/test_171_1_manual_input_label.py new file mode 100644 index 000000000..c8a37513c --- /dev/null +++ b/resources/tester/test_171_1_manual_input_label.py @@ -0,0 +1,52 @@ +"""171-1 「손입력 · 손 입력 · 손 줄」 → 「수기 입력 · 수기 줄」 화면 글 — 소스 시험. + +화면 글(따옴표 안)만 바꿈 · 저장 키(`{손: 수}` · 수량출처 「손」 · 표 `손` 깃) · 주석 · 손료는 그대로. +""" + +import re +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[2] + +SPOTS = { + "A00_Common/design/design_structure_ford_calc.ts": ["설계유량 없음 — 수기 입력"], + "B08_Quantity/B08_Quantity_UI_Material.ts": ["2공구 엑셀 수기 입력값과 다름"], + "B09_Estimation/B09_Estimation_Calc_Bill.ts": ['"수기 줄 — 연결 없음(우클릭 [연결])"'], + "B09_Estimation/B09_Estimation_Calc_Bill.py": ['"수기 줄 — 연결 없음(우클릭 [연결])"'], + "B09_Estimation/B09_Estimation_Sangeun.py": ['f"수기 줄 {'], + "B09_Estimation/B09_Estimation_UI_Tabs_Base.ts": ["견적 단가 · 면 = 수기 입력"], + "B09_Estimation/B09_Estimation_UI_Tabs_Total.ts": ['"수기 입력"', '"수기 입력 = 안전관리비'], + "ui_template/ui_template_locale_b2.ts": [ + "수량 원천: 수기 입력(직접비)", + "수량 원천: 수기 입력 공종", + ], +} + +# 따옴표 안 화면 글에 남은 옛 이름(주석 · 문서 글 빼고) +OLD = re.compile(r"[\"'`][^\"'`\n]*(손 ?입력|손 줄|손값)") +NOTE = re.compile(r'"""[\s\S]*?"""|/\*[\s\S]*?\*/|^\s*(//|#).*$', re.M) + + +def _text(rel: str) -> str: + return (ROOT / rel).read_text(encoding="utf-8") + + +def test_새_이름_자리(): + for rel, wants in SPOTS.items(): + src = _text(rel) + for w in wants: + assert w in src, f"{rel}: {w}" + + +def test_화면_글에_옛_이름_없음(): + for rel in SPOTS: + for line in NOTE.sub("", _text(rel)).splitlines(): + assert not OLD.search(line), f"{rel}: {line.strip()}" + + +def test_저장_키는_그대로(): + calc = _text("M02_MasterTemplete/M02_MasterTemplete_Labor_Calc.ts") + assert 'export type QtySource = "손" | "칸" | "없음";' in calc + assert "export type Qty = { 손: number } | null;" in calc + assert "손?: boolean;" in _text("ui_template/sheet/ui_template_sheet_types.ts") + assert "rows[] 손 줄" in _text("B09_Estimation/B09_Estimation_Calc_Bill.ts") # 주석 그대로 diff --git a/resources/tester/test_52_4_structure_spec_ford.py b/resources/tester/test_52_4_structure_spec_ford.py index 54fc613fa..218a7f2b2 100644 --- a/resources/tester/test_52_4_structure_spec_ford.py +++ b/resources/tester/test_52_4_structure_spec_ford.py @@ -100,7 +100,11 @@ def test_월류_높이는_폭과_연동_필요_수심_올림(out): row = [h for q, b, h in out["table"] if q == 2.54] assert row == sorted(row, reverse=True) and len(set(row)) == len(row) assert out["none"] == [None, None] # 설계유량 · 폭이 없으면 손 입력 - assert out["hints"] == ["필요 수심 0.08 이상", "월류 폭을 넣으면 셈", "설계유량 없음 — 손 입력"] + assert out["hints"] == [ + "필요 수심 0.08 이상", + "월류 폭을 넣으면 셈", + "설계유량 없음 — 수기 입력", + ] def test_정의_파일에_세월교_이름_표가_올라_있음(): diff --git a/ui_template/ui_template_locale_b2.ts b/ui_template/ui_template_locale_b2.ts index 328a6abd4..e84c27cf3 100644 --- a/ui_template/ui_template_locale_b2.ts +++ b/ui_template/ui_template_locale_b2.ts @@ -973,9 +973,9 @@ export const ui_locales_b2 = { "공종별 수량 (한 줄에 「공종코드=수량」)", 'Quantities (one "code=qty" per line)', ], - B09_Estimation_Src_Manual: ["수량 원천: 손입력(직접비 직접 입력)", "Source: manual direct costs"], + B09_Estimation_Src_Manual: ["수량 원천: 수기 입력(직접비)", "Source: manual direct costs"], B09_Estimation_Src_Quantities: [ - "수량 원천: 손입력 공종 수량 × 일위대가", + "수량 원천: 수기 입력 공종 수량 × 일위대가", "Source: manual quantities × unit prices", ], B09_Estimation_Missing_UP: [