Skip to content

Commit

Permalink
Merge pull request #377 from KEEPER31337/feature/#376-세미나-출석-처리-수정
Browse files Browse the repository at this point in the history
Feature/세미나 수정사항
  • Loading branch information
shkisme authored Oct 6, 2023
2 parents 73bb672 + f780c87 commit 060bda0
Show file tree
Hide file tree
Showing 10 changed files with 88 additions and 191 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@
import com.keeper.homepage.domain.merit.entity.MeritLog;
import com.keeper.homepage.domain.merit.entity.MeritType;
import com.keeper.homepage.global.error.BusinessException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
Expand All @@ -28,9 +26,6 @@ public class MeritLogService {
private final MeritTypeRepository meritTypeRepository;
private final MemberFindService memberFindService;

private static final long SEMINAR_ABSENCE_MERIT_TYPE_ID = 2;
private static final long SEMINAR_DUAL_LATENESS_MERIT_TYPE_ID = 3;

@Transactional
public Long recordMerit(long memberId, long meritTypeId) {
Member member = memberFindService.findById(memberId);
Expand All @@ -46,30 +41,6 @@ public Long recordMerit(long memberId, long meritTypeId) {
.getId();
}

@Transactional
public void giveSeminarAbsenceDemerit(Member member) {
MeritType meritType = meritTypeRepository.findById(SEMINAR_ABSENCE_MERIT_TYPE_ID).orElseThrow();

meritLogRepository.save(MeritLog.builder()
.memberId(member.getId())
.memberRealName(member.getRealName())
.memberGeneration(member.getGeneration())
.meritType(meritType)
.build());
}

@Transactional
public void giveDualSeminarLatenessDemerit(Member member) {
MeritType meritType = meritTypeRepository.findById(SEMINAR_DUAL_LATENESS_MERIT_TYPE_ID).orElseThrow();

meritLogRepository.save(MeritLog.builder()
.memberId(member.getId())
.memberRealName(member.getRealName())
.memberGeneration(member.getGeneration())
.meritType(meritType)
.build());
}

public Page<MeritLog> findAllByMeritType(Pageable pageable, String meritType) {
return switch (meritType) {
case "MERIT" -> meritLogRepository.findMeritLogs(pageable);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,12 @@ public ResponseEntity<Page<SeminarAttendanceManageResponse>> getAttendances(
return ResponseEntity.ok(responses);
}

@PatchMapping("/attendances/{attendanceId}") // TODO: 관리자 권한으로 접근 가능하게 설정
@Secured({"ROLE_회장", "ROLE_부회장", "ROLE_서기"})
@PatchMapping("/attendances/{attendanceId}")
public ResponseEntity<Void> changeAttendanceStatus(
@PathVariable long attendanceId,
@RequestBody @Valid SeminarAttendanceStatusRequest request) {
seminarAttendanceService.changeStatus(attendanceId, request);
seminarAttendanceService.changeStatus(attendanceId, request.statusType(), request.excuse());
return ResponseEntity.noContent().build();
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
package com.keeper.homepage.domain.seminar.application;

import static com.keeper.homepage.domain.seminar.entity.SeminarAttendanceStatus.SeminarAttendanceStatusType.ABSENCE;
import static com.keeper.homepage.domain.seminar.entity.SeminarAttendanceStatus.SeminarAttendanceStatusType.ATTENDANCE;
import static com.keeper.homepage.domain.seminar.entity.SeminarAttendanceStatus.SeminarAttendanceStatusType.BEFORE_ATTENDANCE;
import static com.keeper.homepage.domain.seminar.entity.SeminarAttendanceStatus.SeminarAttendanceStatusType.LATENESS;
import static com.keeper.homepage.domain.seminar.entity.SeminarAttendanceStatus.getSeminarAttendanceStatusBy;
import static com.keeper.homepage.domain.seminar.entity.SeminarAttendanceStatus.SeminarAttendanceStatusType.PERSONAL;
import static com.keeper.homepage.global.error.ErrorCode.SEMINAR_ATTENDANCE_ATTEMPT_NOT_AVAILABLE;
import static com.keeper.homepage.global.error.ErrorCode.SEMINAR_ATTENDANCE_CODE_NOT_AVAILABLE;
import static com.keeper.homepage.global.error.ErrorCode.SEMINAR_ATTENDANCE_DUPLICATE;
Expand All @@ -13,10 +11,8 @@

import com.keeper.homepage.domain.member.application.convenience.MemberFindService;
import com.keeper.homepage.domain.member.entity.Member;
import com.keeper.homepage.domain.merit.application.MeritLogService;
import com.keeper.homepage.domain.seminar.application.convenience.ValidSeminarFindService;
import com.keeper.homepage.domain.seminar.dao.SeminarAttendanceRepository;
import com.keeper.homepage.domain.seminar.dto.request.SeminarAttendanceStatusRequest;
import com.keeper.homepage.domain.seminar.dto.response.SeminarAttendanceManageResponse;
import com.keeper.homepage.domain.seminar.dto.response.SeminarAttendanceResponse;
import com.keeper.homepage.domain.seminar.entity.Seminar;
Expand All @@ -26,7 +22,6 @@
import com.keeper.homepage.global.util.redis.RedisUtil;
import com.keeper.homepage.global.util.semester.SemesterUtil;
import java.time.LocalDate;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
Expand All @@ -45,7 +40,6 @@ public class SeminarAttendanceService {
private final ValidSeminarFindService validSeminarFindService;
private final MemberFindService memberFindService;
private final SeminarAttendanceRepository attendanceRepository;
private final MeritLogService meritLogService;

private static final int MAX_ATTEMPT_COUNT = 5;
private static final int ONE_HOUR = 60 * 60;
Expand All @@ -63,7 +57,6 @@ public SeminarAttendanceResponse attendance(Long seminarId, Member member, Strin

SeminarAttendanceStatusType type = seminar.getStatus().getType();
seminarAttendance.changeStatus(type);
giveAttendanceDemerit(type, member);
return SeminarAttendanceResponse.of(seminarAttendance);
}

Expand All @@ -90,38 +83,20 @@ private void checkDuplicateAttendance(SeminarAttendance seminarAttendance) {
}
}

private void giveAttendanceDemerit(SeminarAttendanceStatusType type, Member member) {
if (type == ATTENDANCE) {
return;
}
if (type == LATENESS) {
if (member.isDualLateness()) {
meritLogService.giveDualSeminarLatenessDemerit(member);
}
return;
}
if (type == ABSENCE) {
meritLogService.giveSeminarAbsenceDemerit(member);
}
}

@Transactional
public void changeStatus(long attendanceId, SeminarAttendanceStatusRequest request) {
public void changeStatus(long attendanceId, SeminarAttendanceStatusType statusType, String excuse) {
SeminarAttendance seminarAttendance = attendanceRepository.findById(attendanceId)
.orElseThrow(() -> new BusinessException(attendanceId, "attendanceId", SEMINAR_ATTENDANCE_NOT_FOUND));

seminarAttendance.changeStatus(request.excuse(), request.statusType());
if (statusType == LATENESS || statusType == PERSONAL) {
seminarAttendance.changeStatus(statusType, excuse);
return;
}
seminarAttendance.changeStatus(statusType);
}

@Scheduled(cron = "0 0 0 * * ?", zone = "Asia/Seoul") // 매일 자정에 실행
public void changeAllBeforeAttendanceToAbsence() {
List<SeminarAttendance> beforeAttendances = attendanceRepository
.findAllBySeminarAttendanceStatus(getSeminarAttendanceStatusBy(BEFORE_ATTENDANCE));

beforeAttendances.forEach(seminarAttendance -> {
seminarAttendance.changeStatus((ABSENCE));
meritLogService.giveSeminarAbsenceDemerit(seminarAttendance.getMember());
});
attendanceRepository.updateAllBeforeAttendanceToAbsence();
}

public Page<SeminarAttendanceManageResponse> getAttendances(Pageable pageable) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
package com.keeper.homepage.domain.seminar.dao;

import com.keeper.homepage.domain.seminar.entity.SeminarAttendance;
import com.keeper.homepage.domain.seminar.entity.SeminarAttendanceExcuse;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;

public interface SeminarAttendanceExcuseRepository extends JpaRepository<SeminarAttendanceExcuse, Long> {

Optional<SeminarAttendanceExcuse> findAllBySeminarAttendance(SeminarAttendance seminarAttendance);

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
import com.keeper.homepage.domain.member.entity.Member;
import com.keeper.homepage.domain.seminar.entity.Seminar;
import com.keeper.homepage.domain.seminar.entity.SeminarAttendance;
import com.keeper.homepage.domain.seminar.entity.SeminarAttendanceStatus;
import java.time.LocalDate;
import java.util.List;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

Expand All @@ -17,7 +17,11 @@ public interface SeminarAttendanceRepository extends JpaRepository<SeminarAttend

Optional<SeminarAttendance> findBySeminarAndMember(Seminar seminar, Member member);

List<SeminarAttendance> findAllBySeminarAttendanceStatus(SeminarAttendanceStatus status);
@Modifying
@Query("UPDATE SeminarAttendance s "
+ "SET s.seminarAttendanceStatus.id = 3 " // 결석
+ "WHERE s.seminarAttendanceStatus.id = 5") // 출석 전
void updateAllBeforeAttendanceToAbsence();

@Query("SELECT s FROM SeminarAttendance s "
+ "WHERE s.member.id = :memberId "
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package com.keeper.homepage.domain.seminar.dto.response;

import static com.keeper.homepage.domain.seminar.entity.SeminarAttendanceStatus.SeminarAttendanceStatusType.ABSENCE;
import static com.keeper.homepage.domain.seminar.entity.SeminarAttendanceStatus.SeminarAttendanceStatusType.ATTENDANCE;
import static com.keeper.homepage.domain.seminar.entity.SeminarAttendanceStatus.SeminarAttendanceStatusType.LATENESS;
import static com.keeper.homepage.domain.seminar.entity.SeminarAttendanceStatus.SeminarAttendanceStatusType.PERSONAL;
import static lombok.AccessLevel.PACKAGE;
import static lombok.AccessLevel.PRIVATE;

Expand All @@ -21,13 +25,29 @@ public class SeminarAttendanceManageResponse {
private String memberName;
private String generation;
private List<SeminarAttendanceDetailResponse> attendances;
private long totalAttendance;
private long totalLateness;
private long totalAbsence;
private long totalPersonal;

public static SeminarAttendanceManageResponse of(Member member, List<SeminarAttendance> seminarAttendances) {
return SeminarAttendanceManageResponse.builder()
.memberId(member.getId())
.memberName(member.getRealName())
.generation(member.getGeneration())
.attendances(seminarAttendances.stream().map(SeminarAttendanceDetailResponse::from).toList())
.totalAttendance(seminarAttendances.stream()
.filter(seminarAttendance -> seminarAttendance.isStatus(ATTENDANCE))
.count())
.totalLateness(seminarAttendances.stream()
.filter(seminarAttendance -> seminarAttendance.isStatus(LATENESS))
.count())
.totalAbsence(seminarAttendances.stream()
.filter(seminarAttendance -> seminarAttendance.isStatus(ABSENCE))
.count())
.totalPersonal(seminarAttendances.stream()
.filter(seminarAttendance -> seminarAttendance.isStatus(PERSONAL))
.count())
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ public Optional<String> getExcuse() {
return Optional.ofNullable(this.getSeminarAttendanceExcuse().getAbsenceExcuse());
}

public void changeStatus(String excuse, SeminarAttendanceStatusType type) {
public void changeStatus(SeminarAttendanceStatusType type, String excuse) {
seminarAttendanceStatus = getSeminarAttendanceStatusBy(type);
if (seminarAttendanceExcuse == null) {
seminarAttendanceExcuse = SeminarAttendanceExcuse.builder()
Expand All @@ -92,6 +92,11 @@ private SeminarAttendance(Seminar seminar, Member member,

public boolean isLateness() {
SeminarAttendanceStatusType type = getSeminarAttendanceStatus().getType();
return type.equals(LATENESS);
return type == LATENESS;
}

public boolean isStatus(SeminarAttendanceStatusType statusType) {
SeminarAttendanceStatusType type = getSeminarAttendanceStatus().getType();
return type == statusType;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ public void should_success_when_changeSeminarAttendanceStatus() throws Exception
.description("출석 상태를 변경하고자 하는 세미나 출석 ID")
),
requestFields(
field("excuse", "세미나 사유"),
field("excuse", "세미나 사유").optional(),
field("statusType", "출석 타입"))
)).andReturn();
}
Expand Down Expand Up @@ -311,6 +311,10 @@ FieldDescriptor[] getAttendances() {
fieldWithPath("attendances[].attendDate").description("세미나 출석 날짜"),
fieldWithPath("attendances[].attendanceStatus").description("세미나 출석 상태"),
fieldWithPath("attendances[].excuse").description("세미나 결석/지각 사유").optional(),
fieldWithPath("totalAttendance").description("총 출석일"),
fieldWithPath("totalLateness").description("총 지각일"),
fieldWithPath("totalAbsence").description("총 결석일"),
fieldWithPath("totalPersonal").description("총 개인사정일"),
};
}
}
Expand Down
Loading

0 comments on commit 060bda0

Please sign in to comment.