diff --git a/app/Http/Controllers/V1/ProcessController.php b/app/Http/Controllers/V1/ProcessController.php index dec46878..039ab1c7 100644 --- a/app/Http/Controllers/V1/ProcessController.php +++ b/app/Http/Controllers/V1/ProcessController.php @@ -95,6 +95,17 @@ public function toggleActive(int $id): JsonResponse ); } + /** + * 공정 복제 + */ + public function duplicate(int $id): JsonResponse + { + return ApiResponse::handle( + fn () => $this->processService->duplicate($id), + 'message.created' + ); + } + /** * 공정 옵션 목록 (드롭다운용) */ diff --git a/app/Services/ProcessService.php b/app/Services/ProcessService.php index 7eb64995..8865cbe5 100644 --- a/app/Services/ProcessService.php +++ b/app/Services/ProcessService.php @@ -267,6 +267,92 @@ private function syncProcessItems(Process $process, array $itemIds): void } } + /** + * 공정 복제 + */ + public function duplicate(int $id) + { + $tenantId = $this->tenantId(); + $userId = $this->apiUserId(); + + $source = Process::where('tenant_id', $tenantId) + ->with(['classificationRules', 'processItems', 'steps']) + ->find($id); + + if (! $source) { + throw new NotFoundHttpException(__('error.not_found')); + } + + return DB::transaction(function () use ($source, $tenantId, $userId) { + $newCode = $this->generateProcessCode($tenantId); + + $newProcess = Process::create([ + 'tenant_id' => $tenantId, + 'process_code' => $newCode, + 'process_name' => $source->process_name.' (복사)', + 'description' => $source->description, + 'process_type' => $source->process_type, + 'department' => $source->department, + 'manager' => $source->manager, + 'process_category' => $source->process_category, + 'use_production_date' => $source->use_production_date, + 'work_log_template' => $source->work_log_template, + 'document_template_id' => $source->document_template_id, + 'work_log_template_id' => $source->work_log_template_id, + 'options' => $source->options, + 'required_workers' => $source->required_workers, + 'equipment_info' => $source->equipment_info, + 'work_steps' => $source->work_steps, + 'note' => $source->note, + 'is_active' => $source->is_active, + 'created_by' => $userId, + ]); + + // 분류 규칙 복제 + foreach ($source->classificationRules as $rule) { + ProcessClassificationRule::create([ + 'process_id' => $newProcess->id, + 'registration_type' => $rule->registration_type, + 'rule_type' => $rule->rule_type, + 'matching_type' => $rule->matching_type, + 'condition_value' => $rule->condition_value, + 'priority' => $rule->priority, + 'description' => $rule->description, + 'is_active' => $rule->is_active, + ]); + } + + // 품목 연결 복제 + foreach ($source->processItems as $item) { + ProcessItem::create([ + 'process_id' => $newProcess->id, + 'item_id' => $item->item_id, + 'priority' => $item->priority, + 'is_active' => $item->is_active, + ]); + } + + // 공정 단계 복제 + foreach ($source->steps as $step) { + $newProcess->steps()->create([ + 'step_code' => $step->step_code, + 'step_name' => $step->step_name, + 'is_required' => $step->is_required, + 'needs_approval' => $step->needs_approval, + 'needs_inspection' => $step->needs_inspection, + 'is_active' => $step->is_active, + 'sort_order' => $step->sort_order, + 'connection_type' => $step->connection_type, + 'connection_target' => $step->connection_target, + 'completion_type' => $step->completion_type, + 'options' => $step->options, + ]); + } + + return $newProcess->load(['classificationRules', 'processItems.item:id,code,name', 'steps', 'documentTemplate:id,name,category', 'workLogTemplateRelation:id,name,category']); + }); + } + /** * 드롭다운용 공정 옵션 목록 */ diff --git a/routes/api/v1/production.php b/routes/api/v1/production.php index 18c33f16..cba64d32 100644 --- a/routes/api/v1/production.php +++ b/routes/api/v1/production.php @@ -31,6 +31,7 @@ Route::put('/{id}', [ProcessController::class, 'update'])->whereNumber('id')->name('v1.processes.update'); Route::delete('/{id}', [ProcessController::class, 'destroy'])->whereNumber('id')->name('v1.processes.destroy'); Route::patch('/{id}/toggle', [ProcessController::class, 'toggleActive'])->whereNumber('id')->name('v1.processes.toggle'); + Route::post('/{id}/duplicate', [ProcessController::class, 'duplicate'])->whereNumber('id')->name('v1.processes.duplicate'); // Process Steps (공정 단계) Route::prefix('{processId}/steps')->whereNumber('processId')->group(function () {