50669a66ee
· 메인 그리드 5컬럼(제품구분/제목/WBS/등록자/등록일) + 통합 팝업(트리 CRUD + 엑셀 임포트 + 템플릿 다운로드) · 운영 매핑: pms_wbs_template(헤더) + pms_wbs_task_standard(트리) — 활성 갈래 확정 (_info/_standard2 갈래는 2021년 멈춘 레거시) · wace mergeExcelUploadWBS 1:1: 신규=헤더+트리 INSERT, 수정=트리 일괄 DELETE→INSERT (헤더 변경 없음) · objid 채번 gen_random_uuid()::text, 엑셀 파싱 xlsx(SheetJS), 정적 템플릿 frontend/public/templates/ · DataGrid 컬럼 단위 onClick 추가 (WBS 폴더 셀 클릭용) · DDL: 8개 테이블 162컬럼 (docs/migration/project/ddl-extracted/200_pms_wbs.sql) / GAP: docs/migration/project/02-wbs-template.md · 프로젝트 자동 복사/진행관리 연계는 wace도 미완성 — P2 범위 외 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
114 lines
3.1 KiB
TypeScript
114 lines
3.1 KiB
TypeScript
import { apiClient } from "./client";
|
|
|
|
// ─── 타입 (wace project.xml wbsTemplateMngGridList 1:1) ─────
|
|
|
|
export interface TemplateRow {
|
|
objid: string;
|
|
product_objid: string | null;
|
|
product_name: string | null; // CODE_NAME(PRODUCT_OBJID)
|
|
title: string | null;
|
|
writer: string | null;
|
|
writer_title: string | null; // DEPT_NAME || USER_NAME
|
|
reg_date: string | null;
|
|
reg_date_title: string | null; // YYYY-MM-DD
|
|
wbs_task_cnt: number | string | null;
|
|
customer_product: string | null;
|
|
}
|
|
|
|
export interface TemplateMaster {
|
|
objid: string;
|
|
product_objid: string;
|
|
product_objid_name: string;
|
|
title: string;
|
|
writer: string;
|
|
reg_date: string;
|
|
customer_product: string;
|
|
}
|
|
|
|
export interface TemplateTask {
|
|
objid: string;
|
|
parent_objid: string;
|
|
task_name: string;
|
|
task_seq: string;
|
|
task_level: string;
|
|
user_id: string;
|
|
user_id_title: string;
|
|
writer: string;
|
|
reg_date: string;
|
|
unit_no: string;
|
|
upper_task_objid: string;
|
|
}
|
|
|
|
export interface TemplateDetail {
|
|
master: TemplateMaster;
|
|
tasks: TemplateTask[];
|
|
}
|
|
|
|
// 저장 payload — wace mergeExcelUploadWBS의 폼 hidden 직렬화에 대응
|
|
export interface WbsTaskInput {
|
|
WBS_TASK_OBJID: string;
|
|
TASK_NAME: string;
|
|
UNIT_NO: string;
|
|
UPPER_TASK_OBJID: string;
|
|
TASK_LEVEL: string;
|
|
}
|
|
|
|
export interface SaveTemplatePayload {
|
|
templateObjId?: string; // 있으면 수정, 없으면 신규
|
|
product: string;
|
|
title: string;
|
|
customer_product?: string;
|
|
tasks: WbsTaskInput[]; // TOTAL 행 포함 (TASK_LEVEL=0)
|
|
}
|
|
|
|
// 엑셀 파싱 결과
|
|
export interface ParsedExcelRow {
|
|
WBS_OBJID: string;
|
|
UNIT_NO: string;
|
|
TASK_NAME: string;
|
|
}
|
|
|
|
// ─── API ────────────────────────────────────────────────
|
|
|
|
export const wbsTemplateApi = {
|
|
async list(product?: string): Promise<TemplateRow[]> {
|
|
const res = await apiClient.get("/project/wbs-template", {
|
|
params: product ? { product } : {},
|
|
});
|
|
return (res.data?.data ?? []) as TemplateRow[];
|
|
},
|
|
|
|
async detail(objid: string): Promise<TemplateDetail | null> {
|
|
const res = await apiClient.get(`/project/wbs-template/${objid}`);
|
|
return res.data?.data ?? null;
|
|
},
|
|
|
|
async checkDuplicate(product: string, title: string): Promise<boolean> {
|
|
const res = await apiClient.get("/project/wbs-template/check-duplicate", {
|
|
params: { product, title },
|
|
});
|
|
return Boolean(res.data?.data?.duplicate);
|
|
},
|
|
|
|
async save(payload: SaveTemplatePayload) {
|
|
const res = await apiClient.post("/project/wbs-template", payload);
|
|
return res.data;
|
|
},
|
|
|
|
async remove(objids: string[]) {
|
|
const res = await apiClient.delete("/project/wbs-template", {
|
|
data: { objids },
|
|
});
|
|
return res.data;
|
|
},
|
|
|
|
async parseExcel(file: File): Promise<ParsedExcelRow[]> {
|
|
const form = new FormData();
|
|
form.append("file", file);
|
|
const res = await apiClient.post("/project/wbs-template/parse-excel", form, {
|
|
headers: { "Content-Type": "multipart/form-data" },
|
|
});
|
|
return (res.data?.data ?? []) as ParsedExcelRow[];
|
|
},
|
|
};
|