diff --git a/app/Http/Controllers/Api/V1/ItemsController.php b/app/Http/Controllers/Api/V1/ItemsController.php index a32b24f..0944471 100644 --- a/app/Http/Controllers/Api/V1/ItemsController.php +++ b/app/Http/Controllers/Api/V1/ItemsController.php @@ -27,6 +27,7 @@ public function index(Request $request) 'q' => $request->input('q') ?? $request->input('search'), 'category_id' => $request->input('category_id'), 'item_type' => $request->input('type') ?? $request->input('item_type'), + 'group_id' => $request->input('group_id'), 'active' => $request->input('is_active') ?? $request->input('active'), ]; diff --git a/app/Services/ItemService.php b/app/Services/ItemService.php index 68f5d31..552d0ce 100644 --- a/app/Services/ItemService.php +++ b/app/Services/ItemService.php @@ -79,6 +79,32 @@ private function newQuery(string $itemType) ->where('item_type', strtoupper($itemType)); } + /** + * group_id로 해당 그룹의 item_type 목록 조회 + * + * @param int $groupId common_codes의 item_group id + * @return array item_type 코드 배열 ['FG', 'PT', 'SM', 'RM', 'CS'] + */ + private function getItemTypesByGroupId(int $groupId): array + { + return \DB::table('common_codes') + ->where('code_group', 'item_type') + ->where('parent_id', $groupId) + ->where('is_active', true) + ->pluck('code') + ->toArray(); + } + + /** + * 여러 item_type으로 Query Builder 생성 + */ + private function newQueryForTypes(array $itemTypes) + { + return \App\Models\Items\Item::query() + ->where('tenant_id', $this->tenantId()) + ->whereIn('item_type', array_map('strtoupper', $itemTypes)); + } + /** * items 테이블의 고정 컬럼 목록 조회 (SystemFields + ItemField 기반) */ @@ -252,7 +278,7 @@ protected function fetchCategoryTree(?int $parentId = null) /** * 목록/검색 (동적 테이블 라우팅) * - * @param array $params 검색 파라미터 (item_type 필수) + * @param array $params 검색 파라미터 (item_type 또는 group_id 필수) */ public function index(array $params): LengthAwarePaginator { @@ -260,16 +286,27 @@ public function index(array $params): LengthAwarePaginator $q = trim((string) ($params['q'] ?? $params['search'] ?? '')); $categoryId = $params['category_id'] ?? null; $itemType = $params['item_type'] ?? null; + $groupId = $params['group_id'] ?? null; $active = $params['active'] ?? null; - // item_type 필수 검증 - if (! $itemType) { - throw new BadRequestHttpException(__('error.item_type_required')); + // item_type 또는 group_id 필수 검증 + if (! $itemType && ! $groupId) { + throw new BadRequestHttpException(__('error.item_type_or_group_required')); } - // 동적 테이블 라우팅 - $query = $this->newQuery($itemType) - ->with(['category:id,name', 'details']); + // group_id로 조회 시 해당 그룹의 모든 item_type 조회 + if ($groupId && ! $itemType) { + $itemTypes = $this->getItemTypesByGroupId((int) $groupId); + if (empty($itemTypes)) { + throw new BadRequestHttpException(__('error.invalid_group_id')); + } + $query = $this->newQueryForTypes($itemTypes) + ->with(['category:id,name', 'details']); + } else { + // 단일 item_type 조회 + $query = $this->newQuery($itemType) + ->with(['category:id,name', 'details']); + } // 검색어 if ($q !== '') { diff --git a/database/migrations/2025_12_15_143850_add_item_group_to_common_codes.php b/database/migrations/2025_12_15_143850_add_item_group_to_common_codes.php new file mode 100644 index 0000000..460ec8f --- /dev/null +++ b/database/migrations/2025_12_15_143850_add_item_group_to_common_codes.php @@ -0,0 +1,66 @@ +insertGetId([ + 'tenant_id' => 1, + 'code_group' => 'item_group', + 'code' => 'ITEM', + 'name' => '품목', + 'description' => '품목 관리 그룹 (FG, PT, SM, RM, CS)', + 'is_active' => true, + 'sort_order' => 1, + 'created_at' => now(), + 'updated_at' => now(), + ]); + + // 2. 기존 item_type의 parent_id를 item_group으로 연결 + DB::table('common_codes') + ->where('code_group', 'item_type') + ->whereIn('code', ['FG', 'PT', 'SM', 'RM', 'CS']) + ->update(['parent_id' => $itemGroupId]); + + // 3. item_type의 attributes에서 source_table을 items로 통일 + $itemTypes = DB::table('common_codes') + ->where('code_group', 'item_type') + ->whereIn('code', ['FG', 'PT', 'SM', 'RM', 'CS']) + ->get(); + + foreach ($itemTypes as $itemType) { + $attributes = json_decode($itemType->attributes, true) ?? []; + $attributes['source_table'] = 'items'; + + DB::table('common_codes') + ->where('id', $itemType->id) + ->update(['attributes' => json_encode($attributes)]); + } + } + + public function down(): void + { + // 1. item_type의 parent_id 초기화 + DB::table('common_codes') + ->where('code_group', 'item_type') + ->whereIn('code', ['FG', 'PT', 'SM', 'RM', 'CS']) + ->update(['parent_id' => null]); + + // 2. item_group 삭제 + DB::table('common_codes') + ->where('code_group', 'item_group') + ->where('code', 'ITEM') + ->delete(); + } +}; diff --git a/lang/ko/error.php b/lang/ko/error.php index 42815d9..af52cdb 100644 --- a/lang/ko/error.php +++ b/lang/ko/error.php @@ -112,7 +112,9 @@ 'field_key_reserved' => '":field_key"은(는) 시스템 예약어로 사용할 수 없습니다.', 'bom_not_found' => 'BOM 항목을 찾을 수 없습니다.', 'item_type_required' => '품목 유형(item_type)은 필수입니다.', + 'item_type_or_group_required' => '품목 유형(item_type) 또는 그룹 ID(group_id)는 필수입니다.', 'invalid_item_type' => '유효하지 않은 품목 유형입니다.', + 'invalid_group_id' => '유효하지 않은 그룹 ID이거나 해당 그룹에 품목 유형이 없습니다.', 'invalid_source_table' => '품목 유형에 대한 소스 테이블이 설정되지 않았습니다.', // 품목 관리 관련