- 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>
104 lines
4.3 KiB
TypeScript
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);
|
|
},
|
|
});
|
|
}
|