From 45f4c426c98d86a251644a4858740bec989edf83 Mon Sep 17 00:00:00 2001 From: dujinkim Date: Tue, 20 May 2025 09:01:22 +0000 Subject: (최겸) 기술영업 아이템리스트 수정 및 개발 0520 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/items-tech/table/ship/Items-ship-table.tsx | 10 +++ lib/items-tech/table/ship/import-item-handler.tsx | 56 ++++++++++------- lib/items-tech/table/ship/item-excel-template.tsx | 27 +++++--- .../table/ship/items-ship-table-columns.tsx | 73 ++++------------------ .../table/ship/items-table-toolbar-actions.tsx | 4 +- 5 files changed, 77 insertions(+), 93 deletions(-) (limited to 'lib/items-tech/table/ship') diff --git a/lib/items-tech/table/ship/Items-ship-table.tsx b/lib/items-tech/table/ship/Items-ship-table.tsx index aee90cfc..29ad8f8a 100644 --- a/lib/items-tech/table/ship/Items-ship-table.tsx +++ b/lib/items-tech/table/ship/Items-ship-table.tsx @@ -24,6 +24,7 @@ type ShipbuildingItem = { shipTypes: string; itemCode: string; itemName: string; + itemList: string | null; description: string | null; createdAt: Date; updatedAt: Date; @@ -56,6 +57,10 @@ export function ItemsShipTable({ promises }: ItemsTableProps) { id: "shipTypes", label: "선종", }, + { + id: "itemList", + label: "아이템 리스트", + }, ] /** @@ -95,6 +100,11 @@ export function ItemsShipTable({ promises }: ItemsTableProps) { label: "선종", type: "text", }, + { + id: "itemList", + label: "아이템 리스트", + type: "text", + }, ] const { table } = useDataTable({ diff --git a/lib/items-tech/table/ship/import-item-handler.tsx b/lib/items-tech/table/ship/import-item-handler.tsx index 6ad24398..2a23d9d6 100644 --- a/lib/items-tech/table/ship/import-item-handler.tsx +++ b/lib/items-tech/table/ship/import-item-handler.tsx @@ -8,11 +8,10 @@ const SHIP_TYPES = ['A-MAX', 'S-MAX', 'LNGC', 'VLCC', 'CONT'] as const; // 아이템 데이터 검증을 위한 Zod 스키마 const itemSchema = z.object({ itemCode: z.string().min(1, "아이템 코드는 필수입니다"), - itemName: z.string().min(1, "아이템 명은 필수입니다"), workType: z.enum(["기장", "전장", "선실", "배관", "철의"], { required_error: "기능(공종)은 필수입니다", }), - description: z.string().nullable().optional(), + itemList: z.string().nullable().optional(), }); interface ProcessResult { @@ -25,7 +24,7 @@ interface ProcessResult { * Excel 파일에서 가져온 조선 아이템 데이터 처리하는 함수 */ export async function processFileImport( - jsonData: any[], + jsonData: Record[], progressCallback?: (current: number, total: number) => void ): Promise { // 결과 카운터 초기화 @@ -60,16 +59,14 @@ export async function processFileImport( try { // 필드 매핑 (한글/영문 필드명 모두 지원) const itemCode = row["아이템 코드"] || row["itemCode"] || ""; - const itemName = row["아이템 명"] || row["itemName"] || ""; const workType = row["기능(공종)"] || row["workType"] || ""; - const description = row["설명"] || row["description"] || null; + const itemList = row["아이템 리스트"] || row["itemList"] || null; // 데이터 정제 const cleanedRow = { itemCode: typeof itemCode === 'string' ? itemCode.trim() : String(itemCode).trim(), - itemName: typeof itemName === 'string' ? itemName.trim() : String(itemName).trim(), workType: typeof workType === 'string' ? workType.trim() : String(workType).trim(), - description: description ? (typeof description === 'string' ? description : String(description)) : null, + itemList: itemList ? (typeof itemList === 'string' ? itemList : String(itemList)) : null, }; // 데이터 유효성 검사 @@ -88,27 +85,20 @@ export async function processFileImport( // 선종 데이터 처리 const shipTypeEntries = SHIP_TYPES.map(type => ({ type, - value: row[type]?.toUpperCase() === 'O' + value: row[type] ? String(row[type]).toUpperCase() === 'O' : false })).filter(entry => entry.value); console.log('shipTypeEntries:', shipTypeEntries); + // 선종이 없는 경우에 "option" 값을 사용 if (shipTypeEntries.length === 0) { - errors.push({ - row: rowIndex, - message: "최소 하나 이상의 선종이 'O'로 지정되어야 합니다." - }); - errorCount++; - continue; - } - - // 각 선종에 대해 아이템 생성 - for (const { type } of shipTypeEntries) { + // "option" 값으로 아이템 생성 const result = await createShipbuildingImportItem({ itemCode: cleanedRow.itemCode, - itemName: cleanedRow.itemName, + itemName: "기술영업", // 기본값 사용 workType: cleanedRow.workType as "기장" | "전장" | "선실" | "배관" | "철의", - shipTypes: { [type]: true }, - description: cleanedRow.description, + shipTypes: { "OPTION": true }, + description: null, + itemList: cleanedRow.itemList, }); if (result.success || !result.error) { @@ -116,10 +106,32 @@ export async function processFileImport( } else { errors.push({ row: rowIndex, - message: `${type}: ${result.message || result.error || "알 수 없는 오류"}` + message: `OPTION: ${result.message || result.error || "알 수 없는 오류"}` }); errorCount++; } + } else { + // 각 선종에 대해 아이템 생성 + for (const { type } of shipTypeEntries) { + const result = await createShipbuildingImportItem({ + itemCode: cleanedRow.itemCode, + itemName: "기술영업", // 기본값 사용 + workType: cleanedRow.workType as "기장" | "전장" | "선실" | "배관" | "철의", + shipTypes: { [type]: true }, + description: null, + itemList: cleanedRow.itemList, + }); + + if (result.success || !result.error) { + successCount++; + } else { + errors.push({ + row: rowIndex, + message: `${type}: ${result.message || result.error || "알 수 없는 오류"}` + }); + errorCount++; + } + } } } catch (error) { console.error(`${rowIndex}행 처리 오류:`, error); diff --git a/lib/items-tech/table/ship/item-excel-template.tsx b/lib/items-tech/table/ship/item-excel-template.tsx index 127a1dea..f6b20b6d 100644 --- a/lib/items-tech/table/ship/item-excel-template.tsx +++ b/lib/items-tech/table/ship/item-excel-template.tsx @@ -18,9 +18,8 @@ export async function exportItemTemplate() { // 컬럼 헤더 정의 및 스타일 적용 worksheet.columns = [ { header: '아이템 코드', key: 'itemCode', width: 15 }, - { header: '아이템 명', key: 'itemName', width: 30 }, { header: '기능(공종)', key: 'workType', width: 15 }, - { header: '설명', key: 'description', width: 50 }, + { header: '아이템 리스트', key: 'itemList', width: 30 }, ...SHIP_TYPES.map(type => ({ header: type, key: type, @@ -52,25 +51,33 @@ export async function exportItemTemplate() { const sampleData = [ { itemCode: 'BG0001', - itemName: '샘플 아이템 1', workType: '기장', - description: '이것은 샘플 아이템 1의 설명입니다.', + itemList: '아이템 리스트 내용', 'A-MAX': 'O', 'S-MAX': 'O', 'LNGC': 'O', - 'VLCC': 'X', - 'CONT': 'X' + 'VLCC': ' ', + 'CONT': ' ' }, { itemCode: 'BG0002', - itemName: '샘플 아이템 2', workType: '전장', - description: '이것은 샘플 아이템 2의 설명입니다.', + itemList: '아이템 리스트 내용 2', 'A-MAX': 'O', - 'S-MAX': 'X', + 'S-MAX': ' ', 'LNGC': 'O', 'VLCC': 'O', - 'CONT': 'X' + 'CONT': ' ' + }, + { + itemCode: 'BG0003', + workType: '선실', + itemList: '선종 없는 아이템', + 'A-MAX': ' ', + 'S-MAX': ' ', + 'LNGC': ' ', + 'VLCC': ' ', + 'CONT': ' ' } ]; diff --git a/lib/items-tech/table/ship/items-ship-table-columns.tsx b/lib/items-tech/table/ship/items-ship-table-columns.tsx index 2b46db92..29e1d503 100644 --- a/lib/items-tech/table/ship/items-ship-table-columns.tsx +++ b/lib/items-tech/table/ship/items-ship-table-columns.tsx @@ -24,6 +24,7 @@ interface ShipbuildingTableItem { itemId: number; workType: "기장" | "전장" | "선실" | "배관" | "철의"; shipTypes: string; + itemList: string | null; itemCode: string; itemName: string; description: string | null; @@ -107,11 +108,10 @@ export function getShipbuildingColumns({ setRowAction }: GetColumnsProps): Colum } // ---------------------------------------------------------------- - // 3) 데이터 컬럼들을 그룹별로 구성 + // 3) 데이터 컬럼들 정의 // ---------------------------------------------------------------- - // 3-1) 기본 정보 그룹 컬럼 - const basicInfoColumns: ColumnDef[] = [ + const dataColumns: ColumnDef[] = [ { accessorKey: "itemCode", header: ({ column }) => ( @@ -122,20 +122,6 @@ export function getShipbuildingColumns({ setRowAction }: GetColumnsProps): Colum enableHiding: true, meta: { excelHeader: "Material Group", - group: "기본 정보", - }, - }, - { - accessorKey: "itemName", - header: ({ column }) => ( - - ), - cell: ({ row }) =>
{row.original.itemName}
, - enableSorting: true, - enableHiding: true, - meta: { - excelHeader: "Description", - group: "기본 정보", }, }, { @@ -148,44 +134,32 @@ export function getShipbuildingColumns({ setRowAction }: GetColumnsProps): Colum enableHiding: true, meta: { excelHeader: "기능(공종)", - group: "기본 정보", }, }, { - accessorKey: "description", + accessorKey: "shipTypes", header: ({ column }) => ( - + ), - cell: ({ row }) =>
{row.original.description || "-"}
, + cell: ({ row }) =>
{row.original.shipTypes}
, enableSorting: true, enableHiding: true, meta: { - excelHeader: "Size/Dimension", - group: "기본 정보", + excelHeader: "선종", }, }, - ] - - // 3-2) 선종 정보 그룹 컬럼 - const shipTypesColumns: ColumnDef[] = [ { - accessorKey: "shipTypes", + accessorKey: "itemList", header: ({ column }) => ( - + ), - cell: ({ row }) =>
{row.original.shipTypes}
, + cell: ({ row }) =>
{row.original.itemList || "-"}
, enableSorting: true, enableHiding: true, meta: { - excelHeader: "선종", - group: "선종", + excelHeader: "아이템 리스트", }, }, - ] - - // 3-3) 메타데이터 그룹 컬럼 - const metadataColumns: ColumnDef[] = [ - { accessorKey: "createdAt", header: ({ column }) => ( @@ -196,7 +170,6 @@ export function getShipbuildingColumns({ setRowAction }: GetColumnsProps): Colum enableHiding: true, meta: { excelHeader: "생성일", - group: "Metadata", }, }, { @@ -209,36 +182,16 @@ export function getShipbuildingColumns({ setRowAction }: GetColumnsProps): Colum enableHiding: true, meta: { excelHeader: "수정일", - group: "Metadata", }, } ] - - // 3-4) 그룹별 컬럼 구성 - const groupedColumns: ColumnDef[] = [ - { - id: "기본 정보", - header: "기본 정보", - columns: basicInfoColumns, - }, - { - id: "선종", - header: "선종", - columns: shipTypesColumns, - }, - { - id: "Metadata", - header: "Metadata", - columns: metadataColumns, - } - ] // ---------------------------------------------------------------- - // 4) 최종 컬럼 배열: select, groupedColumns, actions + // 4) 최종 컬럼 배열: select, dataColumns, actions // ---------------------------------------------------------------- return [ selectColumn, - ...groupedColumns, + ...dataColumns, actionsColumn, ] } \ No newline at end of file diff --git a/lib/items-tech/table/ship/items-table-toolbar-actions.tsx b/lib/items-tech/table/ship/items-table-toolbar-actions.tsx index 6cae61af..677173d1 100644 --- a/lib/items-tech/table/ship/items-table-toolbar-actions.tsx +++ b/lib/items-tech/table/ship/items-table-toolbar-actions.tsx @@ -27,6 +27,7 @@ interface ShipbuildingItem { shipTypes: string; itemCode: string; itemName: string; + itemList: string | null; description: string | null; createdAt: Date; updatedAt: Date; @@ -73,7 +74,8 @@ export function ItemsTableToolbarActions({ table }: ItemsTableToolbarActionsProp { key: 'itemName', header: '아이템 명' }, { key: 'description', header: '설명' }, { key: 'workType', header: '기능(공종)' }, - { key: 'shipTypes', header: '선종' } + { key: 'shipTypes', header: '선종' }, + { key: 'itemList', header: '아이템 리스트' } ].filter(header => !excludeColumns.includes(header.key)); console.log("내보내기 헤더:", headers); -- cgit v1.2.3