"use client" import * as React from "react" import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card" import { Button } from "@/components/ui/button" import { Download, FileText } from "lucide-react" import { toast } from "sonner" import { formatCurrency, formatNumber } from "@/lib/utils" import { getDownloadUrlByMaterialCode, checkPosFileExists } from "@/lib/pos" import { PosFileSelectionDialog } from "@/lib/pos/components/pos-file-selection-dialog" interface ContractItem { materialNo?: string itemDescription?: string specification?: string quantity?: number quantityUnit?: string ZPO_UNIT?: string unitPrice?: number | string contractAmount?: number | string // SAP ECC 금액 필드 NETWR?: number BRTWR?: number ZPDT_EXDS_AMT?: number // SAP 날짜 필드 ZPO_DLV_DT?: string ZPLN_ST_DT?: string ZPLN_ED_DT?: string } interface ContractItemsCardProps { items: ContractItem[] currency?: string | null /** * 뷰어 타입 * - 'evcp': EVCP 사용자 (암호화된 파일 직접 다운로드) * - 'partners': 협력사 사용자 (복호화된 파일 다운로드) */ viewerType?: 'evcp' | 'partners' } export function ContractItemsCard({ items, currency, viewerType = 'partners' }: ContractItemsCardProps) { // POS 파일 선택 다이얼로그 상태 const [posDialogOpen, setPosDialogOpen] = React.useState(false) const [selectedMaterialCode, setSelectedMaterialCode] = React.useState("") const [posFiles, setPosFiles] = React.useState>([]) const [loadingPosFiles, setLoadingPosFiles] = React.useState(false) const [downloadingFileIndex, setDownloadingFileIndex] = React.useState(null) // POS 파일 목록 조회 및 다이얼로그 열기 const handleOpenPosDialog = async (materialCode: string) => { if (!materialCode) { toast.error("자재코드가 없습니다") return } setLoadingPosFiles(true) setSelectedMaterialCode(materialCode) try { toast.loading(`POS 파일 목록 조회 중... (${materialCode})`, { id: `pos-check-${materialCode}` }) const result = await checkPosFileExists(materialCode) if (result.exists && result.files && result.files.length > 0) { // 파일 정보를 상세하게 가져오기 위해 getDownloadUrlByMaterialCode 사용 const detailResult = await getDownloadUrlByMaterialCode(materialCode) if (detailResult.success && detailResult.availableFiles) { setPosFiles(detailResult.availableFiles) setPosDialogOpen(true) toast.success(`${result.fileCount}개의 POS 파일을 찾았습니다`, { id: `pos-check-${materialCode}` }) } else { toast.error('POS 파일 정보를 가져올 수 없습니다', { id: `pos-check-${materialCode}` }) } } else { toast.error(result.error || 'POS 파일을 찾을 수 없습니다', { id: `pos-check-${materialCode}` }) } } catch (error) { console.error("POS 파일 조회 오류:", error) toast.error("POS 파일 조회에 실패했습니다", { id: `pos-check-${materialCode}` }) } finally { setLoadingPosFiles(false) } } // POS 파일 다운로드 실행 const handleDownloadPosFile = async (fileIndex: number, fileName: string) => { if (!selectedMaterialCode) return setDownloadingFileIndex(fileIndex) try { toast.loading(`POS 파일 다운로드 준비 중...`, { id: `download-${fileIndex}` }) // viewerType에 따라 다른 엔드포인트 사용 const endpoint = viewerType === 'partners' ? `/api/pos/download-on-demand-partners` // 복호화 포함 : `/api/pos/download-on-demand` // 암호화 파일 그대로 const downloadUrl = `${endpoint}?materialCode=${encodeURIComponent(selectedMaterialCode)}&fileIndex=${fileIndex}` toast.success(`POS 파일 다운로드 시작: ${fileName}`, { id: `download-${fileIndex}` }) window.open(downloadUrl, '_blank', 'noopener,noreferrer') // 다운로드 시작 후 잠시 대기 후 상태 초기화 setTimeout(() => { setDownloadingFileIndex(null) }, 1000) } catch (error) { console.error("POS 파일 다운로드 오류:", error) toast.error("POS 파일 다운로드에 실패했습니다", { id: `download-${fileIndex}` }) setDownloadingFileIndex(null) } } // POS 다이얼로그 닫기 const handleClosePosDialog = () => { setPosDialogOpen(false) setSelectedMaterialCode("") setPosFiles([]) setDownloadingFileIndex(null) } if (!items || items.length === 0) { return null } return ( 계약 품목
{items.map((item, idx) => ( ))}
자재번호 품목/자재내역 규격 수량 단가 기본총액(BRTWR) 조정금액(ZPDT) 최종정가(NETWR) 납기일자 POS
{item.materialNo || "-"} {item.itemDescription || "-"} {item.specification || "-"} {item.quantity} {item.ZPO_UNIT || item.quantityUnit || ""} {item.unitPrice ? currency ? formatCurrency( parseFloat(item.unitPrice.toString()), currency ) : formatNumber(parseFloat(item.unitPrice.toString())) : "-"} {item.BRTWR ? currency ? formatCurrency(item.BRTWR, currency) : formatNumber(item.BRTWR) : "-"} {item.ZPDT_EXDS_AMT ? currency ? formatCurrency(item.ZPDT_EXDS_AMT, currency) : formatNumber(item.ZPDT_EXDS_AMT) : "-"} {item.NETWR ? currency ? formatCurrency(item.NETWR, currency) : formatNumber(item.NETWR) : "-"} {item.ZPO_DLV_DT || "-"} {item.materialNo ? ( ) : ( - )}
{/* POS 파일 선택 다이얼로그 */}
) }