- 새 M02_Hopyo_Row — 단가표 시트(자재단가 · 노임단가 · 기계경비총괄표 · 기계경비적용기준 · 단가산출 · 일위대가 총괄표 · STmate 목록표 코드) → 엑셀 사전(갈래 + M01 키 후보 한 번) · 세부행 4 단계(비고 번호 → 별도계상 → 단위 → 사전) · 후보 차례 장부 → M01 표마다(LB · MT · MO · EQ · FX) → M02 층 SK · SC · 판정 넷(제안 있음 · 2차 필요 · 후보 여럿 · 후보 없음) · 고른 것 꼴 · 수량 = 엑셀 × 몫 × 배 - factor 를 Row 로 옮김(Match.factor 는 부름만) - Elem 유가 후보(oil_rows · oils · lost 유가) · Ledger 짝 고른 것 꼴 넓힘(갈래 · 키 머리 · M01 있음 · 율 비목 · 기준 재검사 · 옛 꼴 그대로) - 고정 줄 이음 유가 MO(LINKS · GROUPS 재료 · 재료비 = MO 값) · 일위대가 자재 목록 MO 허용(Labor_Doc 두 줄 · 줄 수 그대로) - 화면 찾아 넣기 「M01 전체」 탭 유가 줄(oil) · 일위대가 = 고정 줄 이음 유가 · 단가산출 = 더한줄 재료 요소 MO · TS GROUPS 짝 - 시험 새 test_642_3_row(북부청 415 줄 = 단산 268 · 일위 1 · 별도계상 64 · 재료 78 · 기계 3 · 율 1 · 사방 201 · 거창 68 모두 갈래 하나 · 사전 · 장부 짝 · 환산 · MO 고정 셈 · 율 TS 거울) - 낡은 시험 고침: test_721 의 FindKind 글 대조에 oil 더함(종류 하나 늘어난 까닭) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
97 lines
4.5 KiB
TypeScript
97 lines
4.5 KiB
TypeScript
/* =============================================================================
|
|
* 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<LaborRef, "키">[]): Promise<SangeunRow[]> =>
|
|
listLayerDocs(scopes, SANGEUN_KIND);
|
|
|
|
/** 위 층 서고 문서 한 종류(sangeun · precombo) — 층 차례 · 층 안은 서버 차례 */
|
|
export async function listLayerDocs(
|
|
scopes: Omit<LaborRef, "키">[],
|
|
kind: string,
|
|
): Promise<SangeunRow[]> {
|
|
const rank = (x: Omit<LaborRef, "키">): 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<SangeunRow>((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<string, never>; 수량: 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.종류 === "인력" || e.종류 === "재료") &&
|
|
done({ 종류: e.종류, 요소: e.코드, 이름: e.이름, 단위: e.단위, 수량: 1 }),
|
|
// 785-3 유가전력 = 더한줄 재료 요소 MO
|
|
oil: (e) => done({ 종류: "재료", 요소: e.코드, 이름: e.이름, 단위: e.단위, 수량: 1 }),
|
|
// 736-3 기계 = 고정 줄(이음 기계 EQ · 단가 = 한 시간 노 · 재 · 경) · 수량 1
|
|
machine: (e) => done({ 고정: fixedOf(e), 이름: e.이름, 단위: e.단위, 수량: 1 }),
|
|
});
|
|
}
|