package org.synyx.urlaubsverwaltung.web.statistics; import org.joda.time.DateMidnight; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.util.Assert; import org.synyx.urlaubsverwaltung.core.account.domain.Account; import org.synyx.urlaubsverwaltung.core.account.service.AccountService; import org.synyx.urlaubsverwaltung.core.account.service.VacationDaysService; import org.synyx.urlaubsverwaltung.core.application.domain.Application; import org.synyx.urlaubsverwaltung.core.application.domain.ApplicationStatus; import org.synyx.urlaubsverwaltung.core.application.service.ApplicationService; import org.synyx.urlaubsverwaltung.core.application.service.VacationTypeService; import org.synyx.urlaubsverwaltung.core.overtime.OvertimeService; import org.synyx.urlaubsverwaltung.core.period.DayLength; import org.synyx.urlaubsverwaltung.core.person.Person; import org.synyx.urlaubsverwaltung.core.util.DateUtil; import org.synyx.urlaubsverwaltung.core.workingtime.WorkDaysService; import java.math.BigDecimal; import java.util.List; import java.util.Optional; /** * Builds a {@link org.synyx.urlaubsverwaltung.web.statistics.ApplicationForLeaveStatistics} for the given * {@link org.synyx.urlaubsverwaltung.core.person.Person} and period. * * @author Aljona Murygina - murygina@synyx.de */ @Component public class ApplicationForLeaveStatisticsBuilder { private final AccountService accountService; private final ApplicationService applicationService; private final WorkDaysService calendarService; private final VacationDaysService vacationDaysService; private final OvertimeService overtimeService; private final VacationTypeService vacationTypeService; @Autowired public ApplicationForLeaveStatisticsBuilder(AccountService accountService, ApplicationService applicationService, WorkDaysService calendarService, VacationDaysService vacationDaysService, OvertimeService overtimeService, VacationTypeService vacationTypeService) { this.accountService = accountService; this.applicationService = applicationService; this.calendarService = calendarService; this.vacationDaysService = vacationDaysService; this.overtimeService = overtimeService; this.vacationTypeService = vacationTypeService; } public ApplicationForLeaveStatistics build(Person person, DateMidnight from, DateMidnight to) { Assert.notNull(person, "Person must be given"); Assert.notNull(from, "From must be given"); Assert.notNull(to, "To must be given"); Assert.isTrue(from.getYear() == to.getYear(), "From and to must be in the same year"); ApplicationForLeaveStatistics statistics = new ApplicationForLeaveStatistics(person, vacationTypeService); Optional<Account> account = accountService.getHolidaysAccount(from.getYear(), person); if (account.isPresent()) { BigDecimal vacationDaysLeft = vacationDaysService.calculateTotalLeftVacationDays(account.get()); statistics.setLeftVacationDays(vacationDaysLeft); } List<Application> applications = applicationService.getApplicationsForACertainPeriodAndPerson(from, to, person); for (Application application : applications) { if (application.hasStatus(ApplicationStatus.WAITING) || application.hasStatus(ApplicationStatus.TEMPORARY_ALLOWED)) { statistics.addWaitingVacationDays(application.getVacationType(), getVacationDays(application, from.getYear())); } else if (application.hasStatus(ApplicationStatus.ALLOWED)) { statistics.addAllowedVacationDays(application.getVacationType(), getVacationDays(application, from.getYear())); } } statistics.setLeftOvertime(overtimeService.getLeftOvertimeForPerson(person)); return statistics; } private BigDecimal getVacationDays(Application application, int relevantYear) { int yearOfStartDate = application.getStartDate().getYear(); int yearOfEndDate = application.getEndDate().getYear(); DayLength dayLength = application.getDayLength(); Person person = application.getPerson(); if (yearOfStartDate != yearOfEndDate) { DateMidnight startDate = getStartDateForCalculation(application, relevantYear); DateMidnight endDate = getEndDateForCalculation(application, relevantYear); return calendarService.getWorkDays(dayLength, startDate, endDate, person); } return calendarService.getWorkDays(dayLength, application.getStartDate(), application.getEndDate(), person); } private DateMidnight getStartDateForCalculation(Application application, int relevantYear) { if (application.getStartDate().getYear() != relevantYear) { return DateUtil.getFirstDayOfYear(application.getEndDate().getYear()); } return application.getStartDate(); } private DateMidnight getEndDateForCalculation(Application application, int relevantYear) { if (application.getEndDate().getYear() != relevantYear) { return DateUtil.getLastDayOfYear(application.getStartDate().getYear()); } return application.getEndDate(); } }