Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
5 changes: 3 additions & 2 deletions recruitment-service/build.gradle
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
plugins {
id 'java'
id 'org.springframework.boot' version '3.4.5'
id 'io.spring.dependency-management' version '1.1.7'
id 'org.springframework.boot' version '3.1.5'
id 'io.spring.dependency-management' version '1.1.3'
}

group = 'com.example'
Expand All @@ -28,6 +28,7 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.2.0'
compileOnly 'org.projectlombok:lombok'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
runtimeOnly 'com.mysql:mysql-connector-j'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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("모집글 참여 완료");
}

// 모집글 전체 조회
Expand All @@ -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())) {
Expand All @@ -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());
}

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
Expand All @@ -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;

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;
}
}
Loading