fix(725-6): 바탕 없는 단가산출 공통 옵션 칸(더한줄 로직 입력 모음) · 상세 못 셈 줄 금액 「—」 + 까닭 풍선
- 바탕 없는 SK = 더한줄 로직 입력을 모아(같은 이름 하나) 공통 옵션 칸으로 보임 · 값 자리 = 시험 입력 그대로 · 바탕 있으면 지금 그대로 - 입력 바꾸면 SK 셈 바로(바탕 없음 = 시험 계산 단추 없음) · 셈 때 SK 줄 입력 아닌 이름은 거름(공통 옵션 지역이 SK 줄에서 「모르는 입력」으로 멈춤) - 공용 상세 줄 금액 칸 = 까닭 있는 줄만 「—」 + 풍선(M01 줄은 까닭 없음 = 전후 같음) - 시험 test_725_1 에 바탕 없음 지역 서울 5,297.37 · 화면 짜임 단언 더함 Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -454,6 +454,9 @@ function nameCell(e: Entry, label: string, tag: string): HTMLElement {
|
||||
});
|
||||
}
|
||||
|
||||
/** 못 셈 줄(725 · M02 단가산출) — 금액 「—」 + 까닭 풍선 */
|
||||
const gapCell = (why: string): HTMLElement => el("span", { text: "—", attrs: { title: why } });
|
||||
|
||||
/** 보통 줄 · 몫 줄 — 누르면 그 줄 모달 */
|
||||
function lineRow(e: Entry, ctx: HoContext, label = e.name): HTMLTableRowElement {
|
||||
const tag = editTag(ctx, e.idx);
|
||||
@@ -463,7 +466,7 @@ function lineRow(e: Entry, ctx: HoContext, label = e.name): HTMLTableRowElement
|
||||
e.unit,
|
||||
formulaCell(e, ctx),
|
||||
e.price,
|
||||
money(e.amount),
|
||||
e.line?.까닭 ? gapCell(e.line.까닭) : money(e.amount),
|
||||
]);
|
||||
tr.classList.add("m01lab__line");
|
||||
if (e.extra) tr.classList.add("m01lab__line--extra");
|
||||
|
||||
@@ -101,6 +101,8 @@ export interface CalcLine {
|
||||
/** % 덧줄(149-4 · 서버 `M02_Labor_Doc.pct_extras`) — 율 · 밑수 글(「노무비의 %」 · 복합 = 빈 글) */
|
||||
율?: number;
|
||||
규격?: string;
|
||||
/** 못 셈 줄(725 · M02 단가산출) — 금액 없음 까닭 */
|
||||
까닭?: string;
|
||||
}
|
||||
|
||||
/** % 덧줄 표기(149-4) — 율 있으면 수량 = 율 · 단위 % · 이름 뒤 규격 괄호 · 금액은 그대로(M01 · M02 한 벌) */
|
||||
|
||||
@@ -23,6 +23,7 @@ import {
|
||||
fetchLogic,
|
||||
setLogicApiPaths,
|
||||
type CalcLine,
|
||||
type LogicInput,
|
||||
type LogicOne,
|
||||
type LogicRow,
|
||||
type TextAnswer,
|
||||
@@ -82,6 +83,8 @@ export function mountSangeunDetail(
|
||||
let ans: SkAnswer | null = null;
|
||||
let bare: SkAnswer | null = null;
|
||||
let fail = "";
|
||||
let extra: LogicInput[] = []; // 바탕 없는 SK — 더한줄 로직 입력 모음 = 공통 옵션 칸(725-6)
|
||||
const inputsOf = new Map<string, LogicInput[]>();
|
||||
let seq = 0;
|
||||
let alive = true;
|
||||
|
||||
@@ -151,12 +154,35 @@ export function mountSangeunDetail(
|
||||
이름: doc.이름 ?? "",
|
||||
결과단위: `원/${doc.단위 ?? ""}`,
|
||||
출처: doc.바탕?.참조?.키 ?? L("M02_SangeunNoBase"),
|
||||
입력: [],
|
||||
입력: extra,
|
||||
중간: [],
|
||||
호표: [],
|
||||
덧줄: [],
|
||||
});
|
||||
|
||||
/** 바탕 없을 때만 — 더한줄 로직들의 입력을 모음(같은 이름은 하나) · 바탕 있으면 바탕 입력 그대로 */
|
||||
async function syncExtra(): Promise<void> {
|
||||
const keys = [
|
||||
...new Set(
|
||||
doc.바탕 ? [] : (doc.더한줄 ?? []).flatMap((x) => ("로직" in x ? [String(x.로직)] : [])),
|
||||
),
|
||||
];
|
||||
await Promise.all(
|
||||
keys
|
||||
.filter((k) => !inputsOf.has(k))
|
||||
.map((k) =>
|
||||
fetchLogic(k).then(
|
||||
(r) => void inputsOf.set(k, r.logic.입력 ?? []),
|
||||
() => void inputsOf.set(k, []),
|
||||
),
|
||||
),
|
||||
);
|
||||
const seen = new Set<string>();
|
||||
extra = keys
|
||||
.flatMap((k) => inputsOf.get(k) ?? [])
|
||||
.filter((i) => !seen.has(i.이름) && seen.add(i.이름));
|
||||
}
|
||||
|
||||
const touch = (again = true): void => {
|
||||
opt.onChanged(edit && JSON.stringify(doc) !== saved);
|
||||
if (again) void recalc();
|
||||
@@ -165,6 +191,8 @@ export function mountSangeunDetail(
|
||||
|
||||
async function recalc(): Promise<void> {
|
||||
const mine = ++seq;
|
||||
await syncExtra();
|
||||
if (mine !== seq || !alive) return;
|
||||
const plain = { ...doc, 덮개: {}, 뺀줄: [], 더한줄: [] };
|
||||
try {
|
||||
const [got, was] = await Promise.all([
|
||||
@@ -356,6 +384,7 @@ export function mountSangeunDetail(
|
||||
values[name] = v;
|
||||
drawCalc();
|
||||
calcHost.querySelector<HTMLButtonElement>("[data-calc-run]")?.click();
|
||||
if (!base) void recalc(); // 바탕 없음 — 시험 계산 단추 없음 · SK 셈을 바로
|
||||
}
|
||||
|
||||
function drawCalc(): void {
|
||||
|
||||
@@ -194,7 +194,9 @@ def run(
|
||||
gaps = {at: x for at, x in enumerate(row["호표"]) if x.get("빠짐")}
|
||||
key = str(doc.get("키") or "SK-000000")
|
||||
over = _Over(whole, key, {**row, "키": key})
|
||||
values = {**got["입력값"], **(given or {})}
|
||||
# 이 SK 줄의 입력만 — 더한줄 로직 입력은 `_fill` 이 따로 채움
|
||||
names = {str(i.get("이름")) for i in row.get("입력") or []}
|
||||
values = {k: v for k, v in {**got["입력값"], **(given or {})}.items() if k in names}
|
||||
out = labor.run_line(over, key, values, got["켜쌓기율"], got["고름"] or None)
|
||||
covers = doc.get("덮개") or {}
|
||||
lines = []
|
||||
|
||||
@@ -96,3 +96,21 @@ def test_screen_shows_dropped_lines():
|
||||
"""화면 — 빠진 줄 띠(이름 · 까닭) · 금액 없는 줄 계산서 금액 —."""
|
||||
ts = (ROOT / "M02_MasterTemplete" / "M02_MasterTemplete_Sangeun_Detail.ts").read_text("utf-8")
|
||||
assert "ans?.빠진줄" in ts and 'L("M02_SangeunGap")' in ts
|
||||
|
||||
|
||||
def test_no_base_common_option_seoul(world): # noqa: F811
|
||||
"""725-6 — 바탕 없는 SK 도 공통 옵션(지역 서울) 따라감 = M01 셈."""
|
||||
doc = _sk(world["personal"], 더한줄=[GF_LINE])
|
||||
got = _run(world["personal"], doc, {"지역": "서울"})
|
||||
assert got["빠진줄"] == [], got
|
||||
assert got["기준"], {k: v for k, v in got.items() if k != "줄"}
|
||||
assert got["기준"]["계"] == pytest.approx(_m01(GF, {"지역": "서울", "보정작업": "해당 없음"}))
|
||||
assert round(float(got["기준"]["계"]), 2) == 5297.37
|
||||
|
||||
|
||||
def test_screen_no_base_inputs_and_gap_dash():
|
||||
"""725-6 화면 — 바탕 없음 = 더한줄 로직 입력 모음 칸 · 못 셈 줄 금액 「—」 + 까닭 풍선."""
|
||||
ts = (ROOT / "M02_MasterTemplete" / "M02_MasterTemplete_Sangeun_Detail.ts").read_text("utf-8")
|
||||
assert "입력: extra" in ts and "syncExtra" in ts and "if (!base) void recalc()" in ts
|
||||
ho = (ROOT / "M01_MasterData" / "M01_MasterData_UI_LogicLab_Ho.ts").read_text("utf-8")
|
||||
assert "e.line?.까닭 ? gapCell" in ho and "title: why" in ho
|
||||
|
||||
Reference in New Issue
Block a user