diff --git a/backend/src/main/java/moadong/club/controller/ClubApplyController.java b/backend/src/main/java/moadong/club/controller/ClubApplyController.java
index 5a8752653..c8c90e2ac 100644
--- a/backend/src/main/java/moadong/club/controller/ClubApplyController.java
+++ b/backend/src/main/java/moadong/club/controller/ClubApplyController.java
@@ -4,11 +4,10 @@
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.AllArgsConstructor;
-import moadong.club.entity.ClubApplication;
+import moadong.club.payload.request.ClubApplicantEditRequest;
import moadong.club.payload.request.ClubApplicationCreateRequest;
import moadong.club.payload.request.ClubApplicationEditRequest;
import moadong.club.payload.request.ClubApplyRequest;
-import moadong.club.payload.response.ClubApplicationResponse;
import moadong.club.service.ClubApplyService;
import moadong.global.payload.Response;
import moadong.user.annotation.CurrentUser;
@@ -18,8 +17,6 @@
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
-import java.util.List;
-
@RestController
@RequestMapping("/api/club/{clubId}")
@AllArgsConstructor
@@ -73,4 +70,33 @@ public ResponseEntity> getApplyInfo(@PathVariable String clubId,
return Response.ok(clubApplyService.getClubApplyInfo(clubId, user));
}
+ @PutMapping("/apply/{appId}")
+ @Operation(summary = "지원서 변경",
+ description = "클럽 자원자의 지원서 정보를 수정합니다.
"
+ + "appId - 지원서 아이디"
+ )
+ @PreAuthorize("isAuthenticated()")
+ @SecurityRequirement(name = "BearerAuth")
+ public ResponseEntity> editApplicantDetail(@PathVariable String clubId,
+ @PathVariable String appId,
+ @RequestBody @Validated ClubApplicantEditRequest request,
+ @CurrentUser CustomUserDetails user) {
+ clubApplyService.editApplicantDetail(clubId, appId, request, user);
+ return Response.ok("success edit applicant");
+ }
+
+ @DeleteMapping("/apply/{appId}")
+ @Operation(summary = "지원서 삭제",
+ description = "클럽 자원자의 지원서를 삭제합니다.
"
+ + "appId - 지원서 아이디"
+ )
+ @PreAuthorize("isAuthenticated()")
+ @SecurityRequirement(name = "BearerAuth")
+ public ResponseEntity> removeApplicant(@PathVariable String clubId,
+ @PathVariable String appId,
+ @CurrentUser CustomUserDetails user) {
+ clubApplyService.deleteApplicant(clubId, appId, user);
+ return Response.ok("success delete applicant");
+ }
+
}
diff --git a/backend/src/main/java/moadong/club/entity/ClubApplication.java b/backend/src/main/java/moadong/club/entity/ClubApplication.java
index 0b17f2153..7e94df822 100644
--- a/backend/src/main/java/moadong/club/entity/ClubApplication.java
+++ b/backend/src/main/java/moadong/club/entity/ClubApplication.java
@@ -30,9 +30,17 @@ public class ClubApplication {
@Builder.Default
ApplicationStatus status = ApplicationStatus.SUBMITTED;
+ @Builder.Default
+ private String memo = "";
+
@Builder.Default
private List answers = new ArrayList<>();
@Builder.Default
LocalDateTime createdAt = ZonedDateTime.now(ZoneId.of("Asia/Seoul")).toLocalDateTime();
+
+ public void updateDetail(String memo, ApplicationStatus status) {
+ this.memo = memo;
+ this.status = status;
+ }
}
diff --git a/backend/src/main/java/moadong/club/payload/dto/ClubApplicantsResult.java b/backend/src/main/java/moadong/club/payload/dto/ClubApplicantsResult.java
index e44ec0cac..2c8b60c6a 100644
--- a/backend/src/main/java/moadong/club/payload/dto/ClubApplicantsResult.java
+++ b/backend/src/main/java/moadong/club/payload/dto/ClubApplicantsResult.java
@@ -9,15 +9,17 @@
import moadong.global.exception.RestApiException;
import moadong.global.util.AESCipher;
+import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
@Builder
@Slf4j
public record ClubApplicantsResult(
- String questionId,
+ String id,
ApplicationStatus status,
- List answers
+ List answers,
+ LocalDateTime createdAt
) {
public static ClubApplicantsResult of(ClubApplication application, AESCipher cipher) {
List decryptedAnswers = new ArrayList<>();
@@ -35,9 +37,10 @@ public static ClubApplicantsResult of(ClubApplication application, AESCipher cip
}
return ClubApplicantsResult.builder()
- .questionId(application.getQuestionId())
+ .id(application.getId())
.status(application.getStatus())
.answers(decryptedAnswers)
+ .createdAt(application.getCreatedAt())
.build();
}
}
\ No newline at end of file
diff --git a/backend/src/main/java/moadong/club/payload/request/ClubApplicantEditRequest.java b/backend/src/main/java/moadong/club/payload/request/ClubApplicantEditRequest.java
new file mode 100644
index 000000000..7a143c781
--- /dev/null
+++ b/backend/src/main/java/moadong/club/payload/request/ClubApplicantEditRequest.java
@@ -0,0 +1,15 @@
+package moadong.club.payload.request;
+
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Size;
+import moadong.club.enums.ApplicationStatus;
+
+public record ClubApplicantEditRequest(
+ @NotNull
+ @Size(max = 500)
+ String memo,
+
+ @NotNull
+ ApplicationStatus status
+) {
+}
diff --git a/backend/src/main/java/moadong/club/repository/ClubApplicationRepository.java b/backend/src/main/java/moadong/club/repository/ClubApplicationRepository.java
index f4b6f3f69..52ba38527 100644
--- a/backend/src/main/java/moadong/club/repository/ClubApplicationRepository.java
+++ b/backend/src/main/java/moadong/club/repository/ClubApplicationRepository.java
@@ -5,8 +5,11 @@
import org.springframework.data.mongodb.repository.Query;
import java.util.List;
+import java.util.Optional;
public interface ClubApplicationRepository extends MongoRepository {
@Query("{ 'questionId': ?0, 'status': { $exists: true, $ne: 'DRAFT' } }")
List findAllByQuestionId(String questionId);
+
+ Optional findByIdAndQuestionId(String id, String questionId);
}
\ No newline at end of file
diff --git a/backend/src/main/java/moadong/club/service/ClubApplyService.java b/backend/src/main/java/moadong/club/service/ClubApplyService.java
index 7834df050..2bef509df 100644
--- a/backend/src/main/java/moadong/club/service/ClubApplyService.java
+++ b/backend/src/main/java/moadong/club/service/ClubApplyService.java
@@ -1,10 +1,12 @@
package moadong.club.service;
+import jakarta.transaction.Transactional;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import moadong.club.entity.*;
import moadong.club.enums.ClubApplicationQuestionType;
import moadong.club.payload.dto.ClubApplicantsResult;
+import moadong.club.payload.request.ClubApplicantEditRequest;
import moadong.club.payload.request.ClubApplicationCreateRequest;
import moadong.club.payload.request.ClubApplicationEditRequest;
import moadong.club.payload.request.ClubApplyRequest;
@@ -123,6 +125,38 @@ public ClubApplyInfoResponse getClubApplyInfo(String clubId, CustomUserDetails u
.build();
}
+ @Transactional
+ public void editApplicantDetail(String clubId, String appId, ClubApplicantEditRequest request, CustomUserDetails user) {
+ Club club = clubRepository.findById(clubId)
+ .orElseThrow(() -> new RestApiException(ErrorCode.CLUB_NOT_FOUND));
+
+ if (!user.getId().equals(club.getUserId())) {
+ throw new RestApiException(ErrorCode.USER_UNAUTHORIZED);
+ }
+
+ ClubApplication application = clubApplicationRepository.findByIdAndQuestionId(appId, clubId)
+ .orElseThrow(() -> new RestApiException(ErrorCode.APPLICANT_NOT_FOUND));
+
+ application.updateDetail(request.memo(), request.status());
+
+ clubApplicationRepository.save(application);
+ }
+
+ @Transactional
+ public void deleteApplicant(String clubId, String appId, CustomUserDetails user) {
+ Club club = clubRepository.findById(clubId)
+ .orElseThrow(() -> new RestApiException(ErrorCode.CLUB_NOT_FOUND));
+
+ if (!user.getId().equals(club.getUserId())) {
+ throw new RestApiException(ErrorCode.USER_UNAUTHORIZED);
+ }
+
+ ClubApplication application = clubApplicationRepository.findByIdAndQuestionId(appId, clubId)
+ .orElseThrow(() -> new RestApiException(ErrorCode.APPLICANT_NOT_FOUND));
+
+ clubApplicationRepository.delete(application);
+ }
+
private void validateAnswers(List answers, ClubQuestion clubQuestion) {
// 미리 질문과 응답 id 만들어두기
Map questionMap = clubQuestion.getQuestions().stream()
diff --git a/backend/src/main/java/moadong/global/exception/ErrorCode.java b/backend/src/main/java/moadong/global/exception/ErrorCode.java
index e0b6ae873..f32b7ed6b 100644
--- a/backend/src/main/java/moadong/global/exception/ErrorCode.java
+++ b/backend/src/main/java/moadong/global/exception/ErrorCode.java
@@ -39,7 +39,8 @@ public enum ErrorCode {
QUESTION_NOT_FOUND(HttpStatus.NOT_FOUND, "800-4", "존재하지 않은 질문입니다."),
REQUIRED_QUESTION_MISSING(HttpStatus.BAD_REQUEST, "800-5", "필수 응답 질문이 누락되었습니다."),
- AES_CIPHER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "900-1", "암호화 중 오류가 발생했습니다.")
+ AES_CIPHER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "900-1", "암호화 중 오류가 발생했습니다."),
+ APPLICANT_NOT_FOUND(HttpStatus.NOT_FOUND, "900-2", "지원서가 존재하지 않습니다."),
;
private final HttpStatus httpStatus;