diff options
| -rw-r--r-- | config/projectsColumnsConfig.ts | 62 | ||||
| -rw-r--r-- | db/schema/projects.ts | 87 | ||||
| -rw-r--r-- | lib/projects/dialog/project-detail-dialog.tsx | 431 | ||||
| -rw-r--r-- | lib/projects/table/projects-table-columns.tsx | 29 | ||||
| -rw-r--r-- | lib/projects/table/projects-table.tsx | 25 | ||||
| -rw-r--r-- | lib/soap/mdg/mapper/project-mapper.ts | 171 |
6 files changed, 775 insertions, 30 deletions
diff --git a/config/projectsColumnsConfig.ts b/config/projectsColumnsConfig.ts index d5fd2f99..45f292cc 100644 --- a/config/projectsColumnsConfig.ts +++ b/config/projectsColumnsConfig.ts @@ -11,32 +11,74 @@ export interface ProjectColumnConfig { export const projectsColumnsConfig: ProjectColumnConfig[] = [ { id: "code", - label: "Project Code", + label: "프로젝트 코드", excelHeader: "Project Code", - // group: "Basic Info", + group: "기본 정보", }, { id: "name", - label: "Project Name", + label: "프로젝트명", excelHeader: "Project Name", - // group: "Basic Info", + group: "기본 정보", }, { id: "type", - label: "Project Type", + label: "프로젝트 타입", excelHeader: "Project Type", - // group: "Basic Info", + group: "기본 정보", + }, + { + id: "OWN_NM", + label: "선주명", + excelHeader: "Owner Name", + group: "주요 정보", + }, + { + id: "CLS_1", + label: "선급1", + excelHeader: "Classification 1", + group: "주요 정보", + }, + { + id: "CLS_2", + label: "선급2", + excelHeader: "Classification 2", + group: "주요 정보", + }, + { + id: "DOCK_CD", + label: "도크", + excelHeader: "Dock Code", + group: "주요 정보", + }, + { + id: "SHTYPE_CD", + label: "선형코드", + excelHeader: "Ship Type Code", + group: "주요 정보", + }, + { + id: "PRGS_STAT", + label: "진행상태", + excelHeader: "Progress Status", + group: "상태 정보", + }, + { + id: "CNRT_DT", + label: "계약일자", + excelHeader: "Contract Date", + group: "상태 정보", }, { id: "createdAt", - label: "Created At", + label: "생성일", excelHeader: "Created At", - // group: "Metadata",a + group: "메타데이터", }, { id: "updatedAt", - label: "Updated At", + label: "수정일", excelHeader: "Updated At", - // group: "Metadata", + group: "메타데이터", }, ]
\ No newline at end of file diff --git a/db/schema/projects.ts b/db/schema/projects.ts index e4e2553a..81f4043b 100644 --- a/db/schema/projects.ts +++ b/db/schema/projects.ts @@ -2,10 +2,89 @@ import { pgTable, varchar, text, timestamp, char, decimal, serial, uniqueIndex } export const projects = pgTable("projects", { id: serial("id").primaryKey(), - code: varchar("code", { length: 50 }).notNull(), - name: text("name").notNull(), - type: varchar("type", { length: 20 }).default("ship").notNull(), - // pspid: char('pspid', { length: 24 }).unique(), // 프로젝트ID = code 필드 + // 기존 정보 + code: varchar("code", { length: 50 }).notNull(), // PROJ_NO 으로, PSPID와 동일 (나준규 프로 확인) + name: text("name").notNull(), // PROJ_DSC + type: varchar("type", { length: 20 }).default("ship").notNull(), // TYPE 기반으로 산출하며, null 값인 경우 ship으로 처리 + + // MDG 를 위한 컬럼 확장 - PROJECT_MASTER_CMCTB_PROJ_MAST의 모든 컬럼 + AS_GRNT_PRD: varchar("AS_GRNT_PRD", { length: 1000 }), // A/S 보증기간 + BIZCLS: varchar("BIZCLS", { length: 1000 }), // 사업부 + BIZLOC_CD: varchar("BIZLOC_CD", { length: 1000 }), // 사업장코드 + BIZ_DMN: varchar("BIZ_DMN", { length: 1000 }), // 사업영역 + BP_DL_DT: varchar("BP_DL_DT", { length: 1000 }), // 선표인도일자 + CHN_PROJ_TP: varchar("CHN_PROJ_TP", { length: 1000 }), // (중국)프로젝트타입 + CLS_1: varchar("CLS_1", { length: 1000 }), // 선급1 + CLS_2: varchar("CLS_2", { length: 1000 }), // 선급2 + CNRT_CNTN_YN: varchar("CNRT_CNTN_YN", { length: 1000 }), // 계약존속여부 + CNRT_DL_DT: varchar("CNRT_DL_DT", { length: 1000 }), // 계약인도일자 + CNRT_DT: varchar("CNRT_DT", { length: 1000 }), // 계약일자 + CNRT_RESV_YN: varchar("CNRT_RESV_YN", { length: 1000 }), // 계약유보여부 + CO_CD: varchar("CO_CD", { length: 1000 }), // 회사코드 + CSTM_PO_NO: varchar("CSTM_PO_NO", { length: 1000 }), // 고객발주번호 + DEL_YN: varchar("DEL_YN", { length: 1000 }), // 삭제 여부 + DIGT_PDT_GRP: varchar("DIGT_PDT_GRP", { length: 1000 }), // 전기전자 제품군 + DIST_PATH: varchar("DIST_PATH", { length: 1000 }), // 유통경로 + DL_BF_PROJ_NM: varchar("DL_BF_PROJ_NM", { length: 1000 }), // 인도전선명 + DL_CSTM_CD: varchar("DL_CSTM_CD", { length: 1000 }), // 인도고객 ID + DOCK_CD: varchar("DOCK_CD", { length: 1000 }), // 도크 + DSN_CHRGR: varchar("DSN_CHRGR", { length: 1000 }), // 설계담당자 + FIN_GRNT_FN_DT: varchar("FIN_GRNT_FN_DT", { length: 1000 }), // 최종수요자 보증종료일 + GENT_CNT: varchar("GENT_CNT", { length: 1000 }), // 세대수/시리즈 + GOV: varchar("GOV", { length: 1000 }), // 관청명 + GRNT_STDT: varchar("GRNT_STDT", { length: 1000 }), // Project Warranty Start Date + IF_STAT: varchar("IF_STAT", { length: 1000 }), // 인터페이스 진행단계 + IMO_NO: varchar("IMO_NO", { length: 1000 }), // IMO 번호 + INQY_NO: varchar("INQY_NO", { length: 1000 }), // 안건번호 + INQY_SEQ: varchar("INQY_SEQ", { length: 1000 }), // 안건순번 + IO_GB: varchar("IO_GB", { length: 1000 }), // 사내외 구분 + MNG_ACOT_DMN: varchar("MNG_ACOT_DMN", { length: 1000 }), // 관리회계영역 + MN_ENGN_TP_CD: varchar("MN_ENGN_TP_CD", { length: 1000 }), // Main engine type code + MSHIP_NO: varchar("MSHIP_NO", { length: 1000 }), // 기준호선 + NEW_MC_YN: varchar("NEW_MC_YN", { length: 1000 }), // MC YN + NTTP: varchar("NTTP", { length: 1000 }), // 국적 + ORDR_GRNT_FN_DT: varchar("ORDR_GRNT_FN_DT", { length: 1000 }), // 주문주 보증종료일 + ORDR_GRNT_PRD: varchar("ORDR_GRNT_PRD", { length: 1000 }), // 주문주 보증기간 + OWN_1: varchar("OWN_1", { length: 1000 }), // 선주1 + OWN_AB: varchar("OWN_AB", { length: 1000 }), // 선주약어 + OWN_NM: varchar("OWN_NM", { length: 1000 }), // 선주명 + PDT_LVL_4: varchar("PDT_LVL_4", { length: 1000 }), // 제품 Level 4 + PLNT_CD: varchar("PLNT_CD", { length: 1000 }), // 플랜트 코드 + PRCTR: varchar("PRCTR", { length: 1000 }), // 손익센터 + PRGS_STAT: varchar("PRGS_STAT", { length: 1000 }), // 진행상태 + PROJ_CRTE_REQ_DT: varchar("PROJ_CRTE_REQ_DT", { length: 1000 }), // 프로젝트 생성요청일 + PROJ_CRTE_REQ_EMPNO: varchar("PROJ_CRTE_REQ_EMPNO", { length: 1000 }), // 프로젝트 생성요청자 + PROJ_DL_PLN_DT: varchar("PROJ_DL_PLN_DT", { length: 1000 }), // 모프로젝트 인도계획일 + PROJ_DL_RT_DT: varchar("PROJ_DL_RT_DT", { length: 1000 }), // 모프로젝트 인도실적일 + PROJ_DTL_TP: varchar("PROJ_DTL_TP", { length: 1000 }), // 프로젝트 세부타입 + PROJ_ETC_TP: varchar("PROJ_ETC_TP", { length: 1000 }), // 프로젝트 기타타입 + PROJ_GB: varchar("PROJ_GB", { length: 1000 }), // 프로젝트구분 + PROJ_PRGS_YN: varchar("PROJ_PRGS_YN", { length: 1000 }), // 공사진행여부 + PROJ_PROF: varchar("PROJ_PROF", { length: 1000 }), // 프로젝트 프로파일 + PROJ_SCP: varchar("PROJ_SCP", { length: 1000 }), // 프로젝트범위 + PROJ_WBS_TP: varchar("PROJ_WBS_TP", { length: 1000 }), // 프로젝트 WBS타입 + PRO_PROJ_NO: varchar("PRO_PROJ_NO", { length: 1000 }), // 프로포절 프로젝트 + QM_CLS: varchar("QM_CLS", { length: 1000 }), // 품질사업부 + REF_NO: varchar("REF_NO", { length: 1000 }), // 시리즈번호 + RLTD_PROJ: varchar("RLTD_PROJ", { length: 1000 }), // 연관프로젝트 + RL_DL_DT: varchar("RL_DL_DT", { length: 1000 }), // 실인도일자 + SALE_GRP: varchar("SALE_GRP", { length: 1000 }), // 영업그룹 + SALE_ORG_CD: varchar("SALE_ORG_CD", { length: 1000 }), // 영업조직 + SA_DT: varchar("SA_DT", { length: 1000 }), // Sail Away Date + SERS_NO: varchar("SERS_NO", { length: 1000 }), // 시리즈첫공사번호 + SERS_YN: varchar("SERS_YN", { length: 1000 }), // 시리즈여부 + SHTYPE: varchar("SHTYPE", { length: 1000 }), // 선형 + SHTYPE_CD: varchar("SHTYPE_CD", { length: 1000 }), // 선형코드 + SHTYPE_GRP: varchar("SHTYPE_GRP", { length: 1000 }), // 선형군 + SHTYPE_UOM: varchar("SHTYPE_UOM", { length: 1000 }), // 선형단위 + SKND: varchar("SKND", { length: 1000 }), // 선종 + SRC_SYS_ID: varchar("SRC_SYS_ID", { length: 1000 }), // Source System + STDT: varchar("STDT", { length: 1000 }), // 시작일자 + SYS_ACOT_CLSD_DT: varchar("SYS_ACOT_CLSD_DT", { length: 1000 }), // 시스템회계마감일자 + TOT_CNRT_CNT: varchar("TOT_CNRT_CNT", { length: 1000 }), // 전체 계약 대수 + TYPE: varchar("TYPE", { length: 1000 }), // 프로젝트 Top/Hull (원본 TYPE 컬럼) + WP_PROJ_TP: varchar("WP_PROJ_TP", { length: 1000 }), // (풍력)프로젝트타입 + createdAt: timestamp("created_at").defaultNow().notNull(), updatedAt: timestamp("updated_at").defaultNow().notNull(), }) diff --git a/lib/projects/dialog/project-detail-dialog.tsx b/lib/projects/dialog/project-detail-dialog.tsx new file mode 100644 index 00000000..2ecb37a5 --- /dev/null +++ b/lib/projects/dialog/project-detail-dialog.tsx @@ -0,0 +1,431 @@ +"use client" + +import * as React from "react" +import { type Project } from "@/db/schema/projects" + +import { + Dialog, + DialogContent, + DialogDescription, + DialogHeader, + DialogTitle, +} from "@/components/ui/dialog" +import { + Table, + TableBody, + TableCell, + TableRow, +} from "@/components/ui/table" +import { Badge } from "@/components/ui/badge" +import { formatDate } from "@/lib/utils" + +interface ProjectDetailDialogProps { + project: Project + open: boolean + onOpenChange: (open: boolean) => void +} + +export function ProjectDetailDialog({ + project, + open, + onOpenChange, +}: ProjectDetailDialogProps) { + const formatValue = (value: string | null | undefined) => { + return value || "-" + } + + return ( + <Dialog open={open} onOpenChange={onOpenChange}> + <DialogContent className="max-w-6xl h-[90vh] flex flex-col"> + <DialogHeader className="flex-shrink-0"> + <DialogTitle className="flex items-center gap-2"> + 프로젝트 상세 정보 + <Badge variant="outline">{project.code}</Badge> + </DialogTitle> + <DialogDescription> + 프로젝트코드: {project.code} | {project.name} + </DialogDescription> + </DialogHeader> + + <div className="flex-1 overflow-y-auto min-h-0"> + <div className="space-y-6 p-4"> + <h3 className="text-lg font-semibold mb-3">프로젝트 전체 정보</h3> + <Table> + <TableBody> + {/* 기본 프로젝트 정보 */} + <TableRow> + <TableCell className="font-medium w-1/4">프로젝트 코드</TableCell> + <TableCell>{formatValue(project.code)}</TableCell> + </TableRow> + <TableRow> + <TableCell className="font-medium">프로젝트명</TableCell> + <TableCell>{formatValue(project.name)}</TableCell> + </TableRow> + <TableRow> + <TableCell className="font-medium">프로젝트 타입</TableCell> + <TableCell> + <Badge variant={project.type === "ship" ? "default" : "secondary"}> + {project.type === "ship" ? "조선" : "해양"} + </Badge> + </TableCell> + </TableRow> + + {/* 선주 및 기본 정보 */} + <TableRow> + <TableCell className="font-medium">선주명</TableCell> + <TableCell>{formatValue(project.OWN_NM)}</TableCell> + </TableRow> + <TableRow> + <TableCell className="font-medium">선주약어</TableCell> + <TableCell>{formatValue(project.OWN_AB)}</TableCell> + </TableRow> + <TableRow> + <TableCell className="font-medium">선주1</TableCell> + <TableCell>{formatValue(project.OWN_1)}</TableCell> + </TableRow> + + {/* 선급 정보 */} + <TableRow> + <TableCell className="font-medium">선급1</TableCell> + <TableCell>{formatValue(project.CLS_1)}</TableCell> + </TableRow> + <TableRow> + <TableCell className="font-medium">선급2</TableCell> + <TableCell>{formatValue(project.CLS_2)}</TableCell> + </TableRow> + + {/* 선박 정보 */} + <TableRow> + <TableCell className="font-medium">선종</TableCell> + <TableCell>{formatValue(project.SKND)}</TableCell> + </TableRow> + <TableRow> + <TableCell className="font-medium">선형</TableCell> + <TableCell>{formatValue(project.SHTYPE)}</TableCell> + </TableRow> + <TableRow> + <TableCell className="font-medium">선형코드</TableCell> + <TableCell>{formatValue(project.SHTYPE_CD)}</TableCell> + </TableRow> + <TableRow> + <TableCell className="font-medium">선형군</TableCell> + <TableCell>{formatValue(project.SHTYPE_GRP)}</TableCell> + </TableRow> + <TableRow> + <TableCell className="font-medium">선형단위</TableCell> + <TableCell>{formatValue(project.SHTYPE_UOM)}</TableCell> + </TableRow> + + {/* 도크 및 건조 정보 */} + <TableRow> + <TableCell className="font-medium">도크</TableCell> + <TableCell>{formatValue(project.DOCK_CD)}</TableCell> + </TableRow> + <TableRow> + <TableCell className="font-medium">기준호선</TableCell> + <TableCell>{formatValue(project.MSHIP_NO)}</TableCell> + </TableRow> + + {/* 계약 정보 */} + <TableRow> + <TableCell className="font-medium">계약일자</TableCell> + <TableCell>{formatValue(project.CNRT_DT)}</TableCell> + </TableRow> + <TableRow> + <TableCell className="font-medium">계약인도일자</TableCell> + <TableCell>{formatValue(project.CNRT_DL_DT)}</TableCell> + </TableRow> + <TableRow> + <TableCell className="font-medium">실인도일자</TableCell> + <TableCell>{formatValue(project.RL_DL_DT)}</TableCell> + </TableRow> + <TableRow> + <TableCell className="font-medium">선표인도일자</TableCell> + <TableCell>{formatValue(project.BP_DL_DT)}</TableCell> + </TableRow> + <TableRow> + <TableCell className="font-medium">Sail Away Date</TableCell> + <TableCell>{formatValue(project.SA_DT)}</TableCell> + </TableRow> + <TableRow> + <TableCell className="font-medium">고객발주번호</TableCell> + <TableCell>{formatValue(project.CSTM_PO_NO)}</TableCell> + </TableRow> + <TableRow> + <TableCell className="font-medium">계약존속여부</TableCell> + <TableCell>{formatValue(project.CNRT_CNTN_YN)}</TableCell> + </TableRow> + <TableRow> + <TableCell className="font-medium">계약유보여부</TableCell> + <TableCell>{formatValue(project.CNRT_RESV_YN)}</TableCell> + </TableRow> + <TableRow> + <TableCell className="font-medium">전체 계약 대수</TableCell> + <TableCell>{formatValue(project.TOT_CNRT_CNT)}</TableCell> + </TableRow> + + {/* 프로젝트 상태 */} + <TableRow> + <TableCell className="font-medium">진행상태</TableCell> + <TableCell>{formatValue(project.PRGS_STAT)}</TableCell> + </TableRow> + <TableRow> + <TableCell className="font-medium">공사진행여부</TableCell> + <TableCell>{formatValue(project.PROJ_PRGS_YN)}</TableCell> + </TableRow> + <TableRow> + <TableCell className="font-medium">시작일자</TableCell> + <TableCell>{formatValue(project.STDT)}</TableCell> + </TableRow> + <TableRow> + <TableCell className="font-medium">인터페이스 진행단계</TableCell> + <TableCell>{formatValue(project.IF_STAT)}</TableCell> + </TableRow> + + {/* 기술 정보 */} + <TableRow> + <TableCell className="font-medium">IMO 번호</TableCell> + <TableCell>{formatValue(project.IMO_NO)}</TableCell> + </TableRow> + <TableRow> + <TableCell className="font-medium">국적</TableCell> + <TableCell>{formatValue(project.NTTP)}</TableCell> + </TableRow> + <TableRow> + <TableCell className="font-medium">Main engine type code</TableCell> + <TableCell>{formatValue(project.MN_ENGN_TP_CD)}</TableCell> + </TableRow> + <TableRow> + <TableCell className="font-medium">관청명</TableCell> + <TableCell>{formatValue(project.GOV)}</TableCell> + </TableRow> + + {/* 조직 정보 */} + <TableRow> + <TableCell className="font-medium">사업부</TableCell> + <TableCell>{formatValue(project.BIZCLS)}</TableCell> + </TableRow> + <TableRow> + <TableCell className="font-medium">사업장코드</TableCell> + <TableCell>{formatValue(project.BIZLOC_CD)}</TableCell> + </TableRow> + <TableRow> + <TableCell className="font-medium">사업영역</TableCell> + <TableCell>{formatValue(project.BIZ_DMN)}</TableCell> + </TableRow> + <TableRow> + <TableCell className="font-medium">영업그룹</TableCell> + <TableCell>{formatValue(project.SALE_GRP)}</TableCell> + </TableRow> + <TableRow> + <TableCell className="font-medium">영업조직</TableCell> + <TableCell>{formatValue(project.SALE_ORG_CD)}</TableCell> + </TableRow> + <TableRow> + <TableCell className="font-medium">손익센터</TableCell> + <TableCell>{formatValue(project.PRCTR)}</TableCell> + </TableRow> + <TableRow> + <TableCell className="font-medium">설계담당자</TableCell> + <TableCell>{formatValue(project.DSN_CHRGR)}</TableCell> + </TableRow> + <TableRow> + <TableCell className="font-medium">회사코드</TableCell> + <TableCell>{formatValue(project.CO_CD)}</TableCell> + </TableRow> + <TableRow> + <TableCell className="font-medium">플랜트 코드</TableCell> + <TableCell>{formatValue(project.PLNT_CD)}</TableCell> + </TableRow> + <TableRow> + <TableCell className="font-medium">관리회계영역</TableCell> + <TableCell>{formatValue(project.MNG_ACOT_DMN)}</TableCell> + </TableRow> + <TableRow> + <TableCell className="font-medium">품질사업부</TableCell> + <TableCell>{formatValue(project.QM_CLS)}</TableCell> + </TableRow> + + {/* 프로젝트 세부 정보 */} + <TableRow> + <TableCell className="font-medium">프로젝트 세부타입</TableCell> + <TableCell>{formatValue(project.PROJ_DTL_TP)}</TableCell> + </TableRow> + <TableRow> + <TableCell className="font-medium">프로젝트 기타타입</TableCell> + <TableCell>{formatValue(project.PROJ_ETC_TP)}</TableCell> + </TableRow> + <TableRow> + <TableCell className="font-medium">프로젝트구분</TableCell> + <TableCell>{formatValue(project.PROJ_GB)}</TableCell> + </TableRow> + <TableRow> + <TableCell className="font-medium">프로젝트 프로파일</TableCell> + <TableCell>{formatValue(project.PROJ_PROF)}</TableCell> + </TableRow> + <TableRow> + <TableCell className="font-medium">프로젝트범위</TableCell> + <TableCell>{formatValue(project.PROJ_SCP)}</TableCell> + </TableRow> + <TableRow> + <TableCell className="font-medium">프로젝트 WBS타입</TableCell> + <TableCell>{formatValue(project.PROJ_WBS_TP)}</TableCell> + </TableRow> + <TableRow> + <TableCell className="font-medium">원본 TYPE</TableCell> + <TableCell>{formatValue(project.TYPE)}</TableCell> + </TableRow> + <TableRow> + <TableCell className="font-medium">(중국)프로젝트타입</TableCell> + <TableCell>{formatValue(project.CHN_PROJ_TP)}</TableCell> + </TableRow> + <TableRow> + <TableCell className="font-medium">(풍력)프로젝트타입</TableCell> + <TableCell>{formatValue(project.WP_PROJ_TP)}</TableCell> + </TableRow> + + {/* 시리즈 정보 */} + <TableRow> + <TableCell className="font-medium">시리즈여부</TableCell> + <TableCell>{formatValue(project.SERS_YN)}</TableCell> + </TableRow> + <TableRow> + <TableCell className="font-medium">시리즈첫공사번호</TableCell> + <TableCell>{formatValue(project.SERS_NO)}</TableCell> + </TableRow> + <TableRow> + <TableCell className="font-medium">시리즈번호</TableCell> + <TableCell>{formatValue(project.REF_NO)}</TableCell> + </TableRow> + <TableRow> + <TableCell className="font-medium">세대수/시리즈</TableCell> + <TableCell>{formatValue(project.GENT_CNT)}</TableCell> + </TableRow> + <TableRow> + <TableCell className="font-medium">연관프로젝트</TableCell> + <TableCell>{formatValue(project.RLTD_PROJ)}</TableCell> + </TableRow> + + {/* 제품 정보 */} + <TableRow> + <TableCell className="font-medium">제품 Level 4</TableCell> + <TableCell>{formatValue(project.PDT_LVL_4)}</TableCell> + </TableRow> + <TableRow> + <TableCell className="font-medium">전기전자 제품군</TableCell> + <TableCell>{formatValue(project.DIGT_PDT_GRP)}</TableCell> + </TableRow> + + {/* 프로젝트 관리 정보 */} + <TableRow> + <TableCell className="font-medium">프로젝트 생성요청일</TableCell> + <TableCell>{formatValue(project.PROJ_CRTE_REQ_DT)}</TableCell> + </TableRow> + <TableRow> + <TableCell className="font-medium">프로젝트 생성요청자</TableCell> + <TableCell>{formatValue(project.PROJ_CRTE_REQ_EMPNO)}</TableCell> + </TableRow> + <TableRow> + <TableCell className="font-medium">모프로젝트 인도계획일</TableCell> + <TableCell>{formatValue(project.PROJ_DL_PLN_DT)}</TableCell> + </TableRow> + <TableRow> + <TableCell className="font-medium">모프로젝트 인도실적일</TableCell> + <TableCell>{formatValue(project.PROJ_DL_RT_DT)}</TableCell> + </TableRow> + <TableRow> + <TableCell className="font-medium">프로포절 프로젝트</TableCell> + <TableCell>{formatValue(project.PRO_PROJ_NO)}</TableCell> + </TableRow> + + {/* 안건 정보 */} + <TableRow> + <TableCell className="font-medium">안건번호</TableCell> + <TableCell>{formatValue(project.INQY_NO)}</TableCell> + </TableRow> + <TableRow> + <TableCell className="font-medium">안건순번</TableCell> + <TableCell>{formatValue(project.INQY_SEQ)}</TableCell> + </TableRow> + + {/* 보증 정보 */} + <TableRow> + <TableCell className="font-medium">A/S 보증기간</TableCell> + <TableCell>{formatValue(project.AS_GRNT_PRD)}</TableCell> + </TableRow> + <TableRow> + <TableCell className="font-medium">Project Warranty Start Date</TableCell> + <TableCell>{formatValue(project.GRNT_STDT)}</TableCell> + </TableRow> + <TableRow> + <TableCell className="font-medium">주문주 보증기간</TableCell> + <TableCell>{formatValue(project.ORDR_GRNT_PRD)}</TableCell> + </TableRow> + <TableRow> + <TableCell className="font-medium">주문주 보증종료일</TableCell> + <TableCell>{formatValue(project.ORDR_GRNT_FN_DT)}</TableCell> + </TableRow> + <TableRow> + <TableCell className="font-medium">최종수요자 보증종료일</TableCell> + <TableCell>{formatValue(project.FIN_GRNT_FN_DT)}</TableCell> + </TableRow> + + {/* 기타 정보 */} + <TableRow> + <TableCell className="font-medium">MC YN</TableCell> + <TableCell>{formatValue(project.NEW_MC_YN)}</TableCell> + </TableRow> + <TableRow> + <TableCell className="font-medium">사내외 구분</TableCell> + <TableCell>{formatValue(project.IO_GB)}</TableCell> + </TableRow> + <TableRow> + <TableCell className="font-medium">유통경로</TableCell> + <TableCell>{formatValue(project.DIST_PATH)}</TableCell> + </TableRow> + <TableRow> + <TableCell className="font-medium">인도전선명</TableCell> + <TableCell>{formatValue(project.DL_BF_PROJ_NM)}</TableCell> + </TableRow> + <TableRow> + <TableCell className="font-medium">인도고객 ID</TableCell> + <TableCell>{formatValue(project.DL_CSTM_CD)}</TableCell> + </TableRow> + + {/* 시스템 정보 */} + <TableRow> + <TableCell className="font-medium">시스템회계마감일자</TableCell> + <TableCell>{formatValue(project.SYS_ACOT_CLSD_DT)}</TableCell> + </TableRow> + <TableRow> + <TableCell className="font-medium">Source System</TableCell> + <TableCell>{formatValue(project.SRC_SYS_ID)}</TableCell> + </TableRow> + <TableRow> + <TableCell className="font-medium">삭제 여부</TableCell> + <TableCell> + {project.DEL_YN ? ( + <Badge variant="destructive">삭제됨</Badge> + ) : ( + <Badge variant="secondary">활성</Badge> + )} + </TableCell> + </TableRow> + + {/* 생성/수정 정보 */} + <TableRow> + <TableCell className="font-medium">생성일시</TableCell> + <TableCell>{formatDate(project.createdAt, "KR")}</TableCell> + </TableRow> + <TableRow> + <TableCell className="font-medium">수정일시</TableCell> + <TableCell>{formatDate(project.updatedAt, "KR")}</TableCell> + </TableRow> + </TableBody> + </Table> + </div> + </div> + </DialogContent> + </Dialog> + ) +} diff --git a/lib/projects/table/projects-table-columns.tsx b/lib/projects/table/projects-table-columns.tsx index 6926429a..95eeae85 100644 --- a/lib/projects/table/projects-table-columns.tsx +++ b/lib/projects/table/projects-table-columns.tsx @@ -3,8 +3,10 @@ import * as React from "react" import { type DataTableRowAction } from "@/types/table" import { type ColumnDef } from "@tanstack/react-table" +import { Eye } from "lucide-react" import { formatDate } from "@/lib/utils" +import { Button } from "@/components/ui/button" import { DataTableColumnHeaderSimple } from "@/components/data-table/data-table-column-simple-header" import { Project } from "@/db/schema" @@ -12,13 +14,35 @@ import { projectsColumnsConfig } from "@/config/projectsColumnsConfig" interface GetColumnsProps { setRowAction: React.Dispatch<React.SetStateAction<DataTableRowAction<Project> | null>> + onDetailClick: (project: Project) => void } /** * tanstack table 컬럼 정의 (중첩 헤더 버전) */ -export function getColumns({ setRowAction }: GetColumnsProps): ColumnDef<Project>[] { +// eslint-disable-next-line @typescript-eslint/no-unused-vars +export function getColumns({ setRowAction, onDetailClick }: GetColumnsProps): ColumnDef<Project>[] { + // 상세보기 버튼 컬럼 + const detailColumn: ColumnDef<Project> = { + id: "action", + header: "상세보기", + size: 100, + cell: ({ row }) => { + const project = row.original + return ( + <Button + variant="ghost" + size="sm" + onClick={() => onDetailClick(project)} + className="h-8 w-8 p-0" + > + <Eye className="h-4 w-4" /> + <span className="sr-only">상세보기</span> + </Button> + ) + }, + } // ---------------------------------------------------------------- // 3) 일반 컬럼들을 "그룹"별로 묶어 중첩 columns 생성 @@ -82,9 +106,10 @@ export function getColumns({ setRowAction }: GetColumnsProps): ColumnDef<Project }) // ---------------------------------------------------------------- - // 4) 최종 컬럼 배열: select, nestedColumns, actions + // 4) 최종 컬럼 배열: detailColumn, nestedColumns // ---------------------------------------------------------------- return [ + detailColumn, ...nestedColumns, ] }
\ No newline at end of file diff --git a/lib/projects/table/projects-table.tsx b/lib/projects/table/projects-table.tsx index 3da54b7c..462e8638 100644 --- a/lib/projects/table/projects-table.tsx +++ b/lib/projects/table/projects-table.tsx @@ -16,6 +16,7 @@ import { getColumns } from "./projects-table-columns" import { getProjectLists } from "../service" import { Project } from "@/db/schema" import { ProjectTableToolbarActions } from "./projects-table-toolbar-actions" +import { ProjectDetailDialog } from "@/lib/projects/dialog/project-detail-dialog" interface ItemsTableProps { promises: Promise< @@ -26,17 +27,28 @@ interface ItemsTableProps { } export function ProjectsTable({ promises }: ItemsTableProps) { + // eslint-disable-next-line @typescript-eslint/no-unused-vars const { featureFlags } = useFeatureFlags() const [{ data, pageCount }] = React.use(promises) + // eslint-disable-next-line @typescript-eslint/no-unused-vars const [rowAction, setRowAction] = React.useState<DataTableRowAction<Project> | null>(null) + // 상세보기 다이얼로그 상태 관리 + const [selectedProject, setSelectedProject] = React.useState<Project | null>(null) + const [dialogOpen, setDialogOpen] = React.useState(false) + + const handleDetailClick = React.useCallback((project: Project) => { + setSelectedProject(project) + setDialogOpen(true) + }, []) + const columns = React.useMemo( - () => getColumns({ setRowAction }), - [setRowAction] + () => getColumns({ setRowAction, onDetailClick: handleDetailClick }), + [setRowAction, handleDetailClick] ) /** @@ -123,6 +135,15 @@ export function ProjectsTable({ promises }: ItemsTableProps) { <ProjectTableToolbarActions table={table} /> </DataTableAdvancedToolbar> </DataTable> + + {/* 프로젝트 상세보기 다이얼로그 */} + {selectedProject && ( + <ProjectDetailDialog + project={selectedProject} + open={dialogOpen} + onOpenChange={setDialogOpen} + /> + )} </> ) } diff --git a/lib/soap/mdg/mapper/project-mapper.ts b/lib/soap/mdg/mapper/project-mapper.ts index 6de2b38a..43238731 100644 --- a/lib/soap/mdg/mapper/project-mapper.ts +++ b/lib/soap/mdg/mapper/project-mapper.ts @@ -76,14 +76,7 @@ export async function mapAndSaveMDGProjectData( /** * MDG 프로젝트 데이터를 비즈니스 테이블 projects 구조로 변환 - * - id: serial("id").primaryKey(), << 자동 - code: varchar("code", { length: 50 }).notNull(), - name: text("name").notNull(), - type: varchar("type", { length: 20 }).default("ship").notNull(), - pspid: char('pspid', { length: 24 }).unique(), // 프로젝트ID (ECC), TODO: 매핑 필요 - createdAt: timestamp("created_at").defaultNow().notNull(), - updatedAt: timestamp("updated_at").defaultNow().notNull(), + * 모든 MDG 컬럼을 비즈니스 테이블에 매핑 */ function mapMDGToProject(mdgProject: MDGProjectData): ProjectData | null { try { @@ -93,16 +86,94 @@ function mapMDGToProject(mdgProject: MDGProjectData): ProjectData | null { return null; } - // 현재는 기본 구조만 제공 + // MDG의 모든 컬럼을 비즈니스 테이블에 매핑 const mappedProject: ProjectData = { + // 기존 매핑 컬럼들 code: mdgProject.PROJ_NO || '', name: mdgProject.PROJ_DSC || '', type: checkProjectType(mdgProject.TYPE || ''), // 기본값, 필요시 매핑 로직 추가 // type 매핑 방법: TYPE 네임스페이스에서 null 값을 수신한 경우 조선(ship)이고, 그 외는 해양(plant)이다. // 수신할 수 있는 경우의 수는 H, T, H/T, null 인데, 필요시 hull / top 구분 처리하자. 현재는 조선/해양 구분만 필요하고, 기존 코드들도 plant 값인지 ship 값인지만 따지고 있다. // 의미상으로는 H = 해양 Hull, T = 해양 Top, H/T = 해양 Hull과 Top 둘 다 하는 프로젝트 인데, 일단은 조선/해양 구분만 ship/plant 값을 넣어주는 것으로 하자. - // TODO: pspid를 구해야 하는데 mdg에서 안주는 것 같음. 나프로에게 문의함. - pspid: mdgProject.PROJ_NO || null, // ECC 프로젝트 ID와 연결 + + // MDG의 모든 컬럼 매핑 (그대로 수신) + AS_GRNT_PRD: mdgProject.AS_GRNT_PRD || null, + BIZCLS: mdgProject.BIZCLS || null, + BIZLOC_CD: mdgProject.BIZLOC_CD || null, + BIZ_DMN: mdgProject.BIZ_DMN || null, + BP_DL_DT: mdgProject.BP_DL_DT || null, + CHN_PROJ_TP: mdgProject.CHN_PROJ_TP || null, + CLS_1: mdgProject.CLS_1 || null, + CLS_2: mdgProject.CLS_2 || null, + CNRT_CNTN_YN: mdgProject.CNRT_CNTN_YN || null, + CNRT_DL_DT: mdgProject.CNRT_DL_DT || null, + CNRT_DT: mdgProject.CNRT_DT || null, + CNRT_RESV_YN: mdgProject.CNRT_RESV_YN || null, + CO_CD: mdgProject.CO_CD || null, + CSTM_PO_NO: mdgProject.CSTM_PO_NO || null, + DEL_YN: mdgProject.DEL_YN || null, + DIGT_PDT_GRP: mdgProject.DIGT_PDT_GRP || null, + DIST_PATH: mdgProject.DIST_PATH || null, + DL_BF_PROJ_NM: mdgProject.DL_BF_PROJ_NM || null, + DL_CSTM_CD: mdgProject.DL_CSTM_CD || null, + DOCK_CD: mdgProject.DOCK_CD || null, + DSN_CHRGR: mdgProject.DSN_CHRGR || null, + FIN_GRNT_FN_DT: mdgProject.FIN_GRNT_FN_DT || null, + GENT_CNT: mdgProject.GENT_CNT || null, + GOV: mdgProject.GOV || null, + GRNT_STDT: mdgProject.GRNT_STDT || null, + IF_STAT: mdgProject.IF_STAT || null, + IMO_NO: mdgProject.IMO_NO || null, + INQY_NO: mdgProject.INQY_NO || null, + INQY_SEQ: mdgProject.INQY_SEQ || null, + IO_GB: mdgProject.IO_GB || null, + MNG_ACOT_DMN: mdgProject.MNG_ACOT_DMN || null, + MN_ENGN_TP_CD: mdgProject.MN_ENGN_TP_CD || null, + MSHIP_NO: mdgProject.MSHIP_NO || null, + NEW_MC_YN: mdgProject.NEW_MC_YN || null, + NTTP: mdgProject.NTTP || null, + ORDR_GRNT_FN_DT: mdgProject.ORDR_GRNT_FN_DT || null, + ORDR_GRNT_PRD: mdgProject.ORDR_GRNT_PRD || null, + OWN_1: mdgProject.OWN_1 || null, + OWN_AB: mdgProject.OWN_AB || null, + OWN_NM: mdgProject.OWN_NM || null, + PDT_LVL_4: mdgProject.PDT_LVL_4 || null, + PLNT_CD: mdgProject.PLNT_CD || null, + PRCTR: mdgProject.PRCTR || null, + PRGS_STAT: mdgProject.PRGS_STAT || null, + PROJ_CRTE_REQ_DT: mdgProject.PROJ_CRTE_REQ_DT || null, + PROJ_CRTE_REQ_EMPNO: mdgProject.PROJ_CRTE_REQ_EMPNO || null, + PROJ_DL_PLN_DT: mdgProject.PROJ_DL_PLN_DT || null, + PROJ_DL_RT_DT: mdgProject.PROJ_DL_RT_DT || null, + PROJ_DTL_TP: mdgProject.PROJ_DTL_TP || null, + PROJ_ETC_TP: mdgProject.PROJ_ETC_TP || null, + PROJ_GB: mdgProject.PROJ_GB || null, + PROJ_PRGS_YN: mdgProject.PROJ_PRGS_YN || null, + PROJ_PROF: mdgProject.PROJ_PROF || null, + PROJ_SCP: mdgProject.PROJ_SCP || null, + PROJ_WBS_TP: mdgProject.PROJ_WBS_TP || null, + PRO_PROJ_NO: mdgProject.PRO_PROJ_NO || null, + QM_CLS: mdgProject.QM_CLS || null, + REF_NO: mdgProject.REF_NO || null, + RLTD_PROJ: mdgProject.RLTD_PROJ || null, + RL_DL_DT: mdgProject.RL_DL_DT || null, + SALE_GRP: mdgProject.SALE_GRP || null, + SALE_ORG_CD: mdgProject.SALE_ORG_CD || null, + SA_DT: mdgProject.SA_DT || null, + SERS_NO: mdgProject.SERS_NO || null, + SERS_YN: mdgProject.SERS_YN || null, + SHTYPE: mdgProject.SHTYPE || null, + SHTYPE_CD: mdgProject.SHTYPE_CD || null, + SHTYPE_GRP: mdgProject.SHTYPE_GRP || null, + SHTYPE_UOM: mdgProject.SHTYPE_UOM || null, + SKND: mdgProject.SKND || null, + SRC_SYS_ID: mdgProject.SRC_SYS_ID || null, + STDT: mdgProject.STDT || null, + SYS_ACOT_CLSD_DT: mdgProject.SYS_ACOT_CLSD_DT || null, + TOT_CNRT_CNT: mdgProject.TOT_CNRT_CNT || null, + TYPE: mdgProject.TYPE || null, // 원본 TYPE 컬럼 + WP_PROJ_TP: mdgProject.WP_PROJ_TP || null, + // id, createdAt, updatedAt는 자동 생성 }; @@ -141,13 +212,89 @@ async function saveProjectsToDatabase(mappedProjects: ProjectData[]): Promise<vo .limit(1); if (existingProject.length > 0) { - // 기존 데이터 업데이트 + // 기존 데이터 업데이트 - 모든 MDG 컬럼 포함 await tx .update(projects) .set({ code: project.code, name: project.name, type: project.type, + AS_GRNT_PRD: project.AS_GRNT_PRD, + BIZCLS: project.BIZCLS, + BIZLOC_CD: project.BIZLOC_CD, + BIZ_DMN: project.BIZ_DMN, + BP_DL_DT: project.BP_DL_DT, + CHN_PROJ_TP: project.CHN_PROJ_TP, + CLS_1: project.CLS_1, + CLS_2: project.CLS_2, + CNRT_CNTN_YN: project.CNRT_CNTN_YN, + CNRT_DL_DT: project.CNRT_DL_DT, + CNRT_DT: project.CNRT_DT, + CNRT_RESV_YN: project.CNRT_RESV_YN, + CO_CD: project.CO_CD, + CSTM_PO_NO: project.CSTM_PO_NO, + DEL_YN: project.DEL_YN, + DIGT_PDT_GRP: project.DIGT_PDT_GRP, + DIST_PATH: project.DIST_PATH, + DL_BF_PROJ_NM: project.DL_BF_PROJ_NM, + DL_CSTM_CD: project.DL_CSTM_CD, + DOCK_CD: project.DOCK_CD, + DSN_CHRGR: project.DSN_CHRGR, + FIN_GRNT_FN_DT: project.FIN_GRNT_FN_DT, + GENT_CNT: project.GENT_CNT, + GOV: project.GOV, + GRNT_STDT: project.GRNT_STDT, + IF_STAT: project.IF_STAT, + IMO_NO: project.IMO_NO, + INQY_NO: project.INQY_NO, + INQY_SEQ: project.INQY_SEQ, + IO_GB: project.IO_GB, + MNG_ACOT_DMN: project.MNG_ACOT_DMN, + MN_ENGN_TP_CD: project.MN_ENGN_TP_CD, + MSHIP_NO: project.MSHIP_NO, + NEW_MC_YN: project.NEW_MC_YN, + NTTP: project.NTTP, + ORDR_GRNT_FN_DT: project.ORDR_GRNT_FN_DT, + ORDR_GRNT_PRD: project.ORDR_GRNT_PRD, + OWN_1: project.OWN_1, + OWN_AB: project.OWN_AB, + OWN_NM: project.OWN_NM, + PDT_LVL_4: project.PDT_LVL_4, + PLNT_CD: project.PLNT_CD, + PRCTR: project.PRCTR, + PRGS_STAT: project.PRGS_STAT, + PROJ_CRTE_REQ_DT: project.PROJ_CRTE_REQ_DT, + PROJ_CRTE_REQ_EMPNO: project.PROJ_CRTE_REQ_EMPNO, + PROJ_DL_PLN_DT: project.PROJ_DL_PLN_DT, + PROJ_DL_RT_DT: project.PROJ_DL_RT_DT, + PROJ_DTL_TP: project.PROJ_DTL_TP, + PROJ_ETC_TP: project.PROJ_ETC_TP, + PROJ_GB: project.PROJ_GB, + PROJ_PRGS_YN: project.PROJ_PRGS_YN, + PROJ_PROF: project.PROJ_PROF, + PROJ_SCP: project.PROJ_SCP, + PROJ_WBS_TP: project.PROJ_WBS_TP, + PRO_PROJ_NO: project.PRO_PROJ_NO, + QM_CLS: project.QM_CLS, + REF_NO: project.REF_NO, + RLTD_PROJ: project.RLTD_PROJ, + RL_DL_DT: project.RL_DL_DT, + SALE_GRP: project.SALE_GRP, + SALE_ORG_CD: project.SALE_ORG_CD, + SA_DT: project.SA_DT, + SERS_NO: project.SERS_NO, + SERS_YN: project.SERS_YN, + SHTYPE: project.SHTYPE, + SHTYPE_CD: project.SHTYPE_CD, + SHTYPE_GRP: project.SHTYPE_GRP, + SHTYPE_UOM: project.SHTYPE_UOM, + SKND: project.SKND, + SRC_SYS_ID: project.SRC_SYS_ID, + STDT: project.STDT, + SYS_ACOT_CLSD_DT: project.SYS_ACOT_CLSD_DT, + TOT_CNRT_CNT: project.TOT_CNRT_CNT, + TYPE: project.TYPE, + WP_PROJ_TP: project.WP_PROJ_TP, updatedAt: new Date(), }) .where(eq(projects.pspid, project.pspid)); |
