Calculate first/last timesheets dates when saving/editing/deleting a timesheet
In order to do that, a set of order elements affected by the lines added/edit/removed in a timesheet is calculated before saving the timesheet. Afterwards the first/last dates are recalculated for all the order elements in the set. FEA: ItEr77S12AdaptPlanningAccordingTimesheets
This commit is contained in:
parent
460896ee8b
commit
4adc1ec71f
6 changed files with 181 additions and 13 deletions
|
|
@ -74,4 +74,26 @@ public interface ISumChargedEffortDAO extends
|
|||
*/
|
||||
void recalculateSumChargedEfforts(Long orderId);
|
||||
|
||||
/**
|
||||
* Returns a {@link Set} of {@link OrderElement OrderElements} affected by
|
||||
* any change taking into account the lines in the report and the ones to be
|
||||
* removed.
|
||||
*
|
||||
* Usually you call this method to get the set before saving the work
|
||||
* report. After saving the work report you call
|
||||
* {@link ISumChargedEffortDAO#recalculateTimesheetDates(Set)} with the
|
||||
* result of this method.
|
||||
*
|
||||
* You can pass <code>null</code> as param if you only have one of the sets.
|
||||
*/
|
||||
Set<OrderElement> getOrderElementsToRecalculateTimsheetDates(
|
||||
Set<WorkReportLine> workReportLines,
|
||||
Set<WorkReportLine> deletedWorkReportLinesSet);
|
||||
|
||||
/**
|
||||
* Recalulates the first and last timesheets dates for each
|
||||
* {@link OrderElement} in the {@link Set}.
|
||||
*/
|
||||
void recalculateTimesheetDates(Set<OrderElement> orderElements);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -70,6 +70,9 @@ public class SumChargedEffortDAO extends
|
|||
@Autowired
|
||||
private IOrderDAO orderDAO;
|
||||
|
||||
@Autowired
|
||||
private IOrderElementDAO orderElementDAO;
|
||||
|
||||
private Map<OrderElement, SumChargedEffort> mapSumChargedEfforts;
|
||||
|
||||
@Override
|
||||
|
|
@ -118,6 +121,7 @@ public class SumChargedEffortDAO extends
|
|||
forceLoadParents(parent);
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
previousEffort = previous.getFirst();
|
||||
|
|
@ -252,7 +256,7 @@ public class SumChargedEffortDAO extends
|
|||
resetMapSumChargedEfforts();
|
||||
resetSumChargedEffort(order);
|
||||
calculateDirectChargedEffort(order);
|
||||
calculateFirstAndLastTimesheetDates(order);
|
||||
calculateTimesheetDates(order);
|
||||
} catch (InstanceNotFoundException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
|
@ -280,7 +284,7 @@ public class SumChargedEffortDAO extends
|
|||
addDirectChargedEffort(orderElement, effort);
|
||||
}
|
||||
|
||||
private Pair<Date, Date> calculateFirstAndLastTimesheetDates(
|
||||
private Pair<Date, Date> calculateTimesheetDates(
|
||||
OrderElement orderElement) {
|
||||
Pair<Date, Date> minMax = workReportLineDAO
|
||||
.findMinAndMaxDatesByOrderElement(orderElement);
|
||||
|
|
@ -292,18 +296,21 @@ public class SumChargedEffortDAO extends
|
|||
addIfNotNull(maxDates, minMax.getSecond());
|
||||
|
||||
for (OrderElement child : orderElement.getChildren()) {
|
||||
Pair<Date, Date> minMaxChild = calculateFirstAndLastTimesheetDates(child);
|
||||
Pair<Date, Date> minMaxChild = calculateTimesheetDates(child);
|
||||
addIfNotNull(minDates, minMaxChild.getFirst());
|
||||
addIfNotNull(maxDates, minMaxChild.getSecond());
|
||||
}
|
||||
|
||||
SumChargedEffort sumChargedEffort = getByOrderElement(orderElement);
|
||||
sumChargedEffort.setTimesheetDates(minMax.getFirst(),
|
||||
minMax.getSecond());
|
||||
|
||||
return Pair.create(
|
||||
Pair<Date, Date> result = Pair.create(
|
||||
minDates.isEmpty() ? null : Collections.min(minDates),
|
||||
maxDates.isEmpty() ? null : Collections.max(maxDates));
|
||||
|
||||
SumChargedEffort sumChargedEffort = getByOrderElement(orderElement);
|
||||
sumChargedEffort.setTimesheetDates(result.getFirst(),
|
||||
result.getSecond());
|
||||
save(sumChargedEffort);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private void addIfNotNull(Collection<Date> list, Date date) {
|
||||
|
|
@ -312,4 +319,101 @@ public class SumChargedEffortDAO extends
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public Set<OrderElement> getOrderElementsToRecalculateTimsheetDates(
|
||||
Set<WorkReportLine> workReportLines,
|
||||
Set<WorkReportLine> deletedWorkReportLines) {
|
||||
Set<OrderElement> orderElements = new HashSet<OrderElement>();
|
||||
|
||||
if (workReportLines != null) {
|
||||
for (final WorkReportLine workReportLine : workReportLines) {
|
||||
if (!workReportLine.isNewObject()) {
|
||||
OrderElement previousOrderElement = transactionService
|
||||
.runOnAnotherTransaction(new IOnTransaction<OrderElement>() {
|
||||
@Override
|
||||
public OrderElement execute() {
|
||||
try {
|
||||
WorkReportLine line = workReportLineDAO
|
||||
.find(workReportLine.getId());
|
||||
|
||||
return line.getOrderElement();
|
||||
} catch (InstanceNotFoundException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
orderElements.add(previousOrderElement);
|
||||
}
|
||||
orderElements.add(workReportLine.getOrderElement());
|
||||
}
|
||||
}
|
||||
|
||||
if (deletedWorkReportLines != null) {
|
||||
for (WorkReportLine workReportLine : deletedWorkReportLines) {
|
||||
if (workReportLine.isNewObject()) {
|
||||
// If the line hasn't been saved, we don't take it into
|
||||
// account
|
||||
continue;
|
||||
}
|
||||
|
||||
// Refresh data from database, because of changes not saved are
|
||||
// not
|
||||
// useful for the following operations
|
||||
sessionFactory.getCurrentSession().refresh(workReportLine);
|
||||
|
||||
orderElements.add(workReportLine.getOrderElement());
|
||||
}
|
||||
}
|
||||
|
||||
return orderElements;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void recalculateTimesheetDates(Set<OrderElement> orderElements) {
|
||||
try {
|
||||
for (OrderElement orderElement : orderElements) {
|
||||
saveTimesheetDatesRecursively(orderElementDAO.find(orderElement
|
||||
.getId()));
|
||||
}
|
||||
} catch (InstanceNotFoundException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void saveTimesheetDatesRecursively(OrderElement orderElement) {
|
||||
if (orderElement != null) {
|
||||
saveTimesheetDates(orderElement);
|
||||
saveTimesheetDatesRecursively(orderElement.getParent());
|
||||
}
|
||||
}
|
||||
|
||||
private void saveTimesheetDates(OrderElement orderElement) {
|
||||
Pair<Date, Date> minMax = workReportLineDAO
|
||||
.findMinAndMaxDatesByOrderElement(orderElement);
|
||||
|
||||
Set<Date> minDates = new HashSet<Date>();
|
||||
Set<Date> maxDates = new HashSet<Date>();
|
||||
|
||||
addIfNotNull(minDates, minMax.getFirst());
|
||||
addIfNotNull(maxDates, minMax.getSecond());
|
||||
|
||||
for (OrderElement child : orderElement.getChildren()) {
|
||||
SumChargedEffort childSumChargedEffort = getByOrderElement(child);
|
||||
addIfNotNull(minDates,
|
||||
childSumChargedEffort.getFirstTimesheetDate());
|
||||
addIfNotNull(maxDates, childSumChargedEffort.getLastTimesheetDate());
|
||||
}
|
||||
|
||||
Pair<Date, Date> result = Pair.create(minDates.isEmpty() ? null
|
||||
: Collections.min(minDates), maxDates.isEmpty() ? null
|
||||
: Collections.max(maxDates));
|
||||
|
||||
SumChargedEffort sumChargedEffort = getByOrderElement(orderElement);
|
||||
sumChargedEffort.setTimesheetDates(result.getFirst(),
|
||||
result.getSecond());
|
||||
save(sumChargedEffort);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -431,12 +431,16 @@ public class PersonalTimesheetModel implements IPersonalTimesheetModel {
|
|||
// saved as it will not be possible to find it later with
|
||||
// WorkReportDAO.getPersonalTimesheetWorkReport() method.
|
||||
} else {
|
||||
Set<OrderElement> orderElements = sumChargedEffortDAO
|
||||
.getOrderElementsToRecalculateTimsheetDates(
|
||||
workReport.getWorkReportLines(), null);
|
||||
sumChargedEffortDAO
|
||||
.updateRelatedSumChargedEffortWithWorkReportLineSet(workReport
|
||||
.getWorkReportLines());
|
||||
workReport.generateWorkReportLineCodes(entitySequenceDAO
|
||||
.getNumberOfDigitsCode(EntityNameEnum.WORK_REPORT));
|
||||
workReportDAO.save(workReport);
|
||||
sumChargedEffortDAO.recalculateTimesheetDates(orderElements);
|
||||
}
|
||||
|
||||
resetModifiedFields();
|
||||
|
|
|
|||
|
|
@ -274,12 +274,17 @@ public class WorkReportModel extends IntegrationEntityModel implements
|
|||
@Override
|
||||
@Transactional
|
||||
public void confirmSave() throws ValidationException {
|
||||
Set<OrderElement> orderElements = sumChargedEffortDAO
|
||||
.getOrderElementsToRecalculateTimsheetDates(
|
||||
workReport.getWorkReportLines(),
|
||||
deletedWorkReportLinesSet);
|
||||
sumChargedEffortDAO.updateRelatedSumChargedEffortWithDeletedWorkReportLineSet(deletedWorkReportLinesSet);
|
||||
sumChargedEffortDAO
|
||||
.updateRelatedSumChargedEffortWithWorkReportLineSet(workReport
|
||||
.getWorkReportLines());
|
||||
|
||||
workReportDAO.save(workReport);
|
||||
sumChargedEffortDAO.recalculateTimesheetDates(orderElements);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -412,10 +417,14 @@ public class WorkReportModel extends IntegrationEntityModel implements
|
|||
//before deleting the report, update OrderElement.SumChargedHours
|
||||
try {
|
||||
workReportDAO.reattach(workReport);
|
||||
Set<OrderElement> orderElements = sumChargedEffortDAO
|
||||
.getOrderElementsToRecalculateTimsheetDates(null,
|
||||
workReport.getWorkReportLines());
|
||||
sumChargedEffortDAO
|
||||
.updateRelatedSumChargedEffortWithDeletedWorkReportLineSet(workReport
|
||||
.getWorkReportLines());
|
||||
workReportDAO.remove(workReport.getId());
|
||||
sumChargedEffortDAO.recalculateTimesheetDates(orderElements);
|
||||
} catch (InstanceNotFoundException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -143,6 +143,7 @@ public abstract class GenericRESTService<E extends IntegrationEntity,
|
|||
entity.validate();
|
||||
beforeSaving(entity);
|
||||
entityDAO.saveWithoutValidating(entity);
|
||||
afterSaving(entity);
|
||||
|
||||
return null;
|
||||
|
||||
|
|
@ -155,12 +156,23 @@ public abstract class GenericRESTService<E extends IntegrationEntity,
|
|||
}
|
||||
|
||||
/**
|
||||
* it adds operations that must be done before saving.
|
||||
* It allows to add operations that must be done before saving.
|
||||
*
|
||||
* Default implementation is empty.
|
||||
*/
|
||||
protected void beforeSaving(E entity) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* It allows to add operations that must be done after saving.
|
||||
*
|
||||
* Default implementation is empty.
|
||||
*/
|
||||
protected void afterSaving(E entity) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* It creates an entity from a DTO.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -22,7 +22,9 @@
|
|||
package org.libreplan.ws.workreports.impl;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.DELETE;
|
||||
|
|
@ -37,8 +39,8 @@ import javax.ws.rs.core.Response.Status;
|
|||
import org.libreplan.business.common.daos.IIntegrationEntityDAO;
|
||||
import org.libreplan.business.common.exceptions.InstanceNotFoundException;
|
||||
import org.libreplan.business.common.exceptions.ValidationException;
|
||||
import org.libreplan.business.orders.daos.IOrderElementDAO;
|
||||
import org.libreplan.business.orders.daos.ISumChargedEffortDAO;
|
||||
import org.libreplan.business.orders.entities.OrderElement;
|
||||
import org.libreplan.business.workreports.daos.IWorkReportDAO;
|
||||
import org.libreplan.business.workreports.daos.IWorkReportLineDAO;
|
||||
import org.libreplan.business.workreports.entities.WorkReport;
|
||||
|
|
@ -64,15 +66,14 @@ public class WorkReportServiceREST extends
|
|||
GenericRESTService<WorkReport, WorkReportDTO> implements
|
||||
IWorkReportService {
|
||||
|
||||
private Set<OrderElement> orderElements;
|
||||
|
||||
@Autowired
|
||||
private IWorkReportDAO workReportDAO;
|
||||
|
||||
@Autowired
|
||||
private IWorkReportLineDAO workReportLineDAO;
|
||||
|
||||
@Autowired
|
||||
private IOrderElementDAO orderElementDAO;
|
||||
|
||||
@Autowired
|
||||
private ISumChargedEffortDAO sumChargedEffortDAO;
|
||||
|
||||
|
|
@ -120,11 +121,19 @@ public class WorkReportServiceREST extends
|
|||
|
||||
@Override
|
||||
protected void beforeSaving(WorkReport entity) {
|
||||
orderElements = sumChargedEffortDAO
|
||||
.getOrderElementsToRecalculateTimsheetDates(
|
||||
entity.getWorkReportLines(), null);
|
||||
sumChargedEffortDAO
|
||||
.updateRelatedSumChargedEffortWithWorkReportLineSet(entity
|
||||
.getWorkReportLines());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void afterSaving(WorkReport entity) {
|
||||
sumChargedEffortDAO.recalculateTimesheetDates(orderElements);
|
||||
}
|
||||
|
||||
@Override
|
||||
@GET
|
||||
@Path("/{code}/")
|
||||
|
|
@ -140,10 +149,14 @@ public class WorkReportServiceREST extends
|
|||
public Response removeWorkReport(@PathParam("code") String code) {
|
||||
try {
|
||||
WorkReport workReport = workReportDAO.findByCode(code);
|
||||
Set<OrderElement> orderElements = sumChargedEffortDAO
|
||||
.getOrderElementsToRecalculateTimsheetDates(null,
|
||||
workReport.getWorkReportLines());
|
||||
sumChargedEffortDAO
|
||||
.updateRelatedSumChargedEffortWithDeletedWorkReportLineSet(workReport
|
||||
.getWorkReportLines());
|
||||
workReportDAO.remove(workReport.getId());
|
||||
sumChargedEffortDAO.recalculateTimesheetDates(orderElements);
|
||||
return Response.ok().build();
|
||||
} catch (InstanceNotFoundException e) {
|
||||
return Response.status(Status.NOT_FOUND).build();
|
||||
|
|
@ -157,10 +170,14 @@ public class WorkReportServiceREST extends
|
|||
public Response removeWorkReportLine(@PathParam("code") String code) {
|
||||
try {
|
||||
WorkReportLine workReportLine = workReportLineDAO.findByCode(code);
|
||||
Set<OrderElement> orderElements = sumChargedEffortDAO
|
||||
.getOrderElementsToRecalculateTimsheetDates(null,
|
||||
Collections.singleton(workReportLine));
|
||||
sumChargedEffortDAO
|
||||
.updateRelatedSumChargedEffortWithDeletedWorkReportLineSet(new HashSet<WorkReportLine>(
|
||||
Arrays.asList(workReportLine)));
|
||||
workReportLineDAO.remove(workReportLine.getId());
|
||||
sumChargedEffortDAO.recalculateTimesheetDates(orderElements);
|
||||
return Response.ok().build();
|
||||
} catch (InstanceNotFoundException e) {
|
||||
return Response.status(Status.NOT_FOUND).build();
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue