반응형

직원이 연차를 신청할수있게되면서 직원의 근무시간을 조회하는 기능에 추가적인 요구사항이 생겼다.
근무시간을 조회하면서 연차를 사용한날도 같이 조회해주어야한다.
기존에 직원의 정보를 조회해오던 코드의 구조
Controller
@GetMapping("/worktime")
public CommuteTotalResponse checkTime(
@Validated
CommuteGetDto request) {
return service.checkTime(request);
}
Service
@Transactional(readOnly = true)
public CommuteTotalResponse checkTime(CommuteGetDto request) {
//직원아이디로 직원을 조회
Employee employee = memberRepository.findById(request.getEmployeeId())
.orElseThrow(()-> new IllegalArgumentException("직원 정보가없습니다."));
//직원이 가진출퇴근 정보와 검색정보로 응답객체인 CommuteTimeResponseList를 생성
CommuteTimeResponseList commuteTimeResponseList = new CommuteTimeResponseList(request, employee);
return new CommuteTotalResponse(commuteTimeResponseList.getCommuteTimeResponseList());
}
CommuteTimeResponseList
@Getter
public class CommuteTimeResponseList {
List<CommuteTimeResponse> commuteTimeResponseList;
public CommuteTimeResponseList(CommuteGetDto request, Employee employee) {
List<CommuteTimeResponse> collect = filterAndGroupCommuteHistories(request, employee);
//연차 정보를 더해준다. //추가된 메서드
addAnnualLeaveToCommuteTimeResponse(request, employee, collect);
//정렬
this.commuteTimeResponseList = sortCommuteTimeResponseListbyDate(collect);
}
private static List<CommuteTimeResponse> sortCommuteTimeResponseListbyDate(List<CommuteTimeResponse> collect) {
List<CommuteTimeResponse> list = collect.stream()
.sorted(Comparator.comparing(response -> LocalDate.parse(response.getDate())))
.toList();
return list;
}
private static void addAnnualLeaveToCommuteTimeResponse(CommuteGetDto request, Employee employee, List<CommuteTimeResponse> collect) {
employee.getAnnualLeaveRegisters().stream()
.filter(leave -> {
YearMonth startYearMonth = YearMonth.from(leave.getStartDate());
YearMonth endYearMonth = YearMonth.from(leave.getEndDate());
return !startYearMonth.isAfter(request.getSearchDate()) && !endYearMonth.isBefore(request.getSearchDate());
})
.forEach(leave -> {
LocalDate startDate = leave.getStartDate();
LocalDate endDate = leave.getEndDate();
// 검색 시작일과 휴가 시작일 중 늦은 날짜를 선택
LocalDate searchStart = request.getSearchDate().atDay(1);
LocalDate effectiveStartDate = startDate.isBefore(searchStart) ? searchStart : startDate;
// 검색 종료일과 휴가 종료일 중 이른 날짜를 선택
LocalDate searchEnd = request.getSearchDate().atEndOfMonth();
LocalDate effectiveEndDate = endDate.isAfter(searchEnd) ? searchEnd : endDate;
long daysBetween = ChronoUnit.DAYS.between(effectiveStartDate, effectiveEndDate);
for (long i = 0; i <= daysBetween; i++) {
LocalDate currentDate = leave.getStartDate().plusDays(i);
collect.add(new CommuteTimeResponse(currentDate));
}
});
}
private List<CommuteTimeResponse> filterAndGroupCommuteHistories(CommuteGetDto request, Employee employee) {
return employee.getCommuteHistories().stream()
//연월 필터링
.filter(result ->
result.isSameYearMonth(request.getSearchDate())
&& !result.getIsWorking()
)
//그루핑
.collect(Collectors.groupingBy(
result -> dateTimeToFormatString(result.getStartTime(), "yyyy-MM-dd"),
Collectors.summingInt(result -> diffMinute(result.getStartTime(), result.getEndTime()))
))
.entrySet().stream()
.map(result -> {
CommuteTimeResponse response = new CommuteTimeResponse();
response.setDate(result.getKey());
response.setWorkingMinutes(result.getValue());
return response;
}).collect(Collectors.toList());
}
private String dateTimeToFormatString(LocalDateTime time, String format) {
return time.format(DateTimeFormatter.ofPattern(format));
}
private Integer diffMinute(LocalDateTime start, LocalDateTime end) {
return (int) Duration.between(start, end).toMinutes();
}
}
코드를 이해하기쉽게 쓰려고 풀어서 쓰다보니까 상당히 길어졌는데.
기존에 날짜로 그룹화시켜서 리스트로매핑했던데이터에 휴가데이터를 추가해주는 메서드가 추가되었다.
휴가인 날은 usingDayOff 가 true인것이 고정이기때문에
생성시에 고정으로 근무시간은 0 DayOff는 true가 들어간 데이터가 리스트에 추가된다.
그후에 날짜값으로 데이터를 정렬해주게된다.
지금은 우선 기능을구현하려고 한 클래스에 넣어놨지만 코드가 너무길어져서 따로 클래스를 더 만들어야 할것같다.
나눈다면 아마 public에서 사용하고있는 3개의 메서드들을 따로 클래스로 만들어서 관리하게될것같다.
리팩토링
package Company.demo.commute.dto.firstCollection.commutetimeresponse;
import Company.demo.commute.dao.AnnualLeaveRegister;
import Company.demo.commute.dao.CommuteHistory;
import Company.demo.commute.dao.Employee;
import Company.demo.commute.dto.firstCollection.annualleavelist.AnnualLeaveToCommuteResponse;
import Company.demo.commute.dto.firstCollection.annualleavelist.FilterAnnualLeaveRegistered;
import Company.demo.commute.dto.firstCollection.commutehistorylist.FilterCommuteHistories;
import Company.demo.commute.dto.firstCollection.commutehistorylist.GroupCommuteHistories;
import Company.demo.commute.dto.request.CommuteGetDto;
import Company.demo.commute.dto.response.CommuteTimeResponse;
import java.time.LocalDate;
import java.time.YearMonth;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import lombok.Getter;
@Getter
public class CommuteTimeResponseList {
List<CommuteTimeResponse> commuteTimeResponseList;
public CommuteTimeResponseList(CommuteGetDto request, Employee employee) {
List<CommuteHistory> filtered = new FilterCommuteHistories(employee.getCommuteHistories())
.filterByDate(request.getSearchDate());
Map<String, Integer> grouped = new GroupCommuteHistories(filtered).groupByDate();
List<CommuteTimeResponse> commuteTimeResponsesByCommuteHistories = mapToCommuteTimeResponse(grouped);
//연차 정보를 더해준다.
List<CommuteTimeResponse> commuteTimeResponsesByAnnualLeave = AnnualLeaveToCommuteTimeResponse(request.getSearchDate(), employee);
commuteTimeResponsesByCommuteHistories.addAll(commuteTimeResponsesByAnnualLeave);
//정렬
this.commuteTimeResponseList = new SortCommuteTimeResponse(commuteTimeResponsesByCommuteHistories).sort();
}
private static List<CommuteTimeResponse> AnnualLeaveToCommuteTimeResponse(YearMonth searchYearMonth, Employee employee) {
List<AnnualLeaveRegister> filter = new FilterAnnualLeaveRegistered(employee.getAnnualLeaveRegisters()).filter(searchYearMonth);
return new AnnualLeaveToCommuteResponse(filter).leaveToResponse(searchYearMonth);
}
private List<CommuteTimeResponse> mapToCommuteTimeResponse(Map<String, Integer> groupedCommuteHistory) {
return groupedCommuteHistory.entrySet().stream()
.map(result -> {
CommuteTimeResponse response = new CommuteTimeResponse();
response.setDate(result.getKey());
response.setWorkingMinutes(result.getValue());
return response;
}).collect(Collectors.toList());
}
}
각 메소드들을 기능별로 분리하고 정렬 그루핑 매핑 각각 일급컬렉션으로 분리해서 만들어줬다.
반응형
'백엔드 > 자바' 카테고리의 다른 글
워밍업 클럽 2기 BE클린코드 4일차 과제 (리팩토링), SOLID에 대한 정리 (2) | 2024.10.03 |
---|---|
[인프런 워밍업 클럽_0기] BE과제 미니프로젝트 4단계 - 초과근무시간 계산 (0) | 2024.03.27 |
[인프런 워밍업 클럽_0기] BE과제 미니프로젝트 3단계 - 연차신청 연차조회 (0) | 2024.03.15 |
스프링부트 예외처리 - @RestControllerAdvice (1) | 2024.03.15 |
[인프런 워밍업 클럽_0기] BE과제 미니프로젝트 2단계 - 출퇴근기록 조회 (0) | 2024.03.11 |