From 3462d754574e2558c791c7958d3e5da013a7a573 Mon Sep 17 00:00:00 2001 From: dujinkim Date: Tue, 9 Dec 2025 05:31:04 +0000 Subject: (최겸) 구매 pq 내 안전 담당자 평가 기능 추가, vendor 안전적격성 평가 컬럼 추가 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../pq-review-table-new/vendors-table-columns.tsx | 63 +++- .../vendors-table-toolbar-actions.tsx | 20 +- lib/pq/service.ts | 317 ++++++++++++++++++++- 3 files changed, 379 insertions(+), 21 deletions(-) (limited to 'lib/pq') diff --git a/lib/pq/pq-review-table-new/vendors-table-columns.tsx b/lib/pq/pq-review-table-new/vendors-table-columns.tsx index a35884fc..dc2afa66 100644 --- a/lib/pq/pq-review-table-new/vendors-table-columns.tsx +++ b/lib/pq/pq-review-table-new/vendors-table-columns.tsx @@ -295,6 +295,10 @@ export function getColumns({ setRowAction, router }: GetColumnsProps): ExtendedC return { status: "PQ_IN_PROGRESS", label: "PQ 진행 중", variant: "secondary" as const }; case "SUBMITTED": return { status: "PQ_SUBMITTED", label: "PQ 제출됨", variant: "default" as const }; + case "SAFETY_APPROVED": + return { status: "PQ_SAFETY_APPROVED", label: "안전 승인됨", variant: "secondary" as const }; + case "SAFETY_REJECTED": + return { status: "PQ_SAFETY_REJECTED", label: "안전 거절됨", variant: "destructive" as const }; case "APPROVED": return { status: "PQ_APPROVED", label: "PQ 승인됨", variant: "success" as const }; case "REJECTED": @@ -554,25 +558,56 @@ export function getColumns({ setRowAction, router }: GetColumnsProps): ExtendedC ), cell: ({ row }) => { - const pqItems = row.original.pqItems; + const pqItems = row.original.pqItems if (!pqItems) { - return -; + return - } - // JSON 파싱하여 첫 번째 아이템 표시 - const items = typeof pqItems === 'string' ? JSON.parse(pqItems) : pqItems; - if (Array.isArray(items) && items.length > 0) { - const firstItem = items[0]; - return ( -
- {firstItem.itemCode} - {firstItem.itemName} - {items.length > 1 && ( - 외 {items.length - 1}건 - )} -
- ); + // 문자열이면 JSON 파싱을 시도하고, 실패 시 원문 그대로 표시 + const parsed = + typeof pqItems === "string" + ? (() => { + try { + return JSON.parse(pqItems) + } catch { + return pqItems + } + })() + : pqItems + + if (Array.isArray(parsed)) { + if (parsed.length === 0) { + return - } + + return ( +
+ {parsed.map((item, idx) => { + if (!item || typeof item !== "object") return null + const itemObj = item as Record + const displayName = + itemObj.materialGroupDescription || itemObj.itemName || "" + const displayCode = + itemObj.materialGroupCode || itemObj.itemCode || "" + + if (!displayName && !displayCode) return null + + return ( + + {displayName || displayCode || "품목"} + {displayCode && displayName !== displayCode + ? ` (${displayCode})` + : ""} + + ) + })} +
+ ) + } + + // 배열이 아닌 경우 문자열 그대로 표시 + return {String(parsed) || "-"} }, meta: { excelHeader: "실사품목", diff --git a/lib/pq/pq-review-table-new/vendors-table-toolbar-actions.tsx b/lib/pq/pq-review-table-new/vendors-table-toolbar-actions.tsx index a9d37a4b..b7e54f3d 100644 --- a/lib/pq/pq-review-table-new/vendors-table-toolbar-actions.tsx +++ b/lib/pq/pq-review-table-new/vendors-table-toolbar-actions.tsx @@ -572,6 +572,11 @@ const handleOpenRequestDialog = async () => { row.original.type === "NON_INSPECTION" ) + // 승인되지 않은 PQ가 포함되었는지 확인 + const hasNonApprovedStatus = selectedRows.some(row => + row.original.status !== "APPROVED" + ) + // 실사 방법 라벨 변환 함수 const getInvestigationMethodLabel = (method: string): string => { switch (method) { @@ -676,9 +681,20 @@ const handleOpenRequestDialog = async () => { variant="outline" size="sm" onClick={handleOpenRequestDialog} // 여기를 수정: 새로운 핸들러 함수 사용 - disabled={isLoading || selectedRows.length === 0 || hasNonInspectionPQ} + disabled={ + isLoading || + selectedRows.length === 0 || + hasNonInspectionPQ || + hasNonApprovedStatus + } className="gap-2" - title={hasNonInspectionPQ ? "미실사 PQ는 실사 의뢰할 수 없습니다." : undefined} + title={ + hasNonInspectionPQ + ? "미실사 PQ는 실사 의뢰할 수 없습니다." + : hasNonApprovedStatus + ? "승인된 PQ만 실사 의뢰할 수 있습니다." + : undefined + } >