Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,8 @@ public enum CustomResponseStatus {
*/
INTERNAL_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR.value(), "6000", "내부 서버 오류입니다."),
ASYNC_COMPLETION_ERROR(HttpStatus.INTERNAL_SERVER_ERROR.value(), "6001", "비동기 작업에서 오류가 발생하였습니다."),
SOLVED_AC_API_ERROR(HttpStatus.BAD_GATEWAY.value(), "6002", "solved.ac API 호출에 실패했습니다.");
SOLVED_AC_API_ERROR(HttpStatus.BAD_GATEWAY.value(), "6002", "solved.ac API 호출에 실패했습니다."),
NO_VERIFIED_HANDLE(HttpStatus.BAD_REQUEST.value(), "6003", "팀에 인증된 핸들이 없어 추천을 생성할 수 없습니다.");


private final int httpStatusCode;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,11 @@
import com.ryu.studyhelper.infrastructure.ratelimit.RateLimit;
import com.ryu.studyhelper.infrastructure.ratelimit.RateLimitType;
import com.ryu.studyhelper.recommendation.dto.response.MyTodayProblemsResponse;
import com.ryu.studyhelper.recommendation.dto.response.TeamRecommendationDetailResponse;
import com.ryu.studyhelper.recommendation.dto.response.TodayProblemResponse;
import com.ryu.studyhelper.recommendation.dto.response.RecommendationDetailResponse;
import com.ryu.studyhelper.recommendation.service.RecommendationService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
Expand Down Expand Up @@ -40,58 +38,25 @@ public class RecommendationController {
description = """
팀장이 수동으로 문제 추천을 생성합니다.
추천 생성 즉시 팀원들에게 이메일이 발송됩니다.
count 파라미터가 없으면 팀 추천 설정의 problemCount 값을 사용합니다.
팀 추천 설정의 problemCount 값을 사용합니다.
"""
)
@RateLimit(type = RateLimitType.SOLVED_AC)
@PostMapping("/team/{teamId}/manual")
@PreAuthorize("@teamService.isTeamLeader(#teamId, authentication.principal.memberId)")
public ResponseEntity<ApiResponse<TeamRecommendationDetailResponse>> createManualRecommendation(
public ResponseEntity<ApiResponse<RecommendationDetailResponse>> createManualRecommendation(
@Parameter(description = "팀 ID", example = "1")
@PathVariable Long teamId,
@Parameter(description = "추천 문제 개수 (1~10, 미지정 시 팀 설정값 사용)", example = "3")
@RequestParam(required = false) @Min(1) @Max(10) Integer count,
@AuthenticationPrincipal PrincipalDetails principalDetails) {

log.info("팀장 {}가 팀 {}에 수동 추천 생성 (count={})", principalDetails.getMemberId(), teamId, count);
log.info("팀장 {}가 팀 {}에 수동 추천 생성", principalDetails.getMemberId(), teamId);

TeamRecommendationDetailResponse response =
recommendationService.createManualRecommendation(teamId, count);
RecommendationDetailResponse response =
recommendationService.createManualRecommendation(teamId);

return ResponseEntity.ok(ApiResponse.createSuccess(response, CustomResponseStatus.SUCCESS));
}

@Deprecated
@Operation(
summary = "오늘의 문제 조회 (Deprecated)",
description = """
**Deprecated**: `/api/recommendation/my/today-problems` 사용 권장

특정 팀의 오늘 추천된 문제를 조회합니다.
가장 최근 추천(수동 추천 우선)을 반환합니다.
로그인한 사용자의 경우 해결 여부(isSolved)가 포함됩니다.
비로그인 시 isSolved는 null입니다.
""",
deprecated = true
)
@GetMapping("/team/{teamId}/today-problem")
public ResponseEntity<ApiResponse<TodayProblemResponse>> getTodayRecommendation(
@Parameter(description = "팀 ID", example = "1")
@PathVariable Long teamId,
@AuthenticationPrincipal PrincipalDetails principalDetails) {

Long memberId = principalDetails != null ? principalDetails.getMemberId() : null;

if (memberId != null) {
log.info("사용자 {}가 팀 {}의 오늘의 문제 조회", memberId, teamId);
} else {
log.info("비로그인 사용자가 팀 {}의 오늘의 문제 조회", teamId);
}

TodayProblemResponse response = recommendationService.getTodayRecommendation(teamId, memberId);
return ResponseEntity.ok(ApiResponse.createSuccess(response, CustomResponseStatus.SUCCESS));
}

@Operation(
summary = "내 오늘의 문제 전체 조회",
description = """
Expand Down
Loading