-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathLibraryController.java
More file actions
326 lines (278 loc) · 18.8 KB
/
LibraryController.java
File metadata and controls
326 lines (278 loc) · 18.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
package DiffLens.back_end.domain.library.controller;
import DiffLens.back_end.domain.library.dto.LibraryRequestDto;
import DiffLens.back_end.domain.library.dto.LibraryResponseDTO;
import DiffLens.back_end.domain.library.dto.LibraryCompareRequestDTO;
import DiffLens.back_end.domain.library.dto.LibraryCompareResponseDTO;
import DiffLens.back_end.domain.library.service.LibraryService;
import DiffLens.back_end.domain.members.entity.Member;
import DiffLens.back_end.domain.members.service.auth.CurrentUserService;
import DiffLens.back_end.global.responses.exception.ApiResponse;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@Tag(name = "라이브러리 API")
@RestController
@RequestMapping("/libraries")
@RequiredArgsConstructor
public class LibraryController {
private final LibraryService libraryService;
private final CurrentUserService currentUserService;
@GetMapping
@Operation(summary = "라이브러리 목록 조회", description = """
## 개요
인증된 사용자가 생성한 라이브러리 목록을 조회하는 API입니다.
## 응답
- libraries : 라이브러리 목록 배열
- library_id : 라이브러리 ID
- library_name : 라이브러리 이름
- tags : 라이브러리 분류 태그 리스트
- panel_count : 저장된 패널 개수
- created_at : 생성 시간
- page_info : 페이징 정보 (현재는 null, 추후 구현 예정)
## 권한
본인이 생성한 라이브러리만 조회할 수 있습니다.
## 정렬
최근 생성된 순서로 정렬됩니다.
""")
public ApiResponse<LibraryResponseDTO.ListResult> libraryList() {
Member member = currentUserService.getCurrentUser();
LibraryResponseDTO.ListResult result = libraryService.getLibrariesByMember(member);
return ApiResponse.onSuccess(result);
}
@PostMapping
@Operation(summary = "라이브러리 생성", description = """
## 개요
검색 기록을 기반으로 라이브러리를 생성하는 API입니다.
## Request Body
- search_history_id : 저장할 검색 기록의 ID (필수)
- library_name : 라이브러리 이름 (필수)
- tags : 라이브러리 분류 태그 리스트 (필수)
- panel_ids : 저장할 패널 ID 리스트 (선택, null이면 검색 기록의 모든 패널 저장)
## 응답
- library_id : 생성된 라이브러리 ID
- library_name : 라이브러리 이름
- search_history_id : 연결된 검색 기록 ID
- panel_count : 저장된 패널 개수
- created_at : 생성 시간
## 권한
본인의 검색 기록만 라이브러리로 저장할 수 있습니다.
""")
public ApiResponse<LibraryResponseDTO.CreateResult> createLibrary(
@RequestBody @Valid LibraryRequestDto.Create request) {
Member member = currentUserService.getCurrentUser();
LibraryService.LibraryCreateResult createResult = libraryService.createLibrary(request, member);
LibraryResponseDTO.CreateResult result = LibraryResponseDTO.CreateResult.from(
createResult.getLibrary(),
request.getSearchHistoryId(),
createResult.getPanelCount());
return ApiResponse.onSuccess(result);
}
@GetMapping("/{libraryId}")
@Operation(summary = "특정 라이브러리 상세 조회", description = """
## 개요
특정 라이브러리의 상세 정보를 조회하는 API입니다.
## Path Parameters
- libraryId : 조회할 라이브러리 ID
## 응답 데이터
- 라이브러리 기본 정보 (이름, 태그, 생성일, 수정일)
- 포함된 패널들의 상세 정보
- 연결된 검색기록들 -> 혹시 몰라 추가한 로직으로 필요 없다고 판단될 시 안쓰셔도 됩니다.
- 패널 통계 정보 (성별, 연령대, 거주지 분포) -> 혹시 몰라 추가한 로직으로 필요 없다고 판단될 시 안쓰셔도 됩니다.
## 권한
본인이 생성한 라이브러리만 조회할 수 있습니다.
""")
public ApiResponse<LibraryResponseDTO.LibraryDetail> getLibraryDetail(@PathVariable Long libraryId) {
Member member = currentUserService.getCurrentUser();
LibraryResponseDTO.LibraryDetail result = libraryService.getLibraryDetail(libraryId, member);
return ApiResponse.onSuccess(result);
}
@PutMapping("/{libraryId}/search-histories/{searchHistoryId}")
@Operation(summary = "기존 라이브러리에 새로운 검색기록 추가(병합)", description = """
## 개요
기존 라이브러리에 검색기록을 추가하는 API입니다.
라이브러리의 패널 ID와 검색기록의 패널 ID를 병합하여 중복을 제거합니다.
## Path Parameters
- libraryId : 라이브러리 ID
- searchHistoryId : 추가할 검색기록 ID
## 응답
- library_id : 라이브러리 ID
- library_name : 라이브러리 이름
- search_history_id : 추가된 검색기록 ID
- panel_count : 새로 추가된 패널 개수
- panel_ids : 병합된 전체 패널 ID 리스트
- created_at : 생성 시간
## 권한
본인의 라이브러리와 검색기록만 사용할 수 있습니다.
## 예시
- 라이브러리 1번에 패널 ID [1, 2, 3]이 있음
- 검색기록 2번에 패널 ID [3, 4, 5]가 있음
- 결과: 라이브러리 1번에 패널 ID [1, 2, 3, 4, 5]가 됨
""")
public ApiResponse<LibraryResponseDTO.CreateResult> addSearchHistoryToLibrary(
@PathVariable Long libraryId,
@PathVariable Long searchHistoryId) {
Member member = currentUserService.getCurrentUser();
LibraryService.LibraryCreateResult createResult = libraryService.addSearchHistoryToLibrary(libraryId,
searchHistoryId, member);
LibraryResponseDTO.CreateResult result = LibraryResponseDTO.CreateResult.from(
createResult.getLibrary(),
searchHistoryId,
createResult.getPanelCount());
return ApiResponse.onSuccess(result);
}
@PostMapping("/compare")
@Operation(summary = "라이브러리 비교", description = """
## 개요
두 개의 라이브러리를 비교하여 특성, 차트, 기본 통계를 제공하는 API입니다.
## Request Body
- libraryId1 : 첫 번째 라이브러리 ID (필수)
- libraryId2 : 두 번째 라이브러리 ID (필수)
## 응답 데이터
- group1, group2 : 각 라이브러리 기본 정보
- keyCharacteristics : 주요 특성 비교 (차이점 포함)
- comparisonCharts : 비교 차트 데이터 (Chart.js 형식)
- comparisons : 기본 통계 비교
## 권한
본인이 생성한 라이브러리만 비교할 수 있습니다.
## 제약사항
- 동일한 라이브러리는 비교할 수 없습니다.
- 두 라이브러리 모두 존재해야 합니다.
""")
public ApiResponse<LibraryCompareResponseDTO.CompareResult> compareLibraries(
@RequestBody @Valid LibraryCompareRequestDTO.Compare request) {
Member member = currentUserService.getCurrentUser();
LibraryCompareResponseDTO.CompareResult result = libraryService.compareLibraries(request, member);
return ApiResponse.onSuccess(result);
}
@PostMapping("/compare/test")
@Operation(summary = "라이브러리 비교 (테스트용)", description = """
## 개요
AI 서버 연동 없이 하드코딩된 테스트 데이터로 라이브러리 비교를 제공하는 API입니다.
개발 및 테스트 목적으로 사용됩니다.
## Request Body
- libraryId1 : 첫 번째 라이브러리 ID (필수, 실제로는 사용하지 않음)
- libraryId2 : 두 번째 라이브러리 ID (필수, 실제로는 사용하지 않음)
## 응답 데이터
- 하드코딩된 테스트 데이터 반환
- 실제 라이브러리 데이터는 사용하지 않음
## 권한
인증된 사용자만 접근 가능합니다.
""")
public ApiResponse<LibraryCompareResponseDTO.CompareResult> compareLibrariesTest(
@RequestBody @Valid LibraryCompareRequestDTO.Compare request) {
// Group A 정보
LibraryCompareResponseDTO.GroupInfo group1 = LibraryCompareResponseDTO.GroupInfo.builder()
.libraryId(1L)
.libraryName("20대 남성이 타는 차 브랜드 분포")
.summary("20대 남성 소비자의 자동차 브랜드 선호도 분석")
.totalCount(100)
.filters(List.of(
LibraryCompareResponseDTO.Filter.builder()
.key("성별")
.values(List.of("남성"))
.build(),
LibraryCompareResponseDTO.Filter.builder()
.key("연령")
.values(List.of("20-29세"))
.build(),
LibraryCompareResponseDTO.Filter.builder()
.key("차량보유")
.values(List.of("있음"))
.build()))
.color("#4169E1")
.build();
// Group B 정보
LibraryCompareResponseDTO.GroupInfo group2 = LibraryCompareResponseDTO.GroupInfo.builder()
.libraryId(2L)
.libraryName("30대 여성 화장품 구매 패턴")
.summary("30대 여성의 화장품 구매 행동 및 선호 브랜드 분석")
.totalCount(250)
.filters(List.of(
LibraryCompareResponseDTO.Filter.builder()
.key("성별")
.values(List.of("여성"))
.build(),
LibraryCompareResponseDTO.Filter.builder()
.key("연령")
.values(List.of("30-39세"))
.build()))
.color("#FF69B4")
.build();
// 주요 특성 (특성 1, 2, 3)
List<LibraryCompareResponseDTO.KeyCharacteristic> keyCharacteristics = List.of(
LibraryCompareResponseDTO.KeyCharacteristic.builder()
.characteristic("소비 성향")
.description("A그룹은 실용적 소비 성향이 강하고, B그룹은 프리미엄 브랜드 선호도가 높습니다.")
.group1Percentage(30)
.group2Percentage(70)
.difference(40)
.build(),
LibraryCompareResponseDTO.KeyCharacteristic.builder()
.characteristic("브랜드 충성도")
.description("A그룹은 브랜드 전환율이 높은 반면, B그룹은 특정 브랜드에 대한 충성도가 높습니다.")
.group1Percentage(30)
.group2Percentage(70)
.difference(40)
.build(),
LibraryCompareResponseDTO.KeyCharacteristic.builder()
.characteristic("온라인 구매 선호도")
.description("A그룹은 오프라인 구매를 선호하고, B그룹은 온라인 쇼핑몰과 리뷰를 적극 활용합니다.")
.group1Percentage(30)
.group2Percentage(70)
.difference(40)
.build());
// Group A 통계
LibraryCompareResponseDTO.GroupMetrics group1Metrics = LibraryCompareResponseDTO.GroupMetrics.builder()
.male(100)
.female(0)
.seoul(35)
.gyeonggi(40)
.busan(15)
.regionEtc(10)
.avgAge(23.5)
.avgFamily(3.2)
.avgChildren(0.8)
.ratePossessingCar(72)
.avgPersonalIncome(420)
.avgFamilyIncome(340)
.build();
// Group B 통계
LibraryCompareResponseDTO.GroupMetrics group2Metrics = LibraryCompareResponseDTO.GroupMetrics.builder()
.male(0)
.female(100)
.seoul(35)
.gyeonggi(40)
.busan(15)
.regionEtc(10)
.avgAge(32.7)
.avgFamily(4.2)
.avgChildren(3.4)
.ratePossessingCar(30)
.avgPersonalIncome(340)
.avgFamilyIncome(500)
.build();
// Comparisons
LibraryCompareResponseDTO.Comparisons comparisons = LibraryCompareResponseDTO.Comparisons.builder()
.group1(group1Metrics)
.group2(group2Metrics)
.build();
// Insights
LibraryCompareResponseDTO.Insights insights = LibraryCompareResponseDTO.Insights.builder()
.difference("A그룹(20대 남성)은 차량 구매에 있어 실용성과 가성비를 중시하며, 국산 브랜드 선호도가 높습니다. 반면 B그룹(30대 여성)은 화장품 구매 시 브랜드 이미지와 품질을 중시하며, 프리미엄 브랜드에 대한 지출이 큽니다. 또한 A그룹은 차량 보유율이 72%로 높은 반면, B그룹은 30%로 낮아 이동 수단에 대한 접근 방식이 다릅니다.")
.common("두 그룹 모두 서울과 경기 지역에 집중되어 있으며, 지역 분포가 거의 동일합니다. 또한 모두 온라인 쇼핑 플랫폼을 적극 활용하며, 소셜미디어를 통한 제품 정보 습득이 활발합니다.")
.implication("A그룹은 차량 마케팅 시 실용성과 경제성을 강조하는 전략이 효과적일 것입니다. B그룹은 화장품 마케팅 시 브랜드 스토리텔링과 프리미엄 경험 제공이 중요합니다. 두 그룹 모두 지역별 맞춤 마케팅 전략이 필요하며, 온라인 채널을 통한 타겟팅이 핵심입니다.")
.build();
// 최종 결과 생성
LibraryCompareResponseDTO.CompareResult result = LibraryCompareResponseDTO.CompareResult.builder()
.group1(group1)
.group2(group2)
.keyCharacteristics(keyCharacteristics)
.comparisons(comparisons)
.insights(insights)
.build();
return ApiResponse.onSuccess(result);
}
}