Implement constraint to check that only one WorkReportLine per task is finished
FEA: ItEr77S12AdaptPlanningAccordingTimesheets
This commit is contained in:
parent
a8ba46e505
commit
6c3a915b8d
6 changed files with 133 additions and 5 deletions
|
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
* This file is part of LibrePlan
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 Igalia, S.L.
|
||||||
|
*
|
||||||
|
* 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.libreplan.business.common;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utilities class. <br />
|
||||||
|
* @author Manuel Rego Casasnovas <mrego@igalia.com>
|
||||||
|
*/
|
||||||
|
public class Util {
|
||||||
|
|
||||||
|
public static boolean contains(Collection<? extends BaseEntity> collection,
|
||||||
|
BaseEntity entity) {
|
||||||
|
for (BaseEntity each : collection) {
|
||||||
|
if (each.getId().equals(entity.getId())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -69,4 +69,7 @@ public interface IWorkReportLineDAO extends
|
||||||
Pair<Date, Date> findMinAndMaxDatesByOrderElement(
|
Pair<Date, Date> findMinAndMaxDatesByOrderElement(
|
||||||
OrderElement orderElement);
|
OrderElement orderElement);
|
||||||
|
|
||||||
|
List<WorkReportLine> findByOrderElementNotInWorkReportAnotherTransaction(
|
||||||
|
OrderElement orderElement, WorkReport workReport);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,7 @@ import org.libreplan.business.workreports.entities.WorkReportLine;
|
||||||
import org.springframework.beans.factory.config.BeanDefinition;
|
import org.springframework.beans.factory.config.BeanDefinition;
|
||||||
import org.springframework.context.annotation.Scope;
|
import org.springframework.context.annotation.Scope;
|
||||||
import org.springframework.stereotype.Repository;
|
import org.springframework.stereotype.Repository;
|
||||||
|
import org.springframework.transaction.annotation.Propagation;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -168,4 +169,24 @@ public class WorkReportLineDAO extends IntegrationEntityDAO<WorkReportLine>
|
||||||
return Pair.create(min, max);
|
return Pair.create(min, max);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(readOnly = true, propagation = Propagation.REQUIRES_NEW)
|
||||||
|
public List<WorkReportLine> findByOrderElementNotInWorkReportAnotherTransaction(
|
||||||
|
OrderElement orderElement, WorkReport workReport) {
|
||||||
|
return findByOrderElementNotInWorkReport(orderElement, workReport);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private List<WorkReportLine> findByOrderElementNotInWorkReport(
|
||||||
|
OrderElement orderElement, WorkReport workReport) {
|
||||||
|
Criteria criteria = getSession().createCriteria(WorkReportLine.class);
|
||||||
|
|
||||||
|
criteria.add(Restrictions.eq("orderElement", orderElement));
|
||||||
|
if (!workReport.isNewObject()) {
|
||||||
|
criteria.add(Restrictions.ne("workReport", workReport));
|
||||||
|
}
|
||||||
|
|
||||||
|
return (List<WorkReportLine>) criteria.list();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@ import org.hibernate.validator.Valid;
|
||||||
import org.joda.time.LocalDate;
|
import org.joda.time.LocalDate;
|
||||||
import org.libreplan.business.common.IntegrationEntity;
|
import org.libreplan.business.common.IntegrationEntity;
|
||||||
import org.libreplan.business.common.Registry;
|
import org.libreplan.business.common.Registry;
|
||||||
|
import org.libreplan.business.common.Util;
|
||||||
import org.libreplan.business.common.entities.EntitySequence;
|
import org.libreplan.business.common.entities.EntitySequence;
|
||||||
import org.libreplan.business.common.entities.PersonalTimesheetsPeriodicityEnum;
|
import org.libreplan.business.common.entities.PersonalTimesheetsPeriodicityEnum;
|
||||||
import org.libreplan.business.common.exceptions.InstanceNotFoundException;
|
import org.libreplan.business.common.exceptions.InstanceNotFoundException;
|
||||||
|
|
@ -538,4 +539,20 @@ public class WorkReport extends IntegrationEntity implements
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@AssertTrue(message = "the same task is marked as finished by more than one timesheet line")
|
||||||
|
public boolean checkConstraintSameOrderElementFinishedBySeveralWorkReportLines() {
|
||||||
|
Set<OrderElement> finishedOrderElements = new HashSet<OrderElement>();
|
||||||
|
|
||||||
|
for (WorkReportLine line : workReportLines) {
|
||||||
|
if (line.isFinished()) {
|
||||||
|
if (Util.contains(finishedOrderElements, line.getOrderElement())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
finishedOrderElements.add(line.getOrderElement());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ package org.libreplan.business.workreports.entities;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang.StringUtils;
|
||||||
|
|
@ -563,4 +564,22 @@ public class WorkReportLine extends IntegrationEntity implements Comparable,
|
||||||
this.finished = finished;
|
this.finished = finished;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@AssertTrue(message = "there is a timesheet line in another work report marking as finished the same task")
|
||||||
|
public boolean checkConstraintOrderElementFinishedInAnotherWorkReport() {
|
||||||
|
if (!finished) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<WorkReportLine> lines = Registry.getWorkReportLineDAO()
|
||||||
|
.findByOrderElementNotInWorkReportAnotherTransaction(
|
||||||
|
orderElement, workReport);
|
||||||
|
for (WorkReportLine line : lines) {
|
||||||
|
if (line.isFinished()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -277,7 +277,9 @@ public class WorkReportCRUDController extends GenericForwardComposer implements
|
||||||
for (InvalidValue invalidValue : e.getInvalidValues()) {
|
for (InvalidValue invalidValue : e.getInvalidValues()) {
|
||||||
Object value = invalidValue.getBean();
|
Object value = invalidValue.getBean();
|
||||||
if (value instanceof WorkReport) {
|
if (value instanceof WorkReport) {
|
||||||
validateWorkReport();
|
if (validateWorkReport()) {
|
||||||
|
messagesForUser.showInvalidValues(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (value instanceof WorkReportLine) {
|
if (value instanceof WorkReportLine) {
|
||||||
WorkReportLine workReportLine = (WorkReportLine) invalidValue.getBean();
|
WorkReportLine workReportLine = (WorkReportLine) invalidValue.getBean();
|
||||||
|
|
@ -332,6 +334,7 @@ public class WorkReportCRUDController extends GenericForwardComposer implements
|
||||||
_("cannot be empty"));
|
_("cannot be empty"));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -456,6 +459,16 @@ public class WorkReportCRUDController extends GenericForwardComposer implements
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!workReportLine.checkConstraintOrderElementFinishedInAnotherWorkReport()) {
|
||||||
|
Checkbox checkboxFinished = getFinished(row);
|
||||||
|
if (checkboxFinished != null) {
|
||||||
|
String message = _("task is already marked as finished in another timesheet");
|
||||||
|
showInvalidMessage(checkboxFinished, message);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -470,7 +483,7 @@ public class WorkReportCRUDController extends GenericForwardComposer implements
|
||||||
*/
|
*/
|
||||||
private Timebox getTimeboxFinish(Row row) {
|
private Timebox getTimeboxFinish(Row row) {
|
||||||
try {
|
try {
|
||||||
int position = row.getChildren().size() - 5;
|
int position = row.getChildren().size() - 6;
|
||||||
return (Timebox) row.getChildren().get(position);
|
return (Timebox) row.getChildren().get(position);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
return null;
|
return null;
|
||||||
|
|
@ -484,7 +497,7 @@ public class WorkReportCRUDController extends GenericForwardComposer implements
|
||||||
*/
|
*/
|
||||||
private Timebox getTimeboxStart(Row row) {
|
private Timebox getTimeboxStart(Row row) {
|
||||||
try {
|
try {
|
||||||
int position = row.getChildren().size() - 6;
|
int position = row.getChildren().size() - 7;
|
||||||
return (Timebox) row.getChildren().get(position);
|
return (Timebox) row.getChildren().get(position);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
return null;
|
return null;
|
||||||
|
|
@ -498,13 +511,28 @@ public class WorkReportCRUDController extends GenericForwardComposer implements
|
||||||
*/
|
*/
|
||||||
private Listbox getTypeOfHours(Row row) {
|
private Listbox getTypeOfHours(Row row) {
|
||||||
try {
|
try {
|
||||||
int position = row.getChildren().size() - 3;
|
int position = row.getChildren().size() - 4;
|
||||||
return (Listbox) row.getChildren().get(position);
|
return (Listbox) row.getChildren().get(position);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Locates {@link Checkbox} finished in {@link Row}
|
||||||
|
* @param row
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private Checkbox getFinished(Row row) {
|
||||||
|
try {
|
||||||
|
int position = row.getChildren().size() - 3;
|
||||||
|
return (Checkbox) row.getChildren().get(position);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Locates {@link Texbox} code in {@link Row}
|
* Locates {@link Texbox} code in {@link Row}
|
||||||
* @param row
|
* @param row
|
||||||
|
|
@ -527,7 +555,7 @@ public class WorkReportCRUDController extends GenericForwardComposer implements
|
||||||
*/
|
*/
|
||||||
private Textbox getEffort(Row row) {
|
private Textbox getEffort(Row row) {
|
||||||
try {
|
try {
|
||||||
int position = row.getChildren().size() - 4;
|
int position = row.getChildren().size() - 5;
|
||||||
return (Textbox) row.getChildren().get(position);
|
return (Textbox) row.getChildren().get(position);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
return null;
|
return null;
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue