feat: ItemMaster 데이터베이스 구조 구축 (9개 테이블)

- 마이그레이션 9개 생성 (unit_options, section_templates, item_master_fields, item_pages, item_sections, item_fields, item_bom_items, custom_tabs, tab_columns)
- Eloquent 모델 9개 구현 (ItemMaster 네임스페이스)
- ItemMasterSeeder 작성 및 테스트 데이터 생성

주요 특징:
- Multi-tenant 지원 (BelongsToTenant trait)
- Soft Delete 적용 (deleted_at, deleted_by)
- 감사 로그 지원 (created_by, updated_by)
- JSON 필드로 동적 속성 지원 (display_condition, validation_rules, options, properties)
- FK 제약조건 및 Composite Index 설정
- 계층 구조 (ItemPage → ItemSection → ItemField/ItemBomItem)

SAM API Development Rules 준수
This commit is contained in:
2025-11-20 16:36:55 +09:00
parent 8ce8a35f30
commit 7109fc5199
21 changed files with 1370 additions and 1 deletions

View File

@@ -1,3 +1,292 @@
## 2025-11-20 (수) - ItemMaster 데이터베이스 구조 구축
### 주요 작업
- ItemMaster 시스템을 위한 9개 테이블 마이그레이션 생성 및 실행
- 9개 Eloquent 모델 클래스 구현
- 시드 데이터 작성 및 테스트 데이터 생성
- SAM API Development Rules 준수 (Multi-tenant, SoftDeletes, 감사 로그)
### 추가된 파일
#### 마이그레이션 (9개)
1. **database/migrations/2025_11_20_100000_create_unit_options_table.php**
- 단위 옵션 테이블 (kg, EA, m, mm, L, BOX)
- tenant_id, label, value, created_by, updated_by, deleted_by
2. **database/migrations/2025_11_20_100001_create_section_templates_table.php**
- 섹션 템플릿 테이블 (재사용 가능한 섹션 정의)
- title, type (fields/bom), description, is_default
3. **database/migrations/2025_11_20_100002_create_item_master_fields_table.php**
- 마스터 필드 라이브러리
- field_name, field_type, category, is_common
- options, validation_rules, properties (JSON)
4. **database/migrations/2025_11_20_100003_create_item_pages_table.php**
- 품목 페이지 테이블 (FG/PT/SM/RM/CS)
- page_name, item_type (ENUM), absolute_path, is_active
5. **database/migrations/2025_11_20_100004_create_item_sections_table.php**
- 섹션 인스턴스 테이블
- page_id (FK), title, type, order_no
- Composite Index: (page_id, order_no)
6. **database/migrations/2025_11_20_100005_create_item_fields_table.php**
- 필드 인스턴스 테이블
- section_id (FK), field_name, field_type, order_no, is_required
- display_condition, validation_rules, options, properties (JSON)
- Composite Index: (section_id, order_no)
7. **database/migrations/2025_11_20_100006_create_item_bom_items_table.php**
- BOM 항목 테이블
- section_id (FK), item_code, item_name, quantity, unit
- unit_price, total_price, spec, note
8. **database/migrations/2025_11_20_100007_create_custom_tabs_table.php**
- 커스텀 탭 정의
- label, icon, is_default, order_no
9. **database/migrations/2025_11_20_100008_create_tab_columns_table.php**
- 탭별 컬럼 설정
- tab_id (FK), columns (JSON)
- Unique: (tenant_id, tab_id)
#### 모델 (9개)
1. **app/Models/ItemMaster/UnitOption.php**
- Traits: BelongsToTenant, ModelTrait, SoftDeletes
2. **app/Models/ItemMaster/SectionTemplate.php**
- is_default boolean cast
3. **app/Models/ItemMaster/ItemMasterField.php**
- options, validation_rules, properties array cast
4. **app/Models/ItemMaster/ItemPage.php**
- Relationship: sections() hasMany
- is_active boolean cast
5. **app/Models/ItemMaster/ItemSection.php**
- Relationships: page() belongsTo, fields() hasMany, bomItems() hasMany
- order_no integer cast
6. **app/Models/ItemMaster/ItemField.php**
- Relationship: section() belongsTo
- 4개 JSON 필드 array cast
7. **app/Models/ItemMaster/ItemBomItem.php**
- Relationship: section() belongsTo
- quantity decimal:4, prices decimal:2
8. **app/Models/ItemMaster/CustomTab.php**
- Relationship: columnSetting() hasOne
- is_default boolean, order_no integer cast
9. **app/Models/ItemMaster/TabColumn.php**
- Relationship: tab() belongsTo
- columns array cast
- SoftDeletes 미적용 (설정 데이터)
#### 시더
1. **database/seeders/ItemMasterSeeder.php**
- 6개 단위 옵션 생성
- 3개 섹션 템플릿 생성
- 8개 마스터 필드 생성
- 5개 품목 페이지 생성 (FG, PT, SM, RM, CS)
- 각 페이지에 기본 정보 섹션 + 필드 3개
- FG/PT 페이지에 BOM 구성 섹션 + 샘플 BOM 항목
- 3개 커스텀 탭 + 컬럼 설정
### 작업 내용
#### 1단계: 분석
- 프론트엔드 API 명세서 분석
- 기존 DB 구조와 요구사항 비교
- 9개 테이블 간 의존성 파악
- 마이그레이션 실행 순서 결정
#### 2단계: 수정
- SAM API Development Rules 준수하여 마이그레이션 작성
- BelongsToTenant, SoftDeletes 적용
- created_by, updated_by, deleted_by 컬럼 (COMMENT 포함)
- FK 제약조건 with ON DELETE CASCADE
- Eloquent 모델 작성
- 관계 설정 (hasMany, belongsTo, hasOne)
- JSON 필드 캐스팅
- ModelTrait 적용
- 시더 작성 (실제 사용 가능한 테스트 데이터)
#### 3단계: 검증
- `php artisan migrate --pretend` 실행 → 순서 확인
- `php artisan migrate` 실행 → 9개 테이블 생성 성공
- `php artisan db:seed --class=ItemMasterSeeder` 실행
- 데이터 검증:
- Unit Options: 6개
- Item Pages: 5개
- Item Sections: 7개
- Item Fields: 15개
- BOM Items: 2개
#### 4단계: 정리
- 임시 파일 확인 → 없음
### 기술적 특징
#### Multi-tenant 지원
- 모든 테이블에 tenant_id 컬럼
- BelongsToTenant trait로 글로벌 스코프 자동 적용
- 테넌트 격리 보장
#### 감사 로그 지원
- created_by, updated_by, deleted_by 컬럼
- 모든 변경사항 추적 가능
#### 유연한 스키마
- JSON 필드로 동적 속성 지원
- display_condition: 조건부 표시
- validation_rules: 유효성 검사 규칙
- options: 드롭다운 옵션
- properties: 필드 속성 (unit, precision, format)
#### 정렬 및 순서 관리
- order_no 컬럼으로 UI 순서 제어
- Composite Index로 빠른 정렬 쿼리
#### 관계 설정
- ItemPage → ItemSection → ItemField (계층 구조)
- ItemPage → ItemSection → ItemBomItem (BOM 구조)
- CustomTab → TabColumn (1:1 관계)
### 다음 단계 (Week 2-3)
- ItemPageController, ItemSectionController 구현
- ItemFieldController, ItemBomItemController 구현
- FormRequest 클래스 작성
- Service 클래스 구현 (비즈니스 로직)
- Swagger 문서 작성 (/api/v1/item-master/*)
### Git 커밋
```bash
# 커밋 예정
```
---
## 2025-11-17 (일) - is_active 컬럼 추가 (products, materials 테이블)
### 주요 작업
- products 및 materials 테이블에 is_active 컬럼 추가
- Product 및 Material 모델 업데이트
- ModelTrait의 scopeActive() 메서드 지원
### 문제 상황
- GET /api/v1/items 실행 시 `SQLSTATE[42S22]: Column not found: 1054 Unknown column 'is_active'` 에러 발생
- ItemsService에서 `->where('is_active', 1)` 조건 사용
- ModelTrait에 `scopeActive()` 메서드가 is_active 컬럼 참조
- products, materials 테이블에 is_active 컬럼 없음
### 추가된 파일
1. **database/migrations/2025_11_17_145307_add_is_active_to_products_and_materials_tables.php**
- products 테이블에 is_active 추가 (tinyInteger, default 1, AFTER updated_by)
- materials 테이블에 is_active 추가 (tinyInteger, default 1, AFTER updated_by)
- 롤백 지원 (down 메서드)
### 수정된 파일
1. **app/Models/Products/Product.php**
- fillable에 'is_active' 추가
- casts에 'is_active' => 'boolean' 추가
2. **app/Models/Materials/Material.php**
- fillable에 'material_type', 'is_active' 추가
- casts에 'is_active' => 'boolean' 추가
### 작업 내용
- ModelTrait의 scopeActive() 메서드가 정상 작동하도록 is_active 컬럼 추가
- 기본값 1로 설정하여 기존 데이터는 활성 상태로 유지
- Material 모델에 누락된 material_type도 fillable에 추가
### Git 커밋
```bash
git commit 517d594
feat: products 및 materials 테이블에 is_active 컬럼 추가
- is_active 컬럼 추가 마이그레이션 (default 1)
- Product 모델 fillable 및 casts 업데이트
- Material 모델 fillable 및 casts 업데이트
- Material 모델에 material_type fillable 추가
- ModelTrait의 scopeActive() 메서드 지원
git commit 8ce8a35
fix: is_active 마이그레이션에 컬럼 존재 여부 체크 추가
- Schema::hasColumn()으로 컬럼 존재 여부 확인
- 개발 서버와 로컬 환경의 스키마 차이 대응
- 중복 컬럼 추가 오류 방지
```
### 환경별 차이 발견
- **개발 서버**: is_active 컬럼이 이미 존재함
- **로컬 환경**: is_active 컬럼이 없었음
- **원인**: 환경 간 DB 스키마 동기화가 안 되어 있었음
- **해결**: 컬럼 존재 여부를 체크하는 로직 추가로 양쪽 환경 모두 대응
### 개발 서버 마이그레이션 처리 방법
```bash
# 방법 1: 롤백 후 재실행
php artisan migrate:rollback --step=1
git pull origin develop
php artisan migrate
# 방법 2: 실패한 마이그레이션 레코드만 정리 (is_active가 이미 있으므로)
# migrations 테이블에서 해당 레코드를 수동으로 완료 처리
```
### 검증 완료
- [x] 마이그레이션 실행 성공 (로컬)
- [x] Product 모델 업데이트
- [x] Material 모델 업데이트
- [x] 컬럼 존재 여부 체크 추가
- [x] Pint 포맷팅 통과
- [x] Git 커밋 완료 (2개)
---
## 2025-11-17 (일) - BP-MES Phase 1: Swagger 문서 보완 (GET /items 엔드포인트)
### 주요 작업
- ItemsApi Swagger 문서 누락 부분 추가
- GET /api/v1/items 엔드포인트 문서화 완료
### 수정된 파일
1. **app/Swagger/v1/ItemsApi.php**
- index() 메서드 Swagger 문서 추가
- 품목 목록 조회 (통합) 엔드포인트 문서화
- 페이징 파라미터 (page, size) 정의
- 검색 및 필터 파라미터 정의 (search, product_type, category_id, is_active)
- 응답 스키마 정의 (Item array + PaginationMeta)
### 작업 내용
- 라우트는 존재했지만 Swagger 문서가 누락되어 있던 GET /items 엔드포인트 문서화
- ItemsApi.php의 5개 엔드포인트 중 index()만 문서가 없었던 문제 해결
- l5-swagger:generate 실행으로 Swagger JSON 재생성
### Git 커밋
```bash
git commit 7b8f879
docs: GET /items 엔드포인트 Swagger 문서 추가
- ItemsApi.php에 index() 메서드 문서 추가
- 품목 목록 조회 (통합) 엔드포인트 문서화
- 페이징, 검색, 필터 파라미터 정의
- Swagger JSON 재생성 완료
```
### 검증 완료
- [x] Swagger 문서 추가 (index 메서드)
- [x] Swagger JSON 재생성
- [x] Pint 포맷팅 통과
- [x] Git 커밋 완료
---
## 2025-11-17 (일) - BP-MES Phase 1: Items BOM API 및 File Upload API 구현 완료
### 주요 작업