From 1fc2885f76c4dfa746321bf52516d295be796bed Mon Sep 17 00:00:00 2001 From: umsangdon Date: Thu, 1 Oct 2026 20:01:23 +0900 Subject: [PATCH] =?UTF-8?q?refactor(m02-df):=20=EC=9E=AC=EB=A3=8C=20?= =?UTF-8?q?=EC=B0=BE=EA=B8=B0=20=C2=B7=20=EB=8B=A8=EA=B0=80=20=C2=B7=20?= =?UTF-8?q?=EA=B8=88=EC=95=A1=20=ED=91=9C=EC=A4=80=EC=9D=84=20=EC=84=9C?= =?UTF-8?q?=EB=B2=84=20=EA=B8=B8(cfMaterials=20=C2=B7=20cfStandards)?= =?UTF-8?q?=EB=A1=9C=20=EB=B0=94=EA=BE=B8=EA=B3=A0=20=EB=8C=80=EC=8B=A0=20?= =?UTF-8?q?=EA=B8=B8=EC=9D=84=20=EC=A7=80=EC=9B=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Sonnet 5.5 Claude-Session: https://claude.ai/code/session_01EauA2ATmqNRbeV48s9CcBr --- .../DataFlow/M02_DF_Material.ts | 96 +++---------------- M02_MasterTemplete/DataFlow/M02_DF_Round.ts | 31 ++---- 2 files changed, 22 insertions(+), 105 deletions(-) diff --git a/M02_MasterTemplete/DataFlow/M02_DF_Material.ts b/M02_MasterTemplete/DataFlow/M02_DF_Material.ts index 01e1083b2..27204e11a 100644 --- a/M02_MasterTemplete/DataFlow/M02_DF_Material.ts +++ b/M02_MasterTemplete/DataFlow/M02_DF_Material.ts @@ -1,20 +1,13 @@ /* ============================================================================= * M02_DF_Material.ts - * 검증 칸이 쓰는 재료 찾기 · 이름 · 단가 — 서버 `GET /api/m02/df/materials?q&sub&detail&page&size` - * → {total, page, size, items}(아직 없으면 M01 재료 찾기로 대신) · 단가는 `cfValues`(재료 ref = 키) + * 검증 칸이 쓰는 재료 찾기 · 이름 · 단가 — 서버 `GET /api/m02/df/materials`(Api `cfMaterials` · + * 띄어쓰기로 나눈 말을 모두 포함 · 쪽 넘기기) · 단가 = 그 줄의 단가(값을 받는 길과 같은 셈) * 모양은 docs/raw/M01_쉬운단가/흐름도_정함.md 5. 이 폴더째 지워도 됨. * ========================================================================== */ -import { API_BASE_URL } from "@config/config_frontend"; -import { searchElements } from "../../M01_MasterData/M01_MasterData_UI_Logic_Api"; -import { cfValues } from "./M02_DF_Api"; +import { cfMaterials, type CfMaterial } from "./M02_DF_Api"; -export interface CfMat { - ref: string; - name: string; - spec: string; - unit: string; -} +export type CfMat = CfMaterial; export interface CfMatPage { total: number; @@ -23,99 +16,34 @@ export interface CfMatPage { items: CfMat[]; } -const text = (v: unknown): string => - typeof v === "string" || typeof v === "number" ? String(v) : ""; - -const norm = (it: Record): CfMat => ({ - ref: text(it.ref ?? it.키), - name: text(it.이름 ?? it.name), - spec: text(it.규격 ?? it.spec), - unit: text(it.단위 ?? it.unit), -}); - /** 재료 찾기 — q = 찾는 말 · sub = 구분 · detail = 상세구분 · page 는 1 부터 */ -export async function findMaterials(cond: { +export function findMaterials(cond: { q?: string; sub?: string; detail?: string; page?: number; size?: number; }): Promise { - const page = cond.page ?? 1; - const size = cond.size ?? 10; - try { - const qs = new URLSearchParams({ - q: cond.q ?? "", - sub: cond.sub ?? "", - detail: cond.detail ?? "", - page: String(page), - size: String(size), - }); - const r = await fetch(`${API_BASE_URL}/m02/df/materials?${qs.toString()}`, { - credentials: "include", - }); - if (r.ok) { - const d = (await r.json()) as { - total: number; - page?: number; - size?: number; - items: Record[]; - }; - return { - total: d.total, - page: d.page ?? page, - size: d.size ?? size, - items: d.items.map(norm), - }; - } - } catch { - /* 서버 길이 아직 없으면 M01 재료 찾기로 */ - } - const got = await searchElements("재료", cond.q ?? ""); - const all = got.items.filter((it) => { - const x = it as unknown as Record; - return (!cond.sub || x.구분 === cond.sub) && (!cond.detail || x.상세구분 === cond.detail); - }); - const from = (page - 1) * size; - return { - total: all.length, - page, - size, - items: all.slice(from, from + size).map((it) => norm(it as unknown as Record)), - }; + return cfMaterials({ ...cond, page: cond.page ?? 1, size: cond.size ?? 10 }); } -const names = new Map(); +const byKey = new Map(); -/** 재료 키 → 이름 · 규격 (한 번 물은 것은 다시 안 물음) */ +/** 재료 키 → 그 줄(이름 · 규격 · 단가) — 한 번 물은 것은 다시 안 물음 */ export async function materialOf(key: string): Promise { if (!key) return null; - if (names.has(key)) return names.get(key) ?? null; + if (byKey.has(key)) return byKey.get(key) ?? null; let hit: CfMat | null = null; try { - const got = await searchElements("재료", key); - const it = got.items.find((x) => x.ref === key); - hit = it ? norm(it as unknown as Record) : null; + hit = (await cfMaterials({ q: key, size: 20 })).items.find((m) => m.ref === key) ?? null; } catch { hit = null; } - names.set(key, hit); + byKey.set(key, hit); return hit; } -const prices = new Map(); - /** 재료 키 → 단가(원) — 못 구하면 null */ export async function priceOf(key: string): Promise { - if (!key) return null; - if (prices.has(key)) return prices.get(key) ?? null; - let v: number | null = null; - try { - const a = (await cfValues([{ id: "p", group: "재료", ref: key }]))[0]; - v = a?.ok && typeof a.value === "number" ? a.value : null; - } catch { - v = null; - } - prices.set(key, v); - return v; + return (await materialOf(key))?.price ?? null; } diff --git a/M02_MasterTemplete/DataFlow/M02_DF_Round.ts b/M02_MasterTemplete/DataFlow/M02_DF_Round.ts index b4976a9d7..3d1a54d90 100644 --- a/M02_MasterTemplete/DataFlow/M02_DF_Round.ts +++ b/M02_MasterTemplete/DataFlow/M02_DF_Round.ts @@ -2,11 +2,11 @@ * M02_DF_Round.ts * 끝수 기본값 — 금액 단위 표준(산림품셈 1-2-2 「금액의 단위표준」)을 읽어 * 출력(비용) 기본 = 일위대가표 금액란 · 원가 합계 기본 = 일위대가표 계금 (모두 미만 버림) - * 표 읽기 = 서버 `GET /api/m02/df/standards` → {unit, money, saved} · 아직 없으면 `_standard/금액단위표준.json` + * 표 읽기 = 서버 `GET /api/m02/df/standards`(Api `cfStandards`) → {unit, money, saved} * 모양은 docs/raw/M01_쉬운단가/흐름도_정함.md 11 · 12. 이 폴더째 지워도 됨. * ========================================================================== */ -import { API_BASE_URL } from "@config/config_frontend"; +import { cfStandards } from "./M02_DF_Api"; import type { CfRound } from "./M02_DF_Model"; /** 표 한 줄 — 원문 그대로(종목 · 단위 · 지위 · 비고) */ @@ -17,11 +17,6 @@ export interface CfMoneyRow { 비고?: string; } -const FILES = import.meta.glob<{ 줄?: CfMoneyRow[] }>("./_standard/금액단위표준.json", { - eager: true, - import: "default", -}); - /** 표 모양 둘(`{줄: […]}` · 줄 목록)을 줄 목록으로 */ const rowsOf = (x: unknown): CfMoneyRow[] => { const list = Array.isArray(x) ? x : (x as { 줄?: unknown } | null)?.줄; @@ -30,21 +25,15 @@ const rowsOf = (x: unknown): CfMoneyRow[] => { let loaded: Promise | null = null; -/** 금액 단위 표준 줄 — 사용자가 고쳐 저장한 것이 있으면 그것 · 서버가 없으면 처음 값 */ +/** 금액 단위 표준 줄 — 서버가 고친 것(`_data`)이 있으면 그것 · 없으면 처음 값을 줌 */ export function loadMoneyStandard(): Promise { - loaded ??= (async () => { - try { - const r = await fetch(`${API_BASE_URL}/m02/df/standards`, { credentials: "include" }); - if (r.ok) { - const d = (await r.json()) as { money?: unknown; saved?: { money?: unknown } | null }; - const rows = rowsOf(d.saved?.money ?? d.money); - if (rows.length) return rows; - } - } catch { - /* 서버가 없으면 처음 값 */ - } - return rowsOf(Object.values(FILES)[0]); - })(); + loaded ??= cfStandards().then( + (s) => rowsOf(s.money), + () => { + loaded = null; // 못 읽었으면 다음에 다시 — 지금은 정해 둔 기본값으로 + return []; + }, + ); return loaded; }