/* ============================================================================= * M02_MasterTemplete_Sangeun_Pick.ts * M02 단가산출(SK) 고르기(PLAN 717-4) — 위 층 SK 목록 한 벌 · 단가산출 더한줄 고르기. * · `listLayerDocs` = 층 목록 길(`/layers/{층}/templates` · 종류 하나)을 마스터 › 회사 › 개인 차례로 이음 · * 금액 = 서버가 붙인 1 단위 `기준금액` · `listSangeun` = 종류 `sangeun` · 찾아 넣기 창(`Find_Pick`) 탭 · B09 재료 창고 출처가 씀 * · 고른 SK = 참조 `{층, 주인, 키: SK-…}` — 일위대가 줄은 옛 참조 줄 꼴(서버 `M02_Labor_Expand` 가 펼침) * · `openSangeunLinePicker` = 단가산출 [항목 추가] — 찾아 넣기 창(721-2 · M01 로직 · 인력 · 재료 · 단가산출 · 일위대가) * → SK 문서 `더한줄` 한 줄(PLAN 715 이음 꼴 · 인력 · 재료 = 요소 키 LB · MT · 수량 1) * ========================================================================== */ import { call, type Layer } from "./M02_MasterTemplete_Api_Fetch"; import { fixedOf, openFindPicker } from "./M02_MasterTemplete_Find_Pick"; import type { LaborFixed, LaborRef } from "./M02_MasterTemplete_Labor_Calc"; export const SANGEUN_KIND = "sangeun"; /** 층 차례 — 위에서 아래 */ export const LAYER_ORDER = ["system", "company", "personal"] as const; /** SK 목록 한 줄 */ export interface SangeunRow { ref: LaborRef; 이름: string; 제목: string | null; 단위: string | null; 구분: string | null; 상세구분: string | null; 기준금액: number | null; } interface ListRow { 종류: string; 이름: string; 제목?: string | null; 단위?: string | null; 구분?: string | null; 상세구분?: string | null; 기준금액?: number | null; } /** 위 층 SK — 층 차례(마스터 › 회사 › 개인) · 층 안은 서버 차례 */ export const listSangeun = (scopes: Omit[]): Promise => listLayerDocs(scopes, SANGEUN_KIND); /** 위 층 서고 문서 한 종류(sangeun · precombo) — 층 차례 · 층 안은 서버 차례 */ export async function listLayerDocs( scopes: Omit[], kind: string, ): Promise { const rank = (x: Omit): number => LAYER_ORDER.indexOf(x.층 as (typeof LAYER_ORDER)[number]); const sorted = [...scopes].sort((a, b) => rank(a) - rank(b)); const lists = await Promise.all( sorted.map(async (at) => { const q = at.주인 && at.층 !== "system" ? `?owner=${encodeURIComponent(at.주인)}` : ""; const got = await call<{ 양식: ListRow[] }>(`/layers/${at.층}/templates${q}`); return got.양식 .filter((r) => r.종류 === kind) .map((r) => ({ ref: { 층: at.층, 주인: at.층 === "system" ? null : at.주인, 키: r.이름 }, 이름: r.이름, 제목: r.제목 ?? null, 단위: r.단위 ?? null, 구분: r.구분 ?? null, 상세구분: r.상세구분 ?? null, 기준금액: r.기준금액 ?? null, })); }), ); return lists.flat(); } /** 단가산출 더한줄 한 줄(PLAN 715 이음 꼴) */ export type SangeunLine = | { 종류: "로직"; 로직: string; 입력값: Record; 수량: number } | { 참조: LaborRef; 수량: number } | { 종류: "인력" | "재료"; 요소: string; 이름: string | null; 단위: string | null; 수량: number } | { 고정: LaborFixed; 이름: string; 단위: string | null; 수량: number }; /** 단가산출 [항목 추가] — `scope` = 그 SK 문서 층(고를 수 있는 서고 = 위 층만) */ export function openSangeunLinePicker( scope: { layer: Layer; owner: string | null }, done: (line: SangeunLine) => void, ): void { openFindPicker({ ...scope, logic: (x) => done({ 종류: "로직", 로직: x.키, 입력값: {}, 수량: 1 }), ref: (ref) => done({ 참조: ref, 수량: 1 }), element: (e) => e.종류 !== "기계" && done({ 종류: e.종류, 요소: e.코드, 이름: e.이름, 단위: e.단위, 수량: 1 }), // 736-3 기계 = 고정 줄(이음 기계 EQ · 단가 = 한 시간 노 · 재 · 경) · 수량 1 machine: (e) => done({ 고정: fixedOf(e), 이름: e.이름, 단위: e.단위, 수량: 1 }), }); }