/*
* This file is part of LibrePlan
*
* Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e
* Desenvolvemento Tecnolóxico de Galicia
* Copyright (C) 2010-2011 Igalia, S.L.
*
* Copyright (C) 2011-2012 WirelessGalicia, 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.web.orders;
import static org.libreplan.web.I18nHelper._;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import org.apache.commons.lang.Validate;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.joda.time.LocalDate;
import org.libreplan.business.advance.bootstrap.PredefinedAdvancedTypes;
import org.libreplan.business.advance.daos.IAdvanceAssignmentDAO;
import org.libreplan.business.advance.daos.IAdvanceMeasurementDAO;
import org.libreplan.business.advance.daos.IAdvanceTypeDAO;
import org.libreplan.business.advance.entities.AdvanceAssignment;
import org.libreplan.business.advance.entities.AdvanceMeasurement;
import org.libreplan.business.advance.entities.AdvanceMeasurementComparator;
import org.libreplan.business.advance.entities.AdvanceType;
import org.libreplan.business.advance.entities.DirectAdvanceAssignment;
import org.libreplan.business.advance.entities.IndirectAdvanceAssignment;
import org.libreplan.business.advance.exceptions.DuplicateAdvanceAssignmentForOrderElementException;
import org.libreplan.business.advance.exceptions.DuplicateValueTrueReportGlobalAdvanceException;
import org.libreplan.business.common.exceptions.InstanceNotFoundException;
import org.libreplan.business.orders.daos.IOrderElementDAO;
import org.libreplan.business.orders.entities.Order;
import org.libreplan.business.orders.entities.OrderElement;
import org.libreplan.business.planner.entities.TaskElement;
import org.libreplan.business.planner.entities.consolidations.CalculatedConsolidatedValue;
import org.libreplan.business.planner.entities.consolidations.CalculatedConsolidation;
import org.libreplan.business.planner.entities.consolidations.Consolidation;
import org.libreplan.business.planner.entities.consolidations.NonCalculatedConsolidatedValue;
import org.libreplan.business.planner.entities.consolidations.NonCalculatedConsolidation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.zkoss.zul.SimpleXYModel;
import org.zkoss.zul.XYModel;
/**
* Service to manage the advance of a selected order element
*
* @author Susana Montes Pedreira <smontes@wirelessgalicia.com>
* @author Diego Pino García <dpino@igalia.com>
*/
@Service
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
public class ManageOrderElementAdvancesModel implements
IManageOrderElementAdvancesModel {
private static final Log LOG = LogFactory
.getLog(ManageOrderElementAdvancesModel.class);
@Autowired
private final IAdvanceTypeDAO advanceTypeDAO;
@Autowired
private final IOrderElementDAO orderElementDAO;
private OrderElement orderElement;
private DirectAdvanceAssignment advanceAssignment;
private boolean isIndirectAdvanceAssignment = false;
private List<AdvanceAssignment> listAdvanceAssignments;
private List<AdvanceType> listAdvanceTypes;
@Autowired
public ManageOrderElementAdvancesModel(
IAdvanceMeasurementDAO advanceMeasurementDAO,
IAdvanceTypeDAO advanceTypeDAO,
IOrderElementDAO orderElementDAO,
IAdvanceAssignmentDAO advanceAssignmentDAO) {
Validate.notNull(advanceMeasurementDAO);
this.advanceTypeDAO = advanceTypeDAO;
this.orderElementDAO = orderElementDAO;
}
@Override
public String getInfoAdvanceAssignment(){
if (this.advanceAssignment == null || this.orderElement == null) {
return "";
}
return getInfoAdvanceAssignment(this.advanceAssignment);
}
private String getInfoAdvanceAssignment(
DirectAdvanceAssignment assignment) {
if (assignment == null) {
return "";
}
if ((assignment.getAdvanceType() == null)
|| assignment.getMaxValue() == null) {
return "";
}
return _("{0} (max: {1})", assignment.getAdvanceType()
.getUnitName(), assignment.getMaxValue());
}
@Override
@Transactional(readOnly = true)
public List<AdvanceMeasurement> getAdvanceMeasurements() {
if (this.advanceAssignment == null || this.orderElement == null) {
return new ArrayList<AdvanceMeasurement>();
}
return new ArrayList<AdvanceMeasurement>(this.advanceAssignment
.getAdvanceMeasurements());
}
@Override
@Transactional(readOnly = true)
public List<AdvanceAssignment> getAdvanceAssignments() {
if (orderElement == null) {
return new ArrayList<AdvanceAssignment>();
}
return listAdvanceAssignments;
}
@Override
public void refreshChangesFromOrderElement() {
List<AdvanceAssignment> listAdvanceAssignmentsCopy = new ArrayList<AdvanceAssignment>(
listAdvanceAssignments);
fillAdvanceAssignmentList();
for (AdvanceAssignment advance : listAdvanceAssignmentsCopy) {
if ((!listAdvanceAssignments.contains(advance))
&& (advance instanceof DirectAdvanceAssignment)
&& (!advance.getAdvanceType().isQualityForm())
&& (!advance.getAdvanceType().isReadOnly())) {
listAdvanceAssignments.add(advance);
}
}
}
@Override
public void prepareEditAdvanceMeasurements(AdvanceAssignment assignment) {
if (assignment instanceof IndirectAdvanceAssignment) {
this.advanceAssignment = orderElement
.calculateFakeDirectAdvanceAssignment((IndirectAdvanceAssignment) assignment);
this.isIndirectAdvanceAssignment = true;
} else {
if (assignment instanceof DirectAdvanceAssignment) {
this.advanceAssignment = (DirectAdvanceAssignment) assignment;
this.isIndirectAdvanceAssignment = false;
}
}
}
@Override
@Transactional(readOnly = true)
public void initEdit(OrderElement orderElement) {
this.orderElement = orderElement;
this.advanceAssignment = null;
if (orderElement != null){
loadAdvanceTypes();
reattachmentOrderElement();
forceLoadAdvanceAssignmentsAndMeasurements();
fillAdvanceAssignmentList();
}
}
private void forceLoadAdvanceAssignmentsAndMeasurements() {
for (DirectAdvanceAssignment each : orderElement
.getDirectAdvanceAssignments()) {
forceLoadAdvanceConsolidatedValues(each);
each.getNonCalculatedConsolidation().size();
each.getAdvanceType().getUnitName();
}
for (IndirectAdvanceAssignment each : orderElement
.getIndirectAdvanceAssignments()) {
each.getCalculatedConsolidation().size();
each.getAdvanceType().getUnitName();
DirectAdvanceAssignment fakedDirect = orderElement
.calculateFakeDirectAdvanceAssignment(each);
if (fakedDirect != null) {
forceLoadAdvanceConsolidatedValues(fakedDirect);
} else {
LOG
.warn("Fake direct advance assignment shouldn't be NULL for type '"
+ each.getAdvanceType().getUnitName() + "'");
}
}
}
private void forceLoadAdvanceConsolidatedValues(
DirectAdvanceAssignment advance) {
for (AdvanceMeasurement measurement : advance.getAdvanceMeasurements()) {
for (NonCalculatedConsolidatedValue each : measurement
.getNonCalculatedConsolidatedValues()) {
each.getConsolidation().getConsolidatedUntil();
}
}
}
public void reattachmentOrderElement() {
orderElementDAO.reattach(orderElement);
}
private void fillAdvanceAssignmentList() {
listAdvanceAssignments = new ArrayList<AdvanceAssignment>();
for (DirectAdvanceAssignment each : orderElement
.getDirectAdvanceAssignments()) {
listAdvanceAssignments.add(each);
}
for (IndirectAdvanceAssignment each : orderElement
.getIndirectAdvanceAssignments()) {
listAdvanceAssignments.add(each);
}
}
@Override
public boolean addNewLineAdvanceAssignment() {
DirectAdvanceAssignment newAdvance = DirectAdvanceAssignment.create();
newAdvance.setOrderElement(orderElement);
// Set first advance type of the list as default
List<AdvanceType> listAdvanceType = getPossibleAdvanceTypes(newAdvance);
if (listAdvanceType.isEmpty()) {
return false;
}
// Create new progress type and add it to list
final AdvanceType progressType = first(listAdvanceType);
newAdvance.setAdvanceType(progressType);
newAdvance.setMaxValue(getMaxValue(progressType));
newAdvance.setReportGlobalAdvance(listAdvanceAssignments.isEmpty());
listAdvanceAssignments.add(newAdvance);
return true;
}
private AdvanceType first(List<AdvanceType> listAdvanceType) {
return listAdvanceType.get(0);
}
@Override
public BigDecimal getMaxValue(AdvanceType advanceType) {
if (advanceType != null) {
return advanceType.getDefaultMaxValue();
}
return BigDecimal.ZERO;
}
@Override
public AdvanceAssignment getSpreadAdvance() {
for(AdvanceAssignment advance : getAdvanceAssignments()){
if(advance.getReportGlobalAdvance()){
return advance;
}
}
return null;
}
@Override
public AdvanceMeasurement addNewLineAdvaceMeasurement() {
if (advanceAssignment != null) {
AdvanceMeasurement newMeasurement = createMeasurement();
addMeasurement(advanceAssignment, newMeasurement);
return newMeasurement;
}
return null;
}
private AdvanceMeasurement createMeasurement() {
AdvanceMeasurement result = AdvanceMeasurement.create();
result.setDate(new LocalDate());
result.setAdvanceAssignment(advanceAssignment);
return result;
}
private void addMeasurement(AdvanceAssignment assignment, AdvanceMeasurement measurement) {
if (!advanceAssignment.addAdvanceMeasurements(measurement)) {
measurement.setDate(null);
advanceAssignment.addAdvanceMeasurements(measurement);
}
}
@Override
public void removeLineAdvanceAssignment(AdvanceAssignment advance) {
advance.setOrderElement(null);
this.listAdvanceAssignments.remove(advance);
orderElement.removeAdvanceAssignment(advance);
this.advanceAssignment = null;
}
@Override
public void removeLineAdvanceMeasurement(AdvanceMeasurement measurement) {
this.advanceAssignment.removeAdvanceMeasurement(measurement);
}
@Override
public List<AdvanceType> getPossibleAdvanceTypes(
DirectAdvanceAssignment directAdvanceAssignment) {
if(orderElement == null){
return new ArrayList<AdvanceType>();
}
List<AdvanceType> advanceTypes = new ArrayList<AdvanceType>();
for (AdvanceType advanceType : this.listAdvanceTypes) {
if ((advanceType.getUnitName()
.equals(PredefinedAdvancedTypes.CHILDREN.getTypeName()))
|| (advanceType.isQualityForm())
|| advanceType.isReadOnly()) {
continue;
}
if (existsAdvanceTypeAlreadyInThisOrderElement(advanceType)) {
if ((directAdvanceAssignment.getAdvanceType() == null)
|| (!directAdvanceAssignment.getAdvanceType()
.getUnitName()
.equals(advanceType.getUnitName()))) {
continue;
}
}
// if the associated task of the order elemement or of some its
// children is subcontrated the advance type subcontractor is not
// permitted
if (advanceType.getUnitName().equals(
PredefinedAdvancedTypes.SUBCONTRACTOR.getTypeName())
&& hasAnySubcontratedTaskOnChildren()) {
continue;
}
advanceTypes.add(advanceType);
}
return getSpecificOrder(advanceTypes);
}
private List<AdvanceType> getSpecificOrder(List<AdvanceType> advanceTypes ){
Collections.sort(advanceTypes, new Comparator<AdvanceType>(){
@Override
public int compare(AdvanceType arg0, AdvanceType arg1) {
if((arg0 == null) || (arg0.getUnitName() == null)){
return -1;
}
if((arg1 == null) || (arg1.getUnitName() == null) || (arg1.getUnitName().equals(PredefinedAdvancedTypes.PERCENTAGE.getTypeName()))){
return 1;
}
if (arg0.getUnitName().equals(
PredefinedAdvancedTypes.PERCENTAGE.getTypeName())) {
return -1;
}
return (arg0.getUnitName().compareTo(arg1.getUnitName()));
}
});
return advanceTypes;
}
private boolean existsAdvanceTypeAlreadyInThisOrderElement(
AdvanceType advanceType) {
if (listAdvanceAssignments != null) {
for (AdvanceAssignment each : listAdvanceAssignments) {
if ((each.getAdvanceType() != null)
&& (each.getAdvanceType().getUnitName()
.equals(advanceType.getUnitName()))) {
return true;
}
}
}
return false;
}
@Transactional(readOnly = true)
private void loadAdvanceTypes() {
this.listAdvanceTypes = this.advanceTypeDAO.findActivesAdvanceTypes();
}
@Override
public boolean isReadOnlyAdvanceMeasurements(){
if (this.advanceAssignment == null) {
return true;
}
AdvanceType advanceType = this.advanceAssignment.getAdvanceType();
if (advanceType != null) {
if (advanceType.isQualityForm()) {
return true;
}
if (advanceType.isReadOnly()) {
return true;
}
}
if(isIndirectAdvanceAssignment){
return true;
}
return isSubcontratedAdvanceTypeAndSubcontratedTask(advanceAssignment);
}
@Override
public boolean isSubcontratedAdvanceTypeAndSubcontratedTask(
AdvanceAssignment advance) {
return (isSubcontratedAdvanceType(advance) && hasSubcontractedAssociatedTask(advance
.getOrderElement()));
}
@Override
public boolean isSubcontratedAdvanceType(AdvanceAssignment advance) {
AdvanceType advanceType = advance.getAdvanceType();
if (advanceType != null) {
if (advanceType.getUnitName().equals(
PredefinedAdvancedTypes.SUBCONTRACTOR.getTypeName())) {
return true;
}
}
return false;
}
@Override
public void cleanAdvance(DirectAdvanceAssignment advanceAssignment) {
if (advanceAssignment != null) {
advanceAssignment.clearAdvanceMeasurements();
}
}
@Override
public void resetAdvanceAssignment() {
this.advanceAssignment = null;
}
@Override
@Transactional(readOnly = true)
public void confirmSave() throws InstanceNotFoundException,
DuplicateAdvanceAssignmentForOrderElementException,
DuplicateValueTrueReportGlobalAdvanceException {
reattachmentOrderElement();
orderElement.updateAdvancePercentageTaskElement();
validateBasicData();
}
private void validateBasicData() throws InstanceNotFoundException,
DuplicateAdvanceAssignmentForOrderElementException,
DuplicateValueTrueReportGlobalAdvanceException{
updateRemoveAdvances();
for (AdvanceAssignment each : this.listAdvanceAssignments) {
if (each instanceof DirectAdvanceAssignment) {
validateBasicData((DirectAdvanceAssignment) each);
}
}
}
private void updateRemoveAdvances(){
for (AdvanceAssignment each : this.listAdvanceAssignments) {
AdvanceAssignment advance = yetExistAdvanceAssignment(each);
if (advance == null) {
removeAdvanceAssignment(each);
}
}
}
private void validateBasicData(
DirectAdvanceAssignment directAdvanceAssignment)
throws InstanceNotFoundException,DuplicateAdvanceAssignmentForOrderElementException,
DuplicateValueTrueReportGlobalAdvanceException{
if (directAdvanceAssignment.getVersion() == null) {
addAdvanceAssignment(directAdvanceAssignment);
}
}
private AdvanceAssignment yetExistAdvanceAssignment(
AdvanceAssignment assignment) {
for (AdvanceAssignment advance : this.orderElement
.getDirectAdvanceAssignments()) {
if (advance.getVersion() != null
&& advance.getId().equals(assignment.getId())) {
return advance;
}
}
return null;
}
@Transactional(readOnly = true)
private void addAdvanceAssignment(
DirectAdvanceAssignment newAdvanceAssignment)
throws DuplicateAdvanceAssignmentForOrderElementException,
DuplicateValueTrueReportGlobalAdvanceException{
if (newAdvanceAssignment.getReportGlobalAdvance()) {
this.orderElement.removeReportGlobalAdvanceAssignment();
}
this.orderElement.addAdvanceAssignment(newAdvanceAssignment);
}
private void removeAdvanceAssignment(AdvanceAssignment assignment) {
if (assignment != null) {
orderElement.removeAdvanceAssignment(assignment);
}
}
@Override
public boolean isPrecisionValid(AdvanceMeasurement advanceMeasurement) {
if ((this.advanceAssignment != null)
&& (this.advanceAssignment.getAdvanceType() != null)) {
return advanceMeasurement.isValidPrecisionConstraint();
}
return true;
}
@Override
public boolean greatThanMaxValue(AdvanceMeasurement advanceMeasurement) {
if (this.advanceAssignment == null
|| this.advanceAssignment.getMaxValue() == null) {
return false;
}
return !(advanceMeasurement.isValueIsLessThanMaxValueConstraint());
}
@Override
public boolean lessThanPreviousMeasurements() {
if (this.advanceAssignment == null) {
return false;
}
return !(this.advanceAssignment.isValidAdvanceMeasurementsConstraint());
}
@Override
public boolean isDistinctValidDate(LocalDate value,
AdvanceMeasurement newAdvanceMeasurement) {
if (this.advanceAssignment == null) {
return true;
}
for (AdvanceMeasurement advanceMeasurement : advanceAssignment
.getAdvanceMeasurements()) {
LocalDate oldDate = advanceMeasurement.getDate();
if (oldDate != null
&& !newAdvanceMeasurement.equals(advanceMeasurement)
&& oldDate.compareTo(new LocalDate(value)) == 0) {
return false;
}
}
return true;
}
@Override
public BigDecimal getUnitPrecision(){
if (this.advanceAssignment == null) {
return BigDecimal.ZERO;
}
return this.advanceAssignment.getAdvanceType().getUnitPrecision();
}
@Override
@Transactional(readOnly = true)
public AdvanceMeasurement getLastAdvanceMeasurement(
DirectAdvanceAssignment assignment) {
if (assignment != null) {
SortedSet<AdvanceMeasurement> advanceMeasurements = assignment
.getAdvanceMeasurements();
if (advanceMeasurements.size() > 0) {
return advanceMeasurements.first();
}
}
return null;
}
@Override
public void sortListAdvanceMeasurement() {
if (advanceAssignment != null) {
ArrayList<AdvanceMeasurement> advanceMeasurements = new ArrayList<AdvanceMeasurement>(
advanceAssignment.getAdvanceMeasurements());
Collections.sort(advanceMeasurements,
new AdvanceMeasurementComparator());
TreeSet<AdvanceMeasurement> measurements = new TreeSet<AdvanceMeasurement>(
new AdvanceMeasurementComparator());
measurements.addAll(advanceMeasurements);
this.advanceAssignment
.setAdvanceMeasurements(measurements);
}
}
@Override
public BigDecimal getPercentageAdvanceMeasurement(
AdvanceMeasurement advanceMeasurement) {
AdvanceAssignment assignment = advanceMeasurement
.getAdvanceAssignment();
if (assignment == null) {
return BigDecimal.ZERO;
}
BigDecimal maxValue;
if (assignment instanceof IndirectAdvanceAssignment) {
maxValue = orderElement.calculateFakeDirectAdvanceAssignment(
(IndirectAdvanceAssignment) assignment).getMaxValue();
} else {
maxValue = ((DirectAdvanceAssignment) assignment)
.getMaxValue();
}
if (maxValue.compareTo(BigDecimal.ZERO) <= 0) {
return BigDecimal.ZERO;
}
BigDecimal value = advanceMeasurement.getValue();
if (value == null) {
return BigDecimal.ZERO;
}
BigDecimal division = value.divide(maxValue.setScale(2), 4,
RoundingMode.DOWN);
return (division.multiply(new BigDecimal(100))).setScale(2,
RoundingMode.DOWN);
}
@Override
@Transactional(readOnly = true)
public DirectAdvanceAssignment calculateFakeDirectAdvanceAssignment(
IndirectAdvanceAssignment indirectAdvanceAssignment) {
if ((orderElement == null) || (orderElement.isLeaf())) {
return null;
}
reattachmentOrderElement();
return orderElement
.calculateFakeDirectAdvanceAssignment(indirectAdvanceAssignment);
}
@Override
@Transactional(readOnly = true)
public BigDecimal getAdvancePercentageChildren() {
if ((orderElement == null) || orderElement.isLeaf()) {
return null;
}
reattachmentOrderElement();
return orderElement.getAdvancePercentageChildren();
}
@Override
@Transactional(readOnly = true)
public XYModel getChartData(Set<AdvanceAssignment> selectedAdvances) {
XYModel xymodel = new SimpleXYModel();
for (AdvanceAssignment each : selectedAdvances) {
DirectAdvanceAssignment directAdvanceAssignment;
if (each instanceof DirectAdvanceAssignment) {
directAdvanceAssignment = (DirectAdvanceAssignment) each;
} else {
directAdvanceAssignment = calculateFakeDirectAdvanceAssignment((IndirectAdvanceAssignment) each);
}
if (directAdvanceAssignment != null) {
String title = getInfoAdvanceAssignment(directAdvanceAssignment);
SortedSet<AdvanceMeasurement> listAdvanceMeasurements = directAdvanceAssignment
.getAdvanceMeasurements();
if (listAdvanceMeasurements.size() > 1) {
for (AdvanceMeasurement advanceMeasurement : listAdvanceMeasurements) {
BigDecimal value = advanceMeasurement.getValue();
if ((selectedAdvances.size() > 1) && (value != null) && (value.compareTo(BigDecimal.ZERO) > 0)) {
BigDecimal maxValue = directAdvanceAssignment
.getMaxValue();
value = value.setScale(2).divide(maxValue,
RoundingMode.DOWN);
}
LocalDate date = advanceMeasurement.getDate();
if ((value != null) && (date != null)) {
xymodel.addValue(title, Long.valueOf(date
.toDateTimeAtStartOfDay().getMillis()),
value);
}
}
}
}
}
return xymodel;
}
@Override
@Transactional(readOnly = true)
public boolean hasConsolidatedAdvances(AdvanceAssignment advance) {
if (advance instanceof DirectAdvanceAssignment) {
if ((advance.getReportGlobalAdvance())
&& (!((DirectAdvanceAssignment) advance)
.getNonCalculatedConsolidation().isEmpty())) {
return true;
}
return ((!((DirectAdvanceAssignment) advance).isFake()) && (!canBeRemovedAllAdvanceMeasurements((DirectAdvanceAssignment) advance)));
} else {
return ((advance.getReportGlobalAdvance()) && (!((IndirectAdvanceAssignment) advance)
.getCalculatedConsolidation().isEmpty()));
}
}
private boolean canBeRemovedAllAdvanceMeasurements(
DirectAdvanceAssignment advance) {
Iterator<AdvanceMeasurement> iterator = advance
.getAdvanceMeasurements().iterator();
while (iterator.hasNext()) {
if (!canRemoveOrChange(iterator.next())) {
return false;
}
}
return true;
}
@Transactional(readOnly = true)
public boolean canRemoveOrChange(AdvanceMeasurement advanceMeasurement) {
return (!hasConsolidatedAdvances(advanceMeasurement) && !isAlreadyReportedProgress(advanceMeasurement));
}
@Transactional(readOnly = true)
public boolean hasConsolidatedAdvances(AdvanceMeasurement advanceMeasurement) {
return hasConsolidatedAdvances(advanceMeasurement,
isIndirectAdvanceAssignment);
}
private boolean hasConsolidatedAdvances(
AdvanceMeasurement advanceMeasurement,
boolean isIndirectAdvanceAssignment) {
if (isIndirectAdvanceAssignment) {
return false;
}
if (!advanceMeasurement.getNonCalculatedConsolidatedValues().isEmpty()) {
return true;
}
return findIndirectConsolidation(advanceMeasurement);
}
@Override
@Transactional(readOnly = true)
public boolean isQualityForm(AdvanceAssignment advance) {
AdvanceType advanceType = advance.getAdvanceType();
advanceTypeDAO.reattach(advanceType);
return advanceType.isQualityForm();
}
@Override
@Transactional(readOnly = true)
public boolean isReadOnly(AdvanceAssignment advance) {
AdvanceType advanceType = advance.getAdvanceType();
advanceTypeDAO.reattach(advanceType);
return advanceType.isReadOnly();
}
@Override
@Transactional(readOnly = true)
public boolean findIndirectConsolidation(
AdvanceMeasurement advanceMeasurement) {
AdvanceAssignment advance = advanceMeasurement.getAdvanceAssignment();
if ((orderElement != null) && (orderElement.getParent() != null) && (advance instanceof DirectAdvanceAssignment)) {
orderElementDAO.reattach(orderElement);
Set<IndirectAdvanceAssignment> indirects = getSpreadIndirectAdvanceAssignmentWithSameType(
orderElement, advance);
for (IndirectAdvanceAssignment indirect : indirects) {
if (findConsolidatedAdvance(indirect
.getCalculatedConsolidation(), advanceMeasurement)) {
return true;
}
}
}
return false;
}
private Set<IndirectAdvanceAssignment> getSpreadIndirectAdvanceAssignmentWithSameType(
OrderElement orderElement, AdvanceAssignment advance) {
List<String> types = new ArrayList<String>();
types.add(advance.getAdvanceType().getUnitName());
if (advance.getReportGlobalAdvance()) {
types.add(PredefinedAdvancedTypes.CHILDREN.getTypeName());
}
return getSpreadIndirectAdvanceAssignmentWithSameType(orderElement,
types);
}
private Set<IndirectAdvanceAssignment> getSpreadIndirectAdvanceAssignmentWithSameType(
OrderElement orderElement, List<String> types) {
Set<IndirectAdvanceAssignment> result = new HashSet<IndirectAdvanceAssignment>();
for (IndirectAdvanceAssignment indirect : orderElement
.getIndirectAdvanceAssignments()) {
if ((indirect.getReportGlobalAdvance())
&& (types.contains(indirect.getAdvanceType().getUnitName()))) {
result.add(indirect);
}
}
OrderElement parent = orderElement.getParent();
if (parent != null) {
result.addAll(getSpreadIndirectAdvanceAssignmentWithSameType(
parent, types));
}
return result;
}
private boolean findConsolidatedAdvance(
Set<CalculatedConsolidation> consolidations,
AdvanceMeasurement advance) {
for (CalculatedConsolidation consolidation : consolidations) {
for (CalculatedConsolidatedValue value : consolidation
.getCalculatedConsolidatedValues()) {
if ((value.getDate() != null) && (advance.getDate() != null)
&& (value.getDate().compareTo(advance.getDate()) == 0)) {
return true;
}
}
}
return false;
}
@Override
public LocalDate getLastConsolidatedMeasurementDate(
AdvanceAssignment advance) {
List<Consolidation> consolidations = new ArrayList<Consolidation>();
Set<NonCalculatedConsolidation> nonCalculatedConsolidations = ((DirectAdvanceAssignment) advance)
.getNonCalculatedConsolidation();
consolidations.addAll(nonCalculatedConsolidations);
if (consolidations.isEmpty()) {
Set<IndirectAdvanceAssignment> indirects = getSpreadIndirectAdvanceAssignmentWithSameType(
orderElement, advance);
for (IndirectAdvanceAssignment indirect : indirects) {
consolidations.addAll(indirect.getCalculatedConsolidation());
}
}
if (consolidations.isEmpty()) {
return null;
}
Collections.sort(consolidations, new Comparator<Consolidation>() {
@Override
public int compare(Consolidation o1, Consolidation o2) {
return o1.getConsolidatedUntil().compareTo(
o2.getConsolidatedUntil());
}
});
return consolidations.get(consolidations.size() - 1)
.getConsolidatedUntil();
}
@Override
public boolean hasAnyConsolidatedAdvanceCurrentOrderElement() {
if (orderElement == null) {
return false;
}
return orderElement.hasAnyConsolidatedAdvance();
}
@Override
public boolean hasAnySubcontratedTaskOnChildren() {
List<OrderElement> list = new ArrayList<OrderElement>();
list.add(orderElement);
list.addAll(orderElement.getAllChildren());
for (OrderElement child : list) {
if (hasSubcontractedAssociatedTask(child)) {
return true;
}
}
return false;
}
public boolean hasSubcontractedAssociatedTask(OrderElement orderElement) {
for (TaskElement task : orderElement.getTaskElements()) {
if (task.isSubcontracted()) {
return true;
}
}
return false;
}
@Override
public Boolean isAlreadyReportedProgress(AdvanceMeasurement measure) {
if (measure != null && !measure.isNewObject()) {
return isAlreadyReportedProgressWith(measure.getDate());
}
return false;
}
@Override
public Boolean isAlreadyReportedProgressWith(LocalDate date) {
if (isSubcontractedByCustomer() && isSubcontratedAdvanceType(advanceAssignment)) {
LocalDate lastReported = getLastReportedProgressToCustomer();
return (date != null && lastReported != null && date.compareTo(lastReported) <= 0);
}
return false;
}
private LocalDate getLastReportedProgressToCustomer() {
return getLastReportedProgressToCustomerOf(advanceAssignment);
}
private LocalDate getLastReportedProgressToCustomerOf(DirectAdvanceAssignment advanceAssignment) {
if (advanceAssignment != null && isSubcontractedByCustomer()) {
AdvanceMeasurement lastAdvanceMeasurementReported = null;
for (AdvanceMeasurement advanceMeasurement : advanceAssignment.getAdvanceMeasurements()) {
if (advanceMeasurement.getCommunicationDate() != null) {
if (lastAdvanceMeasurementReported == null) {
lastAdvanceMeasurementReported = advanceMeasurement;
} else {
if (advanceMeasurement.getCommunicationDate().compareTo(
lastAdvanceMeasurementReported.getCommunicationDate()) > 0) {
lastAdvanceMeasurementReported = advanceMeasurement;
}
}
}
}
return (lastAdvanceMeasurementReported != null) ? lastAdvanceMeasurementReported
.getDate() : null;
}
return null;
}
private Boolean isSubcontractedByCustomer() {
if (orderElement != null) {
Order order = orderElement.getOrder();
if (order != null && order.getExternalCode() != null) {
return true;
}
}
return false;
}
@Override
public boolean hasReportedProgress(AdvanceAssignment advance) {
if (advance instanceof DirectAdvanceAssignment) {
return isSubcontractedByCustomer()
&& isSubcontratedAdvanceType(advance)
&& (getLastReportedProgressToCustomerOf((DirectAdvanceAssignment) advance) != null);
}
return false;
}
}