fix: POST /v1/pricing item_type_code 검증 오류 수정

- transformFrontendToApi에서 data.itemType 사용 (FG, PT, SM, RM, CS)
- 잘못된 'PRODUCT'/'MATERIAL' 코드 대신 실제 품목 유형 코드 사용
- create/page.tsx에서 itemTypeCode 파라미터 제거
- PricingListClient.tsx URL에서 itemTypeCode 파라미터 제거
- types.ts에서 itemTypeCode 속성 제거
This commit is contained in:
2025-12-21 01:58:54 +09:00
parent c6b605200d
commit e5bea96182
4 changed files with 15 additions and 15 deletions

View File

@@ -1,8 +1,10 @@
/** /**
* 단가 등록 페이지 * 단가 등록 페이지
* *
* 경로: /sales/pricing-management/create?itemId=xxx&itemTypeCode=MATERIAL|PRODUCT * 경로: /sales/pricing-management/create?itemId=xxx
* API: POST /api/v1/pricing * API: POST /api/v1/pricing
*
* item_type_code는 품목 정보에서 자동으로 가져옴 (FG, PT, SM, RM, CS 등)
*/ */
import { PricingFormClient } from '@/components/pricing'; import { PricingFormClient } from '@/components/pricing';
@@ -13,14 +15,12 @@ interface CreatePricingPageProps {
searchParams: Promise<{ searchParams: Promise<{
itemId?: string; itemId?: string;
itemCode?: string; itemCode?: string;
itemTypeCode?: 'PRODUCT' | 'MATERIAL'; // PRODUCT 또는 MATERIAL (API 등록 시 필요)
}>; }>;
} }
export default async function CreatePricingPage({ searchParams }: CreatePricingPageProps) { export default async function CreatePricingPage({ searchParams }: CreatePricingPageProps) {
const params = await searchParams; const params = await searchParams;
const itemId = params.itemId || ''; const itemId = params.itemId || '';
const itemTypeCode = params.itemTypeCode || 'MATERIAL';
// 품목 정보 조회 // 품목 정보 조회
const itemInfo = itemId ? await getItemInfo(itemId) : null; const itemInfo = itemId ? await getItemInfo(itemId) : null;
@@ -53,10 +53,11 @@ export default async function CreatePricingPage({ searchParams }: CreatePricingP
} }
// 서버 액션: 단가 등록 // 서버 액션: 단가 등록
// item_type_code는 data.itemType에서 자동으로 가져옴
async function handleSave(data: PricingData) { async function handleSave(data: PricingData) {
'use server'; 'use server';
const result = await createPricing(data, itemTypeCode); const result = await createPricing(data);
if (!result.success) { if (!result.success) {
throw new Error(result.error || '단가 등록에 실패했습니다.'); throw new Error(result.error || '단가 등록에 실패했습니다.');

View File

@@ -153,9 +153,8 @@ export function PricingListClient({
// 네비게이션 핸들러 // 네비게이션 핸들러
const handleRegister = (item: PricingListItem) => { const handleRegister = (item: PricingListItem) => {
// itemTypeCode를 URL 파라미터에 포함 (PRODUCT 또는 MATERIAL) // item_type_code는 품목 정보에서 자동으로 가져오므로 URL에 포함하지 않음
const itemTypeCode = item.itemTypeCode || 'MATERIAL'; router.push(`/sales/pricing-management/create?itemId=${item.itemId}&itemCode=${item.itemCode}`);
router.push(`/sales/pricing-management/create?itemId=${item.itemId}&itemCode=${item.itemCode}&itemTypeCode=${itemTypeCode}`);
}; };
const handleEdit = (item: PricingListItem) => { const handleEdit = (item: PricingListItem) => {

View File

@@ -152,10 +152,11 @@ function transformApiToFrontend(apiData: PriceApiData): PricingData {
/** /**
* 프론트엔드 데이터 → API 요청 형식 변환 * 프론트엔드 데이터 → API 요청 형식 변환
* item_type_code는 품목 정보(data.itemType)에서 가져옴 (FG, PT, SM, RM, CS 등)
*/ */
function transformFrontendToApi(data: PricingData, itemTypeCode: 'PRODUCT' | 'MATERIAL' = 'MATERIAL'): Record<string, unknown> { function transformFrontendToApi(data: PricingData): Record<string, unknown> {
return { return {
item_type_code: itemTypeCode, item_type_code: data.itemType, // 품목에서 가져온 실제 item_type 값 사용
item_id: parseInt(data.itemId), item_id: parseInt(data.itemId),
purchase_price: data.purchasePrice || null, purchase_price: data.purchasePrice || null,
processing_cost: data.processingCost || null, processing_cost: data.processingCost || null,
@@ -252,14 +253,14 @@ export async function getItemInfo(itemId: string): Promise<ItemInfo | null> {
/** /**
* 단가 등록 * 단가 등록
* item_type_code는 data.itemType에서 자동으로 가져옴
*/ */
export async function createPricing( export async function createPricing(
data: PricingData, data: PricingData
itemTypeCode: 'PRODUCT' | 'MATERIAL' = 'MATERIAL'
): Promise<{ success: boolean; data?: PricingData; error?: string }> { ): Promise<{ success: boolean; data?: PricingData; error?: string }> {
try { try {
const headers = await getApiHeaders(); const headers = await getApiHeaders();
const apiData = transformFrontendToApi(data, itemTypeCode); const apiData = transformFrontendToApi(data);
console.log('[PricingActions] POST pricing request:', apiData); console.log('[PricingActions] POST pricing request:', apiData);
@@ -308,7 +309,7 @@ export async function updatePricing(
const apiData = { const apiData = {
...transformFrontendToApi(data), ...transformFrontendToApi(data),
change_reason: changeReason || null, change_reason: changeReason || null,
}; } as Record<string, unknown>;
console.log('[PricingActions] PUT pricing request:', apiData); console.log('[PricingActions] PUT pricing request:', apiData);

View File

@@ -111,7 +111,7 @@ export interface PricingListItem {
itemId: string; itemId: string;
itemCode: string; itemCode: string;
itemName: string; itemName: string;
itemType: string; itemType: string; // FG, PT, SM, RM, CS 등 (API 등록 시 item_type_code로 사용)
specification?: string; specification?: string;
unit: string; unit: string;
purchasePrice?: number; purchasePrice?: number;
@@ -122,7 +122,6 @@ export interface PricingListItem {
status: PricingStatus | 'not_registered'; status: PricingStatus | 'not_registered';
currentRevision: number; currentRevision: number;
isFinal: boolean; isFinal: boolean;
itemTypeCode?: 'PRODUCT' | 'MATERIAL'; // API 등록 시 필요 (PRODUCT 또는 MATERIAL)
} }
// ===== 유틸리티 타입 ===== // ===== 유틸리티 타입 =====