diff options
Diffstat (limited to 'lib/po/vendor-table/vendor-po-items-dialog.tsx')
| -rw-r--r-- | lib/po/vendor-table/vendor-po-items-dialog.tsx | 131 |
1 files changed, 130 insertions, 1 deletions
diff --git a/lib/po/vendor-table/vendor-po-items-dialog.tsx b/lib/po/vendor-table/vendor-po-items-dialog.tsx index d88d88d1..8b984812 100644 --- a/lib/po/vendor-table/vendor-po-items-dialog.tsx +++ b/lib/po/vendor-table/vendor-po-items-dialog.tsx @@ -16,22 +16,122 @@ import { TableHeader, TableRow, } from "@/components/ui/table" +import { Button } from "@/components/ui/button" import { Skeleton } from "@/components/ui/skeleton" +import { Download, FileText } from "lucide-react" +import { toast } from "sonner" import { VendorPO, VendorPOItem } from "./types" import { getVendorPOItemsByContractNo } from "./service" import { formatNumber } from "@/lib/utils" +import { getDownloadUrlByMaterialCode, checkPosFileExists } from "@/lib/pos" +import { PosFileSelectionDialog } from "@/lib/pos/components/pos-file-selection-dialog" interface VendorPOItemsDialogProps { open: boolean onOpenChange: (open: boolean) => void po: VendorPO | null + /** + * 뷰어 타입 + * - 'evcp': EVCP 사용자 (암호화된 파일 직접 다운로드) + * - 'partners': 협력사 사용자 (복호화된 파일 다운로드) + */ + viewerType?: 'evcp' | 'partners' } -export function VendorPOItemsDialog({ open, onOpenChange, po }: VendorPOItemsDialogProps) { +export function VendorPOItemsDialog({ open, onOpenChange, po, viewerType = 'partners' }: VendorPOItemsDialogProps) { const [items, setItems] = React.useState<VendorPOItem[]>([]) const [loading, setLoading] = React.useState(false) const [error, setError] = React.useState<string | null>(null) + // POS 파일 선택 다이얼로그 상태 + const [posDialogOpen, setPosDialogOpen] = React.useState(false) + const [selectedMaterialCode, setSelectedMaterialCode] = React.useState<string>("") + const [posFiles, setPosFiles] = React.useState<Array<{ + fileName: string + dcmtmId: string + projNo: string + posNo: string + posRevNo: string + fileSer: string + }>>([]) + const [loadingPosFiles, setLoadingPosFiles] = React.useState(false) + const [downloadingFileIndex, setDownloadingFileIndex] = React.useState<number | null>(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) + } + // 상세품목 데이터 로드 React.useEffect(() => { if (!open || !po) { @@ -123,6 +223,7 @@ export function VendorPOItemsDialog({ open, onOpenChange, po }: VendorPOItemsDia <TableHead className="min-w-[120px] text-right whitespace-nowrap">기본총액(BRTWR)</TableHead> <TableHead className="min-w-[120px] text-right whitespace-nowrap">조정금액(ZPDT_EXDS_AMT)</TableHead> <TableHead className="min-w-[120px] text-right whitespace-nowrap">최종정가(NETWR)</TableHead> + <TableHead className="min-w-[100px] text-center whitespace-nowrap">POS</TableHead> <TableHead className="min-w-[100px] whitespace-nowrap">예정시작일자</TableHead> <TableHead className="min-w-[100px] whitespace-nowrap">납기일자</TableHead> <TableHead className="min-w-[100px] whitespace-nowrap">예정종료일자</TableHead> @@ -223,6 +324,24 @@ export function VendorPOItemsDialog({ open, onOpenChange, po }: VendorPOItemsDia return item.NETWR ? formatNumber(item.NETWR, decimals) : '-' })()} </TableCell> + <TableCell className="text-center"> + {item.materialNo ? ( + <Button + variant="ghost" + size="sm" + className="h-8 px-2 text-xs text-green-600 hover:text-green-800" + onClick={() => handleOpenPosDialog(item.materialNo!)} + disabled={loadingPosFiles && selectedMaterialCode === item.materialNo} + title={`POS 파일 다운로드 (자재코드: ${item.materialNo})`} + > + <FileText className="h-3 w-3 mr-1" /> + <Download className="h-3 w-3 mr-1" /> + {loadingPosFiles && selectedMaterialCode === item.materialNo ? '조회중...' : 'POS'} + </Button> + ) : ( + <span className="text-muted-foreground">-</span> + )} + </TableCell> <TableCell>{item.ZPLN_ST_DT || '-'}</TableCell> <TableCell>{item.ZPO_DLV_DT || item.deliveryDate || '-'}</TableCell> <TableCell>{item.ZPLN_ED_DT || '-'}</TableCell> @@ -277,6 +396,16 @@ export function VendorPOItemsDialog({ open, onOpenChange, po }: VendorPOItemsDia </div> </div> )} + + {/* POS 파일 선택 다이얼로그 */} + <PosFileSelectionDialog + isOpen={posDialogOpen} + onClose={handleClosePosDialog} + materialCode={selectedMaterialCode} + files={posFiles} + onDownload={handleDownloadPosFile} + downloadingIndex={downloadingFileIndex} + /> </DialogContent> </Dialog> ) |
