Skip to content

Commit 78e63d4

Browse files
authored
fix/OPS-400 : 수정&삭제 요구사항 반영 (#169)
1 parent 93263ef commit 78e63d4

File tree

6 files changed

+78
-14
lines changed

6 files changed

+78
-14
lines changed

src/main/java/org/tuna/zoopzoop/backend/domain/datasource/controller/DataSourceController.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import org.springframework.web.bind.annotation.*;
1515
import org.springframework.web.multipart.MultipartFile;
1616
import org.tuna.zoopzoop.backend.domain.datasource.dto.*;
17+
import org.tuna.zoopzoop.backend.domain.datasource.entity.Category;
1718
import org.tuna.zoopzoop.backend.domain.datasource.service.DataSourceService;
1819
import org.tuna.zoopzoop.backend.domain.datasource.service.PersonalDataSourceService;
1920
import org.tuna.zoopzoop.backend.global.rsData.RsData;
@@ -212,8 +213,9 @@ public ResponseEntity<RsData<SearchResponse<DataSourceSearchItem>>> search(
212213
@PageableDefault(size = 8, sort = "createdAt", direction = Sort.Direction.DESC) Pageable pageable,
213214
@AuthenticationPrincipal CustomUserDetails user
214215
) {
216+
Category categoryEnum = category != null ? Category.from(category) : null;
215217
var cond = DataSourceSearchCondition.builder()
216-
.title(title).summary(summary).category(category).folderId(folderId)
218+
.title(title).summary(summary).category(categoryEnum).folderId(folderId)
217219
.folderName(folderName).isActive(isActive).keyword(keyword).build();
218220

219221
Page<DataSourceSearchItem> page = personalApp.search(user.getMember().getId(), cond, pageable);

src/main/java/org/tuna/zoopzoop/backend/domain/datasource/dto/DataSourceSearchCondition.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,15 @@
22

33
import lombok.Builder;
44
import lombok.Getter;
5+
import org.tuna.zoopzoop.backend.domain.datasource.entity.Category;
56

67
@Getter
78
@Builder
89
public class DataSourceSearchCondition {
910
private final String title;
1011
private final String summary;
11-
private final String category;
12-
private final String Source;
12+
private final Category category;
13+
// private final String Source;
1314
private final Integer folderId;
1415
private final String folderName;
1516
private final Boolean isActive;

src/main/java/org/tuna/zoopzoop/backend/domain/datasource/entity/Category.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package org.tuna.zoopzoop.backend.domain.datasource.entity;
22

3+
import com.fasterxml.jackson.annotation.JsonCreator;
4+
35
public enum Category {
46
POLITICS("정치"),
57
ECONOMY("경제"),
@@ -29,4 +31,22 @@ public boolean isBlank() {
2931
public String toUpperCase() {
3032
return this.name.toUpperCase();
3133
}
34+
35+
// JSON 문자열을 Category enum으로 변환
36+
@JsonCreator
37+
public static Category from(String input) {
38+
if (input == null || input.isBlank()) return null;
39+
if (input.equalsIgnoreCase("IT")) return IT; // IT 예외
40+
41+
// 1) 한글 이름 매칭
42+
for (Category c : values()) {
43+
if (c.getName().equalsIgnoreCase(input)) return c;
44+
}
45+
// 2) 영문 코드 fallback (e.g., "SPORTS")
46+
try {
47+
return Category.valueOf(input.toUpperCase());
48+
} catch (IllegalArgumentException ex) {
49+
throw new IllegalArgumentException("유효하지 않은 카테고리 값입니다: " + input);
50+
}
51+
}
3252
}

src/main/java/org/tuna/zoopzoop/backend/domain/datasource/repository/DataSourceQRepositoryImpl.java

Lines changed: 48 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import org.tuna.zoopzoop.backend.domain.archive.folder.entity.QFolder;
1818
import org.tuna.zoopzoop.backend.domain.datasource.dto.DataSourceSearchCondition;
1919
import org.tuna.zoopzoop.backend.domain.datasource.dto.DataSourceSearchItem;
20+
import org.tuna.zoopzoop.backend.domain.datasource.entity.Category;
2021
import org.tuna.zoopzoop.backend.domain.datasource.entity.QDataSource;
2122
import org.tuna.zoopzoop.backend.domain.datasource.entity.QTag;
2223

@@ -51,19 +52,28 @@ public Page<DataSourceSearchItem> search(Integer memberId, DataSourceSearchCondi
5152

5253
if (hasText(cond.getTitle())) where.and(ds.title.containsIgnoreCase(cond.getTitle()));
5354
if (hasText(cond.getSummary())) where.and(ds.summary.containsIgnoreCase(cond.getSummary()));
54-
if (hasText(cond.getCategory())) where.and(ds.category.stringValue().containsIgnoreCase(cond.getCategory()));
55-
if (hasText(cond.getSource())) where.and(ds.source.containsIgnoreCase(cond.getSource()));
55+
if (cond.getCategory() != null) where.and(ds.category.eq(cond.getCategory()));
5656

57+
// 키워드 검색 (카테고리는 "한글 라벨 정확 일치" + IT 예외만 허용)
5758
if (hasText(cond.getKeyword())) {
5859
String kw = cond.getKeyword();
60+
61+
BooleanBuilder categoryMatch = new BooleanBuilder();
62+
Category cat = resolveCategoryFromKoreanOrIT(kw); // 한글 또는 IT만 매칭
63+
if (cat != null) {
64+
categoryMatch.or(ds.category.eq(cat));
65+
}
66+
// 영어 ENUM 문자열로의 비교는 제거 (ds.category.stringValue().containsIgnoreCase(kw) 금지)
67+
5968
where.and(
6069
ds.title.containsIgnoreCase(kw)
6170
.or(ds.summary.containsIgnoreCase(kw))
6271
.or(ds.source.containsIgnoreCase(kw))
63-
.or(ds.category.stringValue().containsIgnoreCase(kw))
72+
.or(categoryMatch)
6473
);
6574
}
6675

76+
// 폴더 조건
6777
if (hasText(cond.getFolderName())) where.and(ds.folder.name.eq(cond.getFolderName()));
6878
if (cond.getFolderId() != null) where.and(ds.folder.id.eq(cond.getFolderId()));
6979

@@ -156,33 +166,46 @@ public Page<DataSourceSearchItem> searchInArchive(Integer archiveId, DataSourceS
156166
QTag tag = QTag.tag;
157167

158168
BooleanBuilder where = new BooleanBuilder();
169+
170+
// 활성/비활성
159171
if (cond.getIsActive() == null || Boolean.TRUE.equals(cond.getIsActive())) where.and(ds.isActive.isTrue());
160172
else where.and(ds.isActive.isFalse());
161173

174+
// 개별 필드 필터
162175
if (hasText(cond.getTitle())) where.and(ds.title.containsIgnoreCase(cond.getTitle()));
163176
if (hasText(cond.getSummary())) where.and(ds.summary.containsIgnoreCase(cond.getSummary()));
164-
if (hasText(cond.getCategory())) where.and(ds.category.stringValue().containsIgnoreCase(cond.getCategory()));
165-
if (hasText(cond.getSource())) where.and(ds.source.containsIgnoreCase(cond.getSource()));
177+
if (cond.getCategory() != null) where.and(ds.category.eq(cond.getCategory()));
178+
179+
// 키워드 검색 (카테고리는 "한글 라벨 정확 일치" + IT 예외만 허용)
166180
if (hasText(cond.getKeyword())) {
167181
String kw = cond.getKeyword();
182+
183+
BooleanBuilder categoryMatch = new BooleanBuilder();
184+
Category cat = resolveCategoryFromKoreanOrIT(kw);
185+
if (cat != null) {
186+
categoryMatch.or(ds.category.eq(cat));
187+
}
188+
// 영어 ENUM 문자열 비교 제거
189+
168190
where.and(
169191
ds.title.containsIgnoreCase(kw)
170192
.or(ds.summary.containsIgnoreCase(kw))
171193
.or(ds.source.containsIgnoreCase(kw))
172-
.or(ds.category.stringValue().containsIgnoreCase(kw))
194+
.or(categoryMatch)
173195
);
174196
}
175-
if (hasText(cond.getFolderName())) where.and(ds.folder.name.eq(cond.getFolderName()));
176-
if (cond.getFolderId() != null) where.and(ds.folder.id.eq(cond.getFolderId()));
177197

198+
// 아카이브 스코프
178199
BooleanBuilder scope = new BooleanBuilder().and(folder.archive.id.eq(archiveId));
179200

201+
// count
180202
JPAQuery<Long> countQuery = queryFactory
181203
.select(ds.id.countDistinct())
182204
.from(ds)
183205
.join(ds.folder, folder)
184206
.where(where.and(scope));
185207

208+
// content
186209
JPAQuery<Tuple> contentQuery = queryFactory
187210
.select(ds.id, ds.title, ds.dataCreatedDate, ds.summary, ds.source, ds.sourceUrl, ds.imageUrl, ds.category)
188211
.from(ds)
@@ -220,10 +243,26 @@ public Page<DataSourceSearchItem> searchInArchive(Integer archiveId, DataSourceS
220243
row.get(ds.sourceUrl),
221244
row.get(ds.imageUrl),
222245
tagsById.getOrDefault(row.get(ds.id), List.of()),
223-
row.get(ds.category).name()
246+
row.get(ds.category).name() // 응답은 영문 코드 유지
224247
))
225248
.toList();
226249

227250
return new PageImpl<>(content, pageable, total);
228251
}
252+
253+
/**
254+
* 키워드가 "IT"(대소문자 무시)이면 IT를, 그 외에는
255+
* 카테고리의 한글 라벨과 "정확 일치"할 때만 해당 Enum을 반환.
256+
* (예: "스포츠" -> SPORTS, "SPORTS" -> null)
257+
*/
258+
private Category resolveCategoryFromKoreanOrIT(String kw) {
259+
if (kw == null || kw.isBlank()) return null;
260+
if ("IT".equalsIgnoreCase(kw)) return Category.IT; // 유일한 영문 예외
261+
for (Category c : Category.values()) {
262+
if (c != Category.IT && c.getName().equalsIgnoreCase(kw)) {
263+
return c; // 한글 라벨 정확 일치
264+
}
265+
}
266+
return null; // 영문 코드 등은 매칭하지 않음
267+
}
229268
}

src/main/java/org/tuna/zoopzoop/backend/domain/space/archive/controller/SpaceArchiveDataSourceController.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import org.springframework.web.bind.annotation.*;
1515
import org.springframework.web.multipart.MultipartFile;
1616
import org.tuna.zoopzoop.backend.domain.datasource.dto.*;
17+
import org.tuna.zoopzoop.backend.domain.datasource.entity.Category;
1718
import org.tuna.zoopzoop.backend.domain.datasource.service.DataSourceService;
1819
import org.tuna.zoopzoop.backend.domain.space.archive.service.SpaceDataSourceService;
1920
import org.tuna.zoopzoop.backend.global.rsData.RsData;
@@ -239,8 +240,9 @@ public ResponseEntity<RsData<SearchResponse<DataSourceSearchItem>>> search(
239240
@PageableDefault(size = 8, sort = "createdAt", direction = Sort.Direction.DESC) Pageable pageable,
240241
@AuthenticationPrincipal CustomUserDetails user
241242
) {
243+
Category categoryEnum = category != null ? Category.from(category) : null;
242244
var cond = DataSourceSearchCondition.builder()
243-
.title(title).summary(summary).category(category).folderId(folderId)
245+
.title(title).summary(summary).category(categoryEnum).folderId(folderId)
244246
.folderName(folderName).isActive(isActive).keyword(keyword).build();
245247

246248
Page<DataSourceSearchItem> page = spaceApp.search(user.getMember().getId(), spaceId, cond, pageable);

src/test/java/org/tuna/zoopzoop/backend/domain/datasource/repository/DataSourceQRepositoryImplTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ void filter_summary_contains() {
160160
void filter_category_contains() {
161161
Pageable pageable = PageRequest.of(0, 10);
162162
DataSourceSearchCondition cond = DataSourceSearchCondition.builder()
163-
.category("it")
163+
.category(Category.IT)
164164
.build();
165165

166166
Page<DataSourceSearchItem> page = dataSourceQRepository.search(memberId, cond, pageable);

0 commit comments

Comments
 (0)