Files
sam-api/app/Services/Calculation/ParameterValidator.php

227 lines
7.2 KiB
PHP
Raw Normal View History

<?php
namespace App\Services\Calculation;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\ValidationException;
class ParameterValidator
{
/**
* 파라미터 검증
*
* @param array $schema 파라미터 스키마
* @param array $parameters 검증할 파라미터
*
* @throws ValidationException
*/
public function validate(array $schema, array $parameters): void
{
$rules = $this->buildValidationRules($schema);
$messages = $this->buildValidationMessages($schema);
$validator = Validator::make($parameters, $rules, $messages);
if ($validator->fails()) {
throw new ValidationException($validator);
}
}
/**
* 검증 규칙 생성
*
* @param array $schema 파라미터 스키마
* @return array 라라벨 검증 규칙
*/
protected function buildValidationRules(array $schema): array
{
$rules = [];
if (! isset($schema['required_parameters'])) {
return $rules;
}
foreach ($schema['required_parameters'] as $param) {
$key = $param['key'];
$paramRules = [];
// 필수 여부
if ($param['required'] ?? false) {
$paramRules[] = 'required';
} else {
$paramRules[] = 'nullable';
}
// 데이터 타입
$type = $param['type'] ?? 'string';
switch ($type) {
case 'integer':
$paramRules[] = 'integer';
break;
case 'numeric':
case 'decimal':
$paramRules[] = 'numeric';
break;
case 'boolean':
$paramRules[] = 'boolean';
break;
case 'select':
if (isset($param['options'])) {
$validOptions = is_array($param['options']) ? array_keys($param['options']) : $param['options'];
$paramRules[] = 'in:'.implode(',', $validOptions);
}
break;
default:
$paramRules[] = 'string';
}
// 최소값/최대값
if (isset($param['min'])) {
$paramRules[] = 'min:'.$param['min'];
}
if (isset($param['max'])) {
$paramRules[] = 'max:'.$param['max'];
}
// 정규표현식
if (isset($param['pattern'])) {
$paramRules[] = 'regex:'.$param['pattern'];
}
$rules[$key] = implode('|', $paramRules);
}
return $rules;
}
/**
* 검증 메시지 생성
*
* @param array $schema 파라미터 스키마
* @return array 검증 메시지
*/
protected function buildValidationMessages(array $schema): array
{
$messages = [];
if (! isset($schema['required_parameters'])) {
return $messages;
}
foreach ($schema['required_parameters'] as $param) {
$key = $param['key'];
$label = $param['label'] ?? $key;
$messages["{$key}.required"] = "{$label}은(는) 필수 입력 항목입니다.";
$messages["{$key}.integer"] = "{$label}은(는) 정수여야 합니다.";
$messages["{$key}.numeric"] = "{$label}은(는) 숫자여야 합니다.";
$messages["{$key}.boolean"] = "{$label}은(는) 참/거짓 값이어야 합니다.";
$messages["{$key}.string"] = "{$label}은(는) 문자열이어야 합니다.";
if (isset($param['min'])) {
$messages["{$key}.min"] = "{$label}은(는) 최소 {$param['min']} 이상이어야 합니다.";
}
if (isset($param['max'])) {
$messages["{$key}.max"] = "{$label}은(는) 최대 {$param['max']} 이하여야 합니다.";
}
if (isset($param['options'])) {
$validOptions = is_array($param['options']) ? array_values($param['options']) : $param['options'];
$messages["{$key}.in"] = "{$label}은(는) 다음 중 하나여야 합니다: ".implode(', ', $validOptions);
}
if (isset($param['pattern'])) {
$messages["{$key}.regex"] = "{$label}의 형식이 올바르지 않습니다.";
}
}
return $messages;
}
/**
* 범위 검증
*
* @param array $parameters 파라미터
* @param array $ranges 범위 정의
*/
public function validateRanges(array $parameters, array $ranges): void
{
foreach ($ranges as $key => $range) {
if (! isset($parameters[$key])) {
continue;
}
$value = $parameters[$key];
if (isset($range['min']) && $value < $range['min']) {
throw new ValidationException(validator([], []), [
$key => ["{$key}는 최소 {$range['min']} 이상이어야 합니다."],
]);
}
if (isset($range['max']) && $value > $range['max']) {
throw new ValidationException(validator([], []), [
$key => ["{$key}는 최대 {$range['max']} 이하여야 합니다."],
]);
}
}
}
/**
* 업체별 특수 검증
*
* @param array $parameters 파라미터
* @param string $companyType 업체 타입
*/
public function validateCompanySpecific(array $parameters, string $companyType): void
{
switch ($companyType) {
case '경동기업':
$this->validateKyungdongRules($parameters);
break;
case '삼성물산':
$this->validateSamsungRules($parameters);
break;
default:
// 기본 검증만 수행
break;
}
}
/**
* 경동기업 특수 검증 규칙
*/
protected function validateKyungdongRules(array $parameters): void
{
// 경동기업 특수 규칙 예시
if (isset($parameters['W0']) && isset($parameters['H0'])) {
$area = ($parameters['W0'] * $parameters['H0']) / 1000000;
// 면적이 너무 크면 경고
if ($area > 50) {
throw new ValidationException(validator([], []), [
'area' => ['면적이 50㎡를 초과합니다. 특수 산출식이 필요할 수 있습니다.'],
]);
}
}
// 제품타입별 사이즈 제한
if ($parameters['product_type'] === 'screen' && isset($parameters['W0'])) {
if ($parameters['W0'] > 12000) {
throw new ValidationException(validator([], []), [
'W0' => ['스크린 제품은 가로 12,000mm를 초과할 수 없습니다.'],
]);
}
}
}
/**
* 삼성물산 특수 검증 규칙
*/
protected function validateSamsungRules(array $parameters): void
{
// 삼성물산 특수 규칙 (예시)
// 실제로는 해당 업체의 요구사항에 따라 구현
}
}