Search in sources :

Example 1 with BOMNode

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;
}
Also used : Locale(java.util.Locale) GenericValue(org.apache.ofbiz.entity.GenericValue) LocalDispatcher(org.apache.ofbiz.service.LocalDispatcher) GeneralException(org.apache.ofbiz.base.util.GeneralException) HashMap(java.util.HashMap) Timestamp(java.sql.Timestamp) BigDecimal(java.math.BigDecimal) BOMNode(org.apache.ofbiz.manufacturing.bom.BOMNode) Delegator(org.apache.ofbiz.entity.Delegator) GenericEntityException(org.apache.ofbiz.entity.GenericEntityException) GenericServiceException(org.apache.ofbiz.service.GenericServiceException)

Example 2 with BOMNode

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);
                }
            }
        }
    }
}
Also used : GenericValue(org.apache.ofbiz.entity.GenericValue) Delegator(org.apache.ofbiz.entity.Delegator) GenericEntityException(org.apache.ofbiz.entity.GenericEntityException) Timestamp(java.sql.Timestamp) BOMNode(org.apache.ofbiz.manufacturing.bom.BOMNode) BigDecimal(java.math.BigDecimal)

Example 3 with BOMNode

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;
}
Also used : Locale(java.util.Locale) GenericValue(org.apache.ofbiz.entity.GenericValue) LocalDispatcher(org.apache.ofbiz.service.LocalDispatcher) HashMap(java.util.HashMap) BigDecimal(java.math.BigDecimal) Date(java.util.Date) GenericServiceException(org.apache.ofbiz.service.GenericServiceException) GenericEntityException(org.apache.ofbiz.entity.GenericEntityException) GeneralException(org.apache.ofbiz.base.util.GeneralException) LinkedList(java.util.LinkedList) BOMNode(org.apache.ofbiz.manufacturing.bom.BOMNode) BOMTree(org.apache.ofbiz.manufacturing.bom.BOMTree) Delegator(org.apache.ofbiz.entity.Delegator) GenericEntityException(org.apache.ofbiz.entity.GenericEntityException)

Example 4 with BOMNode

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;
}
Also used : Locale(java.util.Locale) GenericValue(org.apache.ofbiz.entity.GenericValue) LocalDispatcher(org.apache.ofbiz.service.LocalDispatcher) HashMap(java.util.HashMap) Timestamp(java.sql.Timestamp) BigDecimal(java.math.BigDecimal) BOMNode(org.apache.ofbiz.manufacturing.bom.BOMNode) LinkedList(java.util.LinkedList) BOMTree(org.apache.ofbiz.manufacturing.bom.BOMTree) Delegator(org.apache.ofbiz.entity.Delegator) GenericEntityException(org.apache.ofbiz.entity.GenericEntityException)

Example 5 with BOMNode

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;
}
Also used : Locale(java.util.Locale) LocalDispatcher(org.apache.ofbiz.service.LocalDispatcher) EntityCondition(org.apache.ofbiz.entity.condition.EntityCondition) Timestamp(java.sql.Timestamp) BOMNode(org.apache.ofbiz.manufacturing.bom.BOMNode) GenericValue(org.apache.ofbiz.entity.GenericValue) BigDecimal(java.math.BigDecimal) GenericServiceException(org.apache.ofbiz.service.GenericServiceException) GenericEntityException(org.apache.ofbiz.entity.GenericEntityException) LinkedList(java.util.LinkedList) Delegator(org.apache.ofbiz.entity.Delegator) GenericEntityException(org.apache.ofbiz.entity.GenericEntityException) GenericServiceException(org.apache.ofbiz.service.GenericServiceException)

Aggregations

GenericEntityException (org.apache.ofbiz.entity.GenericEntityException)7 BOMNode (org.apache.ofbiz.manufacturing.bom.BOMNode)7 Delegator (org.apache.ofbiz.entity.Delegator)6 GenericValue (org.apache.ofbiz.entity.GenericValue)6 BigDecimal (java.math.BigDecimal)5 Timestamp (java.sql.Timestamp)5 LinkedList (java.util.LinkedList)5 GenericServiceException (org.apache.ofbiz.service.GenericServiceException)5 LocalDispatcher (org.apache.ofbiz.service.LocalDispatcher)5 Locale (java.util.Locale)4 BOMTree (org.apache.ofbiz.manufacturing.bom.BOMTree)4 HashMap (java.util.HashMap)3 GeneralException (org.apache.ofbiz.base.util.GeneralException)2 Date (java.util.Date)1 EntityCondition (org.apache.ofbiz.entity.condition.EntityCondition)1