/* ============================================================================= * M02_DF_Material.ts * 검증 칸이 쓰는 재료 찾기 · 이름 · 단가 — 서버 `GET /api/m02/df/materials?q&sub&detail&page&size` * → {total, page, size, items}(아직 없으면 M01 재료 찾기로 대신) · 단가는 `cfValues`(재료 ref = 키) * 모양은 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"; export interface CfMat { ref: string; name: string; spec: string; unit: string; } export interface CfMatPage { total: number; page: number; size: number; 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: { 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)), }; } const names = new Map(); /** 재료 키 → 이름 · 규격 (한 번 물은 것은 다시 안 물음) */ export async function materialOf(key: string): Promise { if (!key) return null; if (names.has(key)) return names.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; } catch { hit = null; } names.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; }