feat: 수주/견적 기능 개선 및 PDF 생성 업데이트
- 수주 상세 뷰/수정 컴포넌트 개선 - 견적 위치 패널 업데이트 - PDF 생성 API 수정 - 레이아웃 및 공통코드 API 업데이트 - 패키지 의존성 업데이트
This commit is contained in:
@@ -45,6 +45,7 @@ import {
|
||||
updateOrder,
|
||||
type OrderStatus,
|
||||
} from "@/components/orders";
|
||||
import { getDeliveryMethodOptions, getCommonCodeOptions } from "@/lib/api/common-codes";
|
||||
|
||||
// 수정 폼 데이터
|
||||
interface EditFormData {
|
||||
@@ -88,22 +89,11 @@ interface EditFormData {
|
||||
}>;
|
||||
}
|
||||
|
||||
// 배송방식 옵션
|
||||
const DELIVERY_METHODS = [
|
||||
{ value: "direct", label: "직접배차" },
|
||||
{ value: "pickup", label: "상차" },
|
||||
{ value: "courier", label: "택배" },
|
||||
{ value: "self", label: "직접수령" },
|
||||
{ value: "freight", label: "화물" },
|
||||
];
|
||||
|
||||
// 운임비용 옵션
|
||||
const SHIPPING_COSTS = [
|
||||
{ value: "free", label: "무료" },
|
||||
{ value: "prepaid", label: "선불" },
|
||||
{ value: "collect", label: "착불" },
|
||||
{ value: "negotiable", label: "협의" },
|
||||
];
|
||||
// 옵션 타입 정의
|
||||
interface SelectOption {
|
||||
value: string;
|
||||
label: string;
|
||||
}
|
||||
|
||||
|
||||
// 상태 뱃지 헬퍼
|
||||
@@ -141,6 +131,10 @@ export function OrderSalesDetailEdit({ orderId }: OrderSalesDetailEditProps) {
|
||||
const [isSaving, setIsSaving] = useState(false);
|
||||
const [expandedProducts, setExpandedProducts] = useState<Set<string>>(new Set());
|
||||
|
||||
// 공통코드 옵션
|
||||
const [deliveryMethods, setDeliveryMethods] = useState<SelectOption[]>([]);
|
||||
const [shippingCosts, setShippingCosts] = useState<SelectOption[]>([]);
|
||||
|
||||
// 제품-부품 트리 토글
|
||||
const toggleProduct = (key: string) => {
|
||||
setExpandedProducts((prev) => {
|
||||
@@ -265,6 +259,24 @@ export function OrderSalesDetailEdit({ orderId }: OrderSalesDetailEditProps) {
|
||||
loadOrder();
|
||||
}, [orderId, router]);
|
||||
|
||||
// 공통코드 옵션 로드
|
||||
useEffect(() => {
|
||||
async function loadCommonCodes() {
|
||||
const [deliveryResult, shippingResult] = await Promise.all([
|
||||
getDeliveryMethodOptions(),
|
||||
getCommonCodeOptions('shipping_cost'),
|
||||
]);
|
||||
|
||||
if (deliveryResult.success && deliveryResult.data) {
|
||||
setDeliveryMethods(deliveryResult.data);
|
||||
}
|
||||
if (shippingResult.success && shippingResult.data) {
|
||||
setShippingCosts(shippingResult.data);
|
||||
}
|
||||
}
|
||||
loadCommonCodes();
|
||||
}, []);
|
||||
|
||||
const handleCancel = () => {
|
||||
// V2 패턴: ?mode=view로 이동
|
||||
router.push(`/sales/order-management-sales/${orderId}?mode=view`);
|
||||
@@ -453,7 +465,7 @@ export function OrderSalesDetailEdit({ orderId }: OrderSalesDetailEditProps) {
|
||||
<SelectValue placeholder="선택" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{DELIVERY_METHODS.map((method) => (
|
||||
{deliveryMethods.map((method) => (
|
||||
<SelectItem key={method.value} value={method.value}>
|
||||
{method.label}
|
||||
</SelectItem>
|
||||
@@ -476,7 +488,7 @@ export function OrderSalesDetailEdit({ orderId }: OrderSalesDetailEditProps) {
|
||||
<SelectValue placeholder="선택" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{SHIPPING_COSTS.map((cost) => (
|
||||
{shippingCosts.map((cost) => (
|
||||
<SelectItem key={cost.value} value={cost.value}>
|
||||
{cost.label}
|
||||
</SelectItem>
|
||||
|
||||
@@ -354,7 +354,7 @@ export function OrderSalesDetailView({ orderId }: OrderSalesDetailViewProps) {
|
||||
<InfoItem label="출고예정일" value={order.expectedShipDate || "미정"} />
|
||||
<InfoItem label="납품요청일" value={order.deliveryRequestDate} />
|
||||
<InfoItem label="배송방식" value={order.deliveryMethodLabel} />
|
||||
<InfoItem label="운임비용" value={order.shippingCost} />
|
||||
<InfoItem label="운임비용" value={order.shippingCostLabel} />
|
||||
<InfoItem label="수신(반장/업체)" value={order.receiver} />
|
||||
<InfoItem label="수신처 연락처" value={order.receiverContact} />
|
||||
<InfoItem label="수신처 주소" value={order.address} />
|
||||
|
||||
@@ -27,6 +27,7 @@ interface ApiOrder {
|
||||
delivery_date: string | null;
|
||||
delivery_method_code: string | null;
|
||||
delivery_method_label?: string; // API에서 조회한 배송방식 라벨
|
||||
shipping_cost_label?: string; // API에서 조회한 운임비용 라벨
|
||||
received_at: string | null;
|
||||
memo: string | null;
|
||||
remarks: string | null;
|
||||
@@ -231,11 +232,17 @@ export interface Order {
|
||||
remarks?: string;
|
||||
note?: string;
|
||||
items?: OrderItem[];
|
||||
// 목록 페이지용 추가 필드
|
||||
productName?: string; // 제품명 (첫 번째 품목명)
|
||||
receiverAddress?: string; // 수신주소
|
||||
receiverPlace?: string; // 수신처 (전화번호)
|
||||
frameCount?: number; // 틀수 (수량)
|
||||
// 상세 페이지용 추가 필드
|
||||
manager?: string; // 담당자
|
||||
contact?: string; // 연락처 (client_contact)
|
||||
deliveryRequestDate?: string; // 납품요청일
|
||||
shippingCost?: string; // 운임비용
|
||||
shippingCost?: string; // 운임비용 (코드)
|
||||
shippingCostLabel?: string; // 운임비용 (라벨)
|
||||
receiver?: string; // 수신자
|
||||
receiverContact?: string; // 수신처 연락처
|
||||
address?: string; // 수신처 주소
|
||||
@@ -457,12 +464,19 @@ function transformApiToFrontend(apiData: ApiOrder): Order {
|
||||
memo: apiData.memo ?? undefined,
|
||||
remarks: apiData.remarks ?? undefined,
|
||||
note: apiData.note ?? undefined,
|
||||
items: apiData.items?.map(transformItemApiToFrontend) || [], // 상세 페이지용 추가 필드 (API에서 매핑)
|
||||
items: apiData.items?.map(transformItemApiToFrontend) || [],
|
||||
// 목록 페이지용 추가 필드
|
||||
productName: apiData.items?.[0]?.item_name ?? undefined,
|
||||
receiverAddress: apiData.options?.shipping_address ?? undefined,
|
||||
receiverPlace: apiData.options?.receiver_contact ?? undefined,
|
||||
frameCount: apiData.quantity ?? undefined,
|
||||
// 상세 페이지용 추가 필드 (API에서 매핑)
|
||||
manager: apiData.client?.manager_name ?? undefined,
|
||||
contact: apiData.client_contact ?? apiData.client?.phone ?? undefined,
|
||||
deliveryRequestDate: apiData.delivery_date ?? undefined, // delivery_date를 공유
|
||||
// options JSON에서 추출
|
||||
shippingCost: apiData.options?.shipping_cost_code ?? undefined,
|
||||
shippingCostLabel: apiData.shipping_cost_label ?? undefined,
|
||||
receiver: apiData.options?.receiver ?? undefined,
|
||||
receiverContact: apiData.options?.receiver_contact ?? undefined,
|
||||
address: apiData.options?.shipping_address ?? undefined,
|
||||
|
||||
Reference in New Issue
Block a user