diff --git a/src/main/java/gg/agit/konect/domain/club/controller/ClubController.java b/src/main/java/gg/agit/konect/domain/club/controller/ClubController.java index ce0a7d93..502c0f59 100644 --- a/src/main/java/gg/agit/konect/domain/club/controller/ClubController.java +++ b/src/main/java/gg/agit/konect/domain/club/controller/ClubController.java @@ -34,8 +34,10 @@ import gg.agit.konect.domain.club.dto.MemberPositionChangeRequest; import gg.agit.konect.domain.club.dto.PresidentTransferRequest; import gg.agit.konect.domain.club.dto.VicePresidentChangeRequest; +import gg.agit.konect.domain.club.service.ClubApplyService; import gg.agit.konect.domain.club.service.ClubMemberManagementService; import gg.agit.konect.domain.club.service.ClubPositionService; +import gg.agit.konect.domain.club.service.ClubRecruitmentService; import gg.agit.konect.domain.club.service.ClubService; import gg.agit.konect.global.auth.annotation.UserId; import jakarta.validation.Valid; @@ -49,6 +51,8 @@ public class ClubController implements ClubApi { private final ClubService clubService; private final ClubPositionService clubPositionService; private final ClubMemberManagementService clubMemberManagementService; + private final ClubRecruitmentService clubRecruitmentService; + private final ClubApplyService clubApplyService; @Override public ResponseEntity getClubs( @@ -114,7 +118,7 @@ public ResponseEntity getClubApplications( @PathVariable(name = "clubId") Integer clubId, @UserId Integer userId ) { - ClubApplicationsResponse response = clubService.getClubApplications(clubId, userId); + ClubApplicationsResponse response = clubApplyService.getClubApplications(clubId, userId); return ResponseEntity.ok(response); } @@ -124,7 +128,7 @@ public ResponseEntity getClubApplicationAnswers( @PathVariable(name = "applicationId") Integer applicationId, @UserId Integer userId ) { - ClubApplicationAnswersResponse response = clubService.getClubApplicationAnswers( + ClubApplicationAnswersResponse response = clubApplyService.getClubApplicationAnswers( clubId, applicationId, userId @@ -149,7 +153,7 @@ public ResponseEntity applyClub( @Valid @RequestBody ClubApplyRequest request, @UserId Integer userId ) { - ClubFeeInfoResponse response = clubService.applyClub(clubId, userId, request); + ClubFeeInfoResponse response = clubApplyService.applyClub(clubId, userId, request); return ResponseEntity.ok(response); } @@ -177,7 +181,7 @@ public ResponseEntity getApplyQuestions( @PathVariable(name = "clubId") Integer clubId, @UserId Integer userId ) { - ClubApplyQuestionsResponse response = clubService.getApplyQuestions(clubId, userId); + ClubApplyQuestionsResponse response = clubApplyService.getApplyQuestions(clubId, userId); return ResponseEntity.ok(response); } @@ -187,7 +191,7 @@ public ResponseEntity replaceApplyQuestions( @Valid @RequestBody ClubApplyQuestionsReplaceRequest request, @UserId Integer userId ) { - ClubApplyQuestionsResponse response = clubService.replaceApplyQuestions(clubId, userId, request); + ClubApplyQuestionsResponse response = clubApplyService.replaceApplyQuestions(clubId, userId, request); return ResponseEntity.ok(response); } @@ -196,7 +200,7 @@ public ResponseEntity getRecruitments( @PathVariable(name = "clubId") Integer clubId, @UserId Integer userId ) { - ClubRecruitmentResponse response = clubService.getRecruitment(clubId, userId); + ClubRecruitmentResponse response = clubRecruitmentService.getRecruitment(clubId, userId); return ResponseEntity.ok(response); } @@ -206,7 +210,7 @@ public ResponseEntity createRecruitment( @PathVariable(name = "clubId") Integer clubId, @UserId Integer userId ) { - clubService.createRecruitment(clubId, userId, request); + clubRecruitmentService.createRecruitment(clubId, userId, request); return ResponseEntity.ok().build(); } @@ -216,7 +220,7 @@ public ResponseEntity updateRecruitment( @PathVariable(name = "clubId") Integer clubId, @UserId Integer userId ) { - clubService.updateRecruitment(clubId, userId, request); + clubRecruitmentService.updateRecruitment(clubId, userId, request); return ResponseEntity.noContent().build(); } diff --git a/src/main/java/gg/agit/konect/domain/club/service/ClubApplyService.java b/src/main/java/gg/agit/konect/domain/club/service/ClubApplyService.java new file mode 100644 index 00000000..1fd5dda8 --- /dev/null +++ b/src/main/java/gg/agit/konect/domain/club/service/ClubApplyService.java @@ -0,0 +1,252 @@ +package gg.agit.konect.domain.club.service; + +import static gg.agit.konect.global.code.ApiResponseCode.ALREADY_APPLIED_CLUB; +import static gg.agit.konect.global.code.ApiResponseCode.DUPLICATE_CLUB_APPLY_QUESTION; +import static gg.agit.konect.global.code.ApiResponseCode.FORBIDDEN_CLUB_MANAGER_ACCESS; +import static gg.agit.konect.global.code.ApiResponseCode.NOT_FOUND_CLUB_APPLY_QUESTION; + +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.util.ArrayList; +import java.util.EnumSet; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import gg.agit.konect.domain.club.dto.ClubApplicationAnswersResponse; +import gg.agit.konect.domain.club.dto.ClubApplicationsResponse; +import gg.agit.konect.domain.club.dto.ClubApplyQuestionsReplaceRequest; +import gg.agit.konect.domain.club.dto.ClubApplyQuestionsResponse; +import gg.agit.konect.domain.club.dto.ClubApplyRequest; +import gg.agit.konect.domain.club.dto.ClubFeeInfoResponse; +import gg.agit.konect.domain.club.enums.ClubPositionGroup; +import gg.agit.konect.domain.club.model.Club; +import gg.agit.konect.domain.club.model.ClubApply; +import gg.agit.konect.domain.club.model.ClubApplyAnswer; +import gg.agit.konect.domain.club.model.ClubApplyQuestion; +import gg.agit.konect.domain.club.model.ClubApplyQuestionAnswers; +import gg.agit.konect.domain.club.model.ClubRecruitment; +import gg.agit.konect.domain.club.repository.ClubApplyAnswerRepository; +import gg.agit.konect.domain.club.repository.ClubApplyQuestionRepository; +import gg.agit.konect.domain.club.repository.ClubApplyRepository; +import gg.agit.konect.domain.club.repository.ClubMemberRepository; +import gg.agit.konect.domain.club.repository.ClubRecruitmentRepository; +import gg.agit.konect.domain.club.repository.ClubRepository; +import gg.agit.konect.domain.user.model.User; +import gg.agit.konect.domain.user.repository.UserRepository; +import gg.agit.konect.global.exception.CustomException; +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +@Transactional(readOnly = true) +public class ClubApplyService { + + private static final Set MANAGER_ALLOWED_GROUPS = + EnumSet.of(ClubPositionGroup.PRESIDENT, ClubPositionGroup.VICE_PRESIDENT); + + private final ClubRepository clubRepository; + private final UserRepository userRepository; + private final ClubMemberRepository clubMemberRepository; + private final ClubApplyRepository clubApplyRepository; + private final ClubApplyQuestionRepository clubApplyQuestionRepository; + private final ClubApplyAnswerRepository clubApplyAnswerRepository; + private final ClubRecruitmentRepository clubRecruitmentRepository; + + public ClubApplicationsResponse getClubApplications(Integer clubId, Integer userId) { + clubRepository.getById(clubId); + + if (!hasClubManageAccess(clubId, userId, MANAGER_ALLOWED_GROUPS)) { + throw CustomException.of(FORBIDDEN_CLUB_MANAGER_ACCESS); + } + + ClubRecruitment recruitment = clubRecruitmentRepository.getByClubId(clubId); + List clubApplies = findApplicationsByRecruitmentPeriod(clubId, recruitment); + + return ClubApplicationsResponse.from(clubApplies); + } + + public ClubApplicationAnswersResponse getClubApplicationAnswers( + Integer clubId, + Integer applicationId, + Integer userId + ) { + clubRepository.getById(clubId); + + if (!hasClubManageAccess(clubId, userId, MANAGER_ALLOWED_GROUPS)) { + throw CustomException.of(FORBIDDEN_CLUB_MANAGER_ACCESS); + } + + ClubApply clubApply = clubApplyRepository.getByIdAndClubId(applicationId, clubId); + List questions = + clubApplyQuestionRepository.findAllByClubIdOrderByIdAsc(clubId); + List answers = clubApplyAnswerRepository.findAllByApplyIdWithQuestion(applicationId); + + return ClubApplicationAnswersResponse.of(clubApply, questions, answers); + } + + public ClubApplyQuestionsResponse getApplyQuestions(Integer clubId, Integer userId) { + userRepository.getById(userId); + List questions = + clubApplyQuestionRepository.findAllByClubIdOrderByIdAsc(clubId); + + return ClubApplyQuestionsResponse.from(questions); + } + + @Transactional + public ClubApplyQuestionsResponse replaceApplyQuestions( + Integer clubId, + Integer userId, + ClubApplyQuestionsReplaceRequest request + ) { + Club club = clubRepository.getById(clubId); + + if (!hasClubManageAccess(clubId, userId, MANAGER_ALLOWED_GROUPS)) { + throw CustomException.of(FORBIDDEN_CLUB_MANAGER_ACCESS); + } + + List questionRequests = request.questions(); + Set requestedQuestionIds = new HashSet<>(); + + List existingQuestions = + clubApplyQuestionRepository.findAllByClubIdOrderByIdAsc(clubId); + Map existingQuestionMap = existingQuestions.stream() + .collect(Collectors.toMap(ClubApplyQuestion::getId, question -> question)); + + updateQuestions(existingQuestionMap, questionRequests, requestedQuestionIds); + + List questionsToCreate = createQuestions(club, questionRequests); + + deleteQuestions(existingQuestions, requestedQuestionIds); + + if (!questionsToCreate.isEmpty()) { + clubApplyQuestionRepository.saveAll(questionsToCreate); + } + + List questions = + clubApplyQuestionRepository.findAllByClubIdOrderByIdAsc(clubId); + + return ClubApplyQuestionsResponse.from(questions); + } + + @Transactional + public ClubFeeInfoResponse applyClub(Integer clubId, Integer userId, ClubApplyRequest request) { + Club club = clubRepository.getById(clubId); + User user = userRepository.getById(userId); + + if (clubApplyRepository.existsByClubIdAndUserId(clubId, userId)) { + throw CustomException.of(ALREADY_APPLIED_CLUB); + } + + List questions = + clubApplyQuestionRepository.findAllByClubIdOrderByIdAsc(clubId); + ClubApplyQuestionAnswers answers = ClubApplyQuestionAnswers.of(questions, request.toAnswerMap()); + + ClubApply apply = clubApplyRepository.save(ClubApply.of(club, user)); + + List applyAnswers = answers.toEntities(apply); + + if (!applyAnswers.isEmpty()) { + clubApplyAnswerRepository.saveAll(applyAnswers); + } + + return ClubFeeInfoResponse.from(club); + } + + private List findApplicationsByRecruitmentPeriod( + Integer clubId, + ClubRecruitment recruitment + ) { + if (recruitment.getIsAlwaysRecruiting()) { + return clubApplyRepository.findAllByClubIdWithUser(clubId); + } + + LocalDateTime startDateTime = recruitment.getStartDate().atStartOfDay(); + LocalDateTime endDateTime = recruitment.getEndDate().atTime(LocalTime.MAX); + + return clubApplyRepository.findAllByClubIdAndCreatedAtBetweenWithUser( + clubId, + startDateTime, + endDateTime + ); + } + + private List createQuestions( + Club club, + List questionRequests + ) { + List questionsToCreate = new ArrayList<>(); + + for (ClubApplyQuestionsReplaceRequest.ApplyQuestionRequest questionRequest : questionRequests) { + if (questionRequest.questionId() != null) { + continue; + } + + questionsToCreate.add(ClubApplyQuestion.of( + club, + questionRequest.question(), + questionRequest.isRequired()) + ); + } + return questionsToCreate; + } + + private void updateQuestions( + Map existingQuestionMap, + List questionRequests, + Set requestedQuestionIds + ) { + for (ClubApplyQuestionsReplaceRequest.ApplyQuestionRequest questionRequest : questionRequests) { + Integer questionId = questionRequest.questionId(); + + if (questionId == null) { + continue; + } + + if (!requestedQuestionIds.add(questionId)) { + throw CustomException.of(DUPLICATE_CLUB_APPLY_QUESTION); + } + + ClubApplyQuestion existingQuestion = existingQuestionMap.get(questionId); + + if (existingQuestion == null) { + throw CustomException.of(NOT_FOUND_CLUB_APPLY_QUESTION); + } + + existingQuestion.update( + questionRequest.question(), + questionRequest.isRequired() + ); + } + } + + private void deleteQuestions( + List existingQuestions, + Set requestedQuestionIds + ) { + List questionsToDelete = existingQuestions.stream() + .filter(question -> !requestedQuestionIds.contains(question.getId())) + .toList(); + + if (!questionsToDelete.isEmpty()) { + clubApplyQuestionRepository.deleteAll(questionsToDelete); + } + } + + private boolean hasClubManageAccess( + Integer clubId, + Integer userId, + Set allowedGroups + ) { + return clubMemberRepository.existsByClubIdAndUserIdAndPositionGroupIn( + clubId, + userId, + allowedGroups + ); + } +} diff --git a/src/main/java/gg/agit/konect/domain/club/service/ClubRecruitmentService.java b/src/main/java/gg/agit/konect/domain/club/service/ClubRecruitmentService.java new file mode 100644 index 00000000..48982127 --- /dev/null +++ b/src/main/java/gg/agit/konect/domain/club/service/ClubRecruitmentService.java @@ -0,0 +1,130 @@ +package gg.agit.konect.domain.club.service; + +import static gg.agit.konect.domain.club.enums.ClubPositionGroup.PRESIDENT; +import static gg.agit.konect.global.code.ApiResponseCode.ALREADY_EXIST_CLUB_RECRUITMENT; +import static gg.agit.konect.global.code.ApiResponseCode.FORBIDDEN_CLUB_MANAGER_ACCESS; +import static gg.agit.konect.global.code.ApiResponseCode.FORBIDDEN_CLUB_RECRUITMENT_CREATE; + +import java.util.EnumSet; +import java.util.List; +import java.util.Set; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import gg.agit.konect.domain.club.dto.ClubRecruitmentCreateRequest; +import gg.agit.konect.domain.club.dto.ClubRecruitmentResponse; +import gg.agit.konect.domain.club.dto.ClubRecruitmentUpdateRequest; +import gg.agit.konect.domain.club.enums.ClubPositionGroup; +import gg.agit.konect.domain.club.model.Club; +import gg.agit.konect.domain.club.model.ClubRecruitment; +import gg.agit.konect.domain.club.model.ClubRecruitmentImage; +import gg.agit.konect.domain.club.repository.ClubApplyRepository; +import gg.agit.konect.domain.club.repository.ClubMemberRepository; +import gg.agit.konect.domain.club.repository.ClubRecruitmentRepository; +import gg.agit.konect.domain.club.repository.ClubRepository; +import gg.agit.konect.domain.user.model.User; +import gg.agit.konect.domain.user.repository.UserRepository; +import gg.agit.konect.global.exception.CustomException; +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +@Transactional(readOnly = true) +public class ClubRecruitmentService { + + private static final Set PRESIDENT_ALLOWED_GROUPS = + EnumSet.of(PRESIDENT); + private static final Set MANAGER_ALLOWED_GROUPS = + EnumSet.of(ClubPositionGroup.PRESIDENT, ClubPositionGroup.VICE_PRESIDENT); + + private final ClubRepository clubRepository; + private final UserRepository userRepository; + private final ClubMemberRepository clubMemberRepository; + private final ClubApplyRepository clubApplyRepository; + private final ClubRecruitmentRepository clubRecruitmentRepository; + + public ClubRecruitmentResponse getRecruitment(Integer clubId, Integer userId) { + Club club = clubRepository.getById(clubId); + User user = userRepository.getById(userId); + ClubRecruitment recruitment = clubRecruitmentRepository.getByClubId(club.getId()); + boolean isMember = clubMemberRepository.existsByClubIdAndUserId(clubId, userId); + boolean isApplied = isMember || clubApplyRepository.existsByClubIdAndUserId(club.getId(), user.getId()); + + return ClubRecruitmentResponse.of(recruitment, isApplied); + } + + @Transactional + public void createRecruitment(Integer clubId, Integer userId, ClubRecruitmentCreateRequest request) { + Club club = clubRepository.getById(clubId); + userRepository.getById(userId); + + if (!hasClubManageAccess(clubId, userId, PRESIDENT_ALLOWED_GROUPS)) { + throw CustomException.of(FORBIDDEN_CLUB_RECRUITMENT_CREATE); + } + + if (clubRecruitmentRepository.existsByClubId(clubId)) { + throw CustomException.of(ALREADY_EXIST_CLUB_RECRUITMENT); + } + + ClubRecruitment clubRecruitment = ClubRecruitment.of( + request.startDate(), + request.endDate(), + request.isAlwaysRecruiting(), + request.content(), + club + ); + List imageUrls = request.getImageUrls(); + for (int index = 0; index < imageUrls.size(); index++) { + ClubRecruitmentImage clubRecruitmentImage = ClubRecruitmentImage.of( + imageUrls.get(index), + index, + clubRecruitment + ); + clubRecruitment.addImage(clubRecruitmentImage); + } + + clubRecruitmentRepository.save(clubRecruitment); + } + + @Transactional + public void updateRecruitment(Integer clubId, Integer userId, ClubRecruitmentUpdateRequest request) { + clubRepository.getById(clubId); + userRepository.getById(userId); + + if (!hasClubManageAccess(clubId, userId, MANAGER_ALLOWED_GROUPS)) { + throw CustomException.of(FORBIDDEN_CLUB_MANAGER_ACCESS); + } + + ClubRecruitment clubRecruitment = clubRecruitmentRepository.getByClubId(clubId); + clubRecruitment.update( + request.startDate(), + request.endDate(), + request.isAlwaysRecruiting(), + request.content() + ); + + clubRecruitment.getImages().clear(); + List imageUrls = request.getImageUrls(); + for (int index = 0; index < imageUrls.size(); index++) { + ClubRecruitmentImage newImage = ClubRecruitmentImage.of( + imageUrls.get(index), + index, + clubRecruitment + ); + clubRecruitment.addImage(newImage); + } + } + + private boolean hasClubManageAccess( + Integer clubId, + Integer userId, + Set allowedGroups + ) { + return clubMemberRepository.existsByClubIdAndUserIdAndPositionGroupIn( + clubId, + userId, + allowedGroups + ); + } +} diff --git a/src/main/java/gg/agit/konect/domain/club/service/ClubService.java b/src/main/java/gg/agit/konect/domain/club/service/ClubService.java index f4ed5149..cd606cfb 100644 --- a/src/main/java/gg/agit/konect/domain/club/service/ClubService.java +++ b/src/main/java/gg/agit/konect/domain/club/service/ClubService.java @@ -1,18 +1,13 @@ package gg.agit.konect.domain.club.service; -import static gg.agit.konect.domain.club.enums.ClubPositionGroup.*; +import static gg.agit.konect.domain.club.enums.ClubPositionGroup.MANAGER; +import static gg.agit.konect.domain.club.enums.ClubPositionGroup.PRESIDENT; import static gg.agit.konect.global.code.ApiResponseCode.*; -import java.time.LocalDateTime; -import java.time.LocalTime; -import java.util.ArrayList; import java.util.Arrays; import java.util.EnumSet; -import java.util.HashSet; import java.util.List; -import java.util.Map; import java.util.Set; -import java.util.stream.Collectors; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; @@ -20,12 +15,7 @@ import org.springframework.transaction.annotation.Transactional; import gg.agit.konect.domain.bank.repository.BankRepository; -import gg.agit.konect.domain.club.dto.ClubApplicationAnswersResponse; import gg.agit.konect.domain.club.dto.ClubAppliedClubsResponse; -import gg.agit.konect.domain.club.dto.ClubApplicationsResponse; -import gg.agit.konect.domain.club.dto.ClubApplyQuestionsReplaceRequest; -import gg.agit.konect.domain.club.dto.ClubApplyQuestionsResponse; -import gg.agit.konect.domain.club.dto.ClubApplyRequest; import gg.agit.konect.domain.club.dto.ClubCondition; import gg.agit.konect.domain.club.dto.ClubCreateRequest; import gg.agit.konect.domain.club.dto.ClubDetailResponse; @@ -34,25 +24,16 @@ import gg.agit.konect.domain.club.dto.ClubMemberCondition; import gg.agit.konect.domain.club.dto.ClubMembersResponse; import gg.agit.konect.domain.club.dto.ClubMembershipsResponse; -import gg.agit.konect.domain.club.dto.ClubRecruitmentCreateRequest; -import gg.agit.konect.domain.club.dto.ClubRecruitmentResponse; -import gg.agit.konect.domain.club.dto.ClubRecruitmentUpdateRequest; import gg.agit.konect.domain.club.dto.ClubUpdateRequest; import gg.agit.konect.domain.club.dto.ClubsResponse; import gg.agit.konect.domain.club.enums.ClubPositionGroup; import gg.agit.konect.domain.club.model.Club; import gg.agit.konect.domain.club.model.ClubApply; -import gg.agit.konect.domain.club.model.ClubApplyAnswer; -import gg.agit.konect.domain.club.model.ClubApplyQuestion; -import gg.agit.konect.domain.club.model.ClubApplyQuestionAnswers; import gg.agit.konect.domain.club.model.ClubMember; import gg.agit.konect.domain.club.model.ClubMembers; import gg.agit.konect.domain.club.model.ClubPosition; import gg.agit.konect.domain.club.model.ClubRecruitment; -import gg.agit.konect.domain.club.model.ClubRecruitmentImage; import gg.agit.konect.domain.club.model.ClubSummaryInfo; -import gg.agit.konect.domain.club.repository.ClubApplyAnswerRepository; -import gg.agit.konect.domain.club.repository.ClubApplyQuestionRepository; import gg.agit.konect.domain.club.repository.ClubApplyRepository; import gg.agit.konect.domain.club.repository.ClubMemberRepository; import gg.agit.konect.domain.club.repository.ClubPositionRepository; @@ -80,8 +61,6 @@ public class ClubService { private final ClubPositionRepository clubPositionRepository; private final ClubRecruitmentRepository clubRecruitmentRepository; private final ClubApplyRepository clubApplyRepository; - private final ClubApplyQuestionRepository clubApplyQuestionRepository; - private final ClubApplyAnswerRepository clubApplyAnswerRepository; private final UserRepository userRepository; private final BankRepository bankRepository; @@ -175,56 +154,6 @@ public ClubAppliedClubsResponse getAppliedClubs(Integer userId) { return ClubAppliedClubsResponse.from(clubApplies); } - public ClubApplicationsResponse getClubApplications(Integer clubId, Integer userId) { - clubRepository.getById(clubId); - - if (!hasClubManageAccess(clubId, userId, MANAGER_ALLOWED_GROUPS)) { - throw CustomException.of(FORBIDDEN_CLUB_MANAGER_ACCESS); - } - - ClubRecruitment recruitment = clubRecruitmentRepository.getByClubId(clubId); - List clubApplies = findApplicationsByRecruitmentPeriod(clubId, recruitment); - - return ClubApplicationsResponse.from(clubApplies); - } - - public ClubApplicationAnswersResponse getClubApplicationAnswers( - Integer clubId, - Integer applicationId, - Integer userId - ) { - clubRepository.getById(clubId); - - if (!hasClubManageAccess(clubId, userId, MANAGER_ALLOWED_GROUPS)) { - throw CustomException.of(FORBIDDEN_CLUB_MANAGER_ACCESS); - } - - ClubApply clubApply = clubApplyRepository.getByIdAndClubId(applicationId, clubId); - List questions = - clubApplyQuestionRepository.findAllByClubIdOrderByIdAsc(clubId); - List answers = clubApplyAnswerRepository.findAllByApplyIdWithQuestion(applicationId); - - return ClubApplicationAnswersResponse.of(clubApply, questions, answers); - } - - private List findApplicationsByRecruitmentPeriod( - Integer clubId, - ClubRecruitment recruitment - ) { - if (recruitment.getIsAlwaysRecruiting()) { - return clubApplyRepository.findAllByClubIdWithUser(clubId); - } - - LocalDateTime startDateTime = recruitment.getStartDate().atStartOfDay(); - LocalDateTime endDateTime = recruitment.getEndDate().atTime(LocalTime.MAX); - - return clubApplyRepository.findAllByClubIdAndCreatedAtBetweenWithUser( - clubId, - startDateTime, - endDateTime - ); - } - public ClubMembersResponse getClubMembers(Integer clubId, Integer userId, ClubMemberCondition condition) { boolean isMember = clubMemberRepository.existsByClubIdAndUserId(clubId, userId); if (!isMember) { @@ -281,208 +210,6 @@ public ClubFeeInfoResponse replaceFeeInfo(Integer clubId, Integer userId, ClubFe return ClubFeeInfoResponse.from(club); } - public ClubApplyQuestionsResponse getApplyQuestions(Integer clubId, Integer userId) { - User user = userRepository.getById(userId); - List questions = - clubApplyQuestionRepository.findAllByClubIdOrderByIdAsc(clubId); - - return ClubApplyQuestionsResponse.from(questions); - } - - @Transactional - public ClubApplyQuestionsResponse replaceApplyQuestions( - Integer clubId, - Integer userId, - ClubApplyQuestionsReplaceRequest request - ) { - Club club = clubRepository.getById(clubId); - - if (!hasClubManageAccess(clubId, userId, MANAGER_ALLOWED_GROUPS)) { - throw CustomException.of(FORBIDDEN_CLUB_MANAGER_ACCESS); - } - - List questionRequests = request.questions(); - Set requestedQuestionIds = new HashSet<>(); - - List existingQuestions = - clubApplyQuestionRepository.findAllByClubIdOrderByIdAsc(clubId); - Map existingQuestionMap = existingQuestions.stream() - .collect(Collectors.toMap(ClubApplyQuestion::getId, question -> question)); - - updateQuestions(existingQuestionMap, questionRequests, requestedQuestionIds); - - List questionsToCreate = createQuestions(club, questionRequests); - - deleteQuestions(existingQuestions, requestedQuestionIds); - - if (!questionsToCreate.isEmpty()) { - clubApplyQuestionRepository.saveAll(questionsToCreate); - } - - List questions = - clubApplyQuestionRepository.findAllByClubIdOrderByIdAsc(clubId); - - return ClubApplyQuestionsResponse.from(questions); - } - - public ClubRecruitmentResponse getRecruitment(Integer clubId, Integer userId) { - Club club = clubRepository.getById(clubId); - User user = userRepository.getById(userId); - ClubRecruitment recruitment = clubRecruitmentRepository.getByClubId(club.getId()); - boolean isMember = clubMemberRepository.existsByClubIdAndUserId(clubId, userId); - boolean isApplied = isMember || clubApplyRepository.existsByClubIdAndUserId(club.getId(), user.getId()); - - return ClubRecruitmentResponse.of(recruitment, isApplied); - } - - @Transactional - public ClubFeeInfoResponse applyClub(Integer clubId, Integer userId, ClubApplyRequest request) { - Club club = clubRepository.getById(clubId); - User user = userRepository.getById(userId); - - if (clubApplyRepository.existsByClubIdAndUserId(clubId, userId)) { - throw CustomException.of(ALREADY_APPLIED_CLUB); - } - - List questions = - clubApplyQuestionRepository.findAllByClubIdOrderByIdAsc(clubId); - ClubApplyQuestionAnswers answers = ClubApplyQuestionAnswers.of(questions, request.toAnswerMap()); - - ClubApply apply = clubApplyRepository.save(ClubApply.of(club, user)); - - List applyAnswers = answers.toEntities(apply); - - if (!applyAnswers.isEmpty()) { - clubApplyAnswerRepository.saveAll(applyAnswers); - } - - return ClubFeeInfoResponse.from(club); - } - - private List createQuestions( - Club club, - List questionRequests - ) { - List questionsToCreate = new ArrayList<>(); - - for (ClubApplyQuestionsReplaceRequest.ApplyQuestionRequest questionRequest : questionRequests) { - if (questionRequest.questionId() != null) { - continue; - } - - questionsToCreate.add(ClubApplyQuestion.of( - club, - questionRequest.question(), - questionRequest.isRequired()) - ); - } - return questionsToCreate; - } - - private void updateQuestions( - Map existingQuestionMap, - List questionRequests, - Set requestedQuestionIds - ) { - for (ClubApplyQuestionsReplaceRequest.ApplyQuestionRequest questionRequest : questionRequests) { - Integer questionId = questionRequest.questionId(); - - if (questionId == null) { - continue; - } - - if (!requestedQuestionIds.add(questionId)) { - throw CustomException.of(DUPLICATE_CLUB_APPLY_QUESTION); - } - - ClubApplyQuestion existingQuestion = existingQuestionMap.get(questionId); - - if (existingQuestion == null) { - throw CustomException.of(NOT_FOUND_CLUB_APPLY_QUESTION); - } - - existingQuestion.update( - questionRequest.question(), - questionRequest.isRequired() - ); - } - } - - private void deleteQuestions( - List existingQuestions, - Set requestedQuestionIds - ) { - List questionsToDelete = existingQuestions.stream() - .filter(question -> !requestedQuestionIds.contains(question.getId())) - .toList(); - - if (!questionsToDelete.isEmpty()) { - clubApplyQuestionRepository.deleteAll(questionsToDelete); - } - } - - @Transactional - public void createRecruitment(Integer clubId, Integer userId, ClubRecruitmentCreateRequest request) { - Club club = clubRepository.getById(clubId); - User user = userRepository.getById(userId); - - if (!hasClubManageAccess(clubId, userId, PRESIDENT_ALLOWED_GROUPS)) { - throw CustomException.of(FORBIDDEN_CLUB_RECRUITMENT_CREATE); - } - - if (clubRecruitmentRepository.existsByClubId(clubId)) { - throw CustomException.of(ALREADY_EXIST_CLUB_RECRUITMENT); - } - - ClubRecruitment clubRecruitment = ClubRecruitment.of( - request.startDate(), - request.endDate(), - request.isAlwaysRecruiting(), - request.content(), - club - ); - List imageUrls = request.getImageUrls(); - for (int index = 0; index < imageUrls.size(); index++) { - ClubRecruitmentImage clubRecruitmentImage = ClubRecruitmentImage.of( - imageUrls.get(index), - index, - clubRecruitment - ); - clubRecruitment.addImage(clubRecruitmentImage); - } - - clubRecruitmentRepository.save(clubRecruitment); - } - - @Transactional - public void updateRecruitment(Integer clubId, Integer userId, ClubRecruitmentUpdateRequest request) { - clubRepository.getById(clubId); - userRepository.getById(userId); - - if (!hasClubManageAccess(clubId, userId, MANAGER_ALLOWED_GROUPS)) { - throw CustomException.of(FORBIDDEN_CLUB_MANAGER_ACCESS); - } - - ClubRecruitment clubRecruitment = clubRecruitmentRepository.getByClubId(clubId); - clubRecruitment.update( - request.startDate(), - request.endDate(), - request.isAlwaysRecruiting(), - request.content() - ); - - clubRecruitment.getImages().clear(); - List imageUrls = request.getImageUrls(); - for (int index = 0; index < imageUrls.size(); index++) { - ClubRecruitmentImage newImage = ClubRecruitmentImage.of( - imageUrls.get(index), - index, - clubRecruitment - ); - clubRecruitment.addImage(newImage); - } - } - private boolean hasClubManageAccess( Integer clubId, Integer userId,