반응형

연차 정보가 생기면서 추가된 요구사항.

 

직원이 연차를 신청할수있게되면서 직원의 근무시간을 조회하는 기능에 추가적인 요구사항이 생겼다. 

근무시간을 조회하면서  연차를 사용한날도 같이 조회해주어야한다. 

 

기존에 직원의 정보를 조회해오던 코드의 구조

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());
    }
}

 

각 메소드들을 기능별로 분리하고 정렬 그루핑 매핑 각각 일급컬렉션으로 분리해서 만들어줬다. 

반응형

+ Recent posts