public static Map<String, Object> createProductionRun(DispatchContext ctx, Map<String, ? extends Object> context) {
Map<String, Object> result = FastMap.newInstance();
Delegator delegator = ctx.getDelegator();
LocalDispatcher dispatcher = ctx.getDispatcher();
Locale locale = (Locale) context.get("locale");
GenericValue userLogin = (GenericValue) context.get("userLogin");
/* TODO: security management and finishing cleaning (ex copy from PartyServices.java)
if (!security.hasEntityPermission(secEntity, secOperation, userLogin)) {
result.put(ModelService.RESPONSE_MESSAGE, ModelService.RESPOND_ERROR);
result.put(ModelService.ERROR_MESSAGE, "You do not have permission to perform this operation for this party");
return partyId;
}
*/
// Mandatory input fields
String productId = (String) context.get("productId");
Timestamp startDate = (Timestamp) context.get("startDate");
BigDecimal pRQuantity = (BigDecimal) context.get("pRQuantity");
String facilityId = (String) context.get("facilityId");
// Optional input fields
String workEffortId = (String) context.get("routingId");
String workEffortName = (String) context.get("workEffortName");
String description = (String) context.get("description");
GenericValue routing = null;
GenericValue product = null;
List<GenericValue> routingTaskAssocs = null;
try {
// Find the product
product = delegator.findByPrimaryKey("Product", UtilMisc.toMap("productId", productId));
if (product == null) {
return ServiceUtil.returnError(UtilProperties.getMessage(resource, "ManufacturingProductNotExist", locale));
}
} catch (GenericEntityException e) {
Debug.logWarning(e.getMessage(), module);
return ServiceUtil.returnError(e.getMessage());
}
// -------------------
// Routing and routing tasks
// -------------------
// Select the product's routing
try {
Map<String, Object> routingInMap = UtilMisc.toMap("productId", productId, "applicableDate", startDate, "userLogin", userLogin);
if (workEffortId != null) {
routingInMap.put("workEffortId", workEffortId);
}
Map<String, Object> routingOutMap = dispatcher.runSync("getProductRouting", routingInMap);
routing = (GenericValue)routingOutMap.get("routing");
routingTaskAssocs = UtilGenerics.checkList(routingOutMap.get("tasks"));
} catch (GenericServiceException gse) {
Debug.logWarning(gse.getMessage(), module);
}
if (routing == null) {
return ServiceUtil.returnError(UtilProperties.getMessage(resource, "ManufacturingProductRoutingNotExist", locale));
}
if (UtilValidate.isEmpty(routingTaskAssocs)) {
return ServiceUtil.returnError(UtilProperties.getMessage(resource, "ManufacturingRoutingHasNoRoutingTask", locale));
}
// -------------------
// Components
// -------------------
// The components are retrieved using the getManufacturingComponents service
// (that performs a bom breakdown and if needed runs the configurator).
List<BOMNode> components = null;
Map<String, Object> serviceContext = FastMap.newInstance();
serviceContext.put("productId", productId); // the product that we want to manufacture
serviceContext.put("quantity", pRQuantity); // the quantity that we want to manufacture
serviceContext.put("userLogin", userLogin);
Map<String, Object> resultService = null;
try {
resultService = dispatcher.runSync("getManufacturingComponents", serviceContext);
components = UtilGenerics.checkList(resultService.get("components")); // a list of objects representing the product's components
} catch (GenericServiceException e) {
Debug.logError(e, "Problem calling the getManufacturingComponents service", module);
return ServiceUtil.returnError(e.getMessage());
}
// ProductionRun header creation,
if (workEffortName == null) {
String prdName = UtilValidate.isNotEmpty(product.getString("productName"))? product.getString("productName"): product.getString("productId");
String wefName = UtilValidate.isNotEmpty(routing.getString("workEffortName"))? routing.getString("workEffortName"): routing.getString("workEffortId");
workEffortName = prdName + "-" + wefName;
}
serviceContext.clear();
serviceContext.put("workEffortTypeId", "PROD_ORDER_HEADER");
serviceContext.put("workEffortPurposeTypeId", "WEPT_PRODUCTION_RUN");
serviceContext.put("currentStatusId", "PRUN_CREATED");
serviceContext.put("workEffortName", workEffortName);
serviceContext.put("description",description);
serviceContext.put("facilityId", facilityId);
serviceContext.put("estimatedStartDate",startDate);
serviceContext.put("quantityToProduce", pRQuantity);
serviceContext.put("userLogin", userLogin);
try {
resultService = dispatcher.runSync("createWorkEffort", serviceContext);
} catch (GenericServiceException e) {
Debug.logError(e, "Problem calling the createWorkEffort service", module);
return ServiceUtil.returnError(e.getMessage());
}
String productionRunId = (String) resultService.get("workEffortId");
if (Debug.infoOn()) {
Debug.logInfo("ProductionRun created: " + productionRunId, module);
}
// ProductionRun, product will be produce creation = WorkEffortGoodStandard for the productId
serviceContext.clear();
serviceContext.put("workEffortId", productionRunId);
serviceContext.put("productId", productId);
serviceContext.put("workEffortGoodStdTypeId", "PRUN_PROD_DELIV");
serviceContext.put("statusId", "WEGS_CREATED");
serviceContext.put("estimatedQuantity", pRQuantity);
serviceContext.put("fromDate", startDate);
serviceContext.put("userLogin", userLogin);
try {
resultService = dispatcher.runSync("createWorkEffortGoodStandard", serviceContext);
} catch (GenericServiceException e) {
Debug.logError(e, "Problem calling the createWorkEffortGoodStandard service", module);
return ServiceUtil.returnError(e.getMessage());
}
// Multi creation (like clone) ProductionRunTask and GoodAssoc
boolean first = true;
for(GenericValue routingTaskAssoc : routingTaskAssocs) {
if (EntityUtil.isValueActive(routingTaskAssoc, startDate)) {
GenericValue routingTask = null;
try {
routingTask = routingTaskAssoc.getRelatedOne("ToWorkEffort");
} catch (GenericEntityException e) {
Debug.logError(e.getMessage(), module);
}
// Calculate the estimatedCompletionDate
long totalTime = ProductionRun.getEstimatedTaskTime(routingTask, pRQuantity, dispatcher);
Timestamp endDate = TechDataServices.addForward(TechDataServices.getTechDataCalendar(routingTask),startDate, totalTime);
serviceContext.clear();
serviceContext.put("priority", routingTaskAssoc.get("sequenceNum"));
serviceContext.put("workEffortPurposeTypeId", routingTask.get("workEffortPurposeTypeId"));
serviceContext.put("workEffortName",routingTask.get("workEffortName"));
serviceContext.put("description",routingTask.get("description"));
serviceContext.put("fixedAssetId",routingTask.get("fixedAssetId"));
serviceContext.put("workEffortTypeId", "PROD_ORDER_TASK");
serviceContext.put("currentStatusId","PRUN_CREATED");
serviceContext.put("workEffortParentId", productionRunId);
serviceContext.put("facilityId", facilityId);
serviceContext.put("reservPersons", routingTask.get("reservPersons"));
serviceContext.put("estimatedStartDate",startDate);
serviceContext.put("estimatedCompletionDate",endDate);
serviceContext.put("estimatedSetupMillis", routingTask.get("estimatedSetupMillis"));
serviceContext.put("estimatedMilliSeconds", routingTask.get("estimatedMilliSeconds"));
serviceContext.put("quantityToProduce", pRQuantity);
serviceContext.put("userLogin", userLogin);
resultService = null;
try {
resultService = dispatcher.runSync("createWorkEffort", serviceContext);
} catch (GenericServiceException e) {
Debug.logError(e, "Problem calling the createWorkEffort service", module);
}
String productionRunTaskId = (String) resultService.get("workEffortId");
if (Debug.infoOn()) Debug.logInfo("ProductionRunTaskId created: " + productionRunTaskId, module);
// The newly created production run task is associated to the routing task
// to keep track of the template used to generate it.
serviceContext.clear();
serviceContext.put("userLogin", userLogin);
serviceContext.put("workEffortIdFrom", routingTask.getString("workEffortId"));
serviceContext.put("workEffortIdTo", productionRunTaskId);
serviceContext.put("workEffortAssocTypeId", "WORK_EFF_TEMPLATE");
try {
resultService = dispatcher.runSync("createWorkEffortAssoc", serviceContext);
} catch (GenericServiceException e) {
Debug.logError(e, "Problem calling the createWorkEffortAssoc service", module);
}
// clone associated objects from the routing task to the run task
String routingTaskId = routingTaskAssoc.getString("workEffortIdTo");
cloneWorkEffortPartyAssignments(ctx, userLogin, routingTaskId, productionRunTaskId);
cloneWorkEffortCostCalcs(ctx, userLogin, routingTaskId, productionRunTaskId);
// Now we iterate thru the components returned by the getManufacturingComponents service
// TODO: if in the BOM a routingWorkEffortId is specified, but the task is not in the routing
// the component is not added to the production run.
for(BOMNode node : components) {
// The components variable contains a list of BOMNodes:
// each node represents a product (component).
GenericValue productBom = node.getProductAssoc();
if ((productBom.getString("routingWorkEffortId") == null && first) || (productBom.getString("routingWorkEffortId") != null && productBom.getString("routingWorkEffortId").equals(routingTask.getString("workEffortId")))) {
serviceContext.clear();
serviceContext.put("workEffortId", productionRunTaskId);
// Here we get the ProductAssoc record from the BOMNode
// object to be sure to use the
// right component (possibly configured).
serviceContext.put("productId", node.getProduct().get("productId"));
serviceContext.put("workEffortGoodStdTypeId", "PRUNT_PROD_NEEDED");
serviceContext.put("statusId", "WEGS_CREATED");
serviceContext.put("fromDate", productBom.get("fromDate"));
// Here we use the getQuantity method to get the quantity already
// computed by the getManufacturingComponents service
serviceContext.put("estimatedQuantity", node.getQuantity());
serviceContext.put("userLogin", userLogin);
resultService = null;
try {
resultService = dispatcher.runSync("createWorkEffortGoodStandard", serviceContext);
} catch (GenericServiceException e) {
Debug.logError(e, "Problem calling the createWorkEffortGoodStandard service", module);
}
if (Debug.infoOn()) Debug.logInfo("ProductLink created for productId: " + productBom.getString("productIdTo"), module);
}
}
first = false;
startDate = endDate;
}