fix: [order] 수주 변환 연동 + 상세/수정 UI 개선
- 견적→수주 변환 API 연동 (createOrderFromQuote) - 수주 상세 뷰 개선 (PhoneInput, 금액 포맷) - 수주 수정 페이지 필드명 수정 (deliveryDate→expectedShipDate)
This commit is contained in:
@@ -520,10 +520,10 @@ export default function OrderEditPage() {
|
||||
<TableCell className="text-center">{formatQuantity(item.quantity, item.unit)}</TableCell>
|
||||
<TableCell className="text-center">{item.unit}</TableCell>
|
||||
<TableCell className="text-right">
|
||||
{formatAmount(item.unitPrice)}원
|
||||
{formatAmount(item.unitPrice)}
|
||||
</TableCell>
|
||||
<TableCell className="text-right font-medium">
|
||||
{formatAmount(item.amount ?? 0)}원
|
||||
{formatAmount(item.amount ?? 0)}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
@@ -536,7 +536,7 @@ export default function OrderEditPage() {
|
||||
<div className="flex items-center gap-4 text-sm">
|
||||
<span className="text-muted-foreground">소계:</span>
|
||||
<span className="w-32 text-right">
|
||||
{formatAmount(form.subtotal)}원
|
||||
{formatAmount(form.subtotal)}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-4 text-sm">
|
||||
@@ -546,7 +546,7 @@ export default function OrderEditPage() {
|
||||
<div className="flex items-center gap-4 text-lg font-semibold">
|
||||
<span>총금액:</span>
|
||||
<span className="w-32 text-right text-green-600">
|
||||
{formatAmount(form.totalAmount)}원
|
||||
{formatAmount(form.totalAmount)}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -620,7 +620,13 @@ export default function OrderDetailPage() {
|
||||
const product = order.products?.[nodeIndex];
|
||||
const nodeWidth = (node.options?.width as number) || product?.openWidth;
|
||||
const nodeHeight = (node.options?.height as number) || product?.openHeight;
|
||||
const productName = product?.productName || node.name || `개소 ${nodeIndex + 1}`;
|
||||
const nodeProductName = (node.options as Record<string, unknown>)?.product_name as string || product?.productName || '';
|
||||
const nodeFloor = (node.options as Record<string, unknown>)?.floor as string || '';
|
||||
const nodeSymbol = (node.options as Record<string, unknown>)?.symbol as string || '';
|
||||
const locLabel = [nodeFloor, nodeSymbol].filter(Boolean).join(' / ');
|
||||
const productName = nodeProductName
|
||||
? `${nodeProductName}${locLabel ? ` (${locLabel})` : ''}`
|
||||
: node.name || `개소 ${nodeIndex + 1}`;
|
||||
const nodeItems = node.items || [];
|
||||
|
||||
return (
|
||||
@@ -831,29 +837,7 @@ export default function OrderDetailPage() {
|
||||
);
|
||||
})()}
|
||||
|
||||
{/* 합계 */}
|
||||
<Card>
|
||||
<CardContent className="pt-6">
|
||||
<div className="flex flex-col items-end gap-2">
|
||||
<div className="flex items-center gap-4 text-sm">
|
||||
<span className="text-muted-foreground">소계:</span>
|
||||
<span className="w-32 text-right">
|
||||
{formatAmount(order.subtotal || 0)}원
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-4 text-sm">
|
||||
<span className="text-muted-foreground">할인율:</span>
|
||||
<span className="w-32 text-right">{Number.isInteger(order.discountRate || 0) ? (order.discountRate || 0) : Math.round(order.discountRate || 0)}%</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-4 text-lg font-semibold border-t pt-2 mt-2">
|
||||
<span>총금액:</span>
|
||||
<span className="w-32 text-right text-green-600">
|
||||
{formatAmount(order.totalAmount || 0)}원
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
{/* 합계 - 제거됨 (소계/할인율/총금액은 수주 상세에서 불필요) */}
|
||||
{/* 절곡 재고 현황 */}
|
||||
{bendingStock.length > 0 && (
|
||||
<Card>
|
||||
@@ -1192,12 +1176,13 @@ export default function OrderDetailPage() {
|
||||
<TableBody>
|
||||
{order.nodes && order.nodes.length > 0 ? (
|
||||
order.nodes.map((node, idx) => {
|
||||
const opts = node.options as Record<string, unknown> || {};
|
||||
const product = order.products?.[idx];
|
||||
const width = (node.options?.width as number) || product?.openWidth;
|
||||
const height = (node.options?.height as number) || product?.openHeight;
|
||||
const productName = product?.productName || node.name || '-';
|
||||
const floor = product?.floor || '-';
|
||||
const code = product?.code || '-';
|
||||
const width = (opts.width as number) || product?.openWidth;
|
||||
const height = (opts.height as number) || product?.openHeight;
|
||||
const productName = (opts.product_name as string) || product?.productName || node.name || '-';
|
||||
const floor = (opts.floor as string) || product?.floor || '-';
|
||||
const code = (opts.symbol as string) || product?.code || '-';
|
||||
return (
|
||||
<TableRow key={node.id}>
|
||||
<TableCell className="text-center text-xs">{idx + 1}</TableCell>
|
||||
@@ -1450,7 +1435,7 @@ export default function OrderDetailPage() {
|
||||
<div className="flex justify-between">
|
||||
<span className="text-muted-foreground">총금액</span>
|
||||
<span className="font-medium text-green-600">
|
||||
{formatAmount(order.totalAmount || 0)}원
|
||||
{formatAmount(order.totalAmount || 0)}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex justify-between items-center">
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
import { useRouter, useSearchParams } from "next/navigation";
|
||||
import { useEffect, useState } from "react";
|
||||
import { OrderRegistration, OrderFormData, createOrder, getQuoteByIdForSelect } from "@/components/orders";
|
||||
import { OrderRegistration, OrderFormData, createOrder, createOrderFromQuote, getQuoteByIdForSelect } from "@/components/orders";
|
||||
import type { QuotationForSelect, QuotationItem } from "@/components/orders/actions";
|
||||
import { toast } from "sonner";
|
||||
import { Loader2 } from "lucide-react";
|
||||
@@ -56,6 +56,30 @@ export default function OrderNewPage() {
|
||||
|
||||
const handleSave = async (formData: OrderFormData) => {
|
||||
try {
|
||||
// quoteId가 있으면 견적→수주 변환 API 호출 (개소별 분리 포함)
|
||||
if (quoteId) {
|
||||
const result = await createOrderFromQuote(Number(quoteId), {
|
||||
deliveryDate: formData.expectedShipDate,
|
||||
memo: formData.remarks,
|
||||
deliveryMethodCode: formData.deliveryMethod,
|
||||
options: {
|
||||
receiver: formData.receiver,
|
||||
receiver_contact: formData.receiverContact,
|
||||
shipping_address: formData.address,
|
||||
shipping_address_detail: formData.addressDetail,
|
||||
shipping_cost_code: formData.shippingCost,
|
||||
},
|
||||
});
|
||||
|
||||
if (result.success) {
|
||||
toast.success("견적에서 수주가 생성되었습니다.");
|
||||
router.push("/sales/order-management-sales");
|
||||
} else {
|
||||
toast.error(result.error || "수주 생성에 실패했습니다.");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const result = await createOrder(formData);
|
||||
|
||||
if (result.success) {
|
||||
|
||||
Reference in New Issue
Block a user