Skip to content

Commit b0b0272

Browse files
authored
Merge pull request #183 from o-ddong/develop
fix: 내 체험단, 관심공고, 팝업 API 변경된 case 적용
2 parents 410f620 + 7e9c7d9 commit b0b0272

13 files changed

+419
-92
lines changed

src/main/java/com/example/cherrydan/campaign/controller/BookmarkController.java

Lines changed: 20 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3,27 +3,22 @@
33
import com.example.cherrydan.campaign.dto.BookmarkDeleteDTO;
44
import com.example.cherrydan.campaign.dto.BookmarkCancelDTO;
55
import com.example.cherrydan.campaign.dto.BookmarkResponseDTO;
6+
import com.example.cherrydan.campaign.domain.BookmarkCase;
67
import com.example.cherrydan.campaign.service.BookmarkService;
78
import com.example.cherrydan.common.response.ApiResponse;
89
import com.example.cherrydan.common.response.PageListResponseDTO;
910
import com.example.cherrydan.common.response.EmptyResponse;
11+
import com.example.cherrydan.common.exception.CampaignException;
12+
import com.example.cherrydan.common.exception.ErrorMessage;
1013
import com.example.cherrydan.oauth.security.jwt.UserDetailsImpl;
1114
import lombok.RequiredArgsConstructor;
12-
import org.springframework.data.domain.Page;
1315
import org.springframework.data.domain.Pageable;
14-
import org.springframework.data.web.PageableDefault;
16+
import org.springframework.http.ResponseEntity;
1517
import org.springframework.security.core.annotation.AuthenticationPrincipal;
1618
import org.springframework.web.bind.annotation.*;
17-
import java.util.List;
1819
import io.swagger.v3.oas.annotations.Operation;
1920
import io.swagger.v3.oas.annotations.Parameter;
2021
import io.swagger.v3.oas.annotations.tags.Tag;
21-
import com.example.cherrydan.common.response.ApiResponse;
22-
import org.springframework.http.ResponseEntity;
23-
import org.springframework.data.domain.Page;
24-
import org.springframework.data.domain.Pageable;
25-
import org.springframework.data.domain.PageRequest;
26-
import com.example.cherrydan.common.response.PageListResponseDTO;
2722
import jakarta.validation.Valid;
2823

2924
@Tag(name = "Bookmark", description = "캠페인 북마크(찜) 관련 API")
@@ -54,29 +49,26 @@ public ResponseEntity<ApiResponse<EmptyResponse>> cancelBookmark(
5449
}
5550

5651
@Operation(
57-
summary = "오늘+기간 남은 북마크 목록 조회",
58-
description = "오늘 이후 reviewerAnnouncement가 남아있는 북마크 목록을 조회합니다."
59-
)
60-
@GetMapping("/bookmarks/open")
61-
public ResponseEntity<ApiResponse<PageListResponseDTO<BookmarkResponseDTO>>> getOpenBookmarks(
62-
@AuthenticationPrincipal UserDetailsImpl currentUser,
63-
Pageable pageable
64-
) {
65-
PageListResponseDTO<BookmarkResponseDTO> result = bookmarkService.getOpenBookmarks(currentUser.getId(), pageable);
66-
return ResponseEntity.ok(ApiResponse.success("기간 남은 북마크 목록 조회 성공", result));
67-
}
68-
69-
@Operation(
70-
summary = "기간 지난 북마크 목록 조회",
71-
description = "오늘 이전 reviewerAnnouncement가 지난 북마크 목록을 조회합니다."
52+
summary = "북마크 목록 조회",
53+
description = "case 파라미터(open/closed)로 북마크 목록을 조회합니다. open: 기간 남은 북마크, closed: 기간 지난 북마크"
7254
)
73-
@GetMapping("/bookmarks/closed")
74-
public ResponseEntity<ApiResponse<PageListResponseDTO<BookmarkResponseDTO>>> getClosedBookmarks(
55+
@GetMapping("/bookmarks")
56+
public ResponseEntity<ApiResponse<PageListResponseDTO<BookmarkResponseDTO>>> getBookmarksByCase(
57+
@Parameter(description = "북마크 케이스 (open: 기간 남은 북마크, closed: 기간 지난 북마크)", required = false)
58+
@RequestParam(value = "case", defaultValue = "open") String caseParam,
7559
@AuthenticationPrincipal UserDetailsImpl currentUser,
7660
Pageable pageable
7761
) {
78-
PageListResponseDTO<BookmarkResponseDTO> result = bookmarkService.getClosedBookmarks(currentUser.getId(), pageable);
79-
return ResponseEntity.ok(ApiResponse.success("기간 지난 북마크 목록 조회 성공", result));
62+
BookmarkCase bookmarkCase;
63+
try {
64+
bookmarkCase = BookmarkCase.fromCode(caseParam.trim());
65+
} catch (IllegalArgumentException e) {
66+
throw new CampaignException(ErrorMessage.CAMPAIGN_STATUS_INVALID);
67+
}
68+
69+
PageListResponseDTO<BookmarkResponseDTO> result = bookmarkService.getBookmarksByCase(currentUser.getId(), bookmarkCase, pageable);
70+
String message = bookmarkCase == BookmarkCase.LIKED_OPEN ? "신청 가능한 공고 목록 조회 성공" : "신청 마감된 공고 목록 조회 성공";
71+
return ResponseEntity.ok(ApiResponse.success(message, result));
8072
}
8173

8274
@Operation(summary = "북마크 완전 삭제", description = "캠페인 북마크(찜) 정보를 완전히 삭제합니다.")

src/main/java/com/example/cherrydan/campaign/controller/CampaignStatusController.java

Lines changed: 12 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import com.example.cherrydan.campaign.dto.CampaignStatusRequestDTO;
44
import com.example.cherrydan.campaign.dto.CampaignStatusResponseDTO;
55
import com.example.cherrydan.campaign.dto.CampaignStatusCountResponseDTO;
6-
import com.example.cherrydan.campaign.domain.CampaignStatusType;
6+
import com.example.cherrydan.campaign.domain.CampaignStatusCase;
77
import com.example.cherrydan.common.response.EmptyResponse;
88
import com.example.cherrydan.common.response.PageListResponseDTO;
99
import org.springframework.data.domain.PageRequest;
@@ -26,7 +26,6 @@
2626
import com.example.cherrydan.campaign.dto.CampaignStatusBatchRequestDTO;
2727
import com.example.cherrydan.campaign.dto.CampaignStatusDeleteRequestDTO;
2828
import com.example.cherrydan.campaign.dto.CampaignStatusPopupByTypeResponseDTO;
29-
import io.swagger.v3.oas.annotations.Parameter;
3029

3130
import java.util.List;
3231

@@ -37,22 +36,25 @@
3736
public class CampaignStatusController {
3837
private final CampaignStatusService campaignStatusService;
3938

40-
@Operation(summary = "내 체험단 상태별 목록 조회", description = "status 파라미터(APPLY/SELECTED/NOT_SELECTED/REVIEWING/ENDED) 기준 페이지네이션")
39+
@Operation(summary = "내 체험단 상태별 목록 조회",
40+
description = "case 파라미터(appliedCompleted/appliedWaiting/resultSelected/resultNotSelected/reviewInProgress/reviewCompleted) 기준 페이지네이션")
4141
@GetMapping
42-
public ResponseEntity<ApiResponse<PageListResponseDTO<CampaignStatusResponseDTO>>> getMyStatusesByType(
43-
@RequestParam(value = "status", defaultValue = "APPLY") String status,
42+
public ResponseEntity<ApiResponse<PageListResponseDTO<CampaignStatusResponseDTO>>> getMyStatusesByCase(
43+
@RequestParam(value = "case", defaultValue = "appliedCompleted") String caseParam,
4444
@RequestParam(defaultValue = "0") int page,
4545
@RequestParam(defaultValue = "20") int size,
4646
@AuthenticationPrincipal UserDetailsImpl currentUser
4747
) {
48-
CampaignStatusType statusType;
48+
CampaignStatusCase statusCase;
49+
50+
System.out.println("caseParam: " + caseParam);
4951
try {
50-
statusType = CampaignStatusType.valueOf(status.trim().toUpperCase());
52+
statusCase = CampaignStatusCase.fromCode(caseParam.trim());
5153
} catch (IllegalArgumentException e) {
5254
throw new CampaignException(ErrorMessage.CAMPAIGN_STATUS_INVALID);
5355
}
5456
Pageable pageable = PageRequest.of(page, size);
55-
PageListResponseDTO<CampaignStatusResponseDTO> result = campaignStatusService.getStatusesByType(currentUser.getId(), statusType, pageable);
57+
PageListResponseDTO<CampaignStatusResponseDTO> result = campaignStatusService.getStatusesByCase(currentUser.getId(), statusCase, pageable);
5658
return ResponseEntity.ok(ApiResponse.success(result));
5759
}
5860

@@ -95,21 +97,12 @@ public ResponseEntity<ApiResponse<EmptyResponse>> deleteStatus(
9597
return ResponseEntity.ok(ApiResponse.success("체험단 상태 삭제 성공"));
9698
}
9799

98-
@Operation(summary = "내 체험단 노출 팝업 조회", description = "지정된 상태의 기간이 지난 데이터만 최대 4개씩 반환")
100+
@Operation(summary = "내 체험단 노출 팝업 조회", description = "활성 관심공고 전체 반환 (마감일 순으로 정렬)")
99101
@GetMapping("/popup")
100102
public ResponseEntity<ApiResponse<CampaignStatusPopupByTypeResponseDTO>> getPopupStatus(
101-
@Parameter(description = "상태 타입 (APPLY, SELECTED, REVIEWING, ENDED)", required = true)
102-
@RequestParam String status,
103103
@AuthenticationPrincipal UserDetailsImpl currentUser
104104
) {
105-
CampaignStatusType statusType;
106-
try {
107-
statusType = CampaignStatusType.valueOf(status.toUpperCase());
108-
} catch (IllegalArgumentException e) {
109-
throw new CampaignException(ErrorMessage.CAMPAIGN_STATUS_INVALID);
110-
}
111-
112-
CampaignStatusPopupByTypeResponseDTO result = campaignStatusService.getPopupStatusByType(currentUser.getId(), statusType);
105+
CampaignStatusPopupByTypeResponseDTO result = campaignStatusService.getPopupStatusByBookmark(currentUser.getId());
113106
return ResponseEntity.ok(ApiResponse.success("팝업 상태 조회 성공", result));
114107
}
115108
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package com.example.cherrydan.campaign.domain;
2+
3+
import io.swagger.v3.oas.annotations.media.Schema;
4+
import lombok.Getter;
5+
6+
@Schema(description = "북마크 케이스 타입")
7+
@Getter
8+
public enum BookmarkCase {
9+
LIKED_OPEN("likedOpen", "신청 가능한 공고"),
10+
LIKED_CLOSED("likedClosed", "신청 마감된 공고");
11+
12+
private final String code;
13+
private final String label;
14+
15+
BookmarkCase(String code, String label) {
16+
this.code = code;
17+
this.label = label;
18+
}
19+
20+
public String getCode() {
21+
return code;
22+
}
23+
24+
public String getLabel() {
25+
return label;
26+
}
27+
28+
/**
29+
* 코드로 BookmarkCase 찾기
30+
*/
31+
public static BookmarkCase fromCode(String code) {
32+
for (BookmarkCase bookmarkCase : values()) {
33+
if (bookmarkCase.code.equalsIgnoreCase(code)) {
34+
return bookmarkCase;
35+
}
36+
}
37+
throw new IllegalArgumentException("Invalid BookmarkCase code: " + code);
38+
}
39+
}
40+
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package com.example.cherrydan.campaign.domain;
2+
3+
import io.swagger.v3.oas.annotations.media.Schema;
4+
import lombok.Getter;
5+
6+
@Schema(description = "캠페인 상태 케이스 타입")
7+
@Getter
8+
public enum CampaignStatusCase {
9+
APPLIED_COMPLETED("appliedCompleted", "결과 발표 완료"),
10+
APPLIED_WAITING("appliedWaiting", "발표 기다리는중"),
11+
RESULT_SELECTED("resultSelected", "선정된 공고"),
12+
RESULT_NOT_SELECTED("resultNotSelected", "선정되지 않은 공고"),
13+
REVIEW_IN_PROGRESS("reviewInProgress", "리뷰 작성할 공고"),
14+
REVIEW_COMPLETED("reviewCompleted", "리뷰 작성 완료한 공고");
15+
16+
private final String code;
17+
private final String label;
18+
19+
CampaignStatusCase(String code, String label) {
20+
this.code = code;
21+
this.label = label;
22+
}
23+
24+
public String getCode() {
25+
return code;
26+
}
27+
28+
public String getLabel() {
29+
return label;
30+
}
31+
32+
/**
33+
* 코드로 CampaignStatusCase 찾기
34+
*/
35+
public static CampaignStatusCase fromCode(String code) {
36+
for (CampaignStatusCase statusCase : values()) {
37+
if (statusCase.code.equalsIgnoreCase(code)) {
38+
return statusCase;
39+
}
40+
}
41+
throw new IllegalArgumentException("Invalid CampaignStatusCase code: " + code);
42+
}
43+
44+
/**
45+
* CampaignStatusCase를 CampaignStatusType으로 변환
46+
*/
47+
public CampaignStatusType toStatusType() {
48+
return switch (this) {
49+
case APPLIED_WAITING, APPLIED_COMPLETED -> CampaignStatusType.APPLY;
50+
case RESULT_SELECTED -> CampaignStatusType.SELECTED;
51+
case RESULT_NOT_SELECTED -> CampaignStatusType.NOT_SELECTED;
52+
case REVIEW_IN_PROGRESS -> CampaignStatusType.REVIEWING;
53+
case REVIEW_COMPLETED -> CampaignStatusType.ENDED;
54+
};
55+
}
56+
}
57+

src/main/java/com/example/cherrydan/campaign/dto/CampaignStatusCountResponseDTO.java

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,18 @@
88
@Builder
99
@Schema(description = "내 체험단 상태별 카운트 응답")
1010
public class CampaignStatusCountResponseDTO {
11-
@Schema(description = "지원한 공고 개수")
12-
private long apply;
13-
@Schema(description = "선정 결과 개수")
14-
private long selected;
15-
@Schema(description = "미선정 결과 개수")
16-
private long notSelected;
17-
@Schema(description = "리뷰 작성 중 개수")
18-
private long reviewing;
19-
@Schema(description = "작성 완료 개수")
20-
private long ended;
11+
@Schema(description = "결과 발표 완료 개수")
12+
private long appliedCompleted;
13+
@Schema(description = "발표 기다리는 중 개수")
14+
private long appliedWaiting;
15+
@Schema(description = "선정된 공고 개수")
16+
private long resultSelected;
17+
@Schema(description = "선정되지 않은 공고 개수")
18+
private long resultNotSelected;
19+
@Schema(description = "리뷰 작성할 공고 개수")
20+
private long reviewInProgress;
21+
@Schema(description = "리뷰 작성 완료한 공고 개수")
22+
private long reviewCompleted;
2123
}
2224

2325

src/main/java/com/example/cherrydan/campaign/dto/CampaignStatusPopupByTypeResponseDTO.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,7 @@
1010
@Builder
1111
@Schema(description = "특정 상태의 내 체험단 팝업용 응답 DTO")
1212
public class CampaignStatusPopupByTypeResponseDTO {
13-
@Schema(description = "상태 타입", example = "APPLY", nullable = false, requiredMode = Schema.RequiredMode.REQUIRED)
14-
private CampaignStatusType statusType;
15-
13+
1614
@Schema(description = "총 개수", example = "4", nullable = false, requiredMode = Schema.RequiredMode.REQUIRED)
1715
private long totalCount;
1816

src/main/java/com/example/cherrydan/campaign/dto/CampaignStatusPopupItemDTO.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.example.cherrydan.campaign.dto;
22

33
import com.example.cherrydan.campaign.domain.CampaignStatus;
4+
import com.example.cherrydan.campaign.domain.Bookmark;
45

56
import lombok.Builder;
67
import lombok.Getter;
@@ -40,4 +41,18 @@ public static CampaignStatusPopupItemDTO fromEntity(CampaignStatus status) {
4041
.benefit(status.getCampaign().getBenefit())
4142
.build();
4243
}
44+
45+
public static CampaignStatusPopupItemDTO fromBookmark(Bookmark bookmark) {
46+
String reviewerAnnouncementStatus = CampaignStatusResponseDTO.getStatusMessage(
47+
bookmark.getCampaign().getApplyEnd(),
48+
"bookmark"
49+
);
50+
return CampaignStatusPopupItemDTO.builder()
51+
.campaignId(bookmark.getCampaign().getId())
52+
.title(bookmark.getCampaign().getTitle())
53+
.imageUrl(bookmark.getCampaign().getImageUrl())
54+
.reviewerAnnouncementStatus(reviewerAnnouncementStatus)
55+
.benefit(bookmark.getCampaign().getBenefit())
56+
.build();
57+
}
4358
}

src/main/java/com/example/cherrydan/campaign/repository/BookmarkRepository.java

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,13 @@ public interface BookmarkRepository extends JpaRepository<Bookmark, Long> {
2323
boolean existsByUserIdAndCampaignIdAndIsActiveTrue(Long userId, Long campaignId);
2424
List<Bookmark> findAllByUserIdAndIsActiveTrue(Long userId);
2525

26-
// 원격에서 추가된 메서드들 (ReviewerAnnouncement -> ApplyEnd로 변경)
2726
Page<Bookmark> findByUserIdAndIsActiveTrueAndCampaign_ApplyEndGreaterThanEqual(Long userId, LocalDate date, Pageable pageable);
28-
Page<Bookmark> findByUserIdAndIsActiveTrueAndCampaign_ApplyEndLessThan(Long userId, LocalDate date, Pageable pageable);
27+
Page<Bookmark> findByUserIdAndIsActiveTrueAndCampaign_ApplyEndBetween(
28+
Long userId,
29+
LocalDate startDate,
30+
LocalDate endDate,
31+
Pageable pageable
32+
);
2933

3034
/**
3135
* 특정 사용자의 여러 캠페인 ID에 대한 북마크를 조회
@@ -66,4 +70,18 @@ public interface BookmarkRepository extends JpaRepository<Bookmark, Long> {
6670
@Modifying
6771
@Query("DELETE FROM Bookmark b WHERE b.user.id = :userId")
6872
void deleteByUserId(@Param("userId") Long userId);
73+
74+
/**
75+
* 팝업용: 사용자의 활성 관심공고 전체 조회
76+
* 마감일이 오늘 이후인 것만 조회하여 마감일 순으로 정렬
77+
*/
78+
@Query("SELECT b FROM Bookmark b " +
79+
"JOIN FETCH b.campaign c " +
80+
"JOIN FETCH b.user u " +
81+
"WHERE b.user.id = :userId " +
82+
"AND b.isActive = true " +
83+
"AND c.isActive = true " +
84+
"AND c.applyEnd >= :today " +
85+
"ORDER BY c.applyEnd DESC")
86+
List<Bookmark> findActiveBookmarksByUserForPopup(@Param("userId") Long userId, @Param("today") LocalDate today);
6987
}

0 commit comments

Comments
 (0)