- 면적산출 편집 화면 알약 막대 위 한 줄(일위대가 키 · 이름 · 담은 로직 수 · 같이 쓰는 다른 열 수 · 본뜬키) + [조합 고치기](시스템 관리자만) - 담은 로직 표(더하기 = M01 로직 찾기 · 빼기 · 차례 · 메모) → [적용] 때 갈라 내기 모달(이름 자동 미리 채움) → 새 조합 알림 → 알약만 다시 받음(시트 고침 유지) - 재료산출 엑셀 옆 접히는 판에 자재 조합 담은 자재 표 · 더하기 · 빼기(이은 칸이면 연결도 풂 확인) · [적용] 모달 - 서버 길(branchCombo · branchMaterialCombo · 자재 조합 읽기)은 아직 안 올라와 M02_MasterTemplete_Combo_Api.ts 한 곳에 가정 모양으로 둠 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NWHNLQYPZN7kKf1rzrrRZq
101 lines
4.5 KiB
TypeScript
101 lines
4.5 KiB
TypeScript
/* =============================================================================
|
|
* M02_MasterTemplete_Combo_Api.ts
|
|
* 면적산출 조합 고치기 · 재료산출 자재 목록이 부르는 서버 길 — 갈라 내기 한 번에(새 조합 + 그 열만 새 키).
|
|
* ⚠ 서버(sub4 `branchCombo` · `branchMaterialCombo`) · 자재 조합 표(sub3 UM)가 아직 안 올라옴 —
|
|
* 아래 길 · 응답 모양은 PLAN 15장 · `14_조합편집검토.md` 1장 기준 가정. 올라오면 이 파일만 맞춤.
|
|
* ========================================================================== */
|
|
|
|
import { API_BASE_URL } from "@config/config_frontend";
|
|
import type { ComboLogic } from "../M01_MasterData/M01_MasterData_UI_Combo_Api";
|
|
import { ApiError } from "../M01_MasterData/M01_MasterData_UI_Logic_Api";
|
|
import { readTemplate } from "./M02_MasterTemplete_Api_Fetch";
|
|
|
|
/** 구조물집계표 이름 — `M02_MasterTemplete_Structure.STRUCTURE_TABLE` 과 같은 글 */
|
|
const STRUCTURE_TABLE = "구조물집계표";
|
|
|
|
export interface MaterialItem {
|
|
코드: string;
|
|
이름: string;
|
|
규격: string;
|
|
단위: string;
|
|
}
|
|
|
|
/** 자재 조합 한 줄(UM) — 담은 자재 목록 · 본뜬키 = 갈라 내기 전 원래 조합 */
|
|
export interface MaterialCombo {
|
|
키: string;
|
|
이름: string;
|
|
담은자재: MaterialItem[];
|
|
본뜬키?: string | null;
|
|
}
|
|
|
|
/** 갈라 내기 결과 — 새로만듦 false = 같은 내용의 있는 조합을 씀 */
|
|
export interface BranchResult {
|
|
키: string;
|
|
이름: string;
|
|
새로만듦: boolean;
|
|
}
|
|
|
|
/** 집계표 열이 가리키는 조합 키 + 같은 조합을 쓰는 다른 열 수 */
|
|
export interface ColumnBase {
|
|
일위대가: string | null;
|
|
자재조합: string | null;
|
|
다른열일위대가: number;
|
|
다른열자재조합: number;
|
|
}
|
|
|
|
async function request<T>(path: string, body?: unknown): Promise<T> {
|
|
const response = await fetch(`${API_BASE_URL}${path}`, {
|
|
method: body === undefined ? "GET" : "POST",
|
|
credentials: "include",
|
|
headers: { "Content-Type": "application/json" },
|
|
body: body === undefined ? undefined : JSON.stringify(body),
|
|
});
|
|
const data = (await response.json().catch(() => ({}))) as { detail?: unknown } & T;
|
|
if (!response.ok) throw new ApiError(response.status, data.detail ?? response.statusText);
|
|
return data;
|
|
}
|
|
|
|
/** 서버가 준 까닭 글 — 422 는 검사 글 목록 */
|
|
export function reasonOf(error: unknown): string {
|
|
if (error instanceof ApiError && typeof error.detail === "object" && error.detail) {
|
|
const d = error.detail as { errors?: string[] };
|
|
if (d.errors) return d.errors.join(" / ");
|
|
}
|
|
return error instanceof Error ? error.message : "";
|
|
}
|
|
|
|
/** 집계표(시스템 층)에서 이 열의 일위대가 · 자재조합 키와 같이 쓰는 다른 열 수 */
|
|
export async function readColumnBase(column: string): Promise<ColumnBase> {
|
|
type Col = { id: string; 일위대가?: string | null; 자재조합?: string | null };
|
|
const table = await readTemplate("system", "table", STRUCTURE_TABLE, null).catch(() => null);
|
|
const cols = ((table?.문서 as { 열?: Col[] } | null)?.열 ?? []) as Col[];
|
|
const mine = cols.find((c) => c.id === column);
|
|
const same = (key: string | null | undefined, pick: (c: Col) => string | null | undefined) =>
|
|
key ? cols.filter((c) => c.id !== column && pick(c) === key).length : 0;
|
|
return {
|
|
일위대가: mine?.일위대가 || null,
|
|
자재조합: mine?.자재조합 || null,
|
|
다른열일위대가: same(mine?.일위대가, (c) => c.일위대가),
|
|
다른열자재조합: same(mine?.자재조합, (c) => c.자재조합),
|
|
};
|
|
}
|
|
|
|
/** 고친 담은 로직으로 새 조합을 만들고 이 열만 새 조합을 가리킴(같은 내용이면 있는 조합) */
|
|
export const branchCombo = (
|
|
column: string,
|
|
body: { 본뜬키: string; 담은로직: ComboLogic[]; 이름: string },
|
|
): Promise<BranchResult> => request(`/m02/structures/${encodeURIComponent(column)}/combo`, body);
|
|
|
|
/** 자재 조합 한 줄 읽기(M01 자재 조합 표 UM) */
|
|
export const fetchMaterialCombo = (key: string): Promise<MaterialCombo> =>
|
|
request<{ combo: MaterialCombo }>(`/m01/material-combo?key=${encodeURIComponent(key)}`).then(
|
|
(d) => d.combo,
|
|
);
|
|
|
|
/** 고친 담은 자재로 새 자재 조합을 만들고 이 열만 가리킴(같은 내용이면 있는 조합) */
|
|
export const branchMaterialCombo = (
|
|
column: string,
|
|
body: { 본뜬키: string; 담은자재: MaterialItem[]; 이름: string },
|
|
): Promise<BranchResult> =>
|
|
request(`/m02/structures/${encodeURIComponent(column)}/material-combo`, body);
|