diff options
| author | joonhoekim <26rote@gmail.com> | 2025-11-19 15:01:42 +0900 |
|---|---|---|
| committer | joonhoekim <26rote@gmail.com> | 2025-11-19 15:01:42 +0900 |
| commit | 9bf5b15734cdf87a02c68b2d2a25046a0678a037 (patch) | |
| tree | dc85b186618b46adbebb1722764bfb1f33a8a83b /lib/rfq-last | |
| parent | 7df302681099aa7f17148e2747fe08bb39ec2e40 (diff) | |
(김준회) 견적상세관리: PO 생성 요청시, 오류 발생시 PO생성 트랜잭션처리 처리 (폴백)
Diffstat (limited to 'lib/rfq-last')
| -rw-r--r-- | lib/rfq-last/quotation-compare-view.tsx | 90 |
1 files changed, 85 insertions, 5 deletions
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> ); |
