Files
Aislo/M02_MasterTemplete/M02_MyMachine_Api.ts
T
eomsangdonandClaude Opus 5.5 2149351b34 fix(827-1): 기계 창 [확인] 직후 금액 즉시 — 확인 길이 그 식 셈 기록을 줌
- 서버 확인 길(my-machines/draft) = 화면이 정한 표지로 그 식 한 줄 셈 기록(요소 · 표 · 식 문서) 돌려줌
- 화면은 기록을 계산기 캐시에 합침 → 서버 왕복 전 0 원 깜빡임 없음(미리 셈 값과 같음)
- 기계 창 목록 열 이름 「구분」 · 폭 조정
- 시험 test_827_1 ⑦ 셈 기록 확인 더함

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-13 10:36:33 +09:00

198 lines
6.1 KiB
TypeScript

/* =============================================================================
* M02_MyMachine_Api.ts
* M02 내 기계 · 내 품목 서버 호출(PLAN 821-3) — 개인 층만.
* 내 기계 = `/layers/personal/my-machines`(821-1 · `M02_MyMachine_Router`) — 목록 · 하나 · 만들기 · 고치기 · 지우기
* 양식 목록 · 비슷한 기계 찾기 · 내 품목 = `M02_MyMachine_Look`(읽기만)
* ========================================================================== */
import type { MachinePick, MachineValues } from "@ui/ui_template_machine_form";
import type { DocRecord } from "../common_util/common_util_formula_doc_cache";
import { call } from "./M02_MasterTemplete_Api_Fetch";
import type { M01Element } from "./M02_MasterTemplete_Find_Pick";
export type MachineHow = "바로" | "품셈" | "직접";
type Costs = Record<"노무비" | "재료비" | "경비", number>;
/** 서버 시간당 셈 답 — ok 아님 = 까닭 */
export interface MyHourly extends Partial<Costs> {
ok: boolean;
계?: number;
로직?: string | null;
직접?: boolean;
reason?: string;
}
/** 내 기계 줄(저장 꼴) */
export interface MyMachine {
키: string;
원문번호: string;
이름: string;
규격: string;
방식: MachineHow;
값: MachineValues;
시간당?: Costs;
비고?: string;
넣은날: string;
고친날: string;
본뜬?: string;
}
export interface MyMachineRow extends Omit<MyMachine, "시간당"> {
시간당: MyHourly;
쓰는곳수: number;
}
export interface Use {
키: string;
이름: string;
}
export interface MyMachineOne {
줄: MyMachine;
시간당: MyHourly;
같은이름: { 키: string; 이름: string; 규격: string; 출처: string }[];
쓰는곳?: Use[];
}
/** 보내는 줄 — 방식 · 값 또는 시간당(직접) */
export interface MyMachineBody {
이름: string;
규격: string;
방식: MachineHow;
값?: MachineValues;
시간당?: Partial<Costs>;
}
export interface MachineLists {
fuels: MachinePick[];
jobs: MachinePick[];
power: number;
hour: number;
}
export interface SimilarRow {
키: string;
원문번호?: string;
이름: string;
규격: string;
구분: string;
값?: MachineValues;
방식?: MachineHow;
시간당?: Costs;
출처: "개인" | "M01";
}
export interface MyItem {
이름: string;
규격: string;
단위: string;
값: unknown;
쓰는곳: Use[];
}
const at = (owner: string | null, tail = "", q: Record<string, string> = {}): string => {
const ask = new URLSearchParams({ ...q, ...(owner ? { owner } : {}) }).toString();
return `/layers/personal/my-machines${tail}${ask ? `?${ask}` : ""}`;
};
const look = (owner: string | null, path: string, q: Record<string, string> = {}): string => {
const ask = new URLSearchParams({ ...q, ...(owner ? { owner } : {}) }).toString();
return `/layers/personal/${path}${ask ? `?${ask}` : ""}`;
};
const key = (k: string): string => `/${encodeURIComponent(k)}`;
export const listMyMachines = async (owner: string | null): Promise<MyMachineRow[]> =>
(await call<{ 줄: MyMachineRow[] }>(at(owner))).줄;
export const readMyMachine = (owner: string | null, k: string): Promise<MyMachineOne> =>
call(at(owner, key(k)));
export const createMyMachine = (
owner: string | null,
body: MyMachineBody,
base?: string,
): Promise<MyMachineOne> =>
call(at(owner), { method: "POST", body: JSON.stringify({ 줄: body, 본뜬: base ?? null }) });
export const updateMyMachine = (
owner: string | null,
k: string,
body: MyMachineBody,
): Promise<MyMachineOne> =>
call(at(owner, key(k)), { method: "PUT", body: JSON.stringify({ 줄: body }) });
export const deleteMyMachine = (owner: string | null, k: string): Promise<{ 쓰는곳: Use[] }> =>
call(at(owner, key(k)), { method: "DELETE" });
let lists: Promise<MachineLists> | null = null;
/** 양식 고르기 목록 — 한 번 받아 둠 */
export const fetchMyMachineLists = (): Promise<MachineLists> =>
(lists ??= call<MachineLists>("/my-machine-lists").catch((e) => {
lists = null;
return Promise.reject(e);
}));
export const findSimilar = async (owner: string | null, q: string): Promise<SimilarRow[]> =>
(await call<{ rows: SimilarRow[] }>(look(owner, "my-machine-find", { q }))).rows;
export const listMyItems = async (owner: string | null): Promise<MyItem[]> =>
(await call<{ rows: MyItem[] }>(look(owner, "my-items"))).rows;
/** 단가산출 줄 기계 입력 글(줄 쌓기 `기계='개인 EQP…'`) */
export const machineArg = (no: string): string => `'${no}'`;
/** 내 기계 → 기계 고르기 한 줄(`M01Element` 꼴 · 줄 쌓기 = 로직 + 기계='개인 EQP…') */
export const mineElement = (
row: Pick<MyMachine, "키" | "원문번호" | "이름" | "규격">,
h: MyHourly,
): M01Element => ({
종류: "기계",
코드: row.키,
이름: row.이름,
규격: row.규격,
단위: "시간",
값: h.ok ? (h.계 ?? null) : null,
단가: { 노무비: h.노무비 ?? 0, 재료비: h.재료비 ?? 0, 경비: h.경비 ?? 0 },
로직: h.로직 ?? undefined,
원문번호: row.원문번호,
});
/** 기계 창 [확인](827-1) — 초안 몸 검사 · 셈 꼴 값 · 시간당(식 키) · 그 식 셈 기록(계산기 캐시) · 쓰기 없음 */
export interface DraftCheck {
줄: MyMachine;
셈값: Record<string, unknown>;
시간당: MyHourly;
연결: DocRecord;
}
export const checkDraft = (
owner: string | null,
body: MyMachineBody,
target: { 표지: string; 키?: string; 본뜬?: string },
): Promise<DraftCheck> =>
call(at(owner, "/draft"), {
method: "POST",
body: JSON.stringify({
줄: body,
표지: target.표지,
키: target.키 ?? null,
본뜬: target.본뜬 ?? null,
}),
});
/** M01 기계 줄 값 + 시간당(기계 창 목록 · 양식 · 60 까지) */
export interface MachineBrief {
키: string;
원문번호: string;
이름: string;
규격: string;
값: MachineValues;
시간당: MyHourly;
}
export const machineRows = async (keys: string[]): Promise<MachineBrief[]> =>
keys.length
? (
await call<{ rows: MachineBrief[] }>(
`/logic-lib/machine-rows?keys=${encodeURIComponent(keys.join(","))}`,
)
).rows
: [];