-
Notifications
You must be signed in to change notification settings - Fork 0
feat: 모집 생성 및 참여 시 주문 생성 기능 구현 #52
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -2,15 +2,13 @@ | |||||||||||||||||
|
|
||||||||||||||||||
| import com.example.recruitment.dto.RecruitmentDetailDto; | ||||||||||||||||||
| import com.example.recruitment.dto.RecruitmentRequestDto; | ||||||||||||||||||
| import com.example.recruitment.dto.order.OrderRequestDto; | ||||||||||||||||||
| import com.example.recruitment.entity.Recruitment; | ||||||||||||||||||
| import com.example.recruitment.entity.RecruitmentParticipant; | ||||||||||||||||||
| import com.example.recruitment.entity.Store; | ||||||||||||||||||
| import com.example.recruitment.entity.User; | ||||||||||||||||||
| import com.example.recruitment.repository.RecruitmentParticipantRepository; | ||||||||||||||||||
| import com.example.recruitment.repository.RecruitmentRepository; | ||||||||||||||||||
| import com.example.recruitment.repository.StoreRepository; | ||||||||||||||||||
| import com.example.recruitment.repository.UserRepository; | ||||||||||||||||||
|
|
||||||||||||||||||
| import com.example.recruitment.service.RecruitmentService; | ||||||||||||||||||
| import jakarta.validation.Valid; | ||||||||||||||||||
| import lombok.RequiredArgsConstructor; | ||||||||||||||||||
| import org.springframework.http.ResponseEntity; | ||||||||||||||||||
|
|
@@ -21,29 +19,27 @@ | |||||||||||||||||
|
|
||||||||||||||||||
| @RestController | ||||||||||||||||||
| @RequiredArgsConstructor | ||||||||||||||||||
| @RequestMapping("/api/recruitments") | ||||||||||||||||||
| @RequestMapping("/api/v1/recruitments") | ||||||||||||||||||
| public class RecruitmentController { | ||||||||||||||||||
|
|
||||||||||||||||||
| private final RecruitmentService recruitmentService; | ||||||||||||||||||
| private final RecruitmentRepository recruitmentRepository; | ||||||||||||||||||
| private final UserRepository userRepository; | ||||||||||||||||||
| private final StoreRepository storeRepository; | ||||||||||||||||||
| private final RecruitmentParticipantRepository participantRepository; | ||||||||||||||||||
|
|
||||||||||||||||||
| // 모집글 생성 | ||||||||||||||||||
| //모집글 생성 (Order 서버에 주문 생성 포함) | ||||||||||||||||||
| @PostMapping | ||||||||||||||||||
| public Recruitment createRecruitment(@Valid @RequestBody RecruitmentRequestDto dto) { | ||||||||||||||||||
| User user = userRepository.findById(dto.getUserId()).orElseThrow(); | ||||||||||||||||||
| Store store = storeRepository.findById(dto.getStoreId()).orElseThrow(); | ||||||||||||||||||
|
|
||||||||||||||||||
| Recruitment recruitment = new Recruitment(); | ||||||||||||||||||
| recruitment.setUser(user); | ||||||||||||||||||
| recruitment.setStore(store); | ||||||||||||||||||
| recruitment.setTitle(dto.getTitle()); | ||||||||||||||||||
| recruitment.setDescription(dto.getDescription()); | ||||||||||||||||||
| recruitment.setDeadlineTime(dto.getDeadlineTime()); | ||||||||||||||||||
| recruitment.setStatus("RECRUITING"); | ||||||||||||||||||
| public ResponseEntity<?> createRecruitment(@Valid @RequestBody RecruitmentRequestDto dto) { | ||||||||||||||||||
| recruitmentService.createRecruitment(dto); | ||||||||||||||||||
| return ResponseEntity.ok("모집글 생성 완료"); | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| return recruitmentRepository.save(recruitment); | ||||||||||||||||||
| //모집글 참여 (Order 서버에 주문 생성 포함) | ||||||||||||||||||
| @PostMapping("/{recruitmentId}/join") | ||||||||||||||||||
| public ResponseEntity<?> joinRecruitment(@PathVariable Long recruitmentId, | ||||||||||||||||||
| @RequestParam Long userId, | ||||||||||||||||||
| @RequestBody OrderRequestDto orderRequestDto) { | ||||||||||||||||||
| recruitmentService.joinRecruitment(recruitmentId, userId, orderRequestDto); | ||||||||||||||||||
| return ResponseEntity.ok("모집글 참여 완료"); | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| // 모집글 전체 조회 | ||||||||||||||||||
|
|
@@ -52,84 +48,56 @@ public List<Recruitment> getAll() { | |||||||||||||||||
| return recruitmentRepository.findAll(); | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| // 상태별 조회 (ex. /api/recruitments?status=RECRUITING) | ||||||||||||||||||
| // 상태별 조회 | ||||||||||||||||||
| @GetMapping(params = "status") | ||||||||||||||||||
| public List<Recruitment> getByStatus(@RequestParam String status) { | ||||||||||||||||||
| return recruitmentRepository.findByStatus(status); | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| // 모집글 상세 조회 | ||||||||||||||||||
| @GetMapping("/{recruitmentId}") | ||||||||||||||||||
| public ResponseEntity<?> getRecruitmentDetail(@PathVariable Long recruitmentId) { | ||||||||||||||||||
| Recruitment recruitment = recruitmentRepository.findById(recruitmentId).orElseThrow(); | ||||||||||||||||||
|
|
||||||||||||||||||
| // 참여자 목록 조회 | ||||||||||||||||||
| List<RecruitmentParticipant> participantEntities = | ||||||||||||||||||
| participantRepository.findByRecruitmentId(recruitmentId); | ||||||||||||||||||
|
|
||||||||||||||||||
| List<User> participants = participantEntities.stream() | ||||||||||||||||||
| .map(RecruitmentParticipant::getUser) | ||||||||||||||||||
| .toList(); | ||||||||||||||||||
|
|
||||||||||||||||||
| // DTO 구성 | ||||||||||||||||||
| RecruitmentDetailDto dto = new RecruitmentDetailDto(); | ||||||||||||||||||
| dto.setId(recruitment.getId()); | ||||||||||||||||||
| dto.setTitle(recruitment.getTitle()); | ||||||||||||||||||
| dto.setDescription(recruitment.getDescription()); | ||||||||||||||||||
| dto.setStatus(recruitment.getStatus()); | ||||||||||||||||||
| dto.setDeadlineTime(recruitment.getDeadlineTime()); | ||||||||||||||||||
| dto.setUser(recruitment.getUser()); | ||||||||||||||||||
| dto.setStore(recruitment.getStore()); | ||||||||||||||||||
| dto.setParticipants(participants); | ||||||||||||||||||
|
|
||||||||||||||||||
| return ResponseEntity.ok(dto); | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| @GetMapping("/user/{userId}/created-recruitments") | ||||||||||||||||||
| public List<Recruitment> getRecruitmentsCreatedByUser(@PathVariable Long userId) { | ||||||||||||||||||
| return recruitmentRepository.findByUserId(userId); | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| // 특정 유저가 참여한 모집글 조회 | ||||||||||||||||||
| @GetMapping("/user/{userId}/joined-recruitments") | ||||||||||||||||||
| public List<Recruitment> getRecruitmentsJoinedByUser(@PathVariable Long userId) { | ||||||||||||||||||
| List<RecruitmentParticipant> participantList = participantRepository.findByUserId(userId); | ||||||||||||||||||
| return participantList.stream() | ||||||||||||||||||
| .map(RecruitmentParticipant::getRecruitment) | ||||||||||||||||||
| .toList(); | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
|
|
||||||||||||||||||
|
|
||||||||||||||||||
|
|
||||||||||||||||||
| // 모집글 참여 | ||||||||||||||||||
| @PostMapping("/{recruitmentId}/join") | ||||||||||||||||||
| public ResponseEntity<?> joinRecruitment(@PathVariable Long recruitmentId, @RequestParam Long userId) { | ||||||||||||||||||
| User user = userRepository.findById(userId).orElseThrow(); | ||||||||||||||||||
| public ResponseEntity<?> getRecruitmentDetail(@PathVariable Long recruitmentId) { | ||||||||||||||||||
| Recruitment recruitment = recruitmentRepository.findById(recruitmentId).orElseThrow(); | ||||||||||||||||||
|
|
||||||||||||||||||
| boolean alreadyJoined = participantRepository | ||||||||||||||||||
| .findByUserIdAndRecruitmentId(userId, recruitmentId) | ||||||||||||||||||
| .isPresent(); | ||||||||||||||||||
|
|
||||||||||||||||||
| if (alreadyJoined) { | ||||||||||||||||||
| return ResponseEntity.badRequest().body("이미 참여한 모집입니다."); | ||||||||||||||||||
| } | ||||||||||||||||||
| List<RecruitmentParticipant> participants = | ||||||||||||||||||
| participantRepository.findByRecruitmentId(recruitmentId); | ||||||||||||||||||
| List<User> participantUsers = participants.stream() | ||||||||||||||||||
| .map(RecruitmentParticipant::getUser) | ||||||||||||||||||
| .toList(); | ||||||||||||||||||
|
|
||||||||||||||||||
| RecruitmentDetailDto dto = new RecruitmentDetailDto(); | ||||||||||||||||||
| dto.setId(recruitment.getId()); | ||||||||||||||||||
| dto.setTitle(recruitment.getTitle()); | ||||||||||||||||||
| dto.setDescription(recruitment.getDescription()); | ||||||||||||||||||
| dto.setStatus(recruitment.getStatus()); | ||||||||||||||||||
| dto.setDeadlineTime(recruitment.getDeadlineTime()); | ||||||||||||||||||
| dto.setUser(recruitment.getUser()); | ||||||||||||||||||
| dto.setStore(recruitment.getStore()); | ||||||||||||||||||
| dto.setParticipants(participantUsers); | ||||||||||||||||||
|
|
||||||||||||||||||
| return ResponseEntity.ok(dto); | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| RecruitmentParticipant participant = new RecruitmentParticipant(); | ||||||||||||||||||
| participant.setUser(user); | ||||||||||||||||||
| participant.setRecruitment(recruitment); | ||||||||||||||||||
| participant.setJoinedAt(LocalDateTime.now()); | ||||||||||||||||||
| // 유저가 만든 모집글 | ||||||||||||||||||
| @GetMapping("/user/{userId}/created-recruitments") | ||||||||||||||||||
| public List<Recruitment> getRecruitmentsCreatedByUser(@PathVariable Long userId) { | ||||||||||||||||||
| return recruitmentRepository.findByUserId(userId); | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| participantRepository.save(participant); | ||||||||||||||||||
| return ResponseEntity.ok("모집글 참여 완료"); | ||||||||||||||||||
| // 유저가 참여한 모집글 | ||||||||||||||||||
| @GetMapping("/user/{userId}/joined-recruitments") | ||||||||||||||||||
| public List<Recruitment> getRecruitmentsJoinedByUser(@PathVariable Long userId) { | ||||||||||||||||||
| List<RecruitmentParticipant> participantList = participantRepository.findByUserId(userId); | ||||||||||||||||||
| return participantList.stream() | ||||||||||||||||||
| .map(RecruitmentParticipant::getRecruitment) | ||||||||||||||||||
| .toList(); | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| // 모집 상태 업데이트 (CONFIRMED 또는 FAILED) | ||||||||||||||||||
| // 모집 상태 업데이트 | ||||||||||||||||||
| @PatchMapping("/{recruitmentId}/status") | ||||||||||||||||||
| public ResponseEntity<?> updateRecruitmentStatus(@PathVariable Long recruitmentId) { | ||||||||||||||||||
| Recruitment recruitment = recruitmentRepository.findById(recruitmentId).orElseThrow(); | ||||||||||||||||||
| LocalDateTime now = LocalDateTime.now(); | ||||||||||||||||||
|
|
||||||||||||||||||
| long participantCount = participantRepository.countByRecruitmentId(recruitmentId); | ||||||||||||||||||
|
|
||||||||||||||||||
| if (now.isAfter(recruitment.getDeadlineTime())) { | ||||||||||||||||||
|
|
@@ -145,68 +113,56 @@ public ResponseEntity<?> updateRecruitmentStatus(@PathVariable Long recruitmentI | |||||||||||||||||
| } | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| // 주문 수락 상태로 변경 (ACCEPTED) | ||||||||||||||||||
| // 주문 수락 상태 변경 | ||||||||||||||||||
| @PatchMapping("/{recruitmentId}/accept") | ||||||||||||||||||
| public ResponseEntity<?> acceptRecruitment(@PathVariable Long recruitmentId) { | ||||||||||||||||||
| Recruitment recruitment = recruitmentRepository.findById(recruitmentId).orElseThrow(); | ||||||||||||||||||
|
|
||||||||||||||||||
| if (!"CONFIRMED".equals(recruitment.getStatus())) { | ||||||||||||||||||
| return ResponseEntity.badRequest().body("주문 수락은 CONFIRMED 상태에서만 가능합니다."); | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| recruitment.setStatus("ACCEPTED"); | ||||||||||||||||||
| recruitmentRepository.save(recruitment); | ||||||||||||||||||
|
|
||||||||||||||||||
| return ResponseEntity.ok("상태가 ACCEPTED로 변경되었습니다."); | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| // 배달 완료 상태로 변경 (DELIVERED) | ||||||||||||||||||
| // 배달 완료 상태 변경 | ||||||||||||||||||
| @PatchMapping("/{recruitmentId}/deliver") | ||||||||||||||||||
| public ResponseEntity<?> completeDelivery(@PathVariable Long recruitmentId) { | ||||||||||||||||||
| Recruitment recruitment = recruitmentRepository.findById(recruitmentId).orElseThrow(); | ||||||||||||||||||
|
|
||||||||||||||||||
| if (!"ACCEPTED".equals(recruitment.getStatus())) { | ||||||||||||||||||
| return ResponseEntity.badRequest().body("배달 완료는 ACCEPTED 상태에서만 가능합니다."); | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| recruitment.setStatus("DELIVERED"); | ||||||||||||||||||
| recruitmentRepository.save(recruitment); | ||||||||||||||||||
|
|
||||||||||||||||||
| return ResponseEntity.ok("상태가 DELIVERED로 변경되었습니다."); | ||||||||||||||||||
| } | ||||||||||||||||||
| // 모집글 삭제 | ||||||||||||||||||
| @DeleteMapping("/{recruitmentId}") | ||||||||||||||||||
| public ResponseEntity<?> deleteRecruitment(@PathVariable Long recruitmentId) { | ||||||||||||||||||
| Recruitment recruitment = recruitmentRepository.findById(recruitmentId).orElseThrow(); | ||||||||||||||||||
|
|
||||||||||||||||||
| recruitmentRepository.delete(recruitment); | ||||||||||||||||||
| return ResponseEntity.ok("모집글이 삭제되었습니다."); | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| // 모집글 수정 | ||||||||||||||||||
| @PutMapping("/{recruitmentId}") | ||||||||||||||||||
| public ResponseEntity<?> updateRecruitment(@PathVariable Long recruitmentId, | ||||||||||||||||||
| @Valid @RequestBody RecruitmentRequestDto dto) { | ||||||||||||||||||
| Recruitment recruitment = recruitmentRepository.findById(recruitmentId).orElseThrow(); | ||||||||||||||||||
|
|
||||||||||||||||||
| // (선택) 본인 작성한 글인지 확인 | ||||||||||||||||||
| if (!recruitment.getUser().getId().equals(dto.getUserId())) { | ||||||||||||||||||
| return ResponseEntity.status(403).body("작성자만 수정할 수 있습니다."); | ||||||||||||||||||
| // 모집글 삭제 | ||||||||||||||||||
| @DeleteMapping("/{recruitmentId}") | ||||||||||||||||||
| public ResponseEntity<?> deleteRecruitment(@PathVariable Long recruitmentId) { | ||||||||||||||||||
| Recruitment recruitment = recruitmentRepository.findById(recruitmentId).orElseThrow(); | ||||||||||||||||||
| recruitmentRepository.delete(recruitment); | ||||||||||||||||||
| return ResponseEntity.ok("모집글이 삭제되었습니다."); | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| // 수정할 항목들 업데이트 | ||||||||||||||||||
| recruitment.setTitle(dto.getTitle()); | ||||||||||||||||||
| recruitment.setDescription(dto.getDescription()); | ||||||||||||||||||
| recruitment.setDeadlineTime(dto.getDeadlineTime()); | ||||||||||||||||||
| // 모집글 수정 | ||||||||||||||||||
| @PutMapping("/{recruitmentId}") | ||||||||||||||||||
| public ResponseEntity<?> updateRecruitment(@PathVariable Long recruitmentId, | ||||||||||||||||||
| @Valid @RequestBody RecruitmentRequestDto dto) { | ||||||||||||||||||
| Recruitment recruitment = recruitmentRepository.findById(recruitmentId).orElseThrow(); | ||||||||||||||||||
| if (!recruitment.getUser().getId().equals(dto.getUserId())) { | ||||||||||||||||||
| return ResponseEntity.status(403).body("작성자만 수정할 수 있습니다."); | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| // (선택) 가게 변경도 허용 | ||||||||||||||||||
| if (dto.getStoreId() != null) { | ||||||||||||||||||
| Store store = storeRepository.findById(dto.getStoreId()).orElseThrow(); | ||||||||||||||||||
| recruitment.setStore(store); | ||||||||||||||||||
| } | ||||||||||||||||||
| recruitment.setTitle(dto.getTitle()); | ||||||||||||||||||
| recruitment.setDescription(dto.getDescription()); | ||||||||||||||||||
| recruitment.setDeadlineTime(dto.getDeadlineTime()); | ||||||||||||||||||
|
|
||||||||||||||||||
| recruitmentRepository.save(recruitment); | ||||||||||||||||||
| return ResponseEntity.ok("모집글이 수정되었습니다."); | ||||||||||||||||||
| } | ||||||||||||||||||
| if (dto.getStoreId() != null) { | ||||||||||||||||||
| recruitment.setStore(recruitment.getStore()); | ||||||||||||||||||
| } | ||||||||||||||||||
|
Comment on lines
+161
to
+163
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 치명적인 로직 버그가 있습니다 새로운 다음과 같이 수정해야 합니다: if (dto.getStoreId() != null) {
- recruitment.setStore(recruitment.getStore());
+ Store store = storeRepository.findById(dto.getStoreId())
+ .orElseThrow(() -> new EntityNotFoundException("Store not found"));
+ recruitment.setStore(store);
}이를 위해 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||
|
|
||||||||||||||||||
| recruitmentRepository.save(recruitment); | ||||||||||||||||||
| return ResponseEntity.ok("모집글이 수정되었습니다."); | ||||||||||||||||||
| } | ||||||||||||||||||
| } | ||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| package com.example.recruitment.controller; | ||
|
|
||
| import org.springframework.web.bind.annotation.GetMapping; | ||
| import org.springframework.web.bind.annotation.RequestMapping; | ||
| import org.springframework.web.bind.annotation.RestController; | ||
|
|
||
| @RestController | ||
| @RequestMapping("/swagger-test") | ||
| public class SwaggerTestController { | ||
| @GetMapping | ||
| public String test() { | ||
| return "Swagger works!"; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,13 +1,14 @@ | ||
| package com.example.recruitment.dto; | ||
|
|
||
| import com.example.recruitment.dto.order.OrderRequestDto; | ||
| import lombok.Getter; | ||
| import lombok.Setter; | ||
|
|
||
| import jakarta.validation.constraints.NotBlank; | ||
| import jakarta.validation.constraints.NotNull; | ||
| import jakarta.validation.constraints.Size; | ||
|
|
||
| import java.time.LocalDateTime; | ||
|
|
||
| import lombok.Getter; | ||
| import lombok.Setter; | ||
| import java.util.List; | ||
|
|
||
| @Getter | ||
| @Setter | ||
|
|
@@ -27,25 +28,19 @@ public class RecruitmentRequestDto { | |
|
|
||
| @NotNull(message = "마감 시간은 필수입니다.") | ||
| private LocalDateTime deadlineTime; | ||
| } | ||
|
|
||
|
|
||
|
|
||
| //원래 dto 코드 | ||
| /* | ||
| * package com.example.recruitment.dto; | ||
| @NotBlank(message = "카테고리는 비어 있을 수 없습니다.") | ||
| private String category; | ||
|
|
||
| import java.time.LocalDateTime; | ||
| // 주문용 메뉴 정보 | ||
| private List<OrderRequestDto.MenuDto> menus; | ||
|
Comment on lines
+35
to
+36
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion 메뉴 필드에 검증 추가를 권장합니다. 메뉴 정보는 주문 생성에 필수적인 데이터이므로 적절한 검증이 필요합니다. 메뉴 필드에 검증 어노테이션을 추가하는 것을 권장합니다: // 주문용 메뉴 정보
+@NotEmpty(message = "메뉴 정보는 필수입니다.")
+@Valid
private List<OrderRequestDto.MenuDto> menus;🤖 Prompt for AI Agents |
||
|
|
||
| import lombok.Getter; | ||
| import lombok.Setter; | ||
|
|
||
| @Getter @Setter | ||
| public class RecruitmentRequestDto { | ||
| private Long userId; | ||
| private Long storeId; | ||
| private String title; | ||
| private String description; | ||
| private LocalDateTime deadlineTime; | ||
| //OrderRequestDto 변환 메서드 | ||
| public OrderRequestDto toOrderRequestDto() { | ||
| OrderRequestDto dto = new OrderRequestDto(); | ||
| dto.setUserId(this.userId); | ||
| dto.setStoreId(this.storeId); | ||
| dto.setMenus(this.menus); | ||
| return dto; | ||
| } | ||
| } | ||
| */ | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,32 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| package com.example.recruitment.dto.order; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import java.util.List; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import lombok.Getter; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import lombok.Setter; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @Getter | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @Setter | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public class OrderRequestDto { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private Long groupId; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private Long userId; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private Long storeId; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private List<MenuDto> menus; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @Getter @Setter | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public static class MenuDto { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private Long menuId; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private String menuName; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private int basePrice; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private int count; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private List<OptionDto> options; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @Getter @Setter | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public static class OptionDto { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private Long optionId; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private String optionName; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private int price; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+11
to
+32
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion 데이터 검증 어노테이션을 추가하세요. DTO에 검증 어노테이션이 없어서 잘못된 데이터가 전달될 수 있습니다. 필수 필드와 값 범위에 대한 검증을 추가하는 것이 좋습니다. +import jakarta.validation.Valid;
+import jakarta.validation.constraints.*;
public class OrderRequestDto {
+ @NotNull(message = "그룹 ID는 필수입니다")
private Long groupId;
+ @NotNull(message = "사용자 ID는 필수입니다")
private Long userId;
+ @NotNull(message = "가게 ID는 필수입니다")
private Long storeId;
+ @NotEmpty(message = "메뉴는 최소 1개 이상이어야 합니다")
+ @Valid
private List<MenuDto> menus;
@Getter @Setter
public static class MenuDto {
+ @NotNull(message = "메뉴 ID는 필수입니다")
private Long menuId;
+ @NotBlank(message = "메뉴명은 필수입니다")
private String menuName;
+ @Min(value = 0, message = "기본 가격은 0 이상이어야 합니다")
private int basePrice;
+ @Min(value = 1, message = "수량은 1 이상이어야 합니다")
private int count;
+ @Valid
private List<OptionDto> options;
}
@Getter @Setter
public static class OptionDto {
+ @NotNull(message = "옵션 ID는 필수입니다")
private Long optionId;
+ @NotBlank(message = "옵션명은 필수입니다")
private String optionName;
+ @Min(value = 0, message = "옵션 가격은 0 이상이어야 합니다")
private int price;
}
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
모집글 참여 기능이 잘 구현되었습니다
새로운 참여 엔드포인트가 RESTful 원칙에 맞게 구현되었고, 서비스 계층으로의 위임도 적절합니다.
보안상
userId를 URL 파라미터 대신 인증된 사용자 정보에서 가져오는 것을 권장합니다:📝 Committable suggestion
🤖 Prompt for AI Agents