feat(714-2): 장비 펼침 넉 줄 — 서버 펼침(714-1b · 부른 기계경비 로직 시간당 줄 조종원 · 주연료 · 잡재료비 · 기계손료 · 원/시간 계) 머리 글 + 넉 줄 → 그 장비 노 · 재 · 경 몫 식

- calc_sheet.ts SheetUnfold · 펼침 줄 · calc_sheet.css 펼침 글 들여씀
- 지킴 시험 test_714_2_calc_sheet 펼침 글 줄

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-11-01 16:39:11 +09:00
co-authored by Claude Opus 5.5
parent ebc6ac25a9
commit dcf476d504
3 changed files with 35 additions and 2 deletions
+5
View File
@@ -12,3 +12,8 @@
[data-sheet-part] .ui-calc-row__label {
padding-left: var(--spacing-16);
}
p[data-sheet-part] {
margin: 0;
padding-left: var(--spacing-16);
}
+28 -2
View File
@@ -29,6 +29,15 @@ export interface SheetLine {
장비?: boolean | null;
기준단위?: string | null;
환산근거?: string;
/** 714-1b 장비 줄 펼침 — 부른 기계경비 로직의 시간당 줄(조종원 · 주연료 · 잡재료비 · 기계손료) */
펼침?: SheetUnfold | null;
}
export interface SheetUnfold {
키: string;
이름: string;
단위: string;
줄: { 비목: string; 이름: string; 글: string; 금액: number | null }[];
계: number | null;
}
export interface SheetGroup {
비목: string;
@@ -130,7 +139,8 @@ const TEXT = {
하위: ["하위 로직", "Sub logic"],
Basis: ["기준", "Basis"],
Short: ["노 {a} · 재 {b} · 경 {c}", "L {a} · M {b} · E {c}"],
Fold: ["누르면 노 · 재 · 경 식 펼침", "Click to expand labor · material · expense"],
Fold: ["누르면 펼침", "Click to expand"],
Per: ["{n} — {v} 원/{u}", "{n} — {v} KRW/{u}"],
} as const satisfies Record<string, readonly [string, string]>;
const t = (k: keyof typeof TEXT): string => TEXT[k][currentLanguageIndex as 0 | 1] ?? TEXT[k][0];
const bundleName = (b: string): string => (b in TEXT ? t(b as keyof typeof TEXT) : b);
@@ -177,7 +187,23 @@ function mergedRows(m: SheetMerged): HTMLElement[] {
.replace("{b}", won(share("재료비"), 1))
.replace("{c}", won(share("경비"), 1));
const head = createCalcFormulaRow(`▸ ${m.이름}`, createCalcFormula(short), out(m.금액, false, 1));
const parts = m.몫.map((x) => lineRow(x.줄, `${x.비목}`));
// 펼침 = 부른 기계경비 로직 시간당 줄(손료 · 주연료 · 잡품 · 운전사 · 714-1b) → 이 줄 노 · 재 · 경 몫 식
const unfold = m.몫.find((x) => x.줄.펼침)?.줄.펼침;
const parts = [
...(unfold
? [
createText(
t("Per")
.replace("{n}", unfold.이름)
.replace("{v}", won(unfold.계, 1))
.replace("{u}", unfold.단위 || "-"),
"hint",
),
...unfold.줄.map((x) => lineRow(x, `${x.이름} (${x.비목})`)),
]
: []),
...m.몫.map((x) => lineRow(x.줄, `${x.비목}`)),
];
for (const p of parts) {
p.hidden = true;
p.dataset.sheetPart = m.이름;
@@ -31,6 +31,8 @@ def test_부품_상자만():
s = _text(SHEET)
assert "<button" not in s and "document.createElement" not in s and "<table" not in s
assert "@ui/ui_template_calc_row" in s and "@ui/ui_template_input" in s
# 장비 펼침 = 서버 「펼침」(714-1b · 부른 기계경비 로직 시간당 줄) 먼저 · 그 뒤 노 · 재 · 경 몫 식
assert "x.줄.펼침" in s and "unfold.줄.map(" in s
@pytest.mark.skipif(shutil.which("node") is None, reason="node 가 없음")