tenantId(); // 모델 존재 확인 $model = DesignModel::where('tenant_id', $tenantId)->where('id', $modelId)->first(); if (!$model) { throw new NotFoundHttpException(__('error.not_found')); } $query = ModelParameter::query() ->where('tenant_id', $tenantId) ->where('model_id', $modelId); if ($q !== '') { $query->where(function ($w) use ($q) { $w->where('parameter_name', 'like', "%{$q}%") ->orWhere('description', 'like', "%{$q}%"); }); } return $query->orderBy('sort_order')->orderBy('id')->paginate($size, ['*'], 'page', $page); } /** * 매개변수 조회 */ public function show(int $parameterId): ModelParameter { $tenantId = $this->tenantId(); $parameter = ModelParameter::where('tenant_id', $tenantId)->where('id', $parameterId)->first(); if (!$parameter) { throw new NotFoundHttpException(__('error.not_found')); } return $parameter; } /** * 매개변수 생성 */ public function create(array $data): ModelParameter { $tenantId = $this->tenantId(); $userId = $this->apiUserId(); // 모델 존재 확인 $model = DesignModel::where('tenant_id', $tenantId)->where('id', $data['model_id'])->first(); if (!$model) { throw new NotFoundHttpException(__('error.not_found')); } // 같은 모델 내에서 매개변수명 중복 체크 $exists = ModelParameter::query() ->where('tenant_id', $tenantId) ->where('model_id', $data['model_id']) ->where('parameter_name', $data['parameter_name']) ->exists(); if ($exists) { throw ValidationException::withMessages(['parameter_name' => __('error.duplicate')]); } return DB::transaction(function () use ($tenantId, $userId, $data) { // sort_order가 없으면 자동 설정 if (!isset($data['sort_order'])) { $maxOrder = ModelParameter::where('tenant_id', $tenantId) ->where('model_id', $data['model_id']) ->max('sort_order') ?? 0; $data['sort_order'] = $maxOrder + 1; } $payload = array_merge($data, [ 'tenant_id' => $tenantId, 'created_by' => $userId, 'updated_by' => $userId, ]); return ModelParameter::create($payload); }); } /** * 매개변수 수정 */ public function update(int $parameterId, array $data): ModelParameter { $tenantId = $this->tenantId(); $userId = $this->apiUserId(); $parameter = ModelParameter::where('tenant_id', $tenantId)->where('id', $parameterId)->first(); if (!$parameter) { throw new NotFoundHttpException(__('error.not_found')); } // 매개변수명 변경 시 중복 체크 if (isset($data['parameter_name']) && $data['parameter_name'] !== $parameter->parameter_name) { $exists = ModelParameter::query() ->where('tenant_id', $tenantId) ->where('model_id', $parameter->model_id) ->where('parameter_name', $data['parameter_name']) ->where('id', '!=', $parameterId) ->exists(); if ($exists) { throw ValidationException::withMessages(['parameter_name' => __('error.duplicate')]); } } return DB::transaction(function () use ($parameter, $userId, $data) { $payload = array_merge($data, ['updated_by' => $userId]); $parameter->update($payload); return $parameter->fresh(); }); } /** * 매개변수 삭제 */ public function delete(int $parameterId): bool { $tenantId = $this->tenantId(); $userId = $this->apiUserId(); $parameter = ModelParameter::where('tenant_id', $tenantId)->where('id', $parameterId)->first(); if (!$parameter) { throw new NotFoundHttpException(__('error.not_found')); } return DB::transaction(function () use ($parameter, $userId) { $parameter->update(['deleted_by' => $userId]); return $parameter->delete(); }); } /** * 매개변수 순서 변경 */ public function reorder(int $modelId, array $parameterIds): array { $tenantId = $this->tenantId(); $userId = $this->apiUserId(); // 모델 존재 확인 $model = DesignModel::where('tenant_id', $tenantId)->where('id', $modelId)->first(); if (!$model) { throw new NotFoundHttpException(__('error.not_found')); } return DB::transaction(function () use ($tenantId, $userId, $modelId, $parameterIds) { $order = 1; $updated = []; foreach ($parameterIds as $parameterId) { $parameter = ModelParameter::query() ->where('tenant_id', $tenantId) ->where('model_id', $modelId) ->where('id', $parameterId) ->first(); if ($parameter) { $parameter->update([ 'sort_order' => $order, 'updated_by' => $userId, ]); $updated[] = $parameter->fresh(); $order++; } } return $updated; }); } /** * 매개변수 대량 저장 (upsert) */ public function bulkUpsert(int $modelId, array $parameters): array { $tenantId = $this->tenantId(); $userId = $this->apiUserId(); // 모델 존재 확인 $model = DesignModel::where('tenant_id', $tenantId)->where('id', $modelId)->first(); if (!$model) { throw new NotFoundHttpException(__('error.not_found')); } return DB::transaction(function () use ($tenantId, $userId, $modelId, $parameters) { $result = []; foreach ($parameters as $index => $paramData) { $paramData['model_id'] = $modelId; // ID가 있으면 업데이트, 없으면 생성 if (isset($paramData['id']) && $paramData['id']) { $parameter = ModelParameter::query() ->where('tenant_id', $tenantId) ->where('model_id', $modelId) ->where('id', $paramData['id']) ->first(); if ($parameter) { $parameter->update(array_merge($paramData, ['updated_by' => $userId])); $result[] = $parameter->fresh(); } } else { // 새로운 매개변수 생성 $exists = ModelParameter::query() ->where('tenant_id', $tenantId) ->where('model_id', $modelId) ->where('parameter_name', $paramData['parameter_name']) ->exists(); if (!$exists) { if (!isset($paramData['sort_order'])) { $paramData['sort_order'] = $index + 1; } $payload = array_merge($paramData, [ 'tenant_id' => $tenantId, 'created_by' => $userId, 'updated_by' => $userId, ]); $result[] = ModelParameter::create($payload); } } } return $result; }); } /** * 매개변수 값 검증 */ public function validateParameters(int $modelId, array $values): array { $tenantId = $this->tenantId(); // 모델의 모든 매개변수 조회 $parameters = ModelParameter::query() ->where('tenant_id', $tenantId) ->where('model_id', $modelId) ->orderBy('sort_order') ->get(); $errors = []; $validated = []; foreach ($parameters as $parameter) { $paramName = $parameter->parameter_name; $value = $values[$paramName] ?? null; // 필수 매개변수 체크 if ($parameter->is_required && ($value === null || $value === '')) { $errors[$paramName] = __('error.required'); continue; } // 값이 없고 필수가 아니면 기본값 사용 if ($value === null || $value === '') { $validated[$paramName] = $parameter->default_value; continue; } // 타입별 검증 if (!$parameter->validateValue($value)) { $errors[$paramName] = __('error.invalid_value'); continue; } // 형변환 후 저장 $validated[$paramName] = $parameter->castValue($value); } if (!empty($errors)) { throw ValidationException::withMessages($errors); } return $validated; } /** * 모델의 매개변수 스키마 조회 (API용) */ public function getParameterSchema(int $modelId): array { $tenantId = $this->tenantId(); // 모델 존재 확인 $model = DesignModel::where('tenant_id', $tenantId)->where('id', $modelId)->first(); if (!$model) { throw new NotFoundHttpException(__('error.not_found')); } $parameters = ModelParameter::query() ->where('tenant_id', $tenantId) ->where('model_id', $modelId) ->orderBy('sort_order') ->get(); return [ 'model' => [ 'id' => $model->id, 'code' => $model->code, 'name' => $model->name, ], 'parameters' => $parameters->map(function ($param) { return [ 'name' => $param->parameter_name, 'type' => $param->parameter_type, 'required' => $param->is_required, 'default' => $param->default_value, 'min' => $param->min_value, 'max' => $param->max_value, 'unit' => $param->unit, 'options' => $param->options, 'description' => $param->description, ]; })->toArray(), ]; } }