From 9bf5b15734cdf87a02c68b2d2a25046a0678a037 Mon Sep 17 00:00:00 2001
From: joonhoekim <26rote@gmail.com>
Date: Wed, 19 Nov 2025 15:01:42 +0900
Subject: (김준회) 견적상세관리: PO 생성 요청시, 오류 발생시 PO생성
 트랜잭션처리 처리 (폴백)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 lib/rfq-last/quotation-compare-view.tsx | 90 +++++++++++++++++++++++++++++++--
 1 file changed, 85 insertions(+), 5 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 7a4fd751..40ea676c 100644
--- a/lib/rfq-last/quotation-compare-view.tsx
+++ b/lib/rfq-last/quotation-compare-view.tsx
@@ -72,6 +72,9 @@ export function QuotationCompareView({ data }: QuotationCompareViewProps) {
   const [selectedContractType, setSelectedContractType] = React.useState<"PO" | "CONTRACT" | "BIDDING" | "">("");
   const [cancelReason, setCancelReason] = React.useState("");
   const [isSubmitting, setIsSubmitting] = React.useState(false);
+  const [showErrorDialog, setShowErrorDialog] = React.useState(false);
+  const [errorMessage, setErrorMessage] = React.useState("");
+  const [errorDetails, setErrorDetails] = React.useState<string>("");
   const router = useRouter()
 
   const [selectedGeneralContractType, setSelectedGeneralContractType] = React.useState("");
@@ -190,7 +193,7 @@ export function QuotationCompareView({ data }: QuotationCompareViewProps) {
     setIsSubmitting(true);
 
     try {
-      let result;
+      let result: { success: boolean; message?: string; error?: string; responseData?: string; statusCode?: number; poNumber?: string; contractNumber?: string; contractId?: number; biddingNumber?: string; biddingId?: number };
 
       switch (selectedContractType) {
         case "PO":
@@ -254,11 +257,37 @@ export function QuotationCompareView({ data }: QuotationCompareViewProps) {
         setBiddingEndDate("");
         router.refresh();
       } else {
-        throw new Error(result.error || "계약 진행 중 오류가 발생했습니다.");
+        // 실패 응답 처리
+        const errorMsg = result.error || "계약 진행 중 오류가 발생했습니다.";
+        const responseData = result.responseData;
+        
+        // 'check payment terms and tax code' 메시지 확인
+        const isPaymentTaxError = 
+          errorMsg.toLowerCase().includes("check payment terms and tax code") ||
+          (responseData && responseData.toLowerCase().includes("check payment terms and tax code"));
+        
+        if (isPaymentTaxError) {
+          toast.error("Please check payment terms and tax code. SAP rejected it", {
+            duration: 5000,
+          });
+        }
+        
+        // 에러 dialog 표시
+        setErrorMessage(errorMsg);
+        setErrorDetails(responseData || "");
+        setShowErrorDialog(true);
+        
+        // Dialog는 닫지 않고 사용자가 다시 시도할 수 있도록 유지
+        console.error("계약 생성 실패:", errorMsg);
       }
     } catch (error) {
       console.error("계약 생성 오류:", error);
-      toast.error(error instanceof Error ? error.message : "계약 진행 중 오류가 발생했습니다.");
+      const errorMsg = error instanceof Error ? error.message : "계약 진행 중 오류가 발생했습니다.";
+      toast.error(errorMsg);
+      
+      // 에러 dialog 표시
+      setErrorMessage(errorMsg);
+      setShowErrorDialog(true);
     } finally {
       setIsSubmitting(false);
     }
@@ -1485,7 +1514,7 @@ export function QuotationCompareView({ data }: QuotationCompareViewProps) {
                         id="bidding-contract-type"
                         className="w-full px-3 py-2 border rounded-md focus:outline-none focus:ring-2 focus:ring-purple-500"
                         value={biddingContractType}
-                        onChange={(e) => setBiddingContractType(e.target.value as any)}
+                        onChange={(e) => setBiddingContractType(e.target.value as "unit_price" | "general" | "sale")}
                         required
                       >
                         <option value="">계약구분을 선택하세요</option>
@@ -1527,7 +1556,7 @@ export function QuotationCompareView({ data }: QuotationCompareViewProps) {
                         id="award-count"
                         className="w-full px-3 py-2 border rounded-md focus:outline-none focus:ring-2 focus:ring-purple-500"
                         value={awardCount}
-                        onChange={(e) => setAwardCount(e.target.value as any)}
+                        onChange={(e) => setAwardCount(e.target.value as "single" | "multiple")}
                       >
                         {awardCounts.map(type => (
                           <option key={type.value} value={type.value}>
@@ -1642,6 +1671,57 @@ export function QuotationCompareView({ data }: QuotationCompareViewProps) {
         </div>
       )}
 
+      {/* 에러 메시지 Dialog */}
+      <Dialog open={showErrorDialog} onOpenChange={setShowErrorDialog}>
+        <DialogContent className="max-w-2xl">
+          <DialogHeader>
+            <DialogTitle className="flex items-center gap-2 text-red-600">
+              <AlertCircle className="h-5 w-5" />
+              계약 생성 실패
+            </DialogTitle>
+          </DialogHeader>
+          
+          <div className="space-y-4">
+            <Alert variant="destructive">
+              <AlertTriangle className="h-4 w-4" />
+              <AlertTitle>오류 발생</AlertTitle>
+              <AlertDescription className="mt-2">
+                {errorMessage}
+              </AlertDescription>
+            </Alert>
+            
+            {errorDetails && (
+              <div className="space-y-2">
+                <p className="text-sm font-medium">상세 응답 메시지:</p>
+                <div className="p-3 bg-gray-50 rounded-md border border-gray-200 max-h-[300px] overflow-y-auto">
+                  <pre className="text-xs whitespace-pre-wrap break-words">
+                    {errorDetails}
+                  </pre>
+                </div>
+              </div>
+            )}
+            
+            <div className="p-4 bg-blue-50 rounded-md border border-blue-200">
+              <p className="text-sm text-blue-800">
+                <strong>안내:</strong> 계약 생성 dialog를 닫지 않았으므로 필요한 경우 조건을 수정하여 다시 시도할 수 있습니다.
+              </p>
+            </div>
+          </div>
+          
+          <div className="flex justify-end gap-2 mt-4">
+            <Button
+              variant="outline"
+              onClick={() => {
+                setShowErrorDialog(false);
+                setErrorMessage("");
+                setErrorDetails("");
+              }}
+            >
+              확인
+            </Button>
+          </div>
+        </DialogContent>
+      </Dialog>
 
     </div>
   );
-- 
cgit v1.2.3

