Search in sources :

Example 41 with EntityExpr

use of org.apache.ofbiz.entity.condition.EntityExpr in project ofbiz-framework by apache.

the class OrderServices method loadCartForUpdate.

/*
     *  Warning: loadCartForUpdate(...) and saveUpdatedCartToOrder(...) must always
     *           be used together in this sequence.
     *           In fact loadCartForUpdate(...) will remove or cancel data associated to the order,
     *           before returning the ShoppingCart object; for this reason, the cart
     *           must be stored back using the method saveUpdatedCartToOrder(...),
     *           because that method will recreate the data.
     */
private static ShoppingCart loadCartForUpdate(LocalDispatcher dispatcher, Delegator delegator, GenericValue userLogin, String orderId) throws GeneralException {
    // load the order into a shopping cart
    Map<String, Object> loadCartResp = null;
    try {
        loadCartResp = dispatcher.runSync("loadCartFromOrder", UtilMisc.<String, Object>toMap("orderId", orderId, // the items are already reserved, no need to check again
        "skipInventoryChecks", // the items are already reserved, no need to check again
        Boolean.TRUE, // the products are already in the order, no need to check their validity now
        "skipProductChecks", // the products are already in the order, no need to check their validity now
        Boolean.TRUE, "userLogin", userLogin));
    } catch (GenericServiceException e) {
        Debug.logError(e, module);
        throw new GeneralException(e.getMessage());
    }
    if (ServiceUtil.isError(loadCartResp)) {
        throw new GeneralException(ServiceUtil.getErrorMessage(loadCartResp));
    }
    ShoppingCart cart = (ShoppingCart) loadCartResp.get("shoppingCart");
    if (cart == null) {
        throw new GeneralException("Error loading shopping cart from order [" + orderId + "]");
    }
    cart.setOrderId(orderId);
    // Now that the cart is loaded, all the data that will be re-created
    // when the method saveUpdatedCartToOrder(...) will be called, are
    // removed and cancelled:
    // - inventory reservations are cancelled
    // - promotional items are cancelled
    // - order payments are released (cancelled)
    // - offline non received payments are cancelled
    // - promotional, shipping and tax adjustments are removed
    // Inventory reservations
    // find ship group associations
    List<GenericValue> shipGroupAssocs = null;
    try {
        shipGroupAssocs = EntityQuery.use(delegator).from("OrderItemShipGroupAssoc").where("orderId", orderId).queryList();
    } catch (GenericEntityException e) {
        Debug.logError(e, module);
        throw new GeneralException(e.getMessage());
    }
    // cancel existing inventory reservations
    if (shipGroupAssocs != null) {
        for (GenericValue shipGroupAssoc : shipGroupAssocs) {
            String orderItemSeqId = shipGroupAssoc.getString("orderItemSeqId");
            String shipGroupSeqId = shipGroupAssoc.getString("shipGroupSeqId");
            Map<String, Object> cancelCtx = UtilMisc.<String, Object>toMap("userLogin", userLogin, "orderId", orderId);
            cancelCtx.put("orderItemSeqId", orderItemSeqId);
            cancelCtx.put("shipGroupSeqId", shipGroupSeqId);
            Map<String, Object> cancelResp = null;
            try {
                cancelResp = dispatcher.runSync("cancelOrderInventoryReservation", cancelCtx);
            } catch (GenericServiceException e) {
                Debug.logError(e, module);
                throw new GeneralException(e.getMessage());
            }
            if (ServiceUtil.isError(cancelResp)) {
                throw new GeneralException(ServiceUtil.getErrorMessage(cancelResp));
            }
        }
    }
    // cancel promo items -- if the promo still qualifies it will be added by the cart
    List<GenericValue> promoItems = null;
    try {
        promoItems = EntityQuery.use(delegator).from("OrderItem").where("orderId", orderId, "isPromo", "Y").queryList();
    } catch (GenericEntityException e) {
        Debug.logError(e, module);
        throw new GeneralException(e.getMessage());
    }
    if (promoItems != null) {
        for (GenericValue promoItem : promoItems) {
            // Skip if the promo is already cancelled
            if ("ITEM_CANCELLED".equals(promoItem.get("statusId"))) {
                continue;
            }
            Map<String, Object> cancelPromoCtx = UtilMisc.<String, Object>toMap("orderId", orderId);
            cancelPromoCtx.put("orderItemSeqId", promoItem.getString("orderItemSeqId"));
            cancelPromoCtx.put("userLogin", userLogin);
            Map<String, Object> cancelResp = null;
            try {
                cancelResp = dispatcher.runSync("cancelOrderItemNoActions", cancelPromoCtx);
            } catch (GenericServiceException e) {
                Debug.logError(e, module);
                throw new GeneralException(e.getMessage());
            }
            if (ServiceUtil.isError(cancelResp)) {
                throw new GeneralException(ServiceUtil.getErrorMessage(cancelResp));
            }
        }
    }
    // cancel exiting authorizations
    Map<String, Object> releaseResp = null;
    try {
        releaseResp = dispatcher.runSync("releaseOrderPayments", UtilMisc.<String, Object>toMap("orderId", orderId, "userLogin", userLogin));
    } catch (GenericServiceException e) {
        Debug.logError(e, module);
        throw new GeneralException(e.getMessage());
    }
    if (ServiceUtil.isError(releaseResp)) {
        throw new GeneralException(ServiceUtil.getErrorMessage(releaseResp));
    }
    // cancel other (non-completed and non-cancelled) payments
    List<GenericValue> paymentPrefsToCancel = null;
    try {
        List<EntityExpr> exprs = UtilMisc.toList(EntityCondition.makeCondition("orderId", EntityOperator.EQUALS, orderId));
        exprs.add(EntityCondition.makeCondition("statusId", EntityOperator.NOT_EQUAL, "PAYMENT_RECEIVED"));
        exprs.add(EntityCondition.makeCondition("statusId", EntityOperator.NOT_EQUAL, "PAYMENT_CANCELLED"));
        exprs.add(EntityCondition.makeCondition("statusId", EntityOperator.NOT_EQUAL, "PAYMENT_DECLINED"));
        exprs.add(EntityCondition.makeCondition("statusId", EntityOperator.NOT_EQUAL, "PAYMENT_SETTLED"));
        exprs.add(EntityCondition.makeCondition("statusId", EntityOperator.NOT_EQUAL, "PAYMENT_REFUNDED"));
        paymentPrefsToCancel = EntityQuery.use(delegator).from("OrderPaymentPreference").where(exprs).queryList();
    } catch (GenericEntityException e) {
        Debug.logError(e, module);
        throw new GeneralException(e.getMessage());
    }
    if (paymentPrefsToCancel != null) {
        for (GenericValue opp : paymentPrefsToCancel) {
            try {
                opp.set("statusId", "PAYMENT_CANCELLED");
                opp.store();
            } catch (GenericEntityException e) {
                Debug.logError(e, module);
                throw new GeneralException(e.getMessage());
            }
        }
    }
    // remove the adjustments
    try {
        List<EntityCondition> adjExprs = new LinkedList<>();
        adjExprs.add(EntityCondition.makeCondition("orderId", EntityOperator.EQUALS, orderId));
        List<EntityCondition> exprs = new LinkedList<>();
        exprs.add(EntityCondition.makeCondition("orderAdjustmentTypeId", EntityOperator.EQUALS, "PROMOTION_ADJUSTMENT"));
        exprs.add(EntityCondition.makeCondition("orderAdjustmentTypeId", EntityOperator.EQUALS, "SHIPPING_CHARGES"));
        exprs.add(EntityCondition.makeCondition("orderAdjustmentTypeId", EntityOperator.EQUALS, "SALES_TAX"));
        exprs.add(EntityCondition.makeCondition("orderAdjustmentTypeId", EntityOperator.EQUALS, "VAT_TAX"));
        exprs.add(EntityCondition.makeCondition("orderAdjustmentTypeId", EntityOperator.EQUALS, "VAT_PRICE_CORRECT"));
        adjExprs.add(EntityCondition.makeCondition(exprs, EntityOperator.OR));
        EntityCondition cond = EntityCondition.makeCondition(adjExprs, EntityOperator.AND);
        List<GenericValue> orderAdjustmentsToDelete = EntityQuery.use(delegator).from("OrderAdjustment").where(cond).queryList();
        List<GenericValue> orderAdjustmentsToStore = new LinkedList<>();
        List<GenericValue> orderAdjustmentsToRemove = new LinkedList<>();
        if (UtilValidate.isNotEmpty(orderAdjustmentsToDelete)) {
            for (GenericValue orderAdjustment : orderAdjustmentsToDelete) {
                // check if the adjustment has a related entry in entity OrderAdjustmentBilling
                List<GenericValue> oaBilling = orderAdjustment.getRelated("OrderAdjustmentBilling", null, null, false);
                if (UtilValidate.isNotEmpty(oaBilling)) {
                    orderAdjustmentsToRemove.add(orderAdjustment);
                    if ("SALES_TAX".equals(orderAdjustment.get("orderAdjustmentTypeId"))) {
                        // if the orderAdjustment is  a sale tax, set the amount to 0 to avoid amount addition
                        orderAdjustmentsToStore.add(orderAdjustment);
                    }
                }
            }
        }
        // then remove order Adjustment of the list
        if (UtilValidate.isNotEmpty(orderAdjustmentsToDelete)) {
            orderAdjustmentsToDelete.removeAll(orderAdjustmentsToRemove);
            delegator.removeAll(orderAdjustmentsToDelete);
        }
        if (UtilValidate.isNotEmpty(orderAdjustmentsToStore)) {
            for (GenericValue orderAdjustment : orderAdjustmentsToStore) {
                orderAdjustment.set("amount", BigDecimal.ZERO);
            }
            delegator.storeAll(orderAdjustmentsToStore);
        }
    } catch (GenericEntityException e) {
        Debug.logError(e, module);
        throw new GeneralException(e.getMessage());
    }
    return cart;
}
Also used : GenericValue(org.apache.ofbiz.entity.GenericValue) GeneralException(org.apache.ofbiz.base.util.GeneralException) EntityCondition(org.apache.ofbiz.entity.condition.EntityCondition) LinkedList(java.util.LinkedList) ShoppingCart(org.apache.ofbiz.order.shoppingcart.ShoppingCart) GenericEntityException(org.apache.ofbiz.entity.GenericEntityException) GenericServiceException(org.apache.ofbiz.service.GenericServiceException) EntityExpr(org.apache.ofbiz.entity.condition.EntityExpr)

Example 42 with EntityExpr

use of org.apache.ofbiz.entity.condition.EntityExpr in project ofbiz-framework by apache.

the class OrderServices method fulfillDigitalItems.

public static Map<String, Object> fulfillDigitalItems(DispatchContext ctx, Map<String, ? extends Object> context) {
    Delegator delegator = ctx.getDelegator();
    LocalDispatcher dispatcher = ctx.getDispatcher();
    // appears to not be used: String orderId = (String) context.get("orderId");
    List<GenericValue> orderItems = UtilGenerics.checkList(context.get("orderItems"));
    GenericValue userLogin = (GenericValue) context.get("userLogin");
    Locale locale = (Locale) context.get("locale");
    if (UtilValidate.isNotEmpty(orderItems)) {
        // loop through the digital items to fulfill
        for (GenericValue orderItem : orderItems) {
            // make sure we have a valid item
            if (orderItem == null) {
                return ServiceUtil.returnError(UtilProperties.getMessage(resource_error, "OrderErrorCannotCheckForFulfillmentItemNotFound", locale));
            }
            // locate the Product & ProductContent records
            GenericValue product = null;
            List<GenericValue> productContent = null;
            try {
                product = orderItem.getRelatedOne("Product", false);
                if (product == null) {
                    return ServiceUtil.returnError(UtilProperties.getMessage(resource_error, "OrderErrorCannotCheckForFulfillmentProductNotFound", locale));
                }
                List<EntityExpr> exprs = new ArrayList<>();
                exprs.add(EntityCondition.makeCondition("productContentTypeId", EntityOperator.IN, UtilMisc.toList("FULFILLMENT_EXTASYNC", "FULFILLMENT_EXTSYNC", "FULFILLMENT_EMAIL", "DIGITAL_DOWNLOAD")));
                exprs.add(EntityCondition.makeCondition("productId", EntityOperator.EQUALS, product.getString("productId")));
                // try looking up the parent product if the product has no content and is a variant
                List<GenericValue> allProductContent = EntityQuery.use(delegator).from("ProductContent").where(exprs).queryList();
                if (UtilValidate.isEmpty(allProductContent) && ("Y".equals(product.getString("isVariant")))) {
                    GenericValue parentProduct = ProductWorker.getParentProduct(product.getString("productId"), delegator);
                    if (allProductContent == null) {
                        allProductContent = new LinkedList<>();
                    }
                    if (parentProduct != null) {
                        allProductContent.addAll(parentProduct.getRelated("ProductContent", null, null, false));
                    }
                }
                if (UtilValidate.isNotEmpty(allProductContent)) {
                    // only keep ones with valid dates
                    productContent = EntityUtil.filterByDate(allProductContent, UtilDateTime.nowTimestamp(), "fromDate", "thruDate", true);
                    Debug.logInfo("Product has " + allProductContent.size() + " associations, " + (productContent == null ? "0" : "" + productContent.size()) + " has valid from/thru dates", module);
                }
            } catch (GenericEntityException e) {
                return ServiceUtil.returnError(UtilProperties.getMessage(resource_error, "OrderErrorCannotGetProductEntity", locale) + e.getMessage());
            }
            // now use the ProductContent to fulfill the item
            if (UtilValidate.isNotEmpty(productContent)) {
                for (GenericValue productContentItem : productContent) {
                    GenericValue content = null;
                    try {
                        content = productContentItem.getRelatedOne("Content", false);
                    } catch (GenericEntityException e) {
                        Debug.logError(e, "ERROR: Cannot get Content entity: " + e.getMessage(), module);
                        continue;
                    }
                    String fulfillmentType = productContentItem.getString("productContentTypeId");
                    if ("FULFILLMENT_EXTASYNC".equals(fulfillmentType) || "FULFILLMENT_EXTSYNC".equals(fulfillmentType)) {
                        // external service fulfillment
                        // Kept for backward compatibility
                        String fulfillmentService = (String) content.get("serviceName");
                        GenericValue custMethod = null;
                        if (UtilValidate.isNotEmpty(content.getString("customMethodId"))) {
                            try {
                                custMethod = EntityQuery.use(delegator).from("CustomMethod").where("customMethodId", content.get("customMethodId")).cache().queryOne();
                            } catch (GenericEntityException e) {
                                Debug.logError(e, "ERROR: Cannot get CustomMethod associate to Content entity: " + e.getMessage(), module);
                                continue;
                            }
                        }
                        if (custMethod != null) {
                            fulfillmentService = custMethod.getString("customMethodName");
                        }
                        if (fulfillmentService == null) {
                            Debug.logError("ProductContent of type FULFILLMENT_EXTERNAL had Content with empty serviceName, can not run fulfillment", module);
                        }
                        Map<String, Object> serviceCtx = UtilMisc.<String, Object>toMap("userLogin", userLogin, "orderItem", orderItem);
                        serviceCtx.putAll(productContentItem.getPrimaryKey());
                        try {
                            Debug.logInfo("Running external fulfillment '" + fulfillmentService + "'", module);
                            if ("FULFILLMENT_EXTASYNC".equals(fulfillmentType)) {
                                dispatcher.runAsync(fulfillmentService, serviceCtx, true);
                            } else if ("FULFILLMENT_EXTSYNC".equals(fulfillmentType)) {
                                Map<String, Object> resp = dispatcher.runSync(fulfillmentService, serviceCtx);
                                if (ServiceUtil.isError(resp)) {
                                    return ServiceUtil.returnError(UtilProperties.getMessage(resource, "OrderOrderExternalFulfillmentError", locale), null, null, resp);
                                }
                            }
                        } catch (GenericServiceException e) {
                            Debug.logError(e, "ERROR: Could not run external fulfillment service '" + fulfillmentService + "'; " + e.getMessage(), module);
                        }
                    } else if ("FULFILLMENT_EMAIL".equals(fulfillmentType)) {
                        // TODO: Add support for fulfillment email
                        return ServiceUtil.returnError(UtilProperties.getMessage(resource_error, "OrderEmailFulfillmentTypeNotYetImplemented", locale));
                    } else if ("DIGITAL_DOWNLOAD".equals(fulfillmentType)) {
                    // digital download fulfillment
                    // Nothing to do for here. Downloads are made available to the user
                    // though a query of OrderItems with related ProductContent.
                    } else {
                        Debug.logError("Invalid fulfillment type : " + fulfillmentType + " not supported.", module);
                    }
                }
            }
        }
    }
    return ServiceUtil.returnSuccess();
}
Also used : Locale(java.util.Locale) GenericValue(org.apache.ofbiz.entity.GenericValue) LocalDispatcher(org.apache.ofbiz.service.LocalDispatcher) ArrayList(java.util.ArrayList) Delegator(org.apache.ofbiz.entity.Delegator) GenericEntityException(org.apache.ofbiz.entity.GenericEntityException) GenericServiceException(org.apache.ofbiz.service.GenericServiceException) Map(java.util.Map) HashMap(java.util.HashMap) EntityExpr(org.apache.ofbiz.entity.condition.EntityExpr)

Example 43 with EntityExpr

use of org.apache.ofbiz.entity.condition.EntityExpr in project ofbiz-framework by apache.

the class OrderServices method setEmptyGrandTotals.

/**
 * Service for setting the OrderHeader grandTotal for all OrderHeaders with no grandTotal
 */
public static Map<String, Object> setEmptyGrandTotals(DispatchContext ctx, Map<String, ? extends Object> context) {
    Delegator delegator = ctx.getDelegator();
    LocalDispatcher dispatcher = ctx.getDispatcher();
    GenericValue userLogin = (GenericValue) context.get("userLogin");
    Boolean forceAll = (Boolean) context.get("forceAll");
    Locale locale = (Locale) context.get("locale");
    if (forceAll == null) {
        forceAll = Boolean.FALSE;
    }
    EntityCondition cond = null;
    if (!forceAll.booleanValue()) {
        List<EntityExpr> exprs = UtilMisc.toList(EntityCondition.makeCondition("grandTotal", EntityOperator.EQUALS, null), EntityCondition.makeCondition("remainingSubTotal", EntityOperator.EQUALS, null));
        cond = EntityCondition.makeCondition(exprs, EntityOperator.OR);
    }
    try (EntityListIterator eli = EntityQuery.use(delegator).select("orderId").from("OrderHeader").where(cond).queryIterator()) {
        if (eli != null) {
            // reset each order
            GenericValue orderHeader = null;
            while ((orderHeader = eli.next()) != null) {
                String orderId = orderHeader.getString("orderId");
                Map<String, Object> resetResult = null;
                try {
                    resetResult = dispatcher.runSync("resetGrandTotal", UtilMisc.<String, Object>toMap("orderId", orderId, "userLogin", userLogin));
                    if (ServiceUtil.isError(resetResult)) {
                        return ServiceUtil.returnError(ServiceUtil.getErrorMessage(resetResult));
                    }
                } catch (GenericServiceException e) {
                    Debug.logError(e, "ERROR: Cannot reset order totals - " + orderId, module);
                }
                if (resetResult != null && ServiceUtil.isError(resetResult)) {
                    Debug.logWarning(UtilProperties.getMessage(resource_error, "OrderErrorCannotResetOrderTotals", UtilMisc.toMap("orderId", orderId, "resetResult", ServiceUtil.getErrorMessage(resetResult)), locale), module);
                } else {
                    Debug.logInfo("No orders found for reset processing", module);
                }
            }
        }
    } catch (GenericEntityException e) {
        Debug.logError(e, module);
    }
    return ServiceUtil.returnSuccess();
}
Also used : Locale(java.util.Locale) GenericValue(org.apache.ofbiz.entity.GenericValue) LocalDispatcher(org.apache.ofbiz.service.LocalDispatcher) EntityCondition(org.apache.ofbiz.entity.condition.EntityCondition) Delegator(org.apache.ofbiz.entity.Delegator) GenericEntityException(org.apache.ofbiz.entity.GenericEntityException) GenericServiceException(org.apache.ofbiz.service.GenericServiceException) EntityListIterator(org.apache.ofbiz.entity.util.EntityListIterator) EntityExpr(org.apache.ofbiz.entity.condition.EntityExpr)

Example 44 with EntityExpr

use of org.apache.ofbiz.entity.condition.EntityExpr in project ofbiz-framework by apache.

the class OrderServices method createAlsoBoughtProductAssocs.

public static Map<String, Object> createAlsoBoughtProductAssocs(DispatchContext dctx, Map<String, ? extends Object> context) {
    final Delegator delegator = dctx.getDelegator();
    LocalDispatcher dispatcher = dctx.getDispatcher();
    // All orders with an entryDate > orderEntryFromDateTime will be processed
    Timestamp orderEntryFromDateTime = (Timestamp) context.get("orderEntryFromDateTime");
    // If true all orders ever created will be processed and any pre-existing ALSO_BOUGHT ProductAssocs will be expired
    boolean processAllOrders = context.get("processAllOrders") == null ? false : (Boolean) context.get("processAllOrders");
    if (orderEntryFromDateTime == null && !processAllOrders) {
        // No from date supplied, check to see when this service last ran and use the startDateTime
        // FIXME: This code is unreliable - the JobSandbox value might have been purged. Use another mechanism to persist orderEntryFromDateTime.
        EntityCondition cond = EntityCondition.makeCondition(UtilMisc.toMap("statusId", "SERVICE_FINISHED", "serviceName", "createAlsoBoughtProductAssocs"));
        EntityFindOptions efo = new EntityFindOptions();
        efo.setMaxRows(1);
        try {
            GenericValue lastRunJobSandbox = EntityUtil.getFirst(delegator.findList("JobSandbox", cond, null, UtilMisc.toList("startDateTime DESC"), efo, false));
            if (lastRunJobSandbox != null) {
                orderEntryFromDateTime = lastRunJobSandbox.getTimestamp("startDateTime");
            }
        } catch (GenericEntityException e) {
            Debug.logError(e, module);
        }
        if (orderEntryFromDateTime == null) {
            // Still null, process all orders
            processAllOrders = true;
        }
    }
    if (processAllOrders) {
        // Expire any pre-existing ALSO_BOUGHT ProductAssocs in preparation for reprocessing
        EntityCondition cond = EntityCondition.makeCondition(UtilMisc.toList(EntityCondition.makeCondition("productAssocTypeId", "ALSO_BOUGHT"), EntityCondition.makeConditionDate("fromDate", "thruDate")));
        try {
            delegator.storeByCondition("ProductAssoc", UtilMisc.toMap("thruDate", UtilDateTime.nowTimestamp()), cond);
        } catch (GenericEntityException e) {
            Debug.logError(e, module);
        }
    }
    List<EntityExpr> orderCondList = UtilMisc.toList(EntityCondition.makeCondition("orderTypeId", "SALES_ORDER"));
    if (!processAllOrders && orderEntryFromDateTime != null) {
        orderCondList.add(EntityCondition.makeCondition("entryDate", EntityOperator.GREATER_THAN, orderEntryFromDateTime));
    }
    final EntityCondition cond = EntityCondition.makeCondition(orderCondList);
    List<String> orderIds;
    try {
        orderIds = TransactionUtil.doNewTransaction(new Callable<List<String>>() {

            @Override
            public List<String> call() throws Exception {
                List<String> orderIds = new LinkedList<>();
                EntityQuery eq = EntityQuery.use(delegator).select("orderId").from("OrderHeader").where(cond).orderBy("entryDate ASC");
                try (EntityListIterator eli = eq.queryIterator()) {
                    GenericValue orderHeader;
                    while ((orderHeader = eli.next()) != null) {
                        orderIds.add(orderHeader.getString("orderId"));
                    }
                }
                return orderIds;
            }
        }, "getSalesOrderIds", 0, true);
    } catch (GenericEntityException e) {
        Debug.logError(e, module);
        return ServiceUtil.returnError(e.getMessage());
    }
    for (String orderId : orderIds) {
        Map<String, Object> svcIn = new HashMap<>();
        svcIn.put("userLogin", context.get("userLogin"));
        svcIn.put("orderId", orderId);
        try {
            Map<String, Object> serviceResult = dispatcher.runSync("createAlsoBoughtProductAssocsForOrder", svcIn);
            if (ServiceUtil.isError(serviceResult)) {
                return ServiceUtil.returnError(ServiceUtil.getErrorMessage(serviceResult));
            }
        } catch (GenericServiceException e) {
            Debug.logError(e, module);
        }
    }
    return ServiceUtil.returnSuccess();
}
Also used : GenericValue(org.apache.ofbiz.entity.GenericValue) LocalDispatcher(org.apache.ofbiz.service.LocalDispatcher) HashMap(java.util.HashMap) EntityCondition(org.apache.ofbiz.entity.condition.EntityCondition) EntityQuery(org.apache.ofbiz.entity.util.EntityQuery) Timestamp(java.sql.Timestamp) Callable(java.util.concurrent.Callable) LinkedList(java.util.LinkedList) Delegator(org.apache.ofbiz.entity.Delegator) EntityFindOptions(org.apache.ofbiz.entity.util.EntityFindOptions) GenericEntityException(org.apache.ofbiz.entity.GenericEntityException) GenericServiceException(org.apache.ofbiz.service.GenericServiceException) EntityListIterator(org.apache.ofbiz.entity.util.EntityListIterator) EntityExpr(org.apache.ofbiz.entity.condition.EntityExpr)

Example 45 with EntityExpr

use of org.apache.ofbiz.entity.condition.EntityExpr in project ofbiz-framework by apache.

the class RequirementServices method createATPRequirementsForOrder.

// note that this service is designed to work only when a sales order status changes from CREATED -> APPROVED because HOLD -> APPROVED is too complex
public static Map<String, Object> createATPRequirementsForOrder(DispatchContext ctx, Map<String, ? extends Object> context) {
    Delegator delegator = ctx.getDelegator();
    LocalDispatcher dispatcher = ctx.getDispatcher();
    GenericValue userLogin = (GenericValue) context.get("userLogin");
    /*
         * The strategy in this service is to begin making requirements when the product falls below the
         * ProductFacility.minimumStock.  Because the minimumStock is an upper bound, the quantity to be required
         * is either that required to bring the ATP back up to the minimumStock level or the amount ordered,
         * whichever is less.
         *
         * If there is a way to support reorderQuantity without losing the order item -> requirement association data,
         * then this service should be updated.
         *
         * The result is that this service generates many small requirements when stock levels are low for a product,
         * which is perfectly fine since the system is capable of creating POs in bulk from aggregate requirements.
         * The only concern would be a UI to manage numerous requirements with ease, preferrably by aggregating
         * on productId.
         */
    String orderId = (String) context.get("orderId");
    try {
        GenericValue order = EntityQuery.use(delegator).from("OrderHeader").where("orderId", orderId).queryOne();
        GenericValue productStore = order.getRelatedOne("ProductStore", true);
        if (productStore == null) {
            Debug.logInfo("ProductStore for order ID " + orderId + " not found, ATP requirements not created", module);
            return ServiceUtil.returnSuccess();
        }
        String facilityId = productStore.getString("inventoryFacilityId");
        List<GenericValue> orderItems = order.getRelated("OrderItem", null, null, false);
        for (GenericValue item : orderItems) {
            GenericValue product = item.getRelatedOne("Product", false);
            if (product == null)
                continue;
            if (!("PRODRQM_ATP".equals(product.get("requirementMethodEnumId")) || ("PRODRQM_ATP".equals(productStore.get("requirementMethodEnumId")) && product.get("requirementMethodEnumId") == null)))
                continue;
            BigDecimal quantity = item.getBigDecimal("quantity");
            BigDecimal cancelQuantity = item.getBigDecimal("cancelQuantity");
            BigDecimal ordered = quantity.subtract(cancelQuantity == null ? BigDecimal.ZERO : cancelQuantity);
            if (ordered.compareTo(BigDecimal.ZERO) <= 0)
                continue;
            // get the minimum stock for this facility (if not configured assume a minimum of zero, ie create requirements when it goes into backorder)
            GenericValue productFacility = EntityQuery.use(delegator).from("ProductFacility").where("facilityId", facilityId, "productId", product.get("productId")).queryOne();
            BigDecimal minimumStock = BigDecimal.ZERO;
            if (productFacility != null && productFacility.get("minimumStock") != null) {
                minimumStock = productFacility.getBigDecimal("minimumStock");
            }
            // get the facility ATP for product, which should be updated for this item's reservation
            Map<String, Object> results = dispatcher.runSync("getInventoryAvailableByFacility", UtilMisc.toMap("userLogin", userLogin, "productId", product.get("productId"), "facilityId", facilityId));
            if (ServiceUtil.isError(results)) {
                return ServiceUtil.returnError(ServiceUtil.getErrorMessage(results));
            }
            // safe since this is a required OUT param
            BigDecimal atp = ((BigDecimal) results.get("availableToPromiseTotal"));
            // count all current requirements for this product
            BigDecimal pendingRequirements = BigDecimal.ZERO;
            EntityConditionList<EntityExpr> ecl = EntityCondition.makeCondition(UtilMisc.toList(EntityCondition.makeCondition("facilityId", EntityOperator.EQUALS, facilityId), EntityCondition.makeCondition("productId", EntityOperator.EQUALS, product.get("productId")), EntityCondition.makeCondition("requirementTypeId", EntityOperator.EQUALS, "PRODUCT_REQUIREMENT"), EntityCondition.makeCondition("statusId", EntityOperator.NOT_EQUAL, "REQ_ORDERED"), EntityCondition.makeCondition("statusId", EntityOperator.NOT_EQUAL, "REQ_REJECTED")), EntityOperator.AND);
            List<GenericValue> requirements = EntityQuery.use(delegator).from("Requirement").where(ecl).queryList();
            for (GenericValue requirement : requirements) {
                pendingRequirements = pendingRequirements.add(requirement.get("quantity") == null ? BigDecimal.ZERO : requirement.getBigDecimal("quantity"));
            }
            // the minimum stock is an upper bound, therefore we either require up to the minimum stock or the input required quantity, whichever is less
            BigDecimal shortfall = minimumStock.subtract(atp).subtract(pendingRequirements);
            BigDecimal required = ordered.compareTo(shortfall) < 0 ? ordered : shortfall;
            if (required.compareTo(BigDecimal.ZERO) <= 0)
                continue;
            Map<String, Object> input = UtilMisc.toMap("userLogin", userLogin, "facilityId", facilityId, "productId", product.get("productId"), "quantity", required, "requirementTypeId", "PRODUCT_REQUIREMENT");
            results = dispatcher.runSync("createRequirement", input);
            if (ServiceUtil.isError(results)) {
                return ServiceUtil.returnError(ServiceUtil.getErrorMessage(results));
            }
            String requirementId = (String) results.get("requirementId");
            input = UtilMisc.toMap("userLogin", userLogin, "orderId", order.get("orderId"), "orderItemSeqId", item.get("orderItemSeqId"), "requirementId", requirementId, "quantity", required);
            results = dispatcher.runSync("createOrderRequirementCommitment", input);
            if (ServiceUtil.isError(results)) {
                return ServiceUtil.returnError(ServiceUtil.getErrorMessage(results));
            }
        }
    } catch (GenericEntityException e) {
        Debug.logError(e, module);
    } catch (GenericServiceException e) {
        Debug.logError(e, module);
    }
    return ServiceUtil.returnSuccess();
}
Also used : GenericValue(org.apache.ofbiz.entity.GenericValue) LocalDispatcher(org.apache.ofbiz.service.LocalDispatcher) Delegator(org.apache.ofbiz.entity.Delegator) GenericEntityException(org.apache.ofbiz.entity.GenericEntityException) GenericServiceException(org.apache.ofbiz.service.GenericServiceException) BigDecimal(java.math.BigDecimal) EntityExpr(org.apache.ofbiz.entity.condition.EntityExpr)

Aggregations

EntityExpr (org.apache.ofbiz.entity.condition.EntityExpr)57 GenericValue (org.apache.ofbiz.entity.GenericValue)51 GenericEntityException (org.apache.ofbiz.entity.GenericEntityException)47 Delegator (org.apache.ofbiz.entity.Delegator)29 LinkedList (java.util.LinkedList)27 HashMap (java.util.HashMap)24 Locale (java.util.Locale)23 BigDecimal (java.math.BigDecimal)19 EntityCondition (org.apache.ofbiz.entity.condition.EntityCondition)18 GenericServiceException (org.apache.ofbiz.service.GenericServiceException)16 LocalDispatcher (org.apache.ofbiz.service.LocalDispatcher)15 Timestamp (java.sql.Timestamp)13 ArrayList (java.util.ArrayList)11 GeneralException (org.apache.ofbiz.base.util.GeneralException)7 List (java.util.List)6 Map (java.util.Map)6 EntityListIterator (org.apache.ofbiz.entity.util.EntityListIterator)6 Calendar (com.ibm.icu.util.Calendar)4 LinkedHashSet (java.util.LinkedHashSet)4 EntityConditionList (org.apache.ofbiz.entity.condition.EntityConditionList)4