Skip to content
Merged
Show file tree
Hide file tree
Changes from 12 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 @@ -36,6 +36,7 @@ public enum ErrorCode {
SLOT_NOT_ACTIVE(400, "C027", "해당 슬롯이 비활성화 되었습니다."),
FILE_ENCODE_FAIL(400, "C028", "파일 인코딩에 실패하였습니다."),
RECRUITMENT_NOT_ACTIVE(400, "C029", "모집 기간이 아닙니다."),
NOT_FOUND_PARTICIPANT(400, "C030", "참가자를 찾을 수 없습니다.")
;

private final int status;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package dmu.dasom.api.domain.interview.repositoty;
package dmu.dasom.api.domain.interview.repository;

import dmu.dasom.api.domain.interview.entity.InterviewReservation;
import org.springframework.data.jpa.repository.JpaRepository;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package dmu.dasom.api.domain.interview.repositoty;
package dmu.dasom.api.domain.interview.repository;

import dmu.dasom.api.domain.interview.entity.InterviewSlot;
import dmu.dasom.api.domain.interview.enums.InterviewStatus;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
import dmu.dasom.api.domain.interview.entity.InterviewReservation;
import dmu.dasom.api.domain.interview.entity.InterviewSlot;
import dmu.dasom.api.domain.interview.enums.InterviewStatus;
import dmu.dasom.api.domain.interview.repositoty.InterviewReservationRepository;
import dmu.dasom.api.domain.interview.repositoty.InterviewSlotRepository;
import dmu.dasom.api.domain.interview.repository.InterviewReservationRepository;
import dmu.dasom.api.domain.interview.repository.InterviewSlotRepository;
import dmu.dasom.api.domain.recruit.service.RecruitServiceImpl;
import jakarta.persistence.EntityListeners;
import lombok.RequiredArgsConstructor;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
package dmu.dasom.api.domain.somkathon.controller;

import dmu.dasom.api.domain.somkathon.dto.SomParticipantRequestDto;
import dmu.dasom.api.domain.somkathon.dto.SomParticipantResponseDto;
import dmu.dasom.api.domain.somkathon.service.SomParticipantService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.ExampleObject;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.ErrorResponse;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/api/somkathon/participants")
@RequiredArgsConstructor
public class SomParticipantController {

private final SomParticipantService somParticipantService;

/**
* 참가자 등록
*/
@Operation(summary = "솜커톤 참가자 등록", description = "솜커톤 참가자를 등록합니다.")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "참가자 등록 성공"),
@ApiResponse(responseCode = "400", description = "중복 학번 또는 필수 값 누락",
content = @Content(
mediaType = "application/json",
schema = @Schema(implementation = ErrorResponse.class),
examples = {
@ExampleObject(
name = "중복된 학번",
value = "{ \"code\": \"C002\", \"message\": \"이미 등록된 학번입니다.\" }"
),
@ExampleObject(
name = "필수 값 누락",
value = "{ \"code\": \"C001\", \"message\": \"요청한 값이 올바르지 않습니다.\" }"
)}))})
@PostMapping("/create")
public ResponseEntity<SomParticipantResponseDto> create(@Valid @RequestBody final SomParticipantRequestDto request) {
final SomParticipantResponseDto responseDto = somParticipantService.createParticipant(request);
return ResponseEntity.ok(responseDto);
}

/**
* 모든 참가자 조회
*/
@Operation(summary = "솜커톤 참가자 목록 조회", description = "모든 솜커톤 참가자를 조회합니다.")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "참가자 목록 조회 성공")})
@GetMapping
public ResponseEntity<List<SomParticipantResponseDto>> findAll() {
final List<SomParticipantResponseDto> participants = somParticipantService.getAllParticipants();
return ResponseEntity.ok(participants);
}

/**
* 특정 참가자 조회
*/
@Operation(summary = "솜커톤 참가자 상세 조회", description = "특정 솜커톤 참가자의 상세 정보를 조회합니다.")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "참가자 상세 조회 성공"),
@ApiResponse(responseCode = "400", description = "존재하지 않는 ID",
content = @Content(
mediaType = "application/json",
schema = @Schema(implementation=ErrorResponse.class),
examples={
@ExampleObject(
name="존재하지 않는 ID",
value="{\"code\":\"C004\",\"message\":\"참가자를 찾을 수 없습니다.\"}")}))})
@GetMapping("/{id}")
public ResponseEntity<SomParticipantResponseDto> getById(@PathVariable final Long id) {
final SomParticipantResponseDto responseDto = somParticipantService.getParticipant(id);
return ResponseEntity.ok(responseDto);
}

/**
* 참가자 정보 수정
*/
@Operation(summary = "솜커톤 참가자 정보 수정", description = "특정 솜커톤 참가자의 정보를 수정합니다.")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "참가자 정보 수정 성공"),
@ApiResponse(responseCode = "400", description = "중복 학번 또는 존재하지 않는 ID",
content = @Content(
mediaType = "application/json",
schema=@Schema(implementation=ErrorResponse.class),
examples={
@ExampleObject(
name="중복된 학번",
value="{\"code\":\"C002\",\"message\":\"이미 등록된 학번입니다.\"}"),
@ExampleObject(
name="존재하지 않는 ID",
value="{\"code\":\"C004\",\"message\":\"참가자를 찾을 수 없습니다.\"}")}))})
@PutMapping("/{id}")
public ResponseEntity<SomParticipantResponseDto> update(@PathVariable final Long id,
@Valid @RequestBody final SomParticipantRequestDto request) {
final SomParticipantResponseDto responseDto = somParticipantService.updateParticipant(id, request);
return ResponseEntity.ok(responseDto);
}

/**
* 참가자 삭제 (Delete)
*/
@Operation(summary = "솜커톤 참가자 삭제", description = "특정 솜커톤 참가자를 삭제합니다.")
@ApiResponses(value={
@ApiResponse(responseCode="204",description="참가자 삭제 성공"),
@ApiResponse(responseCode="400",description="존재하지 않는 ID",
content=@Content(
mediaType="application/json",
schema=@Schema(implementation=ErrorResponse.class),
examples={
@ExampleObject(
name="존재하지 않는 ID",
value="{\"code\":\"C004\",\"message\":\"참가자를 찾을 수 없습니다.\"}")}))})
@DeleteMapping("/{id}")
public ResponseEntity<Void> delete(@PathVariable final Long id) {
somParticipantService.deleteParticipant(id);
return ResponseEntity.noContent().build();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package dmu.dasom.api.domain.somkathon.dto;

import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class SomParticipantRequestDto {
private String participantName; // 참가자 이름
private String studentId;
private String department; // 학과
private String grade; // 학년
private String contact; // 연락처
private String email; // 이메일
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package dmu.dasom.api.domain.somkathon.dto;

import dmu.dasom.api.domain.somkathon.entity.SomParticipant;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
@Builder
public class SomParticipantResponseDto {
private Long id; // 참가자 ID
private String participantName; // 참가자 이름
private String studentId; // 학번
private String department; // 학과
private String grade; // 학년
private String contact; // 연락처
private String email; // 이메일


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package dmu.dasom.api.domain.somkathon.entity;

import dmu.dasom.api.domain.common.BaseEntity;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

@AllArgsConstructor
@Builder
@Entity
@EntityListeners(AuditingEntityListener.class)
@Getter
@NoArgsConstructor
public class SomParticipant extends BaseEntity {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Column(nullable = false)
private String participantName; // 참가자 이름

@Column(nullable = false, unique = true)
private String studentId; // 학번

@Column(nullable = false)
private String department; // 학과

@Column(nullable = false)
private String grade; // 학년

@Column(nullable = false)
private String contact; // 연락처

@Column(nullable = false)
private String email; // 이메일
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package dmu.dasom.api.domain.somkathon.repository;

import dmu.dasom.api.domain.somkathon.entity.SomParticipant;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import java.util.Optional;

@Repository
public interface SomParticipantRepository extends JpaRepository<SomParticipant, Long> {
Optional<SomParticipant> findByStudentId(String studentId); // 학번으로 참가자 조회
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package dmu.dasom.api.domain.somkathon.service;

import dmu.dasom.api.domain.common.exception.CustomException;
import dmu.dasom.api.domain.common.exception.ErrorCode;
import dmu.dasom.api.domain.somkathon.dto.SomParticipantRequestDto;
import dmu.dasom.api.domain.somkathon.dto.SomParticipantResponseDto;
import dmu.dasom.api.domain.somkathon.entity.SomParticipant;
import dmu.dasom.api.domain.somkathon.repository.SomParticipantRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class SomParticipantService {
private final SomParticipantRepository somParticipantRepository;

// 참가자 등록
public SomParticipantResponseDto createParticipant(SomParticipantRequestDto requestDto) {
if(somParticipantRepository.findByStudentId(requestDto.getStudentId()).isPresent()) {
throw new CustomException(ErrorCode.DUPLICATED_STUDENT_NO);
}

SomParticipant participant = SomParticipant.builder()
.participantName(requestDto.getParticipantName())
.studentId(requestDto.getStudentId())
.department(requestDto.getDepartment())
.grade(requestDto.getGrade())
.contact(requestDto.getContact())
.email(requestDto.getEmail())
.build();

SomParticipant saved = somParticipantRepository.save(participant);

return toResponseDto(saved);
}

/**
* 모든 참가자 조회 (Read)
*/
public List<SomParticipantResponseDto> getAllParticipants() {
return somParticipantRepository.findAll().stream()
.map(this::toResponseDto)
.collect(Collectors.toList());
}

/**
* 특정 참가자 조회 (Read)
*/
public SomParticipantResponseDto getParticipant(Long id){
SomParticipant participant = somParticipantRepository.findById(id).orElseThrow(() -> new CustomException(ErrorCode.NOT_FOUND_PARTICIPANT));

return toResponseDto(participant);
}

public SomParticipantResponseDto updateParticipant(Long id, SomParticipantRequestDto requestDto){
SomParticipant participant = somParticipantRepository.findById(id).orElseThrow(() -> new CustomException(ErrorCode.NOT_FOUND_PARTICIPANT));

participant = SomParticipant.builder()
.id(participant.getId())
.participantName(requestDto.getParticipantName())
.studentId(requestDto.getStudentId())
.department(requestDto.getDepartment())
.grade(requestDto.getGrade())
.contact(requestDto.getContact())
.email(requestDto.getEmail())
.build();

Copy link

Copilot AI Apr 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Instead of rebuilding the participant entity using the builder, consider updating the existing entity's fields to preserve any audit or managed fields provided by BaseEntity.

Suggested change
participant = SomParticipant.builder()
.id(participant.getId())
.participantName(requestDto.getParticipantName())
.studentId(requestDto.getStudentId())
.department(requestDto.getDepartment())
.grade(requestDto.getGrade())
.contact(requestDto.getContact())
.email(requestDto.getEmail())
.build();
participant.setParticipantName(requestDto.getParticipantName());
participant.setStudentId(requestDto.getStudentId());
participant.setDepartment(requestDto.getDepartment());
participant.setGrade(requestDto.getGrade());
participant.setContact(requestDto.getContact());
participant.setEmail(requestDto.getEmail());

Copilot uses AI. Check for mistakes.
SomParticipant updated = somParticipantRepository.save(participant);

return toResponseDto(updated);
}

/**
* 참가자 삭제 (Delete)
*/
public void deleteParticipant(Long id) {
if (!somParticipantRepository.existsById(id)) {
throw new RuntimeException("참가자를 찾을 수 없습니다.");
}
somParticipantRepository.deleteById(id);
}


/**
* Entity → Response DTO 변환 메서드
*/
private SomParticipantResponseDto toResponseDto(SomParticipant participant) {
return SomParticipantResponseDto.builder()
.id(participant.getId())
.participantName(participant.getParticipantName())
.studentId(participant.getStudentId())
.department(participant.getDepartment())
.grade(participant.getGrade())
.contact(participant.getContact())
.email(participant.getEmail())
.build();
}
}