fix: 견적 확정 시 finalize API 호출 및 라벨 수정
- 견적 확정 시 updateQuote + finalizeQuote 순차 호출 - is_final 플래그가 정상적으로 설정되어 목록에서 "최종확정" 뱃지 표시 - 버튼 라벨: 임시저장 → 저장, 최종저장 → 견적 확정 - 뱃지 라벨: 최종저장 → 견적 확정, 임시저장 → 저장됨 - toast 메시지 업데이트
This commit is contained in:
@@ -16,7 +16,7 @@ import { IntegratedDetailTemplate } from "@/components/templates/IntegratedDetai
|
||||
import { quoteConfig } from "@/components/quotes/quoteConfig";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { toast } from "sonner";
|
||||
import { getQuoteById, updateQuote, calculateBomBulk, BomCalculateItem } from "@/components/quotes/actions";
|
||||
import { getQuoteById, updateQuote, finalizeQuote, calculateBomBulk, BomCalculateItem } from "@/components/quotes/actions";
|
||||
import { transformApiToV2, transformV2ToApi } from "@/components/quotes/types";
|
||||
|
||||
export default function QuoteDetailPage() {
|
||||
@@ -113,6 +113,16 @@ export default function QuoteDetailPage() {
|
||||
router.push("/sales/quote-management");
|
||||
}, [router]);
|
||||
|
||||
// 수정 모드로 전환 핸들러
|
||||
const handleEdit = useCallback(() => {
|
||||
router.push(`/sales/quote-management/${quoteId}?mode=edit`);
|
||||
}, [router, quoteId]);
|
||||
|
||||
// 수주등록 페이지로 이동 핸들러
|
||||
const handleOrderRegister = useCallback(() => {
|
||||
router.push(`/sales/order-management-sales/new?quoteId=${quoteId}`);
|
||||
}, [router, quoteId]);
|
||||
|
||||
// 수정 저장 핸들러
|
||||
const handleSave = useCallback(async (data: QuoteFormDataV2, saveType: "temporary" | "final") => {
|
||||
setIsSaving(true);
|
||||
@@ -123,26 +133,44 @@ export default function QuoteDetailPage() {
|
||||
|
||||
console.log("[QuoteDetailPage] 수정 데이터:", apiData);
|
||||
console.log("[QuoteDetailPage] 저장 타입:", saveType);
|
||||
console.log("[QuoteDetailPage] 현재 모드:", isEditMode ? "edit" : "view");
|
||||
|
||||
// API 호출
|
||||
const result = await updateQuote(quoteId, apiData);
|
||||
// 1. 먼저 데이터 저장
|
||||
const updateResult = await updateQuote(quoteId, apiData);
|
||||
|
||||
if (!result.success) {
|
||||
toast.error(result.error || "저장 중 오류가 발생했습니다.");
|
||||
if (!updateResult.success) {
|
||||
toast.error(updateResult.error || "저장 중 오류가 발생했습니다.");
|
||||
return;
|
||||
}
|
||||
|
||||
toast.success(`${saveType === "temporary" ? "임시" : "최종"} 저장 완료`);
|
||||
// 2. 견적 확정인 경우 finalize API 호출
|
||||
if (saveType === "final") {
|
||||
const finalizeResult = await finalizeQuote(quoteId);
|
||||
|
||||
// 저장 후 view 모드로 전환
|
||||
router.push(`/sales/quote-management/${quoteId}`);
|
||||
if (!finalizeResult.success) {
|
||||
toast.error(finalizeResult.error || "견적 확정 중 오류가 발생했습니다.");
|
||||
return;
|
||||
}
|
||||
|
||||
toast.success("견적이 확정되었습니다.");
|
||||
} else {
|
||||
toast.success("저장되었습니다.");
|
||||
}
|
||||
|
||||
if (isEditMode) {
|
||||
// edit 모드에서 저장 후 view 모드로 전환
|
||||
router.push(`/sales/quote-management/${quoteId}`);
|
||||
} else {
|
||||
// view 모드에서 최종저장 후 페이지 새로고침 (데이터 갱신)
|
||||
router.refresh();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("[QuoteDetailPage] 저장 오류:", error);
|
||||
toast.error("저장 중 오류가 발생했습니다.");
|
||||
} finally {
|
||||
setIsSaving(false);
|
||||
}
|
||||
}, [router, quoteId]);
|
||||
}, [router, quoteId, isEditMode]);
|
||||
|
||||
// 동적 config (모드별 타이틀)
|
||||
const dynamicConfig = useMemo(() => {
|
||||
@@ -158,7 +186,7 @@ export default function QuoteDetailPage() {
|
||||
if (!quote) return null;
|
||||
return (
|
||||
<Badge variant={quote.status === "final" ? "default" : quote.status === "temporary" ? "secondary" : "outline"}>
|
||||
{quote.status === "final" ? "최종저장" : quote.status === "temporary" ? "임시저장" : "작성중"}
|
||||
{quote.status === "final" ? "견적 확정" : quote.status === "temporary" ? "저장됨" : "작성중"}
|
||||
</Badge>
|
||||
);
|
||||
}, [quote]);
|
||||
@@ -169,13 +197,15 @@ export default function QuoteDetailPage() {
|
||||
<QuoteRegistrationV2
|
||||
mode={isEditMode ? "edit" : "view"}
|
||||
onBack={handleBack}
|
||||
onSave={isEditMode ? handleSave : undefined}
|
||||
onSave={handleSave}
|
||||
onEdit={handleEdit}
|
||||
onOrderRegister={handleOrderRegister}
|
||||
initialData={quote}
|
||||
isLoading={isSaving}
|
||||
hideHeader={true}
|
||||
/>
|
||||
);
|
||||
}, [isEditMode, handleBack, handleSave, quote, isSaving]);
|
||||
}, [isEditMode, handleBack, handleSave, handleEdit, handleOrderRegister, quote, isSaving]);
|
||||
|
||||
// IntegratedDetailTemplate 사용
|
||||
return (
|
||||
|
||||
@@ -619,7 +619,7 @@ export function QuoteRegistrationV2({
|
||||
status: saveType === "temporary" ? "temporary" : "final",
|
||||
};
|
||||
await onSave(dataToSave, saveType);
|
||||
toast.success(saveType === "temporary" ? "임시 저장되었습니다." : "최종 저장되었습니다.");
|
||||
toast.success(saveType === "temporary" ? "저장되었습니다." : "견적이 확정되었습니다.");
|
||||
} catch (error) {
|
||||
if (isNextRedirectError(error)) throw error;
|
||||
toast.error("저장 중 오류가 발생했습니다.");
|
||||
@@ -647,7 +647,7 @@ export function QuoteRegistrationV2({
|
||||
{pageTitle}
|
||||
</h1>
|
||||
<Badge variant={formData.status === "final" ? "default" : formData.status === "temporary" ? "secondary" : "outline"}>
|
||||
{formData.status === "final" ? "최종저장" : formData.status === "temporary" ? "임시저장" : "작성중"}
|
||||
{formData.status === "final" ? "견적 확정" : formData.status === "temporary" ? "저장됨" : "작성중"}
|
||||
</Badge>
|
||||
</div>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user