feat(M02 실무자료 빠짐 0): 확인 안 한 줄 · 노임 · % = 고정 줄 · [모두 고정으로 들여오기] · [품셈으로 바꾸기] (PLAN 705-3)
- 만들기 — 체크 안 한 줄 · 노임 · 「우리에 없음」 = 고정 줄(엑셀 숫자 그대로 · 서버가 파일에서) · % 줄 = 비율 고정 줄(밑수 = 다른 줄 합일 때 · 아니면 금액 그대로) · 합계만 = 재료비 · 같은 이름 = 차례 가름 · 하위 호표 = 확인된 사전조합 참조 - 이음 = 이름 · 규격 · 단위 · 단가 다 같은 노임 · 자재만 저절로 · 다른 단가 = 이음 후보 수 - 시트 통째 — /hopyo-build-all(하위 먼저 · 확인된 호표 그대로) · 알림 「호표 · 줄 · 품셈 줄 · 고정 줄 · 빠짐 · 엑셀 합계 = 우리 합계」 · 비교 = 엑셀 끝수 규칙(EST 내림 · STmate 반올림) - 비율 고정 줄 셈 — M02 settle 짝(파이썬 · TS ratioLines) · 사전조합 셈 · B09 pct 줄 - 확인 창 — 만든 사전조합 품셈 줄 = 첫 체크 · [품셈으로 바꾸기] · [모두 고정으로] · 생성 물음에 전후 금액 · 품 다른 줄 수 - 낡은 시험 고침 — 빈 몸 400 · 빠진 줄(확인 안 함 · %) 단정 = 고정 줄로 바뀐 규칙 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -9,6 +9,9 @@
|
||||
* · 대상 · 옵션을 바꾸면 서버 `guess`(저장 안 함 · 줄마다 최신 응답만)가 우리 품을 다시 셈
|
||||
* · 캐시 = sessionStorage `m02-hopyo-check:{층}:{주인}:{키}:{번}`(조작 즉시 · 만들기 성공하면 지움) · 자동 저장 없음
|
||||
* · 화면 잠금은 [사전조합 생성] 때만 · 쓰기 단추 = 만들 층 쓰기 권한만.
|
||||
* · 705-3 — 체크 안 한 줄 = 고정 줄(엑셀 숫자 그대로) · 만든 사전조합이 있으면 첫 체크 = 그 품셈 줄(`만든.품셈`) ·
|
||||
* [품셈으로 바꾸기 (n)] = 맞음 · 별칭 줄 체크 + 생성 · [모두 고정으로] = 체크 모두 끔 + 생성(되돌리기) ·
|
||||
* 생성 물음에 전후 금액(품셈 = 우리 미리 셈 · 고정 = 엑셀) · 품 다른 줄 수.
|
||||
* 계산은 서버(`M02_Hopyo_Match` · `M02_Hopyo_Build` · `/labor/{열}/calc`) — 화면은 보이기 · 체크 · 고름만.
|
||||
* ========================================================================== */
|
||||
|
||||
@@ -240,6 +243,8 @@ export function buildHopyoCheck(opt: CheckOptions): HTMLElement {
|
||||
const one = await readHopyoOne(opt.scope, opt.key, opt.no, opt.target);
|
||||
if (my !== seq) return;
|
||||
got = one;
|
||||
const made = one.호표.만든?.품셈; // 705-3 — 만든 사전조합의 품셈 줄 = 첫 체크
|
||||
if (made && !hasDraft(k)) for (const l of one.호표.줄) d.체크[l.차례] = made.includes(l.차례);
|
||||
draw();
|
||||
} catch (error) {
|
||||
if (my === seq && !quiet) root.replaceChildren(loadingError(why(error), () => void load()));
|
||||
@@ -391,21 +396,38 @@ export function buildHopyoCheck(opt: CheckOptions): HTMLElement {
|
||||
단산행: 행,
|
||||
});
|
||||
|
||||
/** 1 단위 금액(705-3) — 품셈 줄 = 우리 미리 셈 · 고정 줄 = 엑셀 · 셈 중 = null */
|
||||
function sumOf(lines: HopyoLine[], poom: (l: HopyoLine) => boolean): number | null {
|
||||
let total = 0;
|
||||
for (const l of lines) {
|
||||
const p = poom(l) ? price(l) : null;
|
||||
if (p && !p.calc && !p.fail) return null;
|
||||
total += p?.calc?.반영합?.계 ?? l.금액.계 ?? 0;
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
async function make(h: HopyoOne["호표"]): Promise<void> {
|
||||
const whole = !!h.통째 && (d.통째 ?? h.통째.체크);
|
||||
const lines = whole ? [] : bodyOf(h.줄, d);
|
||||
const out = leftOut(h.줄, d);
|
||||
const put = lines.filter((x) => x.대상).length;
|
||||
const outs = lines.length - put;
|
||||
const poom = (l: HopyoLine): boolean => isChecked(l, d) && checkable(l, d) && !d.뺌[l.차례];
|
||||
const now = (l: HopyoLine): boolean => (h.만든?.품셈 ?? []).includes(l.차례);
|
||||
const outs = h.줄.filter((l) => isChecked(l, d) && d.뺌[l.차례] === "안 씀").length;
|
||||
const put = h.줄.filter(poom);
|
||||
const diff = put.filter((l) => {
|
||||
const q = d.품[l.차례] ?? l.맞춤.품;
|
||||
return !!q && Object.values(q.같음).some((v) => !v);
|
||||
}).length;
|
||||
const after = sumOf(h.줄, poom);
|
||||
const known = !!h.만든?.품셈; // 옛 사전조합(품셈 줄 기록 없음) = 지금 금액 모름
|
||||
const before = known ? sumOf(h.줄, now) : null;
|
||||
const money =
|
||||
`1 단위 ${known ? `지금 ${before === null ? "셈 중" : won(Math.round(before))} → ` : ""}` +
|
||||
`바뀐 뒤 ${after === null ? "셈 중" : won(Math.round(after))} · 엑셀 ${won(h.금액.계)}`;
|
||||
const ask = whole
|
||||
? `호표 통째로 만듦 — ${h.통째!.대상.map(targetText).join(" · ")}`
|
||||
: `넣을 줄 ${put} · 뺌 ${outs} · 빠질 줄 ${Object.values(out).reduce((a, b) => a + b, 0)}` +
|
||||
(Object.keys(out).length
|
||||
? `(${Object.entries(out)
|
||||
.map(([a, b]) => `${a} ${b}`)
|
||||
.join(" · ")})`
|
||||
: "") +
|
||||
" — 사전조합 생성";
|
||||
: `품셈 줄 ${put.length}${diff ? `(품 다름 ${diff})` : ""} · 고정 줄 ${h.줄.length - put.length - outs}` +
|
||||
` · 뺌 ${outs} — ${money}(미리 셈 · 끝수 차 있음) — 사전조합 생성`;
|
||||
if (!(await showConfirmDialog(ask, "생성"))) return;
|
||||
const from = { 층: opt.scope.layer, 주인: opt.scope.owner, 키: opt.key, 번: opt.no };
|
||||
showLoadingOverlay();
|
||||
@@ -498,10 +520,32 @@ export function buildHopyoCheck(opt: CheckOptions): HTMLElement {
|
||||
});
|
||||
const whole = !!h.통째 && (d.통째 ?? h.통째.체크);
|
||||
const go = createButton({ label: "사전조합 생성", variant: "filled", size: "sm" });
|
||||
go.disabled = !whole && checked < 1;
|
||||
go.setAttribute("data-hopyo-make", "");
|
||||
go.addEventListener("click", () => void make(h));
|
||||
tools.push(all, go);
|
||||
tools.push(all);
|
||||
if (h.만든 && !whole) {
|
||||
// 705-3 — 고정 ↔ 품셈 바꾸기(줄 하나 = 체크 하나 + [사전조합 생성])
|
||||
const poom = createButton({ label: `품셈으로 바꾸기 (${sure.length})`, size: "sm" });
|
||||
poom.setAttribute("data-hopyo-to-poom", "");
|
||||
poom.disabled = !sure.length;
|
||||
poom.addEventListener("click", () => {
|
||||
for (const l of sure) d.체크[l.차례] = true;
|
||||
keep();
|
||||
draw();
|
||||
void make(h);
|
||||
});
|
||||
const back = createButton({ label: "모두 고정으로", size: "sm" });
|
||||
back.setAttribute("data-hopyo-to-fixed", "");
|
||||
back.disabled = !h.만든.품셈?.length;
|
||||
back.addEventListener("click", () => {
|
||||
for (const l of h.줄) d.체크[l.차례] = false;
|
||||
keep();
|
||||
draw();
|
||||
void make(h);
|
||||
});
|
||||
tools.push(poom, back);
|
||||
}
|
||||
tools.push(go);
|
||||
}
|
||||
const head = el("div", {
|
||||
className: "ui-toolbar m02-hopyo__bar",
|
||||
@@ -515,7 +559,16 @@ export function buildHopyoCheck(opt: CheckOptions): HTMLElement {
|
||||
...(calc && !calc.끝
|
||||
? [note(`숫자 판정 셈 중 ${calc.한}/${calc.모두}${calc.까닭 ? ` · ${calc.까닭}` : ""}`)]
|
||||
: []),
|
||||
...(h.만든 ? [note(`만든 사전조합 ${h.만든.키}${h.만든.확인 ? " · 확인함" : ""}`)] : []),
|
||||
...(h.만든
|
||||
? [
|
||||
note(
|
||||
`만든 사전조합 ${h.만든.키}${h.만든.확인 ? " · 확인함" : ""}` +
|
||||
(h.만든.품셈
|
||||
? ` · 품셈 줄 ${h.만든.품셈.length} · 고정 줄 ${h.만든.고정 ?? 0}`
|
||||
: ""),
|
||||
),
|
||||
]
|
||||
: []),
|
||||
createButton({
|
||||
label: "엑셀 보기",
|
||||
size: "sm",
|
||||
|
||||
Reference in New Issue
Block a user