diff --git a/src/components/process-management/actions.ts b/src/components/process-management/actions.ts index c3698c27..95cdef04 100644 --- a/src/components/process-management/actions.ts +++ b/src/components/process-management/actions.ts @@ -26,6 +26,7 @@ interface ApiProcess { created_at: string; updated_at: string; classification_rules?: ApiClassificationRule[]; + process_items?: ApiProcessItem[]; } interface ApiClassificationRule { @@ -42,6 +43,19 @@ interface ApiClassificationRule { updated_at: string; } +interface ApiProcessItem { + id: number; + process_id: number; + item_id: number; + priority: number; + is_active: boolean; + item?: { + id: number; + code: string; + name: string; + }; +} + interface ApiResponse { success: boolean; message: string; @@ -61,6 +75,12 @@ interface PaginatedResponse { // ============================================================================ function transformApiToFrontend(apiData: ApiProcess): Process { + // Pattern 규칙 변환 + const patternRules = (apiData.classification_rules ?? []).map(transformRuleApiToFrontend); + + // 개별 품목 → individual 분류 규칙으로 변환 + const individualRules = transformProcessItemsToRules(apiData.process_items ?? []); + return { id: String(apiData.id), processCode: apiData.process_code, @@ -69,7 +89,7 @@ function transformApiToFrontend(apiData: ApiProcess): Process { processType: apiData.process_type as Process['processType'], department: apiData.department ?? '', workLogTemplate: apiData.work_log_template ?? undefined, - classificationRules: (apiData.classification_rules ?? []).map(transformRuleApiToFrontend), + classificationRules: [...patternRules, ...individualRules], requiredWorkers: apiData.required_workers, equipmentInfo: apiData.equipment_info ?? undefined, workSteps: apiData.work_steps ?? [], @@ -80,6 +100,34 @@ function transformApiToFrontend(apiData: ApiProcess): Process { }; } +/** + * process_items 배열을 individual 분류 규칙으로 변환 + * 모든 개별 품목을 하나의 규칙으로 통합 + */ +function transformProcessItemsToRules(processItems: ApiProcessItem[]): ClassificationRule[] { + if (processItems.length === 0) return []; + + // 모든 품목 ID를 쉼표로 구분하여 하나의 규칙으로 통합 + const itemIds = processItems + .filter(pi => pi.is_active) + .map(pi => String(pi.item_id)) + .join(','); + + if (!itemIds) return []; + + return [{ + id: `individual-${Date.now()}`, + registrationType: 'individual', + ruleType: '품목코드', + matchingType: 'equals', + conditionValue: itemIds, + priority: 0, + description: `개별 품목 ${processItems.length}개`, + isActive: true, + createdAt: new Date().toISOString(), + }]; +} + function transformRuleApiToFrontend(apiRule: ApiClassificationRule): ClassificationRule { return { id: String(apiRule.id), @@ -95,6 +143,24 @@ function transformRuleApiToFrontend(apiRule: ApiClassificationRule): Classificat } function transformFrontendToApi(data: ProcessFormData): Record { + // 패턴 규칙만 분리 (individual 제외) + const patternRules = data.classificationRules.filter( + (rule) => rule.registrationType === 'pattern' + ); + + // 개별 품목 규칙에서 item_ids 추출 + const individualRules = data.classificationRules.filter( + (rule) => rule.registrationType === 'individual' + ); + + // 개별 품목의 conditionValue에서 ID 배열 추출 (쉼표 구분) + const itemIds: number[] = individualRules.flatMap((rule) => + rule.conditionValue + .split(',') + .map((id) => parseInt(id.trim(), 10)) + .filter((n) => !isNaN(n) && n > 0) + ); + return { process_name: data.processName, process_type: data.processType, @@ -105,8 +171,8 @@ function transformFrontendToApi(data: ProcessFormData): Record work_steps: data.workSteps ? data.workSteps.split(',').map((s) => s.trim()).filter(Boolean) : [], note: data.note || null, is_active: data.isActive, - classification_rules: data.classificationRules.map((rule) => ({ - registration_type: rule.registrationType, + // 패턴 규칙만 전송 (registration_type 제외) + classification_rules: patternRules.map((rule) => ({ rule_type: rule.ruleType, matching_type: rule.matchingType, condition_value: rule.conditionValue, @@ -114,6 +180,8 @@ function transformFrontendToApi(data: ProcessFormData): Record description: rule.description || null, is_active: rule.isActive, })), + // 개별 품목 ID 배열 전송 + item_ids: itemIds, }; } @@ -494,8 +562,8 @@ export async function getDepartmentOptions(): Promise { } const result = await response.json(); - if (result.success && result.data) { - return result.data.map((dept: { id: number; name: string }) => ({ + if (result.success && result.data?.data) { + return result.data.data.map((dept: { id: number; name: string }) => ({ value: dept.name, label: dept.name, })); @@ -552,12 +620,12 @@ export async function getItemList(params?: GetItemListParams): Promise ({ + return result.data.data.map((item: { id: number; name: string; code?: string; item_type?: string }) => ({ value: String(item.id), - label: item.item_name, - code: item.item_code || '', + label: item.name, + code: item.code || '', id: String(item.id), - fullName: item.item_name, + fullName: item.name, type: item.item_type || '', })); }