From 0ee0f102634dd703aea7ad0b8a338eb5e9bdadab Mon Sep 17 00:00:00 2001
From: dujinkim <dujin.kim@dtsolution.co.kr>
Date: Thu, 16 Oct 2025 09:26:56 +0000
Subject: (최겸) 구매 견적 비교 수정(create-PO 개발 필)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 lib/rfq-last/quotation-compare-view.tsx | 970 +++++++++++++++-----------------
 1 file changed, 464 insertions(+), 506 deletions(-)

(limited to 'lib/rfq-last/quotation-compare-view.tsx')

diff --git a/lib/rfq-last/quotation-compare-view.tsx b/lib/rfq-last/quotation-compare-view.tsx
index 91d46295..723d1044 100644
--- a/lib/rfq-last/quotation-compare-view.tsx
+++ b/lib/rfq-last/quotation-compare-view.tsx
@@ -43,7 +43,13 @@ import {
   CollapsibleContent,
   CollapsibleTrigger,
 } from "@/components/ui/collapsible";
-import { ComparisonData, selectVendor, cancelVendorSelection } from "./compare-action";
+import {
+  Dialog,
+  DialogContent,
+  DialogHeader,
+  DialogTitle,
+} from "@/components/ui/dialog";
+import { ComparisonData, selectVendor, cancelVendorSelection, VendorResponseVersion } from "./compare-action";
 import { createPO, createGeneralContract, createBidding } from "./contract-actions";
 import { toast } from "sonner";
 import { useRouter } from "next/navigation"
@@ -58,6 +64,9 @@ export function QuotationCompareView({ data }: QuotationCompareViewProps) {
   const [showSelectionDialog, setShowSelectionDialog] = React.useState(false);
   const [showCancelDialog, setShowCancelDialog] = React.useState(false);
   const [showContractDialog, setShowContractDialog] = React.useState(false);
+  const [showItemDetailsDialog, setShowItemDetailsDialog] = React.useState(false);
+  const [selectedResponse, setSelectedResponse] = React.useState<VendorResponseVersion | null>(null);
+  const [selectedVendorName, setSelectedVendorName] = React.useState<string>("");
   const [selectedContractType, setSelectedContractType] = React.useState<"PO" | "CONTRACT" | "BIDDING" | "">("");
   const [selectionReason, setSelectionReason] = React.useState("");
   const [cancelReason, setCancelReason] = React.useState("");
@@ -88,7 +97,7 @@ export function QuotationCompareView({ data }: QuotationCompareViewProps) {
   ];
 
   // 입찰 관련 state 추가
-  const [biddingContractType, setBiddingContractType] = React.useState<"unit_price" | "general" | "sale" | "">("");
+  const [biddingContractType, setBiddingContractType] = React.useState<"unit_price" | "general" | "sale">("unit_price");
   const [biddingType, setBiddingType] = React.useState<string>("");
   const [awardCount, setAwardCount] = React.useState<"single" | "multiple">("single");
   const [biddingStartDate, setBiddingStartDate] = React.useState("");
@@ -236,7 +245,7 @@ export function QuotationCompareView({ data }: QuotationCompareViewProps) {
         setSelectedGeneralContractType("");
         setContractStartDate("");
         setContractEndDate("");
-        setBiddingContractType("");
+        setBiddingContractType("unit_price");
         setBiddingType("");
         setAwardCount("single");
         setBiddingStartDate("");
@@ -323,17 +332,23 @@ export function QuotationCompareView({ data }: QuotationCompareViewProps) {
         throw new Error("선택한 업체를 찾을 수 없습니다.");
       }
 
+      // 최신 응답 정보 사용
+      const latestResponse = vendor.responses[0];
+      if (!latestResponse) {
+        throw new Error("업체의 견적 정보를 찾을 수 없습니다.");
+      }
+
       const result = await selectVendor({
         rfqId: data.rfqInfo.id,
         vendorId: vendor.vendorId,
         vendorName: vendor.vendorName,
         vendorCode: vendor.vendorCode,
-        totalAmount: vendor.totalAmount,
-        currency: vendor.currency,
+        totalAmount: latestResponse.totalAmount,
+        currency: latestResponse.currency,
         selectionReason: selectionReason,
-        priceRank: vendor.rank || 0,
-        hasConditionDifferences: vendor.conditionDifferences.hasDifferences,
-        criticalDifferences: vendor.conditionDifferences.criticalDifferences,
+        priceRank: latestResponse.rank || 0,
+        hasConditionDifferences: latestResponse.conditionDifferences.hasDifferences,
+        criticalDifferences: latestResponse.conditionDifferences.criticalDifferences,
       });
 
       if (result.success) {
@@ -526,7 +541,7 @@ export function QuotationCompareView({ data }: QuotationCompareViewProps) {
       )}
 
       {/* 요약 카드 */}
-      <div className="grid grid-cols-1 md:grid-cols-4 gap-4">
+      <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
         {/* 최저가 벤더 */}
         <Card>
           <CardHeader className="pb-3">
@@ -577,147 +592,111 @@ export function QuotationCompareView({ data }: QuotationCompareViewProps) {
             </CardContent>
           </Card>
         )}
-
-        {/* 가격 범위 */}
-        <Card>
-          <CardHeader className="pb-3">
-            <CardTitle className="text-sm font-medium flex items-center gap-2">
-              <TrendingUp className="h-4 w-4" />
-              가격 범위
-            </CardTitle>
-          </CardHeader>
-          <CardContent>
-            <p className="text-lg font-bold">
-              {((data.summary.priceRange.max - data.summary.priceRange.min) / data.summary.priceRange.min * 100).toFixed(1)}%
-            </p>
-            <p className="text-sm text-muted-foreground">
-              최저가 대비 최고가 차이
-            </p>
-          </CardContent>
-        </Card>
-
-        {/* 조건 불일치 */}
-        <Card>
-          <CardHeader className="pb-3">
-            <CardTitle className="text-sm font-medium flex items-center gap-2">
-              <AlertCircle className="h-4 w-4 text-orange-500" />
-              조건 불일치
-            </CardTitle>
-          </CardHeader>
-          <CardContent>
-            <p className="text-lg font-bold">
-              {data.vendors.filter(v => v.conditionDifferences.hasDifferences).length}개
-            </p>
-            <p className="text-sm text-muted-foreground">
-              제시 조건과 차이 있음
-            </p>
-          </CardContent>
-        </Card>
       </div>
 
       {/* 탭 뷰 */}
       <Tabs defaultValue="overview" className="w-full">
-        <TabsList className="grid w-full grid-cols-4">
+        <TabsList className="grid w-full grid-cols-2">
           <TabsTrigger value="overview">종합 비교</TabsTrigger>
           <TabsTrigger value="conditions">조건 비교</TabsTrigger>
-          <TabsTrigger value="items">아이템별 비교</TabsTrigger>
-          <TabsTrigger value="analysis">상세 분석</TabsTrigger>
         </TabsList>
 
         {/* 종합 비교 */}
         <TabsContent value="overview" className="space-y-4">
           <Card>
             <CardHeader>
-              <CardTitle>가격 순위 및 업체 선정</CardTitle>
+              <CardTitle>협력업체별 차수별 견적</CardTitle>
             </CardHeader>
             <CardContent>
-              <div className="space-y-4">
-                {data.vendors.map((vendor) => (
-                  <div
-                    key={vendor.vendorId}
-                    className={cn(
-                      "flex items-center justify-between p-4 border rounded-lg transition-colors",
-                      vendor.isSelected
-                        ? "bg-blue-100 border-blue-400 border-2"
-                        : hasSelection
-                          ? "opacity-60"
-                          : selectedVendorId === vendor.vendorId.toString()
-                            ? "bg-blue-50 border-blue-300 cursor-pointer"
-                            : "hover:bg-gray-50 cursor-pointer"
-                    )}
-                    onClick={() => {
-                      if (!hasSelection) {
-                        setSelectedVendorId(vendor.vendorId.toString());
-                      }
-                    }}
-                  >
-                    <div className="flex items-center gap-4">
-                      {!hasSelection && (
-                        <input
-                          type="radio"
-                          name="vendor-selection"
-                          value={vendor.vendorId}
-                          checked={selectedVendorId === vendor.vendorId.toString()}
-                          onChange={(e) => setSelectedVendorId(e.target.value)}
-                          className="h-4 w-4 text-blue-600"
-                        />
-                      )}
-                      <div
+              <div className="overflow-x-auto">
+                <table className="w-full">
+                  <thead>
+                    <tr className="border-b bg-gray-50">
+                      {!hasSelection && <th className="text-left p-3 font-semibold">선택</th>}
+                      <th className="text-left p-3 font-semibold">협력사 코드</th>
+                      <th className="text-left p-3 font-semibold">협력사 명</th>
+                      {(() => {
+                        // 모든 차수 추출 (중복 제거 및 내림차순 정렬)
+                        const allVersions = Array.from(
+                          new Set(
+                            data.vendors.flatMap(v => v.responses.map(r => r.responseVersion))
+                          )
+                        ).sort((a, b) => b - a);
+                        
+                        return allVersions.map(version => (
+                          <th key={version} className="text-right p-3 font-semibold">
+                            {version}차
+                          </th>
+                        ));
+                      })()}
+                    </tr>
+                  </thead>
+                  <tbody className="divide-y">
+                    {data.vendors.map((vendor) => (
+                      <tr
+                        key={vendor.vendorId}
                         className={cn(
-                          "w-10 h-10 rounded-full flex items-center justify-center font-bold",
-                          getRankColor(vendor.rank || 0)
+                          "hover:bg-gray-50 transition-colors",
+                          vendor.isSelected && "bg-blue-50"
                         )}
                       >
-                        {vendor.rank}
-                      </div>
-                      <div>
-                        <p className="font-semibold flex items-center gap-2">
-                          {vendor.vendorName}
-                          {vendor.isSelected && (
-                            <Badge className="bg-blue-600">선정</Badge>
-                          )}
-                        </p>
-                        <p className="text-sm text-muted-foreground">
-                          {vendor.vendorCode} • {vendor.vendorCountry}
-                        </p>
-                      </div>
-                    </div>
-
-                    <div className="flex items-center gap-6">
-                      {/* 조건 차이 표시 */}
-                      {vendor.conditionDifferences.criticalDifferences.length > 0 && (
-                        <TooltipProvider>
-                          <Tooltip>
-                            <TooltipTrigger>
-                              <Badge variant="destructive" className="gap-1">
-                                <AlertTriangle className="h-3 w-3" />
-                                중요 차이 {vendor.conditionDifferences.criticalDifferences.length}
-                              </Badge>
-                            </TooltipTrigger>
-                            <TooltipContent>
-                              <div className="space-y-1">
-                                {vendor.conditionDifferences.criticalDifferences.map((diff, idx) => (
-                                  <p key={idx} className="text-xs">{diff}</p>
-                                ))}
-                              </div>
-                            </TooltipContent>
-                          </Tooltip>
-                        </TooltipProvider>
-                      )}
-
-                      {/* 가격 정보 */}
-                      <div className="text-right">
-                        <p className="text-lg font-bold">
-                          {formatAmount(vendor.totalAmount, vendor.currency)}
-                        </p>
-                        <p className={cn("text-sm", getVarianceColor(vendor.priceVariance || 0))}>
-                          {vendor.priceVariance && vendor.priceVariance > 0 ? "+" : ""}
-                          {vendor.priceVariance?.toFixed(1)}% vs 평균
-                        </p>
-                      </div>
-                    </div>
-                  </div>
-                ))}
+                        {!hasSelection && (
+                          <td className="p-3">
+                            <input
+                              type="radio"
+                              name="vendor-selection"
+                              value={vendor.vendorId}
+                              checked={selectedVendorId === vendor.vendorId.toString()}
+                              onChange={(e) => setSelectedVendorId(e.target.value)}
+                              className="h-4 w-4 text-blue-600"
+                            />
+                          </td>
+                        )}
+                        <td className="p-3 text-sm font-medium">{vendor.vendorCode}</td>
+                        <td className="p-3">
+                          <div className="flex items-center gap-2">
+                            <span className="font-semibold">{vendor.vendorName}</span>
+                            {vendor.isSelected && (
+                              <Badge className="bg-blue-600 text-xs">선정</Badge>
+                            )}
+                          </div>
+                        </td>
+                        {(() => {
+                          const allVersions = Array.from(
+                            new Set(
+                              data.vendors.flatMap(v => v.responses.map(r => r.responseVersion))
+                            )
+                          ).sort((a, b) => b - a);
+                          
+                          return allVersions.map(version => {
+                            const response = vendor.responses.find(r => r.responseVersion === version);
+                            
+                            return (
+                              <td key={version} className="p-3 text-right">
+                                {response ? (
+                                  <Button
+                                    variant="link"
+                                    size="sm"
+                                    className="h-auto p-0 font-bold text-blue-600 hover:text-blue-800"
+                                    onClick={() => {
+                                      setSelectedResponse(response);
+                                      setSelectedVendorName(vendor.vendorName);
+                                      setShowItemDetailsDialog(true);
+                                    }}
+                                  >
+                                    {formatAmount(response.totalAmount, response.currency)}
+                                  </Button>
+                                ) : (
+                                  <span className="text-sm text-gray-400">-</span>
+                                )}
+                              </td>
+                            );
+                          });
+                        })()}
+                      </tr>
+                    ))}
+                  </tbody>
+                </table>
               </div>
             </CardContent>
           </Card>
@@ -733,16 +712,16 @@ export function QuotationCompareView({ data }: QuotationCompareViewProps) {
               <table className="w-full">
                 <thead>
                   <tr className="border-b">
-                    <th className="text-left p-2">항목</th>
-                    <th className="text-left p-2">구매자 제시</th>
+                    <th className="text-left p-3 font-semibold">항목</th>
+                    <th className="text-left p-3 font-semibold">구매자 제시</th>
                     {data.vendors.map((vendor) => (
                       <th key={vendor.vendorId} className={cn(
-                        "text-left p-2",
+                        "text-left p-3 font-semibold",
                         vendor.isSelected && "bg-blue-50"
                       )}>
                         {vendor.vendorName}
                         {vendor.isSelected && (
-                          <Badge className="ml-2 bg-blue-600">선정</Badge>
+                          <Badge className="ml-2 bg-blue-600 text-xs">선정</Badge>
                         )}
                       </th>
                     ))}
@@ -751,30 +730,33 @@ export function QuotationCompareView({ data }: QuotationCompareViewProps) {
                 <tbody className="divide-y">
                   {/* 통화 */}
                   <tr>
-                    <td className="p-2 font-medium">통화</td>
-                    <td className="p-2">{data.vendors[0]?.buyerConditions.currency}</td>
-                    {data.vendors.map((vendor) => (
-                      <td key={vendor.vendorId} className={cn(
-                        "p-2",
-                        vendor.isSelected && "bg-blue-50"
-                      )}>
-                        <div className="flex items-center gap-2">
-                          {vendor.vendorConditions.currency || vendor.buyerConditions.currency}
-                          {vendor.vendorConditions.currency !== vendor.buyerConditions.currency && (
-                            <Badge variant="outline" className="text-xs">변경</Badge>
-                          )}
-                        </div>
-                      </td>
-                    ))}
+                    <td className="p-3 font-medium">통화</td>
+                    <td className="p-3">{data.vendors[0]?.buyerConditions.currency}</td>
+                    {data.vendors.map((vendor) => {
+                      const latestResponse = vendor.responses[0]; // 최신 응답 (이미 정렬되어 있음)
+                      return (
+                        <td key={vendor.vendorId} className={cn(
+                          "p-3",
+                          vendor.isSelected && "bg-blue-50"
+                        )}>
+                          <div className="flex items-center gap-2">
+                            {latestResponse?.vendorConditions?.currency || vendor.buyerConditions.currency}
+                            {latestResponse?.vendorConditions?.currency && latestResponse.vendorConditions.currency !== vendor.buyerConditions.currency && (
+                              <Badge variant="destructive" className="text-xs">변경</Badge>
+                            )}
+                          </div>
+                        </td>
+                      );
+                    })}
                   </tr>
 
                   {/* 지급조건 */}
                   <tr>
-                    <td className="p-2 font-medium">지급조건</td>
-                    <td className="p-2">
+                    <td className="p-3 font-medium">지급조건</td>
+                    <td className="p-3">
                       <TooltipProvider>
                         <Tooltip>
-                          <TooltipTrigger>
+                          <TooltipTrigger className="cursor-help border-b border-dashed">
                             {data.vendors[0]?.buyerConditions.paymentTermsCode}
                           </TooltipTrigger>
                           <TooltipContent>
@@ -783,327 +765,298 @@ export function QuotationCompareView({ data }: QuotationCompareViewProps) {
                         </Tooltip>
                       </TooltipProvider>
                     </td>
-                    {data.vendors.map((vendor) => (
-                      <td key={vendor.vendorId} className={cn(
-                        "p-2",
-                        vendor.isSelected && "bg-blue-50"
-                      )}>
-                        <div className="flex items-center gap-2">
-                          <TooltipProvider>
-                            <Tooltip>
-                              <TooltipTrigger>
-                                {vendor.vendorConditions.paymentTermsCode || vendor.buyerConditions.paymentTermsCode}
-                              </TooltipTrigger>
-                              <TooltipContent>
-                                {vendor.vendorConditions.paymentTermsDesc || vendor.buyerConditions.paymentTermsDesc}
-                              </TooltipContent>
-                            </Tooltip>
-                          </TooltipProvider>
-                          {vendor.vendorConditions.paymentTermsCode &&
-                            vendor.vendorConditions.paymentTermsCode !== vendor.buyerConditions.paymentTermsCode && (
-                              <Badge variant="outline" className="text-xs">변경</Badge>
-                            )}
-                        </div>
-                      </td>
-                    ))}
+                    {data.vendors.map((vendor) => {
+                      const latestResponse = vendor.responses[0];
+                      return (
+                        <td key={vendor.vendorId} className={cn(
+                          "p-3",
+                          vendor.isSelected && "bg-blue-50"
+                        )}>
+                          <div className="flex items-center gap-2">
+                            <TooltipProvider>
+                              <Tooltip>
+                                <TooltipTrigger className="cursor-help border-b border-dashed">
+                                  {latestResponse?.vendorConditions?.paymentTermsCode || vendor.buyerConditions.paymentTermsCode}
+                                </TooltipTrigger>
+                                <TooltipContent>
+                                  {latestResponse?.vendorConditions?.paymentTermsDesc || vendor.buyerConditions.paymentTermsDesc}
+                                </TooltipContent>
+                              </Tooltip>
+                            </TooltipProvider>
+                            {latestResponse?.vendorConditions?.paymentTermsCode &&
+                              latestResponse.vendorConditions.paymentTermsCode !== vendor.buyerConditions.paymentTermsCode && (
+                                <Badge variant="outline" className="text-xs">변경</Badge>
+                              )}
+                          </div>
+                        </td>
+                      );
+                    })}
                   </tr>
 
-                  {/* 나머지 조건들도 동일한 패턴으로 처리 */}
-                </tbody>
-              </table>
-            </CardContent>
-          </Card>
-        </TabsContent>
-
-        {/* 아이템별 비교 */}
-        <TabsContent value="items" className="space-y-4">
-          <Card>
-            <CardHeader>
-              <CardTitle>PR 아이템별 가격 비교</CardTitle>
-            </CardHeader>
-            <CardContent>
-              <div className="space-y-2">
-                {data.prItems.map((item) => (
-                  <Collapsible
-                    key={item.prItemId}
-                    open={expandedItems.has(item.prItemId)}
-                    onOpenChange={() => toggleItemExpansion(item.prItemId)}
-                  >
-                    <div className="border rounded-lg">
-                      <CollapsibleTrigger className="w-full p-4 hover:bg-gray-50 transition-colors">
-                        <div className="flex items-center justify-between">
-                          <div className="flex items-center gap-4 text-left">
-                            <div className="flex items-center gap-2">
-                              {expandedItems.has(item.prItemId) ? (
-                                <ChevronUp className="h-4 w-4" />
-                              ) : (
-                                <ChevronDown className="h-4 w-4" />
+                  {/* 인코텀즈 */}
+                  <tr>
+                    <td className="p-3 font-medium">인코텀즈</td>
+                    <td className="p-3">
+                      <TooltipProvider>
+                        <Tooltip>
+                          <TooltipTrigger className="cursor-help border-b border-dashed">
+                            {data.vendors[0]?.buyerConditions.incotermsCode}
+                          </TooltipTrigger>
+                          <TooltipContent>
+                            {data.vendors[0]?.buyerConditions.incotermsDesc}
+                          </TooltipContent>
+                        </Tooltip>
+                      </TooltipProvider>
+                    </td>
+                    {data.vendors.map((vendor) => {
+                      const latestResponse = vendor.responses[0];
+                      return (
+                        <td key={vendor.vendorId} className={cn(
+                          "p-3",
+                          vendor.isSelected && "bg-blue-50"
+                        )}>
+                          <div className="flex items-center gap-2">
+                            <TooltipProvider>
+                              <Tooltip>
+                                <TooltipTrigger className="cursor-help border-b border-dashed">
+                                  {latestResponse?.vendorConditions?.incotermsCode || vendor.buyerConditions.incotermsCode}
+                                </TooltipTrigger>
+                                <TooltipContent>
+                                  {latestResponse?.vendorConditions?.incotermsDesc || vendor.buyerConditions.incotermsDesc}
+                                </TooltipContent>
+                              </Tooltip>
+                            </TooltipProvider>
+                            {latestResponse?.vendorConditions?.incotermsCode &&
+                              latestResponse.vendorConditions.incotermsCode !== vendor.buyerConditions.incotermsCode && (
+                                <Badge variant="outline" className="text-xs">변경</Badge>
                               )}
-                              <Package className="h-4 w-4 text-muted-foreground" />
-                            </div>
-                            <div>
-                              <p className="font-medium">{item.materialDescription}</p>
-                              <p className="text-sm text-muted-foreground">
-                                {item.materialCode} • {item.prNo} • {item.requestedQuantity} {item.uom}
-                              </p>
-                            </div>
                           </div>
-                          <div className="text-right">
-                            <p className="text-sm text-muted-foreground">단가 범위</p>
-                            <p className="font-semibold">
-                              {formatAmount(item.priceAnalysis.lowestPrice)} ~ {formatAmount(item.priceAnalysis.highestPrice)}
-                            </p>
-                          </div>
-                        </div>
-                      </CollapsibleTrigger>
-
-                      <CollapsibleContent>
-                        <div className="p-4 pt-0">
-                          <table className="w-full">
-                            <thead>
-                              <tr className="border-b text-sm">
-                                <th className="text-left p-2">벤더</th>
-                                <th className="text-right p-2">단가</th>
-                                <th className="text-right p-2">총액</th>
-                                <th className="text-right p-2">수량</th>
-                                <th className="text-left p-2">납기</th>
-                                <th className="text-left p-2">제조사</th>
-                                <th className="text-center p-2">순위</th>
-                              </tr>
-                            </thead>
-                            <tbody className="divide-y">
-                              {item.vendorQuotes.map((quote) => (
-                                <tr key={quote.vendorId} className="text-sm">
-                                  <td className="p-2 font-medium">{quote.vendorName}</td>
-                                  <td className="p-2 text-right">
-                                    {formatAmount(quote.unitPrice, quote.currency)}
-                                  </td>
-                                  <td className="p-2 text-right">
-                                    {formatAmount(quote.totalPrice, quote.currency)}
-                                  </td>
-                                  <td className="p-2 text-right">{quote.quotedQuantity}</td>
-                                  <td className="p-2">
-                                    {quote.deliveryDate
-                                      ? format(new Date(quote.deliveryDate), "yyyy-MM-dd")
-                                      : quote.leadTime
-                                        ? `${quote.leadTime}일`
-                                        : "-"}
-                                  </td>
-                                  <td className="p-2">
-                                    {quote.manufacturer && (
-                                      <div>
-                                        <p>{quote.manufacturer}</p>
-                                        {quote.modelNo && (
-                                          <p className="text-xs text-muted-foreground">{quote.modelNo}</p>
-                                        )}
-                                      </div>
-                                    )}
-                                  </td>
-                                  <td className="p-2 text-center">
-                                    <Badge className={cn("", getRankColor(quote.priceRank || 0))}>
-                                      #{quote.priceRank}
-                                    </Badge>
-                                  </td>
-                                </tr>
-                              ))}
-                            </tbody>
-                          </table>
-
-                          {/* 가격 분석 요약 */}
-                          <div className="mt-4 p-3 bg-gray-50 rounded-lg">
-                            <div className="grid grid-cols-4 gap-4 text-sm">
-                              <div>
-                                <p className="text-muted-foreground">평균 단가</p>
-                                <p className="font-semibold">
-                                  {formatAmount(item.priceAnalysis.averagePrice)}
-                                </p>
-                              </div>
-                              <div>
-                                <p className="text-muted-foreground">가격 편차</p>
-                                <p className="font-semibold">
-                                  ±{formatAmount(item.priceAnalysis.priceVariance)}
-                                </p>
-                              </div>
-                              <div>
-                                <p className="text-muted-foreground">최저가 업체</p>
-                                <p className="font-semibold">
-                                  {item.vendorQuotes.find(q => q.priceRank === 1)?.vendorName}
-                                </p>
-                              </div>
-                              <div>
-                                <p className="text-muted-foreground">가격 차이</p>
-                                <p className="font-semibold">
-                                  {((item.priceAnalysis.highestPrice - item.priceAnalysis.lowestPrice) /
-                                    item.priceAnalysis.lowestPrice * 100).toFixed(1)}%
-                                </p>
-                              </div>
-                            </div>
-                          </div>
-                        </div>
-                      </CollapsibleContent>
-                    </div>
-                  </Collapsible>
-                ))}
-              </div>
-            </CardContent>
-          </Card>
-        </TabsContent>
+                        </td>
+                      );
+                    })}
+                  </tr>
 
-        {/* 상세 분석 */}
-        <TabsContent value="analysis" className="space-y-4">
-          <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
-            {/* 위험 요소 분석 */}
-            <Card>
-              <CardHeader>
-                <CardTitle className="flex items-center gap-2">
-                  <AlertTriangle className="h-5 w-5 text-orange-500" />
-                  위험 요소 분석
-                </CardTitle>
-              </CardHeader>
-              <CardContent>
-                <div className="space-y-3">
-                  {data.vendors.map((vendor) => {
-                    if (!vendor.conditionDifferences.hasDifferences) return null;
-
-                    return (
-                      <div key={vendor.vendorId} className="p-3 border rounded-lg">
-                        <p className="font-medium mb-2">{vendor.vendorName}</p>
-                        {vendor.conditionDifferences.criticalDifferences.length > 0 && (
-                          <div className="space-y-1 mb-2">
-                            <p className="text-xs font-medium text-red-600">중요 차이점:</p>
-                            {vendor.conditionDifferences.criticalDifferences.map((diff, idx) => (
-                              <p key={idx} className="text-xs text-red-600 pl-2">• {diff}</p>
-                            ))}
-                          </div>
-                        )}
-                        {vendor.conditionDifferences.differences.length > 0 && (
-                          <div className="space-y-1">
-                            <p className="text-xs font-medium text-orange-600">일반 차이점:</p>
-                            {vendor.conditionDifferences.differences.map((diff, idx) => (
-                              <p key={idx} className="text-xs text-orange-600 pl-2">• {diff}</p>
-                            ))}
+                  {/* 선적지 */}
+                  <tr>
+                    <td className="p-3 font-medium">선적지</td>
+                    <td className="p-3">{data.vendors[0]?.buyerConditions.placeOfShipping || "-"}</td>
+                    {data.vendors.map((vendor) => {
+                      const latestResponse = vendor.responses[0];
+                      return (
+                        <td key={vendor.vendorId} className={cn(
+                          "p-3",
+                          vendor.isSelected && "bg-blue-50"
+                        )}>
+                          <div className="flex items-center gap-2">
+                            {latestResponse?.vendorConditions?.placeOfShipping || vendor.buyerConditions.placeOfShipping || "-"}
+                            {latestResponse?.vendorConditions?.placeOfShipping &&
+                              latestResponse.vendorConditions.placeOfShipping !== vendor.buyerConditions.placeOfShipping && (
+                                <Badge variant="outline" className="text-xs">변경</Badge>
+                              )}
                           </div>
-                        )}
-                      </div>
-                    );
-                  })}
-                </div>
-              </CardContent>
-            </Card>
-
-            {/* 추천 사항 */}
-            <Card>
-              <CardHeader>
-                <CardTitle className="flex items-center gap-2">
-                  <Info className="h-5 w-5 text-blue-500" />
-                  선정 추천
-                </CardTitle>
-              </CardHeader>
-              <CardContent>
-                <div className="space-y-4">
-                  {/* 가격 기준 추천 */}
-                  <div className="p-3 bg-green-50 border border-green-200 rounded-lg">
-                    <p className="font-medium text-green-800 mb-1">가격 우선 선정</p>
-                    <p className="text-sm text-green-700">
-                      {data.vendors[0]?.vendorName} - {formatAmount(data.vendors[0]?.totalAmount || 0)}
-                    </p>
-                    {data.vendors[0]?.conditionDifferences.hasDifferences && (
-                      <p className="text-xs text-orange-600 mt-1">
-                        ⚠️ 조건 차이 검토 필요
-                      </p>
-                    )}
-                  </div>
+                        </td>
+                      );
+                    })}
+                  </tr>
 
-                  {/* 조건 준수 기준 추천 */}
-                  <div className="p-3 bg-blue-50 border border-blue-200 rounded-lg">
-                    <p className="font-medium text-blue-800 mb-1">조건 준수 우선 선정</p>
-                    {(() => {
-                      const compliantVendor = data.vendors.find(v => !v.conditionDifferences.hasDifferences);
-                      if (compliantVendor) {
-                        return (
-                          <div>
-                            <p className="text-sm text-blue-700">
-                              {compliantVendor.vendorName} - {formatAmount(compliantVendor.totalAmount)}
-                            </p>
-                            <p className="text-xs text-blue-600 mt-1">
-                              모든 조건 충족 (가격 순위: #{compliantVendor.rank})
-                            </p>
-                          </div>
-                        );
-                      }
+                  {/* 하역지 */}
+                  <tr>
+                    <td className="p-3 font-medium">하역지</td>
+                    <td className="p-3">{data.vendors[0]?.buyerConditions.placeOfDestination || "-"}</td>
+                    {data.vendors.map((vendor) => {
+                      const latestResponse = vendor.responses[0];
                       return (
-                        <p className="text-sm text-blue-700">
-                          모든 조건을 충족하는 벤더 없음
-                        </p>
+                        <td key={vendor.vendorId} className={cn(
+                          "p-3",
+                          vendor.isSelected && "bg-blue-50"
+                        )}>
+                          <div className="flex items-center gap-2">
+                            {latestResponse?.vendorConditions?.placeOfDestination || vendor.buyerConditions.placeOfDestination || "-"}
+                            {latestResponse?.vendorConditions?.placeOfDestination &&
+                              latestResponse.vendorConditions.placeOfDestination !== vendor.buyerConditions.placeOfDestination && (
+                                <Badge variant="outline" className="text-xs">변경</Badge>
+                              )}
+                          </div>
+                        </td>
                       );
-                    })()}
-                  </div>
+                    })}
+                  </tr>
 
-                  {/* 균형 추천 */}
-                  <div className="p-3 bg-purple-50 border border-purple-200 rounded-lg">
-                    <p className="font-medium text-purple-800 mb-1">균형 선정 (추천)</p>
-                    {(() => {
-                      // 가격 순위와 조건 차이를 고려한 점수 계산
-                      const scoredVendors = data.vendors.map(v => ({
-                        ...v,
-                        score: (v.rank || 10) + v.conditionDifferences.criticalDifferences.length * 3 +
-                          v.conditionDifferences.differences.length
-                      }));
-                      scoredVendors.sort((a, b) => a.score - b.score);
-                      const recommended = scoredVendors[0];
+                  {/* 납기일 */}
+                  <tr>
+                    <td className="p-3 font-medium">납기일</td>
+                    <td className="p-3">
+                      {data.vendors[0]?.buyerConditions.deliveryDate 
+                        ? format(new Date(data.vendors[0].buyerConditions.deliveryDate), "yyyy-MM-dd")
+                        : "-"}
+                    </td>
+                    {data.vendors.map((vendor) => {
+                      const latestResponse = vendor.responses[0];
+                      return (
+                        <td key={vendor.vendorId} className={cn(
+                          "p-3",
+                          vendor.isSelected && "bg-blue-50"
+                        )}>
+                          <div className="flex items-center gap-2">
+                            {latestResponse?.vendorConditions?.deliveryDate 
+                              ? format(new Date(latestResponse.vendorConditions.deliveryDate), "yyyy-MM-dd")
+                              : vendor.buyerConditions.deliveryDate
+                                ? format(new Date(vendor.buyerConditions.deliveryDate), "yyyy-MM-dd")
+                                : "-"}
+                            {latestResponse?.vendorConditions?.deliveryDate && vendor.buyerConditions.deliveryDate &&
+                              new Date(latestResponse.vendorConditions.deliveryDate).getTime() !== new Date(vendor.buyerConditions.deliveryDate).getTime() && (
+                                <Badge variant="outline" className="text-xs">변경</Badge>
+                              )}
+                          </div>
+                        </td>
+                      );
+                    })}
+                  </tr>
 
+                  {/* 세금조건 */}
+                  <tr>
+                    <td className="p-3 font-medium">세금조건</td>
+                    <td className="p-3">{data.vendors[0]?.buyerConditions.taxCode || "-"}</td>
+                    {data.vendors.map((vendor) => {
+                      const latestResponse = vendor.responses[0];
                       return (
-                        <div>
-                          <p className="text-sm text-purple-700">
-                            {recommended.vendorName} - {formatAmount(recommended.totalAmount)}
-                          </p>
-                          <p className="text-xs text-purple-600 mt-1">
-                            가격 순위 #{recommended.rank}, 조건 차이 최소화
-                          </p>
-                        </div>
+                        <td key={vendor.vendorId} className={cn(
+                          "p-3",
+                          vendor.isSelected && "bg-blue-50"
+                        )}>
+                          <div className="flex items-center gap-2">
+                            {latestResponse?.vendorConditions?.taxCode || vendor.buyerConditions.taxCode || "-"}
+                            {latestResponse?.vendorConditions?.taxCode &&
+                              latestResponse.vendorConditions.taxCode !== vendor.buyerConditions.taxCode && (
+                                <Badge variant="outline" className="text-xs">변경</Badge>
+                              )}
+                          </div>
+                        </td>
                       );
-                    })()}
-                  </div>
-                </div>
-              </CardContent>
-            </Card>
-          </div>
+                    })}
+                  </tr>
 
-          {/* 벤더별 비고사항 */}
-          {data.vendors.some(v => v.generalRemark || v.technicalProposal) && (
-            <Card>
-              <CardHeader>
-                <CardTitle>벤더 제안사항 및 비고</CardTitle>
-              </CardHeader>
-              <CardContent>
-                <div className="space-y-4">
-                  {data.vendors.map((vendor) => {
-                    if (!vendor.generalRemark && !vendor.technicalProposal) return null;
-
-                    return (
-                      <div key={vendor.vendorId} className="border rounded-lg p-4">
-                        <p className="font-medium mb-2">{vendor.vendorName}</p>
-                        {vendor.generalRemark && (
-                          <div className="mb-2">
-                            <p className="text-sm font-medium text-muted-foreground">일반 비고:</p>
-                            <p className="text-sm">{vendor.generalRemark}</p>
+                  {/* 계약기간 */}
+                  <tr>
+                    <td className="p-3 font-medium">계약기간</td>
+                    <td className="p-3">{data.vendors[0]?.buyerConditions.contractDuration || "-"}</td>
+                    {data.vendors.map((vendor) => {
+                      const latestResponse = vendor.responses[0];
+                      return (
+                        <td key={vendor.vendorId} className={cn(
+                          "p-3",
+                          vendor.isSelected && "bg-blue-50"
+                        )}>
+                          <div className="flex items-center gap-2">
+                            {latestResponse?.vendorConditions?.contractDuration || vendor.buyerConditions.contractDuration || "-"}
+                            {latestResponse?.vendorConditions?.contractDuration &&
+                              latestResponse.vendorConditions.contractDuration !== vendor.buyerConditions.contractDuration && (
+                                <Badge variant="outline" className="text-xs">변경</Badge>
+                              )}
                           </div>
-                        )}
-                        {vendor.technicalProposal && (
+                        </td>
+                      );
+                    })}
+                  </tr>
+                </tbody>
+              </table>
+            </CardContent>
+          </Card>
+        </TabsContent>
+      </Tabs>
+
+      {/* 품목별 상세 정보 다이얼로그 */}
+      <Dialog open={showItemDetailsDialog} onOpenChange={setShowItemDetailsDialog}>
+        <DialogContent className="max-w-6xl max-h-[90vh] overflow-y-auto">
+          <DialogHeader>
+            <DialogTitle>
+              {selectedVendorName} - {selectedResponse?.responseVersion}차 품목별 견적 상세
+            </DialogTitle>
+          </DialogHeader>
+
+          <div className="overflow-x-auto">
+            <table className="w-full">
+              <thead>
+                <tr className="border-b bg-gray-50">
+                  <th className="text-left p-3 font-semibold">품목코드</th>
+                  <th className="text-left p-3 font-semibold">품목명</th>
+                  <th className="text-right p-3 font-semibold">수량</th>
+                  <th className="text-right p-3 font-semibold">단가</th>
+                  <th className="text-right p-3 font-semibold">총액</th>
+                  <th className="text-left p-3 font-semibold">납기</th>
+                  <th className="text-left p-3 font-semibold">제조사</th>
+                </tr>
+              </thead>
+              <tbody className="divide-y">
+                {selectedResponse?.quotationItems?.map((quoteItem) => {
+                  const prItem = data.prItems.find(item => item.prItemId === quoteItem.prItemId);
+                  if (!prItem) return null;
+
+                  return (
+                    <tr key={quoteItem.prItemId} className="hover:bg-gray-50">
+                      <td className="p-3 text-sm">{prItem.materialCode}</td>
+                      <td className="p-3">
+                        <p className="font-medium">{prItem.materialDescription}</p>
+                        <p className="text-xs text-muted-foreground">
+                          {prItem.prNo} • {prItem.prItem}
+                        </p>
+                      </td>
+                      <td className="p-3 text-right">
+                        {quoteItem.quantity} {prItem.uom}
+                      </td>
+                      <td className="p-3 text-right font-medium">
+                        {formatAmount(quoteItem.unitPrice, quoteItem.currency)}
+                      </td>
+                      <td className="p-3 text-right font-bold">
+                        {formatAmount(quoteItem.totalPrice, quoteItem.currency)}
+                      </td>
+                      <td className="p-3 text-sm">
+                        {quoteItem.deliveryDate
+                          ? format(new Date(quoteItem.deliveryDate), "yyyy-MM-dd")
+                          : quoteItem.leadTime
+                            ? `${quoteItem.leadTime}일`
+                            : "-"}
+                      </td>
+                      <td className="p-3 text-sm">
+                        {quoteItem.manufacturer ? (
                           <div>
-                            <p className="text-sm font-medium text-muted-foreground">기술 제안:</p>
-                            <p className="text-sm">{vendor.technicalProposal}</p>
+                            <p>{quoteItem.manufacturer}</p>
+                            {quoteItem.modelNo && (
+                              <p className="text-xs text-muted-foreground">{quoteItem.modelNo}</p>
+                            )}
                           </div>
-                        )}
-                      </div>
-                    );
-                  })}
-                </div>
-              </CardContent>
-            </Card>
+                        ) : "-"}
+                      </td>
+                    </tr>
+                  );
+                })}
+              </tbody>
+            </table>
+          </div>
+
+          {/* 비고사항 */}
+          {(selectedResponse?.generalRemark || selectedResponse?.technicalProposal) && (
+            <div className="mt-6 pt-6 border-t">
+              <h4 className="font-semibold mb-3">비고사항</h4>
+              <div className="space-y-3">
+                {selectedResponse.generalRemark && (
+                  <div>
+                    <p className="text-sm font-medium text-muted-foreground">일반 비고:</p>
+                    <p className="text-sm">{selectedResponse.generalRemark}</p>
+                  </div>
+                )}
+                {selectedResponse.technicalProposal && (
+                  <div>
+                    <p className="text-sm font-medium text-muted-foreground">기술 제안:</p>
+                    <p className="text-sm">{selectedResponse.technicalProposal}</p>
+                  </div>
+                )}
+              </div>
+            </div>
           )}
-        </TabsContent>
-      </Tabs>
+        </DialogContent>
+      </Dialog>
+
 
       {/* 업체 선정 모달 */}
       {showSelectionDialog && (
@@ -1113,57 +1066,62 @@ export function QuotationCompareView({ data }: QuotationCompareViewProps) {
               {hasSelection ? "업체 재선정 확인" : "업체 선정 확인"}
             </h3>
 
-            {selectedVendorId && (
-              <div className="space-y-4">
-                <div className="rounded-lg border p-4">
-                  <div className="space-y-2">
-                    <div className="flex justify-between">
-                      <span className="text-sm font-medium">선정 업체</span>
-                      <span className="text-sm font-bold">
-                        {data.vendors.find(v => v.vendorId === parseInt(selectedVendorId))?.vendorName}
-                      </span>
-                    </div>
-                    <div className="flex justify-between">
-                      <span className="text-sm font-medium">견적 금액</span>
-                      <span className="text-sm">
-                        {formatAmount(
-                          data.vendors.find(v => v.vendorId === parseInt(selectedVendorId))?.totalAmount || 0,
-                          data.vendors.find(v => v.vendorId === parseInt(selectedVendorId))?.currency
-                        )}
-                      </span>
-                    </div>
-                    <div className="flex justify-between">
-                      <span className="text-sm font-medium">가격 순위</span>
-                      <span className="text-sm">
-                        #{data.vendors.find(v => v.vendorId === parseInt(selectedVendorId))?.rank || 0}
-                      </span>
+            {selectedVendorId && (() => {
+              const vendor = data.vendors.find(v => v.vendorId === parseInt(selectedVendorId));
+              const latestResponse = vendor?.responses[0];
+              
+              return (
+                <div className="space-y-4">
+                  <div className="rounded-lg border p-4">
+                    <div className="space-y-2">
+                      <div className="flex justify-between">
+                        <span className="text-sm font-medium">선정 업체</span>
+                        <span className="text-sm font-bold">
+                          {vendor?.vendorName}
+                        </span>
+                      </div>
+                      <div className="flex justify-between">
+                        <span className="text-sm font-medium">견적 금액</span>
+                        <span className="text-sm">
+                          {formatAmount(
+                            latestResponse?.totalAmount || 0,
+                            latestResponse?.currency || "USD"
+                          )}
+                        </span>
+                      </div>
+                      <div className="flex justify-between">
+                        <span className="text-sm font-medium">가격 순위</span>
+                        <span className="text-sm">
+                          #{latestResponse?.rank || 0}
+                        </span>
+                      </div>
+                      {latestResponse?.conditionDifferences.hasDifferences && (
+                        <Alert className="mt-2">
+                          <AlertCircle className="h-4 w-4" />
+                          <AlertDescription>
+                            제시 조건과 차이가 있습니다. 선정 사유를 명확히 기재해주세요.
+                          </AlertDescription>
+                        </Alert>
+                      )}
                     </div>
-                    {data.vendors.find(v => v.vendorId === parseInt(selectedVendorId))?.conditionDifferences.hasDifferences && (
-                      <Alert className="mt-2">
-                        <AlertCircle className="h-4 w-4" />
-                        <AlertDescription>
-                          제시 조건과 차이가 있습니다. 선정 사유를 명확히 기재해주세요.
-                        </AlertDescription>
-                      </Alert>
-                    )}
                   </div>
-                </div>
 
-                <div className="space-y-2">
-                  <label htmlFor="selection-reason" className="text-sm font-medium">
-                    선정 사유 *
-                  </label>
-                  <textarea
-                    id="selection-reason"
-                    className="w-full min-h-[100px] p-3 border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
-                    placeholder="업체 선정 사유를 입력해주세요..."
-                    value={selectionReason}
-                    onChange={(e) => setSelectionReason(e.target.value)}
-                    required
-                  />
+                  <div className="space-y-2">
+                    <label htmlFor="selection-reason" className="text-sm font-medium">
+                      선정 사유 *
+                    </label>
+                    <textarea
+                      id="selection-reason"
+                      className="w-full min-h-[100px] p-3 border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
+                      placeholder="업체 선정 사유를 입력해주세요..."
+                      value={selectionReason}
+                      onChange={(e) => setSelectionReason(e.target.value)}
+                      required
+                    />
+                  </div>
                 </div>
-              </div>
-            )}
+              );
+            })()}
 
             <div className="flex justify-end gap-2 mt-6">
               <Button
@@ -1527,7 +1485,7 @@ export function QuotationCompareView({ data }: QuotationCompareViewProps) {
                   setSelectedGeneralContractType("");
                   setContractStartDate("");
                   setContractEndDate("");
-                  setBiddingContractType("");
+                  setBiddingContractType("unit_price");
                   setBiddingType("");
                   setAwardCount("single");
                   setBiddingStartDate("");
-- 
cgit v1.2.3

