- DB 연결: 로컬/Docker 환경 오버라이딩 설정 (.env) - 테넌트 위젯: redirect 버그 수정 (TenantSelectorWidget) - 통계 위젯: 사용자/제품/자재/주문 카드 추가 (StatsOverviewWidget) - 리소스 한국어화: Product, Material 모델 레이블 추가 - 대시보드: 위젯 등록 및 캐시 최적화 🤖 Generated with [Claude Code](https://claude.ai/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
278 lines
8.1 KiB
PHP
278 lines
8.1 KiB
PHP
<?php
|
|
|
|
namespace App\Services;
|
|
|
|
use App\Services\Service;
|
|
use Shared\Models\Products\ModelParameter;
|
|
use Shared\Models\Products\ModelMaster;
|
|
use Illuminate\Database\Eloquent\Collection;
|
|
use Illuminate\Pagination\LengthAwarePaginator;
|
|
|
|
/**
|
|
* Model Parameter Service
|
|
* 모델 매개변수 관리 서비스
|
|
*/
|
|
class ModelParameterService extends Service
|
|
{
|
|
/**
|
|
* 모델별 매개변수 목록 조회
|
|
*/
|
|
public function getParametersByModel(int $modelId, bool $paginate = false, int $perPage = 15): Collection|LengthAwarePaginator
|
|
{
|
|
$this->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
|
|
]));
|
|
}
|
|
}
|
|
}
|
|
} |