| /********************************************************************************
|
| * Copyright (c) 2018 Mettenmeier GmbH
|
| *
|
| * See the NOTICE file(s) distributed with this work for additional
|
| * information regarding copyright ownership.
|
| *
|
| * This program and the accompanying materials are made available under the
|
| * terms of the Eclipse Public License 2.0 which is available at
|
| * http://www.eclipse.org/legal/epl-2.0
|
| *
|
| * SPDX-License-Identifier: EPL-2.0
|
| ********************************************************************************/
|
| package org.eclipse.openk.sp.controller.planning;
|
|
|
| import java.text.MessageFormat;
|
| import java.util.ArrayList;
|
| import java.util.Collections;
|
| import java.util.Date;
|
| import java.util.HashMap;
|
| import java.util.List;
|
| import java.util.Map;
|
| import java.util.Map.Entry;
|
|
|
| import org.apache.commons.collections.CollectionUtils;
|
| import org.apache.log4j.Logger;
|
| import org.eclipse.openk.sp.controller.AbstractController;
|
| import org.eclipse.openk.sp.controller.validation.ValidationController;
|
| import org.eclipse.openk.sp.db.dao.CalendarRepository;
|
| import org.eclipse.openk.sp.db.dao.StandbyDurationRepository;
|
| import org.eclipse.openk.sp.db.dao.StandbyGroupRepository;
|
| import org.eclipse.openk.sp.db.dao.StandbyListRepository;
|
| import org.eclipse.openk.sp.db.dao.StandbyScheduleBodyRepository;
|
| import org.eclipse.openk.sp.db.dao.StandbyStatusRepository;
|
| import org.eclipse.openk.sp.db.dao.UserInStandbyGroupRepository;
|
| import org.eclipse.openk.sp.db.dao.UserRepository;
|
| import org.eclipse.openk.sp.db.model.CalendarDay;
|
| import org.eclipse.openk.sp.db.model.StandbyDuration;
|
| import org.eclipse.openk.sp.db.model.StandbyGroup;
|
| import org.eclipse.openk.sp.db.model.StandbyScheduleBody;
|
| import org.eclipse.openk.sp.db.model.User;
|
| import org.eclipse.openk.sp.db.model.UserInStandbyGroup;
|
| import org.eclipse.openk.sp.dto.StandbyScheduleBlueprintDto;
|
| import org.eclipse.openk.sp.dto.planning.PlanningBodyResultDto;
|
| import org.eclipse.openk.sp.dto.planning.PlanningMsgDto;
|
| import org.eclipse.openk.sp.dto.planning.PlanningMsgResponseDto;
|
| import org.eclipse.openk.sp.dto.planning.PlanningPhaseDto;
|
| import org.eclipse.openk.sp.dto.planning.StandbyScheduleActionDto;
|
| import org.eclipse.openk.sp.exceptions.SpErrorEntry;
|
| import org.eclipse.openk.sp.exceptions.SpException;
|
| import org.eclipse.openk.sp.exceptions.SpExceptionEnum;
|
| import org.eclipse.openk.sp.mail.MailRequest;
|
| import org.eclipse.openk.sp.util.DateHelper;
|
| import org.eclipse.openk.sp.util.SpMsg;
|
| import org.eclipse.openk.sp.util.ValidationHelper;
|
| import org.joda.time.DateTime;
|
| import org.joda.time.Interval;
|
| import org.springframework.beans.factory.annotation.Autowired;
|
| import org.springframework.stereotype.Service;
|
| import org.springframework.transaction.annotation.Transactional;
|
|
|
| @Service
|
| @Transactional(rollbackFor = Exception.class)
|
| /** Class to handle planning operations. */
|
| public class PlanningController extends AbstractController {
|
| protected static final Logger LOGGER = Logger.getLogger(PlanningController.class);
|
| public static final String TXT_AUTOMATIC_PLANNING = "autom. Planung";
|
| public static final String TXT_AUTOMATIC_PLANNING_HOLIDAY = "autom. Planung (Dienstfrei)";
|
| public static final String TXT_AUTOMATIC_CHANGE = "autom. Ă„nderung";
|
| public static final String TXT_MANUAL_CHANGE = "manuelle Ă„nderung";
|
| public static final String TXT_AND_MORE = "und weitere";
|
|
|
| @Autowired
|
| private StandbyGroupRepository standbyGroupRepository;
|
|
|
| @Autowired
|
| private StandbyListRepository standbyListRepository;
|
|
|
| @Autowired
|
| private StandbyDurationRepository standbyDurationRepository;
|
|
|
| @Autowired
|
| private StandbyStatusRepository standbyStatusRepository;
|
|
|
| @Autowired
|
| private ArchiveController archiveController;
|
|
|
| @Autowired
|
| private StandbyScheduleBodyRepository standbyScheduleBodyRepository;
|
|
|
| @Autowired
|
| private UserInStandbyGroupRepository uisgRepository;
|
|
|
| @Autowired
|
| private UserRepository userRepository;
|
|
|
| @Autowired
|
| private CalendarRepository calendarRepository;
|
|
|
| @Autowired
|
| private ValidationController validatonController;
|
|
|
| @Autowired
|
| private MailRequest mailing;
|
|
|
| private List<PlanningMsgDto> lsPlanningMsg = new ArrayList<>();
|
| private int warningCounter = 0;
|
|
|
| public PlanningMsgResponseDto startPlanning(StandbyScheduleBlueprintDto standbyBlueprintDto, String username)
|
| throws SpException {
|
| PlanningMsgResponseDto responseDto = new PlanningMsgResponseDto();
|
| try {
|
| lsPlanningMsg = new ArrayList<>();
|
| warningCounter = 0;
|
|
|
| // check if input is valid
|
| if (this.validateInputForPlanCalculation(standbyBlueprintDto)) {
|
| standbyBlueprintDto.setValidTo(DateHelper.getEndOfDay(standbyBlueprintDto.getValidTo()));
|
|
|
| // calculate the different phases.
|
| Map<Integer, PlanningPhaseDto> planningPhaseMap = this.calculatePlanningPhaseMap(standbyBlueprintDto);
|
| this.createMsgNumberOfPhases(planningPhaseMap, standbyBlueprintDto);
|
|
|
| Long lastStartUserId = standbyBlueprintDto.getStartIdOfUser();
|
| // loop over planning phases
|
|
|
| // delete existing entries
|
| StandbyGroup stbyGroup = standbyGroupRepository.findOne(standbyBlueprintDto.getStandbyGroupId());
|
| Date lastCalcDate = DateHelper
|
| .getEndOfDay(new DateTime(standbyBlueprintDto.getValidTo()).minusSeconds(1).toDate());
|
| this.changeOrDeleteExistingBodies(stbyGroup,
|
| new DateTime(DateHelper.getStartOfDay(standbyBlueprintDto.getValidFrom())).plusSeconds(1)
|
| .toDate(),
|
| lastCalcDate, 1L, username);
|
|
|
| for (Entry<Integer, PlanningPhaseDto> entry : planningPhaseMap.entrySet()) {
|
| LOGGER.debug("Start Plannig for phase " + entry.getKey());
|
| PlanningPhaseDto dto = entry.getValue();
|
| this.createMsgStartOfPhase(entry.getKey(), dto);
|
| PlanningBodyResultDto planningBodyResultDto = this.calculatePlanForPhase(dto, lastStartUserId,
|
| username, entry.getKey(), lastCalcDate);
|
| lastStartUserId = planningBodyResultDto.getLastUserId();
|
| this.createMsgEndOfPhase(entry.getKey());
|
| LOGGER.debug("End Plannig for phase " + entry.getKey());
|
| }
|
| standbyScheduleBodyRepository.flush();
|
|
|
| // start validation
|
| List<String> lsValidationBeanNames = new ArrayList<>();
|
| lsValidationBeanNames.add(ValidationController.BEAN_GROUP_COVERAGE_VALIDATOR);
|
| lsValidationBeanNames.add(ValidationController.BEAN_DOUBLE_PLANNED_VALIDATOR);
|
| lsValidationBeanNames.add(ValidationController.BEAN_PLACEHOLDER_STANDBY_USER_VALIDATOR);
|
|
|
| List<StandbyGroup> lsStandbyGroups = new ArrayList<>();
|
| lsStandbyGroups.add(standbyGroupRepository.findOne(standbyBlueprintDto.getStandbyGroupId()));
|
|
|
| validatonController.startValidation(standbyBlueprintDto.getValidFrom(),
|
| standbyBlueprintDto.getValidTo(), lsStandbyGroups, lsValidationBeanNames,
|
| standbyBlueprintDto.getStatusId(), null);
|
| responseDto.setLsMsg(lsPlanningMsg);
|
| }
|
| return responseDto;
|
| } catch (SpException e) {
|
| LOGGER.error(e, e);
|
| throw e;
|
| } catch (Exception e) {
|
| LOGGER.error(e, e);
|
| SpErrorEntry ee = SpExceptionEnum.DEFAULT_EXCEPTION.getEntry();
|
| ee.setE(e);
|
| throw new SpException(ee);
|
| }
|
| }
|
|
|
| /**
|
| * Method to calculate the different phases for changing groups.
|
| *
|
| * @param standbyBlueprintDto
|
| * @return
|
| * @throws SpException
|
| */
|
| public Map<Integer, PlanningPhaseDto> calculatePlanningPhaseMap(StandbyScheduleBlueprintDto standbyBlueprintDto)
|
| throws SpException {
|
| Map<Integer, PlanningPhaseDto> resultMap = new HashMap<>();
|
| try {
|
| // start of full planning time slot.
|
| Date validFrom = standbyBlueprintDto.getValidFrom();
|
|
|
| // end of full planning time slot.
|
| DateTime dt = new DateTime(standbyBlueprintDto.getValidTo());
|
| dt = dt.minusSeconds(1);
|
| Date validTo = dt.toDate();
|
|
|
| // temporal date for calculation
|
| Date tmpDate = validFrom;
|
| StandbyGroup group = standbyGroupRepository.findOne(standbyBlueprintDto.getStandbyGroupId());
|
| StandbyDuration firstDuration = this.getFittingDurationOfGroup(group, validFrom);
|
| if (firstDuration != null) {
|
| tmpDate = DateHelper.getDateWithTime(tmpDate, firstDuration.getValidFrom());
|
| tmpDate = new DateTime(tmpDate).plusSeconds(1).toDate();
|
| }
|
|
|
| int phase = 1;
|
| int differenceOfDays = 0;
|
| while (tmpDate.getTime() < validTo.getTime()) {
|
| // get fitting duration
|
| List<StandbyDuration> lsDur = this.getFittingDurationsAroundDate(group, tmpDate);
|
|
|
| StandbyDuration duration = null;
|
| if (lsDur != null && !lsDur.isEmpty()) {
|
| duration = lsDur.get(lsDur.size() - 1);
|
|
|
| // current week day
|
| int tempDateDay = DateHelper.getDayOfWeek(tmpDate);
|
|
|
| // get days between duration start and duration end
|
| int differenceOfDurationDays = DateHelper.calculateDifferenceOfDays(duration.getValidDayFrom(),
|
| duration.getValidDayTo(), duration.getValidFrom(), duration.getValidTo());
|
|
|
| // get days between duration start and the current date (tmpDate)
|
| int differenceOfTempDateAndDurStart = DateHelper.calculateDifferenceOfDays(
|
| duration.getValidDayFrom(), tempDateDay, duration.getValidFrom(), tmpDate);
|
|
|
| // reduce duration slot with the starting difference
|
| differenceOfDays = differenceOfDurationDays - differenceOfTempDateAndDurStart;
|
|
|
| Date startOfDuration = DateHelper.getDateWithTime(tmpDate, duration.getValidFrom());
|
| Date endOfDuration = DateHelper.addDaysToDate(tmpDate, differenceOfDays);
|
| endOfDuration = DateHelper.getDateWithTime(endOfDuration, duration.getValidTo());
|
|
|
| if (!duration.getNextUserInNextDuration()) {
|
| // find next duration with a changing user allowed
|
| StandbyDuration tmpDur = this.getNextDurationWithMaChange(group, endOfDuration);
|
| if (tmpDur != null) {
|
| differenceOfDays = DateHelper.calculateDifferenceOfDays(
|
| DateHelper.getDayOfWeek(startOfDuration), tmpDur.getValidDayTo(), startOfDuration,
|
| tmpDur.getValidTo());
|
| endOfDuration = DateHelper.addDaysToDate(tmpDate, differenceOfDays);
|
| endOfDuration = DateHelper.getDateWithTime(endOfDuration, tmpDur.getValidTo());
|
| } else {
|
| LOGGER.debug("Keine Duration fĂ¼r den Tag : " + startOfDuration + " gefunden.");
|
| }
|
| }
|
|
|
| if (DateHelper.isDateAfter(endOfDuration, validTo)) {
|
| endOfDuration = validTo;
|
| }
|
| List<UserInStandbyGroup> lsUserInGroup = uisgRepository
|
| .findUserForInterval(standbyBlueprintDto.getStandbyGroupId(), tmpDate, endOfDuration);
|
| if (lsUserInGroup != null && !lsUserInGroup.isEmpty()) {
|
| if (resultMap.containsKey(phase)) {
|
| PlanningPhaseDto dto = resultMap.get(phase);
|
| if (CollectionUtils.isEqualCollection(dto.getLsUsers(), lsUserInGroup)) {
|
| dto.setEndDate(endOfDuration);
|
| } else {
|
| phase++;
|
| LOGGER.debug("Add phase " + phase);
|
| resultMap.put(phase,
|
| new PlanningPhaseDto(dto.getEndDate(), endOfDuration, lsUserInGroup));
|
|
|
| }
|
| } else {
|
| LOGGER.debug("Add phase " + phase);
|
| resultMap.put(phase, new PlanningPhaseDto(startOfDuration, endOfDuration, lsUserInGroup));
|
| }
|
| } else {
|
| LOGGER.debug("Keine Gruppe gefunden!");
|
| }
|
|
|
| if (differenceOfDays == 0) {
|
| // add at least one day
|
| differenceOfDays = 1;
|
| }
|
| tmpDate = DateHelper.addDaysToDate(tmpDate, differenceOfDays);
|
| }
|
| }
|
| this.logPhases(resultMap);
|
| return resultMap;
|
| } catch (Exception e) {
|
| LOGGER.error(e, e);
|
| SpErrorEntry ee = SpExceptionEnum.DEFAULT_EXCEPTION.getEntry();
|
| ee.setE(e);
|
| throw new SpException(ee);
|
| }
|
|
|
| }
|
|
|
| /**
|
| * Method to search the next standby duration for a group that has the
|
| * getNextUserInNextDuration flag = true.
|
| *
|
| * @param group
|
| * @param date
|
| * @return
|
| */
|
| public StandbyDuration getNextDurationWithMaChange(StandbyGroup group, Date date) {
|
| for (int i = 0; i <= 6; i++) {
|
| List<StandbyDuration> lsDuration = this.getFittingDurationsByValidTo(group, date);
|
| for (StandbyDuration stbDur : lsDuration) {
|
| if (stbDur.getNextUserInNextDuration()) {
|
| return stbDur;
|
| }
|
| }
|
| date = DateHelper.addDaysToDate(date, 1);
|
| }
|
| return null;
|
| }
|
|
|
| public void changeOrDeleteAtIntervalStart(StandbyScheduleBody body, StandbyDuration duration, Date tmpDate,
|
| String username) {
|
| if (duration != null) {
|
| Date durationStart = DateHelper.getDateWithTime(tmpDate, duration.getValidFrom());
|
| if (DateHelper.isDateBefore(body.getValidFrom(), durationStart)) {
|
| if (DateHelper.isDateAfter(body.getValidTo(), durationStart)) {
|
| body.setValidTo(durationStart);
|
| body.setModificationDate(new Date());
|
| body.setModifiedCause(TXT_AUTOMATIC_CHANGE);
|
| body.setModifiedCause(username);
|
| standbyScheduleBodyRepository.save(body);
|
| }
|
| } else {
|
| standbyScheduleBodyRepository.delete(body);
|
| }
|
| }
|
| }
|
|
|
| public void changeOrDeleteAtIntervalEnd(StandbyScheduleBody body, StandbyDuration duration, Date tmpDate,
|
| String username) {
|
| if (duration != null) {
|
| Date durationEnd = DateHelper.getDateWithTime(tmpDate, duration.getValidTo());
|
| if (DateHelper.isDateBefore(body.getValidFrom(), durationEnd)) {
|
| if (DateHelper.isDateAfter(body.getValidTo(), durationEnd)) {
|
| body.setValidTo(durationEnd);
|
| body.setModificationDate(new Date());
|
| body.setModifiedCause(TXT_AUTOMATIC_CHANGE);
|
| body.setModifiedCause(username);
|
| standbyScheduleBodyRepository.save(body);
|
| }
|
| } else {
|
| standbyScheduleBodyRepository.delete(body);
|
| }
|
| }
|
| }
|
|
|
| public void changeOrDeleteExistingBodies(StandbyGroup group, Date startDate, Date endDate, Long statusId,
|
| String username) {
|
| startDate = DateHelper.getStartOfDay(startDate);
|
| Date tmpDate = startDate;
|
| while (tmpDate.getTime() <= endDate.getTime()) {
|
| List<StandbyScheduleBody> lsBodies = standbyScheduleBodyRepository
|
| .findByGroupAndStatusHittingDateInterval(group.getId(), tmpDate, endDate, statusId);
|
|
|
| List<StandbyDuration> lsFittingDurations = this.getFittingDurationsOfGroup(group, tmpDate);
|
| StandbyDuration duration = null;
|
| if (lsFittingDurations != null && !lsFittingDurations.isEmpty()) {
|
| duration = lsFittingDurations.get(0);
|
| }
|
| for (StandbyScheduleBody body : lsBodies) {
|
| // if (tmpDate.getTime() == endDate.getTime()) {
|
| // this.changeOrDeleteAtIntervalEnd(body, duration, tmpDate, username);
|
| // } else
|
|
|
| if (body.getValidFrom().getTime() >= startDate.getTime()
|
| && body.getValidTo().getTime() <= endDate.getTime()) {
|
| standbyScheduleBodyRepository.delete(body);
|
| }
|
|
|
| }
|
| tmpDate = DateHelper.addDaysToDate(tmpDate, 1);
|
| }
|
|
|
| }
|
|
|
| public PlanningBodyResultDto calculatePlanForPhase(PlanningPhaseDto dto, Long lastStartUserId, String username,
|
| int phaseNumber, Date lastCalcDate) throws SpException {
|
| try {
|
| List<UserInStandbyGroup> lsUserInGroup = dto.getLsUsers();
|
| Long lastTurnUserId = lastStartUserId;
|
|
|
| Collections.sort(lsUserInGroup,
|
| (UserInStandbyGroup o1, UserInStandbyGroup o2) -> o1.getPosition().compareTo(o2.getPosition()));
|
|
|
| int currentPosition = this.getIndexOfLastPlannedUser(lastStartUserId, lsUserInGroup);
|
| if (currentPosition == -1) {
|
| this.createMsgGroupLeaderChanged(userRepository.findOne(lastStartUserId), lsUserInGroup);
|
| currentPosition = 0;
|
| }
|
| Date tmpDate = dto.getStartDate();
|
|
|
| PlanningBodyResultDto planningBodyResultDto = null;
|
| while (tmpDate.getTime() < dto.getEndDate().getTime()) {
|
|
|
| // reset position if end of list has been reached
|
| planningBodyResultDto = this.calculateScheduleBodyEntries(lsUserInGroup, dto.getStartDate(), tmpDate,
|
| lastCalcDate, lastTurnUserId, username, lastStartUserId, phaseNumber);
|
| tmpDate = planningBodyResultDto.getTempDate();
|
| currentPosition = planningBodyResultDto.getNewPosition();
|
| lastStartUserId = planningBodyResultDto.getLastStartUserId();
|
| lastTurnUserId = planningBodyResultDto.getLastUserId();
|
|
|
| this.addMessagesToList(planningBodyResultDto.getLsMsg());
|
| }
|
| planningBodyResultDto.setLastUserId(lastTurnUserId);
|
| return planningBodyResultDto;
|
| } catch (Exception e) {
|
| LOGGER.error(e, e);
|
| SpErrorEntry ee = SpExceptionEnum.DEFAULT_EXCEPTION.getEntry();
|
| ee.setE(e);
|
| throw new SpException(ee);
|
| }
|
| }
|
|
|
| /**
|
| * Method to create a simple {@link StandbyScheduleBody} object with input
|
| * values for planning.
|
| *
|
| * @param group
|
| * @param username
|
| * @param date
|
| * @param user
|
| * @param duration
|
| * @return
|
| */
|
| public StandbyScheduleBody createScheduleBodyObject(StandbyGroup group, String username, Date date, User user,
|
| StandbyDuration duration, String cause) {
|
| StandbyScheduleBody stbyBody = new StandbyScheduleBody();
|
| stbyBody.setModificationDate(new Date());
|
| stbyBody.setModifiedBy(username);
|
| stbyBody.setModifiedCause(cause);
|
| stbyBody.setStandbyGroup(group);
|
| stbyBody.setUser(user);
|
| stbyBody.setStatus(standbyStatusRepository.findOne(1l));
|
| stbyBody.setValidFrom(DateHelper.getDateWithTime(date, duration.getValidFrom()));
|
| stbyBody.setValidTo(DateHelper.getDateWithTime(date, duration.getValidTo()));
|
|
|
| return stbyBody;
|
| }
|
|
|
| public List<StandbyScheduleBody> createOverlappingScheduleBodyObjects(StandbyGroup group, String username,
|
| Date date, User user, StandbyDuration duration, int loopPos, int loopLength) {
|
| List<StandbyScheduleBody> lsStandbyScheduleBodies = new ArrayList<>();
|
| StandbyScheduleBody stbyBody = this.createScheduleBodyObject(group, username, date, user, duration,
|
| TXT_AUTOMATIC_PLANNING);
|
| if (loopPos > 0) {
|
| // if not the first loop the schedule body should start at the begin of the day.
|
| stbyBody.setValidFrom(DateHelper.getDateWithTime(date, DateHelper.getStartOfDay(duration.getValidFrom())));
|
| }
|
| Date validTo = DateHelper.getDateWithTime(date, duration.getValidTo());
|
| validTo = DateHelper.getEndOfDay(validTo);
|
| stbyBody.setValidTo(validTo);
|
|
|
| stbyBody = this.calculateHoliday(group, date, stbyBody, false);
|
|
|
| lsStandbyScheduleBodies.add(stbyBody);
|
| if (loopPos + 1 == loopLength) {
|
| // if last entry use end time of duration
|
| StandbyScheduleBody stbyBody2 = null;
|
| stbyBody2 = this.createScheduleBodyObject(group, username, date, user, duration, TXT_AUTOMATIC_PLANNING);
|
| Date nextDay = DateHelper.addDaysToDate(date, 1);
|
| Date validFrom = DateHelper.getDateWithTime(DateHelper.addDaysToDate(date, 1),
|
| DateHelper.getStartOfDay(duration.getValidFrom()));
|
| stbyBody2.setValidFrom(validFrom);
|
| validTo = DateHelper.getDateWithTime(nextDay, duration.getValidTo());
|
| stbyBody2.setValidTo(validTo);
|
| this.calculateHoliday(group, nextDay, stbyBody2, false);
|
| lsStandbyScheduleBodies.add(stbyBody2);
|
| }
|
|
|
| return lsStandbyScheduleBodies;
|
| }
|
|
|
| /**
|
| * Method to check if the current day is a holiday for the standby group and
|
| * calls the pre-draw or extend calculation.
|
| *
|
| * @param group
|
| * @param date
|
| * @param stbyBody
|
| * @return
|
| */
|
| public StandbyScheduleBody calculateHoliday(StandbyGroup group, Date date, StandbyScheduleBody stbyBody,
|
| boolean isSingleDay) {
|
| if (isHoliday(date, group)) {
|
| if (group.getExtendStandbyTime()) {
|
| // if extend of standby time is needed
|
| stbyBody = this.calculateHolidayExtend(group, date, stbyBody);
|
| if (isSingleDay) { // additional calculation if no day overlapping time slot
|
| stbyBody = this.calculateHolidayPreDraw(group, date, stbyBody);
|
| }
|
| } else {
|
| // is pre-draw of standby time needed
|
| stbyBody = this.calculateHolidayPreDraw(group, date, stbyBody);
|
| if (isSingleDay) { // additional calculation if no day overlapping time slot
|
| stbyBody = this.calculateHolidayExtend(group, date, stbyBody);
|
| }
|
| }
|
| }
|
| return stbyBody;
|
| }
|
|
|
| /**
|
| * Method to change the standby time if a holiday / calendar day is defined and
|
| * the standby time has to be pre-drawn.
|
| *
|
| * @param group
|
| * @param date
|
| * @param stbyBody
|
| * @return
|
| */
|
| public StandbyScheduleBody calculateHolidayPreDraw(StandbyGroup group, Date date, StandbyScheduleBody stbyBody) {
|
|
|
| List<StandbyDuration> lsDurations = this.getFittingDurationsByValidTo(group, date);
|
| if (lsDurations != null) {
|
| int size = lsDurations.size();
|
| // loop backward to find last fitting duration
|
| for (int a = size; a > 0; a--) {
|
| StandbyDuration dur = lsDurations.get(a - 1);
|
| // proof if found duration ends before current body starts.
|
| if (dur != null && DateHelper.isDateBefore(DateHelper.getDateWithTime(date, dur.getValidTo()),
|
| stbyBody.getValidFrom())) {
|
| // set last found duration end as start of current entry
|
| stbyBody.setValidFrom(DateHelper.getDateWithTime(date, dur.getValidTo()));
|
| this.createMsgExtendHoliday(stbyBody, date, false);
|
| // end loop after first fitting result.
|
| stbyBody.setModifiedCause(TXT_AUTOMATIC_PLANNING_HOLIDAY);
|
| return stbyBody;
|
| }
|
| }
|
| // no last duration for the day has been found. Therefore the start of day has
|
| // been used for current entry
|
| if (DateHelper.isDateBefore(DateHelper.getStartOfDay(date), stbyBody.getValidFrom())) {
|
| stbyBody.setValidFrom(DateHelper.getDateWithTime(date, DateHelper.getStartOfDay(date)));
|
| this.createMsgExtendHoliday(stbyBody, date, false);
|
| stbyBody.setModifiedCause(TXT_AUTOMATIC_PLANNING_HOLIDAY);
|
| }
|
| } else {
|
| // no last duration for the day has been found. Therefore the start of day has
|
| // been used for current entry
|
| if (DateHelper.isDateBefore(DateHelper.getStartOfDay(date), stbyBody.getValidFrom())) {
|
| stbyBody.setValidFrom(DateHelper.getDateWithTime(date, DateHelper.getStartOfDay(date)));
|
| this.createMsgExtendHoliday(stbyBody, date, false);
|
| stbyBody.setModifiedCause(TXT_AUTOMATIC_PLANNING_HOLIDAY);
|
| }
|
| }
|
|
|
| return stbyBody;
|
| }
|
|
|
| /**
|
| * Method to change the standby time if a holiday / calendar day is defined and
|
| * the standby time has to be extended.
|
| *
|
| * @param group
|
| * @param date
|
| * @param stbyBody
|
| * @return
|
| */
|
| public StandbyScheduleBody calculateHolidayExtend(StandbyGroup group, Date date, StandbyScheduleBody stbyBody) {
|
| List<StandbyDuration> lsDurations = this.getFittingDurationsOfGroup(group, date);
|
| if (lsDurations != null) {
|
| int size = lsDurations.size();
|
| // loop forward to find fitting duration that starts after current schedule body
|
| for (int a = 0; a < size; a++) {
|
| StandbyDuration dur = lsDurations.get(a);
|
| // proof if found duration starts after the end of current body.
|
| if (dur != null && DateHelper.isDateAfter(DateHelper.getDateWithTime(date, dur.getValidFrom()),
|
| stbyBody.getValidTo())) {
|
| // set end time of current entry to the start of the next duration
|
| stbyBody.setValidTo(DateHelper.getDateWithTime(date, dur.getValidFrom()));
|
| stbyBody.setModifiedCause(TXT_AUTOMATIC_PLANNING_HOLIDAY);
|
| this.createMsgExtendHoliday(stbyBody, date, true);
|
| // end loop after first fitting result.
|
| return stbyBody;
|
| }
|
| }
|
| // no last duration for the day has been found. Therefore the start of day has
|
| // been used for current entry
|
| if (DateHelper.isDateAfter(DateHelper.getEndOfDay(date), stbyBody.getValidTo())) {
|
| stbyBody.setValidTo(DateHelper.getEndOfDay(date));
|
| stbyBody.setModifiedCause(TXT_AUTOMATIC_PLANNING_HOLIDAY);
|
| this.createMsgExtendHoliday(stbyBody, date, true);
|
| }
|
| } else {
|
| // no last duration for the day has been found. Therefore the start of day has
|
| // been used for current entry
|
| if (DateHelper.isDateAfter(DateHelper.getEndOfDay(date), stbyBody.getValidTo())) {
|
| stbyBody.setValidTo(DateHelper.getEndOfDay(date));
|
| stbyBody.setModifiedCause(TXT_AUTOMATIC_PLANNING_HOLIDAY);
|
| this.createMsgExtendHoliday(stbyBody, date, true);
|
| }
|
| }
|
| return stbyBody;
|
| }
|
|
|
| public PlanningBodyResultDto calculateScheduleBodyEntries(List<UserInStandbyGroup> lsUserInGroup, Date startDate,
|
| Date currentDate, Date lastDate, Long lastTurnUserId, String username, Long lastStartUserId,
|
| int phaseNumber) {
|
| StandbyGroup group = lsUserInGroup.get(0).getStandbyGroup();
|
| int currentPosition = this.getIndexOfLastPlannedUser(lastTurnUserId, lsUserInGroup);
|
| if (currentPosition == -1) {
|
| currentPosition = 0;
|
| }
|
| PlanningBodyResultDto resultObj = new PlanningBodyResultDto();
|
| resultObj.setLastStartUserId(lastStartUserId);
|
| resultObj.setNewPosition(currentPosition);
|
| resultObj.setLastUserId(lsUserInGroup.get(currentPosition).getUser().getId());
|
|
|
| // read fitting duration for the current phase.
|
| List<StandbyDuration> lsFittingDurations = new ArrayList<>();
|
|
|
| // BP-738 - check if durations are ending at start of phase.
|
| if (phaseNumber == 1) {
|
| this.appendEndingDurationsAtStartingPhase(lsFittingDurations, group, startDate, currentDate);
|
| }
|
| lsFittingDurations.addAll(this.getFittingDurationsOfGroup(group, currentDate));
|
|
|
| if (!lsFittingDurations.isEmpty()) {
|
| for (StandbyDuration fittingDuration : lsFittingDurations) {
|
| int startWeekDayInt = DateHelper.getDayOfWeek(currentDate);
|
| int endWeekDayInt = fittingDuration.getValidDayTo();
|
| int coveredDays = DateHelper.calculateDifferenceOfDays(startWeekDayInt, endWeekDayInt,
|
| fittingDuration.getValidFrom(),
|
| new DateTime(fittingDuration.getValidTo()).minusSeconds(1).toDate());
|
|
|
| if (coveredDays == 0) {
|
| // single entry with no over night duration
|
| LOGGER.debug("A day was found that just cover a single day.");
|
| StandbyScheduleBody stbyBody = this.createScheduleBodyObject(group, username, currentDate,
|
| lsUserInGroup.get(currentPosition).getUser(), fittingDuration, TXT_AUTOMATIC_PLANNING);
|
| standbyScheduleBodyRepository.save(stbyBody);
|
| // calculate if holiday
|
| stbyBody = this.calculateHoliday(group, currentDate, stbyBody, true);
|
|
|
| createMsgSavingBody(stbyBody);
|
| } else {
|
| resultObj = this.calculateMultiScheduleBodyEntries(lsUserInGroup, currentDate, lastDate,
|
| currentPosition, username, fittingDuration, coveredDays);
|
| }
|
| resultObj.setCurrentDuration(fittingDuration);
|
| PlanningBodyResultDto resultDto = this.resetCounterToNewPosition(currentPosition, lastStartUserId,
|
| lsUserInGroup, group.getNextUserInNextCycle(), fittingDuration.getNextUserInNextDuration());
|
| currentPosition = resultDto.getNewPosition();
|
| lastStartUserId = resultDto.getLastStartUserId();
|
| resultObj.setLastStartUserId(lastStartUserId);
|
| }
|
| resultObj.setNewPosition(currentPosition);
|
| resultObj.setTempDate(DateHelper.addDaysToDate(currentDate, 1));
|
| resultObj.setLastUserId(lsUserInGroup.get(currentPosition).getUser().getId());
|
|
|
| } else {
|
| resultObj.setTempDate(DateHelper.addDaysToDate(currentDate, 1));
|
| // this.createMsgNotAvailable(group, currentDate);
|
| }
|
| return resultObj;
|
| }
|
|
|
| public PlanningBodyResultDto calculateMultiScheduleBodyEntries(List<UserInStandbyGroup> lsUserInGroup,
|
| Date currentDate, Date lastDate, int currentPosition, String username, StandbyDuration fittingDuration,
|
| int coveredDays) {
|
| PlanningBodyResultDto resultObj = new PlanningBodyResultDto();
|
| Date nextDay = null;
|
| // entries with over night or many days duration
|
| for (int i = 0; i < coveredDays; i++) {
|
| nextDay = DateHelper.addDaysToDate(currentDate, 1);
|
| if (DateHelper.isDateAfter(nextDay, lastDate) || DateHelper.isSameDate(nextDay, lastDate)) {
|
| StandbyScheduleBody stbyBody = this.createScheduleBodyObject(lsUserInGroup.get(0).getStandbyGroup(),
|
| username, currentDate, lsUserInGroup.get(currentPosition).getUser(), fittingDuration,
|
| TXT_AUTOMATIC_PLANNING);
|
| int dayOfCurrentWeek = DateHelper.getDayOfWeek(currentDate);
|
| if (dayOfCurrentWeek != DateHelper.getDayOfWeek(new DateTime(lastDate).minusSeconds(1).toDate())
|
| || fittingDuration.getValidDayFrom() != dayOfCurrentWeek) {
|
|
|
| // set start of day when it is not the start of the duration and it is not the
|
| // end of the planning phase
|
| stbyBody.setValidFrom(DateHelper.getStartOfDay(currentDate));
|
|
|
| }
|
|
|
| // reset ending date to beginning of next day.
|
| stbyBody.setValidTo(DateHelper.getEndOfDay(currentDate));
|
| standbyScheduleBodyRepository.save(stbyBody);
|
| createMsgSavingBody(stbyBody);
|
|
|
| String warning = "FĂ¼r das Datum (" + currentDate
|
| + ") wird der Eintrag nur bis zum Tages-Ende geplant, da der Folgetag den definierten Zeitraum der Phase Ă¼berschreitet.";
|
| this.addMessageToList((new PlanningMsgDto(warning, PlanningMsgDto.INFO, PlanningMsgDto.CSS_INFO)));
|
| resultObj.setNewPosition(currentPosition);
|
| return resultObj;
|
|
|
| } else {
|
| List<StandbyScheduleBody> lsScheduleBodies = this.createOverlappingScheduleBodyObjects(
|
| lsUserInGroup.get(0).getStandbyGroup(), username, currentDate,
|
| lsUserInGroup.get(currentPosition).getUser(), fittingDuration, i, coveredDays);
|
| for (StandbyScheduleBody stbyBody : lsScheduleBodies) {
|
| standbyScheduleBodyRepository.save(stbyBody);
|
| createMsgSavingBody(stbyBody);
|
| resultObj.setTempDate(nextDay);
|
| }
|
| resultObj.setNewPosition(currentPosition);
|
| resultObj.setTempDate(nextDay);
|
| currentDate = resultObj.getTempDate();
|
| }
|
| }
|
| return resultObj;
|
| }
|
|
|
| /**
|
| * Method to create a success message for saving an {@link StandbyScheduleBody}
|
| * object.
|
| *
|
| * @param stbyBody
|
| * @return
|
| */
|
| protected PlanningMsgDto createMsgSavingBody(StandbyScheduleBody stbyBody) {
|
| String info = stbyBody.getUser().getFirstname() + " " + stbyBody.getUser().getLastname()
|
| + " wurde fĂ¼r den Zeitraum vom (" + stbyBody.getValidFrom() + ") bis zum (" + stbyBody.getValidTo()
|
| + ") eingeplant.";
|
| PlanningMsgDto dto = new PlanningMsgDto(info, PlanningMsgDto.INFO, PlanningMsgDto.CSS_INFO_ML3);
|
| this.addMessageToList(dto);
|
| return dto;
|
| }
|
|
|
| /**
|
| * Method to create a success message for saving an {@link StandbyScheduleBody}
|
| * object.
|
| *
|
| * @param stbyBody
|
| * @return
|
| */
|
| protected PlanningMsgDto createMsgExtendHoliday(StandbyScheduleBody stbyBody, Date date, Boolean isExtendedDuty) {
|
| StringBuilder strBuilder = new StringBuilder("Die Bereitschaftszeit fĂ¼r " + stbyBody.getUser().getFirstname()
|
| + " " + stbyBody.getUser().getLastname() + " muss am (" + date
|
| + ") auf Grund eines dienstfreien Tages");
|
|
|
| if (isExtendedDuty) {
|
| strBuilder.append(" verlängert werden.");
|
| } else {
|
| strBuilder.append(" vorgezogen werden.");
|
| }
|
|
|
| PlanningMsgDto dto = new PlanningMsgDto(strBuilder.toString(), PlanningMsgDto.INFO, PlanningMsgDto.CSS_INFO);
|
| this.addMessageToList(dto);
|
| return dto;
|
| }
|
|
|
| /**
|
| * Method to create a warning because of no given group for planning.
|
| *
|
| * @param stbyBody
|
| * @return
|
| */
|
| protected PlanningMsgDto createMsgNotAvailable(StandbyGroup group, Date currentDate) {
|
| String warning = "FĂ¼r die Gruppe (" + group.getTitle()
|
| + ") wurde keine beginnende Duration fĂ¼r folgenden Tag gefunden: (" + currentDate + ")";
|
| LOGGER.warn(warning);
|
| PlanningMsgDto dto = new PlanningMsgDto(warning, PlanningMsgDto.WARN, PlanningMsgDto.CSS_WARN);
|
| this.addMessageToList(dto);
|
| return dto;
|
| }
|
|
|
| /**
|
| * Method to create a info message with the number of old deleted ScheduleBody
|
| * objects.
|
| *
|
| * @param map
|
| * @param blueprintDto
|
| * @return
|
| */
|
| protected PlanningMsgDto createMsgNumberOfPhases(Map<Integer, PlanningPhaseDto> map,
|
| StandbyScheduleBlueprintDto blueprintDto) {
|
| String info = "";
|
|
|
| if (map == null || map.size() == 0) {
|
| info = "Auf Grund fehlender Bereitschaften im gewählten Zeitraum, vom " + blueprintDto.getValidFrom()
|
| + " bis " + blueprintDto.getValidTo() + ", konnte keine Bereitschaftsphase generiert werden.";
|
| LOGGER.info(info);
|
| PlanningMsgDto dto = new PlanningMsgDto(info, PlanningMsgDto.WARN, PlanningMsgDto.CSS_WARN);
|
| this.addMessageToList(dto);
|
| return dto;
|
| } else {
|
| // search missing phase slots
|
| this.addMessagesToList(this.createMsgMissingPhasesFound(map, blueprintDto));
|
|
|
| info = "Durch wechselnde Gruppenmitglieder wurde(n) " + map.size()
|
| + " Bereitschaftsphase(n) fĂ¼r den angegebenen Zeitraum , vom " + blueprintDto.getValidFrom()
|
| + " bis " + blueprintDto.getValidTo() + ", erkannt.";
|
| LOGGER.info(info);
|
| PlanningMsgDto dto = new PlanningMsgDto(info, PlanningMsgDto.INFO, PlanningMsgDto.CSS_INFO);
|
| this.addMessageToList(dto);
|
|
|
| return dto;
|
| }
|
|
|
| }
|
|
|
| protected List<PlanningMsgDto> createMsgStartOfPhase(Integer phaseId, PlanningPhaseDto phase) {
|
| List<PlanningMsgDto> lsMsgDto = new ArrayList<>();
|
| String info = "Die Bereitschaftsphase (" + phaseId + ") wird jetzt fĂ¼r den Zeitraum vom ("
|
| + DateHelper.getStartOfDay(phase.getStartDate()) + ") bis zum ("
|
| + DateHelper.getStartOfDay(phase.getEndDate()) + ") berechnet";
|
| LOGGER.info(info);
|
| PlanningMsgDto dto = new PlanningMsgDto(info, PlanningMsgDto.INFO, PlanningMsgDto.CSS_INFO);
|
| this.addMessageToList(dto);
|
| lsMsgDto.add(dto);
|
|
|
| StringBuilder builder = new StringBuilder();
|
| for (UserInStandbyGroup uisg : phase.getLsUsers()) {
|
| User user = uisg.getUser();
|
| String name = user.getFirstname() + " " + user.getLastname();
|
| if (builder.toString().isEmpty()) {
|
| builder.append(name);
|
| } else {
|
| builder.append(", " + name);
|
| }
|
| }
|
| info = "Folgende Bereitschaftende werden verplant: " + builder.toString();
|
| LOGGER.info(info);
|
| dto = new PlanningMsgDto(info, PlanningMsgDto.INFO, PlanningMsgDto.CSS_INFO);
|
| this.addMessageToList(dto);
|
| lsMsgDto.add(dto);
|
|
|
| return lsMsgDto;
|
| }
|
|
|
| protected List<PlanningMsgDto> createMsgMissingPhasesFound(Map<Integer, PlanningPhaseDto> map,
|
| StandbyScheduleBlueprintDto blueprintDto) {
|
| List<PlanningMsgDto> lsResults = new ArrayList<>();
|
|
|
| Date validFromDate = DateHelper.getStartOfDay(blueprintDto.getValidFrom());
|
| Date validToDate = DateHelper.getStartOfDay(blueprintDto.getValidTo());
|
| Date currentDate = null;
|
| Date lastDate = null;
|
|
|
| for (Entry<Integer, PlanningPhaseDto> entry : map.entrySet()) {
|
| currentDate = DateHelper.getStartOfDay(entry.getValue().getStartDate());
|
| // set the validFromDate as lastDate for the first round
|
| if (entry.getKey().intValue() == 1) {
|
| lastDate = validFromDate;
|
| }
|
|
|
| if (!DateHelper.isSameDate(lastDate, currentDate)) {
|
| String warn = "Es konnte keine Bereitschaftsphase vom (" + currentDate + ") bis zum (" + lastDate
|
| + ") berechnet werden, da es in der Bereitschaftsgruppe keine gĂ¼ltigen Mitarbeiter zur Auswahl gibt. "
|
| + "Der Plan kann somit fĂ¼r diesen Zeitraum nicht generiert werden.";
|
| LOGGER.info(warn);
|
| PlanningMsgDto dto = new PlanningMsgDto(warn, PlanningMsgDto.WARN, PlanningMsgDto.CSS_WARN);
|
| lsResults.add(dto);
|
| }
|
|
|
| if (entry.getKey() == map.size()) {
|
| Date endDate = DateHelper.getStartOfDay(entry.getValue().getEndDate());
|
| if (DateHelper.isDateBefore(endDate, new DateTime(validToDate).minusDays(1).toDate())) {
|
| String warn = "Es konnte keine Bereitschaftsphase vom (" + endDate + ") bis zum (" + validToDate
|
| + ") berechnet werden, da es in der Bereitschaftsgruppe keine gĂ¼ltigen Mitarbeiter zur Auswahl gibt. "
|
| + "Der Plan kann somit fĂ¼r diesen Zeitraum nicht generiert werden.";
|
| LOGGER.info(warn);
|
| PlanningMsgDto dto = new PlanningMsgDto(warn, PlanningMsgDto.WARN, PlanningMsgDto.CSS_WARN);
|
| lsResults.add(dto);
|
| }
|
|
|
| }
|
| // refresh last found date
|
| lastDate = entry.getValue().getEndDate();
|
| lastDate = DateHelper.getStartOfDay(lastDate);
|
| }
|
| return lsResults;
|
| }
|
|
|
| protected PlanningMsgDto createMsgEndOfPhase(Integer phasenId) {
|
| String info = "Die Berechnung der Bereitschaftsphase (" + phasenId + ") wurde abgeschlossen";
|
| LOGGER.info(info);
|
| PlanningMsgDto dto = new PlanningMsgDto(info, PlanningMsgDto.INFO, PlanningMsgDto.CSS_INFO);
|
| this.addMessageToList(dto);
|
| return dto;
|
| }
|
|
|
| /**
|
| * Method to create a info message with the number of old deleted ScheduleBody
|
| * objects.
|
| *
|
| * @param stbyBody
|
| * @return
|
| */
|
| protected PlanningMsgDto createMsgLeaveOutStarter() {
|
| String info = "Der letzte Starter wurde aufgrund des aktivierten Vorschubs Ă¼bersprungen.";
|
| LOGGER.info(info);
|
| PlanningMsgDto dto = new PlanningMsgDto(info, PlanningMsgDto.INFO, PlanningMsgDto.CSS_INFO);
|
| this.addMessageToList(dto);
|
| return dto;
|
| }
|
|
|
| /**
|
| * Method to create a info message with the number of old deleted ScheduleBody
|
| * objects.
|
| *
|
| * @param stbyBody
|
| * @return
|
| */
|
| protected PlanningMsgDto createMsgDeleteScheduleBodies(int numberOfElements) {
|
| String warning = "Es wurden " + numberOfElements
|
| + " ältere Bereitschaften fĂ¼r den angegebenen Zeitraum entfernt.";
|
| LOGGER.info(warning);
|
| PlanningMsgDto dto = new PlanningMsgDto(warning, PlanningMsgDto.WARN, PlanningMsgDto.CSS_WARN);
|
| this.addMessageToList(dto);
|
| return dto;
|
| }
|
|
|
| /**
|
| * Method to create a info message with the number of old deleted ScheduleBody
|
| * objects.
|
| *
|
| * @param stbyBody
|
| * @return
|
| */
|
| protected PlanningMsgDto createMsgGroupLeaderChanged(User user, List<UserInStandbyGroup> lsUserInStandbyGroup) {
|
| User nextUser = lsUserInStandbyGroup.get(0).getUser();
|
| String warning = "Die ausgewählte Start - Bereitschaft (" + user.getFirstname() + " " + user.getLastname()
|
| + ") ist im angegebenen Zeitraum nicht aktiv. Es wird mit (" + nextUser.getFirstname() + " "
|
| + nextUser.getLastname() + ") begonnen.";
|
| LOGGER.info(warning);
|
| PlanningMsgDto dto = new PlanningMsgDto(warning, PlanningMsgDto.WARN, PlanningMsgDto.CSS_WARN);
|
| this.addMessageToList(dto);
|
| return dto;
|
| }
|
|
|
| /**
|
| * Method to delete {@link StandbyScheduleBody} Objects by a list of id's.
|
| *
|
| * @param lsIds
|
| * @return
|
| */
|
| public PlanningMsgDto deleteScheduleBodiesByIds(List<Long> lsIds) throws SpException {
|
| try {
|
| for (Long id : lsIds) {
|
| standbyScheduleBodyRepository.delete(id);
|
| }
|
| return createMsgDeleteScheduleBodies(lsIds.size());
|
| } catch (Exception e) {
|
| SpErrorEntry ee = SpExceptionEnum.COULD_NOT_DELETE_ENTITY_EXCEPTION.getEntry();
|
| ee.setMessage(MessageFormat.format(ee.getMessage(), "StandbyScheduleBodies", e.getMessage()));
|
| SpException spE = new SpException(ee);
|
| LOGGER.error(spE, spE);
|
| throw spE;
|
| }
|
| }
|
|
|
| /**
|
| * Method to check if date is a defined value in calendar database.
|
| *
|
| * @param date
|
| * @return
|
| */
|
| public Boolean isHoliday(Date date, StandbyGroup group) {
|
| DateTime endTime = new DateTime(DateHelper.getEndOfDay(date));
|
| endTime = endTime.minus(100);
|
| List<CalendarDay> lsCalendarDays = calendarRepository.findValidByDate(DateHelper.getStartOfDay(date),
|
| endTime.toDate());
|
| if (lsCalendarDays != null && !lsCalendarDays.isEmpty()) {
|
| List<CalendarDay> lsIgnoreList = group.getLsIgnoredCalendarDays();
|
| for (CalendarDay day : lsCalendarDays) {
|
| if (!lsIgnoreList.contains(day)) {
|
| return true;
|
| }
|
| }
|
| return false;
|
| } else {
|
| return false;
|
| }
|
| }
|
|
|
| /**
|
| * Method to get the start duration time for the group.
|
| *
|
| * @param group
|
| * @param date
|
| * @return null if no fitting duration is available
|
| */
|
| public StandbyDuration getFittingDurationOfGroup(StandbyGroup group, Date date) {
|
| List<StandbyDuration> lsDuration = this.getFittingDurationsOfGroup(group, date);
|
| if (lsDuration != null && !lsDuration.isEmpty()) {
|
| return lsDuration.get(0);
|
| }
|
| return null;
|
| }
|
|
|
| /**
|
| * Method to get the start duration time for the group.
|
| *
|
| * @param group
|
| * @param date
|
| * @return null if no fitting duration is available
|
| */
|
| public List<StandbyDuration> getFittingDurationsOfGroup(StandbyGroup group, Date date) {
|
| int dayOfWeek = DateHelper.getDayOfWeek(date);
|
| return standbyDurationRepository.findDurationForValidFromDay(group.getId(), dayOfWeek);
|
| }
|
|
|
| /**
|
| * Method to get the start duration time for the group.
|
| *
|
| * @param group
|
| * @param date
|
| * @return null if no fitting duration is available
|
| */
|
| public StandbyDuration getFittingDurationByValidTo(StandbyGroup group, Date date) {
|
| List<StandbyDuration> lsDuration = this.getFittingDurationsByValidTo(group, date);
|
| if (lsDuration != null && !lsDuration.isEmpty()) {
|
| return lsDuration.get(lsDuration.size() - 1);
|
| }
|
| return null;
|
| }
|
|
|
| /**
|
| * Method to get a list of {@link StandbyDuration} by its end time for the
|
| * group.
|
| *
|
| * @param group
|
| * @param date
|
| * @return null if no fitting duration is available
|
| */
|
| public List<StandbyDuration> getFittingDurationsByValidTo(StandbyGroup group, Date endDate) {
|
| int dayOfWeek = DateHelper.getDayOfWeek(endDate);
|
| return standbyDurationRepository.findDurationForValidToDay(group.getId(), dayOfWeek);
|
| }
|
|
|
| /**
|
| * Method to get a list of {@link StandbyDuration} where the time is around the
|
| * searched date. startOfDuration <= searchedDate <= endDate
|
| *
|
| * @param group
|
| * @param date
|
| * @return null if no fitting duration is available
|
| */
|
| public List<StandbyDuration> getFittingDurationsAroundDate(StandbyGroup group, Date date) {
|
| int dayOfWeek = DateHelper.getDayOfWeek(date);
|
| List<StandbyDuration> lsFittingDurations = new ArrayList<>();
|
| List<StandbyDuration> lsDurations = standbyDurationRepository.findById(group.getId());
|
| for (StandbyDuration dur : lsDurations) {
|
| if (dur.getValidDayFrom() <= dayOfWeek && dayOfWeek <= dur.getValidDayTo()) {
|
| // start <= current <= end
|
| lsFittingDurations.add(dur);
|
| } else if (dur.getValidDayFrom() > dur.getValidDayTo()) {
|
| // start > end
|
| int calcValue = dayOfWeek;
|
| if (dur.getValidDayFrom() > dayOfWeek) {
|
| // AND start > current
|
| calcValue = dayOfWeek + 7;
|
| }
|
| if (dur.getValidDayFrom() < calcValue && calcValue <= (dur.getValidDayTo() + 7)) {
|
| lsFittingDurations.add(dur);
|
| }
|
| } else if (dur.getValidDayFrom() == dur.getValidDayTo() && (dur.getValidDayFrom() == dayOfWeek
|
| || DateHelper.calculateDifferenceOfDays(dur.getValidDayFrom(), dur.getValidDayTo(),
|
| dur.getValidFrom(), dur.getValidTo()) == 7)) {
|
| // if same day of week or if whole week
|
| lsFittingDurations.add(dur);
|
| }
|
| }
|
| return lsFittingDurations;
|
| }
|
|
|
| /**
|
| * Method to set the currentPosition to 0 if end of list is reached.
|
| *
|
| * @param currentPosition
|
| * @param listSize
|
| * @return
|
| */
|
| public PlanningBodyResultDto resetCounterToNewPosition(int currentPosition, Long lastStartUserId,
|
| List<UserInStandbyGroup> lsUserInGroup, Boolean isNextUserInNextCycle, Boolean isNextUserInNextDuration) {
|
| LOGGER.debug("currentPosition: " + currentPosition);
|
| LOGGER.debug("lastStartUserId: " + lastStartUserId);
|
| LOGGER.debug("UserList Size: " + lsUserInGroup.size());
|
|
|
| // default values
|
| PlanningBodyResultDto result = new PlanningBodyResultDto();
|
| result.setLastStartUserId(lastStartUserId);
|
| result.setNewPosition(currentPosition);
|
|
|
| if (isNextUserInNextDuration) {
|
| // get next available position
|
| currentPosition = this.getNextAvailablePosition(currentPosition, lsUserInGroup);
|
| LOGGER.debug("next currentPosition is: " + currentPosition);
|
| int lastIndex = this.getIndexOfLastPlannedUser(lastStartUserId, lsUserInGroup);
|
| LOGGER.debug("lastIndexOf: " + lastIndex);
|
| if (currentPosition == lastIndex) {
|
| LOGGER.debug("start user found at current position " + currentPosition);
|
| if (isNextUserInNextCycle) {
|
| LOGGER.debug("Because of isNextUserInNextCycle = '" + isNextUserInNextCycle
|
| + "' next position will be searched...) ");
|
| this.createMsgLeaveOutStarter();
|
| currentPosition = this.getNextAvailablePosition(currentPosition, lsUserInGroup);
|
| LOGGER.debug("next currentPosition is: " + currentPosition);
|
| Long nextStartUserId = lsUserInGroup.get(currentPosition).getUser().getId();
|
| result.setLastStartUserId(nextStartUserId);
|
| LOGGER.debug("Next start user id is set to :" + nextStartUserId.longValue());
|
| } else {
|
| LOGGER.debug("Because of isNextUserInNextCycle = '" + isNextUserInNextCycle
|
| + "' currentPosition is still: " + currentPosition);
|
| }
|
| }
|
| } else {
|
| LOGGER.info("isNextUserInNextDuration == false. CurrentUser still in charge.");
|
| }
|
| result.setNewPosition(currentPosition);
|
| return result;
|
| }
|
|
|
| /**
|
| * Method to calculate the next available position in array list. Starts with
|
| * the first on if list has reached the end.
|
| *
|
| * @param currentPosition
|
| * @param lsUserInGroup
|
| * @return
|
| */
|
| public int getNextAvailablePosition(int currentPosition, List<UserInStandbyGroup> lsUserInGroup) {
|
| if (currentPosition + 1 < lsUserInGroup.size()) {
|
| return currentPosition + 1;
|
| } else {
|
| return 0;
|
| }
|
| }
|
|
|
| /**
|
| * Method to get the position of the last planned user. Returns back '-1' if not
|
| * found in given list.
|
| *
|
| * @param currentPosition
|
| * @param listSize
|
| * @return
|
| */
|
| public int getIndexOfLastPlannedUser(Long lastStartUserId, List<UserInStandbyGroup> lsUserInGroup) {
|
| int indexOf = -1;
|
| for (UserInStandbyGroup userInGroup : lsUserInGroup) {
|
| if (userInGroup.getUser().getId().longValue() == lastStartUserId.longValue()) {
|
| indexOf = lsUserInGroup.indexOf(userInGroup);
|
| return indexOf;
|
| }
|
| }
|
| return indexOf;
|
| }
|
|
|
| /**
|
| * Method to validate the input parameter for the planning.
|
| *
|
| * @param standbyBlueprintDto
|
| * @return
|
| * @throws SpException
|
| */
|
| public boolean validateInputForPlanCalculation(StandbyScheduleBlueprintDto standbyBlueprintDto) throws SpException {
|
| if (standbyBlueprintDto.getStandbyListId() != null) {
|
| if (!standbyListRepository.exists(standbyBlueprintDto.getStandbyListId())) {
|
| SpErrorEntry ee = SpExceptionEnum.UNKNOWN_ENTITY_EXCEPTION.getEntry();
|
| String txt = MessageFormat.format(SpMsg.TXT_STANDBY_LIST_WITH_ID,
|
| standbyBlueprintDto.getStandbyListId());
|
| ee.setMessage(MessageFormat.format(ee.getMessage(), txt));
|
| SpException spE = new SpException(ee);
|
| LOGGER.error(spE, spE);
|
| throw spE;
|
| }
|
| } else {
|
| SpErrorEntry ee = SpExceptionEnum.MISSING_PARAMETER_EXCEPTION.getEntry();
|
| ee.setMessage(MessageFormat.format(ee.getMessage(), "StandbyList"));
|
| SpException spE = new SpException(ee);
|
| LOGGER.error(spE, spE);
|
| throw spE;
|
| }
|
|
|
| if (standbyBlueprintDto.getStandbyGroupId() != null) {
|
| if (!standbyGroupRepository.exists(standbyBlueprintDto.getStandbyGroupId())) {
|
| SpErrorEntry ee = SpExceptionEnum.UNKNOWN_ENTITY_EXCEPTION.getEntry();
|
| String txt = MessageFormat.format(SpMsg.TXT_STANDBY_GROUP_WITH_ID,
|
| standbyBlueprintDto.getStandbyGroupId());
|
| ee.setMessage(MessageFormat.format(ee.getMessage(), txt));
|
| SpException spE = new SpException(ee);
|
| LOGGER.error(spE, spE);
|
| throw spE;
|
| }
|
| } else {
|
| SpErrorEntry ee = SpExceptionEnum.MISSING_PARAMETER_EXCEPTION.getEntry();
|
| ee.setMessage(MessageFormat.format(ee.getMessage(), "StandbyGroup"));
|
| SpException spE = new SpException(ee);
|
| LOGGER.error(spE, spE);
|
| throw spE;
|
| }
|
|
|
| if (standbyBlueprintDto.getValidFrom() == null) {
|
| SpErrorEntry ee = SpExceptionEnum.MISSING_PARAMETER_EXCEPTION.getEntry();
|
| ee.setMessage(MessageFormat.format(ee.getMessage(), "validFrom"));
|
| SpException spE = new SpException(ee);
|
| LOGGER.error(spE, spE);
|
| throw spE;
|
| }
|
|
|
| if (standbyBlueprintDto.getValidTo() == null) {
|
| SpErrorEntry ee = SpExceptionEnum.MISSING_PARAMETER_EXCEPTION.getEntry();
|
| ee.setMessage(MessageFormat.format(ee.getMessage(), "validTo"));
|
| SpException spE = new SpException(ee);
|
| LOGGER.error(spE, spE);
|
| throw spE;
|
| }
|
|
|
| return true;
|
| }
|
|
|
| /**
|
| * Method to log the phase map object.
|
| *
|
| * @param resultMap
|
| */
|
| public void logPhases(Map<Integer, PlanningPhaseDto> resultMap) {
|
| LOGGER.debug("The following " + resultMap.keySet().size() + " had been found");
|
| for (Entry<Integer, PlanningPhaseDto> entry : resultMap.entrySet()) {
|
| LOGGER.debug("-----------------------");
|
| LOGGER.debug("Phase :" + entry.getKey());
|
| LOGGER.debug("-----------------------");
|
| PlanningPhaseDto dto = entry.getValue();
|
| LOGGER.debug("StartDate :" + dto.getStartDate());
|
| LOGGER.debug("EndDate :" + dto.getEndDate());
|
| LOGGER.debug("Number of StandbyUser :" + dto.getLsUsers().size());
|
| for (UserInStandbyGroup uisg : dto.getLsUsers()) {
|
| LOGGER.debug("Gruppenmitglied :" + uisg.getUser().getFirstname() + " " + uisg.getUser().getLastname());
|
| }
|
| }
|
| }
|
|
|
| /**
|
| * Method to replace user in schedule bodies for the given interval
|
| *
|
| * @param actionDto
|
| * @param username
|
| * @return
|
| * @throws SpException
|
| */
|
| public PlanningMsgResponseDto replaceUserInPlan(StandbyScheduleActionDto actionDto, String username)
|
| throws SpException {
|
| PlanningMsgResponseDto responseDto = new PlanningMsgResponseDto();
|
| this.startWithNewList();
|
|
|
| // check input values
|
| List<Object> lsInputParams = new ArrayList<>();
|
| lsInputParams.add(actionDto.getCurrentUserId());
|
| lsInputParams.add(actionDto.getNewUserId());
|
| lsInputParams.add(actionDto.getStandbyGroupId());
|
| lsInputParams.add(actionDto.getStatusId());
|
| lsInputParams.add(actionDto.getValidFrom());
|
| lsInputParams.add(actionDto.getValidTo());
|
| lsInputParams.add(username);
|
| ValidationHelper.isNoNullValueInList(lsInputParams);
|
|
|
| try {
|
|
|
| // history
|
| archiveController.createArchiveOnReplaceInOneGroup(actionDto, username);
|
|
|
| User currentUser = userRepository.findOne(actionDto.getCurrentUserId());
|
| User newUser = userRepository.findOne(actionDto.getNewUserId());
|
| StandbyGroup standbyGroup = standbyGroupRepository.findOne(actionDto.getStandbyGroupId());
|
| Date from = actionDto.getValidFrom();
|
| Date to = actionDto.getValidTo();
|
|
|
| // mail
|
| mailing.replaceMessage1(actionDto, currentUser, newUser, standbyGroup);
|
| mailing.replaceMessage2(actionDto, currentUser, newUser, standbyGroup);
|
|
|
| ArrayList<StandbyGroup> lsStandbyGroups = new ArrayList<>();
|
| List<StandbyScheduleBody> lsBodies = standbyScheduleBodyRepository.findByUserAndGroupAndDateAndStatus(
|
| currentUser.getId(), actionDto.getStandbyGroupId(), DateHelper.getStartOfDay(from),
|
| DateHelper.getEndOfDay(to), actionDto.getStatusId());
|
|
|
| for (StandbyScheduleBody body : lsBodies) {
|
| this.splitScheduleBody(body, from, to, newUser, username);
|
| if (!lsStandbyGroups.contains(body.getStandbyGroup())) {
|
| lsStandbyGroups.add(body.getStandbyGroup());
|
| }
|
| }
|
|
|
| // start validation
|
| List<String> lsValidationBeanNames = new ArrayList<>();
|
| lsValidationBeanNames.add(ValidationController.BEAN_USER_AVAILABLE_VALIDATOR);
|
| lsValidationBeanNames.add(ValidationController.BEAN_USER_AVAILABLE_FOR_GROUP_VALIDATOR);
|
| lsValidationBeanNames.add(ValidationController.BEAN_GROUP_COVERAGE_VALIDATOR);
|
| lsValidationBeanNames.add(ValidationController.BEAN_DOUBLE_PLANNED_VALIDATOR);
|
| lsValidationBeanNames.add(ValidationController.BEAN_PLACEHOLDER_STANDBY_USER_VALIDATOR);
|
|
|
| responseDto.getLsMsg()
|
| .addAll(validatonController.startValidation(actionDto.getValidFrom(), actionDto.getValidTo(),
|
| lsStandbyGroups, lsValidationBeanNames, actionDto.getStatusId(), actionDto.getNewUserId()));
|
|
|
| return responseDto;
|
| } catch (Exception e) {
|
| LOGGER.error(e, e);
|
| SpErrorEntry ee = SpExceptionEnum.DEFAULT_EXCEPTION.getEntry();
|
| ee.setE(e);
|
| throw new SpException(ee);
|
| }
|
| }
|
|
|
| protected Boolean splitScheduleBody(StandbyScheduleBody body, Date from, Date to, User newUser, String modifiedBy)
|
| throws SpException {
|
| try {
|
| Date tmpFrom = from;
|
| Date tmpTo = to;
|
| if (DateHelper.isDateBefore(from, DateHelper.getStartOfDay(body.getValidFrom()))) {
|
| tmpFrom = DateHelper.getStartOfDay(body.getValidFrom());
|
| }
|
|
|
| if (DateHelper.isDateAfter(to, DateHelper.getEndOfDay(body.getValidFrom()))) {
|
| tmpTo = DateHelper.getEndOfDay(body.getValidFrom());
|
| }
|
|
|
| // interval of ui params
|
| Interval intervalSelection = new Interval(new DateTime(tmpFrom).getMillis(),
|
| new DateTime(tmpTo).getMillis());
|
|
|
| // interval of saved schedule body
|
| Interval intervalBody = new Interval(new DateTime(body.getValidFrom()).getMillis(),
|
| new DateTime(body.getValidTo()).getMillis());
|
|
|
| // overlapping interval between params and schedule body values
|
| Interval intervalOverlap = intervalBody.overlap(intervalSelection);
|
|
|
| if (intervalOverlap != null) {
|
| int isSameStart = DateHelper.isSameDateTime(body.getValidFrom(), tmpFrom);
|
| int isSameEnd = DateHelper.isSameDateTime(body.getValidTo(), tmpTo);
|
|
|
| tmpFrom = intervalOverlap.getStart().toDate();
|
| tmpTo = intervalOverlap.getEnd().toDate();
|
| if (isSameStart >= 0) {
|
| if (isSameEnd == 0) {
|
| // full replace
|
| body.setUser(newUser);
|
| body.setModifiedCause(TXT_MANUAL_CHANGE);
|
| body.setModificationDate(new Date());
|
| body.setModifiedBy(modifiedBy);
|
| standbyScheduleBodyRepository.save(body);
|
| } else if (isSameEnd < 0) {
|
| body.setUser(newUser);
|
| body.setModifiedCause(TXT_MANUAL_CHANGE);
|
| body.setModificationDate(new Date());
|
| body.setModifiedBy(modifiedBy);
|
| body.setValidTo(tmpTo);
|
| standbyScheduleBodyRepository.save(body);
|
| } else {
|
| StandbyScheduleBody newBody = body.copy();
|
| newBody.setUser(newUser);
|
| newBody.setModifiedCause(TXT_MANUAL_CHANGE);
|
| newBody.setModificationDate(new Date());
|
| newBody.setModifiedBy(modifiedBy);
|
| newBody.setValidTo(tmpTo);
|
| standbyScheduleBodyRepository.save(newBody);
|
|
|
| body.setValidFrom(tmpTo);
|
| body.setModifiedCause(TXT_MANUAL_CHANGE);
|
| body.setModificationDate(new Date());
|
| body.setModifiedBy(modifiedBy);
|
| standbyScheduleBodyRepository.save(body);
|
| }
|
| } else if (isSameEnd == 0) {
|
| StandbyScheduleBody newBody = body.copy();
|
| newBody.setUser(newUser);
|
| newBody.setModifiedCause(TXT_MANUAL_CHANGE);
|
| newBody.setModificationDate(new Date());
|
| newBody.setModifiedBy(modifiedBy);
|
| newBody.setValidFrom(tmpFrom);
|
| standbyScheduleBodyRepository.save(newBody);
|
|
|
| body.setValidTo(tmpFrom);
|
| body.setModifiedCause(TXT_MANUAL_CHANGE);
|
| body.setModificationDate(new Date());
|
| body.setModifiedBy(modifiedBy);
|
| standbyScheduleBodyRepository.save(body);
|
| } else if (isSameEnd < 0) {
|
| // replace with end at 23:59
|
| StandbyScheduleBody newBody = body.copy();
|
| newBody.setUser(newUser);
|
| newBody.setModifiedCause(TXT_MANUAL_CHANGE);
|
| newBody.setModificationDate(new Date());
|
| newBody.setModifiedBy(modifiedBy);
|
| newBody.setValidFrom(tmpFrom);
|
| newBody.setValidTo(tmpTo);
|
| standbyScheduleBodyRepository.save(newBody);
|
|
|
| body.setModifiedCause(TXT_MANUAL_CHANGE);
|
| body.setModificationDate(new Date());
|
| body.setModifiedBy(modifiedBy);
|
| body.setValidTo(tmpFrom);
|
| standbyScheduleBodyRepository.save(body);
|
| } else {
|
| // set new user (n1) between old (o1) existing entry by splitting it.
|
| // Looks like this [o1--n1--o2]
|
| StandbyScheduleBody newBody = body.copy();
|
| newBody.setUser(newUser);
|
| newBody.setModifiedCause(TXT_MANUAL_CHANGE);
|
| newBody.setModificationDate(new Date());
|
| newBody.setModifiedBy(modifiedBy);
|
| newBody.setValidFrom(tmpFrom);
|
| newBody.setValidTo(tmpTo);
|
| standbyScheduleBodyRepository.save(newBody);
|
|
|
| // set new entry to not loose the time after
|
| StandbyScheduleBody oldBodyAfter = body.copy();
|
| oldBodyAfter.setModifiedCause(TXT_MANUAL_CHANGE);
|
| oldBodyAfter.setModificationDate(new Date());
|
| oldBodyAfter.setModifiedBy(modifiedBy);
|
| oldBodyAfter.setValidFrom(tmpTo);
|
| standbyScheduleBodyRepository.save(oldBodyAfter);
|
|
|
| // set
|
| body.setModifiedCause(TXT_MANUAL_CHANGE);
|
| body.setModificationDate(new Date());
|
| body.setModifiedBy(modifiedBy);
|
| body.setValidTo(tmpFrom);
|
| standbyScheduleBodyRepository.save(body);
|
| }
|
| }
|
|
|
| return true;
|
| } catch (Exception e) {
|
| LOGGER.error(e, e);
|
| SpErrorEntry ee = SpExceptionEnum.DEFAULT_EXCEPTION.getEntry();
|
| ee.setE(e);
|
| throw new SpException(ee);
|
| }
|
| }
|
|
|
| /**
|
| * Method to change the time of a schedule body.
|
| *
|
| * @param actionDto
|
| * @param username
|
| * @return
|
| * @throws SpException
|
| */
|
| public PlanningMsgResponseDto moveUserInPlan(StandbyScheduleActionDto actionDto, String username)
|
| throws SpException {
|
| PlanningMsgResponseDto responseDto = new PlanningMsgResponseDto();
|
| this.startWithNewList();
|
|
|
| // check input values
|
| List<Object> lsInputParams = new ArrayList<>();
|
| lsInputParams.add(actionDto.getNewUserId());
|
| lsInputParams.add(actionDto.getScheduleBodyId());
|
| lsInputParams.add(actionDto.getValidFrom());
|
| lsInputParams.add(actionDto.getValidTo());
|
| lsInputParams.add(actionDto.getStandbyGroupId());
|
| lsInputParams.add(username);
|
| ValidationHelper.isNoNullValueInList(lsInputParams);
|
|
|
| StandbyGroup tempOldGroup = null;
|
| StandbyGroup tempNewGroup = null;
|
|
|
| try {
|
|
|
| // history
|
| archiveController.createArchiveOnMove(actionDto, username);
|
|
|
| StandbyScheduleBody body = standbyScheduleBodyRepository.findOne(actionDto.getScheduleBodyId());
|
| tempNewGroup = standbyGroupRepository.findOne(actionDto.getStandbyGroupId());
|
|
|
| // mail
|
| mailing.moveMessage1(actionDto, body, tempNewGroup);
|
|
|
| tempOldGroup = body.getStandbyGroup();
|
| body.setModifiedCause(SpMsg.ACT_STANDBY_MOVE);
|
| body.setModificationDate(new Date());
|
| body.setModifiedBy(username);
|
| body.setStandbyGroup(tempNewGroup);
|
|
|
| DateTime dt = new DateTime(actionDto.getValidTo());
|
| if (DateHelper.isSameDate(actionDto.getValidFrom(), dt.minusSeconds(1).toDate())) {
|
| // because of no overlapping day schedule body just
|
| // gets new values, no second body is needed.
|
| body.setValidFrom(actionDto.getValidFrom());
|
| body.setValidTo(actionDto.getValidTo());
|
| standbyScheduleBodyRepository.save(body);
|
|
|
| } else {
|
| Date nextDate = actionDto.getValidFrom();
|
| StandbyScheduleBody newBody = null;
|
| while (DateHelper.isDateBefore(nextDate, actionDto.getValidTo())
|
| && !DateHelper.isSameDate(nextDate, actionDto.getValidTo())) {
|
| newBody = body.copy();
|
| if (DateHelper.isSameDate(actionDto.getValidFrom(), nextDate)) {
|
| // do not change start time on first day
|
| newBody.setValidFrom(nextDate);
|
| } else {
|
| // begin with = 0:00 if not first day
|
| newBody.setValidFrom(DateHelper.getStartOfDay(nextDate));
|
| }
|
| newBody.setValidTo(DateHelper.getEndOfDay(nextDate));
|
| newBody.setModifiedCause(TXT_MANUAL_CHANGE);
|
| newBody.setModificationDate(new Date());
|
| newBody.setModifiedBy(username);
|
| newBody.setStandbyGroup(body.getStandbyGroup());
|
| standbyScheduleBodyRepository.save(newBody);
|
|
|
| nextDate = DateHelper.addDaysToDate(nextDate, 1);
|
| }
|
|
|
| // add last day
|
| StandbyScheduleBody lastBody = body.copy();
|
| lastBody.setValidFrom(DateHelper.getStartOfDay(actionDto.getValidTo()));
|
| lastBody.setValidTo(actionDto.getValidTo());
|
| lastBody.setModifiedCause(TXT_MANUAL_CHANGE);
|
| lastBody.setModificationDate(new Date());
|
| lastBody.setModifiedBy(username);
|
| lastBody.setStandbyGroup(body.getStandbyGroup());
|
| standbyScheduleBodyRepository.save(lastBody);
|
|
|
| // remove original because of splitting it to multiple entries
|
| standbyScheduleBodyRepository.delete(body.getId());
|
| }
|
|
|
| ArrayList<StandbyGroup> lsStandbyGroups = new ArrayList<>();
|
| lsStandbyGroups.add(tempOldGroup);
|
| // add new group to check list if it differs from origin group
|
| if (tempOldGroup.getId().longValue() != tempNewGroup.getId().longValue()) {
|
| lsStandbyGroups.add(tempNewGroup);
|
| }
|
|
|
| // start validation
|
| List<String> lsValidationBeanNames = new ArrayList<>();
|
| lsValidationBeanNames.add(ValidationController.BEAN_USER_AVAILABLE_VALIDATOR);
|
| lsValidationBeanNames.add(ValidationController.BEAN_USER_AVAILABLE_FOR_GROUP_VALIDATOR);
|
| lsValidationBeanNames.add(ValidationController.BEAN_GROUP_COVERAGE_VALIDATOR);
|
| lsValidationBeanNames.add(ValidationController.BEAN_DOUBLE_PLANNED_VALIDATOR);
|
| lsValidationBeanNames.add(ValidationController.BEAN_PLACEHOLDER_STANDBY_USER_VALIDATOR);
|
| responseDto.getLsMsg()
|
| .addAll(validatonController.startValidation(actionDto.getValidFrom(), actionDto.getValidTo(),
|
| lsStandbyGroups, lsValidationBeanNames, actionDto.getStatusId(), actionDto.getNewUserId()));
|
|
|
| return responseDto;
|
| } catch (Exception e) {
|
| LOGGER.error(e, e);
|
| SpErrorEntry ee = SpExceptionEnum.DEFAULT_EXCEPTION.getEntry();
|
| ee.setE(e);
|
| throw new SpException(ee);
|
| }
|
| }
|
|
|
| /**
|
| * Method to search for durations that will end at the day the current phase is
|
| * starting. Therefore maybe the end of durations that are starting the day
|
| * before will be found.
|
| *
|
| * @param lsFittingDurations
|
| * @param group
|
| * @param startDate
|
| * @param currentDate
|
| * @return
|
| */
|
| private List<StandbyDuration> appendEndingDurationsAtStartingPhase(List<StandbyDuration> lsFittingDurations,
|
| StandbyGroup group, Date startDate, Date currentDate) {
|
| // Only at the start of a new phase the ending durations have to be used, too.
|
| if (startDate.equals(currentDate)) {
|
| List<StandbyDuration> lsFittingDurationsEndingAtStart = this.getFittingDurationsAroundDate(group,
|
| currentDate);
|
| if (lsFittingDurationsEndingAtStart != null && !lsFittingDurationsEndingAtStart.isEmpty()) {
|
| for (StandbyDuration dur : lsFittingDurationsEndingAtStart) {
|
| int currentWeekDayInt = DateHelper.getDayOfWeek(currentDate);
|
| int startDurationWeekDayInt = dur.getValidDayFrom();
|
| // do not use durations that start at the current day because they will be found
|
| // in the normal calculation.
|
| if (startDurationWeekDayInt != currentWeekDayInt) {
|
| StandbyDuration tmpDuration = dur.copy();
|
| // set start to current day 00:00 because duration comes from day earlier.
|
| tmpDuration.setValidFrom(DateHelper.getStartOfDay(tmpDuration.getValidTo()));
|
| tmpDuration.setValidDayFrom(DateHelper.getDayOfWeek(currentDate));
|
| int endDurationWeekDayInt = dur.getValidDayTo();
|
| if (endDurationWeekDayInt == currentWeekDayInt) {
|
| // if durations ends current day use the end of duration
|
| tmpDuration.setValidDayTo(DateHelper.getDayOfWeek(currentDate));
|
| } else {
|
| // else use the end of day.
|
| tmpDuration.setValidDayTo(DateHelper.getDayOfWeek(currentDate));
|
| tmpDuration.setValidTo(DateHelper.getEndOfDay(currentDate));
|
| }
|
| lsFittingDurations.add(tmpDuration);
|
| }
|
| }
|
| }
|
| }
|
| return lsFittingDurations;
|
| }
|
|
|
| /**
|
| * Method to add PlanningMsgDtos to list and stop filling the list at an amount
|
| * bigger then 200 entries.
|
| */
|
| public void addMessagesToList(List<PlanningMsgDto> lsMsg) {
|
| for (PlanningMsgDto dto : lsMsg) {
|
| if (dto.getType().equals(PlanningMsgDto.INFO)) {
|
| lsPlanningMsg.add(dto);
|
| } else if (warningCounter < 200) {
|
| lsPlanningMsg.add(dto);
|
| warningCounter++;
|
| } else {
|
| PlanningMsgDto lastDto = lsPlanningMsg.get(lsPlanningMsg.size() - 1);
|
| if (!lastDto.getMsg().equals(TXT_AND_MORE)) {
|
| lsPlanningMsg.add(new PlanningMsgDto(TXT_AND_MORE, PlanningMsgDto.WARN, PlanningMsgDto.CSS_WARN));
|
| }
|
| }
|
| }
|
| }
|
|
|
| /**
|
| * Method to add a PlanningMsgDto to list.
|
| */
|
| public void addMessageToList(PlanningMsgDto msg) {
|
| List<PlanningMsgDto> lsMsg = new ArrayList<>();
|
| lsMsg.add(msg);
|
| this.addMessagesToList(lsMsg);
|
| }
|
|
|
| public List<PlanningMsgDto> getLsMsgDto() {
|
| return lsPlanningMsg;
|
| }
|
|
|
| public void startWithNewList() {
|
| lsPlanningMsg = new ArrayList<>();
|
| warningCounter = 0;
|
| }
|
|
|
| public int getWarningCounter() {
|
| return warningCounter;
|
| }
|
| }
|