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
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package com.mos.backend.studysettings.application;

import com.mos.backend.common.exception.MosException;
import com.mos.backend.common.infrastructure.EntityFacade;
import com.mos.backend.studies.entity.Study;
import com.mos.backend.studysettings.application.res.StudySettingRes;
import com.mos.backend.studysettings.entity.StudySettings;
import com.mos.backend.studysettings.entity.exception.StudySettingsErrorCode;
import com.mos.backend.studysettings.infrastructure.StudySettingRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@RequiredArgsConstructor
public class StudySettingService {
private final StudySettingRepository studySettingRepository;
private final EntityFacade entityFacade;

/**
* 스터디 설정 생성
* @param studyId 생성할 스터디 설정의 스터디 id
*/
@Transactional
public void createStudySetting(Long studyId) {
Study study = entityFacade.getStudy(studyId);
StudySettings studySettings = StudySettings.create(study);
studySettingRepository.save(studySettings);
}

/**
* 스터디 아이디로 스터디 설정 조회해서 업데이트
* @param studyId 조회할 스터디 아이디
* @param lateThresholdMinutes 수정할 지간 기준 시간
* @param absenceThresholdMinutes 수정할 결석 기준 시간
* @return
*/
@Transactional
@PreAuthorize("@studySecurity.isLeaderOrAdmin(#studyId)")
public StudySettingRes update(Long studyId, Integer lateThresholdMinutes, Integer absenceThresholdMinutes) {
StudySettings studySettings = studySettingRepository.findByStudyId(studyId)
.orElseThrow(() -> new MosException(StudySettingsErrorCode.NOT_FOUND));
studySettings.update(lateThresholdMinutes, absenceThresholdMinutes);
return StudySettingRes.of(studySettings, studyId);
}

/**
* 스터디 아이디로 스터디 설정 단 건 조회
* @param studyId 조회할 스터디 설정의 스터디 아이디
* @return 스터디 설정의 공용 응답 dto
*/
@Transactional
@PreAuthorize("@studySecurity.isMemberOrAdmin(#studyId)")
public StudySettingRes read(Long studyId) {
StudySettings studySettings = studySettingRepository.findByStudyId(studyId)
.orElseThrow(() -> new MosException(StudySettingsErrorCode.NOT_FOUND));
return StudySettingRes.of(studySettings, studyId);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.mos.backend.studysettings.application.consumer;

import com.mos.backend.common.event.Event;
import com.mos.backend.studies.application.event.StudyCreatedEventPayload;
import com.mos.backend.studysettings.application.StudySettingService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import org.springframework.transaction.event.TransactionalEventListener;

import static org.springframework.transaction.event.TransactionPhase.BEFORE_COMMIT;

@RequiredArgsConstructor
@Component
public class StudySettingConsumer {
private final StudySettingService studySettingService;

@TransactionalEventListener(phase = BEFORE_COMMIT)
public void handleStudyCreatedEvent(Event<StudyCreatedEventPayload> event) {
StudyCreatedEventPayload payload = event.getPayload();
studySettingService.createStudySetting(payload.getStudyId());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.mos.backend.studysettings.application.res;

import com.mos.backend.studysettings.entity.StudySettings;
import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
public class StudySettingRes {
private Long studySettingId;
private Long studyId;
private Integer lateThresholdMinutes;
private Integer absenceThresholdMinutes;

public static StudySettingRes of(StudySettings studySettings, Long studyId) {
return new StudySettingRes(
studySettings.getId(),
studyId,
studySettings.getLateThresholdMinutes(),
studySettings.getAbsenceThresholdMinutes()
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package com.mos.backend.studysettings.entity;

import com.mos.backend.common.entity.BaseAuditableEntity;
import com.mos.backend.studies.entity.Study;
import jakarta.persistence.*;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.OnDelete;
import org.hibernate.annotations.OnDeleteAction;

@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Table(name = "study_settings")
public class StudySettings extends BaseAuditableEntity {

public static final int DEFAULT_LATE_THRESHOLD_MINUTES = 15;
public static final int DEFAULT_ABSENCE_THRESHOLD_MINUTES = 60;

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

@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(nullable = false, name = "study_id")
@OnDelete(action = OnDeleteAction.CASCADE)
private Study study;

@Column(nullable = false)
private Integer lateThresholdMinutes;

@Column(nullable = false)
private Integer absenceThresholdMinutes;

public static StudySettings create(Study study) {
StudySettings studySettings = new StudySettings();
studySettings.study = study;
studySettings.lateThresholdMinutes = DEFAULT_LATE_THRESHOLD_MINUTES;
studySettings.absenceThresholdMinutes = DEFAULT_ABSENCE_THRESHOLD_MINUTES;
return studySettings;
}

public void update(Integer lateThresholdMinutes, Integer absenceThresholdMinutes) {
this.lateThresholdMinutes = lateThresholdMinutes;
this.absenceThresholdMinutes = absenceThresholdMinutes;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.mos.backend.studysettings.entity.exception;

import com.mos.backend.common.exception.ErrorCode;
import lombok.RequiredArgsConstructor;
import org.springframework.context.MessageSource;
import org.springframework.http.HttpStatus;

import java.util.Locale;

@RequiredArgsConstructor
public enum StudySettingsErrorCode implements ErrorCode {
NOT_FOUND(HttpStatus.NOT_FOUND, "study-settings.not-found")
;

private final HttpStatus httpStatus;
private final String messageKey;

@Override
public HttpStatus getStatus() {
return httpStatus;
}

@Override
public String getErrorName() {
return this.name();
}

@Override
public String getMessage(MessageSource messageSource) {
return messageSource.getMessage(messageKey, null, Locale.getDefault());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.mos.backend.studysettings.infrastructure;

import com.mos.backend.studysettings.entity.StudySettings;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.Optional;

public interface StudySettingJpaRepository extends JpaRepository<StudySettings, Long> {
Optional<StudySettings> findByStudyId(Long studyId);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.mos.backend.studysettings.infrastructure;

import com.mos.backend.studysettings.entity.StudySettings;

import java.util.Optional;

public interface StudySettingRepository {

void save(StudySettings studySettings);

Optional<StudySettings> findByStudyId(Long studyId);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.mos.backend.studysettings.infrastructure;

import com.mos.backend.studysettings.entity.StudySettings;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository;

import java.util.Optional;

@RequiredArgsConstructor
@Repository
public class StudySettingRepositoryImpl implements StudySettingRepository{
private final StudySettingJpaRepository studySettingJpaRepository;

@Override
public void save(StudySettings studySettings) {
studySettingJpaRepository.save(studySettings);
}

@Override
public Optional<StudySettings> findByStudyId(Long studyId) {
return studySettingJpaRepository.findByStudyId(studyId);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package com.mos.backend.studysettings.presentation;

import com.mos.backend.studysettings.application.StudySettingService;
import com.mos.backend.studysettings.application.res.StudySettingRes;
import com.mos.backend.studysettings.presentation.requestdto.StudySettingUpdateRequestDto;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;

@RestController
@RequiredArgsConstructor
@RequestMapping
public class StudySettingController {

private final StudySettingService studySettingService;

/**
* 스터디 아이디로 해당 스터디 설정 조회
* @param studyId
* @return
*/
@GetMapping("/studies/{studyId}/study-settings")
@ResponseStatus(HttpStatus.OK)
public StudySettingRes read(
@PathVariable Long studyId
) {
return studySettingService.read(studyId);
}

/**
* 스터디 아이디로 조회해서 스터디 설정 수정
* 지각 기준 시간, 결석 기준 시간 수정
* @param studyId
* @param requestDto
* @return
*/
@PatchMapping("/studies/{studyId}/study-settings")
@ResponseStatus(HttpStatus.OK)
public StudySettingRes update(
@PathVariable Long studyId,
@Valid @RequestBody StudySettingUpdateRequestDto requestDto
) {
return studySettingService.update(studyId, requestDto.getLateThresholdMinutes(), requestDto.getAbsenceThresholdMinutes());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.mos.backend.studysettings.presentation.requestdto;

import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Positive;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@AllArgsConstructor
@NoArgsConstructor
public class StudySettingUpdateRequestDto {
@NotNull(message = "lateThresholdMinutes는 필수입니다.")
@Positive(message = "lateThresholdMiniutes는 0보다 커야합니다.")
private Integer lateThresholdMinutes;
@NotNull(message = "absenceThresholdMinutes는 필수입니다.")
@Positive(message = "absenceThresholdMinutes는 0보다 커야합니다.")
private Integer absenceThresholdMinutes;
}
5 changes: 4 additions & 1 deletion src/main/resources/messages/messages-error.properties
Original file line number Diff line number Diff line change
Expand Up @@ -131,4 +131,7 @@ user-study-setting.not-found=스터디에 등록된 유저를 찾을 수 없습

# banner
banner.not-found = 배너를 찾을 수 없습니다.
banner.sort-order.not-proper = 올바르지 않은 배너 순서입니다. 순서는 전체 배너의 수와 같거나 작아야 하며, 1보다 같거나 커야 합니다.
banner.sort-order.not-proper = 올바르지 않은 배너 순서입니다. 순서는 전체 배너의 수와 같거나 작아야 하며, 1보다 같거나 커야 합니다.

#study-settings
study-settings.not-found=스터디 설정을 찾을 수 없습니다.