From 6615f3946600263faf5079a88603b82452d6875a Mon Sep 17 00:00:00 2001 From: kent Date: Fri, 9 Jan 2026 17:25:24 +0900 Subject: [PATCH] =?UTF-8?q?feat(order-management):=20Mock=20=E2=86=92=20AP?= =?UTF-8?q?I=20=EC=97=B0=EB=8F=99=20=EB=B0=8F=20common-codes=20=EC=9C=A0?= =?UTF-8?q?=ED=8B=B8=EB=A6=AC=ED=8B=B0=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - common-codes.ts 신규 생성 (공용 코드 조회 유틸리티) - getCommonCodes(), getCommonCodeOptions() 기본 함수 - getOrderStatusOptions(), getOrderTypeOptions() 등 편의 함수 - order-management/actions.ts Mock 데이터 → 실제 API 연동 - 상태 변환 함수 (Frontend ↔ Backend 매핑) - getOrderList(), getOrderStats(), createOrder(), updateOrder() 등 구현 - lib/api/index.ts에 common-codes 모듈 export 추가 --- .../construction/order-management/actions.ts | 584 ++++++++++-------- src/lib/api/common-codes.ts | 121 ++++ src/lib/api/index.ts | 15 + 3 files changed, 474 insertions(+), 246 deletions(-) create mode 100644 src/lib/api/common-codes.ts diff --git a/src/components/business/construction/order-management/actions.ts b/src/components/business/construction/order-management/actions.ts index d006af86..16173d18 100644 --- a/src/components/business/construction/order-management/actions.ts +++ b/src/components/business/construction/order-management/actions.ts @@ -1,131 +1,189 @@ 'use server'; -import type { Order, OrderStats, OrderType, OrderDetail, OrderDetailFormData } from './types'; -import { MOCK_ORDER_DETAIL } from './types'; -import { format, addDays, subDays, subMonths } from 'date-fns'; +import type { Order, OrderStats, OrderDetail, OrderDetailFormData, OrderStatus, OrderType } from './types'; +import { apiClient, getOrderStatusOptions, getOrderTypeOptions } from '@/lib/api'; + +// ======================================== +// 타입 변환 함수 +// ======================================== /** - * 목업 발주 데이터 생성 (고정 데이터) - * - types.ts의 MOCK 옵션들과 정확히 일치해야 필터가 동작함 - * - Math.random() 제거 → index 기반 deterministic 데이터 + * Backend status_code → Frontend OrderStatus 변환 + * DRAFT → waiting, CONFIRMED → order_complete, IN_PROGRESS → delivery_scheduled, COMPLETED → delivery_complete */ -function generateMockOrders(): Order[] { - // types.ts MOCK_PARTNERS와 일치 - const partners = [ - { id: '1', name: '(주)대한건설' }, - { id: '2', name: '삼성물산' }, - { id: '3', name: '현대건설' }, - { id: '4', name: 'GS건설' }, - { id: '5', name: '대림산업' }, - ]; - - // types.ts MOCK_SITES와 일치 - const sites = [ - '강남 오피스빌딩 신축', - '판교 데이터센터', - '송도 물류센터', - '인천공항 터미널', - '부산항 창고', - ]; - - const names = [ - '철근 HD13', - '철근 HD16', - '철근 HD19', - '철근 HD22', - 'H빔 300x300', - 'H빔 200x200', - '콘크리트 25-21-12', - '레미콘 배합', - ]; - - const items = [ - '철근 HD13', - '철근 HD16', - '철근 HD19', - 'H빔', - '레미콘', - '앵커볼트', - '데크플레이트', - '용접봉', - ]; - - // types.ts MOCK_CONSTRUCTION_PM과 일치 - const constructionPMs = ['홍길동', '김철수', '이영희', '박민수']; - // types.ts MOCK_ORDER_MANAGERS와 일치 - const orderManagers = ['김담당', '이담당', '박담당', '최담당']; - // types.ts MOCK_ORDER_COMPANIES와 일치 - const orderCompanies = ['A건설', 'B철강', 'C자재', 'D산업']; - // types.ts MOCK_WORK_TEAM_LEADERS와 일치 - const workTeamLeaders = ['이반장', '김반장', '박반장', '최반장']; - const orderTypes: OrderType[] = ['steel_bar', 'material', 'outsourcing']; - const statuses: Order['status'][] = ['waiting', 'order_complete', 'delivery_scheduled', 'delivery_complete']; - - const orders: Order[] = []; - // 고정 기준일 (2026-01-06) - const baseDate = new Date(2026, 0, 6); - - for (let i = 0; i < 50; i++) { - // index 기반 deterministic 선택 (랜덤 제거) - const partner = partners[i % partners.length]; - const site = sites[i % sites.length]; - const status = statuses[i % statuses.length]; - const orderType = orderTypes[i % orderTypes.length]; - - // 날짜도 index 기반으로 고정 - const monthOffset = i % 3; // 0, 1, 2개월 전 - const dayOffset = (i * 3) % 30; // 0~29일 분산 - const periodStart = subMonths(addDays(baseDate, -dayOffset), monthOffset); - const periodEnd = addDays(periodStart, 10 + (i % 20)); // 10~29일 기간 - const orderDate = subDays(periodStart, i % 5); - const constructionStartDate = addDays(periodStart, i % 5); - const plannedDelivery = addDays(orderDate, 3 + (i % 14)); - const actualDelivery = status === 'delivery_complete' - ? format(addDays(plannedDelivery, (i % 5) - 2), 'yyyy-MM-dd') - : null; - - orders.push({ - id: `order-${i + 1}`, - contractNumber: `CT-${2026}-${String(i + 1).padStart(4, '0')}`, - partnerId: partner.id, - partnerName: partner.name, - siteName: site, - name: names[i % names.length], - constructionPM: constructionPMs[i % constructionPMs.length], - orderManager: orderManagers[i % orderManagers.length], - orderNumber: `ORD-${2026}-${String(i + 1).padStart(4, '0')}`, - orderCompany: orderCompanies[i % orderCompanies.length], - workTeamLeader: workTeamLeaders[i % workTeamLeaders.length], - constructionStartDate: format(constructionStartDate, 'yyyy-MM-dd'), - orderType, - item: items[i % items.length], - quantity: 10 + (i * 7) % 90, // 10~99 고정 패턴 - orderDate: format(orderDate, 'yyyy-MM-dd'), - plannedDeliveryDate: format(plannedDelivery, 'yyyy-MM-dd'), - actualDeliveryDate: actualDelivery, - status, - periodStart: format(periodStart, 'yyyy-MM-dd'), - periodEnd: format(periodEnd, 'yyyy-MM-dd'), - createdAt: format(subDays(periodStart, i % 10), 'yyyy-MM-dd\'T\'HH:mm:ss'), - updatedAt: format(baseDate, 'yyyy-MM-dd\'T\'HH:mm:ss'), - }); - } - - return orders; +function transformStatus(backendStatus: string | null | undefined): OrderStatus { + const statusMap: Record = { + DRAFT: 'waiting', + CONFIRMED: 'order_complete', + IN_PROGRESS: 'delivery_scheduled', + COMPLETED: 'delivery_complete', + CANCELLED: 'waiting', // 취소는 대기로 표시 + }; + return statusMap[backendStatus?.toUpperCase() || ''] || 'waiting'; } -// 캐시된 목업 데이터 -let cachedOrders: Order[] | null = null; - -function getMockOrders(): Order[] { - if (!cachedOrders) { - cachedOrders = generateMockOrders(); - } - return cachedOrders; +/** + * Frontend OrderStatus → Backend status_code 변환 + */ +function transformToBackendStatus(frontendStatus: OrderStatus): string { + const statusMap: Record = { + waiting: 'DRAFT', + order_complete: 'CONFIRMED', + delivery_scheduled: 'IN_PROGRESS', + delivery_complete: 'COMPLETED', + }; + return statusMap[frontendStatus] || 'DRAFT'; } +/** + * Backend order_type_code → Frontend OrderType 변환 + */ +function transformOrderType(backendType: string | null | undefined): OrderType { + // Backend: ORDER, PURCHASE + // Frontend: steel_bar, material, outsourcing + // 현재 Backend는 ORDER/PURCHASE만 있으므로 options에서 가져오거나 기본값 사용 + const typeMap: Record = { + ORDER: 'steel_bar', + PURCHASE: 'material', + }; + return typeMap[backendType?.toUpperCase() || ''] || 'steel_bar'; +} + +/** + * Frontend OrderType → Backend order_type_code 변환 + */ +function transformToBackendOrderType(frontendType: OrderType): string { + const typeMap: Record = { + steel_bar: 'ORDER', + material: 'PURCHASE', + outsourcing: 'ORDER', + }; + return typeMap[frontendType] || 'ORDER'; +} + +// ======================================== +// API 응답 타입 +// ======================================== + +interface ApiOrder { + id: number; + order_no: string; + client_id: number | null; + client_name: string | null; + client?: { id: number; name: string } | null; + site_name: string | null; + status_code: string; + order_type_code: string; + received_at: string | null; + delivery_date: string | null; + actual_delivery_date: string | null; + total_amount: number | null; + supply_amount: number | null; + tax_amount: number | null; + memo: string | null; + created_at: string; + updated_at: string; + items?: ApiOrderItem[]; + quote?: { id: number; quote_no: string; site_name: string } | null; +} + +interface ApiOrderItem { + id: number; + item_id: number | null; + item_name: string; + specification: string | null; + quantity: number; + unit: string | null; + unit_price: number; + supply_amount: number; + tax_amount: number; + total_amount: number; + sort_order: number; +} + +interface ApiOrderStats { + total: number; + draft: number; + confirmed: number; + in_progress: number; + completed: number; + cancelled: number; + total_amount: number; + confirmed_amount: number; +} + +/** + * API 응답 → Order 타입 변환 + */ +function transformOrder(apiOrder: ApiOrder): Order { + return { + id: String(apiOrder.id), + contractNumber: apiOrder.quote?.quote_no || '', + partnerId: apiOrder.client_id ? String(apiOrder.client_id) : '', + partnerName: apiOrder.client?.name || apiOrder.client_name || '', + siteName: apiOrder.site_name || '', + name: apiOrder.items?.[0]?.item_name || '', + constructionPM: '', // Backend에 없음 - options로 확장 가능 + orderManager: '', // Backend에 없음 - options로 확장 가능 + orderNumber: apiOrder.order_no, + orderCompany: '', // Backend에 없음 - options로 확장 가능 + workTeamLeader: '', // Backend에 없음 - options로 확장 가능 + constructionStartDate: apiOrder.received_at || '', + orderType: transformOrderType(apiOrder.order_type_code), + item: apiOrder.items?.[0]?.item_name || '', + quantity: apiOrder.items?.[0]?.quantity || 0, + orderDate: apiOrder.received_at || '', + plannedDeliveryDate: apiOrder.delivery_date || '', + actualDeliveryDate: apiOrder.actual_delivery_date || null, + status: transformStatus(apiOrder.status_code), + periodStart: apiOrder.received_at || '', + periodEnd: apiOrder.delivery_date || '', + createdAt: apiOrder.created_at, + updatedAt: apiOrder.updated_at, + }; +} + +/** + * API 응답 → OrderDetail 타입 변환 + */ +function transformOrderDetail(apiOrder: ApiOrder): OrderDetail { + const baseOrder = transformOrder(apiOrder); + + return { + ...baseOrder, + orderCompanyId: '', // Backend에 없음 + deliveryLocationType: 'site', + deliveryAddress: '', // Backend에 없음 + deliveryMemo: apiOrder.memo || '', + totalAmount: apiOrder.total_amount || 0, + supplyAmount: apiOrder.supply_amount || 0, + taxAmount: apiOrder.tax_amount || 0, + categories: [], // Backend 구조와 다름 - items를 카테고리로 그룹화 필요 + }; +} + +/** + * OrderDetailFormData → API 요청 데이터 변환 + */ +function transformOrderToApi(data: OrderDetailFormData): Record { + return { + client_id: data.partnerId ? parseInt(data.partnerId, 10) : null, + site_name: data.siteName, + status_code: transformToBackendStatus(data.status), + order_type_code: transformToBackendOrderType(data.orderType), + delivery_date: data.deliveryAddress ? undefined : undefined, // 필드 매핑 필요 + memo: data.deliveryMemo, + // items 변환은 별도 처리 필요 + }; +} + +// ======================================== +// API 함수 +// ======================================== + /** * 발주 목록 조회 + * GET /api/v1/orders */ export async function getOrderList(params?: { size?: number; @@ -141,61 +199,67 @@ export async function getOrderList(params?: { error?: string; }> { try { - // 목업 데이터 - let orders = getMockOrders(); + const queryParams: Record = {}; - // 날짜 필터 - if (params?.startDate && params?.endDate) { - orders = orders.filter((order) => { - return order.periodStart >= params.startDate! && order.periodEnd <= params.endDate!; - }); - } + // 페이지네이션 + if (params?.page) queryParams.page = String(params.page); + if (params?.size) queryParams.size = String(params.size); - // 상태 필터 + // 검색 + if (params?.search) queryParams.q = params.search; + + // 상태 필터 (Frontend → Backend 변환) if (params?.status && params.status !== 'all') { - orders = orders.filter((order) => order.status === params.status); + queryParams.status = transformToBackendStatus(params.status as OrderStatus); } // 거래처 필터 if (params?.partnerId && params.partnerId !== 'all') { - orders = orders.filter((order) => order.partnerId === params.partnerId); + queryParams.client_id = params.partnerId; } - // 검색 - if (params?.search) { - const search = params.search.toLowerCase(); - orders = orders.filter( - (order) => - order.orderNumber.toLowerCase().includes(search) || - order.partnerName.toLowerCase().includes(search) || - order.siteName.toLowerCase().includes(search) || - order.orderManager.toLowerCase().includes(search) - ); + // 날짜 범위 필터 + if (params?.startDate) { + queryParams.date_from = params.startDate; + } + if (params?.endDate) { + queryParams.date_to = params.endDate; } - // 페이지네이션 - const page = params?.page || 1; - const size = params?.size || 1000; - const start = (page - 1) * size; - const paginatedOrders = orders.slice(start, start + size); + const response = await apiClient.get<{ + data: ApiOrder[]; + meta?: { total: number; current_page: number; per_page: number }; + total?: number; + current_page?: number; + per_page?: number; + }>('/orders', { params: queryParams }); + + // API 응답 구조 처리 + const orders = Array.isArray(response.data) ? response.data : (response.data as unknown as ApiOrder[]); + const meta = response.meta || { + total: response.total || orders.length, + current_page: response.current_page || params?.page || 1, + per_page: response.per_page || params?.size || 20, + }; + + const transformedOrders = orders.map(transformOrder); return { success: true, data: { - items: paginatedOrders, - total: orders.length, + items: transformedOrders, + total: meta.total, }, }; - } catch { - return { - success: false, - error: '발주 목록 조회에 실패했습니다.', - }; + } catch (error) { + console.error('발주 목록 조회 오류:', error); + return { success: false, error: '발주 목록을 불러오는데 실패했습니다.' }; } } /** * 발주 통계 조회 + * GET /api/v1/orders/stats */ export async function getOrderStats(): Promise<{ success: boolean; @@ -203,52 +267,44 @@ export async function getOrderStats(): Promise<{ error?: string; }> { try { - const orders = getMockOrders(); - - const stats: OrderStats = { - total: orders.length, - waiting: orders.filter((o) => o.status === 'waiting').length, - orderComplete: orders.filter((o) => o.status === 'order_complete').length, - deliveryScheduled: orders.filter((o) => o.status === 'delivery_scheduled').length, - deliveryComplete: orders.filter((o) => o.status === 'delivery_complete').length, - }; + const response = await apiClient.get('/orders/stats'); return { success: true, - data: stats, - }; - } catch { - return { - success: false, - error: '발주 통계 조회에 실패했습니다.', + data: { + total: response.total, + waiting: response.draft, + orderComplete: response.confirmed, + deliveryScheduled: response.in_progress, + deliveryComplete: response.completed, + }, }; + } catch (error) { + console.error('발주 통계 조회 오류:', error); + return { success: false, error: '발주 통계를 불러오는데 실패했습니다.' }; } } /** * 발주 삭제 + * DELETE /api/v1/orders/{id} */ export async function deleteOrder(id: string): Promise<{ success: boolean; error?: string; }> { try { - // 목업: 실제로는 API 호출 - if (cachedOrders) { - cachedOrders = cachedOrders.filter((o) => o.id !== id); - } - + await apiClient.delete(`/orders/${id}`); return { success: true }; - } catch { - return { - success: false, - error: '발주 삭제에 실패했습니다.', - }; + } catch (error) { + console.error('발주 삭제 오류:', error); + return { success: false, error: '발주 삭제에 실패했습니다.' }; } } /** * 발주 일괄 삭제 + * Backend에 batch API가 없으므로 개별 삭제 반복 */ export async function deleteOrders(ids: string[]): Promise<{ success: boolean; @@ -256,32 +312,28 @@ export async function deleteOrders(ids: string[]): Promise<{ error?: string; }> { try { - // 목업: 실제로는 API 호출 - if (cachedOrders) { - const beforeCount = cachedOrders.length; - cachedOrders = cachedOrders.filter((o) => !ids.includes(o.id)); - const deletedCount = beforeCount - cachedOrders.length; + let deletedCount = 0; - return { - success: true, - deletedCount, - }; + for (const id of ids) { + try { + await apiClient.delete(`/orders/${id}`); + deletedCount++; + } catch { + // 개별 삭제 실패는 무시하고 계속 진행 + console.warn(`발주 삭제 실패: ${id}`); + } } - return { - success: true, - deletedCount: ids.length, - }; - } catch { - return { - success: false, - error: '발주 일괄 삭제에 실패했습니다.', - }; + return { success: true, deletedCount }; + } catch (error) { + console.error('발주 일괄 삭제 오류:', error); + return { success: false, error: '발주 일괄 삭제에 실패했습니다.' }; } } /** * 발주 상세 조회 + * GET /api/v1/orders/{id} */ export async function getOrderDetail(id: string): Promise<{ success: boolean; @@ -289,30 +341,17 @@ export async function getOrderDetail(id: string): Promise<{ error?: string; }> { try { - const orders = getMockOrders(); - const order = orders.find((o) => o.id === id); - - if (!order) { - return { - success: false, - error: '발주를 찾을 수 없습니다.', - }; - } - - return { - success: true, - data: order, - }; - } catch { - return { - success: false, - error: '발주 상세 조회에 실패했습니다.', - }; + const response = await apiClient.get(`/orders/${id}`); + return { success: true, data: transformOrder(response) }; + } catch (error) { + console.error('발주 상세 조회 오류:', error); + return { success: false, error: '발주를 찾을 수 없습니다.' }; } } /** * 발주 상세 조회 (전체 정보) + * GET /api/v1/orders/{id} */ export async function getOrderDetailFull(id: string): Promise<{ success: boolean; @@ -320,27 +359,17 @@ export async function getOrderDetailFull(id: string): Promise<{ error?: string; }> { try { - // 목업: 실제로는 API 호출 - // 임시로 MOCK_ORDER_DETAIL 반환 - const mockDetail: OrderDetail = { - ...MOCK_ORDER_DETAIL, - id, - }; - - return { - success: true, - data: mockDetail, - }; - } catch { - return { - success: false, - error: '발주 상세 조회에 실패했습니다.', - }; + const response = await apiClient.get(`/orders/${id}`); + return { success: true, data: transformOrderDetail(response) }; + } catch (error) { + console.error('발주 상세 조회 오류:', error); + return { success: false, error: '발주 상세 조회에 실패했습니다.' }; } } /** * 발주 수정 + * PUT /api/v1/orders/{id} */ export async function updateOrder( id: string, @@ -350,20 +379,18 @@ export async function updateOrder( error?: string; }> { try { - // 목업: 실제로는 API 호출 - console.log('Updating order:', id, data); - + const apiData = transformOrderToApi(data); + await apiClient.put(`/orders/${id}`, apiData); return { success: true }; - } catch { - return { - success: false, - error: '발주 수정에 실패했습니다.', - }; + } catch (error) { + console.error('발주 수정 오류:', error); + return { success: false, error: '발주 수정에 실패했습니다.' }; } } /** * 발주 복제 + * 기존 발주를 조회 후 새로 생성 */ export async function duplicateOrder(id: string): Promise<{ success: boolean; @@ -371,18 +398,83 @@ export async function duplicateOrder(id: string): Promise<{ error?: string; }> { try { - // 목업: 실제로는 API 호출 - const newId = `order-${Date.now()}`; - console.log('Duplicating order:', id, '-> new id:', newId); + // 1. 기존 발주 조회 + const existingOrder = await apiClient.get(`/orders/${id}`); + + // 2. 새 발주 생성 (order_no는 자동 생성됨) + const newOrderData = { + client_id: existingOrder.client_id, + site_name: existingOrder.site_name, + status_code: 'DRAFT', // 복제된 발주는 항상 임시저장 + order_type_code: existingOrder.order_type_code, + delivery_date: existingOrder.delivery_date, + memo: existingOrder.memo ? `[복제] ${existingOrder.memo}` : '[복제됨]', + items: existingOrder.items?.map((item) => ({ + item_id: item.item_id, + item_name: item.item_name, + specification: item.specification, + quantity: item.quantity, + unit: item.unit, + unit_price: item.unit_price, + })), + }; + + const response = await apiClient.post<{ id: number }>('/orders', newOrderData); return { success: true, - newId, - }; - } catch { - return { - success: false, - error: '발주 복제에 실패했습니다.', + newId: String(response.id), }; + } catch (error) { + console.error('발주 복제 오류:', error); + return { success: false, error: '발주 복제에 실패했습니다.' }; } -} \ No newline at end of file +} + +/** + * 발주 생성 + * POST /api/v1/orders + */ +export async function createOrder(data: OrderDetailFormData): Promise<{ + success: boolean; + data?: { id: string }; + error?: string; +}> { + try { + const apiData = transformOrderToApi(data); + const response = await apiClient.post<{ id: number }>('/orders', apiData); + + return { success: true, data: { id: String(response.id) } }; + } catch (error) { + console.error('발주 생성 오류:', error); + return { success: false, error: '발주 생성에 실패했습니다.' }; + } +} + +/** + * 발주 상태 변경 + * PATCH /api/v1/orders/{id}/status + */ +export async function updateOrderStatus( + id: string, + status: OrderStatus +): Promise<{ + success: boolean; + error?: string; +}> { + try { + await apiClient.patch(`/orders/${id}/status`, { + status: transformToBackendStatus(status), + }); + return { success: true }; + } catch (error) { + console.error('발주 상태 변경 오류:', error); + return { success: false, error: '발주 상태 변경에 실패했습니다.' }; + } +} + +// ======================================== +// 공통 코드 조회 (재사용) +// ======================================== + +export { getOrderStatusOptions, getOrderTypeOptions }; \ No newline at end of file diff --git a/src/lib/api/common-codes.ts b/src/lib/api/common-codes.ts new file mode 100644 index 00000000..bc3ab97e --- /dev/null +++ b/src/lib/api/common-codes.ts @@ -0,0 +1,121 @@ +'use server'; + +import { apiClient } from './index'; + +// ======================================== +// 공통 코드 타입 +// ======================================== + +export interface CommonCode { + id: number; + code: string; + name: string; + description: string | null; + sort_order: number; + attributes: Record | null; +} + +// ======================================== +// 공통 코드 조회 함수 +// ======================================== + +/** + * 특정 그룹의 공통 코드 목록 조회 + * GET /api/v1/settings/common/{group} + */ +export async function getCommonCodes(group: string): Promise<{ + success: boolean; + data?: CommonCode[]; + error?: string; +}> { + try { + const response = await apiClient.get(`/settings/common/${group}`); + return { success: true, data: response }; + } catch (error) { + console.error(`공통코드 조회 오류 (${group}):`, error); + return { success: false, error: '공통코드를 불러오는데 실패했습니다.' }; + } +} + +/** + * 공통 코드 옵션 형태로 변환 + * Select/ComboBox 등에서 사용 + */ +export async function getCommonCodeOptions(group: string): Promise<{ + success: boolean; + data?: { value: string; label: string }[]; + error?: string; +}> { + const result = await getCommonCodes(group); + + if (!result.success || !result.data) { + return { success: false, error: result.error }; + } + + const options = result.data.map((code) => ({ + value: code.code, + label: code.name, + })); + + return { success: true, data: options }; +} + +// ======================================== +// 자주 사용하는 코드 그룹 함수 +// ======================================== + +/** + * 수주 상태 코드 조회 + */ +export async function getOrderStatusCodes() { + return getCommonCodes('order_status'); +} + +/** + * 수주 상태 옵션 조회 + */ +export async function getOrderStatusOptions() { + return getCommonCodeOptions('order_status'); +} + +/** + * 수주 유형 코드 조회 + */ +export async function getOrderTypeCodes() { + return getCommonCodes('order_type'); +} + +/** + * 수주 유형 옵션 조회 + */ +export async function getOrderTypeOptions() { + return getCommonCodeOptions('order_type'); +} + +/** + * 거래처 유형 코드 조회 + */ +export async function getClientTypeCodes() { + return getCommonCodes('client_type'); +} + +/** + * 거래처 유형 옵션 조회 + */ +export async function getClientTypeOptions() { + return getCommonCodeOptions('client_type'); +} + +/** + * 품목 유형 코드 조회 + */ +export async function getItemTypeCodes() { + return getCommonCodes('item_type'); +} + +/** + * 품목 유형 옵션 조회 + */ +export async function getItemTypeOptions() { + return getCommonCodeOptions('item_type'); +} \ No newline at end of file diff --git a/src/lib/api/index.ts b/src/lib/api/index.ts index d751411e..c031012b 100644 --- a/src/lib/api/index.ts +++ b/src/lib/api/index.ts @@ -5,6 +5,21 @@ export { ApiClient, withTokenRefresh } from './client'; export { serverFetch } from './fetch-wrapper'; export { AUTH_CONFIG } from './auth/auth-config'; +// 공통 코드 유틸리티 +export { + getCommonCodes, + getCommonCodeOptions, + getOrderStatusCodes, + getOrderStatusOptions, + getOrderTypeCodes, + getOrderTypeOptions, + getClientTypeCodes, + getClientTypeOptions, + getItemTypeCodes, + getItemTypeOptions, + type CommonCode, +} from './common-codes'; + // Server-side API 클라이언트 인스턴스 // 서버 액션에서 사용 import { ApiClient } from './client';