/*
* 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.
*
* 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.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
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.entities.AdvanceAssignment;
import org.libreplan.business.advance.entities.AdvanceMeasurement;
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.entities.OrderElement;
import org.libreplan.web.common.IMessagesForUser;
import org.libreplan.web.common.Level;
import org.libreplan.web.common.MessagesForUser;
import org.libreplan.web.common.Util;
import org.zkoss.util.IllegalSyntaxException;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.WrongValueException;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zk.ui.event.Events;
import org.zkoss.zk.ui.util.GenericForwardComposer;
import org.zkoss.zkplus.spring.SpringUtil;
import org.zkoss.zul.Button;
import org.zkoss.zul.Chart;
import org.zkoss.zul.Checkbox;
import org.zkoss.zul.Combobox;
import org.zkoss.zul.Comboitem;
import org.zkoss.zul.Constraint;
import org.zkoss.zul.Datebox;
import org.zkoss.zul.Decimalbox;
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.Radio;
import org.zkoss.zul.Tabbox;
import org.zkoss.zul.XYModel;
/**
* Controller for show the advances of the selected order element.
* <br />
*
* @author Susana Montes Pedreria <smontes@wirelessgalicia.com>
*/
public class ManageOrderElementAdvancesController extends GenericForwardComposer {
private static final Log LOG = LogFactory .getLog(ManageOrderElementAdvancesController.class);
private IMessagesForUser messagesForUser;
private int indexSelectedItem = -1;
private IManageOrderElementAdvancesModel manageOrderElementAdvancesModel;
private AdvanceTypeListRenderer advanceTypeListRenderer = new AdvanceTypeListRenderer();
private AdvanceMeasurementRenderer advanceMeasurementRenderer = new AdvanceMeasurementRenderer();
private Set<AdvanceAssignment> selectedAdvances = new HashSet<>();
private Component messagesContainerAdvances;
private Tabbox tabboxOrderElement;
private IOrderElementModel orderElementModel;
private Listbox editAdvances;
private Listbox editAdvancesMeasurement;
private Chart chart;
public ManageOrderElementAdvancesController() {
manageOrderElementAdvancesModel =
(IManageOrderElementAdvancesModel) SpringUtil.getBean("manageOrderElementAdvancesModel");
}
@Override
public void doAfterCompose(Component comp) throws Exception {
super.doAfterCompose(comp);
comp.setAttribute("manageOrderElementAdvancesController", this, true);
messagesForUser = new MessagesForUser(messagesContainerAdvances);
}
public List<AdvanceMeasurement> getAdvanceMeasurements() {
List<AdvanceMeasurement> measurements = manageOrderElementAdvancesModel.getAdvanceMeasurements();
Collections.reverse(measurements);
return measurements;
}
public List<AdvanceAssignment> getAdvanceAssignments() {
return manageOrderElementAdvancesModel.getAdvanceAssignments();
}
public boolean close() {
return save();
}
private void validate() {
if ( !validateDataForm() )
throw new IllegalSyntaxException(_("values are not valid, the values must not be null"));
if ( !validateReportGlobalAdvance() )
throw new IllegalSyntaxException(_("Invalid Spread values. At least one value should be true"));
}
public boolean save() {
try {
validate();
manageOrderElementAdvancesModel.confirmSave();
return true;
} catch (DuplicateAdvanceAssignmentForOrderElementException e) {
messagesForUser.showMessage(Level.ERROR, _("Cannot create another progress of the same type"));
} catch (DuplicateValueTrueReportGlobalAdvanceException e) {
messagesForUser.showMessage(Level.ERROR, _("Invalid Spread values. At least one value should be true"));
} catch (IllegalSyntaxException e) {
messagesForUser.showMessage(Level.ERROR, e.getMessage());
} catch (InstanceNotFoundException e) {
messagesForUser.showMessage(Level.ERROR, e.getMessage());
LOG.error("Couldn't find element: " + e.getKey(), e);
}
increaseScreenHeight();
return false;
}
public void openWindow(IOrderElementModel orderElementModel) {
setOrderElementModel(orderElementModel);
manageOrderElementAdvancesModel.initEdit(getOrderElement());
selectedAdvances.clear();
selectedAdvances.addAll(getAdvanceAssignments());
createAndLoadBindings();
selectSpreadAdvanceLine();
}
public void openWindow(OrderElement orderElement) {
manageOrderElementAdvancesModel.initEdit(orderElement);
selectedAdvances.clear();
selectedAdvances.addAll(getAdvanceAssignments());
createAndLoadBindings();
selectSpreadAdvanceLine();
}
void createAndLoadBindings() {
Util.createBindingsFor(self);
Util.reloadBindings(self);
}
public void setOrderElementModel(IOrderElementModel orderElementModel) {
this.orderElementModel = orderElementModel;
}
private OrderElement getOrderElement() {
return orderElementModel.getOrderElement();
}
private void increaseScreenHeight() {
if ( (tabboxOrderElement != null) && (tabboxOrderElement.getHeight() == null ||
!"680px".equals(tabboxOrderElement.getHeight())) ) {
tabboxOrderElement.setHeight("680px");
tabboxOrderElement.invalidate();
}
}
private void reloadAdvances() {
Util.reloadBindings(self);
setSelectedAdvanceLine();
}
private void setSelectedAdvanceLine() {
if ( (indexSelectedItem > -1) && (indexSelectedItem < editAdvances.getItemCount()) ) {
editAdvances.setSelectedItem(editAdvances.getItemAtIndex(indexSelectedItem));
editAdvances.invalidate();
}
}
public void selectAdvanceLine(Listitem selectedItem) {
/* Validate the previous advance line before changing the selected advance */
setSelectedAdvanceLine();
findErrorsInMeasurements();
/*
* Preparation to select the advance line.
* Set the current selected index that will show when the grid reloads.
*/
if ( selectedItem != null ) {
AdvanceAssignment advance = selectedItem.getValue();
indexSelectedItem = editAdvances.getIndexOfItem(selectedItem);
showInfoAbout(advance);
prepareEditAdvanceMeasurements(advance);
reloadAdvances();
}
}
public void selectAdvanceLine(int index) {
indexSelectedItem = index;
if ( (indexSelectedItem >= 0) && (indexSelectedItem < getAdvanceAssignments().size()) ) {
prepareEditAdvanceMeasurements(getAdvanceAssignments().get(
indexSelectedItem));
}
reloadAdvances();
}
public void selectSpreadAdvanceLine() {
AdvanceAssignment advance = manageOrderElementAdvancesModel.getSpreadAdvance();
if ( advance != null ) {
indexSelectedItem = getAdvanceAssignments().indexOf(advance);
showInfoAbout(advance);
prepareEditAdvanceMeasurements(advance);
} else {
selectAdvanceLine(getAdvanceAssignments().size() - 1);
}
reloadAdvances();
}
private void showInfoAbout(AdvanceAssignment advance) {
if ( manageOrderElementAdvancesModel.isSubcontractedAdvanceTypeAndSubcontractedTask(advance) )
showErrorMessage(_("Subcontractor values are read only " +
"because they were reported by the subcontractor company."));
}
public void prepareEditAdvanceMeasurements(AdvanceAssignment advance) {
if ( advance != null && advance.getAdvanceType() != null ) {
manageOrderElementAdvancesModel.prepareEditAdvanceMeasurements(advance);
}
}
/** It should be public! */
public void goToCreateLineAdvanceAssignment() {
findErrorsInMeasurements();
boolean fineResult = manageOrderElementAdvancesModel.addNewLineAdvanceAssignment();
if ( fineResult ) {
int position = getAdvanceAssignments().size() - 1;
selectAdvanceLine(position);
selectedAdvances.add(getAdvanceAssignments().get(position));
} else {
showMessageNotAddMoreAdvances();
}
}
public void goToCreateLineAdvanceMeasurement() {
AdvanceMeasurement newMeasure = manageOrderElementAdvancesModel.addNewLineAdvanceMeasurement();
if ( (newMeasure != null) &&
(manageOrderElementAdvancesModel.hasConsolidatedAdvances(newMeasure.getAdvanceAssignment())) )
newMeasure.setDate(null);
reloadAdvances();
}
public void goToRemoveLineAdvanceAssignment(Listitem listItem) {
AdvanceAssignment advance = listItem.getValue();
if ( (editAdvances.getItemCount() > 1) && (advance.getReportGlobalAdvance()) )
showMessageDeleteSpread();
else if ( manageOrderElementAdvancesModel.hasConsolidatedAdvances(advance) )
showErrorMessage(_("Progress Assignment cannot be deleted or changed. " +
"Progress Assignment contains Progress Consolidations values"));
else {
manageOrderElementAdvancesModel.removeLineAdvanceAssignment(advance);
selectedAdvances.remove(advance);
if ( indexSelectedItem == editAdvances.getIndexOfItem(listItem) )
selectSpreadAdvanceLine();
else
if ( indexSelectedItem > editAdvances.getIndexOfItem(listItem) )
selectAdvanceLine(indexSelectedItem - 1);
else {
prepareEditAdvanceMeasurements(getAdvanceAssignments().get(indexSelectedItem));
reloadAdvances();
}
}
}
public void goToRemoveLineAdvanceMeasurement(Listitem listItem) {
AdvanceMeasurement advance = listItem.getValue();
if ( manageOrderElementAdvancesModel.canRemoveOrChange(advance) ) {
manageOrderElementAdvancesModel.removeLineAdvanceMeasurement(advance);
reloadAdvances();
} else
showErrorMessage(_("Progress Measurement cannot be deleted. Progress Measurement already consolidated"));
}
/** It should be public! */
public String getInfoAdvance() {
String infoAdvanceAssignment = manageOrderElementAdvancesModel.getInfoAdvanceAssignment();
return infoAdvanceAssignment.isEmpty()
? _("Progress measurements")
: _("Progress measurements") + ": " + infoAdvanceAssignment;
}
public boolean isReadOnlyAdvanceMeasurements() {
return manageOrderElementAdvancesModel.isReadOnlyAdvanceMeasurements();
}
/** It should be public! */
public AdvanceTypeListRenderer getAdvancesRenderer() {
return advanceTypeListRenderer;
}
public void updatesValue() {
this.setPercentage();
this.setCurrentValue();
}
public class AdvanceTypeListRenderer implements ListitemRenderer {
@Override
public void render(Listitem listitem, Object o, int i) throws Exception {
final AdvanceAssignment advance = (AdvanceAssignment) o;
listitem.setValue(advance);
Boolean readOnlyAdvance = false;
boolean isQualityForm = false;
if ( advance.getAdvanceType() != null ) {
isQualityForm = manageOrderElementAdvancesModel.isQualityForm(advance);
readOnlyAdvance = manageOrderElementAdvancesModel.isReadOnly(advance);
if ( !readOnlyAdvance &&
manageOrderElementAdvancesModel.isSubcontractedAdvanceTypeAndSubcontractedTask(advance) )
readOnlyAdvance = true;
}
if ( (advance instanceof DirectAdvanceAssignment) &&
((DirectAdvanceAssignment) advance).getAdvanceMeasurements().isEmpty() &&
!isQualityForm &&
!readOnlyAdvance )
appendComboboxAdvanceType(listitem);
else
appendLabelAdvanceType(listitem);
appendDecimalBoxMaxValue(listitem, isQualityForm || readOnlyAdvance);
appendDecimalBoxValue(listitem);
appendLabelPercentage(listitem);
appendDateBoxDate(listitem);
appendRadioSpread(listitem);
appendCalculatedCheckbox(listitem);
appendChartCheckbox(listitem);
appendOperations(listitem, readOnlyAdvance);
}
private void appendDecimalBoxMaxValue(final Listitem listItem, boolean isQualityFormOrReadOnly) {
final AdvanceAssignment advanceAssignment = listItem.getValue();
final Decimalbox maxValue = new Decimalbox();
maxValue.setScale(2);
maxValue.setSclass("decimal-max-value");
final DirectAdvanceAssignment directAdvanceAssignment;
boolean isAdvanceAssignmentEquals = advanceAssignment.getAdvanceType() != null &&
advanceAssignment.getAdvanceType().getPercentage();
if ( (advanceAssignment instanceof IndirectAdvanceAssignment) ||
isQualityFormOrReadOnly || isAdvanceAssignmentEquals ||
manageOrderElementAdvancesModel.hasConsolidatedAdvances(advanceAssignment) ) {
maxValue.setDisabled(true);
}
if ( advanceAssignment instanceof IndirectAdvanceAssignment ) {
directAdvanceAssignment = manageOrderElementAdvancesModel
.calculateFakeDirectAdvanceAssignment((IndirectAdvanceAssignment) advanceAssignment);
} else {
directAdvanceAssignment = (DirectAdvanceAssignment) advanceAssignment;
}
Util.bind(
maxValue,
() -> directAdvanceAssignment.getMaxValue(),
value -> {
if (!manageOrderElementAdvancesModel.hasConsolidatedAdvances(advanceAssignment))
directAdvanceAssignment.setMaxValue(value);
});
maxValue.addEventListener(Events.ON_CHANGE, (EventListener) event -> {
if (manageOrderElementAdvancesModel.hasConsolidatedAdvances(advanceAssignment))
throw new WrongValueException(
maxValue,
_("Progress Assignment cannot be deleted or changed. " +
"Progress Assignment contains Progress Consolidations values"));
else {
setPercentage();
reloadAdvances();
}
});
Listcell listCell = new Listcell();
listCell.appendChild(maxValue);
listItem.appendChild(listCell);
maxValue.setConstraint(checkMaxValue());
}
private void appendComboboxAdvanceType(final Listitem listItem) {
final DirectAdvanceAssignment advance = listItem.getValue();
final Combobox comboAdvanceTypes = new Combobox();
final List<AdvanceType> listAdvanceType = manageOrderElementAdvancesModel.getPossibleAdvanceTypes(advance);
for(AdvanceType advanceType : listAdvanceType){
if ( !advanceType.getUnitName().equals(PredefinedAdvancedTypes.CHILDREN.getTypeName()) &&
!advanceType.isQualityForm() &&
!advanceType.isReadOnly() ) {
Comboitem comboItem = new Comboitem();
comboItem.setValue(advanceType);
comboItem.setLabel(advanceType.getUnitName());
comboItem.setParent(comboAdvanceTypes);
if ( (advance.getAdvanceType() != null) &&
(advance.getAdvanceType().getId().equals(advanceType.getId())) ) {
comboAdvanceTypes.setSelectedItem(comboItem);
}
}
}
comboAdvanceTypes.addEventListener(Events.ON_SELECT, (EventListener) event -> {
setMaxValue(listItem, comboAdvanceTypes);
cleanFields(advance);
setPercentage();
reloadAdvances();
});
Util.bind(
comboAdvanceTypes,
() -> comboAdvanceTypes.getSelectedItem(),
comboItem -> {
if ( (comboItem!=null) &&
(comboItem.getValue() != null) &&
(comboItem.getValue() instanceof AdvanceType) ) {
AdvanceType advanceType = comboItem.getValue();
advance.setAdvanceType(advanceType);
advance.setMaxValue(manageOrderElementAdvancesModel.getMaxValue(advanceType));
}
});
Listcell listCell = new Listcell();
listCell.appendChild(comboAdvanceTypes);
listItem.appendChild(listCell);
}
private void appendLabelAdvanceType(final Listitem listItem) {
final AdvanceAssignment advance = listItem.getValue();
Label unitName = new Label(advance.getAdvanceType().getUnitName());
Listcell listCell = new Listcell();
listCell.appendChild(unitName);
listItem.appendChild(listCell);
}
private void appendDecimalBoxValue(final Listitem listItem) {
final AdvanceAssignment advanceAssignment = listItem.getValue();
Decimalbox value = new Decimalbox();
value.setScale(2);
value.setDisabled(true);
DirectAdvanceAssignment directAdvanceAssignment;
if (advanceAssignment instanceof IndirectAdvanceAssignment ) {
directAdvanceAssignment = manageOrderElementAdvancesModel
.calculateFakeDirectAdvanceAssignment((IndirectAdvanceAssignment) advanceAssignment);
} else {
directAdvanceAssignment = (DirectAdvanceAssignment) advanceAssignment;
}
final AdvanceMeasurement advanceMeasurement =
manageOrderElementAdvancesModel.getLastAdvanceMeasurement(directAdvanceAssignment);
if ( advanceMeasurement != null ) {
Util.bind(value, () -> advanceMeasurement.getValue());
}
Listcell listCell = new Listcell();
listCell.appendChild(value);
listItem.appendChild(listCell);
}
private void appendLabelPercentage(final Listitem listItem) {
final AdvanceAssignment advanceAssignment = listItem.getValue();
Label percentage = new Label();
DirectAdvanceAssignment directAdvanceAssignment;
if ( advanceAssignment instanceof IndirectAdvanceAssignment ) {
directAdvanceAssignment = manageOrderElementAdvancesModel
.calculateFakeDirectAdvanceAssignment((IndirectAdvanceAssignment) advanceAssignment);
} else {
directAdvanceAssignment = (DirectAdvanceAssignment) advanceAssignment;
}
final AdvanceMeasurement advanceMeasurement =
manageOrderElementAdvancesModel.getLastAdvanceMeasurement(directAdvanceAssignment);
if ( advanceMeasurement != null ) {
percentage.setValue(
manageOrderElementAdvancesModel
.getPercentageAdvanceMeasurement(advanceMeasurement).toString() + " %");
}
Listcell listCell = new Listcell();
listCell.appendChild(percentage);
listItem.appendChild(listCell);
}
private void appendDateBoxDate(final Listitem listItem){
final AdvanceAssignment advanceAssignment = listItem.getValue();
Datebox date = new Datebox();
date.setDisabled(true);
DirectAdvanceAssignment directAdvanceAssignment;
if ( advanceAssignment instanceof IndirectAdvanceAssignment ) {
directAdvanceAssignment = manageOrderElementAdvancesModel
.calculateFakeDirectAdvanceAssignment((IndirectAdvanceAssignment) advanceAssignment);
} else {
directAdvanceAssignment = (DirectAdvanceAssignment) advanceAssignment;
}
final AdvanceMeasurement advanceMeasurement =
manageOrderElementAdvancesModel.getLastAdvanceMeasurement(directAdvanceAssignment);
if ( advanceMeasurement != null ) {
Util.bind(
date,
() -> advanceMeasurement.getDate() == null
? null
: advanceMeasurement.getDate().toDateTimeAtStartOfDay().toDate()
);
}
Listcell listCell = new Listcell();
listCell.appendChild(date);
listItem.appendChild(listCell);
}
private void appendRadioSpread(final Listitem listItem){
final AdvanceAssignment advanceAssignment = listItem.getValue();
final Radio reportGlobalAdvance = Util.bind(
new Radio(),
() -> advanceAssignment.getReportGlobalAdvance(),
value -> {
advanceAssignment.setReportGlobalAdvance(value);
setReportGlobalAdvance(listItem);
});
Listcell listCell = new Listcell();
listCell.appendChild(reportGlobalAdvance);
listItem.appendChild(listCell);
if ( ((AdvanceAssignment) listItem.getValue()).getReportGlobalAdvance() ) {
reportGlobalAdvance.getRadiogroup().setSelectedItem(reportGlobalAdvance);
reportGlobalAdvance.getRadiogroup().invalidate();
}
}
private void appendCalculatedCheckbox(final Listitem listItem){
final AdvanceAssignment advance = listItem.getValue();
Checkbox calculated = new Checkbox();
boolean isCalculated = advance instanceof IndirectAdvanceAssignment;
calculated.setChecked(isCalculated);
calculated.setDisabled(true);
Listcell listCell = new Listcell();
listCell.appendChild(calculated);
listItem.appendChild(listCell);
}
private void appendChartCheckbox(final Listitem listItem) {
final AdvanceAssignment advance = listItem.getValue();
final Checkbox chartCheckbox = new Checkbox();
chartCheckbox.setChecked(selectedAdvances.contains(advance));
chartCheckbox.addEventListener(Events.ON_CHECK,(EventListener) event -> {
if ( chartCheckbox.isChecked() )
selectedAdvances.add(advance);
else
selectedAdvances.remove(advance);
reloadAdvances();
});
Listcell listCell = new Listcell();
listCell.appendChild(chartCheckbox);
listItem.appendChild(listCell);
}
private void appendOperations(final Listitem listItem, Boolean readOnly) {
Hbox hbox = new Hbox();
appendAddMeasurement(hbox, listItem, readOnly);
appendRemoveButton(hbox, listItem, readOnly);
Listcell listCell = new Listcell();
listCell.appendChild(hbox);
listItem.appendChild(listCell);
}
private void appendAddMeasurement(final Hbox hbox, final Listitem listItem, Boolean readOnly) {
final AdvanceAssignment advance = listItem.getValue();
final Button addMeasurementButton = createAddMeasurementButton();
addMeasurementButton.addEventListener(Events.ON_CLICK, (EventListener) event -> {
if ( !listItem.equals(editAdvances.getSelectedItem()) )
selectAdvanceLine(listItem);
goToCreateLineAdvanceMeasurement();
});
if ( (advance.getAdvanceType() != null) && (advance.getAdvanceType().isQualityForm()) ) {
addMeasurementButton.setDisabled(true);
addMeasurementButton.setTooltiptext(_("Progress that are reported by quality forms can not be modified"));
} else if ( (advance.getAdvanceType() != null) && (advance.getAdvanceType().isReadOnly()) ) {
addMeasurementButton.setDisabled(true);
addMeasurementButton.setTooltiptext(_("This progress type cannot be modified"));
} else if ( advance instanceof IndirectAdvanceAssignment ) {
addMeasurementButton.setDisabled(true);
addMeasurementButton.setTooltiptext(_("Calculated progress can not be modified"));
} else if ( readOnly ) {
addMeasurementButton.setDisabled(true);
addMeasurementButton.setTooltiptext(_("Subcontractor values are read only " +
"because they were reported by the subcontractor company."));
}
hbox.appendChild(addMeasurementButton);
}
private void appendRemoveButton(final Hbox hbox, final Listitem listItem, Boolean readOnly) {
final AdvanceAssignment advance = listItem.getValue();
final Button removeButton = createRemoveButton();
removeButton.addEventListener(Events.ON_CLICK, event -> goToRemoveLineAdvanceAssignment(listItem));
if ( (advance.getAdvanceType() != null) && (advance.getAdvanceType().isQualityForm()) ) {
removeButton.setDisabled(true);
removeButton.setTooltiptext(_("Progress that are reported by quality forms cannot be modified"));
} else if ( (advance.getAdvanceType() != null) && (advance.getAdvanceType().isReadOnly()) ) {
removeButton.setDisabled(true);
removeButton.setTooltiptext(_("This progress type cannot be modified"));
} else if ( advance instanceof IndirectAdvanceAssignment ) {
removeButton.setDisabled(true);
removeButton.setTooltiptext(_("Calculated progress cannot be removed"));
} else if ( manageOrderElementAdvancesModel.hasConsolidatedAdvances(advance) ) {
removeButton.setDisabled(true);
removeButton.setTooltiptext(_("Consolidated progress cannot be removed"));
} else if ( readOnly ) {
removeButton.setDisabled(true);
removeButton.setTooltiptext(_("Subcontractor values are read only " +
"because they were reported by the subcontractor company"));
} else if ( manageOrderElementAdvancesModel.hasReportedProgress(advance) ) {
removeButton.setDisabled(true);
removeButton.setTooltiptext(_("Advance assignment cannot be removed as " +
"it has advance measures that have already been reported to the customer"));
}
hbox.appendChild(removeButton);
}
private void setReportGlobalAdvance(final Listitem item) {
boolean spread = true;
if ( manageOrderElementAdvancesModel.hasAnyConsolidatedAdvanceCurrentOrderElement() ) {
showErrorMessage(_("Spread progress cannot be changed " +
"if there is a consolidation in any progress assignment from root task"));
spread = false;
} else if ( !radioSpreadIsConsolidated() )
for (AdvanceAssignment advance : getAdvanceAssignments()) {
advance.setReportGlobalAdvance(false);
}
else {
spread = false;
}
((AdvanceAssignment) item.getValue()).setReportGlobalAdvance(spread);
Util.reloadBindings(editAdvances);
setSelectedAdvanceLine();
}
private boolean radioSpreadIsConsolidated() {
for (AdvanceAssignment advance : getAdvanceAssignments())
if ( (advance.getReportGlobalAdvance()) &&
(manageOrderElementAdvancesModel.hasConsolidatedAdvances(advance)) ) {
showErrorMessage(_("Spread progress cannot be changed " +
"if there is a consolidation in any progress assignment"));
return true;
}
return false;
}
}
private void setMaxValue(final Listitem item,Combobox comboAdvanceTypes) {
Listcell listCell = (Listcell)item.getChildren().get(1);
Decimalbox miBox = (Decimalbox) listCell.getFirstChild();
Comboitem selectedItem = comboAdvanceTypes.getSelectedItem();
if ( selectedItem != null ) {
AdvanceType advanceType = selectedItem.getValue();
if ( advanceType != null ) {
DirectAdvanceAssignment advance = item.getValue();
advance.setMaxValue(manageOrderElementAdvancesModel.getMaxValue(advanceType));
miBox.setValue(manageOrderElementAdvancesModel.getMaxValue(advanceType));
miBox.invalidate();
}
}
}
private Constraint checkMaxValue() {
return (comp, value) -> {
Listitem item = (Listitem) comp.getParent().getParent();
DirectAdvanceAssignment advance = item.getValue();
if ( !manageOrderElementAdvancesModel.hasConsolidatedAdvances(advance) &&
(value == null || (BigDecimal.ZERO.compareTo((BigDecimal) value) >= 0)) ){
((Decimalbox) comp).setValue(advance.getAdvanceType().getDefaultMaxValue());(comp).invalidate();
throw new WrongValueException(comp, _("The max value must be greater than 0"));
}
};
}
private void setPercentage(){
if ( (this.indexSelectedItem < editAdvances.getItemCount()) && (this.indexSelectedItem >= 0) ) {
Listitem selectedItem = editAdvances.getItemAtIndex(indexSelectedItem);
AdvanceAssignment advanceAssignment = selectedItem.getValue();
DirectAdvanceAssignment directAdvanceAssignment;
if ( advanceAssignment instanceof IndirectAdvanceAssignment )
directAdvanceAssignment = manageOrderElementAdvancesModel
.calculateFakeDirectAdvanceAssignment((IndirectAdvanceAssignment) advanceAssignment);
else
directAdvanceAssignment = (DirectAdvanceAssignment) advanceAssignment;
final AdvanceMeasurement greatAdvanceMeasurement =
this.manageOrderElementAdvancesModel.getLastAdvanceMeasurement(directAdvanceAssignment);
if ( greatAdvanceMeasurement != null ) {
Listcell percentage = (Listcell) selectedItem.getChildren().get(3);
((Label) percentage
.getFirstChild())
.setValue(this.manageOrderElementAdvancesModel
.getPercentageAdvanceMeasurement(greatAdvanceMeasurement)
.toString() + " %");
(percentage.getFirstChild()).invalidate();
}
}
}
private void setCurrentValue() {
if ( this.indexSelectedItem >= 0 ) {
Listitem selectedItem = editAdvances.getItemAtIndex(indexSelectedItem);
AdvanceAssignment advanceAssignment = selectedItem.getValue();
DirectAdvanceAssignment directAdvanceAssignment;
if ( advanceAssignment instanceof IndirectAdvanceAssignment )
directAdvanceAssignment = manageOrderElementAdvancesModel
.calculateFakeDirectAdvanceAssignment((IndirectAdvanceAssignment) advanceAssignment);
else
directAdvanceAssignment = (DirectAdvanceAssignment) advanceAssignment;
final AdvanceMeasurement greatAdvanceMeasurement =
this.manageOrderElementAdvancesModel.getLastAdvanceMeasurement(directAdvanceAssignment);
if ( greatAdvanceMeasurement != null ) {
Listcell value = (Listcell)selectedItem.getChildren().get(2);
((Decimalbox) value.getFirstChild()).setValue(greatAdvanceMeasurement.getValue());
(value.getFirstChild()).invalidate();
}
}
}
public void setCurrentDate() {
this.manageOrderElementAdvancesModel.sortListAdvanceMeasurement();
Util.reloadBindings(editAdvancesMeasurement);
this.setCurrentDate();
this.setPercentage();
this.setCurrentValue();
Util.reloadBindings(chart);
}
private void cleanFields(DirectAdvanceAssignment advance) {
this.manageOrderElementAdvancesModel.cleanAdvance(advance);
}
private boolean validateDataForm(){
return (validateListAdvanceAssignment()) &&(validateListAdvanceMeasurement());
}
private boolean validateListAdvanceAssignment(){
for (int i = 0; i < editAdvances.getChildren().size(); i++)
if ( editAdvances.getChildren().get(i) instanceof Listitem ) {
Listitem listItem = (Listitem) editAdvances.getChildren().get(i);
AdvanceAssignment advance = listItem.getValue();
if ( advance != null ) {
if (advance.getAdvanceType() == null )
throw new WrongValueException(getComboboxTypeBy(listItem), _("cannot be empty"));
DirectAdvanceAssignment directAdvanceAssignment;
if ( advance instanceof IndirectAdvanceAssignment ) {
directAdvanceAssignment = manageOrderElementAdvancesModel
.calculateFakeDirectAdvanceAssignment((IndirectAdvanceAssignment) advance);
} else
directAdvanceAssignment = (DirectAdvanceAssignment) advance;
if ( directAdvanceAssignment != null && directAdvanceAssignment.getMaxValue() == null )
throw new WrongValueException(getDecimalboxMaxValueBy(listItem), _("cannot be empty"));
}
}
return true;
}
private boolean validateListAdvanceMeasurement(){
for (int i = 0; i < editAdvancesMeasurement.getChildren().size(); i++)
if ( editAdvancesMeasurement.getChildren().get(i) instanceof Listitem ) {
Listitem listItem = (Listitem) editAdvancesMeasurement.getChildren().get(i);
AdvanceMeasurement advance = listItem.getValue();
if ( advance != null ) {
// Validate the value of the advance measurement
Decimalbox valueBox = getDecimalboxBy(listItem);
validateMeasurementValue(valueBox, advance.getValue());
// Validate the date of the advance measurement
Datebox dateBox = getDateboxBy(listItem);
if ( advance.getDate() == null ) {
validateMeasurementDate(dateBox, null);
} else {
validateMeasurementDate(dateBox, advance.getDate().toDateTimeAtStartOfDay().toDate());
}
}
}
return true;
}
private boolean validateAdvanceMeasurement(AdvanceMeasurement advance) {
boolean result = true;
// Validate the value of advance measurement
if ( advance.getValue() == null )
result = false;
else {
String errorMessage = validateValueAdvanceMeasurement(advance);
if ( errorMessage != null )
result = false;
}
// Validate the date of advance measurement
if ( advance.getDate() == null )
result = false;
else {
String errorMessage = validateDateAdvanceMeasurement(advance.getDate(), advance);
if ( errorMessage != null )
result = false;
}
return result;
}
private Combobox getComboboxTypeBy(Listitem item) {
return (Combobox) (item.getChildren().get(0)).getFirstChild();
}
private Combobox getDecimalboxMaxValueBy(Listitem item) {
return (Combobox) (item.getChildren().get(1)).getFirstChild();
}
private Decimalbox getDecimalboxBy(Listitem item) {
return (Decimalbox) (item.getChildren().get(0)).getFirstChild();
}
private Datebox getDateboxBy(Listitem item) {
return (Datebox) (item.getChildren().get(2)).getFirstChild();
}
private boolean validateReportGlobalAdvance(){
boolean existItems = false;
for (AdvanceAssignment advance : this.getAdvanceAssignments()) {
existItems = true;
if ( advance.getReportGlobalAdvance() )
return true;
}
return !existItems;
}
/** It should be public! */
public AdvanceMeasurementRenderer getAdvanceMeasurementRenderer() {
return advanceMeasurementRenderer;
}
private class AdvanceMeasurementRenderer implements ListitemRenderer {
@Override
public void render(Listitem listitem, Object o, int i) throws Exception {
AdvanceMeasurement advanceMeasurement = (AdvanceMeasurement) o;
listitem.setValue(advanceMeasurement);
appendDecimalBoxValue(listitem);
appendLabelPercentage(listitem);
appendDateboxDate(listitem);
appendRemoveButton(listitem);
}
private void appendDecimalBoxValue(final Listitem listitem) {
final AdvanceMeasurement advanceMeasurement = listitem.getValue();
final Decimalbox decimalbox = new Decimalbox();
Listcell listcell = new Listcell();
listcell.appendChild(decimalbox);
listitem.appendChild(listcell);
decimalbox.setScale(calculateScale(advanceMeasurement));
decimalbox.setDisabled(isReadOnlyAdvanceMeasurements() ||
manageOrderElementAdvancesModel.hasConsolidatedAdvances(advanceMeasurement) ||
manageOrderElementAdvancesModel.isAlreadyReportedProgress(advanceMeasurement));
decimalbox.addEventListener(Events.ON_CHANGE, (EventListener) event -> {
if ( manageOrderElementAdvancesModel.canRemoveOrChange(advanceMeasurement) ) {
updatesValue();
validateMeasurementValue(decimalbox, decimalbox.getValue());
} else
throw new WrongValueException(decimalbox, _("Progress Measurement cannot be deleted." +
" Progress Measurement already consolidated"));
});
Util.bind(
decimalbox,
advanceMeasurement::getValue,
value -> {
if (manageOrderElementAdvancesModel.canRemoveOrChange(advanceMeasurement)) {
advanceMeasurement.setValue(value);
reloadAdvances();
}
});
decimalbox.focus();
}
private void appendLabelPercentage(final Listitem listitem) {
final AdvanceMeasurement advanceMeasurement = listitem.getValue();
BigDecimal percentage = manageOrderElementAdvancesModel.getPercentageAdvanceMeasurement(advanceMeasurement);
Label percentageLabel = new Label(percentage.toString() + " %");
Listcell listcell = new Listcell();
listcell.appendChild(percentageLabel);
listitem.appendChild(listcell);
}
private void appendDateboxDate(final Listitem listitem) {
final AdvanceMeasurement advanceMeasurement = listitem.getValue();
final Datebox date = new Datebox();
Listcell listcell = new Listcell();
listcell.appendChild(date);
listitem.appendChild(listcell);
date.setDisabled(isReadOnlyAdvanceMeasurements() ||
manageOrderElementAdvancesModel.hasConsolidatedAdvances(advanceMeasurement)
|| manageOrderElementAdvancesModel.isAlreadyReportedProgress(advanceMeasurement));
date.addEventListener(Events.ON_CHANGE,(EventListener) event -> {
if ( manageOrderElementAdvancesModel.canRemoveOrChange(advanceMeasurement) ) {
validateMeasurementDate(date, date.getValue());
setCurrentDate();
} else
throw new WrongValueException(date, _("Progress Measurement cannot be deleted." +
" Progress Measurement already consolidated"));
});
Util.bind(
date,
() -> advanceMeasurement.getDate() == null
? null
: advanceMeasurement.getDate().toDateTimeAtStartOfDay().toDate(),
value -> {
if ( manageOrderElementAdvancesModel.canRemoveOrChange(advanceMeasurement) ) {
LocalDate oldDate = advanceMeasurement.getDate();
advanceMeasurement.setDate(new LocalDate(value));
if ( manageOrderElementAdvancesModel.hasConsolidatedAdvances(advanceMeasurement) ) {
showMessagesConsolidation(new LocalDate(value));
advanceMeasurement.setDate(oldDate);
}
manageOrderElementAdvancesModel.sortListAdvanceMeasurement();
reloadAdvances();
}
});
}
private void appendRemoveButton(final Listitem listItem) {
final AdvanceMeasurement measure = listItem.getValue();
final Button removeButton = createRemoveButton();
DirectAdvanceAssignment advance = (DirectAdvanceAssignment) measure.getAdvanceAssignment();
if ( (advance.getAdvanceType() != null) && (advance.getAdvanceType().isQualityForm()) ) {
removeButton.setDisabled(true);
removeButton.setTooltiptext(_("Progress measurements that are reported " +
"by quality forms cannot be removed"));
} else if ( (advance.getAdvanceType() != null) && (advance.getAdvanceType().isReadOnly()) ) {
removeButton.setDisabled(true);
removeButton.setTooltiptext(_("This progress type cannot cannot be removed"));
} else if ( advance.isFake() ) {
removeButton.setDisabled(true);
removeButton.setTooltiptext(_("Calculated progress measurements cannot be removed") );
} else if ( manageOrderElementAdvancesModel.hasConsolidatedAdvances(measure) ) {
removeButton.setDisabled(true);
removeButton.setTooltiptext(_("Consolidated progress measurement cannot be removed"));
} else if ( manageOrderElementAdvancesModel.isAlreadyReportedProgress(measure) ) {
removeButton.setDisabled(true);
removeButton.setTooltiptext(_("Values already sent to the customer. Values cannot be changed "));
} else if ( isReadOnlyAdvanceMeasurements() ) {
removeButton.setDisabled(isReadOnlyAdvanceMeasurements());
removeButton.setTooltiptext(_("Subcontractor values are read only" +
" because they were reported by the subcontractor company."));
}
removeButton.addEventListener(Events.ON_CLICK, event -> goToRemoveLineAdvanceMeasurement(listItem));
Listcell listCell = new Listcell();
listCell.appendChild(removeButton);
listItem.appendChild(listCell);
}
private int calculateScale(AdvanceMeasurement advanceMeasurement) {
return advanceMeasurement
.getAdvanceAssignment()
.getAdvanceType()
.getUnitPrecision()
.stripTrailingZeros()
.scale();
}
private void showMessagesConsolidation(LocalDate date) {
String message = _("Progress measurement cannot be canged to {0}, because it is consolidated", date);
showErrorMessage(message);
}
}
private Button createAddMeasurementButton() {
Button addButton = new Button();
addButton.setLabel(_("Add measure"));
addButton.setClass("add-button");
addButton.setTooltiptext(_("Add new progress measurement"));
return addButton;
}
/** It should be public! */
public XYModel getChartData() {
return this.manageOrderElementAdvancesModel.getChartData(selectedAdvances);
}
private Button createRemoveButton() {
Button removeButton = new Button();
removeButton.setSclass("icono");
removeButton.setImage("/common/img/ico_borrar1.png");
removeButton.setHoverImage("/common/img/ico_borrar.png");
removeButton.setTooltiptext(_("Delete"));
return removeButton;
}
public void refreshChangesFromOrderElement() {
manageOrderElementAdvancesModel.refreshChangesFromOrderElement();
}
private void showMessageNotAddMoreAdvances() {
String message = _("All progress types have already been assigned.");
increaseScreenHeight();
messagesForUser.showMessage(Level.ERROR, message);
}
public void refreshSelectedAdvance() {
if ( (indexSelectedItem < 0) || (indexSelectedItem >= getAdvanceAssignments().size()) )
selectSpreadAdvanceLine();
selectAdvanceLine(indexSelectedItem);
}
private void showMessageDeleteSpread() {
String message = _("Spread progress cannot be removed. Please select another progress as spread.");
showErrorMessage(message);
}
private void showErrorMessage(String message) {
increaseScreenHeight();
messagesForUser.showMessage(Level.ERROR, message);
}
private String validateValueAdvanceMeasurement(AdvanceMeasurement measurement) {
if ( manageOrderElementAdvancesModel.greatThanMaxValue(measurement) )
return _("Value is not valid. It must be smaller than max value");
if ( !manageOrderElementAdvancesModel.isPrecisionValid(measurement) )
return _("Value must be a multiple of the precision value of the progress type: {0}",
manageOrderElementAdvancesModel.getUnitPrecision().stripTrailingZeros().toPlainString());
if ( manageOrderElementAdvancesModel.lessThanPreviousMeasurements() )
return _("Invalid value. Value must be greater than the value of previous progress.");
return null;
}
private String validateDateAdvanceMeasurement(LocalDate value, AdvanceMeasurement measurement) {
LocalDate oldDate = measurement.getDate();
measurement.setDate(value);
if ( !manageOrderElementAdvancesModel.isDistinctValidDate(value, measurement))
return _("Invalid date. Date must be unique for this Progress Assignment");
if ( manageOrderElementAdvancesModel.hasConsolidatedAdvances(measurement) )
measurement.setDate(oldDate);
else {
manageOrderElementAdvancesModel.sortListAdvanceMeasurement();
if ( manageOrderElementAdvancesModel.lessThanPreviousMeasurements() )
return _("Invalid value. Value must be greater than the value of previous progress.");
}
if ( !isReadOnlyAdvanceMeasurements() ) {
LocalDate consolidatedUntil = manageOrderElementAdvancesModel
.getLastConsolidatedMeasurementDate(measurement.getAdvanceAssignment());
if ( consolidatedUntil != null && consolidatedUntil.compareTo(measurement.getDate()) >= 0 ) {
return _("Date is not valid, it must be later than the last progress consolidation");
}
if ( manageOrderElementAdvancesModel.isAlreadyReportedProgressWith(value) ) {
return _("Date is not valid, it must be later than the last progress reported to the customer");
}
}
return null;
}
public boolean findErrorsInMeasurements() {
boolean result = findPageWithError();
validateListAdvanceMeasurement();
return result;
}
private boolean findPageWithError() {
int currentPage = editAdvancesMeasurement.getActivePage();
int i = 0;
int page = 0;
changePage(page);
for (Listitem item : editAdvancesMeasurement.getItems()) {
AdvanceMeasurement advance = item.getValue();
if ( advance != null ) {
if ( !validateAdvanceMeasurement(advance) )
return true;
i++;
if ( i == editAdvancesMeasurement.getPageSize() ) {
i = 0;
changePage(++page);
}
}
}
changePage(currentPage);
return false;
}
private void changePage(int page) {
if ( (page >= 0) && (page < editAdvancesMeasurement.getPageCount()) ) {
editAdvancesMeasurement.setActivePage(page);
editAdvancesMeasurement.invalidate();
}
}
/** It should be public! */
public void onPagingMeasurement() {
validateListAdvanceMeasurement();
}
public void validateMeasurementDate(Component comp, Date value) {
AdvanceMeasurement advanceMeasurement = getAdvanceMeasurementByComponent(comp);
if (manageOrderElementAdvancesModel.canRemoveOrChange(advanceMeasurement)) {
if ( value == null && advanceMeasurement != null ) {
advanceMeasurement.setDate(null);
((Datebox) comp).setValue(null);
throw new WrongValueException(comp, _("cannot be empty"));
} else {
String errorMessage = validateDateAdvanceMeasurement(new LocalDate(value), advanceMeasurement);
LocalDate date = null;
if ( advanceMeasurement != null )
date = advanceMeasurement.getDate();
if ( date != null )
((Datebox) comp).setValue(date.toDateTimeAtStartOfDay().toDate());
if ( errorMessage != null )
throw new WrongValueException(comp, errorMessage);
}
}
}
public void validateMeasurementValue(Component comp, Object value) {
AdvanceMeasurement advanceMeasurement = getAdvanceMeasurementByComponent(comp);
if ( (advanceMeasurement != null) && (manageOrderElementAdvancesModel.canRemoveOrChange(advanceMeasurement)) ) {
advanceMeasurement.setValue((BigDecimal) value);
((Decimalbox) comp).setValue((BigDecimal) value);
if ( (value) == null )
throw new WrongValueException(comp, _("cannot be empty"));
else {
String errorMessage = validateValueAdvanceMeasurement(advanceMeasurement);
if ( errorMessage != null )
throw new WrongValueException(comp, errorMessage);
}
}
}
private AdvanceMeasurement getAdvanceMeasurementByComponent(Component comp) {
try {
Listitem item = (Listitem) comp.getParent().getParent();
return (AdvanceMeasurement) item.getValue();
} catch (Exception e) {
return null;
}
}
}