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;
}