diff --git a/src/app/[locale]/(protected)/sales/order-management-sales/[id]/edit/page.tsx b/src/app/[locale]/(protected)/sales/order-management-sales/[id]/edit/page.tsx index 49b6d51e..1f32f7ef 100644 --- a/src/app/[locale]/(protected)/sales/order-management-sales/[id]/edit/page.tsx +++ b/src/app/[locale]/(protected)/sales/order-management-sales/[id]/edit/page.tsx @@ -520,10 +520,10 @@ export default function OrderEditPage() { {formatQuantity(item.quantity, item.unit)} {item.unit} - {formatAmount(item.unitPrice)}원 + {formatAmount(item.unitPrice)} - {formatAmount(item.amount ?? 0)}원 + {formatAmount(item.amount ?? 0)} ))} @@ -536,7 +536,7 @@ export default function OrderEditPage() {
소계: - {formatAmount(form.subtotal)}원 + {formatAmount(form.subtotal)}
@@ -546,7 +546,7 @@ export default function OrderEditPage() {
총금액: - {formatAmount(form.totalAmount)}원 + {formatAmount(form.totalAmount)}
diff --git a/src/app/[locale]/(protected)/sales/order-management-sales/[id]/page.tsx b/src/app/[locale]/(protected)/sales/order-management-sales/[id]/page.tsx index 20cb0639..35c1357f 100644 --- a/src/app/[locale]/(protected)/sales/order-management-sales/[id]/page.tsx +++ b/src/app/[locale]/(protected)/sales/order-management-sales/[id]/page.tsx @@ -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)?.product_name as string || product?.productName || ''; + const nodeFloor = (node.options as Record)?.floor as string || ''; + const nodeSymbol = (node.options as Record)?.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() { ); })()} - {/* 합계 */} - - -
-
- 소계: - - {formatAmount(order.subtotal || 0)}원 - -
-
- 할인율: - {Number.isInteger(order.discountRate || 0) ? (order.discountRate || 0) : Math.round(order.discountRate || 0)}% -
-
- 총금액: - - {formatAmount(order.totalAmount || 0)}원 - -
-
-
-
+ {/* 합계 - 제거됨 (소계/할인율/총금액은 수주 상세에서 불필요) */} {/* 절곡 재고 현황 */} {bendingStock.length > 0 && ( @@ -1192,12 +1176,13 @@ export default function OrderDetailPage() { {order.nodes && order.nodes.length > 0 ? ( order.nodes.map((node, idx) => { + const opts = node.options as Record || {}; 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 ( {idx + 1} @@ -1450,7 +1435,7 @@ export default function OrderDetailPage() {
총금액 - {formatAmount(order.totalAmount || 0)}원 + {formatAmount(order.totalAmount || 0)}
diff --git a/src/app/[locale]/(protected)/sales/order-management-sales/new/page.tsx b/src/app/[locale]/(protected)/sales/order-management-sales/new/page.tsx index 16819074..e36eec92 100644 --- a/src/app/[locale]/(protected)/sales/order-management-sales/new/page.tsx +++ b/src/app/[locale]/(protected)/sales/order-management-sales/new/page.tsx @@ -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) { diff --git a/src/components/orders/OrderRegistration.tsx b/src/components/orders/OrderRegistration.tsx index a9ecbba1..110c74ce 100644 --- a/src/components/orders/OrderRegistration.tsx +++ b/src/components/orders/OrderRegistration.tsx @@ -833,17 +833,17 @@ export function OrderRegistration({ - { + onChange={(value) => { setForm((prev) => ({ ...prev, - receiverContact: e.target.value, + receiverContact: value, })); clearFieldError("receiverContact"); }} - className={cn(fieldErrors.receiverContact && "border-red-500")} + error={!!fieldErrors.receiverContact} /> {fieldErrors.receiverContact && (

{fieldErrors.receiverContact}

diff --git a/src/components/orders/OrderSalesDetailView.tsx b/src/components/orders/OrderSalesDetailView.tsx index ddef99aa..7e434117 100644 --- a/src/components/orders/OrderSalesDetailView.tsx +++ b/src/components/orders/OrderSalesDetailView.tsx @@ -149,7 +149,7 @@ function OrderNodeCard({ node, depth = 0 }: { node: OrderNode; depth?: number }) {statusConfig.label} - {formatAmount(node.totalPrice)}원 + {formatAmount(node.totalPrice)}
@@ -187,10 +187,10 @@ function OrderNodeCard({ node, depth = 0 }: { node: OrderNode; depth?: number }) {item.quantity} {item.unit} - {formatAmount(item.unitPrice)}원 + {formatAmount(item.unitPrice)} - {formatAmount(item.amount ?? 0)}원 + {formatAmount(item.amount ?? 0)}
))} @@ -515,7 +515,7 @@ export function OrderSalesDetailView({ orderId }: OrderSalesDetailViewProps) {
소계: - {formatAmount(order.subtotal ?? 0)}원 + {formatAmount(order.subtotal ?? 0)}
@@ -525,7 +525,7 @@ export function OrderSalesDetailView({ orderId }: OrderSalesDetailViewProps) {
총금액: - {formatAmount(order.totalAmount ?? 0)}원 + {formatAmount(order.totalAmount ?? 0)}
@@ -570,10 +570,10 @@ export function OrderSalesDetailView({ orderId }: OrderSalesDetailViewProps) { {item.quantity} {item.unit} - {formatAmount(item.unitPrice)}원 + {formatAmount(item.unitPrice)} - {formatAmount(item.amount ?? 0)}원 + {formatAmount(item.amount ?? 0)} ))} @@ -586,7 +586,7 @@ export function OrderSalesDetailView({ orderId }: OrderSalesDetailViewProps) {
소계: - {formatAmount(order.subtotal ?? 0)}원 + {formatAmount(order.subtotal ?? 0)}
@@ -596,7 +596,7 @@ export function OrderSalesDetailView({ orderId }: OrderSalesDetailViewProps) {
총금액: - {formatAmount(order.totalAmount ?? 0)}원 + {formatAmount(order.totalAmount ?? 0)}
@@ -783,7 +783,7 @@ export function OrderSalesDetailView({ orderId }: OrderSalesDetailViewProps) {
총금액 - {formatAmount(order.totalAmount ?? 0)}원 + {formatAmount(order.totalAmount ?? 0)}
diff --git a/src/components/orders/QuotationSelectDialog.tsx b/src/components/orders/QuotationSelectDialog.tsx index 17423640..d4c3786f 100644 --- a/src/components/orders/QuotationSelectDialog.tsx +++ b/src/components/orders/QuotationSelectDialog.tsx @@ -100,7 +100,7 @@ export function QuotationSelectDialog({ [{quotation.siteName}] - {formatAmount(quotation.amount)}원 + {formatAmount(quotation.amount)}
diff --git a/src/components/orders/actions.ts b/src/components/orders/actions.ts index d4b79b07..c8064f46 100644 --- a/src/components/orders/actions.ts +++ b/src/components/orders/actions.ts @@ -394,6 +394,14 @@ export interface OrderStats { export interface CreateFromQuoteData { deliveryDate?: string; memo?: string; + deliveryMethodCode?: string; + options?: { + receiver?: string; + receiver_contact?: string; + shipping_address?: string; + shipping_address_detail?: string; + shipping_cost_code?: string; + }; } // 생산지시 생성용 @@ -1010,6 +1018,8 @@ export async function createOrderFromQuote( const apiData: Record = {}; if (data?.deliveryDate) apiData.delivery_date = data.deliveryDate; if (data?.memo) apiData.memo = data.memo; + if (data?.deliveryMethodCode) apiData.delivery_method_code = data.deliveryMethodCode; + if (data?.options) apiData.options = data.options; const result = await executeServerAction({ url: buildApiUrl(`/api/v1/orders/from-quote/${quoteId}`), diff --git a/src/components/orders/index.ts b/src/components/orders/index.ts index 389551ec..bcf76af3 100644 --- a/src/components/orders/index.ts +++ b/src/components/orders/index.ts @@ -7,6 +7,7 @@ export { getOrders, getOrderById, createOrder, + createOrderFromQuote, updateOrder, deleteOrder, deleteOrders,