diff --git a/libreplan-business/src/main/java/org/libreplan/business/orders/daos/ISumChargedEffortDAO.java b/libreplan-business/src/main/java/org/libreplan/business/orders/daos/ISumChargedEffortDAO.java index 10301a50a..19d0fc17c 100644 --- a/libreplan-business/src/main/java/org/libreplan/business/orders/daos/ISumChargedEffortDAO.java +++ b/libreplan-business/src/main/java/org/libreplan/business/orders/daos/ISumChargedEffortDAO.java @@ -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 null as param if you only have one of the sets. + */ + Set getOrderElementsToRecalculateTimsheetDates( + Set workReportLines, + Set deletedWorkReportLinesSet); + + /** + * Recalulates the first and last timesheets dates for each + * {@link OrderElement} in the {@link Set}. + */ + void recalculateTimesheetDates(Set orderElements); + } diff --git a/libreplan-business/src/main/java/org/libreplan/business/orders/daos/SumChargedEffortDAO.java b/libreplan-business/src/main/java/org/libreplan/business/orders/daos/SumChargedEffortDAO.java index aad876f66..907ce3bb9 100644 --- a/libreplan-business/src/main/java/org/libreplan/business/orders/daos/SumChargedEffortDAO.java +++ b/libreplan-business/src/main/java/org/libreplan/business/orders/daos/SumChargedEffortDAO.java @@ -70,6 +70,9 @@ public class SumChargedEffortDAO extends @Autowired private IOrderDAO orderDAO; + @Autowired + private IOrderElementDAO orderElementDAO; + private Map 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 calculateFirstAndLastTimesheetDates( + private Pair calculateTimesheetDates( OrderElement orderElement) { Pair minMax = workReportLineDAO .findMinAndMaxDatesByOrderElement(orderElement); @@ -292,18 +296,21 @@ public class SumChargedEffortDAO extends addIfNotNull(maxDates, minMax.getSecond()); for (OrderElement child : orderElement.getChildren()) { - Pair minMaxChild = calculateFirstAndLastTimesheetDates(child); + Pair 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 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 list, Date date) { @@ -312,4 +319,101 @@ public class SumChargedEffortDAO extends } } + @Override + @Transactional(readOnly = true) + public Set getOrderElementsToRecalculateTimsheetDates( + Set workReportLines, + Set deletedWorkReportLines) { + Set orderElements = new HashSet(); + + if (workReportLines != null) { + for (final WorkReportLine workReportLine : workReportLines) { + if (!workReportLine.isNewObject()) { + OrderElement previousOrderElement = transactionService + .runOnAnotherTransaction(new IOnTransaction() { + @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 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 minMax = workReportLineDAO + .findMinAndMaxDatesByOrderElement(orderElement); + + Set minDates = new HashSet(); + Set maxDates = new HashSet(); + + 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 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); + } + } diff --git a/libreplan-webapp/src/main/java/org/libreplan/web/users/dashboard/PersonalTimesheetModel.java b/libreplan-webapp/src/main/java/org/libreplan/web/users/dashboard/PersonalTimesheetModel.java index df067c439..95dd7796f 100644 --- a/libreplan-webapp/src/main/java/org/libreplan/web/users/dashboard/PersonalTimesheetModel.java +++ b/libreplan-webapp/src/main/java/org/libreplan/web/users/dashboard/PersonalTimesheetModel.java @@ -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 orderElements = sumChargedEffortDAO + .getOrderElementsToRecalculateTimsheetDates( + workReport.getWorkReportLines(), null); sumChargedEffortDAO .updateRelatedSumChargedEffortWithWorkReportLineSet(workReport .getWorkReportLines()); workReport.generateWorkReportLineCodes(entitySequenceDAO .getNumberOfDigitsCode(EntityNameEnum.WORK_REPORT)); workReportDAO.save(workReport); + sumChargedEffortDAO.recalculateTimesheetDates(orderElements); } resetModifiedFields(); diff --git a/libreplan-webapp/src/main/java/org/libreplan/web/workreports/WorkReportModel.java b/libreplan-webapp/src/main/java/org/libreplan/web/workreports/WorkReportModel.java index f05831956..70de3ad76 100644 --- a/libreplan-webapp/src/main/java/org/libreplan/web/workreports/WorkReportModel.java +++ b/libreplan-webapp/src/main/java/org/libreplan/web/workreports/WorkReportModel.java @@ -274,12 +274,17 @@ public class WorkReportModel extends IntegrationEntityModel implements @Override @Transactional public void confirmSave() throws ValidationException { + Set 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 orderElements = sumChargedEffortDAO + .getOrderElementsToRecalculateTimsheetDates(null, + workReport.getWorkReportLines()); sumChargedEffortDAO .updateRelatedSumChargedEffortWithDeletedWorkReportLineSet(workReport .getWorkReportLines()); workReportDAO.remove(workReport.getId()); + sumChargedEffortDAO.recalculateTimesheetDates(orderElements); } catch (InstanceNotFoundException e) { throw new RuntimeException(e); } diff --git a/libreplan-webapp/src/main/java/org/libreplan/ws/common/impl/GenericRESTService.java b/libreplan-webapp/src/main/java/org/libreplan/ws/common/impl/GenericRESTService.java index 278bad001..2e324e383 100644 --- a/libreplan-webapp/src/main/java/org/libreplan/ws/common/impl/GenericRESTService.java +++ b/libreplan-webapp/src/main/java/org/libreplan/ws/common/impl/GenericRESTService.java @@ -143,6 +143,7 @@ public abstract class GenericRESTService implements IWorkReportService { + private Set 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 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 orderElements = sumChargedEffortDAO + .getOrderElementsToRecalculateTimsheetDates(null, + Collections.singleton(workReportLine)); sumChargedEffortDAO .updateRelatedSumChargedEffortWithDeletedWorkReportLineSet(new HashSet( Arrays.asList(workReportLine))); workReportLineDAO.remove(workReportLine.getId()); + sumChargedEffortDAO.recalculateTimesheetDates(orderElements); return Response.ok().build(); } catch (InstanceNotFoundException e) { return Response.status(Status.NOT_FOUND).build();