feat: 품목 조회 시 BOM 유무 필터 및 코드+이름 형식 지원

- has_bom 파라미터 추가 (1: BOM 있는 품목만, 0: BOM 없는 품목만)
- JSON_LENGTH 활용한 BOM 유무 필터링 구현
- name 필드를 "코드 이름" 형식으로 반환 (일시적 변경)
- FULLTEXT 인덱스 활용 검색 개선 (BOOLEAN MODE)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-27 12:47:38 +09:00
parent eeb55d1c28
commit 3ff3c65ade
2 changed files with 26 additions and 4 deletions

View File

@@ -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);

View File

@@ -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;
})
);