Files
sam-api/app/Models/Kyungdong/KdPriceTable.php
권혁성 3fce54b7d4 feat: 경동기업 전용 견적 계산 로직 구현 (Phase 4 완료)
- KdPriceTable 모델: 경동기업 단가 테이블 (motor, shaft, pipe, angle, raw_material, bdmodels)
- KyungdongFormulaHandler: 모터 용량, 브라켓 크기, 절곡품(10종), 부자재(3종) 계산
- FormulaEvaluatorService: tenant_id=287 라우팅 추가
- kd_price_tables 마이그레이션 및 시더 (47건 단가 데이터)

테스트 결과: W0=3000, H0=2500 입력 시 16개 항목, 합계 751,200원 정상 계산

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-29 01:10:42 +09:00

342 lines
9.1 KiB
PHP

<?php
namespace App\Models\Kyungdong;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
/**
* 경동기업 전용 단가 테이블 모델
*
* 5130 레거시 price_* 테이블 데이터 조회용
*
* @property int $id
* @property int $tenant_id
* @property string $table_type
* @property string|null $item_code
* @property string|null $item_name
* @property string|null $category
* @property string|null $spec1
* @property string|null $spec2
* @property string|null $spec3
* @property float $unit_price
* @property string $unit
* @property array|null $raw_data
* @property bool $is_active
*/
class KdPriceTable extends Model
{
// 테이블 유형 상수
public const TYPE_MOTOR = 'motor';
public const TYPE_SHAFT = 'shaft';
public const TYPE_PIPE = 'pipe';
public const TYPE_ANGLE = 'angle';
public const TYPE_RAW_MATERIAL = 'raw_material';
public const TYPE_BDMODELS = 'bdmodels';
// 경동기업 테넌트 ID
public const TENANT_ID = 287;
protected $table = 'kd_price_tables';
protected $fillable = [
'tenant_id',
'table_type',
'item_code',
'item_name',
'category',
'spec1',
'spec2',
'spec3',
'unit_price',
'unit',
'raw_data',
'is_active',
];
protected $casts = [
'unit_price' => 'decimal:2',
'raw_data' => 'array',
'is_active' => 'boolean',
];
// =========================================================================
// Scopes
// =========================================================================
/**
* 테이블 유형으로 필터링
*/
public function scopeOfType(Builder $query, string $type): Builder
{
return $query->where('table_type', $type);
}
/**
* 활성 데이터만
*/
public function scopeActive(Builder $query): Builder
{
return $query->where('is_active', true);
}
/**
* 모터 단가 조회
*/
public function scopeMotor(Builder $query): Builder
{
return $query->ofType(self::TYPE_MOTOR)->active();
}
/**
* 샤프트 단가 조회
*/
public function scopeShaft(Builder $query): Builder
{
return $query->ofType(self::TYPE_SHAFT)->active();
}
/**
* 파이프 단가 조회
*/
public function scopePipeType(Builder $query): Builder
{
return $query->ofType(self::TYPE_PIPE)->active();
}
/**
* 앵글 단가 조회
*/
public function scopeAngle(Builder $query): Builder
{
return $query->ofType(self::TYPE_ANGLE)->active();
}
// =========================================================================
// Static Query Methods
// =========================================================================
/**
* 모터 단가 조회
*
* @param string $motorCapacity 모터 용량 (150K, 300K, 400K, 500K, 600K, 800K, 1000K)
*/
public static function getMotorPrice(string $motorCapacity): float
{
$record = self::motor()
->where('category', $motorCapacity)
->first();
return (float) ($record?->unit_price ?? 0);
}
/**
* 제어기 단가 조회
*
* @param string $controllerType 제어기 타입 (매립형, 노출형, 뒷박스)
*/
public static function getControllerPrice(string $controllerType): float
{
$record = self::motor()
->where('category', $controllerType)
->first();
return (float) ($record?->unit_price ?? 0);
}
/**
* 샤프트 단가 조회
*
* @param string $size 사이즈 (3, 4, 5인치)
* @param float $length 길이 (m 단위)
*/
public static function getShaftPrice(string $size, float $length): float
{
// 길이를 소수점 1자리 문자열로 변환 (DB 저장 형식: '3.0', '4.0')
$lengthStr = number_format($length, 1, '.', '');
$record = self::shaft()
->where('spec1', $size)
->where('spec2', $lengthStr)
->first();
return (float) ($record?->unit_price ?? 0);
}
/**
* 파이프 단가 조회
*
* @param string $thickness 두께 (1.4 등)
* @param int $length 길이 (3000, 6000)
*/
public static function getPipePrice(string $thickness, int $length): float
{
$record = self::pipeType()
->where('spec1', $thickness)
->where('spec2', (string) $length)
->first();
return (float) ($record?->unit_price ?? 0);
}
/**
* 앵글 단가 조회
*
* @param string $type 타입 (스크린용, 철재용)
* @param string $bracketSize 브라켓크기 (530*320, 600*350, 690*390)
* @param string $angleType 앵글타입 (앵글3T, 앵글4T)
*/
public static function getAnglePrice(string $type, string $bracketSize, string $angleType): float
{
$record = self::angle()
->where('category', $type)
->where('spec1', $bracketSize)
->where('spec2', $angleType)
->first();
return (float) ($record?->unit_price ?? 0);
}
/**
* 원자재 단가 조회
*
* @param string $materialName 원자재명 (실리카, 스크린 등)
*/
public static function getRawMaterialPrice(string $materialName): float
{
$record = self::ofType(self::TYPE_RAW_MATERIAL)
->active()
->where('item_name', $materialName)
->first();
return (float) ($record?->unit_price ?? 0);
}
// =========================================================================
// BDmodels 단가 조회 (절곡품)
// =========================================================================
/**
* BDmodels 스코프
*/
public function scopeBdmodels(Builder $query): Builder
{
return $query->ofType(self::TYPE_BDMODELS)->active();
}
/**
* BDmodels 단가 조회 (케이스, 가이드레일, 하단마감재 등)
*
* @param string $secondItem 부품분류 (케이스, 가이드레일, 하단마감재, L-BAR 등)
* @param string|null $modelName 모델코드 (KSS01, KWS01 등)
* @param string|null $finishingType 마감재질 (SUS, EGI)
* @param string|null $spec 규격 (120*70, 650*550 등)
*/
public static function getBDModelPrice(
string $secondItem,
?string $modelName = null,
?string $finishingType = null,
?string $spec = null
): float {
$query = self::bdmodels()->where('category', $secondItem);
if ($modelName) {
$query->where('item_code', $modelName);
}
if ($finishingType) {
$query->where('spec1', $finishingType);
}
if ($spec) {
$query->where('spec2', $spec);
}
$record = $query->first();
return (float) ($record?->unit_price ?? 0);
}
/**
* 케이스 단가 조회
*
* @param string $spec 케이스 규격 (500*380, 650*550 등)
*/
public static function getCasePrice(string $spec): float
{
return self::getBDModelPrice('케이스', null, null, $spec);
}
/**
* 가이드레일 단가 조회
*
* @param string $modelName 모델코드 (KSS01 등)
* @param string $finishingType 마감재질 (SUS, EGI)
* @param string $spec 규격 (120*70, 120*100)
*/
public static function getGuideRailPrice(string $modelName, string $finishingType, string $spec): float
{
return self::getBDModelPrice('가이드레일', $modelName, $finishingType, $spec);
}
/**
* 하단마감재(하장바) 단가 조회
*
* @param string $modelName 모델코드
* @param string $finishingType 마감재질
*/
public static function getBottomBarPrice(string $modelName, string $finishingType): float
{
return self::getBDModelPrice('하단마감재', $modelName, $finishingType);
}
/**
* L-BAR 단가 조회
*
* @param string $modelName 모델코드
*/
public static function getLBarPrice(string $modelName): float
{
return self::getBDModelPrice('L-BAR', $modelName);
}
/**
* 보강평철 단가 조회
*/
public static function getFlatBarPrice(): float
{
return self::getBDModelPrice('보강평철');
}
/**
* 케이스 마구리 단가 조회
*
* @param string $spec 규격
*/
public static function getCaseCapPrice(string $spec): float
{
return self::getBDModelPrice('마구리', null, null, $spec);
}
/**
* 케이스용 연기차단재 단가 조회
*/
public static function getCaseSmokeBlockPrice(): float
{
return self::getBDModelPrice('케이스용 연기차단재');
}
/**
* 가이드레일용 연기차단재 단가 조회
*/
public static function getRailSmokeBlockPrice(): float
{
return self::getBDModelPrice('가이드레일용 연기차단재');
}
}