/**
* ***************************************************************************
* 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.operationTimeCalculations;
import java.math.BigDecimal;
import java.math.MathContext;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.qcadoo.mes.basic.ParameterService;
import com.qcadoo.mes.operationTimeCalculations.dto.OperationTimesContainer;
import com.qcadoo.mes.technologies.ProductionLinesService;
import com.qcadoo.mes.technologies.constants.TechnologiesConstants;
import com.qcadoo.mes.technologies.constants.TechnologyFields;
import com.qcadoo.mes.technologies.constants.TechnologyOperationComponentFields;
import com.qcadoo.mes.timeNormsForOperations.constants.TechOperCompTimeCalculationsFields;
import com.qcadoo.mes.timeNormsForOperations.constants.TechnologyOperationComponentFieldsTNFO;
import com.qcadoo.mes.timeNormsForOperations.constants.TimeNormsConstants;
import com.qcadoo.model.api.BigDecimalUtils;
import com.qcadoo.model.api.DataDefinition;
import com.qcadoo.model.api.DataDefinitionService;
import com.qcadoo.model.api.Entity;
import com.qcadoo.model.api.NumberService;
@Service
public class OperationWorkTimeServiceImpl implements OperationWorkTimeService {
private static final String L_TECHNOLOGY = "technology";
private static final String L_TECHNOLOGY_OPERATION_COMPONENT = "technologyOperationComponent";
@Autowired
private NumberService numberService;
@Autowired
private ProductionLinesService productionLinesService;
@Autowired
private DataDefinitionService dataDefinitionService;
@Autowired
private ParameterService parameterService;
@Override
public BigDecimal estimateAbstractOperationWorkTime(final Entity operationComponent, final BigDecimal neededNumberOfCycles,
final boolean includeTpz, final boolean includeAdditionalTime, final Integer workstations) {
MathContext mc = numberService.getMathContext();
BigDecimal tj = BigDecimal.valueOf(getValueOfIntFiled(operationComponent, "tj"));
BigDecimal abstractOperationWorkTime = tj.multiply(neededNumberOfCycles, mc);
if (includeTpz) {
BigDecimal tpz = new BigDecimal(getValueOfIntFiled(operationComponent, "tpz"));
abstractOperationWorkTime = abstractOperationWorkTime.add(tpz, mc);
}
if (includeAdditionalTime) {
BigDecimal additionalTime = new BigDecimal(getValueOfIntFiled(operationComponent, "timeNextOperation"));
abstractOperationWorkTime = abstractOperationWorkTime.add(additionalTime, mc);
}
return numberService.setScale(abstractOperationWorkTime);
}
private Integer getValueOfIntFiled(final Entity operationComponent, final String field) {
String entityType = operationComponent.getDataDefinition().getName();
if (TechnologiesConstants.MODEL_TECHNOLOGY_OPERATION_COMPONENT.equals(entityType)) {
return getIntegerValue(operationComponent.getField(field));
} else {
return getIntegerValue(operationComponent.getBelongsToField("technologyOperationComponent").getField(field));
}
}
private BigDecimal getValueOfDecimalFiled(final Entity operationComponent, final String field) {
String entityType = operationComponent.getDataDefinition().getName();
if (TechnologiesConstants.MODEL_TECHNOLOGY_OPERATION_COMPONENT.equals(entityType)) {
return operationComponent.getDecimalField(field);
} else {
return operationComponent.getBelongsToField("technologyOperationComponent").getDecimalField(field);
}
}
@Override
public OperationWorkTime estimateOperationWorkTime(final Entity operationComponent, final BigDecimal neededNumberOfCycles,
final boolean includeTpz, final boolean includeAdditionalTime, final Integer workstations, final boolean saved) {
MathContext mc = numberService.getMathContext();
BigDecimal laborUtilization = BigDecimalUtils
.convertNullToZero(getValueOfDecimalFiled(operationComponent, "laborUtilization"));
BigDecimal machineUtilization = BigDecimalUtils
.convertNullToZero(getValueOfDecimalFiled(operationComponent, "machineUtilization"));
BigDecimal abstractOperationWorkTime = estimateAbstractOperationWorkTime(operationComponent, neededNumberOfCycles,
includeTpz, includeAdditionalTime, workstations);
Integer laborWorkTime = abstractOperationWorkTime.multiply(laborUtilization, mc).intValue();
Integer machineWorkTime = abstractOperationWorkTime.multiply(machineUtilization, mc).intValue();
Integer duration = abstractOperationWorkTime.intValue();
OperationWorkTime operationWorkTime = new OperationWorkTime();
operationWorkTime.setDuration(duration);
operationWorkTime.setLaborWorkTime(laborWorkTime);
operationWorkTime.setMachineWorkTime(machineWorkTime);
if (saved) {
savedWorkTime(operationComponent, machineWorkTime, laborWorkTime, duration);
}
return operationWorkTime;
}
@Override
public Map<Entity, OperationWorkTime> estimateOperationsWorkTime(final List<Entity> operationComponents,
final Map<Entity, BigDecimal> operationRuns, final boolean includeTpz, final boolean includeAdditionalTime,
final Map<Entity, Integer> workstations, final boolean saved) {
Map<Entity, OperationWorkTime> operationsWorkTimes = new HashMap<Entity, OperationWorkTime>();
for (Entity operationComponent : operationComponents) {
OperationWorkTime operationWorkTime = estimateOperationWorkTime(operationComponent,
getOperationRuns(operationRuns, operationComponent), includeTpz, includeAdditionalTime,
getWorkstationsQuantity(workstations, operationComponent), saved);
operationsWorkTimes.put(operationComponent.getDataDefinition().get(operationComponent.getId()), operationWorkTime);
}
return operationsWorkTimes;
}
@Override
public OperationTimesContainer estimateOperationsWorkTimes(List<Entity> operationComponents,
Map<Long, BigDecimal> operationRuns, boolean includeTpz, boolean includeAdditionalTime,
Map<Long, Integer> workstations, boolean saved) {
OperationTimesContainer operationTimesContainer = new OperationTimesContainer();
for (Entity operationComponent : operationComponents) {
OperationWorkTime operationWorkTime = estimateOperationWorkTime(operationComponent,
getOperationRunsFromMap(operationRuns, operationComponent), includeTpz, includeAdditionalTime,
getWorkstationsQuantityFromMap(workstations, operationComponent), saved);
operationTimesContainer.add(operationComponent.getDataDefinition().get(operationComponent.getId()),
operationWorkTime);
}
return operationTimesContainer;
}
@Override
public Map<Entity, OperationWorkTime> estimateOperationsWorkTime(final List<Entity> operationComponents,
final Map<Entity, BigDecimal> operationRuns, final boolean includeTpz, final boolean includeAdditionalTime,
final Entity productionLine, final boolean saved) {
Map<Entity, Integer> workstations = getWorkstationsForOperationsComponent(operationComponents, productionLine);
return estimateOperationsWorkTime(operationComponents, operationRuns, includeTpz, includeAdditionalTime, workstations,
saved);
}
@Override
public Map<Entity, OperationWorkTime> estimateOperationsWorkTimeForOrder(final Entity order,
final Map<Entity, BigDecimal> operationRuns, final boolean includeTpz, final boolean includeAdditionalTime,
final Entity productionLine, final boolean saved) {
List<Entity> operationComponents = order.getBelongsToField(L_TECHNOLOGY)
.getHasManyField(TechnologyFields.OPERATION_COMPONENTS);
Map<Entity, Integer> workstations = getWorkstationsFromOrder(order);
return estimateOperationsWorkTime(operationComponents, operationRuns, includeTpz, includeAdditionalTime, workstations,
saved);
}
@Override
public Map<Entity, OperationWorkTime> estimateOperationsWorkTimeForTechnology(final Entity technology,
final Map<Entity, BigDecimal> operationRuns, final boolean includeTpz, final boolean includeAdditionalTime,
final Entity productionLine, final boolean saved) {
List<Entity> operationComponents = technology.getHasManyField(TechnologyFields.OPERATION_COMPONENTS);
Map<Entity, Integer> workstations = getWorkstationsFromTechnology(technology, productionLine);
return estimateOperationsWorkTime(operationComponents, operationRuns, includeTpz, includeAdditionalTime, workstations,
saved);
}
@Override
public OperationWorkTime estimateTotalWorkTime(final List<Entity> operationComponents,
final Map<Long, BigDecimal> operationRuns, final boolean includeTpz, final boolean includeAdditionalTime,
final Map<Long, Integer> workstations, final boolean saved) {
OperationWorkTime totalWorkTime = new OperationWorkTime();
Integer totalLaborWorkTime = Integer.valueOf(0);
Integer totalMachineWorkTime = Integer.valueOf(0);
Integer duration = Integer.valueOf(0);
for (Entity operationComponent : operationComponents) {
Entity operComp = operationComponent;
OperationWorkTime abstractOperationWorkTime = estimateOperationWorkTime(operComp,
getOperationRunsFromMap(operationRuns, operationComponent), includeTpz, includeAdditionalTime,
getWorkstationsQuantityFromMap(workstations, operationComponent), saved);
totalLaborWorkTime += abstractOperationWorkTime.getLaborWorkTime();
totalMachineWorkTime += abstractOperationWorkTime.getMachineWorkTime();
duration += abstractOperationWorkTime.getDuration();
}
totalWorkTime.setLaborWorkTime(totalLaborWorkTime);
totalWorkTime.setMachineWorkTime(totalMachineWorkTime);
totalWorkTime.setDuration(duration);
return totalWorkTime;
}
private void savedWorkTime(final Entity entity, final Integer machineWorkTime, final Integer laborWorkTime,
final Integer duration) {
String entityType = entity.getDataDefinition().getName();
if (TechnologiesConstants.MODEL_TECHNOLOGY_OPERATION_COMPONENT.equals(entityType)) {
DataDefinition techOperCompTimeCalculationDD = dataDefinitionService.get(TimeNormsConstants.PLUGIN_IDENTIFIER,
TimeNormsConstants.MODEL_TECH_OPER_COMP_TIME_CALCULATION);
Entity techOperCompTimeCalculation = entity
.getBelongsToField(TechnologyOperationComponentFieldsTNFO.TECH_OPER_COMP_TIME_CALCULATION);
if (techOperCompTimeCalculation != null) {
techOperCompTimeCalculation.setField(TechOperCompTimeCalculationsFields.MACHINE_WORK_TIME, machineWorkTime);
techOperCompTimeCalculation.setField(TechOperCompTimeCalculationsFields.LABOR_WORK_TIME, laborWorkTime);
techOperCompTimeCalculation.setField(TechOperCompTimeCalculationsFields.DURATION, duration);
techOperCompTimeCalculationDD.save(techOperCompTimeCalculation);
}
} else {
entity.setField("machineWorkTime", machineWorkTime);
entity.setField("laborWorkTime", laborWorkTime);
entity.setField("duration", duration);
entity.getDataDefinition().save(entity);
}
}
@Override
public OperationWorkTime estimateTotalWorkTime(final List<Entity> operationComponents,
final Map<Long, BigDecimal> operationRuns, final boolean includeTpz, final boolean includeAdditionalTime,
final Entity productionLine, final boolean saved) {
Map<Long, Integer> workstations = getWorkstationsMapsForOperationsComponent(operationComponents, productionLine);
return estimateTotalWorkTime(operationComponents, operationRuns, includeTpz, includeAdditionalTime, workstations, saved);
}
@Override
public OperationWorkTime estimateTotalWorkTimeForOrder(final Entity order, final Map<Long, BigDecimal> operationRuns,
final boolean includeTpz, final boolean includeAdditionalTime, final Entity productionLine, final boolean saved) {
List<Entity> operationComponents = order.getBelongsToField(L_TECHNOLOGY)
.getHasManyField(TechnologyFields.OPERATION_COMPONENTS);
Map<Long, Integer> workstations = getWorkstationsMapFromOrder(order);
return estimateTotalWorkTime(operationComponents, operationRuns, includeTpz, includeAdditionalTime, workstations, saved);
}
@Override
public OperationWorkTime estimateTotalWorkTimeForTechnology(final Entity technology,
final Map<Long, BigDecimal> operationRuns, final boolean includeTpz, final boolean includeAdditionalTime,
final Entity productionLine, final boolean saved) {
List<Entity> operationComponents = technology.getHasManyField(TechnologyFields.OPERATION_COMPONENTS);
Map<Long, Integer> workstations = getWorkstationsMapFromTechnology(technology, productionLine);
return estimateTotalWorkTime(operationComponents, operationRuns, includeTpz, includeAdditionalTime, workstations, saved);
}
private Map<Long, Integer> getWorkstationsMapsForOperationsComponent(final List<Entity> operationsComponents,
final Entity productionLine) {
Map<Long, Integer> workstations = new HashMap<Long, Integer>();
for (Entity operComp : operationsComponents) {
String entityType = operComp.getDataDefinition().getName();
if (!L_TECHNOLOGY_OPERATION_COMPONENT.equals(entityType)) {
operComp = operComp.getBelongsToField(L_TECHNOLOGY_OPERATION_COMPONENT).getDataDefinition()
.get(operComp.getBelongsToField(L_TECHNOLOGY_OPERATION_COMPONENT).getId());
}
if (parameterService.getParameter().getBooleanField("workstationsQuantityFromProductionLine")) {
workstations.put(operComp.getId(), productionLinesService.getWorkstationTypesCount(operComp, productionLine));
} else {
workstations.put(operComp.getId(),
operComp.getIntegerField(TechnologyOperationComponentFields.QUANTITY_OF_WORKSTATIONS));
}
}
return workstations;
}
private Map<Entity, Integer> getWorkstationsForOperationsComponent(final List<Entity> operationsComponents,
final Entity productionLine) {
Map<Entity, Integer> workstations = new HashMap<Entity, Integer>();
for (Entity operComp : operationsComponents) {
String entityType = operComp.getDataDefinition().getName();
if (!L_TECHNOLOGY_OPERATION_COMPONENT.equals(entityType)) {
operComp = operComp.getBelongsToField(L_TECHNOLOGY_OPERATION_COMPONENT).getDataDefinition()
.get(operComp.getBelongsToField(L_TECHNOLOGY_OPERATION_COMPONENT).getId());
}
if (parameterService.getParameter().getBooleanField("workstationsQuantityFromProductionLine")) {
workstations.put(operComp, productionLinesService.getWorkstationTypesCount(operComp, productionLine));
} else {
workstations.put(operComp, operComp.getIntegerField(TechnologyOperationComponentFields.QUANTITY_OF_WORKSTATIONS));
}
}
return workstations;
}
private BigDecimal getOperationRuns(final Map<Entity, BigDecimal> operationRuns, final Entity operationComponent) {
Entity operComp = operationComponent;
String entityType = operationComponent.getDataDefinition().getName();
if (!TechnologiesConstants.MODEL_TECHNOLOGY_OPERATION_COMPONENT.equals(entityType)) {
operComp = operComp.getBelongsToField(L_TECHNOLOGY_OPERATION_COMPONENT).getDataDefinition()
.get(operComp.getBelongsToField(L_TECHNOLOGY_OPERATION_COMPONENT).getId());
}
return BigDecimalUtils.convertNullToZero(operationRuns.get(operComp));
}
private BigDecimal getOperationRunsFromMap(final Map<Long, BigDecimal> operationRuns, final Entity operationComponent) {
Entity operComp = operationComponent;
String entityType = operationComponent.getDataDefinition().getName();
if (!TechnologiesConstants.MODEL_TECHNOLOGY_OPERATION_COMPONENT.equals(entityType)) {
operComp = operComp.getBelongsToField(L_TECHNOLOGY_OPERATION_COMPONENT).getDataDefinition()
.get(operComp.getBelongsToField(L_TECHNOLOGY_OPERATION_COMPONENT).getId());
}
return BigDecimalUtils.convertNullToZero(operationRuns.get(operComp.getId()));
}
private Integer getWorkstationsQuantity(final Map<Entity, Integer> workstations, final Entity operationComponent) {
Entity operComp = operationComponent;
String entityType = operationComponent.getDataDefinition().getName();
if (!TechnologiesConstants.MODEL_TECHNOLOGY_OPERATION_COMPONENT.equals(entityType)) {
operComp = operComp.getBelongsToField(L_TECHNOLOGY_OPERATION_COMPONENT).getDataDefinition()
.get(operComp.getBelongsToField(L_TECHNOLOGY_OPERATION_COMPONENT).getId());
}
return workstations.get(operComp);
}
private Integer getWorkstationsQuantityFromMap(final Map<Long, Integer> workstations, final Entity operationComponent) {
Entity operComp = operationComponent;
String entityType = operationComponent.getDataDefinition().getName();
if (!TechnologiesConstants.MODEL_TECHNOLOGY_OPERATION_COMPONENT.equals(entityType)) {
operComp = operComp.getBelongsToField(L_TECHNOLOGY_OPERATION_COMPONENT).getDataDefinition()
.get(operComp.getBelongsToField(L_TECHNOLOGY_OPERATION_COMPONENT).getId());
}
return workstations.get(operComp.getId());
}
private Map<Long, Integer> getWorkstationsMapFromTechnology(final Entity technology, final Entity productionLine) {
Map<Long, Integer> workstations = new HashMap<Long, Integer>();
for (Entity operComp : technology.getHasManyField(TechnologyFields.OPERATION_COMPONENTS)) {
workstations.put(operComp.getId(), productionLinesService.getWorkstationTypesCount(operComp, productionLine));
}
return workstations;
}
private Map<Entity, Integer> getWorkstationsFromTechnology(final Entity technology, final Entity productionLine) {
Map<Entity, Integer> workstations = new HashMap<Entity, Integer>();
for (Entity operComp : technology.getHasManyField(TechnologyFields.OPERATION_COMPONENTS)) {
if (parameterService.getParameter().getBooleanField("workstationsQuantityFromProductionLine")) {
workstations.put(operComp, productionLinesService.getWorkstationTypesCount(operComp, productionLine));
} else {
workstations.put(operComp, operComp.getIntegerField(TechnologyOperationComponentFields.QUANTITY_OF_WORKSTATIONS));
}
}
return workstations;
}
private Map<Long, Integer> getWorkstationsMapFromOrder(final Entity order) {
Map<Long, Integer> workstations = new HashMap<Long, Integer>();
for (Entity operComp : order.getBelongsToField(L_TECHNOLOGY).getHasManyField("operationComponents")) {
workstations.put(operComp.getId(),
operComp.getIntegerField(TechnologyOperationComponentFields.QUANTITY_OF_WORKSTATIONS));
}
return workstations;
}
private Map<Entity, Integer> getWorkstationsFromOrder(final Entity order) {
Map<Entity, Integer> workstations = new HashMap<Entity, Integer>();
for (Entity operComp : order.getBelongsToField(L_TECHNOLOGY).getHasManyField("operationComponents")) {
workstations.put(operComp, operComp.getIntegerField(TechnologyOperationComponentFields.QUANTITY_OF_WORKSTATIONS));
}
return workstations;
}
private Integer getIntegerValue(final Object value) {
return value == null ? Integer.valueOf(0) : (Integer) value;
}
}