feat(m02-df): 흐름도 서버 — 재료 자리 셋 · 자재 찾기 · 다른 로직 값 · 설계 때 정할 것 · 표준 표 · Eval 과 같은 차례로 다시 셈
- M02_DF_Compute.py — 화면 Eval(evalLogic)과 같은 차례(Model depends) · 선 규칙은 Rule.ts applyRule 과 같은 뜻(값 기준 · 막히면 받는 상자 멈춤) · 끝수 = ROUND 계열 · 함수 시트는 같은 엔진 Node(서로 안 기대는 것은 한 번에) · 다른 로직은 받은 설계 값으로 셈 · 서로 부르면 막음 · 받는 칸에 값만 되돌림 - M02_DF_Values.py(Router 에서 나눔) — 재료 고정 · 선택(고른 품목 · 기본) · 조건 찾기(범위 + 규격/이름 포함/같음 · 0 · 여럿 후보) · 자재 찾기(띄어쓰기 AND · 이름 · 규격 · 키 · 원문번호 · 쪽) · 표준 표 - Router — GET /materials · /design-inputs · POST /logic-value · GET/PUT/DELETE /standards · main.py 등록 - Api — cfMaterials · cfLogicValue · cfDesignInputs · cfStandards(Save · Reset) · slot 물음 - 시험 — 재료 셋 · AND · 다른 로직 · 순환 · 선 규칙 넷 · 끝수 · 설계 때 정할 것 · 표준 표 · 권한 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KmELpdXFDRZHhfbGuRhSmL
This commit is contained in:
@@ -1,13 +1,13 @@
|
||||
/* =============================================================================
|
||||
* M02_DF_Api.ts
|
||||
* 단가산출 다이어그램 Api — 목록(내 것 + 견본) · 열기 · 저장(서버가 입력 값을 마스터에서 다시 받아
|
||||
* 함수 상자 시트를 같은 엔진으로 셈하고 받는 칸에 값만 되돌려 넣음) · 지우기 · 입력 값 한 번에 받기 ·
|
||||
* 사용자 요소. 모양 = sub7 Model(CfLogic · CfGroup · CfUserElement) · 아래는 Api 몫만.
|
||||
* 서버 = `M02_DF_Router.py`(`/api/m02/df/*`) · 정함 `docs/raw/M01_쉬운단가/원가다이어그램_정함.md`
|
||||
* 단가산출 흐름도 Api — 목록(내 것 + 견본) · 열기 · 저장(서버가 입력 값을 마스터에서 다시 받아 화면과
|
||||
* 같은 차례 · 같은 규칙으로 셈하고 받는 칸에 값만 되돌려 넣음) · 지우기 · 입력 값 한 번에 받기 · 사용자 요소 ·
|
||||
* 자재 찾기 · 다른 로직 값 · 설계 때 정할 것 · 단위 · 금액 표준 표. 모양 = sub7 Model · 아래는 Api 몫만.
|
||||
* 서버 = `M02_DF_Router.py`(`/api/m02/df/*`) · 정함 `docs/raw/M01_쉬운단가/흐름도_정함.md`
|
||||
* ========================================================================== */
|
||||
|
||||
import { API_BASE_URL } from "@config/config_frontend";
|
||||
import type { CfGroup, CfLogic, CfUserElement } from "./M02_DF_Model";
|
||||
import type { CfDesign, CfElementRef, CfGroup, CfLogic, CfUserElement } from "./M02_DF_Model";
|
||||
|
||||
/** 돈 로직 결과에서 꺼낼 칸(기계 시간당 경비) */
|
||||
export type CfField = "노무비" | "재료비" | "경비" | "계";
|
||||
@@ -17,7 +17,9 @@ export type CfField = "노무비" | "재료비" | "경비" | "계";
|
||||
* 기존 로직 재료 줄과 같은 단가)
|
||||
* · 유가전력 · 환율 = 그 줄 값 · 요율 = 값 묶음의 field(기본 rate_percent · %)
|
||||
* · 기계 ref = EQ 키 + field(값 칸 — 가격 · 손료계수 …) 또는 `로직(GC…, 기계='…', 지역=지역)` + inputs → 한 시간 값
|
||||
* · 소요량 · 계수 table = {key, row?} → 표 블록(머리 줄 포함 · 조건 칸 → 값 칸 · 범위는 「·아래」 「·위」) */
|
||||
* · 소요량 · 계수 table = {key, row?} → 표 블록(머리 줄 포함 · 조건 칸 → 값 칸 · 범위는 「·아래」 「·위」)
|
||||
* · 재료 자리 slot = 요소 그대로(mode fixed · choice · rule · scope · default) + field · op(조건 찾기 규칙) ·
|
||||
* value = 이어진 알약 값(조건 찾기) · pick = 고른 품목 키(선택) → 단가 · 여럿이면 candidates */
|
||||
export interface CfQuery {
|
||||
id: string;
|
||||
group: CfGroup;
|
||||
@@ -26,6 +28,9 @@ export interface CfQuery {
|
||||
unit?: string;
|
||||
field?: string;
|
||||
inputs?: Record<string, unknown>;
|
||||
slot?: Partial<CfElementRef> & { field?: "규격" | "이름"; op?: "포함" | "같음" };
|
||||
value?: unknown;
|
||||
pick?: string;
|
||||
}
|
||||
|
||||
/** 입력 값 답 — 표는 `rows` · 그 밖은 `value` · 못 구하면 ok false + 쉬운 말 */
|
||||
@@ -37,10 +42,32 @@ export interface CfAnswer {
|
||||
name?: string;
|
||||
unit?: string;
|
||||
reason?: string;
|
||||
/** 재료 조건 찾기가 여럿 맞을 때 후보 다섯 */
|
||||
candidates?: CfMaterial[];
|
||||
}
|
||||
|
||||
/** 서버 계산 결과 — 저장 답 */
|
||||
/** 자재 찾기 한 줄 */
|
||||
export interface CfMaterial {
|
||||
ref: string;
|
||||
name: string;
|
||||
spec: string;
|
||||
unit: string;
|
||||
price: number | null;
|
||||
구분: string;
|
||||
상세구분: string;
|
||||
}
|
||||
|
||||
/** 단위 · 금액 표준 표 — 고친 것(`_data`)이 있으면 saved */
|
||||
export interface CfStandards {
|
||||
unit: { 이름: string; 줄: Record<string, unknown>[]; [k: string]: unknown };
|
||||
money: { 이름: string; 줄: Record<string, unknown>[]; [k: string]: unknown };
|
||||
saved: boolean;
|
||||
}
|
||||
|
||||
/** 서버 계산 결과 — 저장 답(화면 Eval 과 같은 차례 · 같은 규칙 · arrived = 상자마다 받은 값 · breaks = 끊긴 곳) */
|
||||
export interface CfComputed {
|
||||
arrived?: Record<string, Record<string, unknown>>;
|
||||
breaks?: { kind: string; box: string; port?: string; link?: string; text: string }[];
|
||||
/** 상자 id → 내보내는 알약 이름 → 값(표는 칸 덩어리) */
|
||||
ports: Record<string, Record<string, unknown>>;
|
||||
/** 출력 상자 id → 값 */
|
||||
@@ -82,11 +109,11 @@ export class CfError extends Error {
|
||||
}
|
||||
}
|
||||
|
||||
async function send<T>(path: string, body?: unknown): Promise<T> {
|
||||
async function send<T>(path: string, body?: unknown, method?: string): Promise<T> {
|
||||
let response: Response;
|
||||
try {
|
||||
response = await fetch(`${API_BASE_URL}/m02/df${path}`, {
|
||||
method: body === undefined ? "GET" : "POST",
|
||||
method: method ?? (body === undefined ? "GET" : "POST"),
|
||||
credentials: "include",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: body === undefined ? undefined : JSON.stringify(body),
|
||||
@@ -156,3 +183,37 @@ export function cfPlain(e: unknown): string {
|
||||
if (e.status === 400 && text && !/[A-Z]{2}\d{6}|[{}]/.test(text)) return text;
|
||||
return PLAIN[e.status] ?? "저장하지 못함 — 잠시 뒤 다시 해 주세요";
|
||||
}
|
||||
|
||||
/** 자재 찾기 — 띄어쓰기로 나눈 말을 모두 포함(이름 · 규격 · 키 · 원문번호) · 쪽 넘기기 */
|
||||
export async function cfMaterials(q: {
|
||||
q?: string;
|
||||
sub?: string;
|
||||
detail?: string;
|
||||
page?: number;
|
||||
size?: number;
|
||||
}): Promise<{ total: number; page: number; size: number; items: CfMaterial[] }> {
|
||||
const qs = new URLSearchParams(
|
||||
Object.entries(q).flatMap(([k, v]) => (v === undefined || v === "" ? [] : [[k, String(v)]])),
|
||||
);
|
||||
return send(`/materials?${qs.toString()}`);
|
||||
}
|
||||
|
||||
/** 다른 로직 값 — 저장 로직 · 견본을 받은 설계 값(없으면 예시값)으로 서버가 셈 · 출력 이름 → 값 */
|
||||
export async function cfLogicValue(
|
||||
key: string,
|
||||
designs: Record<string, unknown> = {},
|
||||
): Promise<{ outputs: Record<string, unknown>; cost: CfComputed["cost"]; errors: string[] }> {
|
||||
return send("/logic-value", { key, designs });
|
||||
}
|
||||
|
||||
/** 설계 때 정할 것 — 변수 · 재료 자리 · 다른 로직 받는 알약(프로젝트 일위대가가 쓸 꼴) */
|
||||
export async function cfDesignInputs(key: string): Promise<CfDesign[]> {
|
||||
const qs = new URLSearchParams({ key }).toString();
|
||||
return (await send<{ designs: CfDesign[] }>(`/design-inputs?${qs}`)).designs;
|
||||
}
|
||||
|
||||
/** 단위 · 금액 표준 표 읽기 · 고치기(시스템 관리자) · 처음 값으로 */
|
||||
export const cfStandards = (): Promise<CfStandards> => send("/standards");
|
||||
export const cfStandardsSave = (body: Omit<CfStandards, "saved">): Promise<CfStandards> =>
|
||||
send("/standards", body, "PUT");
|
||||
export const cfStandardsReset = (): Promise<CfStandards> => send("/standards", undefined, "DELETE");
|
||||
|
||||
Reference in New Issue
Block a user