2025-12-22 16:37:45 +09:00
|
|
|
# MNG 견적수식 관리 개발 계획
|
|
|
|
|
|
|
|
|
|
> **작성일**: 2025-12-22
|
2025-12-24 08:54:52 +09:00
|
|
|
> **상태**: ✅ 완료
|
2025-12-22 16:37:45 +09:00
|
|
|
> **대상**: mng.sam.kr/quote-formulas
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## 1. 현황 분석
|
|
|
|
|
|
|
|
|
|
### 1.1 MNG 프로젝트 현재 상태
|
|
|
|
|
|
|
|
|
|
#### 구현된 기능 (mng)
|
|
|
|
|
|
|
|
|
|
| 기능 | 상태 | 설명 |
|
|
|
|
|
|-----|------|-----|
|
|
|
|
|
| 수식 목록 | ✅ 완료 | 페이지네이션, 필터링, HTMX 테이블 |
|
|
|
|
|
| 수식 생성 | ✅ 완료 | 카테고리, 유형, 변수명, 수식 입력 |
|
|
|
|
|
| 수식 수정 | ✅ 완료 | 편집 폼, API 연동 |
|
|
|
|
|
| 수식 삭제 | ✅ 완료 | Soft Delete, 복원, 영구삭제 |
|
|
|
|
|
| 수식 복제 | ✅ 완료 | 수식 복사 기능 |
|
|
|
|
|
| 활성/비활성 | ✅ 완료 | 토글 기능 |
|
|
|
|
|
| 카테고리 관리 | ✅ 완료 | CRUD 구현 |
|
|
|
|
|
| 시뮬레이터 | ✅ 완료 | 입력값 → 계산 결과 미리보기 |
|
|
|
|
|
| 변수 참조 | ✅ 완료 | 사용 가능한 변수 목록 표시 |
|
|
|
|
|
| 수식 검증 | ✅ 완료 | 문법 검증 API |
|
2025-12-24 08:54:52 +09:00
|
|
|
| 범위(Range) 관리 UI | ✅ 완료 | 범위별 결과 설정 화면 (Phase 1) |
|
|
|
|
|
| 매핑(Mapping) 관리 UI | ✅ 완료 | 매핑 규칙 설정 화면 (Phase 2) |
|
|
|
|
|
| 품목(Item) 관리 UI | ✅ 완료 | 출력 품목 설정 화면 (Phase 3) |
|
2025-12-22 16:37:45 +09:00
|
|
|
|
|
|
|
|
### 1.2 API 프로젝트 현재 상태
|
|
|
|
|
|
|
|
|
|
#### 모델 구조 (api)
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
QuoteFormulaCategory (카테고리)
|
|
|
|
|
└── QuoteFormula (수식)
|
|
|
|
|
├── QuoteFormulaRange (범위 조건)
|
|
|
|
|
├── QuoteFormulaMapping (매핑 규칙)
|
|
|
|
|
└── QuoteFormulaItem (출력 품목)
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
#### 시더 데이터 (api)
|
|
|
|
|
|
|
|
|
|
| 시더 | 데이터 수 | 설명 |
|
|
|
|
|
|-----|---------|-----|
|
|
|
|
|
| QuoteFormulaCategorySeeder | 11개 | 카테고리 (오픈사이즈~단가수식) |
|
|
|
|
|
| QuoteFormulaSeeder | 30개 수식, 18개 범위 | 스크린 계산 수식 |
|
2025-12-24 08:54:52 +09:00
|
|
|
| QuoteFormulaItemSeeder | 25개 | 품목 마스터 |
|
2025-12-22 16:37:45 +09:00
|
|
|
|
|
|
|
|
#### 서비스 (api)
|
|
|
|
|
|
|
|
|
|
| 서비스 | 역할 |
|
|
|
|
|
|-------|-----|
|
|
|
|
|
| QuoteCalculationService | 자동산출 실행 엔진 |
|
|
|
|
|
| FormulaEvaluatorService | 수식 평가, 범위/매핑 처리 |
|
|
|
|
|
| QuoteService | 견적 CRUD, 상태 관리 |
|
|
|
|
|
| QuoteNumberService | 견적번호 생성 |
|
|
|
|
|
| QuoteDocumentService | PDF/이메일/카카오 발송 (TODO) |
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## 2. MNG vs API 비교 분석
|
|
|
|
|
|
|
|
|
|
### 2.1 데이터 구조 비교
|
|
|
|
|
|
|
|
|
|
| 항목 | MNG | API | 일치 |
|
|
|
|
|
|-----|-----|-----|-----|
|
|
|
|
|
| quote_formula_categories | ✅ | ✅ | ✅ |
|
|
|
|
|
| quote_formulas | ✅ | ✅ | ✅ |
|
|
|
|
|
| quote_formula_ranges | ✅ | ✅ | ✅ |
|
|
|
|
|
| quote_formula_mappings | ✅ | ✅ | ✅ |
|
|
|
|
|
| quote_formula_items | ✅ | ✅ | ✅ |
|
|
|
|
|
|
|
|
|
|
**결론**: 모델 구조는 동일함 (같은 DB 사용)
|
|
|
|
|
|
|
|
|
|
### 2.2 기능 비교
|
|
|
|
|
|
|
|
|
|
| 기능 | MNG | API | 비고 |
|
|
|
|
|
|-----|-----|-----|-----|
|
|
|
|
|
| 수식 CRUD | ✅ | ✅ | 동일 |
|
|
|
|
|
| 카테고리 CRUD | ✅ | ✅ | 동일 |
|
2025-12-24 08:54:52 +09:00
|
|
|
| 범위 관리 UI | ✅ | ✅ (시더) | Phase 1 완료 |
|
|
|
|
|
| 매핑 관리 UI | ✅ | ✅ (시더) | Phase 2 완료 |
|
|
|
|
|
| 품목 관리 UI | ✅ | ✅ (시더) | Phase 3 완료 |
|
2025-12-22 16:37:45 +09:00
|
|
|
| 시뮬레이터 | ✅ | ✅ | 동일 |
|
|
|
|
|
| 자동산출 API | - | ✅ | API 전용 |
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
2025-12-24 08:54:52 +09:00
|
|
|
## 3. 개발 계획 (완료)
|
2025-12-22 16:37:45 +09:00
|
|
|
|
|
|
|
|
### 3.1 목표
|
|
|
|
|
|
|
|
|
|
MNG에서 **범위(Range), 매핑(Mapping), 품목(Item)** 관리 UI를 추가하여:
|
|
|
|
|
1. 시더 없이도 관리자가 직접 수식 규칙 설정 가능
|
2025-12-24 08:54:52 +09:00
|
|
|
2. SAM 자체 품목 마스터로 가격 설정
|
2025-12-22 16:37:45 +09:00
|
|
|
3. 실시간 시뮬레이션으로 설정 검증 가능
|
|
|
|
|
|
2025-12-24 08:54:52 +09:00
|
|
|
### 3.2 개발 범위 (완료)
|
2025-12-22 16:37:45 +09:00
|
|
|
|
2025-12-24 08:54:52 +09:00
|
|
|
#### Phase 1: 범위(Range) 관리 UI ✅
|
2025-12-22 16:37:45 +09:00
|
|
|
|
|
|
|
|
**우선순위**: 높음
|
|
|
|
|
**이유**: 모터, 가이드레일, 케이스 자동 선택에 필수
|
|
|
|
|
|
|
|
|
|
**기능 목록**:
|
|
|
|
|
1. 수식 상세 페이지에 범위 관리 탭 추가
|
|
|
|
|
2. 범위 목록 표시 (min ~ max → 결과)
|
|
|
|
|
3. 범위 추가/수정/삭제
|
|
|
|
|
4. 드래그앤드롭 순서 변경
|
|
|
|
|
5. item_code 연결 (품목 선택)
|
|
|
|
|
|
|
|
|
|
**화면 설계**:
|
|
|
|
|
```
|
|
|
|
|
[수식 수정] 페이지
|
|
|
|
|
├── [기본 정보] 탭 (기존)
|
|
|
|
|
├── [범위 설정] 탭 ← 추가
|
|
|
|
|
│ ├── 조건 변수: [K (중량)] ▼
|
|
|
|
|
│ ├── 범위 목록
|
|
|
|
|
│ │ ┌─────────────────────────────────────────────────┐
|
|
|
|
|
│ │ │ # │ 최소값 │ 최대값 │ 결과값 │ 품목코드 │
|
|
|
|
|
│ │ ├─────────────────────────────────────────────────┤
|
|
|
|
|
│ │ │ 1 │ 0 │ 150 │ 150K │ PT-MOTOR-150│
|
|
|
|
|
│ │ │ 2 │ 150 │ 300 │ 300K │ PT-MOTOR-300│
|
|
|
|
|
│ │ │ 3 │ 300 │ 400 │ 400K │ PT-MOTOR-400│
|
|
|
|
|
│ │ └─────────────────────────────────────────────────┘
|
|
|
|
|
│ └── [+ 범위 추가]
|
|
|
|
|
├── [매핑 설정] 탭
|
|
|
|
|
└── [품목 설정] 탭
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**API 엔드포인트 (MNG 내부)**:
|
|
|
|
|
```
|
|
|
|
|
GET /api/admin/quote-formulas/formulas/{id}/ranges
|
|
|
|
|
POST /api/admin/quote-formulas/formulas/{id}/ranges
|
|
|
|
|
PUT /api/admin/quote-formulas/formulas/{id}/ranges/{rangeId}
|
|
|
|
|
DELETE /api/admin/quote-formulas/formulas/{id}/ranges/{rangeId}
|
|
|
|
|
POST /api/admin/quote-formulas/formulas/{id}/ranges/reorder
|
|
|
|
|
```
|
|
|
|
|
|
2025-12-24 08:54:52 +09:00
|
|
|
#### Phase 2: 매핑(Mapping) 관리 UI ✅
|
2025-12-22 16:37:45 +09:00
|
|
|
|
|
|
|
|
**우선순위**: 중간
|
|
|
|
|
**이유**: 제어기 유형 등 코드 매핑에 사용
|
|
|
|
|
|
|
|
|
|
**기능 목록**:
|
|
|
|
|
1. 수식 상세 페이지에 매핑 관리 탭 추가
|
|
|
|
|
2. 매핑 목록 표시 (소스값 → 결과값)
|
|
|
|
|
3. 매핑 추가/수정/삭제
|
|
|
|
|
|
|
|
|
|
**화면 설계**:
|
|
|
|
|
```
|
|
|
|
|
[매핑 설정] 탭
|
|
|
|
|
├── 소스 변수: [CONTROL_TYPE] ▼
|
|
|
|
|
├── 매핑 목록
|
|
|
|
|
│ ┌──────────────────────────────────────────────────┐
|
|
|
|
|
│ │ # │ 소스값 │ 결과값 │ 품목코드 │
|
|
|
|
|
│ ├──────────────────────────────────────────────────┤
|
|
|
|
|
│ │ 1 │ EMB │ 매립형 │ PT-CTRL-EMB │
|
|
|
|
|
│ │ 2 │ EXP │ 노출형 │ PT-CTRL-EXP │
|
|
|
|
|
│ │ 3 │ BOX_1P │ 콘트롤박스 │ PT-CTRL-BOX-1P │
|
|
|
|
|
│ └──────────────────────────────────────────────────┘
|
|
|
|
|
└── [+ 매핑 추가]
|
|
|
|
|
```
|
|
|
|
|
|
2025-12-24 08:54:52 +09:00
|
|
|
#### Phase 3: 품목(Item) 관리 UI ✅
|
2025-12-22 16:37:45 +09:00
|
|
|
|
|
|
|
|
**우선순위**: 중간
|
|
|
|
|
**이유**: 수식 결과로 생성되는 품목 정의
|
|
|
|
|
|
|
|
|
|
**기능 목록**:
|
|
|
|
|
1. 수식 상세 페이지에 품목 관리 탭 추가
|
|
|
|
|
2. 품목 목록 표시
|
|
|
|
|
3. 품목 추가/수정/삭제
|
|
|
|
|
4. 수량/단가 수식 입력
|
2025-12-24 08:54:52 +09:00
|
|
|
5. SAM 품목 마스터에서 가격 참조
|
2025-12-22 16:37:45 +09:00
|
|
|
|
|
|
|
|
**화면 설계**:
|
|
|
|
|
```
|
|
|
|
|
[품목 설정] 탭
|
|
|
|
|
├── 품목 목록
|
|
|
|
|
│ ┌───────────────────────────────────────────────────────────┐
|
|
|
|
|
│ │ 품목코드 │ 품목명 │ 규격 │ 수량식 │ 단가식│
|
|
|
|
|
│ ├───────────────────────────────────────────────────────────┤
|
|
|
|
|
│ │ PT-MOTOR-150 │ 개폐전동기 150kg│ 150K(S) │ 1 │ 285000│
|
|
|
|
|
│ │ PT-GR-3000 │ 가이드레일 3000 │ 3000mm │ 2 │ 42000 │
|
|
|
|
|
│ └───────────────────────────────────────────────────────────┘
|
2025-12-24 08:54:52 +09:00
|
|
|
└── [+ 품목 추가]
|
2025-12-22 16:37:45 +09:00
|
|
|
```
|
|
|
|
|
|
2025-12-24 08:54:52 +09:00
|
|
|
### 3.3 파일 구조 (구현 완료)
|
2025-12-22 16:37:45 +09:00
|
|
|
|
|
|
|
|
#### Controllers
|
|
|
|
|
```
|
|
|
|
|
app/Http/Controllers/
|
|
|
|
|
├── QuoteFormulaController.php (수정: 탭 추가)
|
|
|
|
|
└── Api/Admin/Quote/
|
2025-12-24 08:54:52 +09:00
|
|
|
├── QuoteFormulaController.php
|
|
|
|
|
├── QuoteFormulaRangeController.php ✅
|
|
|
|
|
├── QuoteFormulaMappingController.php ✅
|
|
|
|
|
├── QuoteFormulaItemController.php ✅
|
|
|
|
|
└── QuoteFormulaCategoryController.php
|
2025-12-22 16:37:45 +09:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
#### Services
|
|
|
|
|
```
|
2025-12-24 08:54:52 +09:00
|
|
|
app/Services/Quote/
|
|
|
|
|
├── QuoteFormulaService.php
|
|
|
|
|
├── QuoteFormulaRangeService.php ✅
|
|
|
|
|
├── QuoteFormulaMappingService.php ✅
|
|
|
|
|
├── QuoteFormulaItemService.php ✅
|
|
|
|
|
└── QuoteFormulaCategoryService.php
|
2025-12-22 16:37:45 +09:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
#### Views
|
|
|
|
|
```
|
|
|
|
|
resources/views/quote-formulas/
|
2025-12-24 08:54:52 +09:00
|
|
|
├── index.blade.php
|
|
|
|
|
├── create.blade.php
|
|
|
|
|
├── edit.blade.php (수정: 탭 구조)
|
|
|
|
|
├── simulator.blade.php
|
|
|
|
|
└── partials/
|
|
|
|
|
├── basic-info-tab.blade.php ✅
|
|
|
|
|
├── ranges-tab.blade.php ✅
|
|
|
|
|
├── mappings-tab.blade.php ✅
|
|
|
|
|
└── items-tab.blade.php ✅
|
2025-12-22 16:37:45 +09:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## 4. 기술 스택
|
|
|
|
|
|
|
|
|
|
### 4.1 Frontend (MNG)
|
|
|
|
|
- **Framework**: Laravel Blade + Alpine.js
|
|
|
|
|
- **Styling**: Tailwind CSS + DaisyUI
|
|
|
|
|
- **AJAX**: HTMX (hx-get, hx-post, hx-delete)
|
|
|
|
|
- **Modal**: DaisyUI modal 컴포넌트
|
|
|
|
|
|
|
|
|
|
### 4.2 Backend (MNG)
|
|
|
|
|
- **Framework**: Laravel 12
|
|
|
|
|
- **ORM**: Eloquent
|
2025-12-24 08:54:52 +09:00
|
|
|
- **DB**: MySQL (samdb)
|
2025-12-22 16:37:45 +09:00
|
|
|
- **Auth**: Session 기반
|
|
|
|
|
|
|
|
|
|
### 4.3 API 연동
|
|
|
|
|
- MNG 내부 API (`/api/admin/quote-formulas/*`)
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
2025-12-24 08:54:52 +09:00
|
|
|
## 5. 검증 계획
|
2025-12-22 16:37:45 +09:00
|
|
|
|
2025-12-24 08:54:52 +09:00
|
|
|
### 5.1 시뮬레이터 테스트
|
2025-12-22 16:37:45 +09:00
|
|
|
```
|
|
|
|
|
입력: W0=3000, H0=2500
|
|
|
|
|
예상 결과:
|
|
|
|
|
- CASE: PT-CASE-3600 (S=3270)
|
|
|
|
|
- GR: PT-GR-3000 (H1=2770)
|
|
|
|
|
- MOTOR: PT-MOTOR-150 (K=41.21kg)
|
|
|
|
|
```
|
|
|
|
|
|
2025-12-24 08:54:52 +09:00
|
|
|
### 5.2 CRUD 테스트
|
2025-12-22 16:37:45 +09:00
|
|
|
- 범위 추가/수정/삭제 후 시뮬레이터 결과 확인
|
|
|
|
|
- 품목 가격 변경 후 합계 확인
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
2025-12-24 08:54:52 +09:00
|
|
|
## 6. 참고 자료
|
2025-12-22 16:37:45 +09:00
|
|
|
|
2025-12-24 08:54:52 +09:00
|
|
|
### 6.1 파일 위치 (MNG)
|
2025-12-22 16:37:45 +09:00
|
|
|
```
|
|
|
|
|
mng/
|
|
|
|
|
├── app/Http/Controllers/
|
|
|
|
|
│ ├── QuoteFormulaController.php
|
2025-12-24 08:54:52 +09:00
|
|
|
│ └── Api/Admin/Quote/
|
|
|
|
|
│ ├── QuoteFormulaController.php
|
|
|
|
|
│ ├── QuoteFormulaRangeController.php
|
|
|
|
|
│ ├── QuoteFormulaMappingController.php
|
|
|
|
|
│ ├── QuoteFormulaItemController.php
|
|
|
|
|
│ └── QuoteFormulaCategoryController.php
|
2025-12-22 16:37:45 +09:00
|
|
|
├── app/Services/Quote/
|
2025-12-24 08:54:52 +09:00
|
|
|
│ ├── QuoteFormulaService.php
|
|
|
|
|
│ ├── QuoteFormulaRangeService.php
|
|
|
|
|
│ ├── QuoteFormulaMappingService.php
|
|
|
|
|
│ ├── QuoteFormulaItemService.php
|
|
|
|
|
│ └── QuoteFormulaCategoryService.php
|
2025-12-22 16:37:45 +09:00
|
|
|
├── app/Models/Quote/
|
|
|
|
|
│ ├── QuoteFormula.php
|
|
|
|
|
│ ├── QuoteFormulaCategory.php
|
|
|
|
|
│ ├── QuoteFormulaRange.php
|
|
|
|
|
│ ├── QuoteFormulaMapping.php
|
|
|
|
|
│ └── QuoteFormulaItem.php
|
|
|
|
|
└── resources/views/quote-formulas/
|
|
|
|
|
├── index.blade.php
|
|
|
|
|
├── create.blade.php
|
|
|
|
|
├── edit.blade.php
|
2025-12-24 08:54:52 +09:00
|
|
|
├── simulator.blade.php
|
|
|
|
|
└── partials/
|
|
|
|
|
├── basic-info-tab.blade.php
|
|
|
|
|
├── ranges-tab.blade.php
|
|
|
|
|
├── mappings-tab.blade.php
|
|
|
|
|
└── items-tab.blade.php
|
2025-12-22 16:37:45 +09:00
|
|
|
```
|
|
|
|
|
|
2025-12-24 08:54:52 +09:00
|
|
|
### 6.2 API 시더 위치
|
2025-12-22 16:37:45 +09:00
|
|
|
```
|
|
|
|
|
api/database/seeders/
|
|
|
|
|
├── QuoteFormulaCategorySeeder.php
|
|
|
|
|
├── QuoteFormulaSeeder.php
|
|
|
|
|
└── QuoteFormulaItemSeeder.php
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
2025-12-24 08:54:52 +09:00
|
|
|
## 7. 코딩 컨벤션 및 예시 코드
|
2025-12-22 16:37:45 +09:00
|
|
|
|
2025-12-24 08:54:52 +09:00
|
|
|
### 7.1 API Controller 패턴 (MNG)
|
2025-12-22 16:37:45 +09:00
|
|
|
|
|
|
|
|
```php
|
|
|
|
|
<?php
|
|
|
|
|
// 파일: app/Http/Controllers/Api/Admin/Quote/QuoteFormulaRangeController.php
|
|
|
|
|
|
|
|
|
|
namespace App\Http\Controllers\Api\Admin\Quote;
|
|
|
|
|
|
|
|
|
|
use App\Http\Controllers\Controller;
|
|
|
|
|
use App\Services\Quote\QuoteFormulaRangeService;
|
|
|
|
|
use Illuminate\Http\JsonResponse;
|
|
|
|
|
use Illuminate\Http\Request;
|
|
|
|
|
|
|
|
|
|
class QuoteFormulaRangeController extends Controller
|
|
|
|
|
{
|
|
|
|
|
public function __construct(
|
|
|
|
|
private readonly QuoteFormulaRangeService $rangeService
|
|
|
|
|
) {}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 범위 목록 조회
|
|
|
|
|
*/
|
|
|
|
|
public function index(int $formulaId): JsonResponse
|
|
|
|
|
{
|
|
|
|
|
$ranges = $this->rangeService->getRangesByFormula($formulaId);
|
|
|
|
|
|
|
|
|
|
return response()->json([
|
|
|
|
|
'success' => true,
|
|
|
|
|
'data' => $ranges,
|
|
|
|
|
]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 범위 생성
|
|
|
|
|
*/
|
|
|
|
|
public function store(Request $request, int $formulaId): JsonResponse
|
|
|
|
|
{
|
|
|
|
|
$validated = $request->validate([
|
|
|
|
|
'min_value' => 'nullable|numeric',
|
|
|
|
|
'max_value' => 'nullable|numeric',
|
|
|
|
|
'condition_variable' => 'required|string|max:50',
|
|
|
|
|
'result_value' => 'required|string',
|
|
|
|
|
'result_type' => 'in:fixed,formula',
|
|
|
|
|
'sort_order' => 'nullable|integer',
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
$range = $this->rangeService->createRange($formulaId, $validated);
|
|
|
|
|
|
|
|
|
|
return response()->json([
|
|
|
|
|
'success' => true,
|
|
|
|
|
'message' => '범위가 추가되었습니다.',
|
|
|
|
|
'data' => $range,
|
|
|
|
|
]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 범위 수정
|
|
|
|
|
*/
|
|
|
|
|
public function update(Request $request, int $formulaId, int $rangeId): JsonResponse
|
|
|
|
|
{
|
|
|
|
|
$validated = $request->validate([
|
|
|
|
|
'min_value' => 'nullable|numeric',
|
|
|
|
|
'max_value' => 'nullable|numeric',
|
|
|
|
|
'result_value' => 'required|string',
|
|
|
|
|
'result_type' => 'in:fixed,formula',
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
$this->rangeService->updateRange($rangeId, $validated);
|
|
|
|
|
|
|
|
|
|
return response()->json([
|
|
|
|
|
'success' => true,
|
|
|
|
|
'message' => '범위가 수정되었습니다.',
|
|
|
|
|
]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 범위 삭제
|
|
|
|
|
*/
|
|
|
|
|
public function destroy(int $formulaId, int $rangeId): JsonResponse
|
|
|
|
|
{
|
|
|
|
|
$this->rangeService->deleteRange($rangeId);
|
|
|
|
|
|
|
|
|
|
return response()->json([
|
|
|
|
|
'success' => true,
|
|
|
|
|
'message' => '범위가 삭제되었습니다.',
|
|
|
|
|
]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 순서 변경
|
|
|
|
|
*/
|
|
|
|
|
public function reorder(Request $request, int $formulaId): JsonResponse
|
|
|
|
|
{
|
|
|
|
|
$validated = $request->validate([
|
|
|
|
|
'range_ids' => 'required|array',
|
|
|
|
|
'range_ids.*' => 'integer',
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
$this->rangeService->reorder($validated['range_ids']);
|
|
|
|
|
|
|
|
|
|
return response()->json([
|
|
|
|
|
'success' => true,
|
|
|
|
|
'message' => '순서가 변경되었습니다.',
|
|
|
|
|
]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
2025-12-24 08:54:52 +09:00
|
|
|
### 7.2 Service 패턴 (MNG)
|
2025-12-22 16:37:45 +09:00
|
|
|
|
|
|
|
|
```php
|
|
|
|
|
<?php
|
|
|
|
|
// 파일: app/Services/Quote/QuoteFormulaRangeService.php
|
|
|
|
|
|
|
|
|
|
namespace App\Services\Quote;
|
|
|
|
|
|
|
|
|
|
use App\Models\Quote\QuoteFormulaRange;
|
|
|
|
|
use Illuminate\Support\Collection;
|
|
|
|
|
|
|
|
|
|
class QuoteFormulaRangeService
|
|
|
|
|
{
|
|
|
|
|
/**
|
|
|
|
|
* 수식별 범위 조회
|
|
|
|
|
*/
|
|
|
|
|
public function getRangesByFormula(int $formulaId): Collection
|
|
|
|
|
{
|
|
|
|
|
return QuoteFormulaRange::where('formula_id', $formulaId)
|
|
|
|
|
->orderBy('sort_order')
|
|
|
|
|
->get();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 범위 생성
|
|
|
|
|
*/
|
|
|
|
|
public function createRange(int $formulaId, array $data): QuoteFormulaRange
|
|
|
|
|
{
|
|
|
|
|
$data['formula_id'] = $formulaId;
|
|
|
|
|
|
|
|
|
|
// 순서 자동 설정
|
|
|
|
|
if (!isset($data['sort_order'])) {
|
|
|
|
|
$maxOrder = QuoteFormulaRange::where('formula_id', $formulaId)->max('sort_order') ?? 0;
|
|
|
|
|
$data['sort_order'] = $maxOrder + 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return QuoteFormulaRange::create($data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 범위 수정
|
|
|
|
|
*/
|
|
|
|
|
public function updateRange(int $rangeId, array $data): QuoteFormulaRange
|
|
|
|
|
{
|
|
|
|
|
$range = QuoteFormulaRange::findOrFail($rangeId);
|
|
|
|
|
$range->update($data);
|
|
|
|
|
|
|
|
|
|
return $range->fresh();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 범위 삭제
|
|
|
|
|
*/
|
|
|
|
|
public function deleteRange(int $rangeId): void
|
|
|
|
|
{
|
|
|
|
|
QuoteFormulaRange::destroy($rangeId);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 순서 변경
|
|
|
|
|
*/
|
|
|
|
|
public function reorder(array $rangeIds): void
|
|
|
|
|
{
|
|
|
|
|
foreach ($rangeIds as $order => $id) {
|
|
|
|
|
QuoteFormulaRange::where('id', $id)->update(['sort_order' => $order + 1]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
2025-12-24 08:54:52 +09:00
|
|
|
### 7.3 API 응답 형식
|
2025-12-22 16:37:45 +09:00
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
// 성공 응답
|
|
|
|
|
{
|
|
|
|
|
"success": true,
|
|
|
|
|
"message": "범위가 추가되었습니다.",
|
|
|
|
|
"data": { ... }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 실패 응답
|
|
|
|
|
{
|
|
|
|
|
"success": false,
|
|
|
|
|
"message": "이미 사용 중인 변수명입니다."
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 목록 응답
|
|
|
|
|
{
|
|
|
|
|
"success": true,
|
|
|
|
|
"data": [
|
|
|
|
|
{
|
|
|
|
|
"id": 1,
|
|
|
|
|
"formula_id": 5,
|
|
|
|
|
"min_value": "0.0000",
|
|
|
|
|
"max_value": "150.0000",
|
|
|
|
|
"condition_variable": "K",
|
|
|
|
|
"result_value": "{\"value\":\"150K\",\"item_code\":\"PT-MOTOR-150\"}",
|
|
|
|
|
"result_type": "fixed",
|
|
|
|
|
"sort_order": 1
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
2025-12-24 08:54:52 +09:00
|
|
|
## 8. 체크리스트 (완료)
|
2025-12-22 16:37:45 +09:00
|
|
|
|
2025-12-24 08:54:52 +09:00
|
|
|
### 개발 완료 확인
|
2025-12-22 16:37:45 +09:00
|
|
|
|
2025-12-24 08:54:52 +09:00
|
|
|
- [x] mng 프로젝트 디렉토리: `/Users/hskwon/Works/@KD_SAM/SAM/mng`
|
|
|
|
|
- [x] `QuoteFormulaRangeController.php` 생성
|
|
|
|
|
- [x] `QuoteFormulaRangeService.php` 생성
|
|
|
|
|
- [x] `QuoteFormulaMappingController.php` 생성
|
|
|
|
|
- [x] `QuoteFormulaMappingService.php` 생성
|
|
|
|
|
- [x] `QuoteFormulaItemController.php` 생성
|
|
|
|
|
- [x] `QuoteFormulaItemService.php` 생성
|
|
|
|
|
- [x] `routes/api.php`에 라우트 추가
|
|
|
|
|
- [x] `edit.blade.php` 탭 구조로 수정
|
|
|
|
|
- [x] `partials/ranges-tab.blade.php` 생성
|
|
|
|
|
- [x] `partials/mappings-tab.blade.php` 생성
|
|
|
|
|
- [x] `partials/items-tab.blade.php` 생성
|
2025-12-22 16:37:45 +09:00
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
2025-12-24 08:54:52 +09:00
|
|
|
*문서 버전*: 2.0
|
2025-12-22 16:37:45 +09:00
|
|
|
*작성자*: Claude Code
|
|
|
|
|
*검토자*: -
|
2025-12-24 08:54:52 +09:00
|
|
|
*최종 업데이트*: 2025-12-22 (Phase 1-3 완료, 5130 연동 제거)
|