- Phase 3 구현 문서 작성 (README, implementation, table-mapping) - PROGRESS.md 업데이트 (Phase 3 완료 상태) - getItemPrice() 연동, Price 모델 생성 기록
5.3 KiB
5.3 KiB
Phase 3 구현 상세
구현일: 2025-12-19 상태: ✅ 완료
1. Price 모델 구현
파일 위치
mng/app/Models/Price.php
주요 기능
상수 정의
// 상태
const STATUS_DRAFT = 'draft';
const STATUS_ACTIVE = 'active';
const STATUS_INACTIVE = 'inactive';
const STATUS_FINALIZED = 'finalized';
// 품목 유형
const ITEM_TYPE_PRODUCT = 'PRODUCT';
const ITEM_TYPE_MATERIAL = 'MATERIAL';
// 반올림 규칙
const ROUNDING_ROUND = 'round';
const ROUNDING_CEIL = 'ceil';
const ROUNDING_FLOOR = 'floor';
getCurrentPrice() 메서드
/**
* 특정 품목의 현재 유효 단가 조회
*
* @param int $tenantId 테넌트 ID
* @param string $itemTypeCode 품목 유형 (PRODUCT/MATERIAL)
* @param int $itemId 품목 ID
* @param int|null $clientGroupId 고객 그룹 ID (NULL = 기본가)
* @return Price|null
*/
public static function getCurrentPrice(
int $tenantId,
string $itemTypeCode,
int $itemId,
?int $clientGroupId = null
): ?self
조회 조건:
- tenant_id 일치
- item_type_code 일치 (PRODUCT/MATERIAL)
- item_id 일치
- client_group_id 일치 또는 NULL (기본가)
- status = 'active'
- effective_from <= 현재일
- effective_to >= 현재일 또는 NULL
우선순위:
- 고객그룹 지정된 가격 > 기본가
- 최신 effective_from 우선
getSalesPriceByItemCode() 메서드
/**
* 품목 코드로 현재 유효 판매단가 조회
* (quote_formula_items.item_code와 연동용)
*
* @param int $tenantId 테넌트 ID
* @param string $itemCode 품목 코드
* @return float 판매단가 (없으면 0)
*/
public static function getSalesPriceByItemCode(int $tenantId, string $itemCode): float
조회 순서:
- products 테이블에서 code로 검색
- 발견되면 → Price::getCurrentPrice() 호출
- 미발견시 → materials 테이블에서 검색
- 발견되면 → Price::getCurrentPrice() 호출
- 미발견시 → 0 반환
2. getItemPrice() 연동
파일 위치
mng/app/Services/Quote/FormulaEvaluatorService.php:324-335
변경 전 (TODO 상태)
private function getItemPrice(string $itemCode): float
{
// TODO: 품목 마스터에서 단가 조회
return 0;
}
변경 후 (구현 완료)
private function getItemPrice(string $itemCode): float
{
$tenantId = session('selected_tenant_id');
if (!$tenantId) {
$this->errors[] = "테넌트 ID가 설정되지 않았습니다.";
return 0;
}
return \App\Models\Price::getSalesPriceByItemCode($tenantId, $itemCode);
}
동작 흐름
quote_formula_items.item_code
↓
FormulaEvaluatorService::getItemPrice()
↓
Price::getSalesPriceByItemCode()
├── products 테이블 검색 (code 컬럼)
└── materials 테이블 검색 (code 컬럼)
↓
Price::getCurrentPrice()
↓
prices.sales_price 반환
3. Seeder 현황
기존 Seeder 파일
| 파일 | 설명 | 데이터 수 |
|---|---|---|
QuoteFormulaCategorySeeder.php |
카테고리 | 11개 |
QuoteFormulaSeeder.php |
수식 | ~30개 |
QuoteFormulaItemSeeder.php |
품목 출력 | 미정 |
QuoteFormulaMappingSeeder.php |
매핑 | 미정 |
카테고리 목록 (11개)
| 코드 | 이름 | 순서 |
|---|---|---|
| OPEN_SIZE | 오픈사이즈 | 1 |
| MAKE_SIZE | 제작사이즈 | 2 |
| AREA | 면적 | 3 |
| WEIGHT | 중량 | 4 |
| GUIDE_RAIL | 가이드레일 | 5 |
| CASE | 케이스 | 6 |
| MOTOR | 모터 | 7 |
| CONTROLLER | 제어기 | 8 |
| EDGE_WING | 마구리 | 9 |
| INSPECTION | 검사 | 10 |
| PRICE_FORMULA | 단가수식 | 11 |
실행 명령어
# api 디렉토리에서 실행
cd /Users/hskwon/Works/@KD_SAM/SAM/api
# 순차 실행 (의존성 순서)
php artisan db:seed --class=QuoteFormulaCategorySeeder
php artisan db:seed --class=QuoteFormulaSeeder
php artisan db:seed --class=QuoteFormulaItemSeeder
php artisan db:seed --class=QuoteFormulaMappingSeeder
# 또는 한번에
php artisan db:seed --class=QuoteFormulaCategorySeeder && \
php artisan db:seed --class=QuoteFormulaSeeder
4. 테스트 방법
1) 단가 조회 테스트
cd /Users/hskwon/Works/@KD_SAM/SAM/api
php artisan tinker
# 테스트
>>> \App\Models\Price::where('tenant_id', 1)->first()
>>> DB::table('products')->where('tenant_id', 1)->first()
2) 수식 실행 테스트
cd /Users/hskwon/Works/@KD_SAM/SAM/mng
# mng UI에서 시뮬레이터 접속
# URL: /quote-formulas/simulator
5. 변경 파일 목록
신규 생성
| 파일 | 설명 |
|---|---|
mng/app/Models/Price.php |
가격 모델 |
docs/projects/quotation/phase-3-implementation/README.md |
Phase 3 README |
docs/projects/quotation/phase-3-implementation/implementation.md |
구현 상세 |
docs/projects/quotation/phase-3-implementation/table-mapping.md |
테이블 매핑 |
수정
| 파일 | 변경 내용 |
|---|---|
mng/app/Services/Quote/FormulaEvaluatorService.php |
getItemPrice() 구현 |
docs/projects/quotation/PROGRESS.md |
Phase 3 상태 업데이트 |