Skip to content

Commit 86690a1

Browse files
authored
feat: 솜커톤 모집 API 생성
* fix: 면접 예약 API 면접 일정 조회시 status도 같이 반환 * fix: 면접 예약 API 예약자 명단 조회 API 추가 * fix: 면접 예약 API 예약되어있는 슬롯은 삭제하지 않는 기능 추가 * fix: 면접 예약자 조회 API 면접일, 면접시간, 면접을 예약한 날짜과 시간 추가 * feat: 솜커톤 참가자 모집 API 생성 * feat: 솜커톤 참가자 모집 API 요청 URL에 somkathon 추가 * fix: 솜커톤 참가자 모집 API comment 해결 * fix: 솜커톤 참가자 모집 API comment 해결
1 parent bd2934c commit 86690a1

File tree

10 files changed

+373
-4
lines changed

10 files changed

+373
-4
lines changed

src/main/java/dmu/dasom/api/domain/common/exception/ErrorCode.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ public enum ErrorCode {
3636
SLOT_NOT_ACTIVE(400, "C027", "해당 슬롯이 비활성화 되었습니다."),
3737
FILE_ENCODE_FAIL(400, "C028", "파일 인코딩에 실패하였습니다."),
3838
RECRUITMENT_NOT_ACTIVE(400, "C029", "모집 기간이 아닙니다."),
39+
NOT_FOUND_PARTICIPANT(400, "C030", "참가자를 찾을 수 없습니다.")
3940
;
4041

4142
private final int status;
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package dmu.dasom.api.domain.interview.repositoty;
1+
package dmu.dasom.api.domain.interview.repository;
22

33
import dmu.dasom.api.domain.interview.entity.InterviewReservation;
44
import org.springframework.data.jpa.repository.JpaRepository;

src/main/java/dmu/dasom/api/domain/interview/repositoty/InterviewSlotRepository.java renamed to src/main/java/dmu/dasom/api/domain/interview/repository/InterviewSlotRepository.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package dmu.dasom.api.domain.interview.repositoty;
1+
package dmu.dasom.api.domain.interview.repository;
22

33
import dmu.dasom.api.domain.interview.entity.InterviewSlot;
44
import dmu.dasom.api.domain.interview.enums.InterviewStatus;

src/main/java/dmu/dasom/api/domain/interview/service/InterviewServiceImpl.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010
import dmu.dasom.api.domain.interview.entity.InterviewReservation;
1111
import dmu.dasom.api.domain.interview.entity.InterviewSlot;
1212
import dmu.dasom.api.domain.interview.enums.InterviewStatus;
13-
import dmu.dasom.api.domain.interview.repositoty.InterviewReservationRepository;
14-
import dmu.dasom.api.domain.interview.repositoty.InterviewSlotRepository;
13+
import dmu.dasom.api.domain.interview.repository.InterviewReservationRepository;
14+
import dmu.dasom.api.domain.interview.repository.InterviewSlotRepository;
1515
import dmu.dasom.api.domain.recruit.service.RecruitServiceImpl;
1616
import jakarta.persistence.EntityListeners;
1717
import lombok.RequiredArgsConstructor;
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
package dmu.dasom.api.domain.somkathon.controller;
2+
3+
import dmu.dasom.api.domain.somkathon.dto.SomParticipantRequestDto;
4+
import dmu.dasom.api.domain.somkathon.dto.SomParticipantResponseDto;
5+
import dmu.dasom.api.domain.somkathon.service.SomParticipantService;
6+
import io.swagger.v3.oas.annotations.Operation;
7+
import io.swagger.v3.oas.annotations.media.Content;
8+
import io.swagger.v3.oas.annotations.media.ExampleObject;
9+
import io.swagger.v3.oas.annotations.media.Schema;
10+
import io.swagger.v3.oas.annotations.responses.ApiResponse;
11+
import io.swagger.v3.oas.annotations.responses.ApiResponses;
12+
import jakarta.validation.Valid;
13+
import lombok.RequiredArgsConstructor;
14+
import org.springframework.http.ResponseEntity;
15+
import org.springframework.validation.annotation.Validated;
16+
import org.springframework.web.ErrorResponse;
17+
import org.springframework.web.bind.annotation.*;
18+
19+
import java.util.List;
20+
21+
@RestController
22+
@RequestMapping("/api/somkathon/participants")
23+
@RequiredArgsConstructor
24+
@Validated
25+
public class SomParticipantController {
26+
27+
private final SomParticipantService somParticipantService;
28+
29+
/**
30+
* 참가자 등록
31+
*/
32+
@Operation(summary = "솜커톤 참가자 등록", description = "솜커톤 참가자를 등록합니다.")
33+
@ApiResponses(value = {
34+
@ApiResponse(responseCode = "200", description = "참가자 등록 성공"),
35+
@ApiResponse(responseCode = "400", description = "중복 학번 또는 필수 값 누락",
36+
content = @Content(
37+
mediaType = "application/json",
38+
schema = @Schema(implementation = ErrorResponse.class),
39+
examples = {
40+
@ExampleObject(
41+
name = "중복된 학번",
42+
value = "{ \"code\": \"C002\", \"message\": \"이미 등록된 학번입니다.\" }"
43+
),
44+
@ExampleObject(
45+
name = "필수 값 누락",
46+
value = "{ \"code\": \"C001\", \"message\": \"요청한 값이 올바르지 않습니다.\" }"
47+
)}))})
48+
@PostMapping("/create")
49+
public ResponseEntity<SomParticipantResponseDto> create(@Valid @RequestBody final SomParticipantRequestDto request) {
50+
return ResponseEntity.ok(somParticipantService.createParticipant(request));
51+
}
52+
53+
/**
54+
* 모든 참가자 조회
55+
*/
56+
@Operation(summary = "솜커톤 참가자 목록 조회", description = "모든 솜커톤 참가자를 조회합니다.")
57+
@ApiResponses(value = {
58+
@ApiResponse(responseCode = "200", description = "참가자 목록 조회 성공")})
59+
@GetMapping
60+
public ResponseEntity<List<SomParticipantResponseDto>> findAll() {
61+
return ResponseEntity.ok(somParticipantService.getAllParticipants());
62+
}
63+
64+
/**
65+
* 특정 참가자 조회
66+
*/
67+
@Operation(summary = "솜커톤 참가자 상세 조회", description = "특정 솜커톤 참가자의 상세 정보를 조회합니다.")
68+
@ApiResponses(value = {
69+
@ApiResponse(responseCode = "200", description = "참가자 상세 조회 성공"),
70+
@ApiResponse(responseCode = "400", description = "존재하지 않는 ID",
71+
content = @Content(
72+
mediaType = "application/json",
73+
schema = @Schema(implementation=ErrorResponse.class),
74+
examples={
75+
@ExampleObject(
76+
name="존재하지 않는 ID",
77+
value="{\"code\":\"C004\",\"message\":\"참가자를 찾을 수 없습니다.\"}")}))})
78+
@GetMapping("/{id}")
79+
public ResponseEntity<SomParticipantResponseDto> getById(@PathVariable final Long id) {
80+
return ResponseEntity.ok(somParticipantService.getParticipant(id));
81+
}
82+
83+
/**
84+
* 참가자 정보 수정
85+
*/
86+
@Operation(summary = "솜커톤 참가자 정보 수정", description = "특정 솜커톤 참가자의 정보를 수정합니다.")
87+
@ApiResponses(value = {
88+
@ApiResponse(responseCode = "200", description = "참가자 정보 수정 성공"),
89+
@ApiResponse(responseCode = "400", description = "중복 학번 또는 존재하지 않는 ID",
90+
content = @Content(
91+
mediaType = "application/json",
92+
schema=@Schema(implementation=ErrorResponse.class),
93+
examples={
94+
@ExampleObject(
95+
name="중복된 학번",
96+
value="{\"code\":\"C002\",\"message\":\"이미 등록된 학번입니다.\"}"),
97+
@ExampleObject(
98+
name="존재하지 않는 ID",
99+
value="{\"code\":\"C004\",\"message\":\"참가자를 찾을 수 없습니다.\"}")}))})
100+
@PutMapping("/{id}")
101+
public ResponseEntity<SomParticipantResponseDto> update(@PathVariable final Long id,
102+
@Valid @RequestBody final SomParticipantRequestDto request) {
103+
return ResponseEntity.ok(somParticipantService.updateParticipant(id, request));
104+
}
105+
106+
/**
107+
* 참가자 삭제 (Delete)
108+
*/
109+
@Operation(summary = "솜커톤 참가자 삭제", description = "특정 솜커톤 참가자를 삭제합니다.")
110+
@ApiResponses(value={
111+
@ApiResponse(responseCode="204",description="참가자 삭제 성공"),
112+
@ApiResponse(responseCode="400",description="존재하지 않는 ID",
113+
content=@Content(
114+
mediaType="application/json",
115+
schema=@Schema(implementation=ErrorResponse.class),
116+
examples={
117+
@ExampleObject(
118+
name="존재하지 않는 ID",
119+
value="{\"code\":\"C004\",\"message\":\"참가자를 찾을 수 없습니다.\"}")}))})
120+
@DeleteMapping("/{id}")
121+
public ResponseEntity<Void> delete(@PathVariable final Long id) {
122+
somParticipantService.deleteParticipant(id);
123+
return ResponseEntity.noContent().build();
124+
}
125+
126+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package dmu.dasom.api.domain.somkathon.dto;
2+
3+
import io.swagger.v3.oas.annotations.media.Schema;
4+
import jakarta.validation.constraints.Email;
5+
import jakarta.validation.constraints.NotBlank;
6+
import jakarta.validation.constraints.Pattern;
7+
import jakarta.validation.constraints.Size;
8+
import lombok.Getter;
9+
import lombok.Setter;
10+
11+
@Getter
12+
@Setter
13+
@Schema(description = "솜커톤 참가자 요청 DTO")
14+
public class SomParticipantRequestDto {
15+
@NotBlank(message = "참가자 이름은 필수 입력 값입니다.")
16+
@Size(max = 50, message = "참가자 이름은 최대 50자까지 입력 가능합니다.")
17+
@Schema(description = "참가자 이름", example = "유승완", required = true)
18+
private String participantName; // 참가자 이름
19+
20+
@NotBlank(message = "학번은 필수 입력 값입니다.")
21+
@Pattern(regexp = "^[0-9]{8}$", message = "학번은 8자리 숫자여야 합니다.")
22+
@Schema(description = "학번 (8자리 숫자)", example = "20250001", required = true)
23+
private String studentId;
24+
25+
@NotBlank(message = "학과는 필수 입력 값입니다.")
26+
@Size(max = 100, message = "학과는 최대 100자까지 입력 가능합니다.")
27+
@Schema(description = "학과", example = "컴퓨터소프트웨어공학과", required = true)
28+
private String department; // 학과
29+
30+
@NotBlank(message = "학년은 필수 입력 값입니다.")
31+
@Pattern(regexp = "^[1-4]$", message = "학년은 1~4 사이의 숫자여야 합니다.")
32+
@Schema(description = "학년 (1~4)", example = "3", required = true)
33+
private String grade; // 학년
34+
35+
@NotBlank(message = "연락처는 필수 입력 값입니다.")
36+
@Pattern(regexp = "^010-[0-9]{4}-[0-9]{4}$", message = "연락처는 '010-XXXX-XXXX' 형식이어야 합니다.")
37+
@Schema(description = "연락처 (010-XXXX-XXXX 형식)", example = "010-1234-5678", required = true)
38+
private String contact; // 연락처
39+
40+
@NotBlank(message = "이메일은 필수 입력 값입니다.")
41+
@Email(message = "올바른 이메일 형식이 아닙니다.")
42+
@Schema(description = "이메일 주소", example = "[email protected]", required = true)
43+
private String email; // 이메일
44+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package dmu.dasom.api.domain.somkathon.dto;
2+
3+
import io.swagger.v3.oas.annotations.media.Schema;
4+
import lombok.Builder;
5+
import lombok.Getter;
6+
import lombok.Setter;
7+
8+
@Getter
9+
@Setter
10+
@Builder
11+
@Schema(description = "솜커톤 참가자 응답 DTO")
12+
public class SomParticipantResponseDto {
13+
14+
@Schema(description = "참가자 ID", example = "1", required = true)
15+
private Long id; // 참가자 ID
16+
17+
@Schema(description = "참가자 이름", example = "홍길동", required = true)
18+
private String participantName; // 참가자 이름
19+
20+
@Schema(description = "학번 (8자리 숫자)", example = "20230001", required = true)
21+
private String studentId; // 학번
22+
23+
@Schema(description = "학과", example = "컴퓨터공학과", required = true)
24+
private String department; // 학과
25+
26+
@Schema(description = "학년 (1~4)", example = "3", required = true)
27+
private String grade; // 학년
28+
29+
@Schema(description = "연락처 (010-XXXX-XXXX 형식)", example = "010-1234-5678", required = true)
30+
private String contact; // 연락처
31+
32+
@Schema(description = "이메일 주소", example = "[email protected]", required = true)
33+
private String email; // 이메일
34+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package dmu.dasom.api.domain.somkathon.entity;
2+
3+
import dmu.dasom.api.domain.common.BaseEntity;
4+
import dmu.dasom.api.domain.somkathon.dto.SomParticipantRequestDto;
5+
import jakarta.persistence.*;
6+
import lombok.AllArgsConstructor;
7+
import lombok.Builder;
8+
import lombok.Getter;
9+
import lombok.NoArgsConstructor;
10+
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
11+
12+
@AllArgsConstructor
13+
@Builder
14+
@Entity
15+
@EntityListeners(AuditingEntityListener.class)
16+
@Getter
17+
@NoArgsConstructor
18+
public class SomParticipant extends BaseEntity {
19+
20+
@Id
21+
@GeneratedValue(strategy = GenerationType.IDENTITY)
22+
private Long id;
23+
24+
@Column(nullable = false)
25+
private String participantName; // 참가자 이름
26+
27+
@Column(nullable = false, unique = true)
28+
private String studentId; // 학번
29+
30+
@Column(nullable = false)
31+
private String department; // 학과
32+
33+
@Column(nullable = false)
34+
private String grade; // 학년
35+
36+
@Column(nullable = false)
37+
private String contact; // 연락처
38+
39+
@Column(nullable = false)
40+
private String email; // 이메일
41+
42+
public void update(SomParticipantRequestDto requestDto) {
43+
this.participantName = requestDto.getParticipantName();
44+
this.studentId = requestDto.getStudentId();
45+
this.department = requestDto.getDepartment();
46+
this.grade = requestDto.getGrade();
47+
this.contact = requestDto.getContact();
48+
this.email = requestDto.getEmail();
49+
}
50+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package dmu.dasom.api.domain.somkathon.repository;
2+
3+
import dmu.dasom.api.domain.somkathon.entity.SomParticipant;
4+
import org.springframework.data.jpa.repository.JpaRepository;
5+
import org.springframework.stereotype.Repository;
6+
7+
import java.util.Optional;
8+
9+
@Repository
10+
public interface SomParticipantRepository extends JpaRepository<SomParticipant, Long> {
11+
Optional<SomParticipant> findByStudentId(String studentId); // 학번으로 참가자 조회
12+
}

0 commit comments

Comments
 (0)