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

Refactor attendance api #28

Merged
merged 13 commits into from
Aug 17, 2024
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
14 changes: 14 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Start with a base image containing Java runtime
FROM openjdk:17-jdk-alpine

# Set the working directory in the container
WORKDIR /app

# Copy the executable jar file to the working directory
COPY build/libs/platform-core-0.0.1-SNAPSHOT.jar app.jar

# Expose the port the application runs on
EXPOSE 8080

# Command to run the executable jar file
ENTRYPOINT ["java", "-jar", "app.jar"]
13 changes: 13 additions & 0 deletions build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/bin/bash

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

하하 sh 부럽다...

# 프로젝트 클린 및 빌드
./gradlew clean bootJar

# Docker 이미지 빌드
docker build -t ekgns33/gdsc-spring:latest .

# Docker 이미지 푸시
docker push ekgns33/gdsc-spring:latest

# 완료 메시지
echo "Docker image pushed to ekgns33/gdsc-spring:latest successfully."
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package gdsc.konkuk.platformcore.application.attendance;

import static gdsc.konkuk.platformcore.application.attendance.AttendanceServiceHelper.findAttendanceById;

import gdsc.konkuk.platformcore.application.attendance.exceptions.AttendanceAlreadyExistException;
import gdsc.konkuk.platformcore.application.attendance.exceptions.AttendanceErrorCode;
import gdsc.konkuk.platformcore.application.attendance.exceptions.AttendanceNotFoundException;
import gdsc.konkuk.platformcore.application.attendance.exceptions.QrInvalidException;
import gdsc.konkuk.platformcore.application.event.exceptions.EventErrorCode;
import gdsc.konkuk.platformcore.application.event.exceptions.EventNotFoundException;
import gdsc.konkuk.platformcore.application.member.exceptions.MemberErrorCode;
Expand All @@ -17,13 +17,12 @@
import gdsc.konkuk.platformcore.domain.event.repository.EventRepository;
import gdsc.konkuk.platformcore.domain.member.entity.Member;
import gdsc.konkuk.platformcore.domain.member.repository.MemberRepository;
import java.util.ArrayList;
import java.util.List;
import lombok.RequiredArgsConstructor;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
Expand All @@ -40,15 +39,8 @@ public Participant attend(String memberEmail, Long attendanceId, String qrUuid)
memberRepository
.findByEmail(memberEmail)
.orElseThrow(() -> UserNotFoundException.of(MemberErrorCode.USER_NOT_FOUND));
Attendance attendance =
attendanceRepository
.findById(attendanceId)
.orElseThrow(
() -> AttendanceNotFoundException.of(AttendanceErrorCode.ATTENDANCE_NOT_FOUND));
if (!attendance.isActiveQr(qrUuid)) {
throw QrInvalidException.of(AttendanceErrorCode.INVALID_QR_UUID);
}

Attendance attendance = findAttendanceById(attendanceRepository, attendanceId);
attendance.validateActiveQr(qrUuid);
return participantService.attend(member.getId(), attendanceId);
}

Expand All @@ -64,10 +56,7 @@ public Long registerAttendance(AttendanceRegisterRequest registerRequest) {
attendanceRepository.saveAndFlush(newAttendance);

List<Member> members = memberRepository.findAllByBatch(registerRequest.getBatch());
List<Participant> participants =
ParticipantMapper.mapMemberListToAbsentParticipantList(members, newAttendance.getId());
participantRepository.saveAll(participants);

registerParticipants(newAttendance, members);
return newAttendance.getId();
}

Expand All @@ -79,25 +68,14 @@ public void deleteAttendance(Long attendanceId) {

@Transactional
public String generateQr(Long attendanceId) {
Attendance attendance =
attendanceRepository
.findById(attendanceId)
.orElseThrow(
() -> AttendanceNotFoundException.of(AttendanceErrorCode.ATTENDANCE_NOT_FOUND));
Attendance attendance = findAttendanceById(attendanceRepository, attendanceId);
return attendance.generateQr();
}

@Transactional
public void expireQr(Long attendanceId, String qrUuid) {
Attendance attendance =
attendanceRepository
.findById(attendanceId)
.orElseThrow(
() -> AttendanceNotFoundException.of(AttendanceErrorCode.ATTENDANCE_NOT_FOUND));
if (!attendance.isActiveQr(qrUuid)) {
throw QrInvalidException.of(AttendanceErrorCode.INVALID_QR_UUID);
}

Attendance attendance = findAttendanceById(attendanceRepository, attendanceId);
attendance.validateActiveQr(qrUuid);
attendance.expireQr();
}

Expand All @@ -110,4 +88,16 @@ private void checkAttendanceAlreadyExist(Event event) {
AttendanceErrorCode.ATTENDANCE_ALREADY_EXIST);
});
}
private void registerParticipants(Attendance attendance, List<Member> members){
List<Participant> participants = new ArrayList<>();
for(Member member : members) {
Participant participant = Participant.builder()
.memberId(member.getId())
.isAttended(false)
.build();
participant.register(attendance);
participants.add(participant);
}
participantRepository.saveAll(participants);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package gdsc.konkuk.platformcore.application.attendance;

import gdsc.konkuk.platformcore.application.attendance.exceptions.AttendanceErrorCode;
import gdsc.konkuk.platformcore.application.attendance.exceptions.AttendanceNotFoundException;
import gdsc.konkuk.platformcore.domain.attendance.entity.Attendance;
import gdsc.konkuk.platformcore.domain.attendance.repository.AttendanceRepository;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;

@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class AttendanceServiceHelper {

public static Attendance findAttendanceById(
AttendanceRepository attendanceRepository, Long attendanceId) {
return attendanceRepository
.findById(attendanceId)
.orElseThrow(
() -> AttendanceNotFoundException.of(AttendanceErrorCode.ATTENDANCE_NOT_FOUND));
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
package gdsc.konkuk.platformcore.application.attendance;
package gdsc.konkuk.platformcore.application.attendance.dtos;

import java.time.LocalDateTime;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;


@Getter
@Setter
@Builder
@AllArgsConstructor
public class AttendanceInfo {
@Builder
public class MemberAttendanceInfo {
private Long attendanceId;
private Long eventId;
private Long memberId;
private Long participantId;
private boolean isAttended;
private LocalDateTime attendanceDate;
private boolean attendance;
private Long participantId;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package gdsc.konkuk.platformcore.application.attendance.dtos;

import gdsc.konkuk.platformcore.domain.member.entity.MemberRole;
import java.time.LocalDateTime;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
@Builder
@AllArgsConstructor
public class MemberAttendanceQueryDto {
private Long eventId;
private Long memberId;
private String memberName;
private MemberRole memberRole;
private String memberDepartment;
private Long participantId;
private Long attendanceId;
private LocalDateTime attendanceDate;
private boolean isAttended;
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
package gdsc.konkuk.platformcore.application.member;

import gdsc.konkuk.platformcore.application.attendance.dtos.MemberAttendanceQueryDto;
import gdsc.konkuk.platformcore.application.member.dtos.MemberAttendances;
import java.time.LocalDate;
import java.time.LocalTime;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import gdsc.konkuk.platformcore.application.attendance.AttendanceInfo;
import gdsc.konkuk.platformcore.application.attendance.exceptions.AttendanceErrorCode;
import gdsc.konkuk.platformcore.application.attendance.exceptions.ParticipantNotFoundException;
import gdsc.konkuk.platformcore.controller.member.AttendanceUpdateInfo;
Expand Down Expand Up @@ -60,37 +61,42 @@ public void withdraw(Long currentId) {
member.withdraw();
}

public List<MemberAttendanceInfo> getMemberAttendanceInfo(String batch, LocalDate month) {
List<Member> batchMemberList = memberRepository.findAllByBatch(batch);
List<AttendanceInfo> attendanceInfoList =
attendanceRepository.findAllAttendanceInfoByStartAtBetween(
public List<MemberAttendances> getMemberAttendanceWithBatchAndPeriod(String batch, LocalDate month) {
List<MemberAttendanceQueryDto> attendanceInfoList =
attendanceRepository.findAllAttendanceInfoByBatchAndPeriod(
batch,
month.withDayOfMonth(1).atStartOfDay(),
month.withDayOfMonth(month.lengthOfMonth()).atTime(LocalTime.MAX));
return MemberAttendanceInfo.from(batchMemberList, attendanceInfoList);
return MemberAttendances.from(attendanceInfoList);
}

@Transactional
public void updateAttendances(
String batch, LocalDate month, List<AttendanceUpdateInfo> attendanceUpdateInfoList) {
Map<Long, Participant> participantMap =
participantRepository
.findAllByBatchAndStartAtBetween(
batch,
month.withDayOfMonth(1).atStartOfDay(),
month.withDayOfMonth(month.lengthOfMonth()).atTime(LocalTime.MAX))
.stream()
.collect(toMap(Participant::getId, identity()));

for (AttendanceUpdateInfo attendanceUpdateInfo : attendanceUpdateInfoList) {
if (!participantMap.containsKey(attendanceUpdateInfo.getParticipantId())) {
Map<Long, Participant> participantMap = fetchParticipants(batch, month);
updateAttendanceStatuses(participantMap, attendanceUpdateInfoList);
}

private void updateAttendanceStatuses(Map<Long, Participant> participants, List<AttendanceUpdateInfo> updateInfos) {
for (AttendanceUpdateInfo attendanceUpdateInfo : updateInfos) {
if (!participants.containsKey(attendanceUpdateInfo.getParticipantId())) {
throw ParticipantNotFoundException.of(AttendanceErrorCode.PARTICIPANT_NOT_FOUND);
}

Participant participant = participantMap.get(attendanceUpdateInfo.getParticipantId());
participant.updateAttendance(attendanceUpdateInfo.isAttendance());
Participant participant = participants.get(attendanceUpdateInfo.getParticipantId());
participant.updateAttendanceStatus(attendanceUpdateInfo.isAttended());
}
}

private Map<Long, Participant> fetchParticipants(String batch, LocalDate month) {
return participantRepository
.findAllByBatchAndStartAtBetween(
batch,
month.withDayOfMonth(1).atStartOfDay(),
month.withDayOfMonth(month.lengthOfMonth()).atTime(LocalTime.MAX))
.stream()
.collect(toMap(Participant::getId, identity()));
}

private boolean checkMemberExistWithMemberId(String memberId) {
Optional<Member> member = memberRepository.findByMemberId(memberId);
return member.isPresent();
Expand Down
Loading