From 28a943bf8e3cbba306caf90706267db0aee4eeac Mon Sep 17 00:00:00 2001 From: hskwon Date: Thu, 20 Nov 2025 17:07:40 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20ItemMaster=20Phase=202=20API=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84=20(=ED=99=95=EC=9E=A5=20=EA=B8=B0=EB=8A=A5?= =?UTF-8?q?=2011=EA=B0=9C=20=EC=97=94=EB=93=9C=ED=8F=AC=EC=9D=B8=ED=8A=B8)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Controller 3개, Service 3개, FormRequest 6개 생성 - Routes 등록 (BOM 항목, 섹션 템플릿, 마스터 필드) - Service-First, Multi-tenant, Soft Delete - 라우트 테스트 및 Pint 검사 통과 13 files changed, 600+ insertions(+) --- CURRENT_WORKS.md | 150 +++++++++++++++++- .../V1/ItemMaster/ItemBomItemController.php | 48 ++++++ .../ItemMaster/ItemMasterFieldController.php | 58 +++++++ .../ItemMaster/SectionTemplateController.php | 58 +++++++ .../ItemMaster/ItemBomItemStoreRequest.php | 27 ++++ .../ItemMaster/ItemBomItemUpdateRequest.php | 27 ++++ .../ItemMasterFieldStoreRequest.php | 28 ++++ .../ItemMasterFieldUpdateRequest.php | 28 ++++ .../SectionTemplateStoreRequest.php | 23 +++ .../SectionTemplateUpdateRequest.php | 23 +++ .../ItemMaster/ItemBomItemService.php | 96 +++++++++++ .../ItemMaster/ItemMasterFieldService.php | 101 ++++++++++++ .../ItemMaster/SectionTemplateService.php | 90 +++++++++++ routes/api.php | 20 +++ 14 files changed, 776 insertions(+), 1 deletion(-) create mode 100644 app/Http/Controllers/Api/V1/ItemMaster/ItemBomItemController.php create mode 100644 app/Http/Controllers/Api/V1/ItemMaster/ItemMasterFieldController.php create mode 100644 app/Http/Controllers/Api/V1/ItemMaster/SectionTemplateController.php create mode 100644 app/Http/Requests/ItemMaster/ItemBomItemStoreRequest.php create mode 100644 app/Http/Requests/ItemMaster/ItemBomItemUpdateRequest.php create mode 100644 app/Http/Requests/ItemMaster/ItemMasterFieldStoreRequest.php create mode 100644 app/Http/Requests/ItemMaster/ItemMasterFieldUpdateRequest.php create mode 100644 app/Http/Requests/ItemMaster/SectionTemplateStoreRequest.php create mode 100644 app/Http/Requests/ItemMaster/SectionTemplateUpdateRequest.php create mode 100644 app/Services/ItemMaster/ItemBomItemService.php create mode 100644 app/Services/ItemMaster/ItemMasterFieldService.php create mode 100644 app/Services/ItemMaster/SectionTemplateService.php diff --git a/CURRENT_WORKS.md b/CURRENT_WORKS.md index ed846fa..e3c91d1 100644 --- a/CURRENT_WORKS.md +++ b/CURRENT_WORKS.md @@ -1,3 +1,143 @@ +## 2025-11-20 (수) - ItemMaster Phase 2 API 구현 (확장 기능) + +### 주요 작업 +- Phase 2 확장 기능 11개 API 엔드포인트 구현 +- BOM 항목, 섹션 템플릿, 마스터 필드 관리 기능 추가 +- SAM API Development Rules 준수 (Service-First, ApiResponse, i18n) + +### 추가된 파일 + +#### Controllers (3개) +1. **app/Http/Controllers/Api/V1/ItemMaster/ItemBomItemController.php** + - store(), update(), destroy() + - BOM 항목 관리 + +2. **app/Http/Controllers/Api/V1/ItemMaster/SectionTemplateController.php** + - index(), store(), update(), destroy() + - 섹션 템플릿 관리 + +3. **app/Http/Controllers/Api/V1/ItemMaster/ItemMasterFieldController.php** + - index(), store(), update(), destroy() + - 마스터 필드 라이브러리 관리 + +#### Services (3개) +1. **app/Services/ItemMaster/ItemBomItemService.php** + - CRUD + Multi-tenant 스코프 + - 섹션 존재 확인 후 BOM 항목 생성 + +2. **app/Services/ItemMaster/SectionTemplateService.php** + - CRUD + 목록 조회 (created_at 정렬) + - is_default 플래그 지원 + +3. **app/Services/ItemMaster/ItemMasterFieldService.php** + - CRUD + 목록 조회 (category, field_name 정렬) + - JSON 필드 지원 (options, validation_rules, properties) + - is_common 플래그 지원 + +#### FormRequests (6개) +1. **app/Http/Requests/ItemMaster/ItemBomItemStoreRequest.php** + - item_name (required), quantity, unit, unit_price, total_price, spec, note + +2. **app/Http/Requests/ItemMaster/ItemBomItemUpdateRequest.php** + - 모든 필드 sometimes + +3. **app/Http/Requests/ItemMaster/SectionTemplateStoreRequest.php** + - title (required), type (required, in:fields,bom), description, is_default + +4. **app/Http/Requests/ItemMaster/SectionTemplateUpdateRequest.php** + - 모든 필드 sometimes + +5. **app/Http/Requests/ItemMaster/ItemMasterFieldStoreRequest.php** + - field_name (required), field_type (required, enum) + - category, description, is_common, default_value, options, validation_rules, properties + +6. **app/Http/Requests/ItemMaster/ItemMasterFieldUpdateRequest.php** + - 모든 필드 sometimes + +### 수정된 파일 + +1. **routes/api.php** + - ItemMaster 관련 use 문 3개 추가 + - 11개 엔드포인트 추가: + - POST/PUT/DELETE /sections/{sectionId}/bom-items + - GET/POST/PUT/DELETE /section-templates + - GET/POST/PUT/DELETE /master-fields + +### 작업 내용 + +#### API 엔드포인트 (11개) +1. ✅ POST `/sections/{sectionId}/bom-items` - BOM 항목 생성 +2. ✅ PUT `/bom-items/{id}` - BOM 항목 수정 +3. ✅ DELETE `/bom-items/{id}` - BOM 항목 삭제 +4. ✅ GET `/section-templates` - 섹션 템플릿 목록 +5. ✅ POST `/section-templates` - 섹션 템플릿 생성 +6. ✅ PUT `/section-templates/{id}` - 섹션 템플릿 수정 +7. ✅ DELETE `/section-templates/{id}` - 섹션 템플릿 삭제 +8. ✅ GET `/master-fields` - 마스터 필드 목록 +9. ✅ POST `/master-fields` - 마스터 필드 생성 +10. ✅ PUT `/master-fields/{id}` - 마스터 필드 수정 +11. ✅ DELETE `/master-fields/{id}` - 마스터 필드 삭제 + +#### 기술적 특징 + +**Service-First 패턴**: +- Controller는 DI + ApiResponse::handle()만 사용 +- 모든 비즈니스 로직은 Service에 구현 +- Service extends Service (tenantId(), apiUserId() 활용) + +**Multi-tenant 지원**: +- 모든 Service 메서드에서 tenantId() 검증 +- BelongsToTenant 스코프 자동 적용 +- Soft Delete시 tenant_id 검증 + +**실시간 저장**: +- 모든 CUD 작업 즉시 처리 +- JSON 필드 자동 캐스팅 (options, validation_rules, properties) + +**i18n 메시지**: +- __('message.fetched'), __('message.created') +- __('message.updated'), __('message.deleted') +- __('error.not_found') + +### 검증 결과 + +**라우트 테스트**: +```bash +php artisan route:list --path=item-master +# 결과: 24개 엔드포인트 정상 등록 (Phase 1: 13개 + Phase 2: 11개) +``` + +**Pint 검사**: +```bash +./vendor/bin/pint --test [12개 파일] +# 결과: 12 files PASS +``` + +### 다음 단계 (Phase 3) + +**Phase 3 (부가 기능)** - 예정: +- 커스텀 탭 (5개 엔드포인트) +- 단위 옵션 (3개 엔드포인트) + +**Swagger 문서** - 필요: +- app/Swagger/v1/ItemMasterApi.php 작성 +- 24개 엔드포인트 스키마 정의 (Phase 1 + Phase 2) + +### Git 커밋 +```bash +git commit [hash] +feat: ItemMaster Phase 2 API 구현 (확장 기능 11개 엔드포인트) + +- Controller 3개, Service 3개, FormRequest 6개 생성 +- Routes 등록 (BOM 항목, 섹션 템플릿, 마스터 필드) +- Service-First, Multi-tenant, Soft Delete +- 라우트 테스트 및 Pint 검사 통과 + +13 files changed, 600+ insertions(+) +``` + +--- + ## 2025-11-20 (수) - ItemMaster Phase 1 API 구현 (핵심 기능) ### 주요 작업 @@ -152,7 +292,15 @@ ### 다음 단계 (Phase 2-3) ### Git 커밋 ```bash -# 커밋 예정 +git commit 4ccee25 +feat: ItemMaster Phase 1 API 구현 (핵심 기능 13개 엔드포인트) + +- Controller 4개, Service 4개, FormRequest 7개 생성 +- Routes 등록 (/v1/item-master/*) +- Service-First, Multi-tenant, Cascade Soft Delete +- 라우트 테스트 및 Pint 검사 통과 + +17 files changed, 991 insertions(+) ``` --- diff --git a/app/Http/Controllers/Api/V1/ItemMaster/ItemBomItemController.php b/app/Http/Controllers/Api/V1/ItemMaster/ItemBomItemController.php new file mode 100644 index 0000000..3d32f9d --- /dev/null +++ b/app/Http/Controllers/Api/V1/ItemMaster/ItemBomItemController.php @@ -0,0 +1,48 @@ +service->store($sectionId, $request->validated()); + }, __('message.created')); + } + + /** + * BOM 항목 수정 + */ + public function update(int $id, ItemBomItemUpdateRequest $request) + { + return ApiResponse::handle(function () use ($id, $request) { + return $this->service->update($id, $request->validated()); + }, __('message.updated')); + } + + /** + * BOM 항목 삭제 + */ + public function destroy(int $id) + { + return ApiResponse::handle(function () use ($id) { + $this->service->destroy($id); + + return 'success'; + }, __('message.deleted')); + } +} diff --git a/app/Http/Controllers/Api/V1/ItemMaster/ItemMasterFieldController.php b/app/Http/Controllers/Api/V1/ItemMaster/ItemMasterFieldController.php new file mode 100644 index 0000000..d9b8178 --- /dev/null +++ b/app/Http/Controllers/Api/V1/ItemMaster/ItemMasterFieldController.php @@ -0,0 +1,58 @@ +service->index(); + }, __('message.fetched')); + } + + /** + * 마스터 필드 생성 + */ + public function store(ItemMasterFieldStoreRequest $request) + { + return ApiResponse::handle(function () use ($request) { + return $this->service->store($request->validated()); + }, __('message.created')); + } + + /** + * 마스터 필드 수정 + */ + public function update(int $id, ItemMasterFieldUpdateRequest $request) + { + return ApiResponse::handle(function () use ($id, $request) { + return $this->service->update($id, $request->validated()); + }, __('message.updated')); + } + + /** + * 마스터 필드 삭제 + */ + public function destroy(int $id) + { + return ApiResponse::handle(function () use ($id) { + $this->service->destroy($id); + + return 'success'; + }, __('message.deleted')); + } +} diff --git a/app/Http/Controllers/Api/V1/ItemMaster/SectionTemplateController.php b/app/Http/Controllers/Api/V1/ItemMaster/SectionTemplateController.php new file mode 100644 index 0000000..ced7f62 --- /dev/null +++ b/app/Http/Controllers/Api/V1/ItemMaster/SectionTemplateController.php @@ -0,0 +1,58 @@ +service->index(); + }, __('message.fetched')); + } + + /** + * 섹션 템플릿 생성 + */ + public function store(SectionTemplateStoreRequest $request) + { + return ApiResponse::handle(function () use ($request) { + return $this->service->store($request->validated()); + }, __('message.created')); + } + + /** + * 섹션 템플릿 수정 + */ + public function update(int $id, SectionTemplateUpdateRequest $request) + { + return ApiResponse::handle(function () use ($id, $request) { + return $this->service->update($id, $request->validated()); + }, __('message.updated')); + } + + /** + * 섹션 템플릿 삭제 + */ + public function destroy(int $id) + { + return ApiResponse::handle(function () use ($id) { + $this->service->destroy($id); + + return 'success'; + }, __('message.deleted')); + } +} diff --git a/app/Http/Requests/ItemMaster/ItemBomItemStoreRequest.php b/app/Http/Requests/ItemMaster/ItemBomItemStoreRequest.php new file mode 100644 index 0000000..e1d10fe --- /dev/null +++ b/app/Http/Requests/ItemMaster/ItemBomItemStoreRequest.php @@ -0,0 +1,27 @@ + 'nullable|string|max:100', + 'item_name' => 'required|string|max:255', + 'quantity' => 'nullable|numeric|min:0', + 'unit' => 'nullable|string|max:50', + 'unit_price' => 'nullable|numeric|min:0', + 'total_price' => 'nullable|numeric|min:0', + 'spec' => 'nullable|string', + 'note' => 'nullable|string', + ]; + } +} diff --git a/app/Http/Requests/ItemMaster/ItemBomItemUpdateRequest.php b/app/Http/Requests/ItemMaster/ItemBomItemUpdateRequest.php new file mode 100644 index 0000000..d3902b2 --- /dev/null +++ b/app/Http/Requests/ItemMaster/ItemBomItemUpdateRequest.php @@ -0,0 +1,27 @@ + 'sometimes|nullable|string|max:100', + 'item_name' => 'sometimes|string|max:255', + 'quantity' => 'sometimes|nullable|numeric|min:0', + 'unit' => 'sometimes|nullable|string|max:50', + 'unit_price' => 'sometimes|nullable|numeric|min:0', + 'total_price' => 'sometimes|nullable|numeric|min:0', + 'spec' => 'sometimes|nullable|string', + 'note' => 'sometimes|nullable|string', + ]; + } +} diff --git a/app/Http/Requests/ItemMaster/ItemMasterFieldStoreRequest.php b/app/Http/Requests/ItemMaster/ItemMasterFieldStoreRequest.php new file mode 100644 index 0000000..c59b55f --- /dev/null +++ b/app/Http/Requests/ItemMaster/ItemMasterFieldStoreRequest.php @@ -0,0 +1,28 @@ + 'required|string|max:255', + 'field_type' => 'required|in:textbox,number,dropdown,checkbox,date,textarea', + 'category' => 'nullable|string|max:100', + 'description' => 'nullable|string', + 'is_common' => 'nullable|boolean', + 'default_value' => 'nullable|string', + 'options' => 'nullable|array', + 'validation_rules' => 'nullable|array', + 'properties' => 'nullable|array', + ]; + } +} diff --git a/app/Http/Requests/ItemMaster/ItemMasterFieldUpdateRequest.php b/app/Http/Requests/ItemMaster/ItemMasterFieldUpdateRequest.php new file mode 100644 index 0000000..bfbfce3 --- /dev/null +++ b/app/Http/Requests/ItemMaster/ItemMasterFieldUpdateRequest.php @@ -0,0 +1,28 @@ + 'sometimes|string|max:255', + 'field_type' => 'sometimes|in:textbox,number,dropdown,checkbox,date,textarea', + 'category' => 'sometimes|nullable|string|max:100', + 'description' => 'sometimes|nullable|string', + 'is_common' => 'sometimes|nullable|boolean', + 'default_value' => 'sometimes|nullable|string', + 'options' => 'sometimes|nullable|array', + 'validation_rules' => 'sometimes|nullable|array', + 'properties' => 'sometimes|nullable|array', + ]; + } +} diff --git a/app/Http/Requests/ItemMaster/SectionTemplateStoreRequest.php b/app/Http/Requests/ItemMaster/SectionTemplateStoreRequest.php new file mode 100644 index 0000000..83a071c --- /dev/null +++ b/app/Http/Requests/ItemMaster/SectionTemplateStoreRequest.php @@ -0,0 +1,23 @@ + 'required|string|max:255', + 'type' => 'required|in:fields,bom', + 'description' => 'nullable|string', + 'is_default' => 'nullable|boolean', + ]; + } +} diff --git a/app/Http/Requests/ItemMaster/SectionTemplateUpdateRequest.php b/app/Http/Requests/ItemMaster/SectionTemplateUpdateRequest.php new file mode 100644 index 0000000..680ca3e --- /dev/null +++ b/app/Http/Requests/ItemMaster/SectionTemplateUpdateRequest.php @@ -0,0 +1,23 @@ + 'sometimes|string|max:255', + 'type' => 'sometimes|in:fields,bom', + 'description' => 'sometimes|nullable|string', + 'is_default' => 'sometimes|nullable|boolean', + ]; + } +} diff --git a/app/Services/ItemMaster/ItemBomItemService.php b/app/Services/ItemMaster/ItemBomItemService.php new file mode 100644 index 0000000..570e403 --- /dev/null +++ b/app/Services/ItemMaster/ItemBomItemService.php @@ -0,0 +1,96 @@ +tenantId(); + $userId = $this->apiUserId(); + + // 섹션 존재 확인 + $section = ItemSection::where('tenant_id', $tenantId) + ->where('id', $sectionId) + ->first(); + + if (! $section) { + throw new NotFoundHttpException(__('error.not_found')); + } + + $bomItem = ItemBomItem::create([ + 'tenant_id' => $tenantId, + 'section_id' => $sectionId, + 'item_code' => $data['item_code'] ?? null, + 'item_name' => $data['item_name'], + 'quantity' => $data['quantity'] ?? 1, + 'unit' => $data['unit'] ?? null, + 'unit_price' => $data['unit_price'] ?? null, + 'total_price' => $data['total_price'] ?? null, + 'spec' => $data['spec'] ?? null, + 'note' => $data['note'] ?? null, + 'created_by' => $userId, + ]); + + return $bomItem; + } + + /** + * BOM 항목 수정 + */ + public function update(int $id, array $data): ItemBomItem + { + $tenantId = $this->tenantId(); + $userId = $this->apiUserId(); + + $bomItem = ItemBomItem::where('tenant_id', $tenantId) + ->where('id', $id) + ->first(); + + if (! $bomItem) { + throw new NotFoundHttpException(__('error.not_found')); + } + + $bomItem->update([ + 'item_code' => $data['item_code'] ?? $bomItem->item_code, + 'item_name' => $data['item_name'] ?? $bomItem->item_name, + 'quantity' => $data['quantity'] ?? $bomItem->quantity, + 'unit' => $data['unit'] ?? $bomItem->unit, + 'unit_price' => $data['unit_price'] ?? $bomItem->unit_price, + 'total_price' => $data['total_price'] ?? $bomItem->total_price, + 'spec' => $data['spec'] ?? $bomItem->spec, + 'note' => $data['note'] ?? $bomItem->note, + 'updated_by' => $userId, + ]); + + return $bomItem->fresh(); + } + + /** + * BOM 항목 삭제 + */ + public function destroy(int $id): void + { + $tenantId = $this->tenantId(); + $userId = $this->apiUserId(); + + $bomItem = ItemBomItem::where('tenant_id', $tenantId) + ->where('id', $id) + ->first(); + + if (! $bomItem) { + throw new NotFoundHttpException(__('error.not_found')); + } + + $bomItem->update(['deleted_by' => $userId]); + $bomItem->delete(); + } +} diff --git a/app/Services/ItemMaster/ItemMasterFieldService.php b/app/Services/ItemMaster/ItemMasterFieldService.php new file mode 100644 index 0000000..490446b --- /dev/null +++ b/app/Services/ItemMaster/ItemMasterFieldService.php @@ -0,0 +1,101 @@ +tenantId(); + + return ItemMasterField::where('tenant_id', $tenantId) + ->orderBy('category') + ->orderBy('field_name') + ->get(); + } + + /** + * 마스터 필드 생성 + */ + public function store(array $data): ItemMasterField + { + $tenantId = $this->tenantId(); + $userId = $this->apiUserId(); + + $field = ItemMasterField::create([ + 'tenant_id' => $tenantId, + 'field_name' => $data['field_name'], + 'field_type' => $data['field_type'], + 'category' => $data['category'] ?? null, + 'description' => $data['description'] ?? null, + 'is_common' => $data['is_common'] ?? false, + 'default_value' => $data['default_value'] ?? null, + 'options' => $data['options'] ?? null, + 'validation_rules' => $data['validation_rules'] ?? null, + 'properties' => $data['properties'] ?? null, + 'created_by' => $userId, + ]); + + return $field; + } + + /** + * 마스터 필드 수정 + */ + public function update(int $id, array $data): ItemMasterField + { + $tenantId = $this->tenantId(); + $userId = $this->apiUserId(); + + $field = ItemMasterField::where('tenant_id', $tenantId) + ->where('id', $id) + ->first(); + + if (! $field) { + throw new NotFoundHttpException(__('error.not_found')); + } + + $field->update([ + 'field_name' => $data['field_name'] ?? $field->field_name, + 'field_type' => $data['field_type'] ?? $field->field_type, + 'category' => $data['category'] ?? $field->category, + 'description' => $data['description'] ?? $field->description, + 'is_common' => $data['is_common'] ?? $field->is_common, + 'default_value' => $data['default_value'] ?? $field->default_value, + 'options' => $data['options'] ?? $field->options, + 'validation_rules' => $data['validation_rules'] ?? $field->validation_rules, + 'properties' => $data['properties'] ?? $field->properties, + 'updated_by' => $userId, + ]); + + return $field->fresh(); + } + + /** + * 마스터 필드 삭제 + */ + public function destroy(int $id): void + { + $tenantId = $this->tenantId(); + $userId = $this->apiUserId(); + + $field = ItemMasterField::where('tenant_id', $tenantId) + ->where('id', $id) + ->first(); + + if (! $field) { + throw new NotFoundHttpException(__('error.not_found')); + } + + $field->update(['deleted_by' => $userId]); + $field->delete(); + } +} diff --git a/app/Services/ItemMaster/SectionTemplateService.php b/app/Services/ItemMaster/SectionTemplateService.php new file mode 100644 index 0000000..f041fed --- /dev/null +++ b/app/Services/ItemMaster/SectionTemplateService.php @@ -0,0 +1,90 @@ +tenantId(); + + return SectionTemplate::where('tenant_id', $tenantId) + ->orderBy('created_at', 'desc') + ->get(); + } + + /** + * 섹션 템플릿 생성 + */ + public function store(array $data): SectionTemplate + { + $tenantId = $this->tenantId(); + $userId = $this->apiUserId(); + + $template = SectionTemplate::create([ + 'tenant_id' => $tenantId, + 'title' => $data['title'], + 'type' => $data['type'], + 'description' => $data['description'] ?? null, + 'is_default' => $data['is_default'] ?? false, + 'created_by' => $userId, + ]); + + return $template; + } + + /** + * 섹션 템플릿 수정 + */ + public function update(int $id, array $data): SectionTemplate + { + $tenantId = $this->tenantId(); + $userId = $this->apiUserId(); + + $template = SectionTemplate::where('tenant_id', $tenantId) + ->where('id', $id) + ->first(); + + if (! $template) { + throw new NotFoundHttpException(__('error.not_found')); + } + + $template->update([ + 'title' => $data['title'] ?? $template->title, + 'type' => $data['type'] ?? $template->type, + 'description' => $data['description'] ?? $template->description, + 'is_default' => $data['is_default'] ?? $template->is_default, + 'updated_by' => $userId, + ]); + + return $template->fresh(); + } + + /** + * 섹션 템플릿 삭제 + */ + public function destroy(int $id): void + { + $tenantId = $this->tenantId(); + $userId = $this->apiUserId(); + + $template = SectionTemplate::where('tenant_id', $tenantId) + ->where('id', $id) + ->first(); + + if (! $template) { + throw new NotFoundHttpException(__('error.not_found')); + } + + $template->update(['deleted_by' => $userId]); + $template->delete(); + } +} diff --git a/routes/api.php b/routes/api.php index 1281c62..50dc628 100644 --- a/routes/api.php +++ b/routes/api.php @@ -19,10 +19,13 @@ use App\Http\Controllers\Api\V1\EstimateController; use App\Http\Controllers\Api\V1\FileStorageController; use App\Http\Controllers\Api\V1\FolderController; +use App\Http\Controllers\Api\V1\ItemMaster\ItemBomItemController; use App\Http\Controllers\Api\V1\ItemMaster\ItemFieldController; use App\Http\Controllers\Api\V1\ItemMaster\ItemMasterController; +use App\Http\Controllers\Api\V1\ItemMaster\ItemMasterFieldController; use App\Http\Controllers\Api\V1\ItemMaster\ItemPageController; use App\Http\Controllers\Api\V1\ItemMaster\ItemSectionController; +use App\Http\Controllers\Api\V1\ItemMaster\SectionTemplateController; use App\Http\Controllers\Api\V1\MaterialController; use App\Http\Controllers\Api\V1\MenuController; use App\Http\Controllers\Api\V1\ModelSetController; @@ -495,6 +498,23 @@ Route::put('/fields/{id}', [ItemFieldController::class, 'update'])->name('v1.item-master.fields.update'); Route::delete('/fields/{id}', [ItemFieldController::class, 'destroy'])->name('v1.item-master.fields.destroy'); Route::put('/sections/{sectionId}/fields/reorder', [ItemFieldController::class, 'reorder'])->name('v1.item-master.fields.reorder'); + + // BOM 항목 관리 + Route::post('/sections/{sectionId}/bom-items', [ItemBomItemController::class, 'store'])->name('v1.item-master.bom-items.store'); + Route::put('/bom-items/{id}', [ItemBomItemController::class, 'update'])->name('v1.item-master.bom-items.update'); + Route::delete('/bom-items/{id}', [ItemBomItemController::class, 'destroy'])->name('v1.item-master.bom-items.destroy'); + + // 섹션 템플릿 + Route::get('/section-templates', [SectionTemplateController::class, 'index'])->name('v1.item-master.section-templates.index'); + Route::post('/section-templates', [SectionTemplateController::class, 'store'])->name('v1.item-master.section-templates.store'); + Route::put('/section-templates/{id}', [SectionTemplateController::class, 'update'])->name('v1.item-master.section-templates.update'); + Route::delete('/section-templates/{id}', [SectionTemplateController::class, 'destroy'])->name('v1.item-master.section-templates.destroy'); + + // 마스터 필드 + Route::get('/master-fields', [ItemMasterFieldController::class, 'index'])->name('v1.item-master.master-fields.index'); + Route::post('/master-fields', [ItemMasterFieldController::class, 'store'])->name('v1.item-master.master-fields.store'); + Route::put('/master-fields/{id}', [ItemMasterFieldController::class, 'update'])->name('v1.item-master.master-fields.update'); + Route::delete('/master-fields/{id}', [ItemMasterFieldController::class, 'destroy'])->name('v1.item-master.master-fields.destroy'); }); });