/**
* ***************************************************************************
* 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.technologies;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
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.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.qcadoo.mes.basic.constants.BasicConstants;
import com.qcadoo.mes.technologies.constants.MrpAlgorithm;
import com.qcadoo.mes.technologies.constants.OperationProductInComponentFields;
import com.qcadoo.mes.technologies.constants.OperationProductOutComponentFields;
import com.qcadoo.mes.technologies.constants.ProductComponentFields;
import com.qcadoo.mes.technologies.constants.TechnologiesConstants;
import com.qcadoo.mes.technologies.constants.TechnologyFields;
import com.qcadoo.mes.technologies.constants.TechnologyOperationComponentEntityType;
import com.qcadoo.mes.technologies.constants.TechnologyOperationComponentFields;
import com.qcadoo.mes.technologies.dto.OperationProductComponentHolder;
import com.qcadoo.mes.technologies.dto.OperationProductComponentWithQuantityContainer;
import com.qcadoo.mes.technologies.dto.ProductQuantitiesHolder;
import com.qcadoo.model.api.DataDefinition;
import com.qcadoo.model.api.DataDefinitionService;
import com.qcadoo.model.api.Entity;
import com.qcadoo.model.api.EntityTree;
import com.qcadoo.model.api.NumberService;
import com.qcadoo.model.api.search.SearchRestrictions;
@Service
public class ProductQuantitiesServiceImpl implements ProductQuantitiesService {
private static final String L_ORDER = "order";
private static final String L_TECHNOLOGY = "technology";
private static final String L_PLANNED_QUANTITY = "plannedQuantity";
private static final String L_QUANTITY = "quantity";
@Autowired
private NumberService numberService;
@Autowired
private DataDefinitionService dataDefinitionService;
@Override
public ProductQuantitiesHolder getProductComponentQuantities(final Entity technology, final BigDecimal givenQuantity) {
Map<Long, BigDecimal> operationRuns = Maps.newHashMap();
OperationProductComponentWithQuantityContainer productQuantities = getProductComponentQuantities(technology,
givenQuantity, operationRuns);
return new ProductQuantitiesHolder(productQuantities, operationRuns);
}
@Override
public OperationProductComponentWithQuantityContainer getProductComponentQuantities(final Entity technology,
final BigDecimal givenQuantity, final Map<Long, BigDecimal> operationRuns) {
Set<OperationProductComponentHolder> nonComponents = Sets.newHashSet();
return getProductComponentWithQuantitiesForTechnology(technology, givenQuantity, operationRuns, nonComponents);
}
@Override
public OperationProductComponentWithQuantityContainer getProductComponentQuantities(final Entity order) {
return getProductComponentQuantities(order, false);
}
private OperationProductComponentWithQuantityContainer getProductComponentQuantities(final Entity order,
final boolean onTheFly) {
Map<Long, BigDecimal> operationRuns = Maps.newHashMap();
return getProductComponentQuantities(order, operationRuns, onTheFly);
}
@Override
public OperationProductComponentWithQuantityContainer getProductComponentQuantities(final Entity order,
final Map<Long, BigDecimal> operationRuns) {
return getProductComponentQuantities(order, operationRuns, false);
}
private OperationProductComponentWithQuantityContainer getProductComponentQuantities(final Entity order,
final Map<Long, BigDecimal> operationRuns, final boolean onTheFly) {
Set<OperationProductComponentHolder> nonComponents = Sets.newHashSet();
return getProductComponentWithQuantitiesForOrders(Lists.newArrayList(order), operationRuns, nonComponents, onTheFly);
}
@Override
public OperationProductComponentWithQuantityContainer getProductComponentQuantitiesWithoutNonComponents(
final List<Entity> orders) {
return getProductComponentQuantitiesWithoutNonComponents(orders, false);
}
@Override
public OperationProductComponentWithQuantityContainer getProductComponentQuantitiesWithoutNonComponents(
final List<Entity> orders, final boolean onTheFly) {
Map<Long, BigDecimal> operationRuns = Maps.newHashMap();
Set<OperationProductComponentHolder> nonComponents = Sets.newHashSet();
OperationProductComponentWithQuantityContainer productComponentWithQuantities = getProductComponentWithQuantitiesForOrders(
orders, operationRuns, nonComponents, onTheFly);
return getProductComponentWithQuantitiesWithoutNonComponents(productComponentWithQuantities, nonComponents);
}
private OperationProductComponentWithQuantityContainer getProductComponentWithQuantitiesWithoutNonComponents(
final OperationProductComponentWithQuantityContainer productComponentWithQuantities,
final Set<OperationProductComponentHolder> nonComponents) {
for (OperationProductComponentHolder nonComponent : nonComponents) {
productComponentWithQuantities.remove(nonComponent);
}
return productComponentWithQuantities;
}
@Override
public Map<Long, BigDecimal> getNeededProductQuantities(final Entity technology, final BigDecimal givenQuantity,
final MrpAlgorithm mrpAlgorithm) {
Map<Long, BigDecimal> operationRuns = Maps.newHashMap();
Set<OperationProductComponentHolder> nonComponents = Sets.newHashSet();
OperationProductComponentWithQuantityContainer productComponentWithQuantities = getProductComponentWithQuantitiesForTechnology(
technology, givenQuantity, operationRuns, nonComponents);
return getProductWithQuantities(productComponentWithQuantities, nonComponents, mrpAlgorithm,
TechnologiesConstants.MODEL_OPERATION_PRODUCT_IN_COMPONENT);
}
@Override
public Map<Long, BigDecimal> getNeededProductQuantities(final Entity order, final MrpAlgorithm mrpAlgorithm) {
return getNeededProductQuantities(Lists.newArrayList(order), mrpAlgorithm, false);
}
@Override
public Map<Long, BigDecimal> getNeededProductQuantities(final List<Entity> orders, final MrpAlgorithm mrpAlgorithm,
final boolean onTheFly) {
Map<Long, BigDecimal> operationRuns = Maps.newHashMap();
return getNeededProductQuantities(orders, mrpAlgorithm, operationRuns, onTheFly);
}
@Override
public Map<Long, BigDecimal> getNeededProductQuantities(final List<Entity> orders, final MrpAlgorithm mrpAlgorithm,
final Map<Long, BigDecimal> operationRuns) {
return getNeededProductQuantities(orders, mrpAlgorithm, operationRuns, false);
}
private Map<Long, BigDecimal> getNeededProductQuantities(final List<Entity> orders, final MrpAlgorithm mrpAlgorithm,
final Map<Long, BigDecimal> operationRuns, final boolean onTheFly) {
Set<OperationProductComponentHolder> nonComponents = Sets.newHashSet();
OperationProductComponentWithQuantityContainer productComponentWithQuantities = getProductComponentWithQuantitiesForOrders(
orders, operationRuns, nonComponents, onTheFly);
return getProductWithQuantities(productComponentWithQuantities, nonComponents, mrpAlgorithm,
TechnologiesConstants.MODEL_OPERATION_PRODUCT_IN_COMPONENT);
}
@Override
public Map<Long, BigDecimal> getNeededProductQuantitiesForComponents(final List<Entity> components,
final MrpAlgorithm mrpAlgorithm) {
return getNeededProductQuantitiesForComponents(components, mrpAlgorithm, false);
}
private Map<Long, BigDecimal> getNeededProductQuantitiesForComponents(final List<Entity> components,
final MrpAlgorithm mrpAlgorithm, final boolean onTheFly) {
Map<Long, BigDecimal> operationRuns = Maps.newHashMap();
Set<OperationProductComponentHolder> nonComponents = Sets.newHashSet();
OperationProductComponentWithQuantityContainer productComponentWithQuantities = getProductComponentWithQuantitiesForOrders(
getOrdersFromComponents(components), operationRuns, nonComponents, onTheFly);
return getProductWithQuantities(productComponentWithQuantities, nonComponents, mrpAlgorithm,
TechnologiesConstants.MODEL_OPERATION_PRODUCT_IN_COMPONENT);
}
@Override
public OperationProductComponentWithQuantityContainer getProductComponentWithQuantitiesForTechnology(final Entity technology,
final BigDecimal givenQuantity, final Map<Long, BigDecimal> operationRuns,
final Set<OperationProductComponentHolder> nonComponents) {
OperationProductComponentWithQuantityContainer operationProductComponentWithQuantityContainer = new OperationProductComponentWithQuantityContainer();
EntityTree operationComponents = getOperationComponentsFromTechnology(technology);
Entity root = operationComponents.getRoot();
if (root != null) {
preloadProductQuantitiesAndOperationRuns(operationComponents, operationProductComponentWithQuantityContainer,
operationRuns);
traverseProductQuantitiesAndOperationRuns(technology, givenQuantity, root, null,
operationProductComponentWithQuantityContainer, nonComponents, operationRuns);
}
return operationProductComponentWithQuantityContainer;
}
private EntityTree getOperationComponentsFromTechnology(final Entity technology) {
return technology.getTreeField(TechnologyFields.OPERATION_COMPONENTS);
}
private OperationProductComponentWithQuantityContainer getProductComponentWithQuantitiesForOrders(final List<Entity> orders,
final Map<Long, BigDecimal> operationRuns, final Set<OperationProductComponentHolder> nonComponents,
final boolean onTheFly) {
Map<Long, OperationProductComponentWithQuantityContainer> productComponentWithQuantitiesForOrders = Maps.newHashMap();
for (Entity order : orders) {
BigDecimal plannedQuantity = order.getDecimalField(L_PLANNED_QUANTITY);
Entity technology = order.getBelongsToField(L_TECHNOLOGY);
if (technology == null) {
throw new IllegalStateException("Order doesn't contain technology.");
}
productComponentWithQuantitiesForOrders.put(order.getId(),
getProductComponentWithQuantitiesForTechnology(technology, plannedQuantity, operationRuns, nonComponents));
}
return groupOperationProductComponentWithQuantities(productComponentWithQuantitiesForOrders);
}
@Override
public OperationProductComponentWithQuantityContainer groupOperationProductComponentWithQuantities(
final Map<Long, OperationProductComponentWithQuantityContainer> operationProductComponentWithQuantityContainerForOrders) {
OperationProductComponentWithQuantityContainer operationProductComponentWithQuantityContainer = new OperationProductComponentWithQuantityContainer();
for (Entry<Long, OperationProductComponentWithQuantityContainer> operationProductComponentWithQuantityContainerForOrder : operationProductComponentWithQuantityContainerForOrders
.entrySet()) {
for (Entry<OperationProductComponentHolder, BigDecimal> productComponentWithQuantity : operationProductComponentWithQuantityContainerForOrder
.getValue().asMap().entrySet()) {
OperationProductComponentHolder operationProductComponentHolder = productComponentWithQuantity.getKey();
BigDecimal quantity = productComponentWithQuantity.getValue();
if (operationProductComponentWithQuantityContainer.containsKey(operationProductComponentHolder)) {
BigDecimal addedQuantity = operationProductComponentWithQuantityContainer
.get(operationProductComponentHolder);
quantity = quantity.add(addedQuantity, numberService.getMathContext());
operationProductComponentWithQuantityContainer.put(operationProductComponentHolder, quantity);
} else {
operationProductComponentWithQuantityContainer.put(operationProductComponentHolder, quantity);
}
}
}
return operationProductComponentWithQuantityContainer;
}
@Override
public void preloadProductQuantitiesAndOperationRuns(final EntityTree operationComponents,
final OperationProductComponentWithQuantityContainer operationProductComponentWithQuantityContainer,
final Map<Long, BigDecimal> operationRuns) {
for (Entity operationComponent : operationComponents) {
if (isTechnologyOperationComponentEntityTypeReferenceTechnology(operationComponent)) {
Entity referenceTechnology = operationComponent
.getBelongsToField(TechnologyOperationComponentFields.REFERENCE_TECHNOLOGY);
EntityTree referenceOperationComponents = referenceTechnology.getTreeField(TechnologyFields.OPERATION_COMPONENTS);
preloadProductQuantitiesAndOperationRuns(referenceOperationComponents,
operationProductComponentWithQuantityContainer, operationRuns);
continue;
}
preloadOperationProductComponentQuantity(
operationComponent.getHasManyField(TechnologyOperationComponentFields.OPERATION_PRODUCT_IN_COMPONENTS),
operationProductComponentWithQuantityContainer);
preloadOperationProductComponentQuantity(
operationComponent.getHasManyField(TechnologyOperationComponentFields.OPERATION_PRODUCT_OUT_COMPONENTS),
operationProductComponentWithQuantityContainer);
operationRuns.put(operationComponent.getId(), BigDecimal.ONE);
}
}
@Override
public void preloadOperationProductComponentQuantity(final List<Entity> operationProductComponents,
final OperationProductComponentWithQuantityContainer operationProductComponentWithQuantityContainer) {
for (Entity operationProductComponent : operationProductComponents) {
BigDecimal neededQuantity = operationProductComponent.getDecimalField(L_QUANTITY);
operationProductComponentWithQuantityContainer.put(operationProductComponent, neededQuantity);
}
}
@Override
public void traverseProductQuantitiesAndOperationRuns(final Entity technology, final BigDecimal givenQuantity,
final Entity operationComponent, final Entity previousOperationComponent,
final OperationProductComponentWithQuantityContainer operationProductComponentWithQuantityContainer,
final Set<OperationProductComponentHolder> nonComponents, final Map<Long, BigDecimal> operationRuns) {
if (isTechnologyOperationComponentEntityTypeReferenceTechnology(operationComponent)) {
Entity referenceTechnology = operationComponent
.getBelongsToField(TechnologyOperationComponentFields.REFERENCE_TECHNOLOGY);
EntityTree referenceOperationComponent = referenceTechnology.getTreeField(TechnologyFields.OPERATION_COMPONENTS);
traverseProductQuantitiesAndOperationRuns(referenceTechnology, givenQuantity, referenceOperationComponent.getRoot(),
previousOperationComponent, operationProductComponentWithQuantityContainer, nonComponents, operationRuns);
return;
}
if (previousOperationComponent == null) {
Entity technologyProduct = technology.getBelongsToField(TechnologyFields.PRODUCT);
for (Entity operationProductOutComponent : operationComponent
.getHasManyField(TechnologyOperationComponentFields.OPERATION_PRODUCT_OUT_COMPONENTS)) {
if (operationProductOutComponent.getBelongsToField(OperationProductOutComponentFields.PRODUCT).getId()
.equals(technologyProduct.getId())) {
BigDecimal outQuantity = operationProductComponentWithQuantityContainer.get(operationProductOutComponent);
multiplyProductQuantitiesAndAddOperationRuns(operationComponent, givenQuantity, outQuantity,
operationProductComponentWithQuantityContainer, operationRuns);
break;
}
}
} else {
for (Entity operationProductInComponent : previousOperationComponent
.getHasManyField(TechnologyOperationComponentFields.OPERATION_PRODUCT_IN_COMPONENTS)) {
boolean isntComponent = false;
for (Entity operationProductOutComponent : operationComponent
.getHasManyField(TechnologyOperationComponentFields.OPERATION_PRODUCT_OUT_COMPONENTS)) {
if (operationProductOutComponent
.getBelongsToField(OperationProductOutComponentFields.PRODUCT)
.getId()
.equals(operationProductInComponent.getBelongsToField(OperationProductInComponentFields.PRODUCT)
.getId())) {
isntComponent = true;
BigDecimal outQuantity = operationProductComponentWithQuantityContainer.get(operationProductOutComponent);
BigDecimal inQuantity = operationProductComponentWithQuantityContainer.get(operationProductInComponent);
multiplyProductQuantitiesAndAddOperationRuns(operationComponent, inQuantity, outQuantity,
operationProductComponentWithQuantityContainer, operationRuns);
break;
}
}
if (isntComponent) {
nonComponents.add(new OperationProductComponentHolder(operationProductInComponent));
}
}
}
for (Entity child : operationComponent.getHasManyField(TechnologyOperationComponentFields.CHILDREN)) {
traverseProductQuantitiesAndOperationRuns(technology, givenQuantity, child, operationComponent,
operationProductComponentWithQuantityContainer, nonComponents, operationRuns);
}
}
@Override
public void traverseProductQuantitiesAndOperationRuns(final Entity technology, Map<Long, Entity> entitiesById,
final BigDecimal givenQuantity, final Entity operationComponent, final Entity previousOperationComponent,
final OperationProductComponentWithQuantityContainer operationProductComponentWithQuantityContainer,
final Set<OperationProductComponentHolder> nonComponents, final Map<Long, BigDecimal> operationRuns) {
if (isTechnologyOperationComponentEntityTypeReferenceTechnology(operationComponent)) {
Entity referenceTechnology = operationComponent
.getBelongsToField(TechnologyOperationComponentFields.REFERENCE_TECHNOLOGY);
EntityTree referenceOperationComponent = referenceTechnology.getTreeField(TechnologyFields.OPERATION_COMPONENTS);
traverseProductQuantitiesAndOperationRuns(referenceTechnology, givenQuantity, referenceOperationComponent.getRoot(),
previousOperationComponent, operationProductComponentWithQuantityContainer, nonComponents, operationRuns);
return;
}
if (previousOperationComponent == null) {
Entity technologyProduct = technology.getBelongsToField(TechnologyFields.PRODUCT);
for (Entity operationProductOutComponent : operationComponent
.getHasManyField(TechnologyOperationComponentFields.OPERATION_PRODUCT_OUT_COMPONENTS)) {
if (operationProductOutComponent.getBelongsToField(OperationProductOutComponentFields.PRODUCT).getId()
.equals(technologyProduct.getId())) {
BigDecimal outQuantity = operationProductComponentWithQuantityContainer.get(operationProductOutComponent);
multiplyProductQuantitiesAndAddOperationRuns(operationComponent, givenQuantity, outQuantity,
operationProductComponentWithQuantityContainer, operationRuns);
break;
}
}
} else {
for (Entity operationProductInComponent : previousOperationComponent
.getHasManyField(TechnologyOperationComponentFields.OPERATION_PRODUCT_IN_COMPONENTS)) {
boolean isntComponent = false;
for (Entity operationProductOutComponent : operationComponent
.getHasManyField(TechnologyOperationComponentFields.OPERATION_PRODUCT_OUT_COMPONENTS)) {
if (operationProductOutComponent
.getBelongsToField(OperationProductOutComponentFields.PRODUCT)
.getId()
.equals(operationProductInComponent.getBelongsToField(OperationProductInComponentFields.PRODUCT)
.getId())) {
isntComponent = true;
BigDecimal outQuantity = operationProductComponentWithQuantityContainer.get(operationProductOutComponent);
BigDecimal inQuantity = operationProductComponentWithQuantityContainer.get(operationProductInComponent);
multiplyProductQuantitiesAndAddOperationRuns(operationComponent, inQuantity, outQuantity,
operationProductComponentWithQuantityContainer, operationRuns);
break;
}
}
if (isntComponent) {
nonComponents.add(new OperationProductComponentHolder(operationProductInComponent));
}
}
}
for (Entity child : entitiesById.get(operationComponent.getId()).getHasManyField(
TechnologyOperationComponentFields.CHILDREN)) {
traverseProductQuantitiesAndOperationRuns(technology, entitiesById, givenQuantity, child, operationComponent,
operationProductComponentWithQuantityContainer, nonComponents, operationRuns);
}
}
private void multiplyProductQuantitiesAndAddOperationRuns(final Entity operationComponent, final BigDecimal needed,
final BigDecimal actual,
final OperationProductComponentWithQuantityContainer operationProductComponentWithQuantityContainer,
final Map<Long, BigDecimal> operationRuns) {
BigDecimal multiplier = needed.divide(actual, numberService.getMathContext());
if (!operationComponent.getBooleanField(TechnologyOperationComponentFields.ARE_PRODUCT_QUANTITIES_DIVISIBLE)) {
// It's intentional to round up the operation runs
multiplier = multiplier.setScale(0, RoundingMode.CEILING);
}
BigDecimal runs = multiplier;
if (!operationComponent.getBooleanField(TechnologyOperationComponentFields.IS_TJ_DIVISIBLE)) {
runs = multiplier.setScale(0, RoundingMode.CEILING);
}
operationRuns.put(operationComponent.getId(), runs);
multiplyOperationProductComponentQuantities(
operationComponent.getHasManyField(TechnologyOperationComponentFields.OPERATION_PRODUCT_IN_COMPONENTS),
multiplier, operationProductComponentWithQuantityContainer);
multiplyOperationProductComponentQuantities(
operationComponent.getHasManyField(TechnologyOperationComponentFields.OPERATION_PRODUCT_OUT_COMPONENTS),
multiplier, operationProductComponentWithQuantityContainer);
}
private void multiplyOperationProductComponentQuantities(final List<Entity> operationProductComponents,
final BigDecimal multiplier,
final OperationProductComponentWithQuantityContainer operationProductComponentWithQuantityContainer) {
for (Entity operationProductComponent : operationProductComponents) {
BigDecimal addedQuantity = operationProductComponentWithQuantityContainer.get(operationProductComponent);
BigDecimal quantity = addedQuantity.multiply(multiplier, numberService.getMathContext());
operationProductComponentWithQuantityContainer.put(operationProductComponent,
quantity.setScale(5, RoundingMode.CEILING));
}
}
private boolean isTechnologyOperationComponentEntityTypeReferenceTechnology(final Entity operationComponent) {
return TechnologyOperationComponentEntityType.REFERENCE_TECHNOLOGY.getStringValue().equals(
operationComponent.getStringField(TechnologyOperationComponentFields.ENTITY_TYPE));
}
@Override
public OperationProductComponentWithQuantityContainer getProductComponentWithQuantities(final List<Entity> orders,
final Map<Long, BigDecimal> operationRuns, final Set<OperationProductComponentHolder> nonComponents) {
return getProductComponentWithQuantitiesForOrders(orders, operationRuns, nonComponents, true);
}
private List<Entity> getOrdersFromComponents(final List<Entity> components) {
List<Entity> orders = Lists.newArrayList();
for (Entity component : components) {
Entity order = component.getBelongsToField(L_ORDER);
if (order == null) {
throw new IllegalStateException(
"Given component doesn't point to an order using getBelongsToField(\"order\") relation");
}
orders.add(order);
}
return orders;
}
@Override
public Map<Long, BigDecimal> getProductWithQuantities(
final OperationProductComponentWithQuantityContainer productComponentWithQuantities,
final Set<OperationProductComponentHolder> nonComponents, final MrpAlgorithm mrpAlgorithm,
final String operationProductComponentModelName) {
OperationProductComponentWithQuantityContainer allWithSameEntityType = productComponentWithQuantities
.getAllWithSameEntityType(operationProductComponentModelName);
if (mrpAlgorithm.equals(MrpAlgorithm.ALL_PRODUCTS_IN)) {
return getProductWithoutSubcontractingProduct(allWithSameEntityType, nonComponents, false);
} else if (mrpAlgorithm.equals(MrpAlgorithm.ONLY_COMPONENTS)) {
return getProductWithoutSubcontractingProduct(allWithSameEntityType, nonComponents, true);
} else if (mrpAlgorithm.equals(MrpAlgorithm.COMPONENTS_AND_SUBCONTRACTORS_PRODUCTS)) {
return getProductWithoutSubcontractingProduct(allWithSameEntityType, nonComponents, false);
} else {
return getProductWithoutSubcontractingProduct(allWithSameEntityType, nonComponents, true, true);
}
}
private Map<Long, BigDecimal> getProductWithoutSubcontractingProduct(
final OperationProductComponentWithQuantityContainer productComponentWithQuantities,
final Set<OperationProductComponentHolder> nonComponents, final boolean onlyComponents) {
return getProductWithoutSubcontractingProduct(productComponentWithQuantities, nonComponents, onlyComponents, false);
}
private Map<Long, BigDecimal> getProductWithoutSubcontractingProduct(
final OperationProductComponentWithQuantityContainer productComponentWithQuantities,
final Set<OperationProductComponentHolder> nonComponents, final boolean onlyComponents, final boolean onlyMaterials) {
Map<Long, BigDecimal> productWithQuantities = Maps.newHashMap();
for (Entry<OperationProductComponentHolder, BigDecimal> productComponentWithQuantity : productComponentWithQuantities
.asMap().entrySet()) {
OperationProductComponentHolder operationProductComponentHolder = productComponentWithQuantity.getKey();
if (onlyComponents && nonComponents.contains(operationProductComponentHolder)) {
continue;
}
if (onlyMaterials) {
Entity product = operationProductComponentHolder.getProduct();
if (hasAcceptedMasterTechnology(product)) {
continue;
}
}
addProductQuantitiesToList(productComponentWithQuantity, productWithQuantities);
}
return productWithQuantities;
}
private boolean hasAcceptedMasterTechnology(final Entity product) {
DataDefinition technologyDD = dataDefinitionService.get(TechnologiesConstants.PLUGIN_IDENTIFIER,
TechnologiesConstants.MODEL_TECHNOLOGY);
Entity masterTechnology = technologyDD
.find()
.add(SearchRestrictions.and(SearchRestrictions.belongsTo(TechnologyFields.PRODUCT, product),
(SearchRestrictions.eq("state", "02accepted"))))
.add(SearchRestrictions.eq(TechnologyFields.MASTER, true)).setMaxResults(1).uniqueResult();
return masterTechnology != null;
}
@Override
public void addProductQuantitiesToList(final Entry<OperationProductComponentHolder, BigDecimal> productComponentWithQuantity,
final Map<Long, BigDecimal> productWithQuantities) {
OperationProductComponentHolder operationProductComponentHolder = productComponentWithQuantity.getKey();
Entity product = operationProductComponentHolder.getProduct();
BigDecimal newQuantity = productComponentWithQuantity.getValue();
BigDecimal oldQuantity = productWithQuantities.get(product.getId());
if (oldQuantity != null) {
newQuantity = newQuantity.add(oldQuantity);
}
productWithQuantities.put(product.getId(), newQuantity);
}
@Override
public Entity getOutputProductsFromOperationComponent(final Entity operationComponent) {
final List<Entity> operationProductOutComponents = operationComponent
.getHasManyField(TechnologyOperationComponentFields.OPERATION_PRODUCT_OUT_COMPONENTS);
if (operationProductOutComponents.isEmpty()) {
return null;
}
final Entity parentOperation = operationComponent.getBelongsToField(TechnologyOperationComponentFields.PARENT);
if (parentOperation == null) {
Entity technology = operationComponent.getBelongsToField(TechnologyOperationComponentFields.TECHNOLOGY);
Entity technologyProduct = technology.getBelongsToField(TechnologyFields.PRODUCT);
for (Entity product : operationProductOutComponents) {
if (product.getBelongsToField(ProductComponentFields.PRODUCT).getId().equals(technologyProduct.getId())) {
return product;
}
}
return null;
} else {
final List<Entity> parentOperationProductInComponents = parentOperation
.getHasManyField(TechnologyOperationComponentFields.OPERATION_PRODUCT_IN_COMPONENTS);
for (Entity operationProductOutComponent : operationProductOutComponents) {
if (findProductParentOperation(operationProductOutComponent, parentOperationProductInComponents)) {
return operationProductOutComponent;
}
}
return null;
}
}
private boolean findProductParentOperation(final Entity operationProductOutComponent,
final List<Entity> parentOperationProductInComponents) {
for (Entity parentOperationProductInComponent : parentOperationProductInComponents) {
Entity parentProduct = parentOperationProductInComponent.getBelongsToField(OperationProductInComponentFields.PRODUCT);
Entity currentProduct = operationProductOutComponent.getBelongsToField(OperationProductOutComponentFields.PRODUCT);
if (parentProduct.getId().equals(currentProduct.getId())) {
return true;
}
}
return false;
}
@Override
public Entity getTechnologyOperationComponent(final Long technologyOperationComponentId) {
return dataDefinitionService.get(TechnologiesConstants.PLUGIN_IDENTIFIER,
TechnologiesConstants.MODEL_TECHNOLOGY_OPERATION_COMPONENT).get(technologyOperationComponentId);
}
@Override
public Entity getProduct(final Long productId) {
return dataDefinitionService.get(BasicConstants.PLUGIN_IDENTIFIER, BasicConstants.MODEL_PRODUCT).get(productId);
}
@Override
public Map<Entity, BigDecimal> convertOperationsRunsFromProductQuantities(
final Map<Long, BigDecimal> operationRunsFromProductionQuantities) {
final Map<Entity, BigDecimal> operationRuns = Maps.newHashMap();
for (Entry<Long, BigDecimal> operationRunsFromProductionQuantity : operationRunsFromProductionQuantities.entrySet()) {
Entity technologyOperatonComponent = getTechnologyOperationComponent(operationRunsFromProductionQuantity.getKey());
operationRuns.put(technologyOperatonComponent, operationRunsFromProductionQuantity.getValue());
}
return operationRuns;
}
}