Files
sam-api/app/Services/Design/ModelParameterService.php
kent bf8036a64b feat: DB 연결 오버라이딩 및 대시보드 통계 위젯 추가
- DB 연결: 로컬/Docker 환경 오버라이딩 설정 (.env)
- 테넌트 위젯: redirect 버그 수정 (TenantSelectorWidget)
- 통계 위젯: 사용자/제품/자재/주문 카드 추가 (StatsOverviewWidget)
- 리소스 한국어화: Product, Material 모델 레이블 추가
- 대시보드: 위젯 등록 및 캐시 최적화

🤖 Generated with [Claude Code](https://claude.ai/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-30 23:31:14 +09:00

344 lines
11 KiB
PHP

<?php
namespace App\Services\Design;
use App\Models\Design\ModelParameter;
use App\Models\Design\DesignModel;
use App\Services\Service;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
use Illuminate\Support\Facades\DB;
use Illuminate\Validation\ValidationException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
class ModelParameterService extends Service
{
/**
* 모델의 매개변수 목록 조회
*/
public function listByModel(int $modelId, string $q = '', int $page = 1, int $size = 20): LengthAwarePaginator
{
$tenantId = $this->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(),
];
}
}