Files
Aislo/M02_MasterTemplete/M02_MasterTemplete_Sangeun_Rate.ts
eomsangdonandClaude Opus 5.5 d9a581659f feat(778-4): 율 줄을 단가산출(SK)에 담음 — 고정 비율 더한줄 · 기준 묶음 · 줄 목록 · 율 위 율
- SK 더한줄 율 줄 허용(일위대가 비율 줄과 같은 꼴 `고정 비율 {기준, 비목}` · 수량 = 율)
- 기준 = 비목(노무비 · 재료비 · 경비) · 묶음(인력 · 재료 · 장비 = 그 줄 종류만 · 기계 노무 섞인 블록도 인력 줄만) ·
  줄 목록(cid · add:#k · 앞 율 줄 = 율 위 율) · 검사 = 자기 · 뒤 율 줄 막음
- 밑 공용 함수 `M02_Labor_Fixed.rate_base` ↔ 짝 `Labor_Calc.ts` `rateBase`(일위대가 비율 줄 · Expand 같이 씀)
- SK 셈 `_rated` = 엔진 한 번 돈 줄로 밑 → 율 줄 값묶음 → 엔진 다시(율 줄 없는 문서 = 한 번 · 값 그대로)
- B09 pct 밑수 `bundle:` · `rows:`(파이썬 · TS 짝) · SK 블록 율 줄 = pct
- 굳힘 — 바탕 없는 SK 율 줄은 한 줄로 안 펼침(참조 그대로) · 겹침 때 기준 열쇠 새 차례
- 화면 — [율 줄 추가] 창(새 `M02_MasterTemplete_Sangeun_Rate.ts` · 부품 상자만) · 율 줄 = % 줄로 보임 ·
  더한줄 지움 · 되살림 때 기준 열쇠 옮김
- 시험 — 새 test_778_4_rate_line(25) · 거울 헬퍼에 rateBase 길 · 전후 대조 SK 16 · 일위대가 118 · B09 대가 입력 14 같음

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-04 12:59:48 +09:00

104 lines
4.3 KiB
TypeScript

/* =============================================================================
* M02_MasterTemplete_Sangeun_Rate.ts
* M02 단가산출(SK) 율 줄 넣기 창(PLAN 778-4 · 요구 623) — [율 줄 추가] → 이름 · 율 % · 기준 · 금액이 드는 칸.
* 기준 = 묶음(인력 · 재료 · 장비 줄 합) · 비목 전체(노무비 · 재료비 · 경비) · 줄 고르기(이 SK 줄 cid 목록 ·
* 앞 율 줄 고르면 율 위 율) → 더한줄 `{고정: {이름, 단위 %, 단가 0, 이음 없음, 비율 {기준, 비목}}, 수량 = 율}`
* (꼴 = 서버 `M02_Sangeun_Doc` · 셈 = 서버 `M02_Sangeun_Calc._rated`) · 부품 상자만.
* ========================================================================== */
import { createButton } from "@ui/ui_template_button";
import { createCheckbox } from "@ui/ui_template_checkbox";
import { el } from "@ui/ui_template_elements";
import { createFormGrid } from "@ui/ui_template_general_layout";
import { createInputField, createSelectField } from "@ui/ui_template_input";
import { t as L } from "@ui/ui_template_locale";
import { openModal } from "@ui/ui_template_modal";
import type { SkAdded } from "./logic/M02_Sangeun_Cover_Model";
const LINES = "줄";
/** 율 줄 넣기 — `rows` = 지금 셈 답 줄(기준 줄 고르기 후보) · `done` = 새 더한줄 한 줄 */
export function openRateLine(
rows: { cid: string; 이름: string }[],
done: (line: SkAdded) => void,
): void {
const name = createInputField({ label: L("M02_SkRateName"), value: L("M02_SkRateDefault") });
const rate = createInputField({
label: L("M02_SkRateRate"),
type: "number",
value: "2",
unit: "%",
min: 0,
});
const picks = rows.map((r) => ({
cid: r.cid,
box: createCheckbox(r.이름 || r.cid, { chip: true, size: 28 }),
}));
const list = el("div", {
className: "m02-sk__tags",
attrs: { "data-sk-rate-lines": "" },
children: picks.length
? picks.map((p) => p.box.root)
: [el("span", { text: L("M02_SkRateNoLines") })],
});
list.hidden = true;
const basis = createSelectField({
label: L("M02_SkRateBasis"),
value: "인력",
options: [
{ value: "인력", text: L("M02_SkRateGroupLabor") },
{ value: "재료", text: L("M02_SkRateGroupMat") },
{ value: "장비", text: L("M02_SkRateGroupMach") },
{ value: "노무비", text: L("M02_SkRateCostLabor") },
{ value: "재료비", text: L("M02_SkRateCostMat") },
{ value: "경비", text: L("M02_SkRateCostExp") },
{ value: LINES, text: L("M02_SkRateBasisLines") },
],
onChange: (v) => (list.hidden = v !== LINES),
});
const part = createSelectField({
label: L("M02_SkRatePart"),
value: "경비",
options: [
{ value: "경비", text: L("M02_SkRatePartExp") },
{ value: "재료비", text: L("M02_SkRatePartMat") },
{ value: "노무비", text: L("M02_SkRatePartLabor") },
],
});
openModal({
title: L("M02_SkRateTitle"),
closeLabel: L("M02_SkRateClose"),
width: "40rem",
mount: (body, close, actions) => {
const ok = createButton({
label: L("M02_SkRateOk"),
variant: "filled",
onClick: () => {
const label = name.input.value.trim();
const q = Number(rate.input.value);
const keys = picks.filter((p) => p.box.input.checked).map((p) => p.cid);
const lines = basis.select.value === LINES;
name.setError(label ? undefined : L("M02_SkRateNeedName"));
rate.setError(rate.input.value.trim() && q >= 0 ? undefined : L("M02_SkRateBadRate"));
if (lines && !keys.length) return void rate.setError(L("M02_SkRateNeedLine"));
if (!label || !rate.input.value.trim() || !(q >= 0)) return;
const fx = {
이름: label,
단위: "%",
단가: { 노무비: 0, 재료비: 0, 경비: 0 },
이음: { 노임: null, 자재: null, 기계: null },
비율: { 기준: lines ? keys : basis.select.value, 비목: part.select.value },
};
done({ 고정: fx, 이름: label, 단위: "%", 수량: q });
close();
},
});
ok.dataset.skRateOk = "";
actions.append(ok);
const grid = createFormGrid([name.root, rate.root, basis.root, part.root]);
grid.dataset.skRate = "";
body.append(grid, list);
},
});
}