fix(M01): 로직 개선 시험 — 호표 묶음을 서버 비목 몫으로 나눔 · 「표 찾기 찾기」 겹침 · 모달 걸린 줄 맞힘
- 호표 묶음 소계가 텍스트 수식 소계와 같아짐(로직을 부르는 줄도 노무비·재료비·경비로 나뉘어 「그 밖」이 사라짐) - 표 줄의 빈 칸은 조건에서 빼 서버 찾기()와 같게 걸린 줄을 맞힘 - 표 꼬리표를 「표」로 줄이고 걸린 줄 없음 안내글을 바로잡음 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016WRFJmmhPi4exAzHgPZHMT
This commit is contained in:
@@ -147,20 +147,27 @@ function infoBox(ctx: DetailContext): HTMLElement {
|
||||
]);
|
||||
}
|
||||
|
||||
/** 계산된 줄은 서버가 준 비목별 몫으로 묶음에 나눠 넣음 — 로직을 부르는 줄도 노무비·재료비·경비로 갈림 */
|
||||
const spread = (e: Entry, line?: CalcLine): Entry[] => {
|
||||
const parts = Object.entries(line?.비목 ?? {}).filter(([, v]) => v !== 0);
|
||||
if (!parts.length) return [e];
|
||||
return parts.map(([k, v]) => ({ ...e, group: OF_COST[k] ?? "other", amount: v }));
|
||||
};
|
||||
|
||||
function entries(ctx: DetailContext): Entry[] {
|
||||
const middles: NamedFormula[] = ctx.row.중간 ?? [];
|
||||
const ho = ctx.row.호표 ?? [];
|
||||
const out: Entry[] = ho.map((item, i) => {
|
||||
const out: Entry[] = ho.flatMap((item, i) => {
|
||||
const line = ctx.lines?.[i];
|
||||
const brief = ctx.prices[item.요소];
|
||||
const price = line ? line.단가 : brief?.값;
|
||||
return {
|
||||
const entry: Entry = {
|
||||
group: groupOfHo(item),
|
||||
name: item.이름 ?? item.요소,
|
||||
spec: item.규격 ?? brief?.규격 ?? "",
|
||||
unit: item.단위 ?? "",
|
||||
qty: item.수량,
|
||||
qtyTag: qtyKind(item.수량),
|
||||
qtyTag: qtyKind(item.수량) === tx("Ho_QtyTable") ? tl("Tag_Table") : qtyKind(item.수량),
|
||||
price: price === undefined || price === null ? "" : formatNumber(price),
|
||||
amount: line ? line.금액 : null,
|
||||
extra: false,
|
||||
@@ -174,10 +181,11 @@ function entries(ctx: DetailContext): Entry[] {
|
||||
values: ctx.values,
|
||||
}),
|
||||
};
|
||||
return spread(entry, line);
|
||||
});
|
||||
(ctx.row.덧줄 ?? []).forEach((extra, i) => {
|
||||
const line = ctx.lines?.[ho.length + i];
|
||||
out.push({
|
||||
const entry: Entry = {
|
||||
group: OF_COST[extra.비목 ?? ""] ?? "other",
|
||||
name: extra.이름,
|
||||
spec: "",
|
||||
@@ -195,7 +203,8 @@ function entries(ctx: DetailContext): Entry[] {
|
||||
middles,
|
||||
values: ctx.values,
|
||||
}),
|
||||
});
|
||||
};
|
||||
out.push(...spread(entry, line));
|
||||
});
|
||||
return out;
|
||||
}
|
||||
|
||||
@@ -34,7 +34,17 @@ function tableView(
|
||||
table: TableRow,
|
||||
values: Record<string, string>,
|
||||
): HTMLElement {
|
||||
const hit = matchRow(table, find.find.conds, { values, middle: {} });
|
||||
// 표 줄의 빈 칸은 「무엇이든」 — 서버 찾기()와 같게 그 칸은 조건에서 뺌
|
||||
const hit =
|
||||
(table.줄 ?? []).find((line) =>
|
||||
matchRow(
|
||||
{ ...table, 줄: [line] },
|
||||
find.find.conds.filter(
|
||||
([col]) => line[col] !== undefined && line[col] !== null && line[col] !== "",
|
||||
),
|
||||
{ values, middle: {} },
|
||||
),
|
||||
) ?? null;
|
||||
const cols = [...Object.keys(table.조건 ?? {}), ...Object.keys(table.값칸 ?? {})];
|
||||
const rows = (table.줄 ?? []).map((line) =>
|
||||
el("tr", {
|
||||
|
||||
@@ -27,7 +27,8 @@ const TEXT = {
|
||||
G_labor: ["인력", "Labor"],
|
||||
G_material: ["자재", "Material"],
|
||||
G_cost: ["경비", "Expense"],
|
||||
G_other: ["그 밖", "Other"],
|
||||
G_other: ["그 밖 (인력·자재·경비 어디에도 안 맞는 줄)", "Other (fits none of the three)"],
|
||||
Tag_Table: ["표", "Table"],
|
||||
Subtotal: ["소계", "Subtotal"],
|
||||
Total: ["계", "Total"],
|
||||
Extra: ["덧줄", "Extra"],
|
||||
@@ -53,8 +54,8 @@ const TEXT = {
|
||||
Modal_NoData: ["표나 단가 자료가 없는 줄 — 수량 식만 있음", "No table or price data"],
|
||||
Modal_Hit: ["노란 줄 = 지금 넣은 값으로 걸린 줄", "Highlighted row matches the trial values"],
|
||||
Modal_NoHit: [
|
||||
"걸린 줄을 아직 못 맞힘 — 「시험 계산」 에 값을 넣고 다시 누르세요",
|
||||
"No matching row yet — enter trial values and reopen",
|
||||
"지금 값으로는 걸린 줄이 없음 — 값을 바꿔 보거나, 이 표를 안 쓰는 갈래일 수 있음",
|
||||
"No row matches the current values — change them, or this table is on an unused branch",
|
||||
],
|
||||
} as const satisfies Record<string, readonly [string, string]>;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user