feat(723-3): 일위대가 줄 모달 = 단가산출 상세 줄 모드(보기 넷) — [적용] = 그 줄 덮개 + 옵션 · 단가산출로도 저장(기본 꺼짐)
- 새 `Labor_RowSk.ts` = 줄 → 이름 없는 SK 문서(lineDoc · 바탕 줄 정체) → 717-2b `mountSangeunDetail` 그대로 얹음 ·
take = 패치 {덮개, 뺀줄, 더한줄}(M02 변경 항목 · M01 안 바뀜) + 옵션(손댄 값만 · 자동값 안 남김)
- `Labor_RowModal.ts` = 717-3 두 보기 갈음 · [적용] 뒤 닫힘 · [단가산출로도 저장] = 개인 층 새 SK(from-line)
- `Sangeun_Detail.ts` handle 에 getValues 한 줄(브레인 허락 · 724 공용 부품이 살림)
- `Labor_Table.ts` = 우클릭 메뉴 두 그림 뒤 엶(칸 초점 밀림에 닫히던 것) · 원문 패널 처음 접힘(표 넓게) · 머리 단추 묶음
- `Hopyo_Relink._total` = 엑셀 수량(본뜬.실무수량)으로 — 705-2 다시 잇기 전 · 후 금액 되살림(723-1 번짐)
- 새 지킴 시험 test_723_labor_table(저장 수량 걷음 · 이은 알약 · 안 줄 알약 · 화면 이음)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
/* =============================================================================
|
||||
* M02_MasterTemplete_Labor_RowSk.ts
|
||||
* 일위대가 줄 모달 안 단가산출 상세 = 717-2b 단가산출(SK) 상세 「줄 모드」(PLAN 723-3 · 정함 4 · 5).
|
||||
* · 줄 → 이름 없는 SK 문서(`lineDoc` · 고름 · 자재표시 = 바탕 줄 정체 cid) → `mountSangeunDetail` 그대로 얹음
|
||||
* (보기 넷 · 품 · 단가 덮개 · 줄 빼기 · 더하기 · 시험 입력 칩)
|
||||
* · `take()` = [적용] 때 그 줄에 남길 것 — 패치 `{덮개, 뺀줄, 더한줄}`(M02 변경 항목 · M01 안 바뀜 · 내역 17-2) +
|
||||
* 옵션(시험 입력 → 그 줄 `입력값` · 정함 5)
|
||||
* · [단가산출로도 저장](기본 꺼짐) = `saveAsSk` — 개인 층 새 SK(`from-line`)
|
||||
* 공용 부품 갈아 끼움은 724(sub2) — 지금은 717-2b 상세를 그대로 씀.
|
||||
* ========================================================================== */
|
||||
|
||||
import { el } from "@ui/ui_template_elements";
|
||||
import { createText } from "@ui/ui_template_text";
|
||||
import { fetchAuto } from "../M01_MasterData/M01_MasterData_UI_Logic_Api";
|
||||
import type { LaborRow } from "./M02_MasterTemplete_Labor_Api";
|
||||
import { calcSangeun, sangeunFromLine, type SkScope } from "./M02_MasterTemplete_Sangeun_Cover";
|
||||
import { mountSangeunDetail } from "./M02_MasterTemplete_Sangeun_Detail";
|
||||
import {
|
||||
cleanPatch,
|
||||
lineDoc,
|
||||
needsIds,
|
||||
type LinePatch,
|
||||
type SkCalc,
|
||||
} from "./M02_Sangeun_Cover_Model";
|
||||
|
||||
export interface RowSkHandle {
|
||||
/** 고친 것(패치 · 옵션) — 없으면 null */
|
||||
take: () => { patch: LinePatch | null; values: Record<string, string> } | null;
|
||||
destroy: () => void;
|
||||
}
|
||||
|
||||
const same = (a: unknown, b: unknown): boolean => JSON.stringify(a) === JSON.stringify(b);
|
||||
|
||||
/** 줄 모드 SK 상세를 `host` 에 — 바탕 줄 정체가 필요하면 먼저 셈 */
|
||||
export function mountRowSk(
|
||||
host: HTMLElement,
|
||||
o: { row: LaborRow; scope: SkScope; title: string; unit: string; readOnly: boolean },
|
||||
): RowSkHandle {
|
||||
let handle: ReturnType<typeof mountSangeunDetail> | null = null;
|
||||
let alive = true;
|
||||
/** 자동값(상세가 빈 입력에 채움) — 손대지 않은 자동값은 줄에 안 남김(빈 값 = 자동값 그대로) */
|
||||
let auto: Record<string, unknown> = {};
|
||||
const before = cleanPatch(o.row.패치);
|
||||
const values0 = Object.fromEntries(
|
||||
Object.entries(o.row.입력값 ?? {}).map(([k, v]) => [k, String(v)]),
|
||||
);
|
||||
host.replaceChildren(createText("…", "muted"));
|
||||
void (async () => {
|
||||
let ids: string[] | null = null;
|
||||
try {
|
||||
if (needsIds(o.row))
|
||||
ids = (await calcSangeun<SkCalc>(o.scope, lineDoc(o.row, null, null))).정체 ?? null;
|
||||
} catch {
|
||||
ids = null; // 정체 못 받음 = 고름 · 자재표시 없이(셈 까닭은 상세가 보임)
|
||||
}
|
||||
if (!alive) return;
|
||||
const doc = { ...lineDoc(o.row, ids, before), 이름: o.title, 단위: o.unit || "식" };
|
||||
const box = el("div", { attrs: { "data-row-sk": "" } });
|
||||
host.replaceChildren(box);
|
||||
handle = mountSangeunDetail(box, doc, {
|
||||
layer: o.scope.layer,
|
||||
owner: o.scope.owner,
|
||||
readOnly: o.readOnly,
|
||||
onChanged: () => undefined,
|
||||
});
|
||||
if (o.row.로직 && !o.row.참조) auto = await fetchAuto(o.row.로직).catch(() => ({}));
|
||||
})();
|
||||
return {
|
||||
take: () => {
|
||||
if (!handle) return null;
|
||||
const d = handle.getDoc();
|
||||
const patch = cleanPatch({
|
||||
덮개: d.덮개 as LinePatch["덮개"],
|
||||
뺀줄: d.뺀줄,
|
||||
더한줄: d.더한줄,
|
||||
});
|
||||
const values = o.row.참조
|
||||
? values0
|
||||
: Object.fromEntries(
|
||||
Object.entries(handle.getValues()).filter(
|
||||
([k, v]) =>
|
||||
String(v).trim() !== "" &&
|
||||
(k in values0 || auto[k] == null || String(auto[k]) !== String(v)),
|
||||
),
|
||||
);
|
||||
return same(patch, before) && same(values, values0) ? null : { patch, values };
|
||||
},
|
||||
destroy: () => {
|
||||
alive = false;
|
||||
handle?.destroy();
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/** [단가산출로도 저장] — 그 줄(고친 패치 포함)을 개인 층 새 SK 로 · 새 이름 돌려줌 */
|
||||
export async function saveAsSk(
|
||||
row: LaborRow,
|
||||
patch: LinePatch | null,
|
||||
name: string,
|
||||
unit: string,
|
||||
): Promise<string> {
|
||||
const line: Record<string, unknown> = { ...row };
|
||||
delete line.패치;
|
||||
delete line.수량;
|
||||
if (patch) line.패치 = patch;
|
||||
const got = await sangeunFromLine({ layer: "personal", owner: null }, line, name, unit || "식");
|
||||
return got.이름;
|
||||
}
|
||||
Reference in New Issue
Block a user