validateModelAccess($modelId); $query = ModelParameter::where('model_id', $modelId) ->active() ->ordered() ->with('model'); if ($paginate) { return $query->paginate($perPage); } return $query->get(); } /** * 매개변수 상세 조회 */ public function getParameter(int $id): ModelParameter { $parameter = ModelParameter::where('tenant_id', $this->tenantId()) ->findOrFail($id); $this->validateModelAccess($parameter->model_id); return $parameter; } /** * 매개변수 생성 */ public function createParameter(array $data): ModelParameter { $this->validateModelAccess($data['model_id']); // 기본값 설정 $data['tenant_id'] = $this->tenantId(); $data['created_by'] = $this->apiUserId(); // 순서가 지정되지 않은 경우 마지막으로 설정 if (!isset($data['order'])) { $maxOrder = ModelParameter::where('tenant_id', $this->tenantId()) ->where('model_id', $data['model_id']) ->max('order') ?? 0; $data['order'] = $maxOrder + 1; } // 매개변수명 중복 체크 $this->validateParameterNameUnique($data['model_id'], $data['name']); // 검증 규칙 처리 if (isset($data['validation_rules']) && is_string($data['validation_rules'])) { $data['validation_rules'] = json_decode($data['validation_rules'], true); } // 옵션 처리 (SELECT 타입) if (isset($data['options']) && is_string($data['options'])) { $data['options'] = json_decode($data['options'], true); } $parameter = ModelParameter::create($data); return $parameter->fresh(); } /** * 매개변수 수정 */ public function updateParameter(int $id, array $data): ModelParameter { $parameter = $this->getParameter($id); // 매개변수명 변경 시 중복 체크 if (isset($data['name']) && $data['name'] !== $parameter->name) { $this->validateParameterNameUnique($parameter->model_id, $data['name'], $id); } // 검증 규칙 처리 if (isset($data['validation_rules']) && is_string($data['validation_rules'])) { $data['validation_rules'] = json_decode($data['validation_rules'], true); } // 옵션 처리 if (isset($data['options']) && is_string($data['options'])) { $data['options'] = json_decode($data['options'], true); } $data['updated_by'] = $this->apiUserId(); $parameter->update($data); return $parameter->fresh(); } /** * 매개변수 삭제 */ public function deleteParameter(int $id): bool { $parameter = $this->getParameter($id); // 다른 공식에서 사용 중인지 확인 $this->validateParameterNotInUse($parameter->model_id, $parameter->name); $parameter->update(['deleted_by' => $this->apiUserId()]); $parameter->delete(); return true; } /** * 매개변수 순서 변경 */ public function reorderParameters(int $modelId, array $orderData): bool { $this->validateModelAccess($modelId); foreach ($orderData as $item) { ModelParameter::where('tenant_id', $this->tenantId()) ->where('model_id', $modelId) ->where('id', $item['id']) ->update([ 'order' => $item['order'], 'updated_by' => $this->apiUserId() ]); } return true; } /** * 매개변수 복사 (다른 모델로) */ public function copyParametersToModel(int $sourceModelId, int $targetModelId): Collection { $this->validateModelAccess($sourceModelId); $this->validateModelAccess($targetModelId); $sourceParameters = $this->getParametersByModel($sourceModelId); $copiedParameters = collect(); foreach ($sourceParameters as $sourceParam) { $data = $sourceParam->toArray(); unset($data['id'], $data['created_at'], $data['updated_at'], $data['deleted_at']); $data['model_id'] = $targetModelId; $data['created_by'] = $this->apiUserId(); // 이름 중복 시 수정 $originalName = $data['name']; $counter = 1; while ($this->isParameterNameExists($targetModelId, $data['name'])) { $data['name'] = $originalName . '_' . $counter; $counter++; } $copiedParameter = ModelParameter::create($data); $copiedParameters->push($copiedParameter); } return $copiedParameters; } /** * 매개변수 값 검증 */ public function validateParameterValues(int $modelId, array $values): array { $this->validateModelAccess($modelId); $parameters = $this->getParametersByModel($modelId); $errors = []; foreach ($parameters as $parameter) { $value = $values[$parameter->name] ?? null; $paramErrors = $parameter->validateValue($value); if (!empty($paramErrors)) { $errors[$parameter->name] = $paramErrors; } } return $errors; } /** * 매개변수 값을 적절한 타입으로 변환 */ public function castParameterValues(int $modelId, array $values): array { $this->validateModelAccess($modelId); $parameters = $this->getParametersByModel($modelId); $castedValues = []; foreach ($parameters as $parameter) { $value = $values[$parameter->name] ?? null; $castedValues[$parameter->name] = $parameter->castValue($value); } return $castedValues; } /** * 모델 접근 권한 검증 */ private function validateModelAccess(int $modelId): void { $model = ModelMaster::where('tenant_id', $this->tenantId()) ->findOrFail($modelId); } /** * 매개변수명 중복 검증 */ private function validateParameterNameUnique(int $modelId, string $name, ?int $excludeId = null): void { $query = ModelParameter::where('tenant_id', $this->tenantId()) ->where('model_id', $modelId) ->where('name', $name); if ($excludeId) { $query->where('id', '!=', $excludeId); } if ($query->exists()) { throw new \InvalidArgumentException(__('error.parameter_name_duplicate')); } } /** * 매개변수명 존재 여부 확인 */ private function isParameterNameExists(int $modelId, string $name): bool { return ModelParameter::where('tenant_id', $this->tenantId()) ->where('model_id', $modelId) ->where('name', $name) ->exists(); } /** * 매개변수가 다른 공식에서 사용 중인지 확인 */ private function validateParameterNotInUse(int $modelId, string $parameterName): void { $formulaService = new ModelFormulaService(); $formulas = $formulaService->getFormulasByModel($modelId); foreach ($formulas as $formula) { if (in_array($parameterName, $formula->dependencies ?? [])) { throw new \InvalidArgumentException(__('error.parameter_in_use_by_formula', [ 'parameter' => $parameterName, 'formula' => $formula->name ])); } } } }