Skip to content
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

모집공고 상태 자동변경 로직 작성 완료 #389

Merged
merged 8 commits into from
Jun 25, 2024
Original file line number Diff line number Diff line change
@@ -1,20 +1,27 @@
package page.clab.api.domain.recruitment.application;

import jakarta.persistence.EntityManager;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;
import page.clab.api.domain.notification.application.NotificationService;
import page.clab.api.domain.recruitment.dao.RecruitmentRepository;
import page.clab.api.domain.recruitment.domain.Recruitment;
import page.clab.api.domain.recruitment.domain.RecruitmentStatus;
import page.clab.api.domain.recruitment.dto.request.RecruitmentRequestDto;
import page.clab.api.domain.recruitment.dto.request.RecruitmentUpdateRequestDto;
import page.clab.api.domain.recruitment.dto.response.RecruitmentResponseDto;
import page.clab.api.global.common.dto.PagedResponseDto;
import page.clab.api.global.exception.NotFoundException;
import page.clab.api.global.validation.ValidationService;

import java.time.LocalDateTime;
import java.util.List;

@Service
Expand All @@ -27,9 +34,16 @@ public class RecruitmentService {

private final RecruitmentRepository recruitmentRepository;

private final PlatformTransactionManager transactionManager;

private final EntityManager entityManager;

private final TransactionDefinition transactionDefinition;

@Transactional
public Long createRecruitment(RecruitmentRequestDto requestDto) {
Recruitment recruitment = RecruitmentRequestDto.toEntity(requestDto);
updateRecruitmentStatusByRecruitment(recruitment);
limehee marked this conversation as resolved.
Show resolved Hide resolved
validationService.checkValid(recruitment);
notificationService.sendNotificationToAllMembers("새로운 모집 공고가 등록되었습니다.");
return recruitmentRepository.save(recruitment).getId();
Expand All @@ -55,6 +69,7 @@ public Long updateRecruitment(Long recruitmentId, RecruitmentUpdateRequestDto re
Recruitment recruitment = getRecruitmentByIdOrThrow(recruitmentId);
recruitment.update(requestDto);
validationService.checkValid(recruitment);
updateRecruitmentStatusByRecruitment(recruitment);
return recruitmentRepository.save(recruitment).getId();
}

Expand All @@ -69,4 +84,24 @@ public Recruitment getRecruitmentByIdOrThrow(Long recruitmentId) {
.orElseThrow(() -> new NotFoundException("해당 모집 공고가 존재하지 않습니다."));
}

@Scheduled(cron = "0 * * * * *")
public void updateRecruitmentStatus(){
List<Recruitment> recruitments = recruitmentRepository.findAll();
recruitments.forEach(this::updateRecruitmentStatusByRecruitment);
}

public void updateRecruitmentStatusByRecruitment(Recruitment recruitment){
TransactionStatus transactionStatus = transactionManager.getTransaction(transactionDefinition);
LocalDateTime now = LocalDateTime.now();
RecruitmentStatus newStatus = RecruitmentStatus.OPEN;
if (now.isBefore(recruitment.getStartDate())) {
newStatus = RecruitmentStatus.UPCOMING;
} else if(now.isAfter(recruitment.getEndDate())) {
newStatus = RecruitmentStatus.CLOSED;
}
recruitment.updateStatus(newStatus);
entityManager.merge(recruitment);
transactionManager.commit(transactionStatus);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -52,15 +52,16 @@ public class Recruitment extends BaseEntity {
private String target;

@Column(nullable = false)
@Size(min = 1, message = "{size.recruitment.status}")
limehee marked this conversation as resolved.
Show resolved Hide resolved
private String status;
@Enumerated(EnumType.STRING)
private RecruitmentStatus status;
limehee marked this conversation as resolved.
Show resolved Hide resolved

public void update(RecruitmentUpdateRequestDto recruitmentUpdateRequestDto) {
Optional.ofNullable(recruitmentUpdateRequestDto.getStartDate()).ifPresent(this::setStartDate);
Optional.ofNullable(recruitmentUpdateRequestDto.getEndDate()).ifPresent(this::setEndDate);
Optional.ofNullable(recruitmentUpdateRequestDto.getApplicationType()).ifPresent(this::setApplicationType);
Optional.ofNullable(recruitmentUpdateRequestDto.getTarget()).ifPresent(this::setTarget);
Optional.ofNullable(recruitmentUpdateRequestDto.getStatus()).ifPresent(this::setStatus);
}

public void updateStatus(RecruitmentStatus status) { this.status = status; }

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package page.clab.api.domain.recruitment.domain;

import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
public enum RecruitmentStatus {

UPCOMING("UPCOMING", "모집 예정"),
OPEN("OPEN", "모집중"),
CLOSED("CLOSED", "모집 종료");

private String key;
private String description;

}
Original file line number Diff line number Diff line change
Expand Up @@ -29,17 +29,12 @@ public class RecruitmentRequestDto {
@Schema(description = "대상", example = "2~3학년", required = true)
private String target;

@NotNull(message = "{notNull.recruitment.status}")
@Schema(description = "상태", example = "종료", required = true)
private String status;

public static Recruitment toEntity(RecruitmentRequestDto requestDto) {
return Recruitment.builder()
.startDate(requestDto.getStartDate())
.endDate(requestDto.getEndDate())
.applicationType(requestDto.getApplicationType())
.target(requestDto.getTarget())
.status(requestDto.getStatus())
.build();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,4 @@ public class RecruitmentUpdateRequestDto {
@Schema(description = "대상", example = "2~3학년")
private String target;

@Schema(description = "상태", example = "종료")
private String status;

}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import lombok.Getter;
import page.clab.api.domain.application.domain.ApplicationType;
import page.clab.api.domain.recruitment.domain.Recruitment;
import page.clab.api.domain.recruitment.domain.RecruitmentStatus;

import java.time.LocalDateTime;

Expand All @@ -21,7 +22,7 @@ public class RecruitmentResponseDto {

private String target;

private String status;
private RecruitmentStatus status;

private LocalDateTime updatedAt;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package page.clab.api.global.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.support.DefaultTransactionDefinition;

@Configuration
public class TransactionConfig {

@Bean
public TransactionDefinition transactionDefinition() {
return new DefaultTransactionDefinition();
}

}
1 change: 0 additions & 1 deletion src/main/resources/messages.properties
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ size.product.name=서비스명은 최소 {min}글자 이상이어야 합니다.
size.product.description=설명은 최소 {min}글자에서 {max}글자 사이어야 합니다.
size.recruitment.applicationType=신청 유형은 최소 {min}자 이상이어야 합니다.
size.recruitment.target=대상은 최소 {min}자 이상이어야 합니다.
size.recruitment.status=상태는 최소 {min}자 이상이어야 합니다.
size.review.content=내용은 {min}자 이상 {max}자 이하여야 합니다.
size.sharedAccount.username=유저명은 {min}자 이상이어야 합니다.
size.sharedAccount.password=비밀번호는 {min}자 이상이어야 합니다.
Expand Down