4007042311
[ECR(Engineering Change Request) 관리]
- ecr_mng / product_mgmt / part_mng 테이블 + seq_ecr_no 시퀀스
- 설변요청 코드(0000090) 자식 코드 시드 (설계오류/품질개선/원가절감/고객요청/법규대응/부품단종)
- API: 목록/상세/등록·수정(merge)/조치완료/삭제 + 옵션(작성자/제품/부품/공통코드)
- 화면: 필터바, 그리드, 등록·수정 모달, 상세 모달, 조치완료 모달
[고객 CS 관리]
- customer_cs_mng 테이블 (기존 customer_mng 거래처 마스터와 충돌 회피)
- 공통코드 5종 카테고리(0000200~0000204) 자동 시드: 관리유형/제품구분/담당자/조치유형/CS상태
- API: 목록/상세/등록·수정/삭제/대시보드(요약·상태별·관리유형별·제품구분별)
- 화면: 요약 카드 4종, 10종 필터바, 14컬럼 그리드, 등록·수정·상세 모달
[결재(APPROVAL) 시스템 — wace_plm ApprovalService 포팅]
- approval / route / inboxtask / approval_target / approval_kind / amaranth_approval 6개 테이블
- 라이프사이클: 상신(startApproval) → 결재함(listInbox) → 승인/반려(approveTask/rejectTask)
→ 다음 결재자 ready 자동 전달, 마지막이면 route+approval+target 일괄 complete
- target_type 별 도메인 status 동기화 훅 (ECR_MNG/CUSTOMER_MNG)
- API: /api/wace-approval/{inbox,start,inbox/:id/approve|reject,by-target,:id,:id/amaranth-link}
[Amaranth(Wehago) 전자결재 RestAPI 연계]
- 외부 커넥션 'Amaranth - 결재' 자동 시드 (auth_config: callerName/accessToken/hashKey/groupSeq/aesKey)
- amaranthApprovalClient: 자바 AmaranthApprovalApiClient 1:1 포팅
HMAC-SHA256 wehago-sign / AES-128-CBC empSeq 암호화 / HTTPS / JSON 파싱
- 6개 endpoint: 인증토큰/결재함/문서목록/문서상세/SSO URL/문서상신
- 하드코딩 0건 — DB 외부 커넥션의 인증 정보를 매 호출 시 로드
- 통신 검증 완료 (dummy empSeq 로 응답 정상 수신)
- 프록시 라우트 /api/amaranth-approval/{box,docs,docs/:id,sso,submit,auth-token}
[wace_plm 데이터 import]
- WacePlmDataImportService: source PG 클라이언트 → 우리 DB ON CONFLICT DO NOTHING idempotent
- 환경변수 WACE_PLM_DB_* 만 읽음 (운영 비번 코드 0건, 미설정 시 명시적 에러)
- /api/wace-import/{all,ecr,cs,masters,approval} (SUPER_ADMIN 전용)
[Bugfix]
- 배치 편집 conditional 매핑 silent drop 방지 — 평가 필드/규칙 누락 시
어느 컬럼이 어떤 이유로 빠졌는지 toast 로 명시 + 저장 차단
- 시드 topup 강화 — extra_auth_config(aesKey 등) 누락된 기존 레코드 자동 보강
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
94 lines
2.8 KiB
TypeScript
94 lines
2.8 KiB
TypeScript
/**
|
|
* ECR(Engineering Change Request) 관리 API 클라이언트
|
|
* - 백엔드: backend-node/src/routes/ecrMngRoutes.ts
|
|
*/
|
|
import { apiClient } from "./client";
|
|
|
|
export interface EcrItem {
|
|
objid: string;
|
|
ecr_no: string;
|
|
product_name?: string;
|
|
product_objid?: string;
|
|
upg_no?: string;
|
|
part_no?: string;
|
|
part_name?: string;
|
|
part_objid?: string;
|
|
request_cd?: string;
|
|
request_name?: string;
|
|
title: string;
|
|
writer?: string;
|
|
writer_name?: string;
|
|
status_cd?: string;
|
|
status_name?: string;
|
|
check_user_id?: string;
|
|
check_name?: string;
|
|
before_contents?: string;
|
|
after_contents?: string;
|
|
reg_date?: string;
|
|
check_date?: string;
|
|
}
|
|
|
|
export interface EcrListResponse {
|
|
success: boolean;
|
|
list: EcrItem[];
|
|
pagination: { page: number; pageSize: number; total: number; totalPages: number };
|
|
}
|
|
|
|
export interface EcrListParams {
|
|
year?: string;
|
|
productCode?: string;
|
|
requestCode?: string;
|
|
writer?: string;
|
|
statusCode?: string;
|
|
page?: number;
|
|
pageSize?: number;
|
|
}
|
|
|
|
export const ecrMngApi = {
|
|
list: async (params: EcrListParams = {}): Promise<EcrListResponse> => {
|
|
const { data } = await apiClient.get("/ecr", { params });
|
|
return data;
|
|
},
|
|
|
|
detail: async (objId: string | number): Promise<EcrItem> => {
|
|
const { data } = await apiClient.get(`/ecr/${objId}`);
|
|
return data.data;
|
|
},
|
|
|
|
/** 등록/수정 (objId 가 있으면 update) */
|
|
merge: async (payload: {
|
|
objId?: string | number;
|
|
title: string;
|
|
product_objid?: string | number | null;
|
|
part_objid?: string | number | null;
|
|
request_codeArr?: string;
|
|
before_contents?: string;
|
|
after_contents?: string;
|
|
}): Promise<{ objid: string; ecr_no: string; status_cd: string }> => {
|
|
const { data } = await apiClient.post("/ecr", payload);
|
|
return data.data;
|
|
},
|
|
|
|
/** 조치완료 — status → 0000102 */
|
|
complete: async (objId: string | number, after_contents: string) => {
|
|
const { data } = await apiClient.post(`/ecr/${objId}/complete`, { after_contents });
|
|
return data;
|
|
},
|
|
|
|
remove: async (objIds: string[]) => {
|
|
const { data } = await apiClient.delete("/ecr", { data: { objIds } });
|
|
return data;
|
|
},
|
|
|
|
// 옵션 — 드롭다운/체크박스용
|
|
writerOptions: async (): Promise<Array<{ value: string; label: string }>> =>
|
|
(await apiClient.get("/ecr/options/writers")).data.data,
|
|
productOptions: async (): Promise<Array<{ value: string; label: string }>> =>
|
|
(await apiClient.get("/ecr/options/products")).data.data,
|
|
partOptions: async (): Promise<Array<{ value: string; label: string }>> =>
|
|
(await apiClient.get("/ecr/options/parts")).data.data,
|
|
/** parentCodeId='0000090' (요청코드) / '0000099' (상태) */
|
|
commCodeOptions: async (parentCodeId: string): Promise<Array<{ value: string; label: string }>> =>
|
|
(await apiClient.get(`/ecr/options/codes/${parentCodeId}`)).data.data,
|
|
};
|