docs: [bending] 절곡품 관리 개발 완료 상태 업데이트
- step1: 데이터 임포트 완료 (170+60건), artisan 커맨드 7개 실행 결과 - step2: API 12개 엔드포인트 완료, item_category 필수 필터 추가 - step3: MNG 샘플 완료 (4개 메뉴, 이미지 473건) - step4: React 구현 가이드 전면 작성 (API 응답 구조, 컴포넌트 설계, 실무 노트) - 코드 체계 변경 불가 사유, 265vs170 차이 설명, 운영 전 정리 항목 추가
This commit is contained in:
@@ -42,22 +42,42 @@ SAM은 절곡품의 "계산과 조합"(BendingInfoBuilder/PrefixResolver)은 잘
|
||||
|
||||
---
|
||||
|
||||
## 작업 순서
|
||||
## 작업 순서 및 진행 상태
|
||||
|
||||
```
|
||||
Step 1 (DB분석) → Step 2 (API) → Step 3 (MNG 화면) → Step 4 (React 연동)
|
||||
레거시 매핑 options 확장 Blade + HTMX 견적 이미지
|
||||
+ 데이터 정리 + 엔드포인트 + 메뉴 등록
|
||||
✅ 완료 ✅ 완료 ✅ 완료 (샘플용) ⬜ 미착수
|
||||
```
|
||||
|
||||
상세 계획: 아래 문서 참조
|
||||
| 문서 | 내용 | 상태 |
|
||||
|------|------|:---:|
|
||||
| `step1-데이터분석.md` | 레거시 매핑 + options 확장 | ✅ 완료 |
|
||||
| `step2-API.md` | API 엔드포인트 + 컨트롤러 설계 | ✅ 완료 |
|
||||
| `step3-MNG화면.md` | Blade 뷰 + HTMX + 메뉴 등록 | ✅ 완료 |
|
||||
| `step4-React연동.md` | React 운영 화면 구현 | ⬜ 미착수 |
|
||||
|
||||
| 문서 | 내용 |
|
||||
|------|------|
|
||||
| `step1-데이터분석.md` | 레거시 매핑 + options 확장 |
|
||||
| `step2-API.md` | API 엔드포인트 + 컨트롤러 설계 |
|
||||
| `step3-MNG화면.md` | Blade 뷰 + HTMX + 메뉴 등록 |
|
||||
| `step4-React연동.md` | 견적 페이지 이미지 컴포넌트 |
|
||||
### 완료된 작업 (2026-03-16~17)
|
||||
|
||||
**Step 1 완료:**
|
||||
- `bending:fill-options` — BD-* prefix/분류 속성 자동 보강 (170건)
|
||||
- `bending:import-legacy` — chandj 전개도(bendingData) 임포트 (139/170건)
|
||||
- `guiderail:import-legacy` — chandj guiderail 20건 임포트
|
||||
- `bending-product:import-legacy` — chandj shutterbox 30건 + bottombar 10건 임포트
|
||||
|
||||
**Step 2 완료:**
|
||||
- `BendingItemController` — CRUD + filters + pagination (6 엔드포인트)
|
||||
- `GuiderailModelController` — CRUD + filters (6 엔드포인트, 3개 카테고리 통합)
|
||||
- `BendingItemResource` / `GuiderailModelResource` — API 응답 포맷
|
||||
- `FormRequest` — Index/Store/Update 유효성 검증
|
||||
- `ApiKeyMiddleware` — bending/guiderail/files 화이트리스트
|
||||
|
||||
**Step 3 완료 (MNG 샘플용):**
|
||||
- 기초관리: 목록(13컬럼) + 폼(기본정보12필드 + 케이스전용5필드 + 절곡테이블 + 이미지업로드)
|
||||
- 절곡품: 가이드레일/케이스/하단마감재 별도 메뉴 + 타입별 헤더 분기
|
||||
- 절곡품 폼: 부품 추가(기초관리 검색 모달) + 삭제 + 수량/품명/재질 편집 + 절곡테이블 inline 편집
|
||||
- 작업지시서: 레거시 포맷 인쇄 페이지 (`/print`)
|
||||
- 파일: FileViewController (API R2 프록시) + 이미지 업로드/표시
|
||||
- DB 메뉴: 기초관리 + 절곡품 + 케이스 + 하단마감재 (4개)
|
||||
|
||||
---
|
||||
|
||||
@@ -271,7 +291,7 @@ AList: [false,false,false...] sum:21, color:false, aAngle:false },
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────────────────────────────┐
|
||||
│ MNG 사이드바 │
|
||||
│ MNG │
|
||||
│ │
|
||||
│ 생산 관리 │
|
||||
│ ├─ 품목기준 필드 관리 │
|
||||
|
||||
@@ -103,14 +103,58 @@
|
||||
| `search_keyword` | varchar(50) | 검색어 |
|
||||
| `material_summary` | text | 재질별 폭합 |
|
||||
|
||||
### 1-1b. 추가 파악 필요
|
||||
### 1-1b. 추가 분석 결과 (완료)
|
||||
|
||||
| 작업 | 대상 | 비고 |
|
||||
|------|------|------|
|
||||
| BendingInfoBuilder.php 지원 모델 추출 | 코드 분석 | 기존 로직 파악 |
|
||||
| PrefixResolver.php PREFIX 규칙 추출 | 코드 분석 | 기존 로직 파악 |
|
||||
| bendingfee 82건 구조 | 절곡 단가 — SAM 연동 필요 여부 | |
|
||||
| bendingmap 9건 구조 | 매핑 용도 확인 | |
|
||||
#### BendingInfoBuilder 지원 모델
|
||||
|
||||
`getMaterialMapping()` (line 924~960)에서 정의:
|
||||
|
||||
| 그룹 | 모델 | 마감재 재질 | 본체 재질 |
|
||||
|------|------|-----------|----------|
|
||||
| Group 1 (SUS 전용) | KQTS01, KSS01, KSS02 | SUS 1.2T | EGI 1.55T |
|
||||
| Group 2 (철재) | KTE01 | EGI 1.55T (SUS마감 시 +SUS 1.2T) | EGI 1.55T |
|
||||
| Group 3 (기타) | KSE01, KWE01 등 | EGI 1.55T (SUS마감 시 +SUS 1.2T) | EGI 1.55T |
|
||||
|
||||
**미지원 모델**: KDSS01, 스크린비인정 (guiderail 테이블에는 있지만 Builder에 미등록)
|
||||
|
||||
#### 🔴 CRITICAL: BOM 카테고리 분류가 한글 BD 코드 의존
|
||||
|
||||
`BendingInfoBuilder.categorizeBomItem()` (line 401~434):
|
||||
|
||||
```php
|
||||
str_starts_with($code, 'BD-가이드레일') → guideRail
|
||||
str_starts_with($code, 'BD-케이스') → shutterBox_case
|
||||
str_starts_with($code, 'BD-마구리') → shutterBox_finCover
|
||||
str_starts_with($code, 'BD-L-BAR') → detail_lbar
|
||||
str_starts_with($code, 'BD-보강평철') → detail_reinforce
|
||||
```
|
||||
|
||||
**→ BD-한글 패턴(58건)을 PREFIX로 변환하면 BOM 분류 로직이 깨짐!**
|
||||
**→ 결정: 한글 코드는 유지하고, `options`에 속성만 추가하는 방식으로 진행**
|
||||
|
||||
#### PrefixResolver PREFIX 규칙
|
||||
|
||||
| 카테고리 | partType → prefix | 비고 |
|
||||
|----------|-------------------|------|
|
||||
| **가이드레일(벽면)** | finish→RS/RE, body→RM, c_type→RC, d_type→RD, extra→YY, base→XX | KTE body→RT |
|
||||
| **가이드레일(측면)** | finish→SS/SE, body→SM, c_type→SC, d_type→SD, extra→YY, base→XX | KTE body→ST |
|
||||
| **하단마감재** | main→BE/BS/TS, lbar→LA, reinforce→HH, extra→YY | 재질 기반 분기 |
|
||||
| **셔터박스** | front→CF, lintel→CL, inspection→CP, rear_corner→CB, top/fin→XX | 고정 |
|
||||
| **연기차단재** | smoke→GI | 전용 길이코드(53/54/83/84) |
|
||||
|
||||
#### bendingfee (82건) — `price_bend` 테이블
|
||||
|
||||
- **용도**: 절곡 BOM 단가 (모델별 단가 JSON)
|
||||
- **구조**: `itemList` (JSON), `registedate`, `is_deleted`
|
||||
- **사용법**: 최신 1건만 사용 (`ORDER BY num DESC LIMIT 1`)
|
||||
- **관련 테이블**: `BDmodels` (모델별 조회)
|
||||
- **SAM 연동**: 1차 제외 (단가 관리는 별도 Phase)
|
||||
|
||||
#### bendingmap (9건)
|
||||
|
||||
- **용도**: 절곡품 그룹화/매핑 (생산 현장용)
|
||||
- **컬럼**: prodcode, railtype, boxsize, boxexit, frontbottom, railwidth, search_tag
|
||||
- **SAM 연동**: 1차 제외 (그룹화는 options.item_bending으로 대체)
|
||||
|
||||
### 1-2. SAM BD 품목 현황 (170건)
|
||||
|
||||
@@ -173,9 +217,64 @@ num:101 본체 EGI 120*70 ↔ BD-RM-30 (PREFIX-LEN — 길이 기준)
|
||||
```
|
||||
|
||||
**핵심 결정사항**:
|
||||
- BD-한글 패턴(58건)을 BD-PREFIX-LEN으로 통일할지
|
||||
- 레거시 265건 중 SAM에 없는 항목 → 신규 생성 범위
|
||||
- 매핑 애매한 항목 → 사업부 확인 목록
|
||||
- ~~BD-한글 패턴(58건)을 BD-PREFIX 으로 통일~~ **취소** — BendingInfoBuilder.categorizeBomItem()이 한글 코드 의존
|
||||
- **BD-한글 패턴(58건)은 코드 유지, `options`에 속성만 추가**
|
||||
- BD-PREFIX-LEN(112건)도 options 속성 보강 (item_sep, item_bending 등)
|
||||
- 레거시 265건 중 SAM에 없는 항목 → 신규 생성 범위 확인 필요
|
||||
|
||||
### 🔴 chandj 265건 vs SAM 170건 차이 설명
|
||||
|
||||
**구조가 다르지만 데이터는 동일**:
|
||||
|
||||
```
|
||||
chandj 265건 = 절곡 "형상" (규격별 1건)
|
||||
예: 마감재 SUS 120*70 → 전개도 [10,11,110,30,15,15,15] ← 1건
|
||||
|
||||
SAM 170건 = 절곡 "제품" (길이별 확장)
|
||||
예: BD-RS-24 (2438mm) ┐
|
||||
BD-RS-30 (3000mm) │ 모두 같은 전개도
|
||||
BD-RS-35 (3500mm) │ (chandj 1건의 형상을 공유)
|
||||
BD-RS-40 (4000mm) │
|
||||
BD-RS-43 (4300mm) ┘ ← 5건
|
||||
```
|
||||
|
||||
| 항목 | chandj | SAM | 관계 |
|
||||
|------|:---:|:---:|------|
|
||||
| 가이드레일 부품 | 71건 (규격별) | 74건 (길이별) | 1:N (형상 1 → 길이 여러 개) |
|
||||
| 케이스 부품 | 160건 (규격×크기별) | 34건 (PREFIX-LEN) | N:1 (여러 규격 → 모델 components로 통합) |
|
||||
| 하단마감재 부품 | 11건 | 21건 | 1:N |
|
||||
| 마구리/기타 | 23건 | 41건 | 1:N |
|
||||
|
||||
**누락 없는 이유**:
|
||||
- chandj 265건의 **전개도 데이터**는 SAM 170건의 `options.bendingData`에 포함 (139건 매핑)
|
||||
- chandj에서 SAM에 직접 없는 부품들은 **모델(GR/SB/BB)의 components**에서 `legacy_bending_num`으로 참조
|
||||
- 추가 임포트 **불필요**
|
||||
|
||||
---
|
||||
|
||||
### 🔴 코드 체계 변경 불가 사유
|
||||
|
||||
**BD 코드(절곡 부품)는 변경 금지:**
|
||||
|
||||
`BendingInfoBuilder.categorizeBomItem()` (line 401~434)에서 코드 접두사 기반으로 BOM 카테고리 분류:
|
||||
```php
|
||||
str_starts_with($code, 'BD-가이드레일') → guideRail
|
||||
str_starts_with($code, 'BD-케이스') → shutterBox_case
|
||||
str_starts_with($code, 'BD-마구리') → shutterBox_finCover
|
||||
str_starts_with($code, 'BD-L-BAR') → detail_lbar
|
||||
str_starts_with($code, 'BD-보강평철') → detail_reinforce
|
||||
```
|
||||
BD-PREFIX-LEN 코드(BD-RS-30 등)도 `PrefixResolver` + LOT 재고에서 참조.
|
||||
→ **견적→BOM→작업지시 전체 흐름이 깨지므로 코드 변경 불가**
|
||||
|
||||
**모델 코드(GR/SB/BB)는 변경 가능** — 신규 생성이라 참조 없음:
|
||||
|
||||
| 코드 | 카테고리 | 변경 가능 | 이유 |
|
||||
|------|---------|:---:|------|
|
||||
| `BD-*` (170건) | BENDING | ❌ | BendingInfoBuilder + PrefixResolver + LOT 의존 |
|
||||
| `GR-*` (20건) | GUIDERAIL_MODEL | ✅ | 신규, 참조 없음 |
|
||||
| `SB-*` (30건) | SHUTTERBOX_MODEL | ✅ | 신규, 참조 없음 |
|
||||
| `BB-*` (10건) | BOTTOMBAR_MODEL | ✅ | 신규, 참조 없음 |
|
||||
|
||||
---
|
||||
|
||||
@@ -247,36 +346,45 @@ num:101 본체 EGI 120*70 ↔ BD-RM-30 (PREFIX-LEN — 길이 기준)
|
||||
→ 레거시 inputList/bendingrateList/sumList/colorList
|
||||
```
|
||||
|
||||
### 2-3. artisan command
|
||||
### 2-3. artisan command (✅ 전체 실행 완료)
|
||||
|
||||
```bash
|
||||
# 1단계
|
||||
php artisan bending:fill-options --dry-run # 미리보기
|
||||
php artisan bending:fill-options # 실행
|
||||
# 1단계: prefix/분류 속성 보강 (170건)
|
||||
php artisan bending:fill-options # ✅ 완료
|
||||
|
||||
# 2단계
|
||||
php artisan bending:import-legacy --dry-run
|
||||
php artisan bending:import-legacy
|
||||
# 2단계+3단계: 전개도(bendingData) + 속성 임포트 (139/170건)
|
||||
php artisan bending:import-legacy # ✅ 완료 (31건 chandj 원본 없음)
|
||||
|
||||
# 3단계 (2단계에 포함 가능)
|
||||
# 가이드레일 모델 임포트 (20건)
|
||||
php artisan guiderail:import-legacy # ✅ 완료
|
||||
|
||||
# 케이스+하단마감재 모델 임포트 (30+10건)
|
||||
php artisan bending-product:import-legacy # ✅ 완료
|
||||
|
||||
# 이미지 마이그레이션
|
||||
php artisan bending:import-images # ✅ 기초관리 부품 이미지 138건
|
||||
php artisan bending-model:import-images # ✅ 모델 부품별 이미지 275건
|
||||
php artisan bending-model:import-assembly-images # ✅ 결합형태 이미지 60건
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. 회귀 테스트 (필수)
|
||||
## 3. 회귀 테스트
|
||||
|
||||
| 테스트 | 확인 내용 | 판정 기준 |
|
||||
|--------|----------|----------|
|
||||
| BendingInfoBuilder | 견적 BOM 계산 결과 | 변경 전/후 동일 |
|
||||
| PrefixResolver | BD 코드 자동 결정 | 변경 전/후 동일 |
|
||||
| 작업지시서 절곡 섹션 | GuideRailSection 렌더링 | 정상 표시 |
|
||||
| 절곡 검사 | inspection-config API | 정상 응답 |
|
||||
| 견적→수주→작업지시 | 전체 흐름 1건 | 오류 없음 |
|
||||
| 테스트 | 확인 내용 | 판정 기준 | 상태 |
|
||||
|--------|----------|----------|:---:|
|
||||
| BendingInfoBuilder | 견적 BOM 계산 결과 | 변경 전/후 동일 | ⚠️ BD 코드 무변경이므로 영향 없음 |
|
||||
| PrefixResolver | BD 코드 자동 결정 | 변경 전/후 동일 | ⚠️ 무변경 |
|
||||
| 작업지시서 절곡 섹션 | GuideRailSection 렌더링 | 정상 표시 | ⚠️ 무변경 |
|
||||
| CRUD 테스트 | 기초관리/모델 전체 | 생성/조회/수정/삭제 | ✅ 검증 완료 |
|
||||
| 테넌트 격리 | 287 vs 1 데이터 분리 | 각 테넌트 독립 조회 | ✅ 검증 완료 |
|
||||
| 이미지 표시 | R2→API→MNG 프록시 | 정상 표시 | ✅ 검증 완료 |
|
||||
|
||||
---
|
||||
|
||||
## 4. 산출물
|
||||
|
||||
- [ ] 매핑 테이블 (레거시 num ↔ SAM item_id)
|
||||
- [ ] artisan command (bending:fill-options, bending:import-legacy)
|
||||
- [ ] 회귀 테스트 결과
|
||||
- [x] 매핑 테이블 (legacy_bending_num으로 chandj↔SAM 연결)
|
||||
- [x] artisan command 7개 (위 목록 참조)
|
||||
- [x] CRUD 검증 완료
|
||||
- [x] 이미지 마이그레이션 완료 (총 473건 R2 업로드)
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
# Step 2: API 엔드포인트
|
||||
# Step 2: API 엔드포인트 ✅ 완료
|
||||
|
||||
> **프로젝트**: API (`sam/api`)
|
||||
> **선행 조건**: Step 1 완료
|
||||
> **상태**: ✅ 구현 완료 (2026-03-16~17)
|
||||
> **참조**: `standards/api-rules.md`, `standards/options-column-policy.md`, `rules/item-policy.md`
|
||||
|
||||
---
|
||||
@@ -58,21 +59,41 @@
|
||||
?item_sep=스크린 # 대분류
|
||||
&item_bending=가이드레일 # 중분류
|
||||
&material=SUS # 재질 (부분 매칭)
|
||||
&model_UA=인정 # 인정여부
|
||||
&model_UA=인정 # 인정여부
|
||||
&search=KSS01 # 통합 검색 (이름/검색어/규격)
|
||||
&page=1&size=50 # 페이지네이션 (size — api-rules 기준)
|
||||
```
|
||||
|
||||
### 2-2. 절곡품 모델 관리 (조합)
|
||||
### 2-2. 절곡품 모델 관리 (가이드레일/케이스/하단마감재 통합)
|
||||
|
||||
| Method | Path | 설명 | 비고 |
|
||||
|--------|------|------|------|
|
||||
| GET | `/api/v1/guiderail-models` | 모델 목록 (타입별) | ?type=가이드레일 |
|
||||
| GET | `/api/v1/guiderail-models` | 모델 목록 | `?item_category=` 필수 |
|
||||
| GET | `/api/v1/guiderail-models/filters` | 필터 옵션 | |
|
||||
| GET | `/api/v1/guiderail-models/{id}` | 모델 상세 (부품 조합 + 재질별 폭합) | |
|
||||
| POST | `/api/v1/guiderail-models` | 모델 등록 | |
|
||||
| PUT | `/api/v1/guiderail-models/{id}` | 모델 수정 | |
|
||||
| DELETE | `/api/v1/guiderail-models/{id}` | 모델 삭제 (soft delete) | |
|
||||
|
||||
**카테고리 구분** (필수 파라미터):
|
||||
|
||||
| item_category | 메뉴 | 건수 | 코드 패턴 |
|
||||
|--------------|------|:---:|---------|
|
||||
| `GUIDERAIL_MODEL` | 가이드레일 | 20 | `GR-KSS01-벽면형-SUS` |
|
||||
| `SHUTTERBOX_MODEL` | 케이스 | 30 | `SB-500*350-밑면` |
|
||||
| `BOTTOMBAR_MODEL` | 하단마감재 | 10 | `BB-KSS01-SUS` |
|
||||
|
||||
**필터 파라미터** (GET /api/v1/guiderail-models):
|
||||
```
|
||||
?item_category=GUIDERAIL_MODEL # 필수: 카테고리 구분
|
||||
&item_sep=스크린 # 대분류
|
||||
&model_UA=인정 # 인정여부
|
||||
&check_type=벽면형 # 형상 (가이드레일만)
|
||||
&model_name=KSS01 # 모델명
|
||||
&search=KSS01 # 통합 검색
|
||||
&page=1&size=50
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. 구현 파일 구조
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
# Step 3: MNG 관리 화면 (Blade + HTMX)
|
||||
# Step 3: MNG 관리 화면 (Blade + HTMX) ✅ 완료
|
||||
|
||||
> **프로젝트**: MNG (`sam/mng`)
|
||||
> **선행 조건**: Step 2 (API 엔드포인트) 완료
|
||||
> **상태**: ✅ 샘플 구현 완료 (2026-03-16~17)
|
||||
> **참조**: 프로토타입 `SAM/work/절곡/`, MNG 기존 Blade 패턴
|
||||
|
||||
---
|
||||
@@ -293,7 +294,7 @@ class FileViewController extends Controller
|
||||
┌───────────────────────────────────┬──────────────────┐
|
||||
│ [기본 정보] │ [형상 이미지] │
|
||||
│ 등록일 | 작성자 │ 이미지 업로드 │
|
||||
├───────────────────────────────────┤ │
|
||||
├───────────────────────────────────┤**** │
|
||||
│ [케이스 정보] │ 품목검색어 │
|
||||
│ 가로(폭) × 세로(높이) │ 비고 │
|
||||
│ 전면밑: [50] | 레일폭: [75] │ │
|
||||
|
||||
@@ -1,43 +1,272 @@
|
||||
# Step 4: React 견적 화면 이미지 연동
|
||||
# Step 4: React 절곡품 관리 화면 + 견적 이미지 연동 ⬜ 미착수
|
||||
|
||||
> **프로젝트**: React (`sam/react`)
|
||||
> **선행 조건**: Step 2 (API), Step 3 (MNG에서 데이터 등록 후)
|
||||
> **참조**: 기존 GuideRailSection 컴포넌트
|
||||
> **선행 조건**: Step 2 (API ✅), Step 3 (MNG 샘플 ✅)
|
||||
> **상태**: ⬜ 미착수
|
||||
> **참조**: MNG 샘플 화면, 기존 GuideRailSection 컴포넌트
|
||||
|
||||
---
|
||||
|
||||
## 1. 목적
|
||||
## 1. 개요
|
||||
|
||||
견적 페이지(`/sales/quote-management/new`)에서 가이드레일 모델 선택 시
|
||||
전개도 이미지 + 부품 조합 테이블을 표시한다.
|
||||
MNG에서 샘플로 구현/검증한 절곡품 관리 기능을 React 운영 화면으로 이관한다.
|
||||
모든 API 엔드포인트는 Step 2에서 완료되어 있으므로, **프론트엔드 구현만** 필요.
|
||||
|
||||
---
|
||||
|
||||
## 2. 현재 흐름
|
||||
## 2. API 엔드포인트 (Step 2 완료 — 그대로 사용)
|
||||
|
||||
### 2-1. 기초관리 (절곡 부품)
|
||||
```
|
||||
제품 선택 → BOM 계산 (BendingInfoBuilder)
|
||||
→ product_code, finish_material 확정
|
||||
→ 가이드레일 모델 결정
|
||||
→ 텍스트만 표시 ❌ 이미지 없음
|
||||
GET /api/v1/bending-items ← 목록 (필터/검색/페이지네이션)
|
||||
GET /api/v1/bending-items/filters ← 필터 옵션 (분류/재질/모델 distinct)
|
||||
GET /api/v1/bending-items/{id} ← 상세 (options 전체)
|
||||
POST /api/v1/bending-items ← 등록
|
||||
PUT /api/v1/bending-items/{id} ← 수정
|
||||
DELETE /api/v1/bending-items/{id} ← 삭제 (soft delete)
|
||||
```
|
||||
|
||||
## 3. 목표 흐름
|
||||
|
||||
**응답 구조** (목록):
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"data": {
|
||||
"data": [
|
||||
{
|
||||
"id": 15862, "code": "BD-BE-30",
|
||||
"name": "하단마감재(스크린) EGI 3000mm",
|
||||
"item_type": "PT", "item_category": "BENDING",
|
||||
"item_name": "하단마감재", "item_sep": "스크린",
|
||||
"item_bending": "하단마감재", "item_spec": "60*40",
|
||||
"material": "EGI 1.55T", "model_name": null,
|
||||
"model_UA": "인정", "search_keyword": null,
|
||||
"rail_width": null, "registration_date": "2025-07-21",
|
||||
"author": "개발자", "memo": null,
|
||||
"exit_direction": null, "front_bottom_width": null,
|
||||
"box_width": null, "box_height": null,
|
||||
"bendingData": [
|
||||
{"no":1,"input":15,"rate":"","sum":15,"color":false,"aAngle":false},
|
||||
{"no":2,"input":14,"rate":"-1","sum":28,"color":false,"aAngle":false}
|
||||
],
|
||||
"prefix": "BE", "length_code": "30", "length_mm": 3000,
|
||||
"legacy_bending_num": 288,
|
||||
"width_sum": 193, "bend_count": 5,
|
||||
"created_at": "2026-02-21 19:47:01"
|
||||
}
|
||||
],
|
||||
"current_page": 1, "total": 170, "last_page": 6, "per_page": 30
|
||||
}
|
||||
}
|
||||
```
|
||||
제품 선택 → BOM 계산 (기존 그대로)
|
||||
→ 모델 확정
|
||||
→ GET /api/guiderail-models/{id} 호출 🆕
|
||||
→ GuiderailPreview 컴포넌트 렌더링 🆕
|
||||
├─ 전개도 이미지
|
||||
└─ 부품 조합 테이블 (부품명/재질/수량/전개폭)
|
||||
|
||||
### 2-2. 절곡품 모델 (가이드레일/케이스/하단마감재 통합)
|
||||
```
|
||||
GET /api/v1/guiderail-models ← 모델 목록
|
||||
GET /api/v1/guiderail-models/filters ← 필터 옵션
|
||||
GET /api/v1/guiderail-models/{id} ← 모델 상세 (부품 조합)
|
||||
POST /api/v1/guiderail-models ← 모델 등록
|
||||
PUT /api/v1/guiderail-models/{id} ← 모델 수정
|
||||
DELETE /api/v1/guiderail-models/{id} ← 모델 삭제
|
||||
```
|
||||
|
||||
**카테고리 필터**: `?item_category=GUIDERAIL_MODEL|SHUTTERBOX_MODEL|BOTTOMBAR_MODEL`
|
||||
|
||||
**응답 구조** (상세):
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"data": {
|
||||
"id": 15914, "code": "GR-KDSS01-벽면형-SUS",
|
||||
"name": "KDSS01 벽면형 SUS마감",
|
||||
"item_category": "GUIDERAIL_MODEL",
|
||||
"model_name": "KDSS01", "check_type": "벽면형",
|
||||
"rail_width": 150, "rail_length": 150,
|
||||
"finishing_type": "SUS마감",
|
||||
"item_sep": "스크린", "model_UA": "인정",
|
||||
"components": [
|
||||
{
|
||||
"orderNumber": 1,
|
||||
"itemName": "1번(마감제)", "material": "SUS 1.2T",
|
||||
"quantity": 2, "width_sum": 227,
|
||||
"bendingData": [
|
||||
{"no":1,"input":15,"rate":"0","sum":15,"color":true,"aAngle":false},
|
||||
{"no":2,"input":13,"rate":"0","sum":28,"color":false,"aAngle":false}
|
||||
],
|
||||
"legacy_bending_num": "170"
|
||||
}
|
||||
],
|
||||
"material_summary": {"SUS 1.2T": 599, "EGI 1.55T": 894},
|
||||
"component_count": 4
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2-3. 이미지 (기존 API 재사용)
|
||||
```
|
||||
POST /api/v1/items/{id}/files ← 업로드 (field_key: 'bending_diagram')
|
||||
GET /api/v1/items/{id}/files ← 목록 조회
|
||||
GET /api/v1/files/{id}/view ← 인라인 표시
|
||||
DELETE /api/v1/items/{id}/files/{fileId} ← 삭제
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. 구현 사항
|
||||
## 3. React 화면 구성
|
||||
|
||||
### 4-1. GuiderailPreview 컴포넌트
|
||||
### 3-1. 메뉴 구조 (사이드바)
|
||||
|
||||
```
|
||||
생산 관리
|
||||
├─ ... (기존)
|
||||
└─ 절곡품 관리
|
||||
├─ 기초관리 /bending/base
|
||||
├─ 절곡품 (가이드레일) /bending/products
|
||||
├─ 케이스 /bending/cases
|
||||
└─ 하단마감재 /bending/bottombars
|
||||
```
|
||||
|
||||
### 3-2. 기초관리 화면
|
||||
|
||||
**목록 (`/bending/base`)**:
|
||||
| 컬럼 | API 필드 |
|
||||
|------|---------|
|
||||
| NO | id |
|
||||
| 코드 | code |
|
||||
| 대분류 | item_sep (스크린=파란배지, 철재=주황배지) |
|
||||
| 인정 | model_UA |
|
||||
| 분류 | item_bending |
|
||||
| 품명 | item_name |
|
||||
| 규격 | item_spec |
|
||||
| 재질 | material |
|
||||
| 모델 | model_name |
|
||||
| 폭합 | width_sum |
|
||||
| 절곡수 | bend_count |
|
||||
| 등록일 | created_at |
|
||||
|
||||
**필터**: item_sep, item_bending, material, search (HTMX 실시간 검색)
|
||||
|
||||
**폼 (`/bending/base/{id}/edit`)**:
|
||||
|
||||
기본 정보 (4열 그리드):
|
||||
- 코드*, 이름*, 품명*, 대분류*(select)
|
||||
- 분류*(datalist), 재질*(datalist), 규격, 모델(datalist)
|
||||
- 인정여부(select), 등록일(date), 작성자, 검색어
|
||||
|
||||
케이스 전용 (분류=케이스 시 표시):
|
||||
- 점검구 방향(select), 전면밑(mm), 레일폭(mm), 케이스 너비(mm), 케이스 높이(mm)
|
||||
|
||||
절곡 입력 테이블:
|
||||
- 동적 열 추가/삭제
|
||||
- 행: 입력(number) → 연신율(text) → 연신율후(자동) → 합계(자동) → 음영(checkbox) → A각(checkbox)
|
||||
- 연신율 규칙: `-1` → input-1mm, `1` → input+1mm, 빈값 → 그대로
|
||||
- 폭합계 + 절곡횟수 자동 표시
|
||||
- `bendingData` JSON으로 직렬화하여 API 전송
|
||||
|
||||
이미지: 파일 업로드 + Ctrl+V 클립보드 + 미리보기
|
||||
|
||||
### 3-3. 절곡품 화면 (3가지 타입)
|
||||
|
||||
**목록** (공통 테이블):
|
||||
| 컬럼 | API 필드 |
|
||||
|------|---------|
|
||||
| NO | id |
|
||||
| 모델명 | model_name |
|
||||
| 대분류 | item_sep |
|
||||
| 인정 | model_UA |
|
||||
| 형상 | check_type |
|
||||
| 레일폭×높이 | rail_width × rail_length |
|
||||
| 마감 | finishing_type |
|
||||
| 부품수 | component_count |
|
||||
| 소요자재량 | material_summary |
|
||||
|
||||
**필터**: `item_category`(필수!), item_sep, model_UA, check_type, model_name, search
|
||||
|
||||
> ⚠️ `item_category` 없이 호출하면 3개 카테고리 60건이 섞여서 나옴
|
||||
|
||||
**폼 — 타입별 헤더 차이**:
|
||||
|
||||
| 필드 | 가이드레일 | 케이스 | 하단마감재 |
|
||||
|------|:---:|:---:|:---:|
|
||||
| 등록일/작성자/비고 | ✅ | ✅ | ✅ |
|
||||
| 외형치수 (가로×세로) | ✅ 너비×폭 | ✅ 폭×높이+전면밑+레일폭 | ✅ 폭×높이 |
|
||||
| 대분류 라디오 | ✅ | ❌ | ✅ |
|
||||
| 인정/비인정 라디오 | ✅ | ❌ | ✅ |
|
||||
| 형태 라디오 (벽면/측면) | ✅ | ❌ | ❌ |
|
||||
| 점검구 방향 라디오 | ❌ | ✅ | ❌ |
|
||||
| 모델 select | ✅ | ❌ | ✅ |
|
||||
| 마감 select | ✅ | ❌ | ✅ |
|
||||
| 품목검색어 | ✅ | ✅ | ✅ |
|
||||
|
||||
**절곡 부품 조립 섹션**:
|
||||
- 부품별 절곡 테이블 (inline 편집)
|
||||
- 부품 추가: 기초관리 검색 모달 (필터+체크박스+선택적용)
|
||||
- 부품 삭제: DOM 즉시 제거
|
||||
- 품명/재질/수량 inline 편집
|
||||
- 순서 변경 (위로/아래로)
|
||||
- `components` JSON으로 직렬화하여 API 전송
|
||||
|
||||
**재질별 폭합**: components에서 자동 계산 (`material_summary`)
|
||||
|
||||
**작업지시서 PDF**: 별도 인쇄 페이지 (`/{type}/{id}/print`)
|
||||
- 레거시 포맷: 번호 | 재질 | 절곡치수(합계+음영) | 폭합 | 수량
|
||||
- A각 표시 행
|
||||
- A4 가로 인쇄 최적화
|
||||
|
||||
---
|
||||
|
||||
## 4. React 컴포넌트 구조 (설계안)
|
||||
|
||||
```
|
||||
src/pages/bending/
|
||||
├─ base/
|
||||
│ ├─ BendingBaseList.tsx ← 기초관리 목록
|
||||
│ └─ BendingBaseForm.tsx ← 등록/수정/조회 (mode 분기)
|
||||
├─ products/
|
||||
│ ├─ BendingProductList.tsx ← 절곡품 목록 (category prop으로 3타입 공용)
|
||||
│ ├─ BendingProductForm.tsx ← 등록/수정/조회 (타입별 헤더 분기)
|
||||
│ └─ BendingProductPrint.tsx ← 작업지시서 인쇄
|
||||
├─ components/
|
||||
│ ├─ BendingTable.tsx ← 절곡 입력 테이블 (공용 컴포넌트)
|
||||
│ ├─ BendingSearchModal.tsx ← 기초관리 부품 검색 모달
|
||||
│ ├─ PartListEditor.tsx ← 부품 조립 편집기
|
||||
│ ├─ MaterialSummary.tsx ← 재질별 폭합 표시
|
||||
│ └─ GuiderailPreview.tsx ← 견적 페이지용 미리보기
|
||||
└─ hooks/
|
||||
├─ useBendingItems.ts ← API 호출 훅
|
||||
└─ useGuiderailModels.ts ← API 호출 훅
|
||||
```
|
||||
|
||||
### 4-1. BendingTable 컴포넌트 (핵심)
|
||||
|
||||
```tsx
|
||||
interface BendingData {
|
||||
no: number;
|
||||
input: number;
|
||||
rate: string; // '' | '-1' | '1'
|
||||
sum: number; // 자동 계산
|
||||
color: boolean; // 음영 마킹
|
||||
aAngle: boolean; // A각 표시
|
||||
}
|
||||
|
||||
interface BendingTableProps {
|
||||
data: BendingData[];
|
||||
onChange: (data: BendingData[]) => void;
|
||||
readOnly?: boolean;
|
||||
}
|
||||
```
|
||||
|
||||
### 4-2. BendingSearchModal 컴포넌트
|
||||
|
||||
```tsx
|
||||
interface BendingSearchModalProps {
|
||||
open: boolean;
|
||||
onClose: () => void;
|
||||
onSelect: (items: BendingItem[]) => void;
|
||||
filters?: { item_sep?: string; item_bending?: string; };
|
||||
}
|
||||
```
|
||||
|
||||
### 4-3. GuiderailPreview 컴포넌트 (견적 페이지 연동)
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────┐
|
||||
@@ -46,44 +275,138 @@
|
||||
│ 전개도 이미지 │ 부품 조합 │
|
||||
│ ┌────────────────┐ │ # │ 부품 │ 재질 │ 수량 │
|
||||
│ │ │ │ 1 │ 마감재 │ SUS │ 2 │
|
||||
│ │ (이미지) │ │ 2 │ 본체 │ EGI │ 1 │
|
||||
│ │ (R2 이미지) │ │ 2 │ 본체 │ EGI │ 1 │
|
||||
│ │ │ │ 3 │ C형 │ EGI │ 1 │
|
||||
│ └────────────────┘ │ 4 │ D형 │ EGI │ 1 │
|
||||
│ │ 재질별 폭합 │
|
||||
│ │ SUS: 406 | EGI: 398 │
|
||||
└──────────────────────┴──────────────────────────────┘
|
||||
```
|
||||
|
||||
### 4-2. 삽입 위치
|
||||
---
|
||||
|
||||
견적 페이지에서 BOM 결과 표시 영역 하단 (기존 레이아웃 무변경)
|
||||
## 5. 데이터 현황 (Step 1~3 완료 시점)
|
||||
|
||||
### 4-3. 데이터 흐름
|
||||
|
||||
```
|
||||
BOM 계산 결과 → product_code + finish_material
|
||||
→ API 호출: GET /api/guiderail-models?model={code}&check_type={형상}
|
||||
→ 응답: image_url + components + material_summary
|
||||
→ GuiderailPreview 렌더링
|
||||
```
|
||||
| 항목 | 건수 | 상태 |
|
||||
|------|:---:|:---:|
|
||||
| 기초관리 (BENDING) | 170건 | ✅ |
|
||||
| ├ 전개도 임포트 | 139/170건 | ✅ (31건 chandj 원본 없음) |
|
||||
| 가이드레일 모델 (GUIDERAIL_MODEL) | 20건 | ✅ |
|
||||
| 케이스 모델 (SHUTTERBOX_MODEL) | 30건 | ✅ |
|
||||
| 하단마감재 모델 (BOTTOMBAR_MODEL) | 10건 | ✅ |
|
||||
| DB 메뉴 | 4개 | ✅ |
|
||||
|
||||
---
|
||||
|
||||
## 5. 주의사항
|
||||
## 6. 주의사항
|
||||
|
||||
- 기존 견적 계산 로직 무변경
|
||||
- 기존 GuideRailSection (작업지시서용) 무변경 — 별도 컴포넌트
|
||||
- 이미지 없는 모델: 텍스트만 표시 (graceful degradation)
|
||||
- 모바일 반응형 처리
|
||||
- ✅ 기존 GuideRailSection (작업지시서용) 무변경 — 별도 컴포넌트
|
||||
- ✅ 기존 BendingInfoBuilder / PrefixResolver 무변경
|
||||
- ✅ 이미지 없는 모델: 텍스트만 표시 (graceful degradation)
|
||||
- ✅ MNG는 **샘플 확인용** — React가 **운영용**
|
||||
- ✅ MNG/React 모두 동일한 API 엔드포인트 호출
|
||||
- ⚠️ tenant_id 287 하드코딩 → React에서는 Sanctum Bearer 토큰으로 자동 해결
|
||||
- ⚠️ **인증 전환**: React 작업 시 `ApiKeyMiddleware.php`의 `allowWithoutAuth`에서 bending 관련 4줄 제거 → 다른 API와 동일한 2중 인증 (API Key + Bearer) 적용
|
||||
- ⚠️ 재고 데이터 (stocks 153건) 이미 존재 — React에서 재고 연동 시 기존 Stock API 사용
|
||||
- ⚠️ **운영 배포 전 정리 필요** (options 불필요 키 삭제):
|
||||
- `source` (5130_migration 등) — 마이그레이션 추적용, 운영 불필요
|
||||
- `legacy_prod`, `legacy_spec`, `legacy_slength` — PREFIX 생성 완료, 삭제 가능
|
||||
- `legacy_bending_num`, `legacy_num`, `legacy_guiderail_num` — 이미지 매핑 완료, 삭제 가능
|
||||
- `lot_managed`, `consumption_method`, `production_source`, `input_tracking` — 재고 시스템 별도 관리
|
||||
- `author = '개발자'` — 실제 담당자로 변경 필요
|
||||
- ⚠️ 레거시 키 삭제 후 `bending:import-*` 커맨드 재실행 불가 — 운영 확정 후 정리
|
||||
- ⚠️ **운영 안정화 후 마이그레이션 커맨드 삭제 가능** (1회성 도구):
|
||||
- `BendingFillOptions.php`, `BendingImportLegacy.php`, `BendingImportImages.php`
|
||||
- `GuiderailImportLegacy.php`, `BendingProductImportLegacy.php`
|
||||
- `BendingModelImportImages.php`, `BendingModelImportAssemblyImages.php`
|
||||
- ⚠️ R2 이미지 + files 레코드는 운영 데이터 — 삭제 불가
|
||||
|
||||
---
|
||||
|
||||
## 6. 범위 (추후 확정)
|
||||
## 7. MNG 샘플에서 발견된 실무 구현 노트
|
||||
|
||||
| 영역 | 설명 | 시점 |
|
||||
> React 구현 시 참고할 MNG 작업 중 발견된 이슈 및 해결 방법
|
||||
|
||||
### 7-1. API 호출 주의사항
|
||||
|
||||
| 이슈 | 원인 | 해결 |
|
||||
|------|------|------|
|
||||
| 견적 이미지 연동 | GuiderailPreview 컴포넌트 | Step 1~3 완료 후 |
|
||||
| 절곡품 관리 화면 | React 버전 CRUD (MNG 대체) | MNG 샘플 검증 후 |
|
||||
| PUT/POST JSON body 파싱 안 됨 | Laravel API가 form-data만 파싱 | React axios는 JSON 자동 처리되므로 문제 없음 |
|
||||
| `bendingData` 전송 | MNG form은 hidden input JSON 문자열 | React는 객체 배열 그대로 전송 가능 |
|
||||
| pagination 메타 누락 | `ResourceCollection` 감싸면 메타 사라짐 | `paginator.transform()` 방식으로 수정 완료 |
|
||||
| `unique:items,code` | Store 시 코드 중복 체크 | React form에서 에러 메시지 표시 필요 |
|
||||
|
||||
- MNG는 **샘플 확인용** — API 연동 검증이 목적
|
||||
- **실제 운영 화면은 React**에서 구현 (MNG와 동일한 API 호출)
|
||||
- React 화면 상세 설계는 MNG 검증 후 별도 문서로 작성 예정
|
||||
- 현재 문서는 견적 이미지 연동 범위만 정의
|
||||
### 7-2. 절곡 테이블 구현 핵심 로직
|
||||
|
||||
```
|
||||
연신율 보정 규칙:
|
||||
rate = "" → 보정 없음 (input 그대로)
|
||||
rate = "-1" → input - 1mm (절곡 시 1mm 줄어듦)
|
||||
rate = "1" → input + 1mm
|
||||
|
||||
합계 = 보정 후 값의 누적합
|
||||
폭합계 = 마지막 합계값
|
||||
|
||||
절곡횟수 = rate가 빈 문자열이 아닌 열의 수
|
||||
```
|
||||
|
||||
### 7-3. 부품 추가 모달 동작
|
||||
|
||||
```
|
||||
1. [+ 부품 추가] 클릭 → 모달 열기
|
||||
2. GET /api/v1/bending-items?item_sep=&item_bending=&material=&search=&size=100
|
||||
3. 체크박스로 복수 선택
|
||||
4. [선택 적용] → 선택된 아이템의 bendingData를 components에 push
|
||||
5. components JSON 직렬화 → hidden input → form submit
|
||||
```
|
||||
|
||||
### 7-4. 타입별 라우트 매핑
|
||||
|
||||
| React 라우트 | API 파라미터 | MNG 참고 |
|
||||
|-------------|------------|---------|
|
||||
| `/bending/base/*` | `/api/v1/bending-items` | `BendingBaseController` |
|
||||
| `/bending/products/*` | `/api/v1/guiderail-models?item_category=GUIDERAIL_MODEL` (20건) | `BendingProductController` |
|
||||
| `/bending/cases/*` | `/api/v1/guiderail-models?item_category=SHUTTERBOX_MODEL` (30건) | 동일 컨트롤러 |
|
||||
| `/bending/bottombars/*` | `/api/v1/guiderail-models?item_category=BOTTOMBAR_MODEL` (10건) | 동일 컨트롤러 |
|
||||
|
||||
> ⚠️ `item_category` 파라미터 누락 시 60건 전부 반환됨 — React에서 반드시 포함할 것
|
||||
|
||||
### 7-5. 작업지시서 PDF
|
||||
|
||||
MNG에서는 `window.print()` 기반 별도 인쇄 페이지(`/print`)로 구현.
|
||||
React에서는 동일 방식 또는 html2pdf.js / react-to-print 라이브러리 사용 가능.
|
||||
|
||||
**인쇄 포맷 (레거시 동일):**
|
||||
- 헤더: 모델명, 형태, 규격, 마감
|
||||
- 테이블: 번호 | 재질 | 절곡치수(합계+음영) | A각 | 폭합 | 수량
|
||||
- 재질별 폭합 요약
|
||||
- A4 가로
|
||||
|
||||
### 7-6. 이미지 업로드 흐름
|
||||
|
||||
```
|
||||
React:
|
||||
1. <input type="file"> 또는 Ctrl+V 클립보드
|
||||
2. POST /api/v1/items/{itemId}/files (FormData: file + field_key=bending_diagram)
|
||||
3. 응답: { file_id, file_url }
|
||||
4. 표시: GET /api/v1/files/{fileId}/view (inline 이미지)
|
||||
```
|
||||
|
||||
### 7-7. 메뉴 구조 (사이드바)
|
||||
|
||||
```
|
||||
절곡품 관리
|
||||
├─ 기초관리 /bending/base (170건)
|
||||
├─ 가이드레일 /bending/products (20건, GUIDERAIL_MODEL)
|
||||
├─ 케이스 /bending/cases (30건, SHUTTERBOX_MODEL)
|
||||
└─ 하단마감재 /bending/bottombars (10건, BOTTOMBAR_MODEL)
|
||||
```
|
||||
|
||||
React 사이드바 메뉴는 DB `menus` 테이블 기반 동적 렌더링 — 이미 등록 완료.
|
||||
|
||||
### 7-8. 재고 연동 (향후)
|
||||
|
||||
절곡 부품 재고는 SAM 기존 재고 시스템에 통합:
|
||||
- `stocks` 테이블: `item_type = 'bent_part'` (153건)
|
||||
- `stock_lots` 테이블: LOT 기반 FIFO 재고
|
||||
- 기존 Stock API 사용 가능 — 별도 재고 API 불필요
|
||||
|
||||
Reference in New Issue
Block a user