견적 기능 개발 Phase 2: mng 분석 완료
- mng 견적 수식 관리 현재 상태 분석 - DB 테이블 5개, Models 5개, Services 2개 - Controllers 3개, Views 9개 구현 완료 - 핵심 이슈 도출 - 품목 단가 조회 미연동 (getItemPrice TODO) - 수식 데이터 미입력 (테이블 비어있음) - eval() 보안 취약점 - 5130 vs mng 비교 분석 - PROGRESS.md 업데이트
This commit is contained in:
@@ -11,7 +11,7 @@
|
|||||||
| Phase | 상태 | 진행률 | 시작일 | 완료일 |
|
| Phase | 상태 | 진행률 | 시작일 | 완료일 |
|
||||||
|-------|------|--------|--------|--------|
|
|-------|------|--------|--------|--------|
|
||||||
| Phase 1: 5130 분석 | ✅ 완료 | 100% | 2025-12-19 | 2025-12-19 |
|
| Phase 1: 5130 분석 | ✅ 완료 | 100% | 2025-12-19 | 2025-12-19 |
|
||||||
| Phase 2: mng 분석 | ⏳ 대기 | 0% | - | - |
|
| Phase 2: mng 분석 | ✅ 완료 | 100% | 2025-12-19 | 2025-12-19 |
|
||||||
| Phase 3: 구현 | ⏳ 대기 | 0% | - | - |
|
| Phase 3: 구현 | ⏳ 대기 | 0% | - | - |
|
||||||
| Phase 4: API 개발 | ⏳ 대기 | 0% | - | - |
|
| Phase 4: API 개발 | ⏳ 대기 | 0% | - | - |
|
||||||
|
|
||||||
@@ -19,8 +19,8 @@
|
|||||||
|
|
||||||
## 🔄 현재 작업
|
## 🔄 현재 작업
|
||||||
|
|
||||||
**현재 Phase:** Phase 1 완료, Phase 2 대기
|
**현재 Phase:** Phase 2 완료, Phase 3 대기
|
||||||
**다음 작업:** mng 견적 수식 관리 현황 분석
|
**다음 작업:** mng 견적 기능 구현 (5130 수식 적용)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -63,21 +63,44 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 📋 Phase 2: mng 견적 수식 관리 분석
|
## ✅ Phase 2: mng 견적 수식 관리 분석 (완료)
|
||||||
|
|
||||||
### 체크리스트
|
### 체크리스트
|
||||||
- [ ] 현재 구현 상태 분석 (quote-formulas)
|
- [x] 현재 구현 상태 분석 (quote-formulas)
|
||||||
- [ ] 오류/문제점 목록화
|
- [x] 오류/문제점 목록화
|
||||||
- [ ] 개선 방향 도출
|
- [x] 5130과의 차이점 분석
|
||||||
- [ ] README.md 작성
|
- [x] 개선 방향 도출
|
||||||
|
- [x] README.md 작성
|
||||||
|
|
||||||
### 산출물
|
### 산출물
|
||||||
- [ ] phase-2-mng-analysis/README.md
|
- [x] [README.md](./phase-2-mng-analysis/README.md) - 분석 요약
|
||||||
- [ ] phase-2-mng-analysis/current-state.md
|
- [x] [current-state.md](./phase-2-mng-analysis/current-state.md) - 현재 구현 상태
|
||||||
- [ ] phase-2-mng-analysis/issues.md
|
- [x] [issues.md](./phase-2-mng-analysis/issues.md) - 문제점 및 개선사항
|
||||||
|
|
||||||
### 메모
|
### 핵심 발견 사항
|
||||||
_Phase 2 진행 시 메모 기록_
|
|
||||||
|
#### 구현 상태 요약
|
||||||
|
| 구성요소 | 개수 | 상태 |
|
||||||
|
|----------|------|------|
|
||||||
|
| DB 테이블 | 5개 | ✅ 완료 |
|
||||||
|
| Models | 5개 | ✅ 완료 |
|
||||||
|
| Services | 2개 | ✅ 완료 |
|
||||||
|
| Controllers | 3개 | ✅ 완료 |
|
||||||
|
| Views | 9개 | ✅ 완료 |
|
||||||
|
|
||||||
|
#### 핵심 이슈 (Phase 3에서 해결)
|
||||||
|
| 우선순위 | 이슈 | 설명 |
|
||||||
|
|---------|------|------|
|
||||||
|
| 🔴 Critical | 품목 단가 조회 | getItemPrice() TODO 상태 |
|
||||||
|
| 🔴 Critical | 수식 데이터 미입력 | 테이블 비어있음 |
|
||||||
|
| 🟡 Important | eval() 사용 | 보안 취약점 |
|
||||||
|
|
||||||
|
#### 5130 vs mng 비교
|
||||||
|
| 항목 | 5130 | mng | 평가 |
|
||||||
|
|------|------|-----|------|
|
||||||
|
| 수식 저장 | JS 하드코딩 | DB 동적관리 | ✅ mng 우수 |
|
||||||
|
| 카테고리 분류 | 없음 | 13개 지원 | ✅ mng 우수 |
|
||||||
|
| 품목 단가 연동 | 직접 조회 | TODO 상태 | 🔴 미완성 |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
84
projects/quotation/phase-2-mng-analysis/README.md
Normal file
84
projects/quotation/phase-2-mng-analysis/README.md
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
# Phase 2: mng 견적 수식 관리 분석
|
||||||
|
|
||||||
|
> **목표:** 현재 mng 견적 기능 상태 파악 및 문제점 도출
|
||||||
|
> **분석일:** 2025-12-19
|
||||||
|
> **상태:** ✅ 완료
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 체크리스트
|
||||||
|
|
||||||
|
- [x] 현재 구현 상태 분석 (quote-formulas)
|
||||||
|
- [x] 오류/문제점 목록화
|
||||||
|
- [x] 5130과의 차이점 분석
|
||||||
|
- [x] 개선 방향 도출
|
||||||
|
- [x] README.md 작성
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 산출물
|
||||||
|
|
||||||
|
| 파일 | 설명 | 상태 |
|
||||||
|
|------|------|------|
|
||||||
|
| [README.md](./README.md) | 분석 체크리스트 및 요약 | ✅ |
|
||||||
|
| [current-state.md](./current-state.md) | 현재 구현 상태 | ✅ |
|
||||||
|
| [issues.md](./issues.md) | 오류/문제점 목록 | ✅ |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 요약
|
||||||
|
|
||||||
|
### 현재 구현 상태
|
||||||
|
|
||||||
|
mng 프로젝트에 견적 수식 관리 기능이 **완전히 구현**되어 있습니다:
|
||||||
|
|
||||||
|
| 구성요소 | 개수 | 상태 |
|
||||||
|
|----------|------|------|
|
||||||
|
| DB 테이블 | 5개 | ✅ 마이그레이션 완료 |
|
||||||
|
| Models | 5개 | ✅ 구현 완료 |
|
||||||
|
| Services | 2개 | ✅ 구현 완료 |
|
||||||
|
| Controllers | 3개 | ✅ 구현 완료 |
|
||||||
|
| Views | 9개 | ✅ 구현 완료 |
|
||||||
|
| API Routes | 30+ | ✅ 구현 완료 |
|
||||||
|
|
||||||
|
### 주요 기능
|
||||||
|
|
||||||
|
1. **수식 관리**: CRUD, 복제, 활성/비활성 토글
|
||||||
|
2. **카테고리 관리**: 수식 그룹화, 순서 관리
|
||||||
|
3. **수식 유형**: input, calculation, range, mapping
|
||||||
|
4. **수식 평가**: 변수 치환, 함수 처리, 조건 평가
|
||||||
|
5. **시뮬레이터**: 전체 수식 테스트
|
||||||
|
|
||||||
|
### 5130 vs mng 비교
|
||||||
|
|
||||||
|
| 항목 | 5130 | mng | Gap |
|
||||||
|
|------|------|-----|-----|
|
||||||
|
| 수식 저장 | JS 파일 하드코딩 | DB 동적 관리 | ✅ mng 우수 |
|
||||||
|
| 카테고리 | 없음 | 13개 분류 지원 | ✅ mng 우수 |
|
||||||
|
| 범위 조건 | PHP 함수 내장 | DB range 테이블 | ✅ mng 우수 |
|
||||||
|
| 매핑 조건 | PHP 조건문 | DB mapping 테이블 | ✅ mng 우수 |
|
||||||
|
| 품목 연동 | price_* 테이블 직접 조회 | ⚠️ TODO 상태 | 🔴 미완성 |
|
||||||
|
| 계산 엔진 | JavaScript | PHP (eval) | ⚠️ 보안 주의 |
|
||||||
|
|
||||||
|
### 핵심 이슈
|
||||||
|
|
||||||
|
1. **🔴 품목 단가 연동 미완성** - `getItemPrice()` TODO 상태
|
||||||
|
2. **🟡 보안 취약점** - `eval()` 사용 중
|
||||||
|
3. **🟡 5130 수식 데이터 미입력** - 빈 테이블 상태
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 다음 단계 (Phase 3)
|
||||||
|
|
||||||
|
1. 5130 수식 데이터를 mng DB로 마이그레이션
|
||||||
|
2. 품목 단가 조회 연동 구현
|
||||||
|
3. eval() 대신 안전한 수식 파서 적용
|
||||||
|
4. 스크린/슬랫 제품별 수식 분리 구현
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 참조 문서
|
||||||
|
|
||||||
|
- [Phase 1: 5130 분석](../phase-1-5130-analysis/README.md)
|
||||||
|
- [current-state.md](./current-state.md) - 상세 구현 상태
|
||||||
|
- [issues.md](./issues.md) - 문제점 및 개선사항
|
||||||
275
projects/quotation/phase-2-mng-analysis/current-state.md
Normal file
275
projects/quotation/phase-2-mng-analysis/current-state.md
Normal file
@@ -0,0 +1,275 @@
|
|||||||
|
# mng 견적 수식 관리 현재 상태
|
||||||
|
|
||||||
|
> **분석일:** 2025-12-19
|
||||||
|
> **대상:** mng 프로젝트 quote-formulas 기능
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. 데이터베이스 구조
|
||||||
|
|
||||||
|
### 테이블 목록 (5개)
|
||||||
|
|
||||||
|
마이그레이션: `api/database/migrations/2025_12_04_133410_create_quote_formula_tables.php`
|
||||||
|
|
||||||
|
| 테이블 | 설명 | 주요 컬럼 |
|
||||||
|
|--------|------|----------|
|
||||||
|
| `quote_formula_categories` | 수식 카테고리 | code, name, sort_order |
|
||||||
|
| `quote_formulas` | 수식 정의 | variable, type, formula, output_type |
|
||||||
|
| `quote_formula_ranges` | 범위별 값 | min_value, max_value, condition_variable |
|
||||||
|
| `quote_formula_mappings` | 매핑 값 | source_variable, source_value, result_value |
|
||||||
|
| `quote_formula_items` | 품목 출력 | item_code, quantity_formula, unit_price_formula |
|
||||||
|
|
||||||
|
### ERD 관계
|
||||||
|
|
||||||
|
```
|
||||||
|
quote_formula_categories (1) ──< (N) quote_formulas
|
||||||
|
│
|
||||||
|
├──< (N) quote_formula_ranges
|
||||||
|
├──< (N) quote_formula_mappings
|
||||||
|
└──< (N) quote_formula_items
|
||||||
|
```
|
||||||
|
|
||||||
|
### 수식 유형 (type)
|
||||||
|
|
||||||
|
| 값 | 설명 | 사용 예시 |
|
||||||
|
|---|------|----------|
|
||||||
|
| `input` | 입력값 | W0 (가로), H0 (세로) |
|
||||||
|
| `calculation` | 계산식 | `W1 = W0 + 50` |
|
||||||
|
| `range` | 범위별 조건 | 면적별 검사비 |
|
||||||
|
| `mapping` | 매핑 조건 | 설치유형별 값 |
|
||||||
|
|
||||||
|
### 출력 유형 (output_type)
|
||||||
|
|
||||||
|
| 값 | 설명 |
|
||||||
|
|---|------|
|
||||||
|
| `variable` | 변수로 저장 (다음 수식에서 참조 가능) |
|
||||||
|
| `item` | 품목으로 출력 (견적서에 표시) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. 모델 구조
|
||||||
|
|
||||||
|
### 파일 위치
|
||||||
|
|
||||||
|
```
|
||||||
|
mng/app/Models/Quote/
|
||||||
|
├── QuoteFormulaCategory.php # 카테고리
|
||||||
|
├── QuoteFormula.php # 수식 (메인)
|
||||||
|
├── QuoteFormulaRange.php # 범위 규칙
|
||||||
|
├── QuoteFormulaMapping.php # 매핑 규칙
|
||||||
|
└── QuoteFormulaItem.php # 품목 출력
|
||||||
|
```
|
||||||
|
|
||||||
|
### QuoteFormula 모델 상세
|
||||||
|
|
||||||
|
```php
|
||||||
|
// 상수 정의
|
||||||
|
TYPE_INPUT = 'input'
|
||||||
|
TYPE_CALCULATION = 'calculation'
|
||||||
|
TYPE_RANGE = 'range'
|
||||||
|
TYPE_MAPPING = 'mapping'
|
||||||
|
|
||||||
|
OUTPUT_VARIABLE = 'variable'
|
||||||
|
OUTPUT_ITEM = 'item'
|
||||||
|
|
||||||
|
// Traits
|
||||||
|
use BelongsToTenant, SoftDeletes;
|
||||||
|
|
||||||
|
// 관계
|
||||||
|
category() → BelongsTo
|
||||||
|
ranges() → HasMany
|
||||||
|
mappings() → HasMany
|
||||||
|
items() → HasMany
|
||||||
|
creator() → BelongsTo (User)
|
||||||
|
updater() → BelongsTo (User)
|
||||||
|
|
||||||
|
// Scopes
|
||||||
|
scopeCommon() → 공통 수식 (product_id IS NULL)
|
||||||
|
scopeForProduct($productId) → 제품별 수식
|
||||||
|
scopeActive() → 활성 수식
|
||||||
|
scopeOrdered() → 정렬
|
||||||
|
scopeOfType($type) → 유형별 필터
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. 서비스 구조
|
||||||
|
|
||||||
|
### QuoteFormulaService
|
||||||
|
|
||||||
|
**파일:** `mng/app/Services/Quote/QuoteFormulaService.php`
|
||||||
|
|
||||||
|
| 메서드 | 설명 |
|
||||||
|
|--------|------|
|
||||||
|
| `getFormulas()` | 수식 목록 (페이지네이션, 필터) |
|
||||||
|
| `getFormulasByCategory()` | 카테고리별 수식 (실행 순서용) |
|
||||||
|
| `getFormulaById()` | 수식 상세 조회 |
|
||||||
|
| `createFormula()` | 수식 생성 (트랜잭션) |
|
||||||
|
| `updateFormula()` | 수식 수정 (트랜잭션) |
|
||||||
|
| `deleteFormula()` | 수식 삭제 (Soft Delete) |
|
||||||
|
| `toggleActive()` | 활성/비활성 토글 |
|
||||||
|
| `duplicateFormula()` | 수식 복제 |
|
||||||
|
| `reorder()` | 순서 변경 |
|
||||||
|
| `isVariableExists()` | 변수명 중복 체크 |
|
||||||
|
| `getAvailableVariables()` | 사용 가능한 변수 목록 |
|
||||||
|
| `getFormulaStats()` | 수식 통계 |
|
||||||
|
|
||||||
|
### FormulaEvaluatorService
|
||||||
|
|
||||||
|
**파일:** `mng/app/Services/Quote/FormulaEvaluatorService.php`
|
||||||
|
|
||||||
|
| 메서드 | 설명 |
|
||||||
|
|--------|------|
|
||||||
|
| `validateFormula()` | 수식 문법 검증 |
|
||||||
|
| `evaluate()` | 단일 수식 평가 |
|
||||||
|
| `evaluateRange()` | 범위별 수식 평가 |
|
||||||
|
| `evaluateMapping()` | 매핑 수식 평가 |
|
||||||
|
| `executeAll()` | 전체 수식 실행 (카테고리 순서) |
|
||||||
|
| `getErrors()` | 에러 목록 반환 |
|
||||||
|
| `getVariables()` | 현재 변수 상태 |
|
||||||
|
| `resetVariables()` | 변수 초기화 |
|
||||||
|
|
||||||
|
### 지원 함수
|
||||||
|
|
||||||
|
```
|
||||||
|
SUM, ROUND, CEIL, FLOOR, ABS, MIN, MAX, IF, AND, OR, NOT
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. 컨트롤러 구조
|
||||||
|
|
||||||
|
### Web 컨트롤러
|
||||||
|
|
||||||
|
**파일:** `mng/app/Http/Controllers/QuoteFormulaController.php`
|
||||||
|
|
||||||
|
| 메서드 | URL | 설명 |
|
||||||
|
|--------|-----|------|
|
||||||
|
| `index()` | `/quote-formulas` | 수식 목록 화면 |
|
||||||
|
| `create()` | `/quote-formulas/create` | 수식 생성 화면 |
|
||||||
|
| `edit()` | `/quote-formulas/{id}/edit` | 수식 수정 화면 |
|
||||||
|
| `categories()` | `/quote-formulas/categories` | 카테고리 목록 |
|
||||||
|
| `simulator()` | `/quote-formulas/simulator` | 시뮬레이터 |
|
||||||
|
|
||||||
|
### API 컨트롤러
|
||||||
|
|
||||||
|
**파일:** `mng/app/Http/Controllers/Api/Admin/Quote/QuoteFormulaController.php`
|
||||||
|
|
||||||
|
| 메서드 | HTTP | URL | 설명 |
|
||||||
|
|--------|------|-----|------|
|
||||||
|
| `index()` | GET | `/api/admin/quote-formulas/formulas` | 목록 (HTMX) |
|
||||||
|
| `store()` | POST | `/api/admin/quote-formulas/formulas` | 생성 |
|
||||||
|
| `show()` | GET | `/api/admin/quote-formulas/formulas/{id}` | 상세 |
|
||||||
|
| `update()` | PUT | `/api/admin/quote-formulas/formulas/{id}` | 수정 |
|
||||||
|
| `destroy()` | DELETE | `/api/admin/quote-formulas/formulas/{id}` | 삭제 |
|
||||||
|
| `restore()` | POST | `/api/admin/quote-formulas/formulas/{id}/restore` | 복원 |
|
||||||
|
| `forceDestroy()` | DELETE | `/api/admin/quote-formulas/formulas/{id}/force` | 영구삭제 |
|
||||||
|
| `toggleActive()` | POST | `/api/admin/quote-formulas/formulas/{id}/toggle-active` | 토글 |
|
||||||
|
| `duplicate()` | POST | `/api/admin/quote-formulas/formulas/{id}/duplicate` | 복제 |
|
||||||
|
| `reorder()` | POST | `/api/admin/quote-formulas/formulas/reorder` | 순서변경 |
|
||||||
|
| `variables()` | GET | `/api/admin/quote-formulas/formulas/variables` | 변수목록 |
|
||||||
|
| `validate()` | POST | `/api/admin/quote-formulas/formulas/validate` | 수식검증 |
|
||||||
|
| `test()` | POST | `/api/admin/quote-formulas/formulas/test` | 수식테스트 |
|
||||||
|
| `simulate()` | POST | `/api/admin/quote-formulas/formulas/simulate` | 시뮬레이션 |
|
||||||
|
| `stats()` | GET | `/api/admin/quote-formulas/formulas/stats` | 통계 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. View 구조
|
||||||
|
|
||||||
|
```
|
||||||
|
mng/resources/views/quote-formulas/
|
||||||
|
├── index.blade.php # 수식 목록 메인
|
||||||
|
├── create.blade.php # 수식 생성 폼
|
||||||
|
├── edit.blade.php # 수식 수정 폼
|
||||||
|
├── simulator.blade.php # 시뮬레이터
|
||||||
|
├── categories/
|
||||||
|
│ ├── index.blade.php # 카테고리 목록
|
||||||
|
│ ├── create.blade.php # 카테고리 생성
|
||||||
|
│ ├── edit.blade.php # 카테고리 수정
|
||||||
|
│ └── partials/
|
||||||
|
│ └── table.blade.php # 카테고리 테이블 (HTMX)
|
||||||
|
└── partials/
|
||||||
|
└── table.blade.php # 수식 테이블 (HTMX)
|
||||||
|
```
|
||||||
|
|
||||||
|
### UI 특징
|
||||||
|
|
||||||
|
- **HTMX 기반**: 페이지 새로고침 없이 데이터 갱신
|
||||||
|
- **필터링**: 카테고리, 유형, 활성상태, 검색
|
||||||
|
- **Soft Delete**: 삭제/복원/영구삭제 지원
|
||||||
|
- **드래그 정렬**: 순서 변경 기능
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. FormRequest
|
||||||
|
|
||||||
|
```
|
||||||
|
mng/app/Http/Requests/Quote/
|
||||||
|
├── StoreQuoteFormulaCategoryRequest.php
|
||||||
|
├── UpdateQuoteFormulaCategoryRequest.php
|
||||||
|
├── StoreQuoteFormulaRequest.php
|
||||||
|
└── UpdateQuoteFormulaRequest.php
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. 라우트 정의
|
||||||
|
|
||||||
|
### Web Routes (`routes/web.php`)
|
||||||
|
|
||||||
|
```php
|
||||||
|
Route::prefix('quote-formulas')->name('quote-formulas.')->group(function () {
|
||||||
|
Route::get('/', [QuoteFormulaController::class, 'index'])->name('index');
|
||||||
|
Route::get('/create', [QuoteFormulaController::class, 'create'])->name('create');
|
||||||
|
Route::get('/{id}/edit', [QuoteFormulaController::class, 'edit'])->name('edit');
|
||||||
|
Route::get('/categories', [QuoteFormulaController::class, 'categories'])->name('categories.index');
|
||||||
|
Route::get('/categories/create', [QuoteFormulaController::class, 'createCategory'])->name('categories.create');
|
||||||
|
Route::get('/categories/{id}/edit', [QuoteFormulaController::class, 'editCategory'])->name('categories.edit');
|
||||||
|
Route::get('/simulator', [QuoteFormulaController::class, 'simulator'])->name('simulator');
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### API Routes (`routes/api.php`)
|
||||||
|
|
||||||
|
30+ 개의 API 엔드포인트 정의 (카테고리 CRUD + 수식 CRUD + 추가 기능)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. 수식 실행 흐름
|
||||||
|
|
||||||
|
```
|
||||||
|
1. 입력값 수집 (W0, H0, 설치유형 등)
|
||||||
|
↓
|
||||||
|
2. 카테고리 순서대로 수식 조회
|
||||||
|
↓
|
||||||
|
3. 각 수식 실행
|
||||||
|
├─ TYPE_INPUT: 입력값 또는 기본값
|
||||||
|
├─ TYPE_CALCULATION: 수식 계산
|
||||||
|
├─ TYPE_RANGE: 범위 조건 평가
|
||||||
|
└─ TYPE_MAPPING: 매핑 조건 평가
|
||||||
|
↓
|
||||||
|
4. 결과 저장
|
||||||
|
├─ OUTPUT_VARIABLE: 변수로 저장 (다음 수식에서 참조)
|
||||||
|
└─ OUTPUT_ITEM: 품목 목록에 추가
|
||||||
|
↓
|
||||||
|
5. 최종 결과 반환
|
||||||
|
├─ variables: 계산된 변수 목록
|
||||||
|
├─ items: 품목 목록 (품명, 수량, 단가, 금액)
|
||||||
|
└─ errors: 오류 목록
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 9. 현재 데이터 상태
|
||||||
|
|
||||||
|
**⚠️ 주의: 테이블이 비어있음 (수식 데이터 미입력)**
|
||||||
|
|
||||||
|
Phase 3에서 5130 분석 결과를 기반으로 수식 데이터를 입력해야 합니다.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 참조
|
||||||
|
|
||||||
|
- [README.md](./README.md) - 분석 요약
|
||||||
|
- [issues.md](./issues.md) - 문제점 및 개선사항
|
||||||
252
projects/quotation/phase-2-mng-analysis/issues.md
Normal file
252
projects/quotation/phase-2-mng-analysis/issues.md
Normal file
@@ -0,0 +1,252 @@
|
|||||||
|
# mng 견적 수식 관리 이슈 및 개선사항
|
||||||
|
|
||||||
|
> **분석일:** 2025-12-19
|
||||||
|
> **대상:** mng 프로젝트 quote-formulas 기능
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔴 Critical Issues (필수 해결)
|
||||||
|
|
||||||
|
### 1. 품목 단가 조회 미연동
|
||||||
|
|
||||||
|
**위치:** `FormulaEvaluatorService.php:324-328`
|
||||||
|
|
||||||
|
```php
|
||||||
|
private function getItemPrice(string $itemCode): float
|
||||||
|
{
|
||||||
|
// TODO: 품목 마스터에서 단가 조회
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**문제점:**
|
||||||
|
- 품목 출력 시 단가가 항상 0으로 반환
|
||||||
|
- 견적 금액 계산 불가
|
||||||
|
|
||||||
|
**해결 방안:**
|
||||||
|
```php
|
||||||
|
private function getItemPrice(string $itemCode): float
|
||||||
|
{
|
||||||
|
$tenantId = session('selected_tenant_id');
|
||||||
|
|
||||||
|
// prices 테이블 또는 products 테이블에서 조회
|
||||||
|
$price = Price::where('tenant_id', $tenantId)
|
||||||
|
->where('item_code', $itemCode)
|
||||||
|
->where('is_active', true)
|
||||||
|
->first();
|
||||||
|
|
||||||
|
return $price?->unit_price ?? 0;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**우선순위:** 🔴 Critical
|
||||||
|
**예상 작업량:** 2시간
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 2. 수식 데이터 미입력
|
||||||
|
|
||||||
|
**문제점:**
|
||||||
|
- `quote_formula_categories`, `quote_formulas` 테이블이 비어있음
|
||||||
|
- Phase 1에서 분석한 5130 수식이 입력되지 않음
|
||||||
|
|
||||||
|
**해결 방안:**
|
||||||
|
- Phase 3에서 5130 수식을 mng DB로 마이그레이션
|
||||||
|
- Seeder 또는 관리 UI를 통한 데이터 입력
|
||||||
|
|
||||||
|
**우선순위:** 🔴 Critical
|
||||||
|
**예상 작업량:** 4시간
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🟡 Important Issues (권장 해결)
|
||||||
|
|
||||||
|
### 3. eval() 사용 보안 취약점
|
||||||
|
|
||||||
|
**위치:** `FormulaEvaluatorService.php:291-299`
|
||||||
|
|
||||||
|
```php
|
||||||
|
private function calculateExpression(string $expression): float
|
||||||
|
{
|
||||||
|
// 안전한 수식 평가 (숫자, 연산자, 괄호만 허용)
|
||||||
|
$expression = preg_replace('/[^0-9+\-*\/().%\s]/', '', $expression);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// eval 대신 안전한 계산 라이브러리 사용 권장
|
||||||
|
return (float) eval("return {$expression};");
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
$this->errors[] = "계산 오류: {$expression}";
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**문제점:**
|
||||||
|
- `eval()` 함수 사용은 잠재적 보안 위험
|
||||||
|
- 코드 주입 공격 가능성 (현재 정규식 필터로 일부 방어)
|
||||||
|
|
||||||
|
**해결 방안:**
|
||||||
|
```php
|
||||||
|
// symfony/expression-language 패키지 사용
|
||||||
|
use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
|
||||||
|
|
||||||
|
private ExpressionLanguage $expressionLanguage;
|
||||||
|
|
||||||
|
private function calculateExpression(string $expression): float
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
return (float) $this->expressionLanguage->evaluate($expression);
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
$this->errors[] = "계산 오류: {$expression}";
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**우선순위:** 🟡 Important
|
||||||
|
**예상 작업량:** 3시간
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 4. 5130 수식 vs mng 수식 Gap
|
||||||
|
|
||||||
|
**5130에서 발견된 수식 중 mng 미지원 항목:**
|
||||||
|
|
||||||
|
| 5130 수식 | mng 지원 | Gap |
|
||||||
|
|----------|---------|-----|
|
||||||
|
| 절곡 옵션에 따른 분기 | ✅ mapping | - |
|
||||||
|
| 면적별 검사비 계산 | ✅ range | - |
|
||||||
|
| 모터 용량 자동 선택 | ⚠️ 부분지원 | 범위 조건 복잡 |
|
||||||
|
| 스크린/슬랫 제품 분기 | ⚠️ product_id | 데이터 없음 |
|
||||||
|
| 단가표 조회 (price_*) | 🔴 미지원 | getItemPrice TODO |
|
||||||
|
|
||||||
|
**우선순위:** 🟡 Important
|
||||||
|
**예상 작업량:** Phase 3 전체
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 5. 중첩 함수 처리 한계
|
||||||
|
|
||||||
|
**현재 상태:**
|
||||||
|
- `ROUND(SUM(A, B), 2)` 같은 중첩 함수 처리 제한적
|
||||||
|
- 정규식 기반 파싱으로 복잡한 중첩 처리 어려움
|
||||||
|
|
||||||
|
**해결 방안:**
|
||||||
|
- 재귀적 파서 구현 또는 AST 기반 파서 도입
|
||||||
|
- 또는 symfony/expression-language로 전환
|
||||||
|
|
||||||
|
**우선순위:** 🟡 Important
|
||||||
|
**예상 작업량:** 4시간
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🟢 Minor Issues (개선 권장)
|
||||||
|
|
||||||
|
### 6. 변수명 검증 강화
|
||||||
|
|
||||||
|
**현재 상태:**
|
||||||
|
- 변수명 중복 체크만 수행
|
||||||
|
- 예약어(함수명) 사용 검증 없음
|
||||||
|
|
||||||
|
**해결 방안:**
|
||||||
|
```php
|
||||||
|
public function isValidVariableName(string $variable): bool
|
||||||
|
{
|
||||||
|
$reserved = ['SUM', 'ROUND', 'CEIL', 'FLOOR', 'ABS', 'MIN', 'MAX', 'IF', 'AND', 'OR', 'NOT'];
|
||||||
|
|
||||||
|
if (in_array(strtoupper($variable), $reserved)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return preg_match('/^[A-Z][A-Z0-9_]*$/', $variable);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**우선순위:** 🟢 Minor
|
||||||
|
**예상 작업량:** 30분
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 7. 수식 의존성 분석
|
||||||
|
|
||||||
|
**현재 상태:**
|
||||||
|
- 수식 간 의존성(어떤 변수가 어떤 수식에서 사용되는지) 분석 없음
|
||||||
|
- 삭제 시 참조 무결성 검증 없음
|
||||||
|
|
||||||
|
**해결 방안:**
|
||||||
|
- 변수 사용처 분석 기능 추가
|
||||||
|
- 삭제 전 참조 검사
|
||||||
|
|
||||||
|
**우선순위:** 🟢 Minor
|
||||||
|
**예상 작업량:** 2시간
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 8. 수식 버전 관리
|
||||||
|
|
||||||
|
**현재 상태:**
|
||||||
|
- 수식 변경 이력 관리 없음
|
||||||
|
- 이전 버전으로 롤백 불가
|
||||||
|
|
||||||
|
**해결 방안:**
|
||||||
|
- `quote_formula_versions` 테이블 추가
|
||||||
|
- 변경 시 이전 버전 저장
|
||||||
|
|
||||||
|
**우선순위:** 🟢 Minor (향후)
|
||||||
|
**예상 작업량:** 4시간
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5130 vs mng 상세 비교
|
||||||
|
|
||||||
|
### 수식 저장 방식
|
||||||
|
|
||||||
|
| 항목 | 5130 | mng |
|
||||||
|
|------|------|-----|
|
||||||
|
| 저장 위치 | JS 파일 하드코딩 | DB 테이블 |
|
||||||
|
| 관리 방식 | 코드 수정 필요 | 관리 UI |
|
||||||
|
| 유연성 | 낮음 | 높음 |
|
||||||
|
| 배포 | 파일 배포 필요 | 즉시 반영 |
|
||||||
|
|
||||||
|
### 계산 엔진
|
||||||
|
|
||||||
|
| 항목 | 5130 | mng |
|
||||||
|
|------|------|-----|
|
||||||
|
| 실행 환경 | 브라우저 JavaScript | 서버 PHP |
|
||||||
|
| 함수 지원 | JS 내장 함수 전체 | 11개 제한 |
|
||||||
|
| 성능 | 클라이언트 부담 | 서버 부담 |
|
||||||
|
| 보안 | 수식 노출 | 수식 보호 |
|
||||||
|
|
||||||
|
### 단가 조회
|
||||||
|
|
||||||
|
| 항목 | 5130 | mng |
|
||||||
|
|------|------|-----|
|
||||||
|
| 조회 방식 | PHP에서 직접 SQL | TODO 상태 |
|
||||||
|
| 테이블 | price_screen, price_slat 등 | prices (통합) |
|
||||||
|
| 캐싱 | 없음 | 가능 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 3 구현 시 고려사항
|
||||||
|
|
||||||
|
1. **수식 데이터 마이그레이션 순서**
|
||||||
|
- 카테고리 먼저 생성 (13개)
|
||||||
|
- 기본정보 수식부터 순차 입력
|
||||||
|
- 의존성 순서 고려
|
||||||
|
|
||||||
|
2. **제품별 수식 분리**
|
||||||
|
- 공통 수식: product_id = NULL
|
||||||
|
- 스크린 전용: product_id = 스크린 ID
|
||||||
|
- 슬랫 전용: product_id = 슬랫 ID
|
||||||
|
|
||||||
|
3. **테스트 케이스 준비**
|
||||||
|
- Phase 1에서 정의한 테스트 케이스 활용
|
||||||
|
- 5130과 동일 결과 검증
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 참조
|
||||||
|
|
||||||
|
- [README.md](./README.md) - 분석 요약
|
||||||
|
- [current-state.md](./current-state.md) - 현재 구현 상태
|
||||||
|
- [Phase 1 수식 분석](../phase-1-5130-analysis/js-formulas.md) - 5130 수식 상세
|
||||||
Reference in New Issue
Block a user