/** * *************************************************************************** * 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.grouping; import java.math.BigDecimal; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.google.common.base.Function; import com.google.common.collect.Collections2; import com.google.common.collect.Lists; import com.qcadoo.mes.technologies.constants.OperationProductInComponentFields; import com.qcadoo.mes.technologies.constants.TechnologiesConstants; import com.qcadoo.mes.technologies.constants.TechnologyOperationComponentFields; import com.qcadoo.mes.technologies.constants.TechnologyOperationComponentMergeProductFields; import com.qcadoo.model.api.DataDefinition; import com.qcadoo.model.api.DataDefinitionService; import com.qcadoo.model.api.Entity; import com.qcadoo.model.api.search.JoinType; import com.qcadoo.model.api.search.SearchProjections; import com.qcadoo.model.api.search.SearchRestrictions; @Service public class OperationMergeServiceImpl implements OperationMergeService { private DataDefinitionService dataDefinitionService; @Autowired public OperationMergeServiceImpl(DataDefinitionService dataDefinitionService) { this.dataDefinitionService = dataDefinitionService; } @Override public void mergeProductIn(Entity order, Entity existingOperationComponent, Entity operationProductIn, BigDecimal quantity) { mergeProduct(mergesProductInDD(), order, existingOperationComponent, operationProductIn, quantity); } @Override public void storeProductIn(Entity order, Entity operationComponent, Entity mergeOperationComponent, Entity operationProductIn, BigDecimal quantity) { persistMerge(mergesProductInDD(), order, operationComponent, mergeOperationComponent, operationProductIn, quantity); } @Override public void mergeProductOut(Entity order, Entity existingOperationComponent, Entity operationProductOut, BigDecimal quantity) { mergeProduct(mergesProductOutDD(), order, existingOperationComponent, operationProductOut, quantity); } @Override public void storeProductOut(Entity order, Entity operationComponent, Entity mergeOperationComponent, Entity operationProductIn, BigDecimal quantity) { persistMerge(mergesProductOutDD(), order, operationComponent, mergeOperationComponent, operationProductIn, quantity); } @Override public List<Entity> findMergedProductInByOrder(Entity order) { return mergesProductInDD().find().add(SearchRestrictions.belongsTo("order", order)).list().getEntities(); } @Override public List<Entity> findMergedProductOutByOrder(Entity order) { return mergesProductOutDD().find().add(SearchRestrictions.belongsTo("order", order)).list().getEntities(); } @Override public List<Long> findMergedToOperationComponentIds() { List<Entity> entities = mergesProductInDD().find() .add(SearchRestrictions.lt(TechnologyOperationComponentMergeProductFields.QUANTITY_CHANGE, BigDecimal.ZERO)) .setProjection(SearchProjections.field(TechnologyOperationComponentMergeProductFields.MERGED_OPERATION_COMPONENT)) .list().getEntities(); return Lists.newArrayList(Collections2.transform(entities, new Function<Entity, Long>() { @Override public Long apply(final Entity from) { return from.getId(); } })); } @Override public Entity findMergedByOperationComponent(Entity operationComponent) { return mergesProductInDD().find() .add(SearchRestrictions.and( SearchRestrictions.belongsTo(TechnologyOperationComponentMergeProductFields.OPERATION_COMPONENT, operationComponent), SearchRestrictions.belongsTo(TechnologyOperationComponentMergeProductFields.MERGED_OPERATION_COMPONENT, operationComponent))) .uniqueResult(); } @Override public Entity findMergedByMergedToc(Entity toc) { return mergesProductInDD().find() .add(SearchRestrictions.belongsTo(TechnologyOperationComponentMergeProductFields.MERGED_OPERATION_COMPONENT, toc)).setMaxResults(1).uniqueResult(); } @Override public Entity findMergedByMergedTocId(Long tocId) { return mergesProductInDD().find() .add(SearchRestrictions.eq(TechnologyOperationComponentMergeProductFields.MERGED_OPERATION_COMPONENT + ".id", tocId)).setMaxResults(1).uniqueResult(); } @Override public boolean isMergedByTocId(Long tocId) { return mergesProductInDD().find() .add(SearchRestrictions.eq(TechnologyOperationComponentMergeProductFields.MERGED_OPERATION_COMPONENT + ".id", tocId)) .add(SearchRestrictions.lt(TechnologyOperationComponentMergeProductFields.QUANTITY_CHANGE, BigDecimal.ZERO)) .list() .getTotalNumberOfEntities() > 0; } @Override public Entity findMergedFromOperationInByOperationComponentId(Long operationComponentId) { Entity operationComponent = dataDefinitionService.get(TechnologiesConstants.PLUGIN_IDENTIFIER, TechnologiesConstants.MODEL_TECHNOLOGY_OPERATION_COMPONENT).get(operationComponentId); return mergesProductInDD().find() .add(SearchRestrictions.and( SearchRestrictions.belongsTo(TechnologyOperationComponentMergeProductFields.OPERATION_COMPONENT, operationComponent), SearchRestrictions.belongsTo(TechnologyOperationComponentMergeProductFields.MERGED_OPERATION_COMPONENT, operationComponent))) .uniqueResult(); } @Override public Entity findMergedFromOperationOutByOperationComponentId(Long operationComponentId) { return mergesProductOutDD().find() .add(SearchRestrictions.and( SearchRestrictions.eq(TechnologyOperationComponentMergeProductFields.OPERATION_COMPONENT + ".id", operationComponentId), SearchRestrictions.eq(TechnologyOperationComponentMergeProductFields.MERGED_OPERATION_COMPONENT + ".id", operationComponentId))) .uniqueResult(); } @Override public List<Entity> findMergedToByOperationComponentId(Long operationComponentId) { Entity operationComponent = dataDefinitionService.get(TechnologiesConstants.PLUGIN_IDENTIFIER, TechnologiesConstants.MODEL_TECHNOLOGY_OPERATION_COMPONENT).get(operationComponentId); return mergesProductInDD().find() .add(SearchRestrictions.and( SearchRestrictions.belongsTo(TechnologyOperationComponentMergeProductFields.OPERATION_COMPONENT, operationComponent), SearchRestrictions.not( SearchRestrictions.belongsTo(TechnologyOperationComponentMergeProductFields.MERGED_OPERATION_COMPONENT, operationComponent) ))) .list().getEntities(); } @Override public List<Entity> findMergedProductInComponentsByOperationComponent(Entity operationComponent) { return mergesProductInDD().find() .add(SearchRestrictions.belongsTo(TechnologyOperationComponentMergeProductFields.OPERATION_COMPONENT, operationComponent)) .add(SearchRestrictions.gt(TechnologyOperationComponentMergeProductFields.QUANTITY_CHANGE, BigDecimal.ZERO)) .list().getEntities(); } @Override public List<Entity> findMergedToProductOutComponentsByOperationComponent(Entity operationComponent) { return mergesProductOutDD().find() .add(SearchRestrictions.belongsTo(TechnologyOperationComponentMergeProductFields.OPERATION_COMPONENT, operationComponent)) .add(SearchRestrictions.isNotNull(TechnologyOperationComponentMergeProductFields.QUANTITY_CHANGE)) .list().getEntities(); } @Override public List<Entity> findMergedEntitiesByOperationComponent(Entity operationComponent) { return mergesProductOutDD().find() .add(SearchRestrictions.belongsTo(TechnologyOperationComponentMergeProductFields.OPERATION_COMPONENT, operationComponent)) .add(SearchRestrictions.isNull(TechnologyOperationComponentMergeProductFields.QUANTITY_CHANGE)) .list().getEntities(); } @Override public List<Entity> findMergedEntitiesByOperationComponentId(Long operationComponentId) { return mergesProductOutDD().find() .add(SearchRestrictions.eq(TechnologyOperationComponentMergeProductFields.OPERATION_COMPONENT + ".id", operationComponentId)) .add(SearchRestrictions.isNull(TechnologyOperationComponentMergeProductFields.QUANTITY_CHANGE)) .list().getEntities(); } @Override public void adjustOperationProductComponentsDueMerge(Entity operationComponent) { adjustOperationProductInComponentsDueMerge(operationComponent); adjustOperationProductOutComponentsDueMerge(operationComponent); } private void adjustOperationProductInComponentsDueMerge(Entity operationComponent) { Entity merge = findMergedByOperationComponent(operationComponent); List<Entity> operationProductInComponents = operationProductInComponents(operationComponent); List<Entity> operationProductInComponentsNew = Lists.newArrayList(); BigDecimal quantity = merge.getDecimalField(TechnologyOperationComponentMergeProductFields.QUANTITY_CHANGE); for (Entity operationProductInComponent : operationProductInComponents) { if (operationProductInComponent.getId().equals(mergedOperationProductComponent(merge).getId())) { operationProductInComponent.setField(OperationProductInComponentFields.QUANTITY, quantity); operationProductInComponentsNew.add(operationProductInComponent); } } operationComponent.setField(TechnologyOperationComponentFields.OPERATION_PRODUCT_IN_COMPONENTS, operationProductInComponentsNew); } private List<Entity> operationProductInComponents(Entity operationComponent) { return operationComponent.getHasManyField(TechnologyOperationComponentFields.OPERATION_PRODUCT_IN_COMPONENTS); } private void adjustOperationProductOutComponentsDueMerge(Entity operationComponent) { Entity merge = findMergedByOperationComponent(operationComponent); List<Entity> operationProductOutComponents = operationProductOutComponents(operationComponent); List<Entity> operationProductOutComponentsNew = Lists.newArrayList(); BigDecimal quantity = merge.getDecimalField(TechnologyOperationComponentMergeProductFields.QUANTITY_CHANGE); if (quantity.compareTo(BigDecimal.ZERO) > 0) { boolean modifiedExisting = false; for (Entity operationProductOutComponent : operationProductOutComponents) { if (operationProductOutComponent.getId().equals(mergedOperationProductComponent(merge).getId())) { operationProductOutComponent.setField(OperationProductInComponentFields.QUANTITY, quantity); operationProductOutComponentsNew.add(operationProductOutComponent); modifiedExisting = true; } } if (!modifiedExisting) { Entity mergedOperationComponent = mergedOperationProductComponent(merge); operationProductOutComponentsNew.add(mergedOperationComponent); } } operationComponent.setField(TechnologyOperationComponentFields.OPERATION_PRODUCT_OUT_COMPONENTS, operationProductOutComponentsNew); } private Entity mergedOperationProductComponent(Entity merge) { return merge.getBelongsToField(TechnologyOperationComponentMergeProductFields.MERGED_OPERATION_PRODUCT_COMPONENT); } private List<Entity> operationProductOutComponents(Entity operationComponent) { return operationComponent.getHasManyField(TechnologyOperationComponentFields.OPERATION_PRODUCT_OUT_COMPONENTS); } private void mergeProduct(DataDefinition dataDefinition, Entity order, Entity existingOperationComponent, Entity operationProduct, BigDecimal quantity) { Entity alreadyMergedProductComponentForOperation = findAlreadyMergedProductComponentForOperation(dataDefinition, existingOperationComponent, operationProduct); if (alreadyMergedProductComponentForOperation != null) { alreadyMergedProductComponentForOperation.setField(TechnologyOperationComponentMergeProductFields.QUANTITY_CHANGE, quantity); dataDefinition.save(alreadyMergedProductComponentForOperation); } else { persistMerge(dataDefinition, order, existingOperationComponent, existingOperationComponent, operationProduct, quantity); } } private void persistMerge(DataDefinition dataDefinition, Entity order, Entity operationComponent, Entity mergeOperationComponent, Entity operationProduct, BigDecimal quantity) { Entity merge = dataDefinition.create(); merge.setField("order", order); merge.setField(TechnologyOperationComponentMergeProductFields.OPERATION_COMPONENT, operationComponent); merge.setField(TechnologyOperationComponentMergeProductFields.MERGED_OPERATION_COMPONENT, mergeOperationComponent); merge.setField(TechnologyOperationComponentMergeProductFields.MERGED_OPERATION_PRODUCT_COMPONENT, operationProduct); merge.setField(TechnologyOperationComponentMergeProductFields.QUANTITY_CHANGE, quantity); dataDefinition.save(merge); } private Entity findAlreadyMergedProductComponentForOperation(DataDefinition dataDefinition, Entity existingOperationComponent, Entity operationProductIn) { Entity product = operationProductIn.getBelongsToField(OperationProductInComponentFields.PRODUCT); return dataDefinition.find().createAlias(TechnologyOperationComponentMergeProductFields.MERGED_OPERATION_PRODUCT_COMPONENT, "mopc", JoinType.FULL) .add(SearchRestrictions.eq(TechnologyOperationComponentMergeProductFields.OPERATION_COMPONENT + ".id", existingOperationComponent.getId())) .add(SearchRestrictions.eq(TechnologyOperationComponentMergeProductFields.MERGED_OPERATION_COMPONENT + ".id", existingOperationComponent.getId())) .add(SearchRestrictions.eq("mopc.product.id", product.getId())).setMaxResults(1).uniqueResult(); } private DataDefinition mergesProductInDD() { return dataDefinitionService.get(TechnologiesConstants.PLUGIN_IDENTIFIER, TechnologiesConstants.MODEL_TECHNOLOGY_OPERATION_COMPONENT_MERGE_PRODUCT_IN); } private DataDefinition mergesProductOutDD() { return dataDefinitionService.get(TechnologiesConstants.PLUGIN_IDENTIFIER, TechnologiesConstants.MODEL_TECHNOLOGY_OPERATION_COMPONENT_MERGE_PRODUCT_OUT); } }