Skip to content

Commit 81e52ed

Browse files
authored
[EC-65] BE/feat: 퇴실 api 구현 (#54)
* [EC-65] feat: 출석 기록 조회 메서드 추가 - findByStudentIdAndCheckInTimestampBetween 메서드 추가 * [EC-65] feat: 퇴실 처리 로직 구현 - checkOut 메서드 추가 - 당일 출석 기록 조회 및 퇴실 시간 기록 - 지각, 조퇴, 정상 출석 상태 처리 로직 구현 - 중복 퇴실 처리 방지 로직 추가 * [EC-65] feat: 퇴실 API 엔드포인트 구현
1 parent 113a23b commit 81e52ed

File tree

3 files changed

+59
-0
lines changed

3 files changed

+59
-0
lines changed

api/src/main/java/org/example/educheck/domain/attendance/controller/AttendanceController.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,4 +80,17 @@ public ResponseEntity<ApiResponse<Object>> updateStudentAttendance(
8080
null
8181
));
8282
}
83+
84+
@PatchMapping("/checkout")
85+
public ResponseEntity<ApiResponse<AttendanceStatusResponseDto>> checkOut(@AuthenticationPrincipal UserDetails user) {
86+
Status attendanceStatus = attendanceService.checkOut(user);
87+
88+
AttendanceStatusResponseDto responseDto = new AttendanceStatusResponseDto(attendanceStatus);
89+
return ResponseEntity.status(HttpStatus.OK)
90+
.body(ApiResponse.ok(
91+
"퇴실 성공",
92+
"OK",
93+
responseDto
94+
));
95+
}
8396
}

api/src/main/java/org/example/educheck/domain/attendance/repository/AttendanceRepository.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44
import org.springframework.data.jpa.repository.JpaRepository;
55
import org.springframework.data.jpa.repository.Query;
66

7+
import java.time.LocalDateTime;
78
import java.util.List;
9+
import java.util.Optional;
810

911

1012
public interface AttendanceRepository extends JpaRepository<Attendance, Long> {
@@ -13,4 +15,10 @@ public interface AttendanceRepository extends JpaRepository<Attendance, Long> {
1315

1416
@Query("SELECT a FROM Attendance a WHERE a.student = :studentId AND a.lecture = :lectureId")
1517
Attendance findByLectureIdStudentId(Long studentId, Long lectureId);
18+
19+
Optional<Attendance> findByStudentIdAndCheckInTimestampBetween(
20+
Long studentId,
21+
LocalDateTime startOfDay,
22+
LocalDateTime endOfDay
23+
);
1624
}

api/src/main/java/org/example/educheck/domain/attendance/service/AttendanceService.java

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,4 +203,42 @@ public void checkStaffHasCourse(UserDetails user, Long courseId) {
203203
staffCourseRepository.findByStaffIdAndCourseId(staff.getId(), courseId)
204204
.orElseThrow(() -> new ResourceNotFoundException("관리자가 해당하는 강의를 가지고 있지 않습니다."));
205205
}
206+
207+
@Transactional
208+
public Status checkOut(UserDetails user) {
209+
String email = user.getUsername();
210+
Member member = memberRepository.findByEmail(email)
211+
.orElseThrow(() -> new ResourceNotFoundException("사용자 정보를 찾을 수 없습니다."));
212+
213+
Student student = studentRepository.findByMemberId(member.getId())
214+
.orElseThrow(() -> new ResourceNotFoundException("학생 정보를 찾을 수 없습니다."));
215+
216+
LocalDate today = LocalDate.now();
217+
LocalDateTime startOfDay = today.atStartOfDay();
218+
LocalDateTime endOfDay = today.plusDays(1).atStartOfDay().minusNanos(1);
219+
220+
Attendance attendance = attendanceRepository.findByStudentIdAndCheckInTimestampBetween(
221+
student.getId(), startOfDay, endOfDay)
222+
.orElseThrow(() -> new IllegalArgumentException("금일 출석 기록이 없습니다."));
223+
224+
if (attendance.getCheckOutTimestamp() != null) {
225+
throw new IllegalStateException("이미 퇴실 처리되었습니다.");
226+
}
227+
228+
LocalDateTime now = LocalDateTime.now();
229+
attendance.setCheckOutTimestamp(now);
230+
231+
LocalTime earlyLeaveTime = LocalTime.of(17, 0);
232+
if (attendance.getStatus() == Status.LATE) {
233+
attendance.setStatus(Status.LATE);
234+
} else if (now.toLocalTime().isBefore(earlyLeaveTime)) {
235+
attendance.setStatus(Status.EARLY_LEAVE);
236+
} else {
237+
attendance.setStatus(Status.ATTENDANCE);
238+
}
239+
240+
attendanceRepository.save(attendance);
241+
return attendance.getStatus();
242+
}
243+
206244
}

0 commit comments

Comments
 (0)