diff options
| -rw-r--r-- | db/schema/vendorDocu.ts | 37 | ||||
| -rw-r--r-- | lib/vendor-document-list/import-service.ts | 15 | ||||
| -rw-r--r-- | lib/vendor-document-list/ship/enhanced-doc-table-columns.tsx | 84 | ||||
| -rw-r--r-- | lib/vendor-document-list/ship/enhanced-documents-table.tsx | 8 |
4 files changed, 140 insertions, 4 deletions
diff --git a/db/schema/vendorDocu.ts b/db/schema/vendorDocu.ts index 304fe5ae..bfa43849 100644 --- a/db/schema/vendorDocu.ts +++ b/db/schema/vendorDocu.ts @@ -873,6 +873,12 @@ export const simplifiedDocumentsView = pgView("simplified_documents_view", { secondStagePlanDate: date("second_stage_plan_date"), secondStageActualDate: date("second_stage_actual_date"), + // 세 번째 스테이지 날짜 정보 (B4 문서의 SHI → GTT) + thirdStageId: integer("third_stage_id"), + thirdStageName: varchar("third_stage_name", { length: 100 }), + thirdStagePlanDate: date("third_stage_plan_date"), + thirdStageActualDate: date("third_stage_actual_date"), + // 전체 스테이지 목록 allStages: json("all_stages").$type<Array<{ id: number; @@ -1063,6 +1069,30 @@ export const simplifiedDocumentsView = pgView("simplified_documents_view", { WHERE rn = 1 ), + -- 세 번째 스테이지 정보 (B4 문서의 SHI → GTT) + third_stage_info AS ( + SELECT + document_id, + third_stage_id, + third_stage_name, + third_stage_plan_date, + third_stage_actual_date + FROM ( + SELECT + ist.document_id, + ist.id as third_stage_id, + ist.stage_name as third_stage_name, + ist.plan_date as third_stage_plan_date, + ist.actual_date as third_stage_actual_date, + ROW_NUMBER() OVER (PARTITION BY ist.document_id ORDER BY ist.stage_order ASC) as rn + FROM issue_stages ist + JOIN documents d ON ist.document_id = d.id + WHERE + d.drawing_kind = 'B4' AND ist.stage_name = 'SHI → GTT' + ) ranked + WHERE rn = 1 + ), + -- 첨부파일 수 집계 attachment_counts AS ( SELECT @@ -1133,6 +1163,12 @@ export const simplifiedDocumentsView = pgView("simplified_documents_view", { ssi.second_stage_plan_date, ssi.second_stage_actual_date, + -- 세 번째 스테이지 정보 + tsi.third_stage_id, + tsi.third_stage_name, + tsi.third_stage_plan_date, + tsi.third_stage_actual_date, + -- 전체 스테이지 (리비전 및 첨부파일 포함) COALESCE(sa.all_stages, '[]'::json) as all_stages, @@ -1150,6 +1186,7 @@ export const simplifiedDocumentsView = pgView("simplified_documents_view", { -- 스테이지 정보 JOIN LEFT JOIN first_stage_info fsi ON d.id = fsi.document_id LEFT JOIN second_stage_info ssi ON d.id = ssi.document_id + LEFT JOIN third_stage_info tsi ON d.id = tsi.document_id LEFT JOIN stage_aggregation sa ON d.id = sa.document_id LEFT JOIN attachment_counts ac ON d.id = ac.document_id diff --git a/lib/vendor-document-list/import-service.ts b/lib/vendor-document-list/import-service.ts index 694b3d43..85c706ed 100644 --- a/lib/vendor-document-list/import-service.ts +++ b/lib/vendor-document-list/import-service.ts @@ -1882,6 +1882,21 @@ class ImportService { }) } + // SHI → GTT 스테이지 생성 (GTTInput) + if (!existingStageNames.includes('SHI → GTT')) { + await db.insert(issueStages).values({ + documentId: documentId, + stageName: 'SHI → GTT', + planDate: this.convertDolceDateToDate(dolceDoc.GTTInput_PlanDate), + actualDate: this.convertDolceDateToDate(dolceDoc.GTTInput_ResultDate), + stageStatus: 'PLANNED', + stageOrder: 3, + priority: 'MEDIUM', + reminderDays: 3, + description: 'SHI 제출 문서 단계' + }) + } + console.log(`Created issue stages for B4 document: ${drawingNo}`) } catch (error) { diff --git a/lib/vendor-document-list/ship/enhanced-doc-table-columns.tsx b/lib/vendor-document-list/ship/enhanced-doc-table-columns.tsx index 882ef885..a2ac622d 100644 --- a/lib/vendor-document-list/ship/enhanced-doc-table-columns.tsx +++ b/lib/vendor-document-list/ship/enhanced-doc-table-columns.tsx @@ -33,6 +33,7 @@ import { DocumentSelectionContext } from "@/components/ship-vendor-document/user interface GetColumnsProps { setRowAction?: React.Dispatch<React.SetStateAction<DataTableRowAction<SimplifiedDocumentsView> | null>> + b4FilterType?: 'all' | 'gtt_deliverable' | 'shi_input' } // 날짜 표시 컴포넌트 (간단 버전) @@ -51,6 +52,7 @@ const DateDisplay = ({ date, isSelected = false }: { date: string | null, isSele export function getSimplifiedDocumentColumns({ setRowAction, + b4FilterType = 'all', }: GetColumnsProps): ColumnDef<SimplifiedDocumentsView>[] { const columns: ColumnDef<SimplifiedDocumentsView>[] = [ @@ -258,6 +260,49 @@ export function getSimplifiedDocumentColumns({ ], }, + // 3차 스테이지 그룹 (SHI → GTT) + { + id: "thirdStageGroup", + header: ({ table }) => { + // 첫 번째 행의 thirdStageName을 그룹 헤더로 사용 + const firstRow = table.getRowModel().rows[0]?.original + const stageName = firstRow?.thirdStageName || "SHI → GTT" + return ( + <div className="text-center font-medium text-foreground"> + {stageName} + </div> + ) + }, + columns: [ + { + accessorKey: "thirdStagePlanDate", + header: ({ column }) => ( + <DataTableColumnHeaderSimple column={column} title="Planned Date" /> + ), + cell: ({ row }) => { + return <ThirdStagePlanDateCell row={row} /> + }, + enableResizing: true, + meta: { + excelHeader: "Third Planned Date" + }, + }, + { + accessorKey: "thirdStageActualDate", + header: ({ column }) => ( + <DataTableColumnHeaderSimple column={column} title="Actual Date" /> + ), + cell: ({ row }) => { + return <ThirdStageActualDateCell row={row} /> + }, + enableResizing: true, + meta: { + excelHeader: "Third Actual Date" + }, + }, + ], + }, + // 첨부파일 수 { accessorKey: "attachmentCount", @@ -341,6 +386,22 @@ export function getSimplifiedDocumentColumns({ // }, ] + // b4FilterType에 따라 스테이지 컬럼 필터링 + if (b4FilterType === 'gtt_deliverable') { + // GTT Deliverables: GTT → SHI 스테이지만 (firstStageGroup, secondStageGroup) + return columns.filter(col => { + const id = 'id' in col ? col.id : null + return id !== 'thirdStageGroup' + }) + } else if (b4FilterType === 'shi_input') { + // SHI Input Document: SHI → GTT 스테이지만 (thirdStageGroup) + return columns.filter(col => { + const id = 'id' in col ? col.id : null + return id !== 'firstStageGroup' && id !== 'secondStageGroup' + }) + } + + // All: 모든 컬럼 표시 return columns } @@ -471,6 +532,29 @@ function SecondStageActualDateCell({ row }: { row: any }) { ); } +function ThirdStagePlanDateCell({ row }: { row: any }) { + const { selectedDocumentId } = React.useContext(DocumentSelectionContext); + const isSelected = selectedDocumentId === row.original.documentId; + + return <DateDisplay date={row.original.thirdStagePlanDate} isSelected={isSelected} />; +} + +function ThirdStageActualDateCell({ row }: { row: any }) { + const { selectedDocumentId } = React.useContext(DocumentSelectionContext); + const isSelected = selectedDocumentId === row.original.documentId; + const date = row.original.thirdStageActualDate; + + return ( + <div className={cn( + date ? "text-emerald-600 dark:text-emerald-400 font-medium" : "", + isSelected && date && "text-emerald-700 dark:text-emerald-300 font-bold" + )}> + <DateDisplay date={date} isSelected={isSelected && !date} /> + {date && <span className="text-xs block">✓ 완료</span>} + </div> + ); +} + function AttachmentCountCell({ count, documentId }: { count: number, documentId: number }) { const { selectedDocumentId } = React.useContext(DocumentSelectionContext); const isSelected = selectedDocumentId === documentId; diff --git a/lib/vendor-document-list/ship/enhanced-documents-table.tsx b/lib/vendor-document-list/ship/enhanced-documents-table.tsx index 13f8f8d4..d92f16dd 100644 --- a/lib/vendor-document-list/ship/enhanced-documents-table.tsx +++ b/lib/vendor-document-list/ship/enhanced-documents-table.tsx @@ -100,10 +100,10 @@ export function SimplifiedDocumentsTable({ } }, [data, onDataLoaded]) - // 🔥 컬럼 메모이제이션 최적화 + // 🔥 컬럼 메모이제이션 최적화 (b4FilterType에 따라 동적 변경) const columns = React.useMemo( - () => getSimplifiedDocumentColumns({}), - [] + () => getSimplifiedDocumentColumns({ b4FilterType }), + [b4FilterType] ) // 🔥 필터 필드들을 메모이제이션 @@ -391,7 +391,7 @@ export function SimplifiedDocumentsTable({ className="gap-2" > <FileInput className="h-4 w-4" /> - GTT Deliverable + GTT Deliverables <Badge variant="secondary" className="ml-1"> {b4Stats.gttDeliverableCount} </Badge> |
