Skip to content

Commit

Permalink
[Feat] late attendance (#55)
Browse files Browse the repository at this point in the history
* feat(attendance): change attendance from boolean into enum

- available options : "ATTEND", "ABSENT", "LATE"

* test(attendance): change attendance from boolean into enum

* docs(attendance): mark TODO (too high complexity)

* refactor(attendance): add `isAbsent` to `AttendanceType`
  • Loading branch information
goldentrash authored Nov 29, 2024
1 parent c786d63 commit 137071f
Show file tree
Hide file tree
Showing 13 changed files with 63 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import gdsc.konkuk.platformcore.application.member.exceptions.MemberErrorCode;
import gdsc.konkuk.platformcore.application.member.exceptions.UserNotFoundException;
import gdsc.konkuk.platformcore.domain.attendance.entity.Attendance;
import gdsc.konkuk.platformcore.domain.attendance.entity.AttendanceType;
import gdsc.konkuk.platformcore.domain.attendance.entity.Participant;
import gdsc.konkuk.platformcore.domain.attendance.repository.AttendanceRepository;
import gdsc.konkuk.platformcore.domain.attendance.repository.ParticipantRepository;
Expand Down Expand Up @@ -56,7 +57,7 @@ public Attendance registerAttendance(String title, String batch) {

public AttendanceStatus getAttendanceStatus(Long attendanceId) {
List<Participant> totalParticipants = participantRepository.findAllByAttendanceId(attendanceId);
List<Participant> attendedParticipants = totalParticipants.stream().filter(Participant::isAttended).toList();
List<Participant> attendedParticipants = totalParticipants.stream().filter(Participant::isAttend).toList();
return AttendanceStatus.of(attendanceId, totalParticipants.size(), attendedParticipants.size());
}

Expand Down Expand Up @@ -84,7 +85,7 @@ private void registerParticipants(Attendance attendance, List<Member> members){
for(Member member : members) {
Participant participant = Participant.builder()
.memberId(member.getId())
.isAttended(false)
.attendanceType(AttendanceType.ABSENT)
.build();
participant.register(attendance);
participants.add(participant);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package gdsc.konkuk.platformcore.application.attendance.dtos;

import gdsc.konkuk.platformcore.domain.attendance.entity.AttendanceType;
import java.time.LocalDateTime;
import lombok.AllArgsConstructor;
import lombok.Builder;
Expand All @@ -11,9 +12,8 @@
@Builder
public class MemberAttendanceInfo {
private Long attendanceId;
private Long eventId;
private Long memberId;
private boolean isAttended;
private AttendanceType attendanceType;
private LocalDateTime attendanceDate;
private Long participantId;
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package gdsc.konkuk.platformcore.application.attendance.dtos;

import gdsc.konkuk.platformcore.domain.attendance.entity.AttendanceType;
import gdsc.konkuk.platformcore.domain.member.entity.MemberRole;
import java.time.LocalDateTime;
import lombok.AllArgsConstructor;
Expand All @@ -19,5 +20,5 @@ public class MemberAttendanceQueryDto {
private Long participantId;
private Long attendanceId;
private LocalDateTime attendanceDate;
private boolean isAttended;
private AttendanceType attendanceType;
}
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ private void updateAttendanceStatuses(Map<Long, Participant> participants, List<
throw ParticipantNotFoundException.of(AttendanceErrorCode.PARTICIPANT_NOT_FOUND);
}
Participant participant = participants.get(attendanceUpdateInfo.getParticipantId());
participant.updateAttendanceStatus(attendanceUpdateInfo.isAttended());
participant.updateAttendanceStatus(attendanceUpdateInfo.getAttendanceType());
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,9 @@ public static List<MemberAttendances> from(List<MemberAttendanceQueryDto> list)
}

private static void updateAttendanceCounts(MemberAttendances memberAttendances, MemberAttendanceQueryDto attendanceInfo) {
// TODO : 너무 높아진 복잡도, 리팩터링 필요
memberAttendances.totalAttendances++;
if (attendanceInfo.isAttended()) {
if (!attendanceInfo.getAttendanceType().isAbsent()) {
memberAttendances.actualAttendances++;
}
}
Expand All @@ -64,7 +65,7 @@ private static MemberAttendanceInfo createMemberAttendanceInfo(MemberAttendanceQ
.attendanceDate(attendanceInfo.getAttendanceDate())
.participantId(attendanceInfo.getParticipantId())
.attendanceId(attendanceInfo.getAttendanceId())
.isAttended(attendanceInfo.isAttended())
.attendanceType(attendanceInfo.getAttendanceType())
.build();
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package gdsc.konkuk.platformcore.controller.member.dtos;

import gdsc.konkuk.platformcore.domain.attendance.entity.AttendanceType;
import jakarta.validation.constraints.NotNull;
import lombok.Builder;
import lombok.Getter;
Expand All @@ -10,5 +11,5 @@
@Builder
public class AttendanceUpdateInfo {
@NotNull private Long participantId;
@NotNull private boolean isAttended;
@NotNull private AttendanceType attendanceType;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package gdsc.konkuk.platformcore.domain.attendance.entity;

public enum AttendanceType {
ATTEND("ATTEND"), ABSENT("ABSENT"), LATE("LATE"),;

private final String value;

AttendanceType(String value) {
this.value = value;
}

public boolean isAbsent() {
return this == ABSENT;
}

@Override
public String toString() {
return value;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
Expand All @@ -28,32 +30,33 @@ public class Participant {
@Column(name = "member_id")
private Long memberId;

@Column(name = "attendance")
private boolean isAttended;
@Column(name = "attendance_type")
@Enumerated(EnumType.STRING)
private AttendanceType attendanceType;

@Builder
public Participant(Long memberId, Attendance attendance, boolean isAttended) {
public Participant(Long memberId, Attendance attendance, AttendanceType attendanceType) {
this.memberId = memberId;
this.attendance = attendance;
this.isAttended = isAttended;
this.attendanceType = attendanceType;
}

public void register(Attendance attendance) {
if(isAttended || attendance == null) {
if(this.attendance != null || attendance == null) {
throw new IllegalStateException();
}
this.attendance = attendance;
}

public void attend() {
this.isAttended = true;
public boolean isAttend() {
return !this.attendanceType.isAbsent();
}

public void cancel() {
this.isAttended = false;
public void attend() {
this.attendanceType = AttendanceType.ATTEND;
}

public void updateAttendanceStatus(boolean isAttended) {
this.isAttended = isAttended;
public void updateAttendanceStatus(AttendanceType isAttended) {
this.attendanceType = isAttended;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public interface AttendanceRepository extends JpaRepository<Attendance, Long> {
List<Attendance> findAllByPeriod(LocalDateTime st, LocalDateTime en);

@Query("SELECT new gdsc.konkuk.platformcore.application.attendance.dtos.MemberAttendanceQueryDto(" +
"m.id, m.name, m.role, m.department, p.id, a.id, a.attendanceTime, p.isAttended) " +
"m.id, m.name, m.role, m.department, p.id, a.id, a.attendanceTime, p.attendanceType) " +
"FROM Attendance a " +
"LEFT JOIN Participant p ON p.attendance.id = a.id " +
"LEFT JOIN Member m ON m.id = p.memberId " +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import gdsc.konkuk.platformcore.controller.attendance.dtos.AttendanceRegisterRequest;
import gdsc.konkuk.platformcore.domain.attendance.entity.Attendance;

import gdsc.konkuk.platformcore.domain.attendance.entity.AttendanceType;
import gdsc.konkuk.platformcore.domain.member.entity.Member;
import gdsc.konkuk.platformcore.domain.member.entity.MemberRole;
import gdsc.konkuk.platformcore.fixture.attendance.AttendanceFixture;
Expand Down Expand Up @@ -139,7 +140,7 @@ void should_attend_when_pass_event_id_and_member_id() throws Exception {
.id(1L).activeQrUuid("uuid").build().getFixture();
given(attendanceService.attend(memberToAttend.getId(), attendanceToAttend.getId(), attendanceToAttend.getActiveQrUuid()))
.willReturn(ParticipantFixture.builder()
.isAttended(true)
.attendanceType(AttendanceType.ATTEND)
.memberId(memberToAttend.getId())
.attendance(attendanceToAttend)
.build().getFixture());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import gdsc.konkuk.platformcore.controller.member.dtos.MemberRegisterRequest;
import gdsc.konkuk.platformcore.controller.member.dtos.MemberUpdateInfo;
import gdsc.konkuk.platformcore.controller.member.dtos.MemberUpdateRequest;
import gdsc.konkuk.platformcore.domain.attendance.entity.AttendanceType;
import gdsc.konkuk.platformcore.domain.member.entity.Member;
import gdsc.konkuk.platformcore.domain.member.entity.MemberRole;
import gdsc.konkuk.platformcore.fixture.member.MemberAttendancesFixture;
Expand Down Expand Up @@ -324,18 +325,15 @@ void should_success_when_get_attendances_by_batch() throws Exception {
fieldWithPath("data[].department").description("멤버 학과"),
fieldWithPath("data[].totalAttendances").description("전체 등록 횟수"),
fieldWithPath("data[].actualAttendances").description("실제 출석 횟수"),
fieldWithPath("data[].attendanceInfoList").description("멤버 출석 정보 리스트"),
fieldWithPath("data[].attendanceInfoList[].attendanceId")
.description("출석 아이디"),
fieldWithPath("data[].attendanceInfoList[].memberId")
.description("멤버 아이디"),
fieldWithPath("data[].attendanceInfoList[].eventId")
.description("이벤트 아이디"),
fieldWithPath("data[].attendanceInfoList[].participantId")
.description("참가자 아이디"),
fieldWithPath("data[].attendanceInfoList[].attendanceDate")
.description("출석 날짜"),
fieldWithPath("data[].attendanceInfoList[].attended")
fieldWithPath("data[].attendanceInfoList[].attendanceType")
.description("출석 여부"))
.build())));
}
Expand All @@ -347,9 +345,9 @@ void should_success_when_update_attendances_by_batch() throws Exception {
Member member = MemberFixture.builder().role(MemberRole.CORE).build().getFixture();
String jwt = jwtTokenProvider.createToken(member);
List<AttendanceUpdateInfo> attendanceUpdateInfoList = List.of(
AttendanceUpdateInfo.builder().participantId(1L).isAttended(true).build(),
AttendanceUpdateInfo.builder().participantId(2L).isAttended(false).build(),
AttendanceUpdateInfo.builder().participantId(3L).isAttended(true).build());
AttendanceUpdateInfo.builder().participantId(1L).attendanceType(AttendanceType.ATTEND).build(),
AttendanceUpdateInfo.builder().participantId(2L).attendanceType(AttendanceType.ABSENT).build(),
AttendanceUpdateInfo.builder().participantId(3L).attendanceType(AttendanceType.LATE).build());
AttendanceUpdateRequest attendanceUpdateRequest = new AttendanceUpdateRequest(attendanceUpdateInfoList);
willDoNothing().given(memberService).updateAttendances(
"24-25",
Expand Down Expand Up @@ -389,7 +387,7 @@ void should_success_when_update_attendances_by_batch() throws Exception {
fieldWithPath("attendanceUpdateInfoList[]").description("출석 정보 수정 리스트"),
fieldWithPath("attendanceUpdateInfoList[].participantId")
.description("참가자 아이디"),
fieldWithPath("attendanceUpdateInfoList[].attended")
fieldWithPath("attendanceUpdateInfoList[].attendanceType")
.description("출석 여부"))
.responseFields(
fieldWithPath("success").description(true),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import static gdsc.konkuk.platformcore.global.utils.GetDefault.getDefault;

import gdsc.konkuk.platformcore.domain.attendance.entity.Attendance;
import gdsc.konkuk.platformcore.domain.attendance.entity.AttendanceType;
import gdsc.konkuk.platformcore.domain.attendance.entity.Participant;
import lombok.Builder;
import lombok.Getter;
Expand All @@ -12,11 +13,11 @@ public class ParticipantFixture {
private final Participant fixture;

@Builder
public ParticipantFixture(Long memberId, Attendance attendance, Boolean isAttended) {
public ParticipantFixture(Long memberId, Attendance attendance, AttendanceType attendanceType) {
this.fixture = Participant.builder()
.memberId(getDefault(memberId, 0L))
.attendance(getDefault(attendance, AttendanceFixture.builder().build().getFixture()))
.isAttended(getDefault(isAttended, false))
.attendanceType(getDefault(attendanceType, AttendanceType.ABSENT))
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import gdsc.konkuk.platformcore.application.attendance.dtos.MemberAttendanceInfo;
import gdsc.konkuk.platformcore.application.member.dtos.MemberAttendances;
import gdsc.konkuk.platformcore.domain.attendance.entity.AttendanceType;
import gdsc.konkuk.platformcore.domain.member.entity.MemberRole;
import java.time.LocalDateTime;
import java.util.List;
Expand All @@ -27,26 +28,23 @@ public MemberAttendancesFixture(Long memberId, String memberName, MemberRole mem
MemberAttendanceInfo.builder()
.attendanceId(0L)
.memberId(0L)
.eventId(0L)
.participantId(0L)
.attendanceType(AttendanceType.ABSENT)
.attendanceDate(LocalDateTime.now())
.isAttended(true)
.build(),
MemberAttendanceInfo.builder()
.attendanceId(1L)
.memberId(0L)
.eventId(1L)
.participantId(1L)
.attendanceType(AttendanceType.LATE)
.attendanceDate(LocalDateTime.now().plusDays(3))
.isAttended(false)
.build(),
MemberAttendanceInfo.builder()
.attendanceId(2L)
.memberId(0L)
.eventId(2L)
.participantId(2L)
.attendanceType(AttendanceType.ATTEND)
.attendanceDate(LocalDateTime.now().plusDays(5))
.isAttended(true)
.build())))
.build();
}
Expand Down

0 comments on commit 137071f

Please sign in to comment.