/**
* ***************************************************************************
* Copyright (c) 2010 Qcadoo Limited
* Project: Qcadoo MES
* Version: 1.4
*
* This file is part of Qcadoo.
*
* Qcadoo is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation; either version 3 of the License,
* or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
* ***************************************************************************
*/
package com.qcadoo.mes.productionPerShift;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.LocalDate;
import org.springframework.stereotype.Service;
import com.google.common.collect.Lists;
import com.qcadoo.commons.dateTime.TimeRange;
import com.qcadoo.mes.basic.constants.ShiftFields;
import com.qcadoo.mes.basic.constants.ShiftTimetableExceptionFields;
import com.qcadoo.mes.basic.constants.TimetableExceptionType;
import com.qcadoo.mes.basic.shift.Shift;
import com.qcadoo.mes.orders.constants.OrderFields;
import com.qcadoo.mes.productionPerShift.constants.DailyProgressFields;
import com.qcadoo.model.api.Entity;
@Service
public class PpsTimeHelper {
public Date findFinishDate(final Entity dailyProgress, Date dateOfDay, Entity order) {
DateTime endDate = null;
DateTime dateOfDayDT = new DateTime(dateOfDay, DateTimeZone.getDefault());
DateTime orderStartDate = new DateTime(order.getDateField(OrderFields.START_DATE), DateTimeZone.getDefault());
Entity shiftEntity = dailyProgress.getBelongsToField(DailyProgressFields.SHIFT);
Shift shift = new Shift(shiftEntity);
int time = dailyProgress.getIntegerField(DailyProgressFields.EFFICIENCY_TIME);
List<TimeRange> shiftWorkTime = Lists.newArrayList();
List<DateTimeRange> shiftWorkDateTime = Lists.newArrayList();
if (shift.worksAt(dateOfDay.getDay() == 0 ? 7 : dateOfDay.getDay())) {
shiftWorkTime = shift.findWorkTimeAt(new LocalDate(dateOfDay));
}
for (TimeRange range : shiftWorkTime) {
DateTimeRange dateTimeRange = new DateTimeRange(dateOfDayDT, range);
DateTimeRange trimmedRange = dateTimeRange.trimBefore(orderStartDate);
if (trimmedRange != null) {
shiftWorkDateTime.add(trimmedRange);
}
}
shiftWorkDateTime = manageExceptions(shiftWorkDateTime, shift.getEntity(), dateOfDay);
for (DateTimeRange range : shiftWorkDateTime) {
if (range.durationInMins() >= time && time > 0) {
endDate = range.getFrom().plusMinutes(time);
time = 0;
} else {
endDate = range.getTo();
time -= range.durationInMins();
}
}
return endDate != null ? endDate.toDate() : null;
}
public List<DateTimeRange> manageExceptions(List<DateTimeRange> shiftWorkDateTime, Entity shiftEntity, Date dateOfDay) {
List<Entity> exceptions = Lists.newArrayList(shiftEntity.getHasManyField(ShiftFields.TIMETABLE_EXCEPTIONS));
if (!exceptions.isEmpty()) {
trimWorkExceptions(exceptions, dateOfDay);
for (Entity exception : exceptions) {
if (TimetableExceptionType.FREE_TIME.getStringValue().equals(
exception.getStringField(ShiftTimetableExceptionFields.TYPE))) {
shiftWorkDateTime = removeFreeTimeException(shiftWorkDateTime, exception);
}
}
for (Entity exception : exceptions) {
if (TimetableExceptionType.WORK_TIME.getStringValue().equals(
exception.getStringField(ShiftTimetableExceptionFields.TYPE))) {
shiftWorkDateTime = addWorkTimeException(shiftWorkDateTime, exception);
}
}
}
return shiftWorkDateTime;
}
private void trimWorkExceptions(final List<Entity> exceptions, Date dateOfDay) {
Date dayStart = new Date(dateOfDay.getYear(), dateOfDay.getMonth(), dateOfDay.getDate());
Date dayEnd = new Date(dayStart.getTime() + TimeUnit.DAYS.toMillis(1));
Date nextDayEnd = new Date(dayEnd.getTime() + TimeUnit.DAYS.toMillis(1));
List<Entity> hoursToRemove = Lists.newArrayList();
for (Entity exception : exceptions) {
if (TimetableExceptionType.WORK_TIME.getStringValue().equals(
exception.getStringField(ShiftTimetableExceptionFields.TYPE))) {
Date fromDate = exception.getDateField(ShiftTimetableExceptionFields.FROM_DATE);
Boolean relatesToPrevDay = exception.getBooleanField(ShiftTimetableExceptionFields.RELATES_TO_PREV_DAY);
if (!relatesToPrevDay && (fromDate.before(dayStart) || !fromDate.before(dayEnd))) {
hoursToRemove.add(exception);
}
if (relatesToPrevDay && (fromDate.before(dayEnd) || !fromDate.before(nextDayEnd))) {
hoursToRemove.add(exception);
}
}
}
exceptions.removeAll(hoursToRemove);
}
private List<DateTimeRange> removeFreeTimeException(final List<DateTimeRange> shiftWorkDateTime, final Entity exception) {
Date fromDate = exception.getDateField(ShiftTimetableExceptionFields.FROM_DATE);
Date toDate = exception.getDateField(ShiftTimetableExceptionFields.TO_DATE);
DateTimeRange exceptionRange = new DateTimeRange(fromDate, toDate);
List<DateTimeRange> result = Lists.newArrayList();
for (DateTimeRange range : shiftWorkDateTime) {
result.addAll(range.remove(exceptionRange));
}
return result;
}
private List<DateTimeRange> addWorkTimeException(List<DateTimeRange> shiftWorkDateTime, final Entity exception) {
Date fromDate = exception.getDateField(ShiftTimetableExceptionFields.FROM_DATE);
Date toDate = exception.getDateField(ShiftTimetableExceptionFields.TO_DATE);
DateTimeRange exceptionRange = new DateTimeRange(fromDate, toDate);
if (shiftWorkDateTime.isEmpty()) {
return Lists.newArrayList(exceptionRange);
}
List<DateTimeRange> result = Lists.newArrayList();
for (DateTimeRange range : shiftWorkDateTime) {
result.addAll(range.add(exceptionRange));
}
return result;
}
}