- 데이터베이스 스키마 확장: BOM 테이블에 계산 관련 필드 추가 - 계산 엔진 구현: CalculationEngine, FormulaParser, ParameterValidator - API 구현: 견적 파라미터 추출, 실시간 BOM 계산, 업체별 산출식 관리 - FormRequest 검증: 모든 입력 데이터 검증 및 한국어 에러 메시지 - 라우트 등록: 5개 BOM 계산 API 엔드포인트 추가 주요 기능: • BOM에서 필요한 조건만 동적 추출하여 견적 화면에 표시 • 경동기업 하드코딩 산출식을 동적 시스템으로 전환 • 업체별 산출식 버전 관리 및 실시간 테스트 지원 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
218 lines
7.1 KiB
PHP
218 lines
7.1 KiB
PHP
<?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
|
|
{
|
|
// 삼성물산 특수 규칙 (예시)
|
|
// 실제로는 해당 업체의 요구사항에 따라 구현
|
|
}
|
|
} |