# BP-MES Phase 1 통합 테스트 가이드 ## 개요 BP-MES Phase 1에서 구현된 Items API의 통합 테스트 가이드입니다. **구현 완료 항목:** - ✅ Phase 1 Day 1-2: products/product_components 테이블 확장 (33개 필드) - ✅ Phase 1 Day 3-5: ItemsController CRUD API (통합 품목 조회/생성/수정/삭제) - ✅ Phase 1 Day 6-9: ItemsBomController API (BOM 관리 10개 엔드포인트) - ✅ Phase 1 Day 10-12: ItemsFileController API (파일 업로드/삭제) **테스트 환경:** - API Base URL: `http://api.sam.kr/api/v1` - Swagger UI: `http://api.sam.kr/api-docs/index.html` - 인증: API Key (X-API-KEY) + Bearer Token (Authorization) --- ## 1. API 엔드포인트 검증 ### 1.1 Items CRUD API (5개 엔드포인트) | Method | Endpoint | Description | Controller | |--------|----------|-------------|------------| | GET | `/items` | 품목 목록 조회 (통합) | ItemsController@index | | POST | `/items` | 품목 생성 | ItemsController@store | | GET | `/items/code/{code}` | 코드 기반 조회 | ItemsController@showByCode | | PUT | `/items/{code}` | 품목 수정 | ItemsController@update | | DELETE | `/items/{code}` | 품목 삭제 | ItemsController@destroy | ### 1.2 Items BOM API (10개 엔드포인트) | Method | Endpoint | Description | Controller | |--------|----------|-------------|------------| | GET | `/items/{code}/bom` | BOM 목록 (flat) | ItemsBomController@index | | GET | `/items/{code}/bom/tree` | BOM 트리 (계층) | ItemsBomController@tree | | POST | `/items/{code}/bom` | BOM 추가 (bulk) | ItemsBomController@store | | PUT | `/items/{code}/bom/{lineId}` | BOM 수정 | ItemsBomController@update | | DELETE | `/items/{code}/bom/{lineId}` | BOM 삭제 | ItemsBomController@destroy | | GET | `/items/{code}/bom/summary` | BOM 요약 | ItemsBomController@summary | | GET | `/items/{code}/bom/validate` | BOM 검증 | ItemsBomController@validate | | POST | `/items/{code}/bom/replace` | BOM 전체 교체 | ItemsBomController@replace | | POST | `/items/{code}/bom/reorder` | BOM 정렬 | ItemsBomController@reorder | | GET | `/items/{code}/bom/categories` | 카테고리 목록 | ItemsBomController@listCategories | ### 1.3 Items File API (2개 엔드포인트) | Method | Endpoint | Description | Controller | |--------|----------|-------------|------------| | POST | `/items/{code}/files` | 파일 업로드 | ItemsFileController@upload | | DELETE | `/items/{code}/files/{type}` | 파일 삭제 | ItemsFileController@delete | **지원 파일 타입:** - `bending_diagram`: 절곡도 (jpg, png, gif, svg - 10MB) - `specification`: 시방서 (pdf, doc, docx, xls, xlsx, hwp - 20MB) - `certification`: 인정서 (pdf, doc, docx, xls, xlsx, hwp - 20MB) --- ## 2. 데이터베이스 검증 ### 2.1 Migration 상태 ```bash php artisan migrate:status ``` **확인 사항:** - ✅ 2025_11_14_000001_add_hybrid_fields_to_products_table (batch 27) - ✅ 2025_11_14_000002_add_attributes_to_product_components_table (batch 27) - ✅ 2025_11_17_125437_add_file_fields_to_products_table (batch 28) ### 2.2 products 테이블 필드 확인 **파일 관련 필드 (9개):** ```sql SELECT bending_diagram, bending_details, specification_file, specification_file_name, certification_file, certification_file_name, certification_number, certification_start_date, certification_end_date FROM products LIMIT 1; ``` ### 2.3 Model 검증 ```bash # Product 모델 fillable 확인 php artisan tinker >>> (new \App\Models\Products\Product)->getFillable(); # Product 모델 casts 확인 >>> (new \App\Models\Products\Product)->getCasts(); ``` **확인 사항:** - ✅ fillable에 9개 파일 필드 포함 - ✅ casts: bending_details (array), certification_start_date (date), certification_end_date (date) --- ## 3. 통합 테스트 시나리오 ### 시나리오 1: 기본 CRUD 흐름 **Step 1: 품목 생성** ```http POST /api/v1/items Content-Type: application/json X-API-KEY: {api_key} Authorization: Bearer {token} { "item_type": "PRODUCT", "code": "TEST-001", "name": "테스트 제품", "unit": "EA", "category_id": 1, "product_type": "FG", "is_sellable": true, "is_purchasable": false, "is_producible": true } ``` **예상 결과:** - HTTP 200 OK - `{"success": true, "message": "품목이 등록되었습니다.", "data": {...}}` **Step 2: 품목 조회** ```http GET /api/v1/items/code/TEST-001 X-API-KEY: {api_key} Authorization: Bearer {token} ``` **예상 결과:** - HTTP 200 OK - Product 데이터 반환 **Step 3: 품목 수정** ```http PUT /api/v1/items/TEST-001 Content-Type: application/json X-API-KEY: {api_key} Authorization: Bearer {token} { "name": "테스트 제품 (수정)", "margin_rate": 15.5, "safety_stock": 100 } ``` **예상 결과:** - HTTP 200 OK - `{"success": true, "message": "품목이 수정되었습니다.", "data": {...}}` --- ### 시나리오 2: BOM 관리 흐름 **전제 조건:** - 부모 품목: TEST-001 (생성 완료) - 자재 1: M-001 (기존 자재) - 자재 2: M-002 (기존 자재) **Step 1: BOM 추가 (Bulk)** ```http POST /api/v1/items/TEST-001/bom Content-Type: application/json X-API-KEY: {api_key} Authorization: Bearer {token} { "items": [ { "ref_type": "MATERIAL", "ref_id": 1, "quantity": 2.5, "sort_order": 1, "quantity_formula": "W * 2" }, { "ref_type": "MATERIAL", "ref_id": 2, "quantity": 1.0, "sort_order": 2, "condition": "MOTOR='Y'" } ] } ``` **예상 결과:** - HTTP 200 OK - BOM 항목 2개 생성 **Step 2: BOM 트리 조회** ```http GET /api/v1/items/TEST-001/bom/tree X-API-KEY: {api_key} Authorization: Bearer {token} ``` **예상 결과:** - HTTP 200 OK - 계층 구조로 BOM 반환 (depth, children 포함) **Step 3: BOM 요약 조회** ```http GET /api/v1/items/TEST-001/bom/summary X-API-KEY: {api_key} Authorization: Bearer {token} ``` **예상 결과:** - HTTP 200 OK - total_count, material_count, product_count 반환 **Step 4: BOM 검증** ```http GET /api/v1/items/TEST-001/bom/validate X-API-KEY: {api_key} Authorization: Bearer {token} ``` **예상 결과:** - HTTP 200 OK - is_valid, errors, warnings 반환 **Step 5: BOM 라인 수정** ```http PUT /api/v1/items/TEST-001/bom/1 Content-Type: application/json X-API-KEY: {api_key} Authorization: Bearer {token} { "quantity": 3.0, "quantity_formula": "W * 3" } ``` **예상 결과:** - HTTP 200 OK - BOM 항목 업데이트 완료 **Step 6: BOM 정렬 변경** ```http POST /api/v1/items/TEST-001/bom/reorder Content-Type: application/json X-API-KEY: {api_key} Authorization: Bearer {token} { "items": [ {"id": 2, "sort_order": 1}, {"id": 1, "sort_order": 2} ] } ``` **예상 결과:** - HTTP 200 OK - BOM 정렬 순서 변경 완료 --- ### 시나리오 3: 파일 업로드 흐름 **전제 조건:** - 품목: TEST-001 (생성 완료) - 테스트 파일: bending.jpg (절곡도), spec.pdf (시방서), cert.pdf (인정서) **Step 1: 절곡도 업로드** ```http POST /api/v1/items/TEST-001/files Content-Type: multipart/form-data X-API-KEY: {api_key} Authorization: Bearer {token} type: bending_diagram file: bending.jpg bending_details: [ {"angle": 90, "length": 100.5, "type": "V형"}, {"angle": 45, "length": 50.0, "type": "Z형"} ] ``` **예상 결과:** - HTTP 200 OK - file_url, file_path, file_name 반환 - product.bending_diagram 필드에 파일 경로 저장 - product.bending_details 필드에 배열 저장 **Step 2: 시방서 업로드** ```http POST /api/v1/items/TEST-001/files Content-Type: multipart/form-data X-API-KEY: {api_key} Authorization: Bearer {token} type: specification file: spec.pdf ``` **예상 결과:** - HTTP 200 OK - product.specification_file, specification_file_name 업데이트 **Step 3: 인정서 업로드** ```http POST /api/v1/items/TEST-001/files Content-Type: multipart/form-data X-API-KEY: {api_key} Authorization: Bearer {token} type: certification file: cert.pdf certification_number: CERT-2025-001 certification_start_date: 2025-01-01 certification_end_date: 2026-12-31 ``` **예상 결과:** - HTTP 200 OK - product.certification_file, certification_file_name, certification_number, certification_start_date, certification_end_date 업데이트 **Step 4: 파일 조회 (품목 정보에 포함)** ```http GET /api/v1/items/code/TEST-001 X-API-KEY: {api_key} Authorization: Bearer {token} ``` **예상 결과:** - HTTP 200 OK - Product 데이터에 파일 URL 포함 **Step 5: 파일 삭제** ```http DELETE /api/v1/items/TEST-001/files/bending_diagram X-API-KEY: {api_key} Authorization: Bearer {token} ``` **예상 결과:** - HTTP 200 OK - 물리적 파일 삭제 - product.bending_diagram, bending_details NULL 처리 --- ### 시나리오 4: 전체 통합 시나리오 **목표:** 품목 생성 → BOM 구성 → 파일 업로드 → 검증 **1. 품목 생성** ```http POST /api/v1/items { "item_type": "PRODUCT", "code": "INT-TEST-001", "name": "통합 테스트 제품", "unit": "EA", "category_id": 1, "product_type": "FG", "product_category": "SCREEN", "is_sellable": true, "is_purchasable": false, "is_producible": true, "margin_rate": 20.0, "safety_stock": 50, "lead_time": 7, "is_variable_size": true } ``` **2. BOM 구성** ```http POST /api/v1/items/INT-TEST-001/bom { "items": [ {"ref_type": "MATERIAL", "ref_id": 1, "quantity": 2.0, "sort_order": 1, "quantity_formula": "W * 2"}, {"ref_type": "MATERIAL", "ref_id": 2, "quantity": 1.0, "sort_order": 2, "condition": "MOTOR='Y'"}, {"ref_type": "PRODUCT", "ref_id": 5, "quantity": 1.0, "sort_order": 3} ] } ``` **3. BOM 트리 및 요약 확인** ```http GET /api/v1/items/INT-TEST-001/bom/tree GET /api/v1/items/INT-TEST-001/bom/summary GET /api/v1/items/INT-TEST-001/bom/validate ``` **4. 절곡도 업로드** ```http POST /api/v1/items/INT-TEST-001/files type: bending_diagram file: test_bending.jpg bending_details: [{"angle": 90, "length": 100, "type": "V형"}] ``` **5. 시방서 업로드** ```http POST /api/v1/items/INT-TEST-001/files type: specification file: test_spec.pdf ``` **6. 인정서 업로드** ```http POST /api/v1/items/INT-TEST-001/files type: certification file: test_cert.pdf certification_number: TEST-CERT-001 certification_start_date: 2025-01-01 certification_end_date: 2026-12-31 ``` **7. 최종 검증** ```http GET /api/v1/items/code/INT-TEST-001 ``` **확인 사항:** - ✅ 품목 정보 정상 반환 - ✅ BOM 데이터 포함 (componentLines 관계) - ✅ 파일 URL 3개 포함 (bending_diagram, specification_file, certification_file) - ✅ 인증 정보 포함 (certification_number, start_date, end_date) - ✅ 절곡 상세 정보 포함 (bending_details 배열) **8. 삭제 테스트** ```http DELETE /api/v1/items/INT-TEST-001/bom/1 DELETE /api/v1/items/INT-TEST-001/files/bending_diagram DELETE /api/v1/items/INT-TEST-001 ``` --- ## 4. 에러 처리 검증 ### 4.1 파일 업로드 에러 **케이스 1: 잘못된 파일 타입** ```http POST /api/v1/items/TEST-001/files type: bending_diagram file: test.txt (텍스트 파일) ``` **예상:** HTTP 422, "허용되지 않는 파일 형식입니다." **케이스 2: 파일 크기 초과** ```http POST /api/v1/items/TEST-001/files type: bending_diagram file: huge_image.jpg (15MB) ``` **예상:** HTTP 422, "파일 크기가 너무 큽니다." **케이스 3: 인증 기간 검증 실패** ```http POST /api/v1/items/TEST-001/files type: certification file: cert.pdf certification_start_date: 2025-12-31 certification_end_date: 2025-01-01 ``` **예상:** HTTP 422, "인증 종료일은 시작일 이후여야 합니다." ### 4.2 BOM 에러 **케이스 1: 존재하지 않는 품목** ```http POST /api/v1/items/INVALID-CODE/bom ``` **예상:** HTTP 404, "존재하지 않는 URI 또는 데이터입니다." **케이스 2: 순환 참조** ```http POST /api/v1/items/TEST-001/bom { "items": [ {"ref_type": "PRODUCT", "ref_id": 1, "quantity": 1.0} ] } ``` (TEST-001의 ID가 1인 경우) **예상:** BOM 검증 시 순환 참조 경고 ### 4.3 CRUD 에러 **케이스 1: 중복 코드** ```http POST /api/v1/items { "code": "TEST-001" (이미 존재) } ``` **예상:** HTTP 422, "중복된 데이터가 존재합니다." **케이스 2: 필수 필드 누락** ```http POST /api/v1/items { "code": "TEST-002" // name 누락 } ``` **예상:** HTTP 422, 검증 실패 --- ## 5. 성능 검증 ### 5.1 BOM 트리 조회 성능 ```bash # 10개 계층, 각 계층 5개 자식 = 약 50개 노드 GET /api/v1/items/{code}/bom/tree # 목표: < 1초 # 실제: {측정 필요} ``` ### 5.2 파일 업로드 성능 ```bash # 10MB 이미지 업로드 POST /api/v1/items/{code}/files # 목표: < 5초 # 실제: {측정 필요} ``` ### 5.3 목록 조회 성능 ```bash # 1000개 품목 페이징 조회 GET /api/v1/items?page=1&size=20 # 목표: < 500ms # 실제: {측정 필요} ``` --- ## 6. Swagger UI 테스트 ### 6.1 접속 확인 ``` URL: http://api.sam.kr/api-docs/index.html ``` **확인 사항:** - ✅ Items Files 태그 표시 - ✅ POST /api/v1/items/{code}/files 엔드포인트 표시 - ✅ DELETE /api/v1/items/{code}/files/{type} 엔드포인트 표시 - ✅ ItemFileUploadResponse 스키마 표시 - ✅ ItemFileDeleteResponse 스키마 표시 - ✅ Try it out 기능 동작 ### 6.2 API 문서 완성도 **Items CRUD:** - ✅ 5개 엔드포인트 모두 문서화 - ✅ Request/Response 스키마 정의 - ✅ 예시 데이터 포함 **Items BOM:** - ✅ 10개 엔드포인트 모두 문서화 - ✅ BOMLine, BOMTree 스키마 정의 - ✅ 예시 데이터 포함 **Items Files:** - ✅ 2개 엔드포인트 모두 문서화 - ✅ multipart/form-data 정의 - ✅ 파일 타입별 검증 규칙 설명 --- ## 7. 체크리스트 ### Phase 1 완료 항목 - [x] products 테이블 확장 (33개 필드) - [x] product_components 테이블 확장 (5개 필드) - [x] products 파일 필드 추가 (9개 필드) - [x] ItemsController CRUD API (5개 엔드포인트) - [x] ItemsBomController API (10개 엔드포인트) - [x] ItemsFileController API (2개 엔드포인트) - [x] FormRequest 검증 (ItemsFileUploadRequest) - [x] Swagger 문서 작성 (ItemsFileApi) - [x] Migration 실행 및 검증 - [x] Pint 코드 포맷팅 - [x] Git 커밋 ### 테스트 권장 순서 1. [ ] Swagger UI 접속 및 문서 확인 2. [ ] Database 스키마 검증 3. [ ] Model fillable/casts 확인 4. [ ] Items CRUD API 테스트 5. [ ] Items BOM API 테스트 6. [ ] Items File API 테스트 7. [ ] 통합 시나리오 테스트 8. [ ] 에러 처리 검증 9. [ ] 성능 측정 10. [ ] 최종 검증 --- ## 8. 다음 단계 **Phase 2 계획 (제안):** - [ ] Frontend 연동 (React/Vue) - [ ] 파일 미리보기 기능 - [ ] BOM 계산 로직 (수식 평가) - [ ] 조건부 BOM 처리 - [ ] 대량 데이터 Import/Export - [ ] 품목 복제 기능 - [ ] 변경 이력 추적 - [ ] 통합 검색 개선 --- **작성일:** 2025-11-17 **작성자:** Claude Code **버전:** 1.0