/**
* ***************************************************************************
* Copyright (c) 2010 Qcadoo Limited
* Project: Qcadoo MES
* Version: 1.4
*
* This file is part of Qcadoo.
*
* Qcadoo 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, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
* ***************************************************************************
*/
package com.qcadoo.mes.costCalculation.hooks;
import java.math.BigDecimal;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.google.common.base.Optional;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.qcadoo.commons.functional.Either;
import com.qcadoo.mes.basic.ParameterService;
import com.qcadoo.mes.basic.constants.ProductFields;
import com.qcadoo.mes.basic.util.CurrencyService;
import com.qcadoo.mes.costCalculation.constants.CostCalculationConstants;
import com.qcadoo.mes.costCalculation.constants.CostCalculationFields;
import com.qcadoo.mes.costCalculation.constants.SourceOfOperationCosts;
import com.qcadoo.mes.costNormsForOperation.constants.CalculateOperationCostMode;
import com.qcadoo.mes.orders.constants.OrderFields;
import com.qcadoo.mes.orders.constants.OrderType;
import com.qcadoo.model.api.BigDecimalUtils;
import com.qcadoo.model.api.Entity;
import com.qcadoo.model.api.NumberService;
import com.qcadoo.view.api.ViewDefinitionState;
import com.qcadoo.view.api.components.*;
import com.qcadoo.view.api.components.lookup.FilterValueHolder;
import com.qcadoo.view.api.ribbon.RibbonActionItem;
import com.qcadoo.view.api.utils.NumberGeneratorService;
@Service
public class CostCalculationDetailsHooks {
private static final String L_FORM = "form";
private static final String L_WINDOW = "window";
private static final String L_PRODUCTION_COST_MARGIN_PROC = "productionCostMarginProc";
private static final String L_MATERIAL_COST_MARGIN_PROC = "materialCostMarginProc";
private static final String L_REGISTRATION_PRICE_OVERHEAD_PROC = "registrationPriceOverheadProc";
private static final String L_PROFIT_PROC = "profitProc";
private static final String L_ADDITIONAL_OVERHEAD_CURRENCY = "additionalOverheadCurrency";
private static final String L_TOTAL_COST_PER_UNIT_UNIT = "totalCostPerUnitUnit";
private static final String L_TOTAL_MACHINE_HOURLY_COSTS_CURRENCY = "totalMachineHourlyCostsCurrency";
private static final String L_TOTAL_LABOR_HOURLY_COSTS_CURRENCY = "totalLaborHourlyCostsCurrency";
private static final String L_TOTAL_PIECEWORK_COSTS_CURRENCY = "totalPieceworkCostsCurrency";
@Autowired
private NumberGeneratorService numberGeneratorService;
@Autowired
private CurrencyService currencyService;
@Autowired
private ParameterService parameterService;
@Autowired
private NumberService numbersService;
public void setCriteriaModifierParameters(final ViewDefinitionState view) {
LookupComponent orderLookup = (LookupComponent) view.getComponentByReference(CostCalculationFields.ORDER);
LookupComponent technologyLookup = (LookupComponent) view.getComponentByReference(CostCalculationFields.TECHNOLOGY);
LookupComponent productLookup = (LookupComponent) view.getComponentByReference(CostCalculationFields.PRODUCT);
Entity order = orderLookup.getEntity();
Entity product = productLookup.getEntity();
FilterValueHolder filterValueHolder = technologyLookup.getFilterValue();
if (order == null) {
filterValueHolder.remove(CostCalculationFields.TECHNOLOGY);
} else {
String orderType = order.getStringField(OrderFields.ORDER_TYPE);
Entity technology = null;
if (OrderType.WITH_PATTERN_TECHNOLOGY.getStringValue().equals(orderType)) {
technology = order.getBelongsToField(OrderFields.TECHNOLOGY_PROTOTYPE);
} else {
technology = order.getBelongsToField(OrderFields.TECHNOLOGY);
}
if (technology == null) {
filterValueHolder.remove(CostCalculationFields.TECHNOLOGY);
} else {
filterValueHolder.put(CostCalculationFields.TECHNOLOGY, technology.getId());
}
}
if (product == null) {
filterValueHolder.remove(CostCalculationFields.PRODUCT);
} else {
filterValueHolder.put(CostCalculationFields.PRODUCT, product.getId());
}
technologyLookup.setFilterValue(filterValueHolder);
}
public void onBeforeRender(final ViewDefinitionState view) {
setCriteriaModifierParameters(view);
setFieldsEnabled(view);
generateNumber(view);
fillCurrencyFields(view);
disableCheckboxIfPieceworkIsSelected(view);
fillOverheadsFromParameters(view);
toggleCalculateOperationCostsModeComponent(view);
roundResults(view);
setButtonEnabled(view);
}
private void roundResults(final ViewDefinitionState view) {
Set<String> referenceNames = Sets.newHashSet(CostCalculationFields.TOTAL_MATERIAL_COSTS,
CostCalculationFields.TOTAL_MACHINE_HOURLY_COSTS, CostCalculationFields.TOTAL_LABOR_HOURLY_COSTS,
CostCalculationFields.TOTAL_PIECEWORK_COSTS, CostCalculationFields.TOTAL_TECHNICAL_PRODUCTION_COSTS,
CostCalculationFields.PRODUCTION_COST_MARGIN_VALUE, CostCalculationFields.MATERIAL_COST_MARGIN_VALUE,
CostCalculationFields.ADDITIONAL_OVERHEAD_VALUE, CostCalculationFields.TOTAL_OVERHEAD,
CostCalculationFields.TOTAL_COSTS, CostCalculationFields.TOTAL_COST_PER_UNIT,
CostCalculationFields.REGISTRATION_PRICE_OVERHEAD_VALUE, CostCalculationFields.TECHNICAL_PRODUCTION_COSTS,
CostCalculationFields.PROFIT_VALUE, CostCalculationFields.SELL_PRICE_VALUE);
for (String name : referenceNames) {
FieldComponent component = (FieldComponent) view.getComponentByReference(name);
String value = (String) component.getFieldValue();
Either<Exception, Optional<BigDecimal>> eitherValue = BigDecimalUtils.tryParse(value, view.getLocale());
if (eitherValue.isRight()) {
Optional<BigDecimal> maybeValue = eitherValue.getRight();
if (maybeValue.isPresent()) {
component.setFieldValue(numbersService.format(numbersService.setScale(maybeValue.get(), 2)));
component.requestComponentUpdateState();
}
}
}
}
private void toggleCalculateOperationCostsModeComponent(ViewDefinitionState view) {
FieldComponent sourceOfOperationCostsComponent = (FieldComponent) view.getComponentByReference("sourceOfOperationCosts");
if (sourceOfOperationCostsComponent.isEnabled()) {
String source = (String) sourceOfOperationCostsComponent.getFieldValue();
FieldComponent calculateOperationCostsModeComponent = (FieldComponent) view
.getComponentByReference("calculateOperationCostsMode");
if (SourceOfOperationCosts.PARAMETERS.getStringValue().equals(source)) {
calculateOperationCostsModeComponent.setEnabled(false);
} else {
calculateOperationCostsModeComponent.setEnabled(true);
}
}
}
public void setFieldsEnabled(final ViewDefinitionState view) {
Set<String> referenceNames = Sets.newHashSet(CostCalculationFields.PRODUCT, CostCalculationFields.ORDER,
CostCalculationFields.QUANTITY, CostCalculationFields.TECHNOLOGY, CostCalculationFields.NUMBER,
CostCalculationFields.PRODUCTION_LINE, CostCalculationFields.DESCRIPTION,
CostCalculationFields.CALCULATE_MATERIAL_COSTS_MODE, CostCalculationFields.CALCULATE_OPERATION_COSTS_MODE,
CostCalculationFields.PRODUCTION_COST_MARGIN, CostCalculationFields.MATERIAL_COST_MARGIN,
CostCalculationFields.ADDITIONAL_OVERHEAD, CostCalculationFields.PRINT_COST_NORMS_OF_MATERIALS,
CostCalculationFields.PRINT_OPERATION_NORMS, CostCalculationFields.INCLUDE_TPZ,
CostCalculationFields.INCLUDE_ADDITIONAL_TIME, CostCalculationFields.SOURCE_OF_MATERIAL_COSTS,
CostCalculationFields.SOURCE_OF_OPERATION_COSTS, CostCalculationFields.REGISTRATION_PRICE_OVERHEAD,
CostCalculationFields.PROFIT, L_PRODUCTION_COST_MARGIN_PROC, L_MATERIAL_COST_MARGIN_PROC,
L_ADDITIONAL_OVERHEAD_CURRENCY);
Map<String, FieldComponent> componentsMap = Maps.newHashMap();
for (String referenceName : referenceNames) {
FieldComponent fieldComponent = (FieldComponent) view.getComponentByReference(referenceName);
componentsMap.put(referenceName, fieldComponent);
}
CheckBoxComponent generatedField = (CheckBoxComponent) view.getComponentByReference(CostCalculationFields.GENERATED);
boolean isGenerated = generatedField.isChecked();
for (Entry<String, FieldComponent> entry : componentsMap.entrySet()) {
entry.getValue().setEnabled(!isGenerated);
}
if (componentsMap.get(CostCalculationFields.TECHNOLOGY).getFieldValue() == null) {
componentsMap.get(CostCalculationFields.PRODUCT).setEnabled(true);
componentsMap.get(CostCalculationFields.QUANTITY).setEnabled(true);
componentsMap.get(CostCalculationFields.ORDER).setEnabled(true);
componentsMap.get(CostCalculationFields.TECHNOLOGY).setEnabled(true);
}
}
public void generateNumber(final ViewDefinitionState view) {
numberGeneratorService.generateAndInsertNumber(view, CostCalculationConstants.PLUGIN_IDENTIFIER,
CostCalculationConstants.MODEL_COST_CALCULATION, L_FORM, CostCalculationFields.NUMBER);
}
public void fillCurrencyFields(final ViewDefinitionState viewDefinitionState) {
final String currencyAlphabeticCode = currencyService.getCurrencyAlphabeticCode();
Set<String> referenceNames = Sets.newHashSet("totalCostsCurrency", "totalOverheadCurrency",
"additionalOverheadValueCurrency", "materialCostMarginValueCurrency", "productionCostMarginValueCurrency",
"totalTechnicalProductionCostsCurrency", L_TOTAL_PIECEWORK_COSTS_CURRENCY, L_TOTAL_LABOR_HOURLY_COSTS_CURRENCY,
L_TOTAL_MACHINE_HOURLY_COSTS_CURRENCY, "totalMaterialCostsCurrency", L_ADDITIONAL_OVERHEAD_CURRENCY,
"profitValueCurrency", "registrationPriceOverheadValueCurrency");
for (String referenceName : referenceNames) {
FieldComponent fieldComponent = (FieldComponent) viewDefinitionState.getComponentByReference(referenceName);
fieldComponent.setFieldValue(currencyAlphabeticCode);
fieldComponent.requestComponentUpdateState();
}
fillComponentWithPercent(L_PRODUCTION_COST_MARGIN_PROC, viewDefinitionState);
fillComponentWithPercent(L_MATERIAL_COST_MARGIN_PROC, viewDefinitionState);
fillComponentWithPercent(L_REGISTRATION_PRICE_OVERHEAD_PROC, viewDefinitionState);
fillComponentWithPercent(L_PROFIT_PROC, viewDefinitionState);
fillCostPerUnitUnitField(viewDefinitionState);
}
private void fillComponentWithPercent(String componentName, ViewDefinitionState viewDefinitionState) {
FieldComponent materialCostMarginProc = (FieldComponent) viewDefinitionState.getComponentByReference(componentName);
materialCostMarginProc.setFieldValue("%");
materialCostMarginProc.requestComponentUpdateState();
}
public void fillCostPerUnitUnitField(final ViewDefinitionState view) {
final String currencyAlphabeticCode = currencyService.getCurrencyAlphabeticCode();
FieldComponent totalCostPerUnitUnit = (FieldComponent) view.getComponentByReference(L_TOTAL_COST_PER_UNIT_UNIT);
FieldComponent sellPriceValueCurrency = (FieldComponent) view.getComponentByReference("sellPriceValueCurrency");
FieldComponent technicalProductionCostsCurrency = (FieldComponent) view
.getComponentByReference("technicalProductionCostsCurrency");
LookupComponent productField = (LookupComponent) view.getComponentByReference(CostCalculationFields.PRODUCT);
Entity product = productField.getEntity();
if (product == null) {
return;
}
String unit = currencyAlphabeticCode + " / " + product.getStringField(ProductFields.UNIT);
totalCostPerUnitUnit.setFieldValue(unit);
totalCostPerUnitUnit.requestComponentUpdateState();
sellPriceValueCurrency.setFieldValue(unit);
sellPriceValueCurrency.requestComponentUpdateState();
technicalProductionCostsCurrency.setFieldValue(unit);
technicalProductionCostsCurrency.requestComponentUpdateState();
}
public void disableCheckboxIfPieceworkIsSelected(final ViewDefinitionState viewDefinitionState) {
FieldComponent calculateOperationCostsModeField = (FieldComponent) viewDefinitionState
.getComponentByReference(CostCalculationFields.CALCULATE_OPERATION_COSTS_MODE);
FieldComponent includeTPZField = (FieldComponent) viewDefinitionState
.getComponentByReference(CostCalculationFields.INCLUDE_TPZ);
FieldComponent includeAdditionalTimeField = (FieldComponent) viewDefinitionState
.getComponentByReference(CostCalculationFields.INCLUDE_ADDITIONAL_TIME);
FieldComponent machineHourlyCostsField = (FieldComponent) viewDefinitionState
.getComponentByReference(CostCalculationFields.TOTAL_MACHINE_HOURLY_COSTS);
FieldComponent machineHourlyCostsCurrencyField = (FieldComponent) viewDefinitionState
.getComponentByReference(L_TOTAL_MACHINE_HOURLY_COSTS_CURRENCY);
FieldComponent totalLaborHourlyCostsField = (FieldComponent) viewDefinitionState
.getComponentByReference(CostCalculationFields.TOTAL_LABOR_HOURLY_COSTS);
FieldComponent totalLaborHourlyCostsCurrencyField = (FieldComponent) viewDefinitionState
.getComponentByReference(L_TOTAL_LABOR_HOURLY_COSTS_CURRENCY);
FieldComponent totalPieceworkCostsField = (FieldComponent) viewDefinitionState
.getComponentByReference(CostCalculationFields.TOTAL_PIECEWORK_COSTS);
FieldComponent totalPieceworkCostsCurrencyField = (FieldComponent) viewDefinitionState
.getComponentByReference(L_TOTAL_PIECEWORK_COSTS_CURRENCY);
if (CalculateOperationCostMode.PIECEWORK.getStringValue().equals(calculateOperationCostsModeField.getFieldValue())) {
includeTPZField.setFieldValue(false);
includeTPZField.setEnabled(false);
includeTPZField.requestComponentUpdateState();
includeAdditionalTimeField.setFieldValue(false);
includeAdditionalTimeField.setEnabled(false);
includeAdditionalTimeField.requestComponentUpdateState();
machineHourlyCostsField.setVisible(false);
machineHourlyCostsCurrencyField.setVisible(false);
totalLaborHourlyCostsField.setVisible(false);
totalLaborHourlyCostsCurrencyField.setVisible(false);
totalPieceworkCostsField.setVisible(true);
totalPieceworkCostsCurrencyField.setVisible(true);
} else {
machineHourlyCostsField.setVisible(true);
machineHourlyCostsCurrencyField.setVisible(true);
totalLaborHourlyCostsField.setVisible(true);
totalLaborHourlyCostsCurrencyField.setVisible(true);
totalPieceworkCostsField.setVisible(false);
totalPieceworkCostsCurrencyField.setVisible(false);
}
}
private void fillOverheadsFromParameters(ViewDefinitionState view) {
FormComponent form = (FormComponent) view.getComponentByReference("form");
Boolean justCreated = form.getEntity().getBooleanField("justCreated");
if (form.getEntityId() == null && justCreated) {
fillWithProperty("sourceOfMaterialCosts", "sourceOfMaterialCostsPB", view);
fillWithProperty("calculateMaterialCostsMode", "calculateMaterialCostsModePB", view);
fillWithProperty("sourceOfOperationCosts", "sourceOfOperationCostsPB", view);
fillWithPropertyOrZero("productionCostMargin", "productionCostMarginPB", view);
fillWithPropertyOrZero("materialCostMargin", "materialCostMarginPB", view);
fillWithPropertyOrZero("additionalOverhead", "additionalOverheadPB", view);
fillWithPropertyOrZero("registrationPriceOverhead", "registrationPriceOverheadPB", view);
fillWithPropertyOrZero("profit", "profitPB", view);
view.getComponentByReference("justCreated").setFieldValue(false);
}
}
private void fillWithProperty(String componentName, String propertyName, ViewDefinitionState view) {
FieldComponent component = (FieldComponent) view.getComponentByReference(componentName);
String propertyValue = parameterService.getParameter().getStringField(propertyName);
if (propertyValue != null) {
component.setFieldValue(propertyValue);
}
}
private void fillWithPropertyOrZero(String componentName, String propertyName, ViewDefinitionState view) {
FieldComponent component = (FieldComponent) view.getComponentByReference(componentName);
if (component.getFieldValue() == null) {
BigDecimal propertyValue = parameterService.getParameter().getDecimalField(propertyName);
if (propertyValue != null) {
String formattedProductionCostMargin = numbersService.formatWithMinimumFractionDigits(propertyValue.setScale(2),
0);
component.setFieldValue(formattedProductionCostMargin);
} else {
component.setFieldValue(0);
}
}
}
private void setButtonEnabled(ViewDefinitionState view) {
WindowComponent window = (WindowComponent) view.getComponentByReference(L_WINDOW);
RibbonActionItem saveNominalCosts = window.getRibbon().getGroupByName(CostCalculationFields.SAVE_COSTS).getItemByName(CostCalculationFields.NOMINAL_COSTS);
CheckBoxComponent generatedField = (CheckBoxComponent) view.getComponentByReference(CostCalculationFields.GENERATED);
if(generatedField.isChecked()){
saveNominalCosts.setEnabled(true);
saveNominalCosts.requestUpdate(true);
}
}
}