ItEr58S10CUAsignacionRecursosLimitantesItEr57S11: Manual allocation of queue element
This commit is contained in:
parent
b76faa2411
commit
c89672c6d1
6 changed files with 496 additions and 43 deletions
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
package org.navalplanner.business.planner.entities;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.joda.time.LocalDate;
|
||||
|
||||
/**
|
||||
|
|
@ -34,6 +35,7 @@ public class DateAndHour implements Comparable<DateAndHour> {
|
|||
private Integer hour;
|
||||
|
||||
public DateAndHour(LocalDate date, Integer hour) {
|
||||
Validate.notNull(date);
|
||||
this.date = date;
|
||||
this.hour = hour;
|
||||
}
|
||||
|
|
@ -47,9 +49,10 @@ public class DateAndHour implements Comparable<DateAndHour> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(DateAndHour dateAndTime) {
|
||||
int compareDate = date.compareTo(getDate(dateAndTime));
|
||||
return (compareDate != 0) ? compareDate : compareHour(dateAndTime
|
||||
public int compareTo(DateAndHour time) {
|
||||
Validate.notNull(time);
|
||||
int compareDate = date.compareTo(getDate(time));
|
||||
return (compareDate != 0) ? compareDate : compareHour(time
|
||||
.getHour());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@ package org.navalplanner.business.planner.entities;
|
|||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
|
@ -72,12 +71,13 @@ public class LimitingResourceAllocator {
|
|||
final List<LimitingResourceQueueElement> elements = new LinkedList<LimitingResourceQueueElement>(
|
||||
queue.getLimitingResourceQueueElements());
|
||||
final int size = elements.size();
|
||||
final DateAndHour startTime = getStartTimeBecauseOfGantt(element);
|
||||
|
||||
// Iterate through queue elements
|
||||
int pos = 0;
|
||||
do {
|
||||
LimitingResourceQueueElementGap gap = getGapInQueueAtPosition(
|
||||
resource, elements, element, pos++);
|
||||
resource, elements, startTime, pos++);
|
||||
|
||||
// The queue cannot hold this element (queue.resource
|
||||
// doesn't meet element.criteria)
|
||||
|
|
@ -85,28 +85,85 @@ public class LimitingResourceAllocator {
|
|||
return null;
|
||||
}
|
||||
|
||||
if (isSpecific(element) && gap.canFit(element)) {
|
||||
return gap;
|
||||
} else if (isGeneric(element)){
|
||||
final List<LimitingResourceQueueElementGap> gaps = splitIntoGapsSatisfyingCriteria(
|
||||
resource, getCriteria(element), gap);
|
||||
for (LimitingResourceQueueElementGap subGap: gaps) {
|
||||
if (subGap.canFit(element)) {
|
||||
return subGap;
|
||||
}
|
||||
}
|
||||
List<LimitingResourceQueueElementGap> subgaps = getFittingSubgaps(element, gap, resource);
|
||||
if (!subgaps.isEmpty()) {
|
||||
return subgaps.get(0);
|
||||
}
|
||||
} while (pos <= size);
|
||||
|
||||
} while (pos < size);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void print(List<Criterion> criteria) {
|
||||
System.out.println("### print");
|
||||
for (Criterion each: criteria) {
|
||||
System.out.println("### each: " + each);
|
||||
|
||||
private static List<LimitingResourceQueueElementGap> getFittingSubgaps(
|
||||
LimitingResourceQueueElement element,
|
||||
final LimitingResourceQueueElementGap gap, final Resource resource) {
|
||||
|
||||
List<LimitingResourceQueueElementGap> result = new ArrayList<LimitingResourceQueueElementGap>();
|
||||
|
||||
if (isSpecific(element) && gap.canFit(element)) {
|
||||
result.add(gap);
|
||||
} else if (isGeneric(element)) {
|
||||
final List<LimitingResourceQueueElementGap> gaps = splitIntoGapsSatisfyingCriteria(
|
||||
resource, getCriteria(element), gap);
|
||||
for (LimitingResourceQueueElementGap subgap : gaps) {
|
||||
if (subgap.canFit(element)) {
|
||||
result.add(subgap);
|
||||
}
|
||||
}
|
||||
}
|
||||
System.out.println("### ");
|
||||
return result;
|
||||
}
|
||||
|
||||
public static List<LimitingResourceQueueElementGap> getValidGapsForElementSince(
|
||||
LimitingResourceQueueElement element, LimitingResourceQueue queue,
|
||||
DateAndHour since) {
|
||||
|
||||
List<LimitingResourceQueueElementGap> result = new ArrayList<LimitingResourceQueueElementGap>();
|
||||
|
||||
final Resource resource = queue.getResource();
|
||||
final List<LimitingResourceQueueElement> elements = new LinkedList<LimitingResourceQueueElement>(
|
||||
queue.getLimitingResourceQueueElements());
|
||||
final int size = elements.size();
|
||||
|
||||
// Move until startTime
|
||||
Integer pos = moveUntil(elements, since);
|
||||
if (pos == null) {
|
||||
if (size == 0) {
|
||||
result.add(createLastGap(since, null, resource));
|
||||
} else {
|
||||
result.add(createLastGap(since, elements.get(size - 1), resource));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Iterate through queue elements
|
||||
do {
|
||||
LimitingResourceQueueElementGap gap = getGapInQueueAtPosition(
|
||||
resource, elements, since, pos++);
|
||||
|
||||
// The queue cannot hold this element (queue.resource
|
||||
// doesn't meet element.criteria)
|
||||
if (gap == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
result.addAll(getFittingSubgaps(element, gap, resource));
|
||||
|
||||
} while (pos < size);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static Integer moveUntil(List<LimitingResourceQueueElement> elements, DateAndHour until) {
|
||||
for (int pos = 0; pos < elements.size(); pos++) {
|
||||
final LimitingResourceQueueElement each = elements.get(pos);
|
||||
if (!until.isBefore(each.getStartTime())) {
|
||||
return pos;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static boolean isGeneric(LimitingResourceQueueElement element) {
|
||||
|
|
@ -209,17 +266,16 @@ public class LimitingResourceAllocator {
|
|||
|
||||
private static LimitingResourceQueueElementGap getGapInQueueAtPosition(
|
||||
Resource resource, List<LimitingResourceQueueElement> elements,
|
||||
LimitingResourceQueueElement element, int pos) {
|
||||
DateAndHour startTimeBecauseOfGantt, int pos) {
|
||||
|
||||
final int size = elements.size();
|
||||
final DateAndHour startTimeBecauseOfGantt = getStartTimeBecauseOfGantt(element);
|
||||
|
||||
if (size == 0) {
|
||||
return createLastGap(element, null, resource);
|
||||
return createLastGap(startTimeBecauseOfGantt, null, resource);
|
||||
}
|
||||
|
||||
if (pos == size) {
|
||||
return createLastGap(element, elements.get(size - 1), resource);
|
||||
return createLastGap(startTimeBecauseOfGantt, elements.get(size - 1), resource);
|
||||
}
|
||||
|
||||
LimitingResourceQueueElement current = elements.get(pos);
|
||||
|
|
@ -244,7 +300,7 @@ public class LimitingResourceAllocator {
|
|||
}
|
||||
} else {
|
||||
// Current was the last element
|
||||
return createLastGap(element, current, resource);
|
||||
return createLastGap(startTimeBecauseOfGantt, current, resource);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -254,13 +310,12 @@ public class LimitingResourceAllocator {
|
|||
}
|
||||
|
||||
private static LimitingResourceQueueElementGap createLastGap(
|
||||
LimitingResourceQueueElement candidate,
|
||||
LimitingResourceQueueElement lastElement, Resource resource) {
|
||||
DateAndHour _startTime, LimitingResourceQueueElement lastElement,
|
||||
Resource resource) {
|
||||
|
||||
final DateAndHour queueEndTime = (lastElement != null) ? lastElement
|
||||
.getEndTime() : null;
|
||||
DateAndHour startTime = DateAndHour.Max(
|
||||
getStartTimeBecauseOfGantt(candidate), queueEndTime);
|
||||
DateAndHour startTime = DateAndHour.Max(_startTime, queueEndTime);
|
||||
return LimitingResourceQueueElementGap
|
||||
.create(resource, startTime, null);
|
||||
}
|
||||
|
|
@ -305,6 +360,31 @@ public class LimitingResourceAllocator {
|
|||
return assignments;
|
||||
}
|
||||
|
||||
private static List<DayAssignment> generateDayAssignmentsStartingFromEnd(ResourceAllocation<?> resourceAllocation,
|
||||
Resource resource,
|
||||
DateAndHour endTime) {
|
||||
|
||||
List<DayAssignment> assignments = new ArrayList<DayAssignment>();
|
||||
|
||||
LocalDate date = endTime.getDate();
|
||||
int totalHours = resourceAllocation.getIntendedTotalHours();
|
||||
|
||||
// Generate last day assignment
|
||||
int hoursCanAllocate = hoursCanWorkOnDay(resource, date, endTime.getHour());
|
||||
if (hoursCanAllocate > 0) {
|
||||
int hoursToAllocate = Math.min(totalHours, hoursCanAllocate);
|
||||
DayAssignment dayAssignment = createDayAssignment(resourceAllocation, resource, date, hoursToAllocate);
|
||||
totalHours -= addDayAssignment(assignments, dayAssignment);
|
||||
}
|
||||
|
||||
// Generate rest of day assignments
|
||||
for (date = date.minusDays(1); totalHours > 0; date = date.minusDays(1)) {
|
||||
totalHours -= addDayAssignment(assignments, generateDayAssignment(
|
||||
resourceAllocation, resource, date, totalHours));
|
||||
}
|
||||
return assignments;
|
||||
}
|
||||
|
||||
private static DayAssignment createDayAssignment(ResourceAllocation<?> resourceAllocation,
|
||||
Resource resource, LocalDate date, int hoursToAllocate) {
|
||||
if (resourceAllocation instanceof SpecificResourceAllocation) {
|
||||
|
|
@ -345,4 +425,21 @@ public class LimitingResourceAllocator {
|
|||
return null;
|
||||
}
|
||||
|
||||
public static DateAndHour startTimeToAllocateStartingFromEnd(
|
||||
ResourceAllocation<?> resourceAllocation, Resource resource,
|
||||
LimitingResourceQueueElementGap gap) {
|
||||
|
||||
// Last element, time is end of last element (gap.starttime)
|
||||
if (gap.getEndTime() == null) {
|
||||
return gap.getStartTime();
|
||||
}
|
||||
|
||||
final List<DayAssignment> dayAssignments = LimitingResourceAllocator
|
||||
.generateDayAssignmentsStartingFromEnd(resourceAllocation,
|
||||
resource, gap.getEndTime());
|
||||
final DateAndHour[] startAndEnd = LimitingResourceAllocator
|
||||
.calculateStartAndEndTime(dayAssignments);
|
||||
return startAndEnd[1];
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ package org.navalplanner.web.limitingresources;
|
|||
import java.util.List;
|
||||
|
||||
import org.navalplanner.business.orders.entities.Order;
|
||||
import org.navalplanner.business.planner.entities.DateAndHour;
|
||||
import org.navalplanner.business.planner.entities.DayAssignment;
|
||||
import org.navalplanner.business.planner.entities.LimitingResourceQueueElement;
|
||||
import org.navalplanner.business.planner.entities.TaskElement;
|
||||
|
|
@ -77,6 +78,9 @@ public interface ILimitingResourceQueueModel {
|
|||
*/
|
||||
boolean assignLimitingResourceQueueElement(LimitingResourceQueueElement element);
|
||||
|
||||
boolean assignEditingLimitingResourceQueueElementToQueueAt(
|
||||
LimitingResourceQueue queue, DateAndHour time);
|
||||
|
||||
ZoomLevel calculateInitialZoomLevel();
|
||||
|
||||
/**
|
||||
|
|
@ -121,4 +125,11 @@ public interface ILimitingResourceQueueModel {
|
|||
|
||||
void setTimeTrackerState(ZoomLevel zoomLevel);
|
||||
|
||||
List<LimitingResourceQueue> getAssignableQueues(
|
||||
LimitingResourceQueueElement element);
|
||||
|
||||
void init(LimitingResourceQueueElement element);
|
||||
|
||||
LimitingResourceQueueElement getLimitingResourceQueueElement();
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ import java.util.Map;
|
|||
import java.util.Set;
|
||||
import java.util.SortedSet;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.hibernate.Hibernate;
|
||||
import org.hibernate.proxy.HibernateProxy;
|
||||
import org.joda.time.LocalDate;
|
||||
|
|
@ -61,7 +62,9 @@ import org.navalplanner.business.planner.entities.SpecificResourceAllocation;
|
|||
import org.navalplanner.business.planner.entities.Task;
|
||||
import org.navalplanner.business.planner.entities.TaskElement;
|
||||
import org.navalplanner.business.resources.entities.Criterion;
|
||||
import org.navalplanner.business.resources.entities.CriterionCompounder;
|
||||
import org.navalplanner.business.resources.entities.CriterionSatisfaction;
|
||||
import org.navalplanner.business.resources.entities.ICriterion;
|
||||
import org.navalplanner.business.resources.entities.LimitingResourceQueue;
|
||||
import org.navalplanner.business.resources.entities.Resource;
|
||||
import org.navalplanner.business.users.daos.IOrderAuthorizationDAO;
|
||||
|
|
@ -110,6 +113,8 @@ public class LimitingResourceQueueModel implements ILimitingResourceQueueModel {
|
|||
|
||||
private List<LimitingResourceQueueElement> unassignedLimitingResourceQueueElements = new ArrayList<LimitingResourceQueueElement>();
|
||||
|
||||
private LimitingResourceQueueElement beingEdited;
|
||||
|
||||
private Set<LimitingResourceQueueElement> toBeRemoved = new HashSet<LimitingResourceQueueElement>();
|
||||
|
||||
private Set<LimitingResourceQueueElement> toBeSaved = new HashSet<LimitingResourceQueueElement>();
|
||||
|
|
@ -427,20 +432,26 @@ public class LimitingResourceQueueModel implements ILimitingResourceQueueModel {
|
|||
queue = firstGapsForQueues.get(earliestGap);
|
||||
startTime = earliestGap.getStartTime();
|
||||
}
|
||||
return assignLimitingResourceQueueElementToQueueAt(queueElement, queue, startTime);
|
||||
}
|
||||
|
||||
private boolean assignLimitingResourceQueueElementToQueueAt(
|
||||
LimitingResourceQueueElement element, LimitingResourceQueue queue,
|
||||
DateAndHour startTime) {
|
||||
|
||||
// Allocate day assignments and adjust start and end times for element
|
||||
List<DayAssignment> dayAssignments = LimitingResourceAllocator
|
||||
.generateDayAssignments(queueElement.getResourceAllocation(),
|
||||
.generateDayAssignments(element.getResourceAllocation(),
|
||||
queue.getResource(), startTime);
|
||||
DateAndHour[] startAndEndTime = LimitingResourceAllocator
|
||||
.calculateStartAndEndTime(dayAssignments);
|
||||
updateStartAndEndTimes(queueElement, startAndEndTime);
|
||||
queueElement.getResourceAllocation().allocateLimitingDayAssignments(
|
||||
updateStartAndEndTimes(element, startAndEndTime);
|
||||
element.getResourceAllocation().allocateLimitingDayAssignments(
|
||||
dayAssignments);
|
||||
|
||||
// Add element to queue
|
||||
addLimitingResourceQueueElement(queue, queueElement);
|
||||
markAsModified(queueElement);
|
||||
addLimitingResourceQueueElement(queue, element);
|
||||
markAsModified(element);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -566,8 +577,6 @@ public class LimitingResourceQueueModel implements ILimitingResourceQueueModel {
|
|||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void confirm() {
|
||||
|
|
@ -705,4 +714,52 @@ public class LimitingResourceQueueModel implements ILimitingResourceQueueModel {
|
|||
this.zoomLevel = timeTrackerState;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<LimitingResourceQueue> getAssignableQueues(
|
||||
LimitingResourceQueueElement element) {
|
||||
|
||||
final ResourceAllocation<?> resourceAllocation = element.getResourceAllocation();
|
||||
if (resourceAllocation instanceof SpecificResourceAllocation) {
|
||||
LimitingResourceQueue queue = retrieveQueueByResourceFromModel(element.getResource());
|
||||
Validate.notNull(queue);
|
||||
return Collections.singletonList(queue);
|
||||
} else if (resourceAllocation instanceof GenericResourceAllocation) {
|
||||
final GenericResourceAllocation generic = (GenericResourceAllocation) element.getResourceAllocation();
|
||||
return findQueuesMatchingCriteria(limitingResourceQueues, generic.getCriterions());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private List<LimitingResourceQueue> findQueuesMatchingCriteria(List<LimitingResourceQueue> queues, Set<Criterion> criteria) {
|
||||
List<LimitingResourceQueue> result = new ArrayList<LimitingResourceQueue>();
|
||||
|
||||
final ICriterion compositedCriterion = CriterionCompounder.buildAnd(criteria).getResult();
|
||||
for (LimitingResourceQueue each: queues) {
|
||||
if (compositedCriterion.isSatisfiedBy(each.getResource())) {
|
||||
result.add(each);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean assignEditingLimitingResourceQueueElementToQueueAt(
|
||||
LimitingResourceQueue queue, DateAndHour startTime) {
|
||||
Validate.notNull(beingEdited);
|
||||
Validate.notNull(queue);
|
||||
Validate.notNull(startTime);
|
||||
|
||||
return assignLimitingResourceQueueElementToQueueAt(beingEdited, queue, startTime);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(LimitingResourceQueueElement element) {
|
||||
beingEdited = retrieveQueueElementFromModel(element);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LimitingResourceQueueElement getLimitingResourceQueueElement() {
|
||||
return beingEdited;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,9 +31,14 @@ import java.util.Set;
|
|||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.navalplanner.business.orders.entities.Order;
|
||||
import org.navalplanner.business.planner.entities.DateAndHour;
|
||||
import org.navalplanner.business.planner.entities.DayAssignment;
|
||||
import org.navalplanner.business.planner.entities.GenericResourceAllocation;
|
||||
import org.navalplanner.business.planner.entities.LimitingResourceAllocator;
|
||||
import org.navalplanner.business.planner.entities.LimitingResourceQueueElement;
|
||||
import org.navalplanner.business.planner.entities.LimitingResourceQueueElementGap;
|
||||
import org.navalplanner.business.planner.entities.ResourceAllocation;
|
||||
import org.navalplanner.business.planner.entities.SpecificResourceAllocation;
|
||||
import org.navalplanner.business.planner.entities.Task;
|
||||
|
|
@ -51,18 +56,28 @@ import org.zkoss.ganttz.resourceload.IFilterChangedListener;
|
|||
import org.zkoss.ganttz.timetracker.TimeTracker;
|
||||
import org.zkoss.ganttz.timetracker.zoom.SeveralModificators;
|
||||
import org.zkoss.ganttz.timetracker.zoom.ZoomLevel;
|
||||
import org.zkoss.zk.ui.SuspendNotAllowedException;
|
||||
import org.zkoss.zk.ui.event.Event;
|
||||
import org.zkoss.zk.ui.event.EventListener;
|
||||
import org.zkoss.zk.ui.event.Events;
|
||||
import org.zkoss.zk.ui.event.SelectEvent;
|
||||
import org.zkoss.zk.ui.util.Composer;
|
||||
import org.zkoss.zul.Button;
|
||||
import org.zkoss.zul.Checkbox;
|
||||
import org.zkoss.zul.Grid;
|
||||
import org.zkoss.zul.Hbox;
|
||||
import org.zkoss.zul.Label;
|
||||
import org.zkoss.zul.Listbox;
|
||||
import org.zkoss.zul.Listcell;
|
||||
import org.zkoss.zul.Listitem;
|
||||
import org.zkoss.zul.ListitemRenderer;
|
||||
import org.zkoss.zul.Messagebox;
|
||||
import org.zkoss.zul.Radio;
|
||||
import org.zkoss.zul.Radiogroup;
|
||||
import org.zkoss.zul.Row;
|
||||
import org.zkoss.zul.RowRenderer;
|
||||
import org.zkoss.zul.SimpleListModel;
|
||||
import org.zkoss.zul.Window;
|
||||
|
||||
/**
|
||||
* Controller for limiting resources view
|
||||
|
|
@ -87,10 +102,18 @@ public class LimitingResourcesController implements Composer {
|
|||
|
||||
private Grid gridUnassignedLimitingResourceQueueElements;
|
||||
|
||||
private Window manualAllocationWindow;
|
||||
|
||||
private Radiogroup radioAllocationDate;
|
||||
|
||||
private final LimitingResourceQueueElementsRenderer limitingResourceQueueElementsRenderer =
|
||||
new LimitingResourceQueueElementsRenderer();
|
||||
|
||||
private transient IFilterChangedListener filterChangedListener;
|
||||
private final QueueRenderer queueRenderer = new QueueRenderer();
|
||||
|
||||
private final CandidateGapRenderer candidateGapRenderer = new CandidateGapRenderer();
|
||||
|
||||
private transient IFilterChangedListener filterChangedListener;
|
||||
|
||||
public LimitingResourcesController() {
|
||||
}
|
||||
|
|
@ -112,6 +135,10 @@ public class LimitingResourcesController implements Composer {
|
|||
reload(filterByResources);
|
||||
}
|
||||
|
||||
private Listbox listAssignableQueues;
|
||||
|
||||
private Listbox listCandidateGaps;
|
||||
|
||||
private void reload(boolean filterByResources) {
|
||||
try {
|
||||
|
||||
|
|
@ -135,6 +162,10 @@ public class LimitingResourcesController implements Composer {
|
|||
limitingResourcesPanel.afterCompose();
|
||||
gridUnassignedLimitingResourceQueueElements = (Grid) limitingResourcesPanel
|
||||
.getFellowIfAny("gridUnassignedLimitingResourceQueueElements");
|
||||
manualAllocationWindow = (Window) limitingResourcesPanel.getFellowIfAny("manualAllocationWindow");
|
||||
listAssignableQueues = (Listbox) manualAllocationWindow.getFellowIfAny("listAssignableQueues");
|
||||
listCandidateGaps = (Listbox) manualAllocationWindow.getFellowIfAny("listCandidateGaps");
|
||||
radioAllocationDate = (Radiogroup) manualAllocationWindow.getFellowIfAny("radioAllocationDate");
|
||||
addCommands(limitingResourcesPanel);
|
||||
} catch (IllegalArgumentException e) {
|
||||
try {
|
||||
|
|
@ -318,9 +349,24 @@ public class LimitingResourcesController implements Composer {
|
|||
Hbox hbox = new Hbox();
|
||||
hbox.appendChild(assignButton(element));
|
||||
hbox.appendChild(removeButton(element));
|
||||
hbox.appendChild(manualButton(element));
|
||||
return hbox;
|
||||
}
|
||||
|
||||
private Button manualButton(final LimitingResourceQueueElementDTO element) {
|
||||
Button result = new Button();
|
||||
result.setLabel(_("Manual"));
|
||||
result.setTooltiptext(_("Manual allocation"));
|
||||
result.addEventListener(Events.ON_CLICK, new EventListener() {
|
||||
|
||||
@Override
|
||||
public void onEvent(Event event) throws Exception {
|
||||
manualAllocateLimitingResourceQueueElement(element);
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
private Button removeButton(final LimitingResourceQueueElementDTO element) {
|
||||
Button result = new Button();
|
||||
result.setLabel(_("Remove"));
|
||||
|
|
@ -373,6 +419,21 @@ public class LimitingResourcesController implements Composer {
|
|||
}
|
||||
}
|
||||
|
||||
private void manualAllocateLimitingResourceQueueElement(LimitingResourceQueueElementDTO dto) {
|
||||
LimitingResourceQueueElement element = dto.getOriginal();
|
||||
try {
|
||||
setAssignableQueues(element);
|
||||
limitingResourceQueueModel.init(element);
|
||||
manualAllocationWindow.doModal();
|
||||
} catch (SuspendNotAllowedException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
} catch (InterruptedException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void showErrorMessage(String error) {
|
||||
try {
|
||||
Messagebox.show(error, _("Error"), Messagebox.OK, Messagebox.ERROR);
|
||||
|
|
@ -403,4 +464,166 @@ public class LimitingResourcesController implements Composer {
|
|||
Util.reloadBindings(gridUnassignedLimitingResourceQueueElements);
|
||||
}
|
||||
|
||||
private void feedValidGaps(LimitingResourceQueueElement element, LimitingResourceQueue queue) {
|
||||
feedValidGapsSince(element, queue, getStartDayBecauseOfGantt(element));
|
||||
}
|
||||
|
||||
private DateAndHour getStartDayBecauseOfGantt(LimitingResourceQueueElement element) {
|
||||
return new DateAndHour(new LocalDate(element.getEarlierStartDateBecauseOfGantt()), 0);
|
||||
}
|
||||
|
||||
private void feedValidGapsSince(LimitingResourceQueueElement element, LimitingResourceQueue queue, DateAndHour since) {
|
||||
List<LimitingResourceQueueElementGap> gaps = LimitingResourceAllocator.getValidGapsForElementSince(element, queue, since);
|
||||
listCandidateGaps.setModel(new SimpleListModel(gaps));
|
||||
if (!gaps.isEmpty()) {
|
||||
listCandidateGaps.setSelectedIndex(0);
|
||||
disable(radioAllocationDate, false);
|
||||
} else {
|
||||
disable(radioAllocationDate, true);
|
||||
}
|
||||
}
|
||||
|
||||
private void disable(Radiogroup radiogroup, boolean disabled) {
|
||||
for (Object obj: radiogroup.getChildren()) {
|
||||
final Radio each = (Radio) obj;
|
||||
each.setDisabled(disabled);
|
||||
}
|
||||
}
|
||||
|
||||
public CandidateGapRenderer getCandidateGapRenderer() {
|
||||
return candidateGapRenderer;
|
||||
}
|
||||
|
||||
private class CandidateGapRenderer implements ListitemRenderer {
|
||||
|
||||
@Override
|
||||
public void render(Listitem item, Object data) throws Exception {
|
||||
LimitingResourceQueueElementGap gap = (LimitingResourceQueueElementGap) data;
|
||||
|
||||
item.setValue(gap);
|
||||
item.appendChild(cell(gap.getStartTime()));
|
||||
item.appendChild(cell(gap.getEndTime()));
|
||||
}
|
||||
|
||||
public Listcell cell(DateAndHour time) {
|
||||
return new Listcell(formatTime(time));
|
||||
}
|
||||
|
||||
private String formatTime(DateAndHour time) {
|
||||
return time == null ? _("END") : time.getDate().toString("dd/MM/yyyy") + " - " + time.getHour();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void setAssignableQueues(final LimitingResourceQueueElement element) {
|
||||
List<LimitingResourceQueue> queues = limitingResourceQueueModel.getAssignableQueues(element);
|
||||
listAssignableQueues.setModel(new SimpleListModel(queues));
|
||||
listAssignableQueues.addEventListener(Events.ON_SELECT, new EventListener() {
|
||||
|
||||
@Override
|
||||
public void onEvent(Event event) throws Exception {
|
||||
SelectEvent se = (SelectEvent) event;
|
||||
|
||||
LimitingResourceQueue queue = getSelectedQueue(se);
|
||||
if (queue != null) {
|
||||
feedValidGaps(element, queue);
|
||||
}
|
||||
}
|
||||
|
||||
public LimitingResourceQueue getSelectedQueue(SelectEvent se) {
|
||||
final Listitem item = (Listitem) se.getSelectedItems().iterator().next();
|
||||
return (LimitingResourceQueue) item.getValue();
|
||||
}
|
||||
|
||||
});
|
||||
listAssignableQueues.setSelectedIndex(0);
|
||||
feedValidGaps(element, queues.get(0));
|
||||
}
|
||||
|
||||
private LimitingResourceQueue getSelectedQueue() {
|
||||
LimitingResourceQueue result = null;
|
||||
|
||||
final Listitem item = listAssignableQueues.getSelectedItem();
|
||||
if (item != null) {
|
||||
result = (LimitingResourceQueue) item.getValue();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public ListitemRenderer getQueueRenderer() {
|
||||
return queueRenderer;
|
||||
}
|
||||
|
||||
private class QueueRenderer implements ListitemRenderer {
|
||||
|
||||
@Override
|
||||
public void render(Listitem item, Object data) throws Exception {
|
||||
final LimitingResourceQueue queue = (LimitingResourceQueue) data;
|
||||
item.setValue(queue);
|
||||
item.appendChild(cell(queue));
|
||||
}
|
||||
|
||||
private Listcell cell(LimitingResourceQueue queue) {
|
||||
Listcell result = new Listcell();
|
||||
result.setLabel(queue.getResource().getName());
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void accept(Event e) {
|
||||
LimitingResourceQueueElement element = limitingResourceQueueModel
|
||||
.getLimitingResourceQueueElement();
|
||||
LimitingResourceQueue queue = getSelectedQueue();
|
||||
DateAndHour time = getSelectedAllocationTime();
|
||||
limitingResourceQueueModel
|
||||
.assignEditingLimitingResourceQueueElementToQueueAt(queue, time);
|
||||
Util.reloadBindings(gridUnassignedLimitingResourceQueueElements);
|
||||
limitingResourcesPanel.appendQueueElementToQueue(element);
|
||||
closeManualAllocationWindow(e);
|
||||
}
|
||||
|
||||
private DateAndHour getSelectedAllocationTime() {
|
||||
final LimitingResourceQueueElementGap selectedGap = getSelectedGap();
|
||||
int index = radioAllocationDate.getSelectedIndex();
|
||||
if (index == 0) {
|
||||
return getEarliestTime(selectedGap);
|
||||
} else if (index == 1) {
|
||||
return getLatestTime(selectedGap);
|
||||
} else if (index == 2) {
|
||||
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private DateAndHour getEarliestTime(LimitingResourceQueueElementGap gap) {
|
||||
Validate.notNull(gap);
|
||||
return gap.getStartTime();
|
||||
}
|
||||
|
||||
private DateAndHour getLatestTime(LimitingResourceQueueElementGap gap) {
|
||||
Validate.notNull(gap);
|
||||
LimitingResourceQueueElement element = limitingResourceQueueModel.getLimitingResourceQueueElement();
|
||||
LimitingResourceQueue queue = getSelectedQueue();
|
||||
return LimitingResourceAllocator.startTimeToAllocateStartingFromEnd(
|
||||
element.getResourceAllocation(), queue.getResource(), gap);
|
||||
}
|
||||
|
||||
private LimitingResourceQueueElementGap getSelectedGap() {
|
||||
Listitem item = listCandidateGaps.getSelectedItem();
|
||||
if (item != null) {
|
||||
return (LimitingResourceQueueElementGap) item.getValue();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void cancel() {
|
||||
|
||||
}
|
||||
|
||||
public void closeManualAllocationWindow(Event e) {
|
||||
manualAllocationWindow.setVisible(false);
|
||||
e.stopPropagation();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,10 +21,11 @@
|
|||
signature="java.lang.String _(java.lang.String name)" ?>
|
||||
|
||||
<zk xmlns:n="http://www.zkoss.org/2005/zk/native">
|
||||
<zscript><![CDATA[
|
||||
limitingResourcesPanel = self;
|
||||
]]>
|
||||
</zscript>
|
||||
|
||||
<zscript><![CDATA[
|
||||
limitingResourcesPanel = self;
|
||||
]]>
|
||||
</zscript>
|
||||
|
||||
<borderlayout sclass="resourcesloadlayout" width="auto">
|
||||
|
||||
|
|
@ -97,11 +98,72 @@ limitingResourcesPanel = self;
|
|||
<column label="${i18n:_('Resource / Criteria')}" sort="auto(resourceOrCriteria)"/>
|
||||
<column label="${i18n:_('Date')}" sort="auto(date)"/>
|
||||
<column label="${i18n:_('Hours to allocate')}" sort="auto(hoursToAllocate)"/>
|
||||
<column label="${i18n:_('Operations')}" width="150px"/>
|
||||
<column label="${i18n:_('Operations')}" width="200px"/>
|
||||
<column label="${i18n:_('Auto queueing')}" width="100px" />
|
||||
</columns>
|
||||
</grid>
|
||||
</south>
|
||||
|
||||
</borderlayout>
|
||||
|
||||
|
||||
<!-- Manual allocation -->
|
||||
<window id="manualAllocationWindow"
|
||||
title="${i18n:_('Manual allocation')}"
|
||||
width="500px" left="50px" top="50px"
|
||||
visible="false"
|
||||
closable="true"
|
||||
onClose="limitingResourcesController.closeManualAllocationWindow(event)">
|
||||
|
||||
<!-- Select assignable queues -->
|
||||
<vbox>
|
||||
<panel title="${i18n:_('Select queue')}" border="normal">
|
||||
<panelchildren>
|
||||
<listbox id="listAssignableQueues"
|
||||
itemRenderer="@{limitingResourcesController.queueRenderer}"
|
||||
mold="select" />
|
||||
</panelchildren>
|
||||
</panel>
|
||||
</vbox>
|
||||
|
||||
<!-- Select gap -->
|
||||
<vbox>
|
||||
<panel title="${i18n:_('Select gap')}" border="normal">
|
||||
<panelchildren>
|
||||
<listbox id="listCandidateGaps"
|
||||
itemRenderer="@{limitingResourcesController.candidateGapRenderer}"
|
||||
multiple="false">
|
||||
<listhead>
|
||||
<listheader label="${i18n:_('Start')}" />
|
||||
<listheader label="${i18n:_('End')}" />
|
||||
</listhead>
|
||||
</listbox>
|
||||
</panelchildren>
|
||||
</panel>
|
||||
</vbox>
|
||||
|
||||
<!-- Select date -->
|
||||
<vbox>
|
||||
<panel title="${i18n:_('Select date')}" border="normal">
|
||||
<panelchildren>
|
||||
<radiogroup id="radioAllocationDate" orient="vertical">
|
||||
<radio label="${i18n:_('Earliest date')}" selected="true" />
|
||||
<radio label="${i18n:_('Latest date')}" />
|
||||
</radiogroup>
|
||||
</panelchildren>
|
||||
</panel>
|
||||
</vbox>
|
||||
|
||||
<separator bar="false" spacing="30px" orient="horizontal"/>
|
||||
|
||||
<!-- Controls -->
|
||||
<hbox>
|
||||
<button id="ok" label="${i18n:_('Accept')}"
|
||||
onClick="limitingResourcesController.accept(event)" />
|
||||
<button id="cancel" label="${i18n:_('Cancel')}"
|
||||
onClick="limitingResourcesController.cancel()" />
|
||||
</hbox>
|
||||
|
||||
</window>
|
||||
|
||||
</zk>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue