fix(b08): 자재 콘크리트소요 5줄 늘 보임 · 콘크리트 전용 빈 까닭 한 줄(163-5)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01STqEqztUthVFBmEP18wBSz
This commit is contained in:
@@ -7,7 +7,8 @@
|
||||
* 고칠 칸 = 단위수량 · ㎥당 배합 · 할증 % — 조작 = 캐시(`b08-materials`) + 짝 계산(`Material_Calc.ts`)으로 바로
|
||||
* 총괄 모래 · 자갈 · 시멘트 할증 = 좌측 패널 값(PLAN 124 · 표에서 안 고침 · 패널 조작에 바로 다시 셈)
|
||||
* [저장] = PUT …/quantity/materials → 서버가 정본으로 다시 셈 · 캐시 비움 · 자동 저장 없음
|
||||
* 값 없는 줄은 숨김(화면만 · 셈 · 열 · 단위수량은 그대로) · 표는 공용 카드 안(PLAN 143-3)
|
||||
* 값 없는 줄은 숨김(화면만 · 셈 · 열 · 단위수량은 그대로) · 표는 공용 카드 안(PLAN 143-3) ·
|
||||
* 콘크리트소요는 5줄 늘 보임(수량 빈칸 · 배합 늘 고침) + 콘크리트 전용 빈 까닭 한 줄(163-5)
|
||||
* 콘크리트(기계) · 모르터 1:3 열 = 늘 보임 · 손 단위수량 → 콘크리트소요(160-4) · 엑셀 손값과 다른
|
||||
* 배합 · 할증은 표 아래 알림 한 줄만 · 맞춤 없는 사본 자재 · 채집석 공제 = 총괄 끝 줄(160-3 · 5)
|
||||
* ========================================================================== */
|
||||
@@ -26,6 +27,7 @@ import {
|
||||
blankUnitRows,
|
||||
computeMaterialSheets,
|
||||
DEDUCT_KEY,
|
||||
matched,
|
||||
MIX_FIELDS,
|
||||
type Cells,
|
||||
type MaterialOverrides,
|
||||
@@ -189,9 +191,31 @@ function excelDiffs(s: MaterialSheets): string {
|
||||
return out.length ? `2공구 엑셀 손값과 다름 — ${out.join(" · ")} · 지금 값 = 품셈 근거` : "";
|
||||
}
|
||||
|
||||
/** 콘크리트소요 원천 = 콘크리트(기계) · 모르터 1:3 열 + 그 둘에 맞는 사본 자재 열(짝 계산 `matched` 그대로) */
|
||||
const CONCRETE_SOURCES = ["concrete_machine", "mortar_1_3"];
|
||||
|
||||
/** 콘크리트소요가 다 빈칸일 때 까닭 한 줄(163-5) — 원천 단위수량이 빈 집계표 줄을 사본 자재 유무로 가름 */
|
||||
function concreteWhy(s: MaterialSheets, source: SummarySource): string {
|
||||
if (s.concrete.rows.some((row) => row.qty != null)) return "";
|
||||
const keys = new Set(
|
||||
s.quantity.materials
|
||||
.filter(
|
||||
(m) =>
|
||||
CONCRETE_SOURCES.includes(m.key) ||
|
||||
CONCRETE_SOURCES.includes(matched(m.name, m.spec, m.unit) ?? ""),
|
||||
)
|
||||
.map((m) => m.key),
|
||||
);
|
||||
const blank = s.quantity.rows.filter((row) => [...keys].every((k) => row.units[k] == null));
|
||||
const copied = blank.filter((row) => source.snapshot?.units?.[row.id]).length;
|
||||
return blank.length
|
||||
? `콘크리트소요 빈 까닭 — 콘크리트(기계) · 모르터 1:3 단위수량 비었음 ${blank.length}줄(사본 자재에 콘크리트 · 모르터 없음 ${copied} · 사본 자재 없음 · 미연결 ${blank.length - copied}) — 자재수량 탭 그 열에 넣음`
|
||||
: "";
|
||||
}
|
||||
|
||||
function concreteTable(s: MaterialSheets, o: MaterialOverrides): Table {
|
||||
const { rows, total } = s.concrete;
|
||||
const keep = shown(rows, (row) => row.qty != null || anyValue(row.amounts));
|
||||
const keep = rows.map((_row, i) => i); // 5줄 늘 보임(163-5) — 수량 없으면 빈칸 · 배합은 늘 고침
|
||||
const rowsOut: DataRow[] = keep.map((at, i) => {
|
||||
const row = rows[at];
|
||||
const out: DataRow = {
|
||||
@@ -310,7 +334,10 @@ export async function renderMaterialSheet(
|
||||
const toolbar = document.createElement("div");
|
||||
toolbar.className = "b08-material__toolbar";
|
||||
const notes = document.createElement("div");
|
||||
notes.append(note(BASIS), note(`${HINTS[sheet]} · ${HIDDEN}`));
|
||||
notes.append(
|
||||
note(BASIS),
|
||||
note(sheet === "concrete" ? HINTS[sheet] : `${HINTS[sheet]} · ${HIDDEN}`),
|
||||
);
|
||||
if (sheet !== "quantity") {
|
||||
// 빈 까닭 한 줄(131) — 단위수량 빈 줄 · 서버 알림 · 빈 칸은 빈칸 그대로
|
||||
const blank = blankUnitRows(sheets);
|
||||
@@ -324,6 +351,9 @@ export async function renderMaterialSheet(
|
||||
notes.append(reason);
|
||||
}
|
||||
}
|
||||
const concreteNote = note(""); // 콘크리트 전용 빈 까닭(163-5) — 조작마다 다시
|
||||
concreteNote.dataset.b08MaterialConcreteWhy = "";
|
||||
if (sheet === "concrete") notes.append(concreteNote);
|
||||
toolbar.append(notes, save);
|
||||
|
||||
let built = BUILD[sheet](sheets, overrides);
|
||||
@@ -358,6 +388,8 @@ export async function renderMaterialSheet(
|
||||
built = BUILD[sheet](sheets, overrides);
|
||||
table.setRows(built.rows, built.total);
|
||||
excel.textContent = sheet === "quantity" ? "" : excelDiffs(sheets);
|
||||
concreteNote.textContent = concreteWhy(sheets, payload.source);
|
||||
concreteNote.hidden = !concreteNote.textContent;
|
||||
};
|
||||
redraw();
|
||||
host.replaceChildren(createCard({ body: [toolbar, table.root, excel] }));
|
||||
|
||||
@@ -12,9 +12,10 @@ SUMMARY = (ROOT / "B08_Quantity/B08_Quantity_UI_Summary.ts").read_text(encoding=
|
||||
|
||||
|
||||
def test_자재_셋_값_없는_줄_숨김():
|
||||
assert MATERIAL.count("const keep = shown(rows, ") == 3 # 총괄 · 콘크리트 · 자재수량
|
||||
assert (
|
||||
MATERIAL.count("const keep = shown(rows, ") == 2
|
||||
) # 총괄 · 자재수량(콘크리트 = 늘 · 163-5)
|
||||
assert "row.qty != null || anyValue(row.units)" in MATERIAL # 손 단위수량 있으면 보임
|
||||
assert "row.qty != null || anyValue(row.amounts)" in MATERIAL
|
||||
assert "row.qty != null || row.amount != null" in MATERIAL
|
||||
# 고친 칸 → 원래 줄(숨긴 줄 건너뜀)
|
||||
for target in (
|
||||
|
||||
Reference in New Issue
Block a user