public static Map changeProductionRunTaskStatus()

in applications/manufacturing/src/main/java/org/apache/ofbiz/manufacturing/jobshopmgt/ProductionRunServices.java [820:1094]


    public static Map<String, Object> changeProductionRunTaskStatus(DispatchContext ctx, Map<String, ? extends Object> context) {
        Map<String, Object> result = new HashMap<>();
        Delegator delegator = ctx.getDelegator();
        LocalDispatcher dispatcher = ctx.getDispatcher();
        Locale locale = (Locale) context.get("locale");
        GenericValue userLogin = (GenericValue) context.get("userLogin");
        String productionRunId = (String) context.get("productionRunId");
        String taskId = (String) context.get("workEffortId");
        String statusId = (String) context.get("statusId");
        Map<String, Object> serviceResult = new HashMap<>();
        Boolean issueAllComponents = (Boolean) context.get("issueAllComponents");
        if (issueAllComponents == null) {
            issueAllComponents = Boolean.FALSE;
        }

        ProductionRun productionRun = new ProductionRun(productionRunId, delegator, dispatcher);
        if (!productionRun.exist()) {
            return ServiceUtil.returnError(UtilProperties.getMessage(RESOURCE, "ManufacturingProductionRunNotExists", locale));
        }
        List<GenericValue> tasks = productionRun.getProductionRunRoutingTasks();
        GenericValue theTask = null;
        GenericValue oneTask = null;
        boolean allTaskCompleted = true;
        boolean allPrecTaskCompletedOrRunning = true;
        for (GenericValue task : tasks) {
            oneTask = task;
            if (oneTask.getString("workEffortId").equals(taskId)) {
                theTask = oneTask;
            } else {
                if (theTask == null && allPrecTaskCompletedOrRunning
                        && (!"PRUN_COMPLETED".equals(oneTask.getString("currentStatusId"))
                        && !"PRUN_RUNNING".equals(oneTask.getString("currentStatusId")))) {
                    allPrecTaskCompletedOrRunning = false;
                }
                if (allTaskCompleted && !"PRUN_COMPLETED".equals(oneTask.getString("currentStatusId"))) {
                    allTaskCompleted = false;
                }
            }
        }
        if (theTask == null) {
            return ServiceUtil.returnError(UtilProperties.getMessage(RESOURCE, "ManufacturingProductionRunTaskNotExists", locale));
        }

        String currentStatusId = theTask.getString("currentStatusId");
        String oldStatusId = theTask.getString("currentStatusId"); // pass back old status for secas to check

        if (statusId != null && currentStatusId.equals(statusId)) {
            result.put("oldStatusId", oldStatusId);
            result.put("newStatusId", currentStatusId);
            result.put(ModelService.SUCCESS_MESSAGE, UtilProperties.getMessage(RESOURCE, "ManufacturingProductionRunTaskStatusChanged",
                    UtilMisc.toMap("newStatusId", currentStatusId), locale));
            return result;
        }

        // PRUN_CREATED or PRUN_SCHEDULED or PRUN_DOC_PRINTED --> PRUN_RUNNING
        // this should be called only when the first task is started
        if (("PRUN_CREATED".equals(currentStatusId) || "PRUN_SCHEDULED".equals(currentStatusId) || "PRUN_DOC_PRINTED".equals(currentStatusId))
                && (statusId == null || "PRUN_RUNNING".equals(statusId))) {
            // change the production run task status to PRUN_RUNNING
            // if necessary change the production run (header) status to PRUN_RUNNING
            if (!allPrecTaskCompletedOrRunning) {
                return ServiceUtil.returnError(UtilProperties.getMessage(RESOURCE,
                        "ManufacturingProductionRunTaskCannotStartPrevTasksNotCompleted", locale));
            }
            if ("PRUN_CREATED".equals(productionRun.getGenericValue().getString("currentStatusId"))) {
                return ServiceUtil.returnError(UtilProperties.getMessage(RESOURCE, "ManufacturingProductionRunTaskCannotStartDocsNotPrinted",
                        locale));
            }
            Map<String, Object> serviceContext = new HashMap<>();
            serviceContext.clear();
            serviceContext.put("workEffortId", taskId);
            serviceContext.put("currentStatusId", "PRUN_RUNNING");
            serviceContext.put("actualStartDate", UtilDateTime.nowTimestamp());
            serviceContext.put("userLogin", userLogin);
            try {
                serviceResult = dispatcher.runSync("updateWorkEffort", serviceContext);
                if (ServiceUtil.isError(serviceResult)) {
                    return ServiceUtil.returnError(UtilProperties.getMessage(RESOURCE, "ManufacturingProductionRunStatusNotChanged", locale));
                }
            } catch (GenericServiceException e) {
                Debug.logError(e, "Problem calling the updateWorkEffort service", MODULE);
                return ServiceUtil.returnError(UtilProperties.getMessage(RESOURCE, "ManufacturingProductionRunStatusNotChanged", locale));
            }
            if (!"PRUN_RUNNING".equals(productionRun.getGenericValue().getString("currentStatusId"))) {
                serviceContext.clear();
                serviceContext.put("productionRunId", productionRunId);
                serviceContext.put("statusId", "PRUN_RUNNING");
                serviceContext.put("userLogin", userLogin);
                try {
                    serviceResult = dispatcher.runSync("changeProductionRunStatus", serviceContext);
                    if (ServiceUtil.isError(serviceResult)) {
                        return ServiceUtil.returnError(UtilProperties.getMessage(RESOURCE, "ManufacturingProductionRunStatusNotChanged", locale));
                    }
                } catch (GenericServiceException e) {
                    Debug.logError(e, "Problem calling the changeProductionRunStatus service", MODULE);
                    return ServiceUtil.returnError(UtilProperties.getMessage(RESOURCE, "ManufacturingProductionRunStatusNotChanged", locale));
                }
            }
            result.put("oldStatusId", oldStatusId);
            result.put("newStatusId", "PRUN_RUNNING");
            result.put(ModelService.SUCCESS_MESSAGE, UtilProperties.getMessage(RESOURCE, "ManufacturingProductionRunStatusChanged", UtilMisc.toMap(
                    "newStatusId", "PRUN_DOC_PRINTED"), locale));
            return result;
        }

        // PRUN_RUNNING --> PRUN_COMPLETED
        // this should be called only when the last task is completed
        if ("PRUN_RUNNING".equals(currentStatusId) && (statusId == null || "PRUN_COMPLETED".equals(statusId))) {
            Map<String, Object> serviceContext = new HashMap<>();
            if (issueAllComponents) {
                // Issue all the components, if this task needs components and they still need to be issued
                try {
                    List<GenericValue> inventoryAssigned = EntityQuery.use(delegator).from("WorkEffortInventoryAssign")
                            .where("workEffortId", taskId)
                            .queryList();
                    if (UtilValidate.isEmpty(inventoryAssigned)) {
                        serviceContext.clear();
                        serviceContext.put("workEffortId", taskId);
                        serviceContext.put("userLogin", userLogin);
                        serviceResult = dispatcher.runSync("issueProductionRunTask", serviceContext);
                        if (ServiceUtil.isError(serviceResult)) {
                            return ServiceUtil.returnError(UtilProperties.getMessage(RESOURCE, "ManufacturingProductionRunStatusNotChanged", locale));
                        }
                    }
                } catch (GenericEntityException | GenericServiceException e) {
                    return ServiceUtil.returnError(UtilProperties.getMessage(RESOURCE, "ManufacturingProductionRunStatusNotChanged", locale));
                }
            }
            // change only the production run task status to PRUN_COMPLETED
            serviceContext.clear();
            serviceContext.put("workEffortId", taskId);
            serviceContext.put("currentStatusId", "PRUN_COMPLETED");
            serviceContext.put("actualCompletionDate", UtilDateTime.nowTimestamp());
            BigDecimal quantityToProduce = theTask.getBigDecimal("quantityToProduce");
            if (quantityToProduce == null) {
                quantityToProduce = BigDecimal.ZERO;
            }
            BigDecimal quantityProduced = theTask.getBigDecimal("quantityProduced");
            if (quantityProduced == null) {
                quantityProduced = BigDecimal.ZERO;
            }
            BigDecimal quantityRejected = theTask.getBigDecimal("quantityRejected");
            if (quantityRejected == null) {
                quantityRejected = BigDecimal.ZERO;
            }
            BigDecimal totalQuantity = quantityProduced.add(quantityRejected);
            BigDecimal diffQuantity = quantityToProduce.subtract(totalQuantity);
            if (diffQuantity.compareTo(BigDecimal.ZERO) > 0) {
                quantityProduced = quantityProduced.add(diffQuantity);
            }
            serviceContext.put("quantityProduced", quantityProduced);
            if (theTask.get("actualSetupMillis") == null) {
                serviceContext.put("actualSetupMillis", theTask.get("estimatedSetupMillis"));
            }
            if (theTask.get("actualMilliSeconds") == null) {
                Double autoMillis = null;
                if (theTask.get("estimatedMilliSeconds") != null) {
                    autoMillis = quantityProduced.doubleValue() * theTask.getDouble("estimatedMilliSeconds");
                }
                serviceContext.put("actualMilliSeconds", autoMillis);
            }
            serviceContext.put("userLogin", userLogin);
            try {
                serviceResult = dispatcher.runSync("updateWorkEffort", serviceContext);
                if (ServiceUtil.isError(serviceResult)) {
                    return ServiceUtil.returnError(UtilProperties.getMessage(RESOURCE, "ManufacturingProductionRunStatusNotChanged", locale));
                }
            } catch (GenericServiceException e) {
                Debug.logError(e, "Problem calling the updateWorkEffort service", MODULE);
                return ServiceUtil.returnError(UtilProperties.getMessage(RESOURCE, "ManufacturingProductionRunStatusNotChanged", locale));
            }
            // Calculate and store the production run task actual costs
            serviceContext.clear();
            serviceContext.put("productionRunTaskId", taskId);
            serviceContext.put("userLogin", userLogin);
            try {
                serviceResult = dispatcher.runSync("createProductionRunTaskCosts", serviceContext);
                if (ServiceUtil.isError(serviceResult)) {
                    return ServiceUtil.returnError(UtilProperties.getMessage(RESOURCE, "ManufacturingProductionRunStatusNotChanged", locale));
                }
            } catch (GenericServiceException e) {
                Debug.logError(e, "Problem calling the createProductionRunTaskCosts service", MODULE);
                return ServiceUtil.returnError(UtilProperties.getMessage(RESOURCE, "ManufacturingProductionRunStatusNotChanged", locale));
            }
            // If this is the last task, then the production run is marked as 'completed'
            if (allTaskCompleted) {
                serviceContext.clear();
                serviceContext.put("productionRunId", productionRunId);
                serviceContext.put("statusId", "PRUN_COMPLETED");
                serviceContext.put("userLogin", userLogin);
                try {
                    serviceResult = dispatcher.runSync("changeProductionRunStatus", serviceContext);
                    if (ServiceUtil.isError(result)) {
                        return ServiceUtil.returnError(ServiceUtil.getErrorMessage(result));
                    }
                } catch (GenericServiceException e) {
                    Debug.logError(e, "Problem calling the updateWorkEffort service", MODULE);
                    return ServiceUtil.returnError(UtilProperties.getMessage(RESOURCE, "ManufacturingProductionRunStatusNotChanged", locale));
                }
                // and compute the overhead costs associated to the finished product
                try {
                    // get the currency
                    GenericValue facility = productionRun.getGenericValue().getRelatedOne("Facility", false);
                    Map<String, Object> outputMap = dispatcher.runSync("getPartyAccountingPreferences",
                            UtilMisc.<String, Object>toMap("userLogin", userLogin,
                                    "organizationPartyId", facility.getString("ownerPartyId")));
                    if (ServiceUtil.isError(outputMap)) {
                        return ServiceUtil.returnError(ServiceUtil.getErrorMessage(outputMap));
                    }
                    GenericValue partyAccountingPreference = (GenericValue) outputMap.get("partyAccountingPreference");
                    if (partyAccountingPreference == null) {
                        return ServiceUtil.returnError(UtilProperties.getMessage(RESOURCE, "ManufacturingProductionRunUnableToFindCosts", locale));
                    }
                    outputMap = dispatcher.runSync("getProductionRunCost", UtilMisc.<String, Object>toMap("userLogin", userLogin, "workEffortId",
                            productionRunId));
                    if (ServiceUtil.isError(outputMap)) {
                        return ServiceUtil.returnError(ServiceUtil.getErrorMessage(outputMap));
                    }
                    BigDecimal totalCost = (BigDecimal) outputMap.get("totalCost");
                    if (totalCost == null) {
                        totalCost = ZERO;
                    }

                    List<GenericValue> productCostComponentCalcs = EntityQuery.use(delegator).from("ProductCostComponentCalc")
                            .where("productId", productionRun.getProductProduced().get("productId"))
                            .orderBy("sequenceNum").queryList();
                    for (GenericValue productCostComponentCalc : productCostComponentCalcs) {
                        GenericValue costComponentCalc = productCostComponentCalc.getRelatedOne("CostComponentCalc", false);
                        GenericValue customMethod = costComponentCalc.getRelatedOne("CustomMethod", false);
                        if (customMethod == null) {
                            // TODO: not supported for CostComponentCalc entries directly associated to a product
                            Debug.logWarning("Unable to create cost component for cost component calc with id [" + costComponentCalc.getString(
                                    "costComponentCalcId") + "] because customMethod is not set", MODULE);
                        } else {
                            Map<String, Object> costMethodResult = dispatcher.runSync(customMethod.getString("customMethodName"),
                                    UtilMisc.toMap("productCostComponentCalc", productCostComponentCalc,
                                            "costComponentCalc", costComponentCalc,
                                            "costComponentTypePrefix", "ACTUAL",
                                            "baseCost", totalCost,
                                            "currencyUomId", (String) partyAccountingPreference.get("baseCurrencyUomId"),
                                            "userLogin", userLogin));
                            if (ServiceUtil.isError(costMethodResult)) {
                                return ServiceUtil.returnError(ServiceUtil.getErrorMessage(costMethodResult));
                            }
                            BigDecimal productCostAdjustment = (BigDecimal) costMethodResult.get("productCostAdjustment");
                            totalCost = totalCost.add(productCostAdjustment);
                            Map<String, Object> inMap = UtilMisc.<String, Object>toMap("userLogin", userLogin, "workEffortId", productionRunId);
                            inMap.put("costComponentCalcId", costComponentCalc.getString("costComponentCalcId"));
                            inMap.put("costComponentTypeId", "ACTUAL_" + productCostComponentCalc.getString("costComponentTypeId"));
                            inMap.put("costUomId", partyAccountingPreference.get("baseCurrencyUomId"));
                            inMap.put("cost", productCostAdjustment);
                            serviceResult = dispatcher.runSync("createCostComponent", inMap);
                            if (ServiceUtil.isError(serviceResult)) {
                                return ServiceUtil.returnError(ServiceUtil.getErrorMessage(serviceResult));
                            }
                        }
                    }
                } catch (GenericEntityException | GenericServiceException gse) {
                    return ServiceUtil.returnError(UtilProperties.getMessage(RESOURCE, "ManufacturingProductionRunUnableToFindOverheadCosts",
                            UtilMisc.toMap("errorString", gse.getMessage()), locale));
                }
            }

            result.put("oldStatusId", oldStatusId);
            result.put("newStatusId", "PRUN_COMPLETED");
            result.put(ModelService.SUCCESS_MESSAGE, UtilProperties.getMessage(RESOURCE, "ManufacturingProductionRunStatusChanged", UtilMisc.toMap(
                    "newStatusId", "PRUN_DOC_PRINTED"), locale));
            return result;
        }
        result.put("oldStatusId", oldStatusId);
        result.put("newStatusId", currentStatusId);
        result.put(ModelService.SUCCESS_MESSAGE, UtilProperties.getMessage(RESOURCE, "ManufacturingProductionRunTaskStatusChanged", UtilMisc.toMap(
                "newStatusId", currentStatusId), locale));
        return result;
    }