Files
Aislo/M02_MasterTemplete/M02_MasterTemplete_Sangeun_Unit.ts
T
eomsangdonandClaude Opus 5.5 08ad680188 feat(728-2): SK 단위 환산 — 기초 기준단위 제안 · 바꾸면 배 · 계수 칸 · 둘째 기초 수량 처음값 · 돈 아닌 기초 뺌
- 서버 Sangeun_Calc: 배 = 바탕 기준단위 → SK 단위(master_unit.swap) · 성격 다름 = 문서 환산 {계수 | 단위중량} · 없으면 셈 · 저장 막음(까닭 글) · 「식」 · 빈 단위 = 옛 셈 그대로(일위대가 줄 모드)
- 화면 셈 답 줄 · 계 = SK 1 단위 몫(per_unit · 화면배) · 머리 띠 「100본 당」 · 「1 본 당」
- 서버 Sangeun_Doc: 환산 칸 검사(계수 양수 · 단위중량 종별 · 형상)
- B09 Labor_Source: SK 참조 배 = 같은 ratio_of(옛 바탕 앞 수 대신 · 기존 문서 같은 값)
- 화면 Sangeun_Detail: SK 단위 처음 값 = 기초 기준단위(「100본」) · 둘째 기초 수량 처음값 = 바탕 기준단위 ÷ 그 기초 기준단위(swapUnit) · 계 칸 원/SK 단위
- 새 Sangeun_Unit: 근거 글 · 환산 계수 칸 · 단위중량 표(CC000337) 고르기
- Cover_Model: 화면 품 × 화면배 = 문서 품(덮개 · 더한줄 · 세부) · 율 그대로
- Find_Pick: 돈 아닌 기초(결과단위 「원」 아님 21 개) 목록에서 뺌
- 낡은 시험 test_715_sangeun_engine(바탕 원/주 + SK ㎡) · test_727(바탕 원/㎡ + SK ㎥) = 성격 다른 단위가 이제 계수 없으면 막혀 SK 단위를 바탕 단위로 고침(금액 같음)
- 새 시험 test_728_2_sk_unit(100본 → 본 1,538.89 · ㎡ 44,791.32 · 계수 · 단위중량 · 식 · 둘째 기초 · 돈 아닌 기초 · 고침 꼴)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 10:52:05 +09:00

104 lines
4.3 KiB
TypeScript

/* =============================================================================
* M02_MasterTemplete_Sangeun_Unit.ts
* 단가산출(SK) 단위 환산 칸(PLAN 728-2 · 요구서_내역19 3장 5) — 바탕 기준단위(「100본」) → SK 단위 근거 글 ·
* 같은 성격 = 배 자동(글만) · 성격 다름 = 환산 계수 칸 · 부피 ↔ 무게 = 단위중량 표(CC000337) 고르기.
* 칸 보임 · 근거 글 = `swapUnit`(짝 `A00_Common/master_unit_swap.ts`) · 셈 = 서버(`M02_Sangeun_Calc.ratio_of`)
* 문서 칸 `환산` {계수 | 단위중량 {종별, 형상}}(꼴 = 서버 `M02_Sangeun_Doc._swap_how`) · 바꿈 = 캐시 → [저장].
* ========================================================================== */
import { el } from "@ui/ui_template_elements";
import { createInputField, createSelectField } from "@ui/ui_template_input";
import { t as L } from "@ui/ui_template_locale";
import { createText } from "@ui/ui_template_text";
import { swapUnit } from "../A00_Common/master_unit_swap";
import { loadTable } from "../M01_MasterData/M01_MasterData_UI_Logic_Note";
export interface SwapHow {
계수?: number;
단위중량?: { 종별: string; 형상: string };
}
const WEIGHT_TABLE = "CC000337";
/** 결과단위 「원/100본」 → 기준단위 「100본」(SK 단위 처음 값) */
export const baseUnitOf = (result: string): string => result.replace(/^원\s*\/\s*/, "").trim();
/** 단위중량 표 줄 → ㎏/㎥(위 끝 · 서버 `master_unit.unit_weight` 기본과 같음) */
const rhoOf = (row: Record<string, unknown> | undefined): number | null =>
row && Number.isFinite(Number(row.위)) ? Number(row.위) : null;
/** 환산 칸 — 「식」 · 빈 단위 · 바탕 없음 = null(옛 셈) */
export function buildUnitSwap(opt: {
result: string;
unit: string;
how: SwapHow | undefined;
edit: boolean;
onChange: (how: SwapHow | undefined) => void;
}): HTMLElement | null {
const have = baseUnitOf(opt.result);
if (!have || !opt.unit || opt.unit === "식") return null;
const how = opt.how ?? {};
const probe = swapUnit(have, opt.unit, 1000, how.계수);
const root = el("div", { className: "m02-sk__tags", attrs: { "data-sk-swap": "" } });
const note = createText("", "muted", 14);
const say = (rho: number | null): void => {
const got = swapUnit(have, opt.unit, rho, how.계수);
note.textContent = got.근거;
note.dataset.skSwapBlocked = got.배 === null ? "1" : "";
};
if (probe.계수 === "사용자") {
const [, ua] = probe.가;
const [, ub] = probe.나;
const box = createInputField({
label: `${L("M02_SangeunSwapCoef")} — 1 ${ua} = ? ${ub}`,
type: "number",
value: how.계수 != null ? String(how.계수) : "",
min: 0,
compact: true,
size: 28,
});
box.input.dataset.skSwapCoef = "";
box.input.disabled = !opt.edit;
box.input.addEventListener("change", () => {
const v = Number(box.input.value);
opt.onChange(Number.isFinite(v) && v > 0 ? { 계수: v } : undefined);
});
root.append(box.root);
} else if (probe.계수 === "단위중량") {
const pick = how.단위중량;
const value = pick ? `${pick.종별}|${pick.형상}` : "";
const select = createSelectField({
label: `${L("M02_SangeunSwapWeight")} (${WEIGHT_TABLE})`,
options: [{ value: "", text: L("M02_SangeunSwapPick") }],
value,
compact: true,
size: 28,
disabled: !opt.edit,
onChange: (v) => {
const [종별, 형상] = v.split("|");
opt.onChange(v ? { 단위중량: { 종별, 형상 } } : undefined);
},
});
select.select.dataset.skSwapWeight = "";
root.append(select.root);
void loadTable(WEIGHT_TABLE).then((table) => {
const rows = table?.줄 ?? [];
select.setOptions(
[
{ value: "", text: L("M02_SangeunSwapPick") },
...rows.map((r) => ({
value: `${String(r.종별)}|${String(r.형상)}`,
text: `${String(r.종별)} · ${String(r.형상)} (${String(r.위)}㎏/㎥)`,
})),
],
value,
);
say(rhoOf(rows.find((r) => r.종별 === pick?.종별 && r.형상 === pick?.형상)));
});
}
say(null);
if (!root.childElementCount && !note.textContent) return null;
root.append(note);
return root;
}