Use DB snapshots the precalculate the data of the resource load graph in company screen.
We prevent doing the calculation when the graph is shown. Now it's done when the application starts, and updated when one of the involved entities changes. FEA: ItEr62S03RFPerformanceCompanyView
This commit is contained in:
parent
648e6d16fc
commit
fe671aded5
3 changed files with 302 additions and 129 deletions
|
|
@ -27,6 +27,10 @@ import java.util.concurrent.Callable;
|
|||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.navalplanner.business.calendars.entities.CalendarAvailability;
|
||||
import org.navalplanner.business.calendars.entities.CalendarData;
|
||||
import org.navalplanner.business.calendars.entities.CalendarException;
|
||||
import org.navalplanner.business.common.AdHocTransactionService;
|
||||
import org.navalplanner.business.common.IAdHocTransactionService;
|
||||
import org.navalplanner.business.costcategories.daos.ICostCategoryDAO;
|
||||
|
|
@ -39,6 +43,13 @@ import org.navalplanner.business.labels.entities.Label;
|
|||
import org.navalplanner.business.labels.entities.LabelType;
|
||||
import org.navalplanner.business.orders.daos.IOrderDAO;
|
||||
import org.navalplanner.business.orders.entities.Order;
|
||||
import org.navalplanner.business.planner.daos.IDayAssignmentDAO;
|
||||
import org.navalplanner.business.planner.entities.DayAssignment;
|
||||
import org.navalplanner.business.planner.entities.GenericResourceAllocation;
|
||||
import org.navalplanner.business.planner.entities.ResourceAllocation;
|
||||
import org.navalplanner.business.planner.entities.ResourceLoadChartData;
|
||||
import org.navalplanner.business.planner.entities.SpecificResourceAllocation;
|
||||
import org.navalplanner.business.planner.entities.TaskElement;
|
||||
import org.navalplanner.business.resources.daos.ICriterionDAO;
|
||||
import org.navalplanner.business.resources.daos.ICriterionTypeDAO;
|
||||
import org.navalplanner.business.resources.daos.IResourceDAO;
|
||||
|
|
@ -49,6 +60,7 @@ import org.navalplanner.business.resources.entities.Machine;
|
|||
import org.navalplanner.business.resources.entities.Resource;
|
||||
import org.navalplanner.business.resources.entities.VirtualWorker;
|
||||
import org.navalplanner.business.resources.entities.Worker;
|
||||
import org.navalplanner.business.scenarios.IScenarioManager;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
|
|
@ -125,6 +137,13 @@ public class PredefinedDatabaseSnapshots {
|
|||
return ordersCodes.getValue();
|
||||
}
|
||||
|
||||
private IAutoUpdatedSnapshot<ResourceLoadChartData>
|
||||
resourceLoadChartData;
|
||||
|
||||
public ResourceLoadChartData snapshotResourceLoadChartData() {
|
||||
return resourceLoadChartData.getValue();
|
||||
}
|
||||
|
||||
private boolean snapshotsRegistered = false;
|
||||
|
||||
public void registerSnapshots() {
|
||||
|
|
@ -153,6 +172,11 @@ public class PredefinedDatabaseSnapshots {
|
|||
calculateCustomerReferences(), Order.class);
|
||||
ordersCodes = snapshot("order codes", calculateOrdersCodes(),
|
||||
Order.class);
|
||||
resourceLoadChartData = snapshot("resource load grouped by date",
|
||||
calculateResourceLoadChartData(),
|
||||
CalendarAvailability.class, CalendarException.class,
|
||||
CalendarData.class, TaskElement.class, SpecificResourceAllocation.class,
|
||||
GenericResourceAllocation.class, ResourceAllocation.class);
|
||||
}
|
||||
|
||||
private <T> IAutoUpdatedSnapshot<T> snapshot(String name,
|
||||
|
|
@ -311,4 +335,25 @@ public class PredefinedDatabaseSnapshots {
|
|||
};
|
||||
}
|
||||
|
||||
@Autowired
|
||||
private IDayAssignmentDAO dayAssignmentDAO;
|
||||
|
||||
@Autowired
|
||||
private IScenarioManager scenarioManager;
|
||||
|
||||
private Callable<ResourceLoadChartData> calculateResourceLoadChartData() {
|
||||
return new Callable<ResourceLoadChartData>() {
|
||||
@Override
|
||||
public ResourceLoadChartData call()
|
||||
throws Exception {
|
||||
|
||||
List<DayAssignment> dayAssignments = dayAssignmentDAO.getAllFor(
|
||||
scenarioManager.getCurrent(), null, null);
|
||||
List<Resource> resources = resourceDAO.list(Resource.class);
|
||||
return new ResourceLoadChartData(dayAssignments, resources);
|
||||
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,248 @@
|
|||
/*
|
||||
* This file is part of NavalPlan
|
||||
*
|
||||
* Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e
|
||||
* Desenvolvemento Tecnolóxico de Galicia
|
||||
*
|
||||
* This program 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.navalplanner.business.planner.entities;
|
||||
|
||||
import static org.navalplanner.business.workingday.EffortDuration.min;
|
||||
import static org.navalplanner.business.workingday.EffortDuration.zero;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.SortedMap;
|
||||
import java.util.TreeMap;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.joda.time.LocalDate;
|
||||
import org.navalplanner.business.calendars.entities.BaseCalendar;
|
||||
import org.navalplanner.business.calendars.entities.ICalendar;
|
||||
import org.navalplanner.business.calendars.entities.SameWorkHoursEveryDay;
|
||||
import org.navalplanner.business.resources.entities.Resource;
|
||||
import org.navalplanner.business.workingday.EffortDuration;
|
||||
import org.navalplanner.business.workingday.IntraDayDate.PartialDay;
|
||||
|
||||
/**
|
||||
* This class groups the calculation of the three values needed for the
|
||||
* chart of the company global resource load. The purpose of the class is
|
||||
* having these data pre-calculated to prevent heavy algorithms being
|
||||
* run each time the chart is shown.
|
||||
* @see PredefinedDatabaseSnapshots
|
||||
* @author Jacobo Aragunde Pérez<jaragunde@igalia.com>
|
||||
*
|
||||
*/
|
||||
public class ResourceLoadChartData {
|
||||
|
||||
private SortedMap<LocalDate, EffortDuration> load;
|
||||
|
||||
private SortedMap<LocalDate, EffortDuration> overload;
|
||||
|
||||
private SortedMap<LocalDate, EffortDuration> availability;
|
||||
|
||||
public ResourceLoadChartData(List<DayAssignment> dayAssignments, List<Resource> resources) {
|
||||
SortedMap<LocalDate, Map<Resource, EffortDuration>> map =
|
||||
groupDurationsByDayAndResource(dayAssignments);
|
||||
this.load = calculateResourceLoadPerDate(map);
|
||||
this.overload = calculateResourceOverloadPerDate(map);
|
||||
if(load.keySet().isEmpty()) {
|
||||
this.availability = new TreeMap<LocalDate, EffortDuration>();
|
||||
}
|
||||
else {
|
||||
this.availability = calculateAvailabilityDurationByDay(
|
||||
resources, load.firstKey(), load.lastKey());
|
||||
}
|
||||
|
||||
for (LocalDate day : this.overload.keySet()) {
|
||||
EffortDuration overloadDuration = this.overload
|
||||
.get(day);
|
||||
EffortDuration maxDuration = this.availability.get(day);
|
||||
this.overload.put(day,
|
||||
overloadDuration.plus(maxDuration));
|
||||
}
|
||||
}
|
||||
|
||||
public SortedMap<LocalDate, EffortDuration> getLoad() {
|
||||
return load;
|
||||
}
|
||||
|
||||
public SortedMap<LocalDate, EffortDuration> getOverload() {
|
||||
return overload;
|
||||
}
|
||||
|
||||
public SortedMap<LocalDate, EffortDuration> getAvailability() {
|
||||
return availability;
|
||||
}
|
||||
|
||||
private SortedMap<LocalDate, Map<Resource, EffortDuration>> groupDurationsByDayAndResource(
|
||||
List<DayAssignment> dayAssignments) {
|
||||
SortedMap<LocalDate, Map<Resource, EffortDuration>> map =
|
||||
new TreeMap<LocalDate, Map<Resource, EffortDuration>>();
|
||||
|
||||
for (DayAssignment dayAssignment : dayAssignments) {
|
||||
final LocalDate day = dayAssignment.getDay();
|
||||
final EffortDuration dayAssignmentDuration = dayAssignment
|
||||
.getDuration();
|
||||
Resource resource = dayAssignment.getResource();
|
||||
if (map.get(day) == null) {
|
||||
map.put(day, new HashMap<Resource, EffortDuration>());
|
||||
}
|
||||
Map<Resource, EffortDuration> forDay = map.get(day);
|
||||
EffortDuration previousDuration = forDay.get(resource);
|
||||
previousDuration = previousDuration != null ? previousDuration
|
||||
: EffortDuration.zero();
|
||||
forDay.put(dayAssignment.getResource(),
|
||||
previousDuration.plus(dayAssignmentDuration));
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
private SortedMap<LocalDate, EffortDuration> calculateResourceLoadPerDate(
|
||||
SortedMap<LocalDate, Map<Resource, EffortDuration>> durationsGrouped) {
|
||||
SortedMap<LocalDate, EffortDuration> map = new TreeMap<LocalDate, EffortDuration>();
|
||||
|
||||
for (LocalDate date : durationsGrouped.keySet()) {
|
||||
EffortDuration result = zero();
|
||||
PartialDay day = PartialDay.wholeDay(date);
|
||||
for (Resource resource : durationsGrouped.get(date).keySet()) {
|
||||
ICalendar calendar = resource.getCalendarOrDefault();
|
||||
EffortDuration workableTime = calendar.getCapacityOn(day);
|
||||
EffortDuration assignedDuration = durationsGrouped.get(
|
||||
day.getDate()).get(resource);
|
||||
result = result.plus(min(assignedDuration, workableTime));
|
||||
}
|
||||
|
||||
map.put(date, result);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
protected abstract class EffortByDayCalculator<T> {
|
||||
public SortedMap<LocalDate, EffortDuration> calculate(
|
||||
Collection<? extends T> elements) {
|
||||
SortedMap<LocalDate, EffortDuration> result = new TreeMap<LocalDate, EffortDuration>();
|
||||
if (elements.isEmpty()) {
|
||||
return result;
|
||||
}
|
||||
for (T element : elements) {
|
||||
if (included(element)) {
|
||||
EffortDuration duration = getDurationFor(element);
|
||||
LocalDate day = getDayFor(element);
|
||||
EffortDuration previous = result.get(day);
|
||||
previous = previous == null ? zero() : previous;
|
||||
result.put(day, previous.plus(duration));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
protected abstract LocalDate getDayFor(T element);
|
||||
|
||||
protected abstract EffortDuration getDurationFor(T element);
|
||||
|
||||
protected boolean included(T each) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private SortedMap<LocalDate, EffortDuration> calculateResourceOverloadPerDate(
|
||||
SortedMap<LocalDate, Map<Resource, EffortDuration>> dayAssignmentGrouped) {
|
||||
return new EffortByDayCalculator<Entry<LocalDate, Map<Resource, EffortDuration>>>() {
|
||||
|
||||
@Override
|
||||
protected LocalDate getDayFor(
|
||||
Entry<LocalDate, Map<Resource, EffortDuration>> element) {
|
||||
return element.getKey();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected EffortDuration getDurationFor(
|
||||
Entry<LocalDate, Map<Resource, EffortDuration>> element) {
|
||||
EffortDuration result = zero();
|
||||
PartialDay day = PartialDay.wholeDay(element.getKey());
|
||||
for (Entry<Resource, EffortDuration> each : element.getValue()
|
||||
.entrySet()) {
|
||||
EffortDuration overlad = getOverloadAt(day,
|
||||
each.getKey(),
|
||||
each.getValue());
|
||||
result = result.plus(overlad);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private EffortDuration getOverloadAt(PartialDay day,
|
||||
Resource resource, EffortDuration assignedDuration) {
|
||||
ICalendar calendar = resource.getCalendarOrDefault();
|
||||
EffortDuration workableDuration = calendar
|
||||
.getCapacityOn(day);
|
||||
if (assignedDuration.compareTo(workableDuration) > 0) {
|
||||
return assignedDuration.minus(workableDuration);
|
||||
}
|
||||
return zero();
|
||||
}
|
||||
}.calculate(dayAssignmentGrouped.entrySet());
|
||||
}
|
||||
|
||||
private SortedMap<LocalDate, EffortDuration> calculateAvailabilityDurationByDay(
|
||||
final List<Resource> resources, LocalDate start, LocalDate finish) {
|
||||
return new EffortByDayCalculator<Entry<LocalDate, List<Resource>>>() {
|
||||
|
||||
@Override
|
||||
protected LocalDate getDayFor(
|
||||
Entry<LocalDate, List<Resource>> element) {
|
||||
return element.getKey();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected EffortDuration getDurationFor(
|
||||
Entry<LocalDate, List<Resource>> element) {
|
||||
LocalDate day = element.getKey();
|
||||
return sumCalendarCapacitiesForDay(resources, day);
|
||||
}
|
||||
|
||||
}.calculate(getResourcesByDateBetween(resources, start, finish));
|
||||
}
|
||||
|
||||
protected static EffortDuration sumCalendarCapacitiesForDay(
|
||||
Collection<? extends Resource> resources, LocalDate day) {
|
||||
PartialDay wholeDay = PartialDay.wholeDay(day);
|
||||
EffortDuration sum = zero();
|
||||
for (Resource resource : resources) {
|
||||
sum = sum.plus(calendarCapacityFor(resource,
|
||||
wholeDay));
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
protected static EffortDuration calendarCapacityFor(Resource resource,
|
||||
PartialDay day) {
|
||||
return resource.getCalendarOrDefault().getCapacityOn(day);
|
||||
}
|
||||
|
||||
private Set<Entry<LocalDate, List<Resource>>> getResourcesByDateBetween(
|
||||
List<Resource> resources, LocalDate start, LocalDate finish) {
|
||||
Map<LocalDate, List<Resource>> result = new HashMap<LocalDate, List<Resource>>();
|
||||
for (LocalDate date = new LocalDate(start); date.compareTo(finish) <= 0; date = date
|
||||
.plusDays(1)) {
|
||||
result.put(date, resources);
|
||||
}
|
||||
return result.entrySet();
|
||||
}
|
||||
}
|
||||
|
|
@ -20,8 +20,6 @@
|
|||
|
||||
package org.navalplanner.web.planner.company;
|
||||
|
||||
import static org.navalplanner.business.workingday.EffortDuration.min;
|
||||
import static org.navalplanner.business.workingday.EffortDuration.zero;
|
||||
import static org.navalplanner.web.I18nHelper._;
|
||||
import static org.navalplanner.web.resourceload.ResourceLoadModel.asDate;
|
||||
|
||||
|
|
@ -36,30 +34,25 @@ import java.util.HashMap;
|
|||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.SortedMap;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import org.joda.time.LocalDate;
|
||||
import org.navalplanner.business.calendars.entities.ICalendar;
|
||||
import org.navalplanner.business.common.IAdHocTransactionService;
|
||||
import org.navalplanner.business.common.IOnTransaction;
|
||||
import org.navalplanner.business.common.daos.IConfigurationDAO;
|
||||
import org.navalplanner.business.common.exceptions.InstanceNotFoundException;
|
||||
import org.navalplanner.business.hibernate.notification.PredefinedDatabaseSnapshots;
|
||||
import org.navalplanner.business.orders.daos.IOrderDAO;
|
||||
import org.navalplanner.business.orders.entities.Order;
|
||||
import org.navalplanner.business.orders.entities.OrderStatusEnum;
|
||||
import org.navalplanner.business.planner.daos.IDayAssignmentDAO;
|
||||
import org.navalplanner.business.planner.daos.ITaskElementDAO;
|
||||
import org.navalplanner.business.planner.entities.DayAssignment;
|
||||
import org.navalplanner.business.planner.entities.ICostCalculator;
|
||||
import org.navalplanner.business.planner.entities.Task;
|
||||
import org.navalplanner.business.planner.entities.TaskElement;
|
||||
import org.navalplanner.business.planner.entities.TaskGroup;
|
||||
import org.navalplanner.business.planner.entities.TaskMilestone;
|
||||
import org.navalplanner.business.resources.daos.IResourceDAO;
|
||||
import org.navalplanner.business.resources.entities.Resource;
|
||||
import org.navalplanner.business.scenarios.IScenarioManager;
|
||||
import org.navalplanner.business.scenarios.entities.Scenario;
|
||||
import org.navalplanner.business.templates.entities.OrderTemplate;
|
||||
|
|
@ -140,12 +133,6 @@ public abstract class CompanyPlanningModel implements ICompanyPlanningModel {
|
|||
@Autowired
|
||||
private IOrderDAO orderDAO;
|
||||
|
||||
@Autowired
|
||||
private IResourceDAO resourceDAO;
|
||||
|
||||
@Autowired
|
||||
private IDayAssignmentDAO dayAssignmentDAO;
|
||||
|
||||
@Autowired
|
||||
private ITaskElementDAO taskElementDAO;
|
||||
|
||||
|
|
@ -177,6 +164,9 @@ public abstract class CompanyPlanningModel implements ICompanyPlanningModel {
|
|||
|
||||
private Scenario currentScenario;
|
||||
|
||||
@Autowired
|
||||
private PredefinedDatabaseSnapshots databaseSnapshots;
|
||||
|
||||
private LocalDate filterStartDate;
|
||||
private LocalDate filterFinishDate;
|
||||
private static final EnumSet<OrderStatusEnum> STATUS_VISUALIZED = EnumSet
|
||||
|
|
@ -817,129 +807,19 @@ public abstract class CompanyPlanningModel implements ICompanyPlanningModel {
|
|||
|
||||
private SortedMap<LocalDate, EffortDuration> getLoad(LocalDate start,
|
||||
LocalDate finish) {
|
||||
List<DayAssignment> dayAssignments = dayAssignmentDAO.getAllFor(
|
||||
currentScenario, start, finish);
|
||||
SortedMap<LocalDate, Map<Resource, EffortDuration>> durationsGrouped = groupDurationsByDayAndResource(dayAssignments);
|
||||
return calculateHoursAdditionByDayWithoutOverload(durationsGrouped);
|
||||
return groupAsNeededByZoom(databaseSnapshots.
|
||||
snapshotResourceLoadChartData().getLoad().subMap(start, finish));
|
||||
}
|
||||
|
||||
private SortedMap<LocalDate, EffortDuration> getOverload(
|
||||
LocalDate start, LocalDate finish) {
|
||||
List<DayAssignment> dayAssignments = dayAssignmentDAO.getAllFor(
|
||||
currentScenario, start, finish);
|
||||
|
||||
SortedMap<LocalDate, Map<Resource, EffortDuration>> dayAssignmentGrouped = groupDurationsByDayAndResource(dayAssignments);
|
||||
SortedMap<LocalDate, EffortDuration> mapDayAssignments = calculateHoursAdditionByDayJustOverload(dayAssignmentGrouped);
|
||||
SortedMap<LocalDate, EffortDuration> mapMaxAvailability = calculateAvailabilityDurationByDay(
|
||||
resourceDAO.list(Resource.class), start, finish);
|
||||
|
||||
for (LocalDate day : mapDayAssignments.keySet()) {
|
||||
if (day.compareTo(new LocalDate(start)) >= 0
|
||||
&& day.compareTo(new LocalDate(finish)) <= 0) {
|
||||
EffortDuration overloadDuration = mapDayAssignments
|
||||
.get(day);
|
||||
EffortDuration maxDuration = mapMaxAvailability.get(day);
|
||||
mapDayAssignments.put(day,
|
||||
overloadDuration.plus(maxDuration));
|
||||
}
|
||||
}
|
||||
|
||||
return mapDayAssignments;
|
||||
}
|
||||
|
||||
private SortedMap<LocalDate, EffortDuration> calculateHoursAdditionByDayWithoutOverload(
|
||||
SortedMap<LocalDate, Map<Resource, EffortDuration>> durationsGrouped) {
|
||||
SortedMap<LocalDate, EffortDuration> map = new TreeMap<LocalDate, EffortDuration>();
|
||||
|
||||
for (LocalDate date : durationsGrouped.keySet()) {
|
||||
EffortDuration result = zero();
|
||||
PartialDay day = PartialDay.wholeDay(date);
|
||||
for (Resource resource : durationsGrouped.get(date).keySet()) {
|
||||
ICalendar calendar = resource.getCalendarOrDefault();
|
||||
EffortDuration workableTime = calendar.getCapacityOn(day);
|
||||
EffortDuration assignedDuration = durationsGrouped.get(
|
||||
day.getDate()).get(resource);
|
||||
result = result.plus(min(assignedDuration, workableTime));
|
||||
}
|
||||
|
||||
map.put(date, result);
|
||||
}
|
||||
return groupAsNeededByZoom(map);
|
||||
}
|
||||
|
||||
private SortedMap<LocalDate, EffortDuration> calculateHoursAdditionByDayJustOverload(
|
||||
SortedMap<LocalDate, Map<Resource, EffortDuration>> dayAssignmentGrouped) {
|
||||
return new EffortByDayCalculator<Entry<LocalDate, Map<Resource, EffortDuration>>>() {
|
||||
|
||||
@Override
|
||||
protected LocalDate getDayFor(
|
||||
Entry<LocalDate, Map<Resource, EffortDuration>> element) {
|
||||
return element.getKey();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected EffortDuration getDurationFor(
|
||||
Entry<LocalDate, Map<Resource, EffortDuration>> element) {
|
||||
EffortDuration result = zero();
|
||||
PartialDay day = PartialDay.wholeDay(element.getKey());
|
||||
for (Entry<Resource, EffortDuration> each : element.getValue()
|
||||
.entrySet()) {
|
||||
EffortDuration overlad = getOverloadAt(day,
|
||||
each.getKey(),
|
||||
each.getValue());
|
||||
result = result.plus(overlad);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private EffortDuration getOverloadAt(PartialDay day,
|
||||
Resource resource, EffortDuration assignedDuration) {
|
||||
ICalendar calendar = resource.getCalendarOrDefault();
|
||||
EffortDuration workableDuration = calendar
|
||||
.getCapacityOn(day);
|
||||
if (assignedDuration.compareTo(workableDuration) > 0) {
|
||||
return assignedDuration.minus(workableDuration);
|
||||
}
|
||||
return zero();
|
||||
}
|
||||
}.calculate(dayAssignmentGrouped.entrySet());
|
||||
return groupAsNeededByZoom(
|
||||
databaseSnapshots.snapshotResourceLoadChartData().getOverload().subMap(start, finish));
|
||||
}
|
||||
|
||||
private SortedMap<LocalDate, EffortDuration> getCalendarMaximumAvailability(
|
||||
LocalDate start, LocalDate finish) {
|
||||
return calculateAvailabilityDurationByDay(
|
||||
resourceDAO.list(Resource.class), start, finish);
|
||||
}
|
||||
|
||||
private SortedMap<LocalDate, EffortDuration> calculateAvailabilityDurationByDay(
|
||||
List<Resource> resources, LocalDate start, LocalDate finish) {
|
||||
return new EffortByDayCalculator<Entry<LocalDate, List<Resource>>>() {
|
||||
|
||||
@Override
|
||||
protected LocalDate getDayFor(
|
||||
Entry<LocalDate, List<Resource>> element) {
|
||||
return element.getKey();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected EffortDuration getDurationFor(
|
||||
Entry<LocalDate, List<Resource>> element) {
|
||||
LocalDate day = element.getKey();
|
||||
List<Resource> resources = element.getValue();
|
||||
return sumCalendarCapacitiesForDay(resources, day);
|
||||
}
|
||||
|
||||
}.calculate(getResourcesByDateBetween(resources, start, finish));
|
||||
}
|
||||
|
||||
private Set<Entry<LocalDate, List<Resource>>> getResourcesByDateBetween(
|
||||
List<Resource> resources, LocalDate start, LocalDate finish) {
|
||||
Map<LocalDate, List<Resource>> result = new HashMap<LocalDate, List<Resource>>();
|
||||
for (LocalDate date = new LocalDate(start); date.compareTo(finish) <= 0; date = date
|
||||
.plusDays(1)) {
|
||||
result.put(date, resources);
|
||||
}
|
||||
return result.entrySet();
|
||||
return databaseSnapshots.snapshotResourceLoadChartData().getAvailability().subMap(start, finish);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue