diff --git a/app/Http/Controllers/Api/V1/ItemsController.php b/app/Http/Controllers/Api/V1/ItemsController.php index b35cfd8..f9d82fc 100644 --- a/app/Http/Controllers/Api/V1/ItemsController.php +++ b/app/Http/Controllers/Api/V1/ItemsController.php @@ -30,6 +30,7 @@ public function index(Request $request) 'item_category' => $request->input('item_category'), 'group_id' => $request->input('group_id'), 'active' => $request->input('is_active') ?? $request->input('active'), + 'has_bom' => $request->input('has_bom'), ]; return $this->service->index($params); diff --git a/app/Services/ItemService.php b/app/Services/ItemService.php index 4c6a64a..ff781ea 100644 --- a/app/Services/ItemService.php +++ b/app/Services/ItemService.php @@ -355,6 +355,7 @@ public function index(array $params): LengthAwarePaginator $itemCategory = $params['item_category'] ?? null; $groupId = $params['group_id'] ?? null; $active = $params['active'] ?? null; + $hasBom = $params['has_bom'] ?? null; // item_type 또는 group_id 없으면 group_id = 1 기본값 적용 if (! $itemType && ! $groupId) { @@ -385,11 +386,13 @@ public function index(array $params): LengthAwarePaginator } } - // 검색어 + // 검색어 (FULLTEXT 인덱스 활용) if ($q !== '') { - $query->where(function ($w) use ($q) { - $w->where('name', 'like', "%{$q}%") - ->orWhere('code', 'like', "%{$q}%") + // FULLTEXT 검색 (name, code) + LIKE 검색 (description) + // 한글 검색을 위해 BOOLEAN MODE 사용, 와일드카드(*) 추가 + $searchTerm = '+'.str_replace(' ', '* +', $q).'*'; + $query->where(function ($w) use ($q, $searchTerm) { + $w->whereRaw('MATCH(name, code) AGAINST(? IN BOOLEAN MODE)', [$searchTerm]) ->orWhere('description', 'like', "%{$q}%"); }); } @@ -409,6 +412,21 @@ public function index(array $params): LengthAwarePaginator $query->where('is_active', (bool) $active); } + // BOM 유무 필터 (has_bom=1: BOM 있는 품목만, has_bom=0: BOM 없는 품목만) + if ($hasBom !== null && $hasBom !== '') { + if (filter_var($hasBom, FILTER_VALIDATE_BOOLEAN)) { + // BOM이 있는 품목만 (bom이 null이 아니고 빈 배열이 아님) + $query->whereNotNull('bom') + ->whereRaw('JSON_LENGTH(bom) > 0'); + } else { + // BOM이 없는 품목만 + $query->where(function ($q) { + $q->whereNull('bom') + ->orWhereRaw('JSON_LENGTH(bom) = 0'); + }); + } + } + $paginator = $query->orderBy('id', 'desc')->paginate($size); // 날짜 형식 변환, files 그룹화, options 펼침, code → item_code @@ -434,6 +452,9 @@ public function index(array $params): LengthAwarePaginator // has_bom 계산 필드 추가 (BOM이 있는 품목 필터링에 사용) $arr['has_bom'] = ! empty($arr['bom']) && is_array($arr['bom']) && count($arr['bom']) > 0; + // name 필드를 "코드 이름" 형식으로 변경 (일시적) + $arr['name'] = trim(($arr['item_code'] ?? '').' '.($arr['name'] ?? '')); + return $arr; }) );