com.qcadoo.mes.productionCounting.ProductionCountingServiceImpl.java Source code

Java tutorial

Introduction

Here is the source code for com.qcadoo.mes.productionCounting.ProductionCountingServiceImpl.java

Source

/**
 * ***************************************************************************
 * Copyright (c) 2010 Qcadoo Limited
 * Project: Qcadoo MES
 * Version: 1.3
 *
 * 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.productionCounting;

import static com.qcadoo.model.api.search.SearchRestrictions.and;
import static com.qcadoo.model.api.search.SearchRestrictions.eq;
import static com.qcadoo.model.api.search.SearchRestrictions.idEq;
import static com.qcadoo.model.api.search.SearchRestrictions.or;

import java.math.BigDecimal;
import java.util.Collections;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.google.common.collect.Lists;
import com.qcadoo.mes.basic.constants.ProductFields;
import com.qcadoo.mes.orders.constants.OrderFields;
import com.qcadoo.mes.orders.states.constants.OrderStateStringValues;
import com.qcadoo.mes.productionCounting.constants.CalculateOperationCostsMode;
import com.qcadoo.mes.productionCounting.constants.OrderFieldsPC;
import com.qcadoo.mes.productionCounting.constants.ProductionBalanceFields;
import com.qcadoo.mes.productionCounting.constants.ProductionCountingConstants;
import com.qcadoo.mes.productionCounting.constants.ProductionTrackingFields;
import com.qcadoo.mes.productionCounting.constants.ProductionTrackingReportFields;
import com.qcadoo.mes.productionCounting.constants.TrackingOperationProductInComponentFields;
import com.qcadoo.mes.productionCounting.constants.TrackingOperationProductOutComponentFields;
import com.qcadoo.mes.productionCounting.constants.TypeOfProductionRecording;
import com.qcadoo.mes.productionCounting.print.utils.EntityProductionTrackingComparator;
import com.qcadoo.mes.productionCounting.states.constants.ProductionTrackingStateChangeFields;
import com.qcadoo.mes.productionCounting.states.constants.ProductionTrackingStateStringValues;
import com.qcadoo.mes.states.constants.StateChangeStatus;
import com.qcadoo.mes.technologies.constants.OperationProductInComponentFields;
import com.qcadoo.mes.technologies.constants.OperationProductOutComponentFields;
import com.qcadoo.model.api.DataDefinition;
import com.qcadoo.model.api.DataDefinitionService;
import com.qcadoo.model.api.Entity;
import com.qcadoo.model.api.NumberService;
import com.qcadoo.model.api.search.JoinType;
import com.qcadoo.model.api.search.SearchCriteriaBuilder;
import com.qcadoo.model.api.search.SearchCriterion;
import com.qcadoo.model.api.search.SearchRestrictions;
import com.qcadoo.view.api.ComponentState;
import com.qcadoo.view.api.ViewDefinitionState;
import com.qcadoo.view.api.components.FieldComponent;
import com.qcadoo.view.api.components.FormComponent;
import com.qcadoo.view.api.components.GridComponent;
import com.qcadoo.view.api.components.LookupComponent;

@Service
public class ProductionCountingServiceImpl implements ProductionCountingService {

    private static final Logger LOGGER = LoggerFactory.getLogger(ProductionCountingServiceImpl.class);

    private static final String L_FORM = "form";

    private static final String L_ORDER = "order";

    private static final String L_PRODUCT = "product";

    private static final String L_NUMBER = "number";

    private static final String L_NAME = "name";

    private static final String L_PLANNED_QUANTITY_UNIT = "plannedQuantityUNIT";

    private static final String L_USED_QUANTITY_UNIT = "usedQuantityUNIT";

    private static final String L_PRODUCTION_TRACKINGS = "productionTrackings";

    private static final List<String> L_TRACKING_OPERATION_PRODUCT_FIELD_NAMES = Lists.newArrayList(L_NUMBER,
            L_NAME, L_PLANNED_QUANTITY_UNIT, L_USED_QUANTITY_UNIT);

    @Autowired
    private DataDefinitionService dataDefinitionService;

    @Autowired
    private NumberService numberService;

    @Override
    public Entity getProductionTrackingReport(final Long productionTrackingReportId) {
        return getProductionTrackingReportDD().get(productionTrackingReportId);
    }

    @Override
    public Entity getProductionTracking(final Long productionTrackingId) {
        return getProductionTrackingDD().get(productionTrackingId);
    }

    @Override
    public Entity getProductionBalance(final Long productionBalanceId) {
        return getProductionBalanceDD().get(productionBalanceId);
    }

    @Override
    public Entity getTrackingOperationProductInComponent(final Long trackingOperationProductInComponentId) {
        return getTrackingOperationProductInComponentDD().get(trackingOperationProductInComponentId);
    }

    @Override
    public Entity getTrackingOperationProductOutComponent(final Long trackingOperationProductOutComponentId) {
        return getTrackingOperationProductOutComponentDD().get(trackingOperationProductOutComponentId);
    }

    @Override
    public DataDefinition getProductionTrackingReportDD() {
        return dataDefinitionService.get(ProductionCountingConstants.PLUGIN_IDENTIFIER,
                ProductionCountingConstants.MODEL_PRODUCTION_TRACKING_REPORT);
    }

    @Override
    public DataDefinition getProductionTrackingDD() {
        return dataDefinitionService.get(ProductionCountingConstants.PLUGIN_IDENTIFIER,
                ProductionCountingConstants.MODEL_PRODUCTION_TRACKING);
    }

    @Override
    public DataDefinition getProductionBalanceDD() {
        return dataDefinitionService.get(ProductionCountingConstants.PLUGIN_IDENTIFIER,
                ProductionCountingConstants.MODEL_PRODUCTION_BALANCE);
    }

    @Override
    public DataDefinition getTrackingOperationProductInComponentDD() {
        return dataDefinitionService.get(ProductionCountingConstants.PLUGIN_IDENTIFIER,
                ProductionCountingConstants.MODEL_TRACKING_OPERATION_PRODUCT_IN_COMPONENT);
    }

    @Override
    public DataDefinition getTrackingOperationProductOutComponentDD() {
        return dataDefinitionService.get(ProductionCountingConstants.PLUGIN_IDENTIFIER,
                ProductionCountingConstants.MODEL_TRACKING_OPERATION_PRODUCT_OUT_COMPONENT);
    }

    @Override
    public List<Entity> getProductionTrackingsForOrder(final Entity order) {
        SearchCriteriaBuilder scb = getProductionTrackingDD().find();
        final String scAlias = "sc_alias";
        scb.createAlias(ProductionTrackingFields.STATE_CHANGES, scAlias, JoinType.INNER);
        scb.createCriteria(ProductionTrackingFields.ORDER, "ord_alias", JoinType.INNER).add(idEq(order.getId()));

        SearchCriterion hasStateChangeFromDraftToAccepted = and(
                eq(scAlias + "." + ProductionTrackingStateChangeFields.SOURCE_STATE,
                        ProductionTrackingStateStringValues.DRAFT),
                eq(scAlias + "." + ProductionTrackingStateChangeFields.TARGET_STATE,
                        ProductionTrackingStateStringValues.ACCEPTED));

        SearchCriterion isAlreadyAccepted = and(
                eq(ProductionTrackingFields.STATE, ProductionTrackingStateStringValues.ACCEPTED),
                eq(scAlias + "." + ProductionTrackingStateChangeFields.STATUS,
                        StateChangeStatus.SUCCESSFUL.getStringValue()),
                hasStateChangeFromDraftToAccepted);

        SearchCriterion isFinalRecordDuringAcceptation = and(eq(ProductionTrackingFields.LAST_TRACKING, true),
                eq(scAlias + "." + ProductionTrackingStateChangeFields.STATUS,
                        StateChangeStatus.IN_PROGRESS.getStringValue()),
                hasStateChangeFromDraftToAccepted);

        /* This is a workaround for missing production tracking entity during its acceptance. */
        scb.add(or(isAlreadyAccepted, isFinalRecordDuringAcceptation));

        return scb.list().getEntities();
    }

    @Override
    public boolean isTypeOfProductionRecordingBasic(final String typeOfProductionRecording) {
        return TypeOfProductionRecording.BASIC.getStringValue().equals(typeOfProductionRecording);
    }

    @Override
    public boolean isTypeOfProductionRecordingForEach(final String typeOfProductionRecording) {
        return TypeOfProductionRecording.FOR_EACH.getStringValue().equals(typeOfProductionRecording);
    }

    @Override
    public boolean isTypeOfProductionRecordingCumulated(final String typeOfProductionRecording) {
        return TypeOfProductionRecording.CUMULATED.getStringValue().equals(typeOfProductionRecording);
    }

    @Override
    public boolean checkIfTypeOfProductionRecordingIsEmptyOrBasic(final String typeOfProductionRecording) {
        return StringUtils.isEmpty(typeOfProductionRecording)
                || isTypeOfProductionRecordingBasic(typeOfProductionRecording);
    }

    @Override
    public boolean isCalculateOperationCostModeHourly(final String calculateOperationCostMode) {
        return CalculateOperationCostsMode.HOURLY.getStringValue().equals(calculateOperationCostMode);
    }

    @Override
    public boolean isCalculateOperationCostModePiecework(final String calculateOperationCostMode) {
        return CalculateOperationCostsMode.PIECEWORK.getStringValue().equals(calculateOperationCostMode);
    }

    @Override
    public boolean validateOrder(final DataDefinition productionTrackingReportOrBalanceDD,
            final Entity productionTrackingReportOrBalance) {
        Entity order = productionTrackingReportOrBalance.getBelongsToField(L_ORDER);

        if ((order == null) || isTypeOfProductionRecordingBasic(
                order.getStringField(OrderFieldsPC.TYPE_OF_PRODUCTION_RECORDING))) {
            productionTrackingReportOrBalance.addError(productionTrackingReportOrBalanceDD.getField(L_ORDER),
                    "productionCounting.productionBalance.report.error.orderWithoutRecordingType");

            return false;
        }

        String calculateOperationCostMode = productionTrackingReportOrBalance
                .getStringField(ProductionBalanceFields.CALCULATE_OPERATION_COST_MODE);

        if (!order.getBooleanField(OrderFieldsPC.REGISTER_PRODUCTION_TIME)
                && isCalculateOperationCostModeHourly(calculateOperationCostMode)) {
            productionTrackingReportOrBalance.addError(productionTrackingReportOrBalanceDD.getField(L_ORDER),
                    "productionCounting.productionBalance.report.error.orderWithoutRegisterProductionTime");

            return false;
        } else if (!order.getBooleanField(OrderFieldsPC.REGISTER_PIECEWORK)
                && isCalculateOperationCostModePiecework(calculateOperationCostMode)) {
            productionTrackingReportOrBalance.addError(productionTrackingReportOrBalanceDD.getField(L_ORDER),
                    "productionCounting.productionBalance.report.error.orderWithoutRegisterPiecework");

            return false;
        }

        List<Entity> productionTrackings = getProductionTrackingsForOrder(order);

        if (productionTrackings.isEmpty()) {
            productionTrackingReportOrBalance.addError(productionTrackingReportOrBalanceDD.getField(L_ORDER),
                    "productionCounting.productionBalance.report.error.orderWithoutProductionTrackings");

            return false;
        }

        return true;
    }

    @Override
    public void setComponentsState(final ViewDefinitionState view, final List<String> componentReferenceNames,
            final boolean isEnabled, final boolean requestComponentUpdateState) {
        for (String componentReferenceName : componentReferenceNames) {
            ComponentState componentState = view.getComponentByReference(componentReferenceName);

            if (componentState == null) {
                if (LOGGER.isWarnEnabled()) {
                    LOGGER.warn(String.format("Cannot find component with reference='%s'", componentReferenceName));
                }
            } else {
                componentState.setEnabled(isEnabled);
            }
        }
    }

    @Override
    public void setComponentsVisibility(final ViewDefinitionState view, final List<String> componentReferenceNames,
            final boolean isVisible, final boolean requestComponentUpdateState) {
        for (String componentReferenceName : componentReferenceNames) {
            ComponentState componnetState = view.getComponentByReference(componentReferenceName);

            if (componnetState == null) {
                if (LOGGER.isWarnEnabled()) {
                    LOGGER.warn(String.format("Cannot find component with reference='%s'", componentReferenceName));
                }
            } else {
                componnetState.setVisible(isVisible);
            }
        }
    }

    @Override
    public void changeDoneQuantityAndAmountOfProducedQuantityFieldState(final ViewDefinitionState view) {
        FormComponent orderForm = (FormComponent) view.getComponentByReference(L_FORM);
        FieldComponent typeOfProductionRecordingField = (FieldComponent) view
                .getComponentByReference(OrderFieldsPC.TYPE_OF_PRODUCTION_RECORDING);

        FieldComponent doneQuantityField = (FieldComponent) view.getComponentByReference(OrderFields.DONE_QUANTITY);
        FieldComponent amountOfProductProducedField = (FieldComponent) view
                .getComponentByReference(OrderFields.AMOUNT_OF_PRODUCT_PRODUCED);

        Long orderId = orderForm.getEntityId();

        if (orderId == null) {
            doneQuantityField.setEnabled(false);
            amountOfProductProducedField.setEnabled(false);

            return;
        }

        Entity order = orderForm.getEntity();

        String state = order.getStringField(OrderFields.STATE);

        if (OrderStateStringValues.PENDING.equals(state) || OrderStateStringValues.ACCEPTED.equals(state)) {
            doneQuantityField.setEnabled(false);
            amountOfProductProducedField.setEnabled(false);
        } else {
            String typeOfProductionRecording = (String) typeOfProductionRecordingField.getFieldValue();

            if (checkIfTypeOfProductionRecordingIsEmptyOrBasic(typeOfProductionRecording)) {
                doneQuantityField.setEnabled(true);
                amountOfProductProducedField.setEnabled(true);
            } else {
                doneQuantityField.setEnabled(false);
                amountOfProductProducedField.setEnabled(false);
            }
        }
    }

    @Override
    public void fillFieldsFromProduct(final ViewDefinitionState view,
            final DataDefinition trackingOperationProductComponentDD) {
        FormComponent trackingOperationProductComponentForm = (FormComponent) view.getComponentByReference(L_FORM);

        Long trackingOperationProductComponentId = trackingOperationProductComponentForm.getEntityId();

        if (trackingOperationProductComponentId == null) {
            return;
        }

        Entity trackingOperationProductComponent = trackingOperationProductComponentDD
                .get(trackingOperationProductComponentId);

        if (trackingOperationProductComponent == null) {
            return;
        }

        Entity product = trackingOperationProductComponent.getBelongsToField(L_PRODUCT);

        if (product == null) {
            return;
        }

        view.getComponentByReference(L_NUMBER).setFieldValue(product.getField(ProductFields.NUMBER));
        view.getComponentByReference(L_NAME).setFieldValue(product.getField(ProductFields.NAME));

        view.getComponentByReference(L_USED_QUANTITY_UNIT)
                .setFieldValue(product.getStringField(ProductFields.UNIT));
        view.getComponentByReference(L_PLANNED_QUANTITY_UNIT)
                .setFieldValue(product.getStringField(ProductFields.UNIT));

        for (String fieldComponentNames : L_TRACKING_OPERATION_PRODUCT_FIELD_NAMES) {
            ((FieldComponent) view.getComponentByReference(fieldComponentNames)).requestComponentUpdateState();
        }
    }

    @Override
    public void fillProductField(final ViewDefinitionState view) {
        LookupComponent orderLookup = (LookupComponent) view
                .getComponentByReference(ProductionTrackingReportFields.ORDER);
        LookupComponent productLookup = (LookupComponent) view
                .getComponentByReference(ProductionTrackingReportFields.PRODUCT);

        Entity order = orderLookup.getEntity();

        if (order == null) {
            productLookup.setFieldValue(null);

            return;
        }

        String typeOfProductionRecording = order.getStringField(OrderFieldsPC.TYPE_OF_PRODUCTION_RECORDING);

        if (checkIfTypeOfProductionRecordingIsEmptyOrBasic(typeOfProductionRecording)) {
            productLookup.setFieldValue(null);

            return;
        }

        setProductFieldValue(view, order);
    }

    private void setProductFieldValue(final ViewDefinitionState view, final Entity order) {
        LookupComponent productLookup = (LookupComponent) view
                .getComponentByReference(ProductionTrackingReportFields.PRODUCT);

        Entity product = order.getBelongsToField(OrderFields.PRODUCT);

        if (product != null) {
            productLookup.setFieldValue(product.getId());
            productLookup.requestComponentUpdateState();
        }
    }

    @Override
    public void fillProductionTrackingsGrid(final ViewDefinitionState view) {
        LookupComponent orderLookup = (LookupComponent) view
                .getComponentByReference(ProductionTrackingReportFields.ORDER);
        GridComponent productionTrackingsGrid = (GridComponent) view
                .getComponentByReference(L_PRODUCTION_TRACKINGS);

        Entity order = orderLookup.getEntity();

        if (order == null) {
            productionTrackingsGrid.setVisible(false);

            return;
        }

        String typeOfProductionRecording = order.getStringField(OrderFieldsPC.TYPE_OF_PRODUCTION_RECORDING);

        if (checkIfTypeOfProductionRecordingIsEmptyOrBasic(typeOfProductionRecording)) {
            productionTrackingsGrid.setVisible(false);

            return;
        }

        productionTrackingsGrid.setVisible(true);

        setProductionTrackingsGridContent(view, order);
    }

    private void setProductionTrackingsGridContent(final ViewDefinitionState view, final Entity order) {
        GridComponent productionTrackingsGrid = (GridComponent) view
                .getComponentByReference(L_PRODUCTION_TRACKINGS);

        List<Entity> productionTrackings = getProductionTrackingsForOrder(order);

        Collections.sort(productionTrackings, new EntityProductionTrackingComparator());

        productionTrackingsGrid.setEntities(productionTrackings);
    }

    @Override
    public BigDecimal getRegisteredProductValueForOperationProductIn(final Entity operationProduct,
            final BigDecimal planed) {
        BigDecimal value = null;
        Entity toc = operationProduct.getBelongsToField(OperationProductInComponentFields.OPERATION_COMPONENT);
        Entity product = operationProduct.getBelongsToField(OperationProductInComponentFields.PRODUCT);

        List<Entity> tracings = getProductionTrackingDD().find()
                .add(SearchRestrictions.belongsTo(ProductionTrackingFields.TECHNOLOGY_OPERATION_COMPONENT, toc))
                .add(SearchRestrictions.eq(ProductionTrackingFields.STATE,
                        ProductionTrackingStateStringValues.ACCEPTED))
                .list().getEntities();
        for (Entity tracking : tracings) {
            Entity topIN = getTrackingOperationProductInComponentDD().find()
                    .add(SearchRestrictions.belongsTo(TrackingOperationProductInComponentFields.PRODUCTION_TRACKING,
                            tracking))
                    .add(SearchRestrictions.belongsTo(TrackingOperationProductInComponentFields.PRODUCT, product))
                    .setMaxResults(1).uniqueResult();
            if (topIN != null) {
                if (value == null) {
                    value = new BigDecimal(0l);
                }
                value = value.add(topIN.getDecimalField(TrackingOperationProductInComponentFields.USED_QUANTITY),
                        numberService.getMathContext());
            }
        }
        if (value != null) {
            value = planed.subtract(value, numberService.getMathContext());
        } else {
            return value;
        }

        if (value.compareTo(new BigDecimal(0l)) == -1) {
            value = new BigDecimal(0l);
        }

        return value;
    }

    @Override
    public BigDecimal getRegisteredProductValueForOperationProductOut(final Entity operationProduct,
            final BigDecimal planed) {
        BigDecimal value = null;
        Entity toc = operationProduct.getBelongsToField(OperationProductOutComponentFields.OPERATION_COMPONENT);
        Entity product = operationProduct.getBelongsToField(OperationProductOutComponentFields.PRODUCT);

        List<Entity> tracings = getProductionTrackingDD().find()
                .add(SearchRestrictions.belongsTo(ProductionTrackingFields.TECHNOLOGY_OPERATION_COMPONENT, toc))
                .add(SearchRestrictions.eq(ProductionTrackingFields.STATE,
                        ProductionTrackingStateStringValues.ACCEPTED))
                .list().getEntities();
        for (Entity tracking : tracings) {
            Entity topIN = getTrackingOperationProductOutComponentDD().find()
                    .add(SearchRestrictions
                            .belongsTo(TrackingOperationProductOutComponentFields.PRODUCTION_TRACKING, tracking))
                    .add(SearchRestrictions.belongsTo(TrackingOperationProductOutComponentFields.PRODUCT, product))
                    .setMaxResults(1).uniqueResult();
            if (topIN != null) {
                if (value == null) {
                    value = new BigDecimal(0l);
                }
                value = value.add(topIN.getDecimalField(TrackingOperationProductOutComponentFields.USED_QUANTITY),
                        numberService.getMathContext());
            }
        }
        if (value != null) {
            value = planed.subtract(value, numberService.getMathContext());
        } else {
            return value;
        }

        if (value.compareTo(new BigDecimal(0l)) == -1) {
            value = new BigDecimal(0l);
        }

        return value;
    }
}