- 좌측 「내 기계」 · 「내 품목」 칸(펼치면 가운데 화면) — 목록(이름 · 규격 · 방식 · 시간당 · 쓰는 곳 · 넣은 · 고친 날 · 찾기) → 양식(821-2 부품 · 바로 넣기 기본 · 저장 때만 서버) - 단가산출 줄 쌓기 기계 고르기에 「내 기계」 묶음 · [새 기계 만들기] · 품셈 기계 줄 「복사해 내 기계로」 - 수식 머리 배지 — 값만 바뀜 = 「새 값 있음」 · 지운 키 = 「지워짐 n」 · [단가 갱신] 확인 창에 바뀐 자원 줄 - 기계 양식 state 에 방식 · 시간당 직접 꼴 · 확인창 글 줄바꿈 그대로 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
157 lines
4.9 KiB
TypeScript
157 lines
4.9 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 { 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.원문번호,
|
|
});
|