use of org.apache.ofbiz.manufacturing.bom.BOMNode in project ofbiz-framework by apache.
the class ProductionRunServices method createProductionRun.
/**
* Creates a Production Run.
* <ul>
* <li> check if routing - product link exist</li>
* <li> check if product have a Bill Of Material</li>
* <li> check if routing have routingTask</li>
* <li> create the workEffort for ProductionRun</li>
* <li> create the WorkEffortGoodStandard for link between ProductionRun and the product it will produce</li>
* <li> for each valid routingTask of the routing create a workeffort-task</li>
* <li> for the first routingTask, create for all the valid productIdTo with no associateRoutingTask a WorkEffortGoodStandard</li>
* <li> for each valid routingTask of the routing and valid productIdTo associate with this RoutingTask create a WorkEffortGoodStandard</li>
* </ul>
* @param ctx The DispatchContext that this service is operating in.
* @param context Map containing the input parameters, productId, routingId, pRQuantity, startDate, workEffortName, description
* @return Map with the result of the service, the output parameters.
*/
public static Map<String, Object> createProductionRun(DispatchContext ctx, Map<String, ? extends Object> context) {
Map<String, Object> result = new HashMap<String, Object>();
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)
*/
// 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 = EntityQuery.use(delegator).from("Product").where("productId", productId).queryOne();
if (product == null) {
return ServiceUtil.returnError(UtilProperties.getMessage(resource, "ManufacturingProductNotExist", locale));
}
} catch (GenericEntityException e) {
Debug.logWarning(e.getMessage(), module);
return ServiceUtil.returnError(e.getMessage());
}
// 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);
if (ServiceUtil.isError(routingOutMap)) {
return ServiceUtil.returnError(ServiceUtil.getErrorMessage(routingOutMap));
}
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 = new HashMap<String, Object>();
// the product that we want to manufacture
serviceContext.put("productId", productId);
// the quantity that we want to manufacture
serviceContext.put("quantity", pRQuantity);
serviceContext.put("userLogin", userLogin);
Map<String, Object> serviceResult = null;
try {
serviceResult = dispatcher.runSync("getManufacturingComponents", serviceContext);
if (ServiceUtil.isError(serviceResult)) {
return ServiceUtil.returnError(ServiceUtil.getErrorMessage(serviceResult));
}
// a list of objects representing the product's components
components = UtilGenerics.checkList(serviceResult.get("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 {
serviceResult = dispatcher.runSync("createWorkEffort", serviceContext);
if (ServiceUtil.isError(serviceResult)) {
return ServiceUtil.returnError(ServiceUtil.getErrorMessage(serviceResult));
}
} catch (GenericServiceException e) {
Debug.logError(e, "Problem calling the createWorkEffort service", module);
return ServiceUtil.returnError(e.getMessage());
}
String productionRunId = (String) serviceResult.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 {
serviceResult = dispatcher.runSync("createWorkEffortGoodStandard", serviceContext);
if (ServiceUtil.isError(serviceResult)) {
return ServiceUtil.returnError(ServiceUtil.getErrorMessage(serviceResult));
}
} 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", false);
} 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", "WEPT_PRODUCTION_RUN");
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);
serviceResult = null;
try {
serviceResult = dispatcher.runSync("createWorkEffort", serviceContext);
if (ServiceUtil.isError(serviceResult)) {
return ServiceUtil.returnError(ServiceUtil.getErrorMessage(serviceResult));
}
} catch (GenericServiceException e) {
Debug.logError(e, "Problem calling the createWorkEffort service", module);
}
String productionRunTaskId = (String) serviceResult.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 {
serviceResult = dispatcher.runSync("createWorkEffortAssoc", serviceContext);
if (ServiceUtil.isError(serviceResult)) {
return ServiceUtil.returnError(ServiceUtil.getErrorMessage(serviceResult));
}
} 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");
try {
cloneWorkEffortPartyAssignments(ctx, userLogin, routingTaskId, productionRunTaskId);
cloneWorkEffortCostCalcs(ctx, userLogin, routingTaskId, productionRunTaskId);
} catch (GeneralException e) {
return ServiceUtil.returnError(e.getMessage());
}
// 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);
serviceResult = null;
try {
serviceResult = dispatcher.runSync("createWorkEffortGoodStandard", serviceContext);
if (ServiceUtil.isError(serviceResult)) {
return ServiceUtil.returnError(ServiceUtil.getErrorMessage(serviceResult));
}
} 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;
}
}
// update the estimatedCompletionDate field for the productionRun
serviceContext.clear();
serviceContext.put("workEffortId", productionRunId);
serviceContext.put("estimatedCompletionDate", startDate);
serviceContext.put("userLogin", userLogin);
serviceResult = null;
try {
serviceResult = dispatcher.runSync("updateWorkEffort", serviceContext);
if (ServiceUtil.isError(serviceResult)) {
return ServiceUtil.returnError(ServiceUtil.getErrorMessage(serviceResult));
}
} catch (GenericServiceException e) {
Debug.logError(e, "Problem calling the updateWorkEffort service", module);
}
result.put("productionRunId", productionRunId);
result.put("estimatedCompletionDate", startDate);
result.put(ModelService.SUCCESS_MESSAGE, UtilProperties.getMessage(resource, "ManufacturingProductionRunCreated", UtilMisc.toMap("productionRunId", productionRunId), locale));
return result;
}
use of org.apache.ofbiz.manufacturing.bom.BOMNode in project ofbiz-framework by apache.
the class MrpServices method processBomComponent.
/**
* Process the bill of material (bom) of the product to insert components in the MrpEvent table.
* Before inserting in the entity, test if there is the record already existing to add quantity rather to create a new one.
* @param mrpId the mrp id
* @param product GenericValue oject of the product
* @param eventQuantity the product quantity needed
* @param startDate the startDate of the productionRun which will used to produce the product
* @param routingTaskStartDate Map with all the routingTask as keys and startDate of each of them
* @param listComponent a List with all the components
*/
public static void processBomComponent(String mrpId, GenericValue product, BigDecimal eventQuantity, Timestamp startDate, Map<String, Object> routingTaskStartDate, List<BOMNode> listComponent) {
// TODO : change the return type to boolean to be able to test if all is ok or if it have had a exception
Delegator delegator = product.getDelegator();
if (UtilValidate.isNotEmpty(listComponent)) {
for (BOMNode node : listComponent) {
GenericValue productComponent = node.getProductAssoc();
// read the startDate for the component
String routingTask = node.getProductAssoc().getString("routingWorkEffortId");
Timestamp eventDate = (routingTask == null || !routingTaskStartDate.containsKey(routingTask)) ? startDate : (Timestamp) routingTaskStartDate.get(routingTask);
// if the components is valid at the event Date create the Mrp requirement in the M entity
if (EntityUtil.isValueActive(productComponent, eventDate)) {
Map<String, Object> parameters = UtilMisc.<String, Object>toMap("productId", node.getProduct().getString("productId"));
parameters.put("mrpId", mrpId);
parameters.put("eventDate", eventDate);
parameters.put("mrpEventTypeId", "MRP_REQUIREMENT");
BigDecimal componentEventQuantity = node.getQuantity();
try {
InventoryEventPlannedServices.createOrUpdateMrpEvent(parameters, componentEventQuantity.negate(), null, product.get("productId") + ": " + eventDate, false, delegator);
} catch (GenericEntityException e) {
Debug.logError("Error : findOne(\"MrpEvent\", parameters) =" + parameters + "--" + e.getMessage(), module);
logMrpError(mrpId, node.getProduct().getString("productId"), "Unable to create event (processBomComponent)", delegator);
}
}
}
}
}
use of org.apache.ofbiz.manufacturing.bom.BOMNode in project ofbiz-framework by apache.
the class ProductionRunServices method createProductionRunsForOrder.
public static Map<String, Object> createProductionRunsForOrder(DispatchContext dctx, Map<String, ? extends Object> context) {
Map<String, Object> result = new HashMap<String, Object>();
Delegator delegator = dctx.getDelegator();
LocalDispatcher dispatcher = dctx.getDispatcher();
GenericValue userLogin = (GenericValue) context.get("userLogin");
String orderId = (String) context.get("orderId");
String shipmentId = (String) context.get("shipmentId");
String orderItemSeqId = (String) context.get("orderItemSeqId");
String shipGroupSeqId = (String) context.get("shipGroupSeqId");
BigDecimal quantity = (BigDecimal) context.get("quantity");
String fromDateStr = (String) context.get("fromDate");
Locale locale = (Locale) context.get("locale");
Date fromDate = null;
if (UtilValidate.isNotEmpty(fromDateStr)) {
try {
fromDate = Timestamp.valueOf(fromDateStr);
} catch (Exception e) {
}
}
if (fromDate == null) {
fromDate = new Date();
}
List<GenericValue> orderItems = null;
if (orderItemSeqId != null) {
try {
GenericValue orderItem = null;
if (UtilValidate.isNotEmpty(shipGroupSeqId)) {
orderItem = EntityQuery.use(delegator).from("OrderItemShipGroupAssoc").where("orderId", orderId, "orderItemSeqId", orderItemSeqId, "shipGroupSeqId", shipGroupSeqId).queryOne();
} else {
orderItem = EntityQuery.use(delegator).from("OrderItem").where("orderId", orderId, "orderItemSeqId", orderItemSeqId).queryOne();
}
if (orderItem == null) {
return ServiceUtil.returnError(UtilProperties.getMessage(resourceOrder, "OrderErrorOrderItemNotFound", UtilMisc.toMap("orderId", orderId, "orderItemSeqId", ""), locale));
}
if (quantity != null) {
orderItem.set("quantity", quantity);
}
orderItems = UtilMisc.toList(orderItem);
} catch (GenericEntityException gee) {
return ServiceUtil.returnError(UtilProperties.getMessage(resourceOrder, "OrderProblemsReadingOrderItemInformation", UtilMisc.toMap("errorString", gee.getMessage()), locale));
}
} else {
try {
orderItems = EntityQuery.use(delegator).from("OrderItem").where("orderId", orderId).queryList();
if (orderItems == null) {
return ServiceUtil.returnError(UtilProperties.getMessage(resourceOrder, "OrderErrorOrderItemNotFound", UtilMisc.toMap("orderId", orderId, "orderItemSeqId", ""), locale));
}
} catch (GenericEntityException gee) {
return ServiceUtil.returnError(UtilProperties.getMessage(resourceOrder, "OrderProblemsReadingOrderItemInformation", UtilMisc.toMap("errorString", gee.getMessage()), locale));
}
}
List<String> productionRuns = new LinkedList<String>();
for (int i = 0; i < orderItems.size(); i++) {
GenericValue orderItemOrShipGroupAssoc = orderItems.get(i);
String productId = null;
BigDecimal amount = null;
GenericValue orderItem = null;
if ("OrderItemShipGroupAssoc".equals(orderItemOrShipGroupAssoc.getEntityName())) {
try {
orderItem = orderItemOrShipGroupAssoc.getRelatedOne("OrderItem", false);
} catch (GenericEntityException gee) {
Debug.logInfo("Unable to find order item for " + orderItemOrShipGroupAssoc, module);
}
} else {
orderItem = orderItemOrShipGroupAssoc;
}
if (orderItem == null || orderItem.get("productId") == null) {
continue;
} else {
productId = orderItem.getString("productId");
}
if (orderItem.get("selectedAmount") != null) {
amount = orderItem.getBigDecimal("selectedAmount");
}
if (amount == null) {
amount = BigDecimal.ZERO;
}
if (orderItemOrShipGroupAssoc.get("quantity") != null) {
quantity = orderItemOrShipGroupAssoc.getBigDecimal("quantity");
} else {
continue;
}
try {
List<GenericValue> existingProductionRuns = null;
if (UtilValidate.isNotEmpty(shipGroupSeqId)) {
existingProductionRuns = EntityQuery.use(delegator).from("WorkAndOrderItemFulfillment").where(EntityCondition.makeCondition("orderId", EntityOperator.EQUALS, orderItemOrShipGroupAssoc.get("orderId")), EntityCondition.makeCondition("orderItemSeqId", EntityOperator.EQUALS, orderItemOrShipGroupAssoc.get("orderItemSeqId")), EntityCondition.makeCondition("shipGroupSeqId", EntityOperator.EQUALS, orderItemOrShipGroupAssoc.get("shipGroupSeqId")), EntityCondition.makeCondition("currentStatusId", EntityOperator.NOT_EQUAL, "PRUN_CANCELLED")).cache().queryList();
} else {
existingProductionRuns = EntityQuery.use(delegator).from("WorkAndOrderItemFulfillment").where(EntityCondition.makeCondition("orderId", EntityOperator.EQUALS, orderItemOrShipGroupAssoc.get("orderId")), EntityCondition.makeCondition("orderItemSeqId", EntityOperator.EQUALS, orderItemOrShipGroupAssoc.get("orderItemSeqId")), EntityCondition.makeCondition("currentStatusId", EntityOperator.NOT_EQUAL, "PRUN_CANCELLED")).cache().queryList();
}
if (UtilValidate.isNotEmpty(existingProductionRuns)) {
Debug.logWarning("Production Run for order item [" + orderItemOrShipGroupAssoc.getString("orderId") + "/" + orderItemOrShipGroupAssoc.getString("orderItemSeqId") + "] and ship group [" + shipGroupSeqId + "] already exists.", module);
continue;
}
} catch (GenericEntityException gee) {
return ServiceUtil.returnError(UtilProperties.getMessage(resource, "ManufacturinWorkOrderItemFulfillmentError", UtilMisc.toMap("errorString", gee.getMessage()), locale));
}
try {
List<BOMNode> components = new LinkedList<BOMNode>();
BOMTree tree = new BOMTree(productId, "MANUF_COMPONENT", fromDate, BOMTree.EXPLOSION_MANUFACTURING, delegator, dispatcher, userLogin);
tree.setRootQuantity(quantity);
tree.setRootAmount(amount);
tree.print(components);
productionRuns.add(tree.createManufacturingOrders(null, fromDate, null, null, null, orderId, orderItem.getString("orderItemSeqId"), shipGroupSeqId, shipmentId, userLogin));
} catch (GenericEntityException gee) {
return ServiceUtil.returnError(UtilProperties.getMessage(resource, "ManufacturingBomErrorCreatingBillOfMaterialsTree", UtilMisc.toMap("errorString", gee.getMessage()), locale));
}
}
result.put("productionRuns", productionRuns);
return result;
}
use of org.apache.ofbiz.manufacturing.bom.BOMNode in project ofbiz-framework by apache.
the class ProductionRunServices method createProductionRunsForProductBom.
public static Map<String, Object> createProductionRunsForProductBom(DispatchContext dctx, Map<String, ? extends Object> context) {
Map<String, Object> result = new HashMap<String, Object>();
Delegator delegator = dctx.getDelegator();
LocalDispatcher dispatcher = dctx.getDispatcher();
GenericValue userLogin = (GenericValue) context.get("userLogin");
Locale locale = (Locale) context.get("locale");
String productId = (String) context.get("productId");
Timestamp startDate = (Timestamp) context.get("startDate");
BigDecimal quantity = (BigDecimal) context.get("quantity");
String facilityId = (String) context.get("facilityId");
String workEffortName = (String) context.get("workEffortName");
String description = (String) context.get("description");
String routingId = (String) context.get("routingId");
String workEffortId = null;
if (quantity == null) {
quantity = BigDecimal.ONE;
}
try {
List<BOMNode> components = new LinkedList<BOMNode>();
BOMTree tree = new BOMTree(productId, "MANUF_COMPONENT", startDate, BOMTree.EXPLOSION_MANUFACTURING, delegator, dispatcher, userLogin);
tree.setRootQuantity(quantity);
tree.setRootAmount(BigDecimal.ZERO);
tree.print(components);
workEffortId = tree.createManufacturingOrders(facilityId, startDate, workEffortName, description, routingId, null, null, null, null, userLogin);
} catch (GenericEntityException gee) {
return ServiceUtil.returnError(UtilProperties.getMessage(resource, "ManufacturingBomErrorCreatingBillOfMaterialsTree", UtilMisc.toMap("errorString", gee.getMessage()), locale));
}
if (workEffortId == null) {
return ServiceUtil.returnError(UtilProperties.getMessage(resource, "ManufacturingProductionRunIsNotRequiredForProductId", UtilMisc.toMap("productId", productId, "startDate", startDate), locale));
}
List<String> productionRuns = new LinkedList<String>();
result.put("productionRuns", productionRuns);
result.put("productionRunId", workEffortId);
return result;
}
use of org.apache.ofbiz.manufacturing.bom.BOMNode in project ofbiz-framework by apache.
the class MrpServices method executeMrp.
/**
* Launch the MRP.
* <ul>
* <li>PreConditions : none</li>
* <li>Result : The date when we must order or begin to build the products and subproducts we need are calculated</li>
* <li>INPUT : parameters to get from the context: <ul><li>String mrpName</li></ul></li>
* <li>OUTPUT : Result to put in the map : <ul><li>none</li></ul></li>
* </ul>
*
* @param ctx The DispatchContext that this service is operating in.
* @param context Map containing the input parameters, productId routingId, quantity, startDate.
* @return Map with the result of the service, the output parameters.
*/
public static Map<String, Object> executeMrp(DispatchContext ctx, Map<String, ? extends Object> context) {
Debug.logInfo("executeMrp called", module);
Delegator delegator = ctx.getDelegator();
LocalDispatcher dispatcher = ctx.getDispatcher();
GenericValue userLogin = (GenericValue) context.get("userLogin");
Timestamp now = UtilDateTime.nowTimestamp();
Locale locale = (Locale) context.get("locale");
String mrpName = (String) context.get("mrpName");
Integer defaultYearsOffset = (Integer) context.get("defaultYearsOffset");
String facilityGroupId = (String) context.get("facilityGroupId");
String facilityId = (String) context.get("facilityId");
String manufacturingFacilityId = null;
if (UtilValidate.isEmpty(facilityId) && UtilValidate.isEmpty(facilityGroupId)) {
return ServiceUtil.returnError(UtilProperties.getMessage(resource, "ManufacturingMrpFacilityNotAvailable", locale));
}
if (UtilValidate.isEmpty(facilityId)) {
try {
GenericValue facilityGroup = EntityQuery.use(delegator).from("FacilityGroup").where("facilityGroupId", facilityGroupId).queryOne();
if (UtilValidate.isEmpty(facilityGroup)) {
return ServiceUtil.returnError(UtilProperties.getMessage(resource, "ManufacturingMrpFacilityGroupIsNotValid", UtilMisc.toMap("facilityGroupId", facilityGroupId), locale));
}
List<GenericValue> facilities = facilityGroup.getRelated("FacilityGroupMember", null, UtilMisc.toList("sequenceNum"), false);
if (UtilValidate.isEmpty(facilities)) {
return ServiceUtil.returnError(UtilProperties.getMessage(resource, "ManufacturingMrpFacilityGroupIsNotAssociatedToFacility", UtilMisc.toMap("facilityGroupId", facilityGroupId), locale));
}
for (GenericValue facilityMember : facilities) {
GenericValue facility = facilityMember.getRelatedOne("Facility", false);
if ("WAREHOUSE".equals(facility.getString("facilityTypeId")) && UtilValidate.isEmpty(facilityId)) {
facilityId = facility.getString("facilityId");
}
if ("PLANT".equals(facility.getString("facilityTypeId")) && UtilValidate.isEmpty(manufacturingFacilityId)) {
manufacturingFacilityId = facility.getString("facilityId");
}
}
} catch (GenericEntityException e) {
return ServiceUtil.returnError(UtilProperties.getMessage(resource, "ManufacturingMrpFacilityGroupCannotBeLoad", UtilMisc.toMap("errorString", e.getMessage()), locale));
}
} else {
manufacturingFacilityId = facilityId;
}
if (UtilValidate.isEmpty(facilityId) || UtilValidate.isEmpty(manufacturingFacilityId)) {
return ServiceUtil.returnError(UtilProperties.getMessage(resource, "ManufacturingMrpFacilityOrManufacturingFacilityNotAvailable", locale));
}
int bomLevelWithNoEvent = 0;
BigDecimal stockTmp = BigDecimal.ZERO;
String oldProductId = null;
String productId = null;
GenericValue product = null;
GenericValue productFacility = null;
BigDecimal eventQuantity = BigDecimal.ZERO;
Timestamp eventDate = null;
BigDecimal reorderQuantity = BigDecimal.ZERO;
BigDecimal minimumStock = BigDecimal.ZERO;
int daysToShip = 0;
List<BOMNode> components = null;
boolean isBuilt = false;
GenericValue routing = null;
String mrpId = delegator.getNextSeqId("MrpEvent");
Map<String, Object> result = null;
Map<String, Object> parameters = null;
List<GenericValue> listInventoryEventForMRP = null;
ListIterator<GenericValue> iteratorListInventoryEventForMRP = null;
// Initialization of the MrpEvent table, This table will contain the products we want to buy or build.
parameters = UtilMisc.<String, Object>toMap("mrpId", mrpId, "reInitialize", Boolean.TRUE, "defaultYearsOffset", defaultYearsOffset, "userLogin", userLogin);
parameters.put("facilityId", facilityId);
parameters.put("manufacturingFacilityId", manufacturingFacilityId);
try {
result = dispatcher.runSync("initMrpEvents", parameters);
if (ServiceUtil.isError(result)) {
return ServiceUtil.returnError(ServiceUtil.getErrorMessage(result));
}
} catch (GenericServiceException e) {
return ServiceUtil.returnError(UtilProperties.getMessage(resource, "ManufacturingMrpErrorRunningInitMrpEvents", UtilMisc.toMap("errorString", e.getMessage()), locale));
}
long bomLevel = 0;
do {
// Find all products in MrpEventView, ordered by bom and eventDate
EntityCondition filterByConditions = null;
if (bomLevel == 0) {
filterByConditions = EntityCondition.makeCondition(EntityCondition.makeCondition("billOfMaterialLevel", EntityOperator.EQUALS, null), EntityOperator.OR, EntityCondition.makeCondition("billOfMaterialLevel", EntityOperator.EQUALS, Long.valueOf(bomLevel)));
} else {
filterByConditions = EntityCondition.makeCondition("billOfMaterialLevel", EntityOperator.EQUALS, Long.valueOf(bomLevel));
}
try {
listInventoryEventForMRP = EntityQuery.use(delegator).from("MrpEventView").where(filterByConditions).orderBy("productId", "eventDate").queryList();
} catch (GenericEntityException e) {
Long bomLevelToString = new Long(bomLevel);
return ServiceUtil.returnError(UtilProperties.getMessage(resource, "ManufacturingMrpErrorForBomLevel", UtilMisc.toMap("bomLevel", bomLevelToString.toString(), "errorString", e.getMessage()), locale));
}
if (UtilValidate.isNotEmpty(listInventoryEventForMRP)) {
bomLevelWithNoEvent = 0;
oldProductId = "";
int eventCount = 0;
for (GenericValue inventoryEventForMRP : listInventoryEventForMRP) {
eventCount++;
productId = inventoryEventForMRP.getString("productId");
boolean isLastEvent = (eventCount == listInventoryEventForMRP.size() || !productId.equals(listInventoryEventForMRP.get(eventCount).getString("productId")));
eventQuantity = inventoryEventForMRP.getBigDecimal("quantity");
if (!productId.equals(oldProductId)) {
BigDecimal positiveEventQuantity = eventQuantity.compareTo(BigDecimal.ZERO) > 0 ? eventQuantity : eventQuantity.negate();
// It's a new product, so it's necessary to read the MrpQoh
try {
product = inventoryEventForMRP.getRelatedOne("Product", true);
productFacility = EntityUtil.getFirst(product.getRelated("ProductFacility", UtilMisc.toMap("facilityId", facilityId), null, true));
} catch (GenericEntityException e) {
return ServiceUtil.returnError(UtilProperties.getMessage(resource, "ManufacturingMrpCannotFindProductForEvent", locale));
}
stockTmp = findProductMrpQoh(mrpId, product, facilityId, dispatcher, delegator);
try {
InventoryEventPlannedServices.createOrUpdateMrpEvent(UtilMisc.<String, Object>toMap("mrpId", mrpId, "productId", product.getString("productId"), "mrpEventTypeId", "INITIAL_QOH", "eventDate", now), stockTmp, facilityId, null, false, delegator);
} catch (GenericEntityException e) {
return ServiceUtil.returnError(UtilProperties.getMessage(resource, "ManufacturingMrpCreateOrUpdateEvent", UtilMisc.toMap("parameters", parameters), locale));
}
// days to ship is only relevant for sales order to plan for preparatory days to ship. Otherwise MRP will push event dates for manufacturing parts
// as well and cause problems
daysToShip = 0;
if (productFacility != null) {
reorderQuantity = (productFacility.getBigDecimal("reorderQuantity") != null ? productFacility.getBigDecimal("reorderQuantity") : BigDecimal.ONE.negate());
minimumStock = (productFacility.getBigDecimal("minimumStock") != null ? productFacility.getBigDecimal("minimumStock") : BigDecimal.ZERO);
if ("SALES_ORDER_SHIP".equals(inventoryEventForMRP.getString("mrpEventTypeId"))) {
daysToShip = (productFacility.getLong("daysToShip") != null ? productFacility.getLong("daysToShip").intValue() : 0);
}
} else {
minimumStock = BigDecimal.ZERO;
reorderQuantity = BigDecimal.ONE.negate();
}
// -----------------------------------------------------
// The components are also loaded thru the configurator
Map<String, Object> serviceResponse = null;
try {
serviceResponse = dispatcher.runSync("getManufacturingComponents", UtilMisc.<String, Object>toMap("productId", product.getString("productId"), "quantity", positiveEventQuantity, "excludeWIPs", Boolean.FALSE, "userLogin", userLogin));
if (ServiceUtil.isError(serviceResponse)) {
return ServiceUtil.returnError(ServiceUtil.getErrorMessage(serviceResponse));
}
} catch (GenericServiceException e) {
return ServiceUtil.returnError(UtilProperties.getMessage(resource, "ManufacturingMrpErrorExplodingProduct", UtilMisc.toMap("productId", product.getString("productId")), locale));
} catch (Exception e) {
return ServiceUtil.returnError(UtilProperties.getMessage(resource, "ManufacturingMrpErrorExplodingProduct", UtilMisc.toMap("productId", product.getString("productId")), locale));
}
components = UtilGenerics.checkList(serviceResponse.get("components"));
if (UtilValidate.isNotEmpty(components)) {
BOMNode node = (components.get(0)).getParentNode();
isBuilt = node.isManufactured();
} else {
isBuilt = false;
}
// #####################################################
oldProductId = productId;
}
stockTmp = stockTmp.add(eventQuantity);
if (stockTmp.compareTo(minimumStock) < 0 && (eventQuantity.compareTo(BigDecimal.ZERO) < 0 || isLastEvent)) {
// No need to create a supply event/requirement if the current event is not a demand and there are other events to process
BigDecimal qtyToStock = minimumStock.subtract(stockTmp);
// need to buy or build the product as we have not enough stock
eventDate = inventoryEventForMRP.getTimestamp("eventDate");
// to be just before the requirement
eventDate.setTime(eventDate.getTime() - 1);
ProposedOrder proposedOrder = new ProposedOrder(product, facilityId, manufacturingFacilityId, isBuilt, eventDate, qtyToStock);
proposedOrder.setMrpName(mrpName);
// calculate the ProposedOrder quantity and update the quantity object property.
proposedOrder.calculateQuantityToSupply(reorderQuantity, minimumStock, iteratorListInventoryEventForMRP);
// -----------------------------------------------------
// The components are also loaded thru the configurator
Map<String, Object> serviceResponse = null;
try {
serviceResponse = dispatcher.runSync("getManufacturingComponents", UtilMisc.<String, Object>toMap("productId", product.getString("productId"), "quantity", proposedOrder.getQuantity(), "excludeWIPs", Boolean.FALSE, "userLogin", userLogin));
if (ServiceUtil.isError(serviceResponse)) {
return ServiceUtil.returnError(ServiceUtil.getErrorMessage(serviceResponse));
}
} catch (GenericServiceException e) {
return ServiceUtil.returnError(UtilProperties.getMessage(resource, "ManufacturingMrpErrorExplodingProduct", UtilMisc.toMap("productId", product.getString("productId")), locale));
} catch (Exception e) {
return ServiceUtil.returnError(UtilProperties.getMessage(resource, "ManufacturingMrpErrorExplodingProduct", UtilMisc.toMap("productId", product.getString("productId")), locale));
}
components = UtilGenerics.checkList(serviceResponse.get("components"));
String routingId = (String) serviceResponse.get("workEffortId");
if (routingId != null) {
try {
routing = EntityQuery.use(delegator).from("WorkEffort").where("workEffortId", routingId).queryOne();
} catch (GenericEntityException e) {
return ServiceUtil.returnError(UtilProperties.getMessage(resource, "ManufacturingMrpCannotFindProductForEvent", locale));
}
} else {
routing = null;
}
if (UtilValidate.isNotEmpty(components)) {
BOMNode node = (components.get(0)).getParentNode();
isBuilt = node.isManufactured();
} else {
isBuilt = false;
}
// #####################################################
// calculate the ProposedOrder requirementStartDate and update the requirementStartDate object property.
Map<String, Object> routingTaskStartDate = proposedOrder.calculateStartDate(daysToShip, routing, delegator, dispatcher, userLogin);
if (isBuilt) {
// process the product components
processBomComponent(mrpId, product, proposedOrder.getQuantity(), proposedOrder.getRequirementStartDate(), routingTaskStartDate, components);
}
// create the ProposedOrder (only if the product is warehouse managed), and the MrpEvent associated
String requirementId = null;
if (productFacility != null) {
requirementId = proposedOrder.create(ctx, userLogin);
}
if (UtilValidate.isEmpty(productFacility) && !isBuilt) {
logMrpError(mrpId, productId, now, "No ProductFacility record for [" + facilityId + "]; no requirement created.", delegator);
}
String eventName = null;
if (UtilValidate.isNotEmpty(requirementId)) {
eventName = "*" + requirementId + " (" + proposedOrder.getRequirementStartDate() + ")*";
}
Map<String, Object> eventMap = UtilMisc.<String, Object>toMap("productId", product.getString("productId"), "mrpId", mrpId, "eventDate", eventDate, "mrpEventTypeId", (isBuilt ? "PROP_MANUF_O_RECP" : "PROP_PUR_O_RECP"));
try {
InventoryEventPlannedServices.createOrUpdateMrpEvent(eventMap, proposedOrder.getQuantity(), null, eventName, (proposedOrder.getRequirementStartDate().compareTo(now) < 0), delegator);
} catch (GenericEntityException e) {
return ServiceUtil.returnError(UtilProperties.getMessage(resource, "ManufacturingMrpCreateOrUpdateEvent", UtilMisc.toMap("parameters", parameters), locale));
}
//
stockTmp = stockTmp.add(proposedOrder.getQuantity());
}
}
} else {
bomLevelWithNoEvent += 1;
}
bomLevel += 1;
// if there are 3 levels with no inventoryEvenPanned we stop
} while (bomLevelWithNoEvent < 3);
result = new HashMap<String, Object>();
List<Object> msgResult = new LinkedList<Object>();
result.put("msgResult", msgResult);
result.put(ModelService.RESPONSE_MESSAGE, ModelService.RESPOND_SUCCESS);
Debug.logInfo("return from executeMrp", module);
return result;
}
Aggregations