Search in sources :

Example 1 with ShoppingCartItem

use of org.apache.ofbiz.order.shoppingcart.ShoppingCartItem in project ofbiz-framework by apache.

the class PayPalServices method getExpressCheckout.

public static Map<String, Object> getExpressCheckout(DispatchContext dctx, Map<String, Object> context) {
    Locale locale = (Locale) context.get("locale");
    LocalDispatcher dispatcher = dctx.getDispatcher();
    Delegator delegator = dctx.getDelegator();
    ShoppingCart cart = (ShoppingCart) context.get("cart");
    GenericValue payPalConfig = getPaymentMethodGatewayPayPal(dctx, context, null);
    if (payPalConfig == null) {
        return ServiceUtil.returnError(UtilProperties.getMessage(resource, "AccountingPayPalPaymentGatewayConfigCannotFind", locale));
    }
    NVPEncoder encoder = new NVPEncoder();
    encoder.add("METHOD", "GetExpressCheckoutDetails");
    String token = (String) cart.getAttribute("payPalCheckoutToken");
    if (UtilValidate.isNotEmpty(token)) {
        encoder.add("TOKEN", token);
    } else {
        return ServiceUtil.returnError(UtilProperties.getMessage(resource, "AccountingPayPalTokenNotFound", locale));
    }
    NVPDecoder decoder;
    try {
        decoder = sendNVPRequest(payPalConfig, encoder);
    } catch (PayPalException e) {
        Debug.logError(e, module);
        return ServiceUtil.returnError(e.getMessage());
    }
    if (UtilValidate.isNotEmpty(decoder.get("NOTE"))) {
        cart.addOrderNote(decoder.get("NOTE"));
    }
    if (cart.getUserLogin() == null) {
        try {
            GenericValue userLogin = EntityQuery.use(delegator).from("UserLogin").where("userLoginId", "anonymous").queryOne();
            try {
                cart.setUserLogin(userLogin, dispatcher);
            } catch (CartItemModifyException e) {
                Debug.logError(e, module);
                return ServiceUtil.returnError(e.getMessage());
            }
        } catch (GenericEntityException e) {
            Debug.logError(e, module);
            return ServiceUtil.returnError(e.getMessage());
        }
    }
    boolean anon = "anonymous".equals(cart.getUserLogin().getString("userLoginId"));
    // Even if anon, a party could already have been created
    String partyId = cart.getOrderPartyId();
    if (partyId == null && anon) {
        // Check nothing has been set on the anon userLogin either
        partyId = cart.getUserLogin() != null ? cart.getUserLogin().getString("partyId") : null;
        cart.setOrderPartyId(partyId);
    }
    if (partyId != null) {
        GenericValue party = null;
        try {
            party = EntityQuery.use(delegator).from("Party").where("partyId", partyId).queryOne();
        } catch (GenericEntityException e) {
            Debug.logError(e, module);
        }
        if (party == null) {
            partyId = null;
        }
    }
    Map<String, Object> inMap = new HashMap<String, Object>();
    Map<String, Object> outMap = null;
    // Create the person if necessary
    boolean newParty = false;
    if (partyId == null) {
        newParty = true;
        inMap.put("userLogin", cart.getUserLogin());
        inMap.put("personalTitle", decoder.get("SALUTATION"));
        inMap.put("firstName", decoder.get("FIRSTNAME"));
        inMap.put("middleName", decoder.get("MIDDLENAME"));
        inMap.put("lastName", decoder.get("LASTNAME"));
        inMap.put("suffix", decoder.get("SUFFIX"));
        try {
            outMap = dispatcher.runSync("createPerson", inMap);
            partyId = (String) outMap.get("partyId");
            cart.setOrderPartyId(partyId);
            cart.getUserLogin().setString("partyId", partyId);
            inMap.clear();
            inMap.put("userLogin", cart.getUserLogin());
            inMap.put("partyId", partyId);
            inMap.put("roleTypeId", "CUSTOMER");
            dispatcher.runSync("createPartyRole", inMap);
        } catch (GenericServiceException e) {
            Debug.logError(e, module);
            return ServiceUtil.returnError(e.getMessage());
        }
    }
    // Create a new email address if necessary
    String emailContactMechId = null;
    String emailContactPurposeTypeId = "PRIMARY_EMAIL";
    String emailAddress = decoder.get("EMAIL");
    if (!newParty) {
        EntityCondition cond = EntityCondition.makeCondition(UtilMisc.toList(EntityCondition.makeCondition(UtilMisc.toMap("partyId", partyId, "contactMechTypeId", "EMAIL_ADDRESS")), EntityCondition.makeCondition(EntityFunction.UPPER_FIELD("infoString"), EntityComparisonOperator.EQUALS, EntityFunction.UPPER(emailAddress))));
        try {
            GenericValue matchingEmail = EntityQuery.use(delegator).from("PartyAndContactMech").where(cond).orderBy("fromDate").filterByDate().queryFirst();
            if (matchingEmail != null) {
                emailContactMechId = matchingEmail.getString("contactMechId");
            } else {
                // No email found so we'll need to create one but first check if it should be PRIMARY or just BILLING
                long primaryEmails = EntityQuery.use(delegator).from("PartyContactWithPurpose").where("partyId", partyId, "contactMechTypeId", "EMAIL_ADDRESS", "contactMechPurposeTypeId", "PRIMARY_EMAIL").filterByDate("contactFromDate", "contactThruDate", "purposeFromDate", "purposeThruDate").queryCount();
                if (primaryEmails > 0)
                    emailContactPurposeTypeId = "BILLING_EMAIL";
            }
        } catch (GenericEntityException e) {
            Debug.logError(e, module);
        }
    }
    if (emailContactMechId == null) {
        inMap.clear();
        inMap.put("userLogin", cart.getUserLogin());
        inMap.put("contactMechPurposeTypeId", emailContactPurposeTypeId);
        inMap.put("emailAddress", emailAddress);
        inMap.put("partyId", partyId);
        inMap.put("roleTypeId", "CUSTOMER");
        // Going to assume PayPal has taken care of this for us
        inMap.put("verified", "Y");
        inMap.put("fromDate", UtilDateTime.nowTimestamp());
        try {
            outMap = dispatcher.runSync("createPartyEmailAddress", inMap);
            emailContactMechId = (String) outMap.get("contactMechId");
        } catch (GenericServiceException e) {
            Debug.logError(e, module);
            return ServiceUtil.returnError(e.getMessage());
        }
    }
    cart.addContactMech("ORDER_EMAIL", emailContactMechId);
    // Phone number
    String phoneNumber = decoder.get("PHONENUM");
    String phoneContactId = null;
    if (phoneNumber != null) {
        inMap.clear();
        if (phoneNumber.startsWith("+")) {
            // International, format is +XXX XXXXXXXX which we'll split into countryCode + contactNumber
            String[] phoneNumbers = phoneNumber.split(" ");
            inMap.put("countryCode", StringUtil.removeNonNumeric(phoneNumbers[0]));
            inMap.put("contactNumber", phoneNumbers[1]);
        } else {
            // U.S., format is XXX-XXX-XXXX which we'll split into areaCode + contactNumber
            inMap.put("countryCode", "1");
            String[] phoneNumbers = phoneNumber.split("-");
            inMap.put("areaCode", phoneNumbers[0]);
            inMap.put("contactNumber", phoneNumbers[1] + phoneNumbers[2]);
        }
        inMap.put("userLogin", cart.getUserLogin());
        inMap.put("partyId", partyId);
        try {
            outMap = dispatcher.runSync("createUpdatePartyTelecomNumber", inMap);
            phoneContactId = (String) outMap.get("contactMechId");
            cart.addContactMech("PHONE_BILLING", phoneContactId);
        } catch (GenericServiceException e) {
            Debug.logError(e, module);
        }
    }
    // Create a new Postal Address if necessary
    String postalContactId = null;
    boolean needsShippingPurpose = true;
    // if the cart for some reason already has a billing address, we'll leave it be
    boolean needsBillingPurpose = (cart.getContactMech("BILLING_LOCATION") == null);
    Map<String, Object> postalMap = new HashMap<String, Object>();
    postalMap.put("toName", decoder.get("SHIPTONAME"));
    postalMap.put("address1", decoder.get("SHIPTOSTREET"));
    postalMap.put("address2", decoder.get("SHIPTOSTREET2"));
    postalMap.put("city", decoder.get("SHIPTOCITY"));
    String countryGeoId = PayPalServices.getCountryGeoIdFromGeoCode(decoder.get("SHIPTOCOUNTRYCODE"), delegator);
    postalMap.put("countryGeoId", countryGeoId);
    postalMap.put("stateProvinceGeoId", parseStateProvinceGeoId(decoder.get("SHIPTOSTATE"), countryGeoId, delegator));
    postalMap.put("postalCode", decoder.get("SHIPTOZIP"));
    if (!newParty) {
        // We want an exact match only
        EntityCondition cond = EntityCondition.makeCondition(UtilMisc.toList(EntityCondition.makeCondition(postalMap), EntityCondition.makeCondition(UtilMisc.toMap("attnName", null, "directions", null, "postalCodeExt", null, "postalCodeGeoId", null)), EntityCondition.makeCondition("partyId", partyId)));
        try {
            GenericValue postalMatch = EntityQuery.use(delegator).from("PartyAndPostalAddress").where(cond).orderBy("fromDate").filterByDate().queryFirst();
            if (postalMatch != null) {
                postalContactId = postalMatch.getString("contactMechId");
                List<GenericValue> postalPurposes = EntityQuery.use(delegator).from("PartyContactMechPurpose").where("partyId", partyId, "contactMechId", postalContactId).filterByDate().queryList();
                List<Object> purposeStrings = EntityUtil.getFieldListFromEntityList(postalPurposes, "contactMechPurposeTypeId", false);
                if (UtilValidate.isNotEmpty(purposeStrings) && purposeStrings.contains("SHIPPING_LOCATION")) {
                    needsShippingPurpose = false;
                }
                if (needsBillingPurpose && UtilValidate.isNotEmpty(purposeStrings) && purposeStrings.contains("BILLING_LOCATION")) {
                    needsBillingPurpose = false;
                }
            }
        } catch (GenericEntityException e) {
            Debug.logError(e, module);
        }
    }
    if (postalContactId == null) {
        postalMap.put("userLogin", cart.getUserLogin());
        postalMap.put("fromDate", UtilDateTime.nowTimestamp());
        try {
            outMap = dispatcher.runSync("createPartyPostalAddress", postalMap);
            postalContactId = (String) outMap.get("contactMechId");
        } catch (GenericServiceException e) {
            Debug.logError(e, module);
            return ServiceUtil.returnError(e.getMessage());
        }
    }
    if (needsShippingPurpose || needsBillingPurpose) {
        inMap.clear();
        inMap.put("userLogin", cart.getUserLogin());
        inMap.put("contactMechId", postalContactId);
        inMap.put("partyId", partyId);
        try {
            if (needsShippingPurpose) {
                inMap.put("contactMechPurposeTypeId", "SHIPPING_LOCATION");
                dispatcher.runSync("createPartyContactMechPurpose", inMap);
            }
            if (needsBillingPurpose) {
                inMap.put("contactMechPurposeTypeId", "BILLING_LOCATION");
                dispatcher.runSync("createPartyContactMechPurpose", inMap);
            }
        } catch (GenericServiceException e) {
            // Not the end of the world, we'll carry on
            Debug.logInfo(e.getMessage(), module);
        }
    }
    // Load the selected shipping method - thanks to PayPal's less than sane API all we've to work with is the shipping option label
    // that was shown to the customer
    String shipMethod = decoder.get("SHIPPINGOPTIONNAME");
    if ("Calculated Offline".equals(shipMethod)) {
        cart.setAllCarrierPartyId("_NA_");
        cart.setAllShipmentMethodTypeId("NO_SHIPPING");
    } else {
        String[] shipMethodSplit = shipMethod.split(" - ");
        cart.setAllCarrierPartyId(shipMethodSplit[0]);
        String shippingMethodTypeDesc = StringUtils.join(shipMethodSplit, " - ", 1, shipMethodSplit.length);
        try {
            GenericValue shipmentMethod = EntityQuery.use(delegator).from("ProductStoreShipmentMethView").where("productStoreId", cart.getProductStoreId(), "partyId", shipMethodSplit[0], "roleTypeId", "CARRIER", "description", shippingMethodTypeDesc).queryFirst();
            cart.setAllShipmentMethodTypeId(shipmentMethod.getString("shipmentMethodTypeId"));
        } catch (GenericEntityException e1) {
            Debug.logError(e1, module);
        }
    }
    // Get rid of any excess ship groups
    List<CartShipInfo> shipGroups = cart.getShipGroups();
    for (int i = 1; i < shipGroups.size(); i++) {
        Map<ShoppingCartItem, BigDecimal> items = cart.getShipGroupItems(i);
        for (Map.Entry<ShoppingCartItem, BigDecimal> entry : items.entrySet()) {
            cart.positionItemToGroup(entry.getKey(), entry.getValue(), i, 0, false);
        }
    }
    cart.cleanUpShipGroups();
    cart.setAllShippingContactMechId(postalContactId);
    Map<String, Object> result = ShippingEvents.getShipGroupEstimate(dispatcher, delegator, cart, 0);
    if (result.get(ModelService.RESPONSE_MESSAGE).equals(ModelService.RESPOND_ERROR)) {
        return ServiceUtil.returnError((String) result.get(ModelService.ERROR_MESSAGE));
    }
    BigDecimal shippingTotal = (BigDecimal) result.get("shippingTotal");
    if (shippingTotal == null) {
        shippingTotal = BigDecimal.ZERO;
    }
    cart.setItemShipGroupEstimate(shippingTotal, 0);
    CheckOutHelper cho = new CheckOutHelper(dispatcher, delegator, cart);
    try {
        cho.calcAndAddTax();
    } catch (GeneralException e) {
        Debug.logError(e, module);
        return ServiceUtil.returnError(e.getMessage());
    }
    // Create the PayPal payment method
    inMap.clear();
    inMap.put("userLogin", cart.getUserLogin());
    inMap.put("partyId", partyId);
    inMap.put("contactMechId", postalContactId);
    inMap.put("fromDate", UtilDateTime.nowTimestamp());
    inMap.put("payerId", decoder.get("PAYERID"));
    inMap.put("expressCheckoutToken", token);
    inMap.put("payerStatus", decoder.get("PAYERSTATUS"));
    try {
        outMap = dispatcher.runSync("createPayPalPaymentMethod", inMap);
    } catch (GenericServiceException e) {
        Debug.logError(e, module);
        return ServiceUtil.returnError(e.getMessage());
    }
    String paymentMethodId = (String) outMap.get("paymentMethodId");
    cart.clearPayments();
    BigDecimal maxAmount = cart.getGrandTotal().setScale(2, RoundingMode.HALF_UP);
    cart.addPaymentAmount(paymentMethodId, maxAmount, true);
    return ServiceUtil.returnSuccess();
}
Also used : Locale(java.util.Locale) LocalDispatcher(org.apache.ofbiz.service.LocalDispatcher) HashMap(java.util.HashMap) WeakHashMap(java.util.WeakHashMap) EntityCondition(org.apache.ofbiz.entity.condition.EntityCondition) CartShipInfo(org.apache.ofbiz.order.shoppingcart.ShoppingCart.CartShipInfo) NVPEncoder(com.paypal.sdk.core.nvp.NVPEncoder) GenericValue(org.apache.ofbiz.entity.GenericValue) GeneralException(org.apache.ofbiz.base.util.GeneralException) PayPalException(com.paypal.sdk.exceptions.PayPalException) CheckOutHelper(org.apache.ofbiz.order.shoppingcart.CheckOutHelper) BigDecimal(java.math.BigDecimal) Delegator(org.apache.ofbiz.entity.Delegator) ShoppingCart(org.apache.ofbiz.order.shoppingcart.ShoppingCart) CartItemModifyException(org.apache.ofbiz.order.shoppingcart.CartItemModifyException) GenericEntityException(org.apache.ofbiz.entity.GenericEntityException) NVPDecoder(com.paypal.sdk.core.nvp.NVPDecoder) GenericServiceException(org.apache.ofbiz.service.GenericServiceException) ShoppingCartItem(org.apache.ofbiz.order.shoppingcart.ShoppingCartItem) Map(java.util.Map) HashMap(java.util.HashMap) WeakHashMap(java.util.WeakHashMap)

Example 2 with ShoppingCartItem

use of org.apache.ofbiz.order.shoppingcart.ShoppingCartItem in project ofbiz-framework by apache.

the class OrderServices method runSubscriptionAutoReorders.

public static Map<String, Object> runSubscriptionAutoReorders(DispatchContext dctx, Map<String, ? extends Object> context) {
    LocalDispatcher dispatcher = dctx.getDispatcher();
    Delegator delegator = dctx.getDelegator();
    GenericValue userLogin = (GenericValue) context.get("userLogin");
    Locale locale = (Locale) context.get("locale");
    int count = 0;
    Map<String, Object> result = null;
    boolean beganTransaction = false;
    List<EntityExpr> exprs = UtilMisc.toList(EntityCondition.makeCondition("automaticExtend", EntityOperator.EQUALS, "Y"), EntityCondition.makeCondition("orderId", EntityOperator.NOT_EQUAL, null), EntityCondition.makeCondition("productId", EntityOperator.NOT_EQUAL, null));
    try {
        beganTransaction = TransactionUtil.begin();
    } catch (GenericTransactionException e1) {
        Debug.logError(e1, "[Delegator] Could not begin transaction: " + e1.toString(), module);
    }
    try (EntityListIterator eli = EntityQuery.use(delegator).from("Subscription").where(exprs).queryIterator()) {
        if (eli != null) {
            GenericValue subscription;
            while (((subscription = eli.next()) != null)) {
                Calendar endDate = Calendar.getInstance();
                endDate.setTime(UtilDateTime.nowTimestamp());
                // Check if today date + cancel period (if provided) is earlier than the thrudate
                int field = Calendar.MONTH;
                if (subscription.get("canclAutmExtTime") != null && subscription.get("canclAutmExtTimeUomId") != null) {
                    if ("TF_day".equals(subscription.getString("canclAutmExtTimeUomId"))) {
                        field = Calendar.DAY_OF_YEAR;
                    } else if ("TF_wk".equals(subscription.getString("canclAutmExtTimeUomId"))) {
                        field = Calendar.WEEK_OF_YEAR;
                    } else if ("TF_mon".equals(subscription.getString("canclAutmExtTimeUomId"))) {
                        field = Calendar.MONTH;
                    } else if ("TF_yr".equals(subscription.getString("canclAutmExtTimeUomId"))) {
                        field = Calendar.YEAR;
                    } else {
                        Debug.logWarning("Don't know anything about canclAutmExtTimeUomId [" + subscription.getString("canclAutmExtTimeUomId") + "], defaulting to month", module);
                    }
                    endDate.add(field, Integer.parseInt(subscription.getString("canclAutmExtTime")));
                }
                Calendar endDateSubscription = Calendar.getInstance();
                endDateSubscription.setTime(subscription.getTimestamp("thruDate"));
                if (endDate.before(endDateSubscription)) {
                    // nor expired yet.....
                    continue;
                }
                result = dispatcher.runSync("loadCartFromOrder", UtilMisc.toMap("orderId", subscription.get("orderId"), "userLogin", userLogin));
                if (ServiceUtil.isError(result)) {
                    return ServiceUtil.returnError(ServiceUtil.getErrorMessage(result));
                }
                ShoppingCart cart = (ShoppingCart) result.get("shoppingCart");
                // remove former orderId from cart (would cause duplicate entry).
                // orderId is set by order-creation services (including store-specific prefixes, e.g.)
                cart.setOrderId(null);
                // only keep the orderitem with the related product.
                List<ShoppingCartItem> cartItems = cart.items();
                for (ShoppingCartItem shoppingCartItem : cartItems) {
                    if (!subscription.get("productId").equals(shoppingCartItem.getProductId())) {
                        cart.removeCartItem(shoppingCartItem, dispatcher);
                    }
                }
                CheckOutHelper helper = new CheckOutHelper(dispatcher, delegator, cart);
                // store the order
                Map<String, Object> createResp = helper.createOrder(userLogin);
                if (createResp != null && ServiceUtil.isError(createResp)) {
                    Debug.logError("Cannot create order for shopping list - " + subscription, module);
                } else {
                    String orderId = (String) createResp.get("orderId");
                    // authorize the payments
                    Map<String, Object> payRes = null;
                    try {
                        payRes = helper.processPayment(ProductStoreWorker.getProductStore(cart.getProductStoreId(), delegator), userLogin);
                    } catch (GeneralException e) {
                        Debug.logError(e, module);
                    }
                    if (payRes != null && ServiceUtil.isError(payRes)) {
                        Debug.logError("Payment processing problems with shopping list - " + subscription, module);
                    }
                    // remove the automatic extension flag
                    subscription.put("automaticExtend", "N");
                    subscription.store();
                    // send notification
                    if (orderId != null) {
                        dispatcher.runAsync("sendOrderPayRetryNotification", UtilMisc.toMap("orderId", orderId));
                    }
                    count++;
                }
            }
        }
    } catch (GenericServiceException e) {
        Debug.logError("Could call service to create cart", module);
        return ServiceUtil.returnError(e.toString());
    } catch (CartItemModifyException e) {
        Debug.logError("Could not modify cart: " + e.toString(), module);
        return ServiceUtil.returnError(e.toString());
    } catch (GenericEntityException e) {
        try {
            // only rollback the transaction if we started one...
            TransactionUtil.rollback(beganTransaction, "Error creating subscription auto-reorders", e);
        } catch (GenericEntityException e2) {
            Debug.logError(e2, "[Delegator] Could not rollback transaction: " + e2.toString(), module);
        }
        Debug.logError(e, "Error while creating new shopping list based automatic reorder" + e.toString(), module);
        return ServiceUtil.returnError(UtilProperties.getMessage(resource, "OrderShoppingListCreationError", UtilMisc.toMap("errorString", e.toString()), locale));
    } finally {
        try {
            // only commit the transaction if we started one... this will throw an exception if it fails
            TransactionUtil.commit(beganTransaction);
        } catch (GenericEntityException e) {
            Debug.logError(e, "Could not commit transaction for creating new shopping list based automatic reorder", module);
        }
    }
    return ServiceUtil.returnSuccess(UtilProperties.getMessage(resource, "OrderRunSubscriptionAutoReorders", UtilMisc.toMap("count", count), locale));
}
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) Calendar(com.ibm.icu.util.Calendar) CheckOutHelper(org.apache.ofbiz.order.shoppingcart.CheckOutHelper) Delegator(org.apache.ofbiz.entity.Delegator) ShoppingCart(org.apache.ofbiz.order.shoppingcart.ShoppingCart) CartItemModifyException(org.apache.ofbiz.order.shoppingcart.CartItemModifyException) GenericEntityException(org.apache.ofbiz.entity.GenericEntityException) GenericTransactionException(org.apache.ofbiz.entity.transaction.GenericTransactionException) ShoppingCartItem(org.apache.ofbiz.order.shoppingcart.ShoppingCartItem) GenericServiceException(org.apache.ofbiz.service.GenericServiceException) EntityListIterator(org.apache.ofbiz.entity.util.EntityListIterator) EntityExpr(org.apache.ofbiz.entity.condition.EntityExpr)

Example 3 with ShoppingCartItem

use of org.apache.ofbiz.order.shoppingcart.ShoppingCartItem in project ofbiz-framework by apache.

the class OrderServices method checkCreateDropShipPurchaseOrders.

public static Map<String, Object> checkCreateDropShipPurchaseOrders(DispatchContext ctx, Map<String, ? extends Object> context) {
    Delegator delegator = ctx.getDelegator();
    LocalDispatcher dispatcher = ctx.getDispatcher();
    // TODO (use the "system" user)
    GenericValue userLogin = (GenericValue) context.get("userLogin");
    String orderId = (String) context.get("orderId");
    Locale locale = (Locale) context.get("locale");
    OrderReadHelper orh = new OrderReadHelper(delegator, orderId);
    try {
        // if sales order
        if ("SALES_ORDER".equals(orh.getOrderTypeId())) {
            // get the order's ship groups
            for (GenericValue shipGroup : orh.getOrderItemShipGroups()) {
                if (UtilValidate.isNotEmpty(shipGroup.getString("supplierPartyId"))) {
                    // This ship group is a drop shipment: we create a purchase order for it
                    String supplierPartyId = shipGroup.getString("supplierPartyId");
                    // Set supplier preferred currency for drop-ship (PO) order to support multi currency
                    GenericValue supplierParty = EntityQuery.use(delegator).from("Party").where("partyId", supplierPartyId).queryOne();
                    String currencyUomId = supplierParty.getString("preferredCurrencyUomId");
                    // If supplier currency not found then set currency of sales order
                    if (UtilValidate.isEmpty(currencyUomId)) {
                        currencyUomId = orh.getCurrency();
                    }
                    // create the cart
                    ShoppingCart cart = new ShoppingCart(delegator, orh.getProductStoreId(), null, currencyUomId);
                    cart.setOrderType("PURCHASE_ORDER");
                    // Company
                    cart.setBillToCustomerPartyId(cart.getBillFromVendorPartyId());
                    cart.setBillFromVendorPartyId(supplierPartyId);
                    cart.setOrderPartyId(supplierPartyId);
                    cart.setAgreementId(shipGroup.getString("supplierAgreementId"));
                    // Get the items associated to it and create po
                    List<GenericValue> items = orh.getValidOrderItems(shipGroup.getString("shipGroupSeqId"));
                    if (UtilValidate.isNotEmpty(items)) {
                        for (GenericValue item : items) {
                            try {
                                int itemIndex = cart.addOrIncreaseItem(item.getString("productId"), // amount
                                null, item.getBigDecimal("quantity"), // reserv
                                null, // reserv
                                null, // reserv
                                null, item.getTimestamp("shipBeforeDate"), item.getTimestamp("shipAfterDate"), null, null, null, null, null, null, null, dispatcher);
                                ShoppingCartItem sci = cart.findCartItem(itemIndex);
                                sci.setAssociatedOrderId(orderId);
                                sci.setAssociatedOrderItemSeqId(item.getString("orderItemSeqId"));
                                sci.setOrderItemAssocTypeId("DROP_SHIPMENT");
                            } catch (CartItemModifyException | ItemNotFoundException e) {
                                return ServiceUtil.returnError(UtilProperties.getMessage(resource, "OrderOrderCreatingDropShipmentsError", UtilMisc.toMap("orderId", orderId, "errorString", e.getMessage()), locale));
                            }
                        }
                    }
                    // If there are indeed items to drop ship, then create the purchase order
                    if (UtilValidate.isNotEmpty(cart.items())) {
                        // resolve supplier promotion
                        ProductPromoWorker.doPromotions(cart, dispatcher);
                        // set checkout options
                        cart.setDefaultCheckoutOptions(dispatcher);
                        // the shipping address is the one of the customer
                        cart.setAllShippingContactMechId(shipGroup.getString("contactMechId"));
                        // associate ship groups of sales and purchase orders
                        ShoppingCart.CartShipInfo cartShipInfo = cart.getShipGroups().get(0);
                        cartShipInfo.setAssociatedShipGroupSeqId(shipGroup.getString("shipGroupSeqId"));
                        // create the order
                        CheckOutHelper coh = new CheckOutHelper(dispatcher, delegator, cart);
                        coh.createOrder(userLogin);
                    } else {
                        // if there are no items to drop ship, then clear out the supplier partyId
                        Debug.logWarning("No drop ship items found for order [" + shipGroup.getString("orderId") + "] and ship group [" + shipGroup.getString("shipGroupSeqId") + "] and supplier party [" + shipGroup.getString("supplierPartyId") + "].  Supplier party information will be cleared for this ship group", module);
                        shipGroup.set("supplierPartyId", null);
                        shipGroup.store();
                    }
                }
            }
        }
    } catch (GenericEntityException exc) {
        // TODO: imporve error handling
        return ServiceUtil.returnError(UtilProperties.getMessage(resource, "OrderOrderCreatingDropShipmentsError", UtilMisc.toMap("orderId", orderId, "errorString", exc.getMessage()), locale));
    }
    return ServiceUtil.returnSuccess();
}
Also used : Locale(java.util.Locale) GenericValue(org.apache.ofbiz.entity.GenericValue) LocalDispatcher(org.apache.ofbiz.service.LocalDispatcher) CheckOutHelper(org.apache.ofbiz.order.shoppingcart.CheckOutHelper) Delegator(org.apache.ofbiz.entity.Delegator) ShoppingCart(org.apache.ofbiz.order.shoppingcart.ShoppingCart) CartItemModifyException(org.apache.ofbiz.order.shoppingcart.CartItemModifyException) GenericEntityException(org.apache.ofbiz.entity.GenericEntityException) ShoppingCartItem(org.apache.ofbiz.order.shoppingcart.ShoppingCartItem) ItemNotFoundException(org.apache.ofbiz.order.shoppingcart.ItemNotFoundException)

Example 4 with ShoppingCartItem

use of org.apache.ofbiz.order.shoppingcart.ShoppingCartItem in project ofbiz-framework by apache.

the class ProductPromoWorker method performAction.

public static void performAction(ActionResultInfo actionResultInfo, GenericValue productPromoAction, ShoppingCart cart, Delegator delegator, LocalDispatcher dispatcher, Timestamp nowTimestamp) throws GenericEntityException, CartItemModifyException {
    String productPromoActionEnumId = productPromoAction.getString("productPromoActionEnumId");
    if ("PROMO_SERVICE".equals(productPromoActionEnumId)) {
        Map<String, Object> serviceCtx = UtilMisc.<String, Object>toMap("productPromoAction", productPromoAction, "shoppingCart", cart, "nowTimestamp", nowTimestamp, "actionResultInfo", actionResultInfo);
        String serviceName = productPromoAction.getString("serviceName");
        Map<String, Object> actionResult;
        try {
            actionResult = dispatcher.runSync(serviceName, serviceCtx);
        } catch (GenericServiceException e) {
            Debug.logError("Error calling promo action service [" + serviceName + "]", module);
            throw new CartItemModifyException("Error calling promo action service [" + serviceName + "]", e);
        }
        if (ServiceUtil.isError(actionResult)) {
            Debug.logError("Error calling promo action service [" + serviceName + "], result is: " + actionResult, module);
            throw new CartItemModifyException(ServiceUtil.getErrorMessage(actionResult));
        }
        CartItemModifyException cartItemModifyException = (CartItemModifyException) actionResult.get("cartItemModifyException");
        if (cartItemModifyException != null) {
            throw cartItemModifyException;
        }
    } else if ("PROMO_GWP".equals(productPromoActionEnumId)) {
        String productStoreId = cart.getProductStoreId();
        // the code was in there for this, so even though I don't think we want to restrict this, just adding this flag to make it easy to change; could make option dynamic, but now implied by the use limit
        boolean allowMultipleGwp = true;
        Integer itemLoc = findPromoItem(productPromoAction, cart);
        if (!allowMultipleGwp && itemLoc != null) {
            if (Debug.verboseOn()) {
                Debug.logVerbose("Not adding promo item, already there; action: " + productPromoAction, module);
            }
            actionResultInfo.ranAction = false;
        } else {
            BigDecimal quantity;
            if (productPromoAction.get("quantity") != null) {
                quantity = productPromoAction.getBigDecimal("quantity");
            } else {
                if ("Y".equals(productPromoAction.get("useCartQuantity"))) {
                    quantity = BigDecimal.ZERO;
                    List<ShoppingCartItem> used = getCartItemsUsed(cart, productPromoAction);
                    for (ShoppingCartItem item : used) {
                        BigDecimal available = item.getPromoQuantityAvailable();
                        quantity = quantity.add(available).add(item.getPromoQuantityCandidateUseActionAndAllConds(productPromoAction));
                        item.addPromoQuantityCandidateUse(available, productPromoAction, false);
                    }
                } else {
                    quantity = BigDecimal.ZERO;
                }
            }
            List<String> optionProductIds = new LinkedList<>();
            String productId = productPromoAction.getString("productId");
            GenericValue product = null;
            if (UtilValidate.isNotEmpty(productId)) {
                product = EntityQuery.use(delegator).from("Product").where("productId", productId).cache().queryOne();
                if (product == null) {
                    String errMsg = "GWP Product not found with ID [" + productId + "] for ProductPromoAction [" + productPromoAction.get("productPromoId") + ":" + productPromoAction.get("productPromoRuleId") + ":" + productPromoAction.get("productPromoActionSeqId") + "]";
                    Debug.logError(errMsg, module);
                    throw new CartItemModifyException(errMsg);
                }
                if ("Y".equals(product.getString("isVirtual"))) {
                    List<GenericValue> productAssocs = EntityUtil.filterByDate(product.getRelated("MainProductAssoc", UtilMisc.toMap("productAssocTypeId", "PRODUCT_VARIANT"), UtilMisc.toList("sequenceNum"), true));
                    for (GenericValue productAssoc : productAssocs) {
                        optionProductIds.add(productAssoc.getString("productIdTo"));
                    }
                    productId = null;
                    product = null;
                } else {
                    // NOTE: even though the store may not require inventory for purchase, we will always require inventory for gifts
                    try {
                        // get the quantity in cart for inventory check
                        BigDecimal quantityAlreadyInCart = BigDecimal.ZERO;
                        List<ShoppingCartItem> matchingItems = cart.findAllCartItems(productId);
                        for (ShoppingCartItem item : matchingItems) {
                            quantityAlreadyInCart = quantityAlreadyInCart.add(item.getQuantity());
                        }
                        Map<String, Object> invReqResult = dispatcher.runSync("isStoreInventoryAvailable", UtilMisc.<String, Object>toMap("productStoreId", productStoreId, "productId", productId, "product", product, "quantity", quantity.add(quantityAlreadyInCart)));
                        if (ServiceUtil.isError(invReqResult)) {
                            Debug.logError("Error calling isStoreInventoryAvailable service, result is: " + invReqResult, module);
                            throw new CartItemModifyException(ServiceUtil.getErrorMessage(invReqResult));
                        } else if (!"Y".equals(invReqResult.get("available"))) {
                            Debug.logWarning(UtilProperties.getMessage(resource_error, "OrderNotApplyingGwpBecauseProductIdIsOutOfStockForProductPromoAction", UtilMisc.toMap("productId", productId, "productPromoAction", productPromoAction), cart.getLocale()), module);
                            productId = null;
                            product = null;
                        }
                    } catch (GenericServiceException e) {
                        String errMsg = "Fatal error calling inventory checking services: " + e.toString();
                        Debug.logError(e, errMsg, module);
                        throw new CartItemModifyException(errMsg);
                    }
                }
            }
            // support multiple gift options if products are attached to the action, or if the productId on the action is a virtual product
            Set<String> productIds = ProductPromoWorker.getPromoRuleActionProductIds(productPromoAction, delegator, nowTimestamp);
            optionProductIds.addAll(productIds);
            // make sure these optionProducts have inventory...
            Iterator<String> optionProductIdIter = optionProductIds.iterator();
            while (optionProductIdIter.hasNext()) {
                String optionProductId = optionProductIdIter.next();
                try {
                    // get the quantity in cart for inventory check
                    BigDecimal quantityAlreadyInCart = BigDecimal.ZERO;
                    List<ShoppingCartItem> matchingItems = cart.findAllCartItems(optionProductId);
                    for (ShoppingCartItem item : matchingItems) {
                        quantityAlreadyInCart = quantityAlreadyInCart.add(item.getQuantity());
                    }
                    Map<String, Object> invReqResult = dispatcher.runSync("isStoreInventoryAvailable", UtilMisc.<String, Object>toMap("productStoreId", productStoreId, "productId", optionProductId, "product", product, "quantity", quantity.add(quantityAlreadyInCart)));
                    if (ServiceUtil.isError(invReqResult)) {
                        Debug.logError("Error calling isStoreInventoryAvailable service, result is: " + invReqResult, module);
                        throw new CartItemModifyException(ServiceUtil.getErrorMessage(invReqResult));
                    } else if (!"Y".equals(invReqResult.get("available"))) {
                        optionProductIdIter.remove();
                    }
                } catch (GenericServiceException e) {
                    String errMsg = "Fatal error calling inventory checking services: " + e.toString();
                    Debug.logError(e, errMsg, module);
                    throw new CartItemModifyException(errMsg);
                }
            }
            // check to see if any desired productIds have been selected for this promo action
            String alternateGwpProductId = cart.getDesiredAlternateGiftByAction(productPromoAction.getPrimaryKey());
            if (UtilValidate.isNotEmpty(alternateGwpProductId)) {
                // also check to make sure this isn't a spoofed ID somehow, check to see if it is in the Set
                if (optionProductIds.contains(alternateGwpProductId)) {
                    if (UtilValidate.isNotEmpty(productId)) {
                        optionProductIds.add(productId);
                    }
                    optionProductIds.remove(alternateGwpProductId);
                    productId = alternateGwpProductId;
                    product = EntityQuery.use(delegator).from("Product").where("productId", productId).cache().queryOne();
                } else {
                    Debug.logWarning(UtilProperties.getMessage(resource_error, "OrderAnAlternateGwpProductIdWasInPlaceButWasEitherNotValidOrIsNoLongerInStockForId", UtilMisc.toMap("alternateGwpProductId", alternateGwpProductId), cart.getLocale()), module);
                }
            }
            // if product is null, get one from the productIds set
            if (product == null && optionProductIds.size() > 0) {
                // get the first from an iterator and remove it since it will be the current one
                Iterator<String> optionProductIdTempIter = optionProductIds.iterator();
                productId = optionProductIdTempIter.next();
                optionProductIdTempIter.remove();
                product = EntityQuery.use(delegator).from("Product").where("productId", productId).cache().queryOne();
            }
            if (product == null) {
                // no product found to add as GWP, just return
                return;
            }
            // pass null for cartLocation to add to end of cart, pass false for doPromotions to avoid infinite recursion
            ShoppingCartItem gwpItem = null;
            try {
                // just leave the prodCatalogId null, this line won't be associated with a catalog
                gwpItem = ShoppingCartItem.makeItem(null, product, null, quantity, null, null, null, null, null, null, null, null, null, null, null, null, dispatcher, cart, Boolean.FALSE, Boolean.TRUE, null, Boolean.FALSE, Boolean.FALSE);
                if (optionProductIds.size() > 0) {
                    gwpItem.setAlternativeOptionProductIds(optionProductIds);
                } else {
                    gwpItem.setAlternativeOptionProductIds(null);
                }
            } catch (CartItemModifyException e) {
                Debug.logError(e.getMessage(), module);
                throw e;
            }
            BigDecimal discountAmount = quantity.multiply(gwpItem.getBasePrice()).negate();
            doOrderItemPromoAction(productPromoAction, gwpItem, discountAmount, "amount", delegator);
            // set promo after create; note that to setQuantity we must clear this flag, setQuantity, then re-set the flag
            gwpItem.setIsPromo(true);
            if (Debug.verboseOn()) {
                Debug.logVerbose("gwpItem adjustments: " + gwpItem.getAdjustments(), module);
            }
            actionResultInfo.ranAction = true;
            actionResultInfo.totalDiscountAmount = discountAmount;
        }
    } else if ("PROMO_FREE_SHIPPING".equals(productPromoActionEnumId)) {
        // this may look a bit funny: on each pass all rules that do free shipping will set their own rule id for it,
        // and on unapply if the promo and rule ids are the same then it will clear it; essentially on any pass
        // through the promos and rules if any free shipping should be there, it will be there
        cart.addFreeShippingProductPromoAction(productPromoAction);
        // don't consider this as a cart change?
        actionResultInfo.ranAction = true;
    // should probably set the totalDiscountAmount to something, but we have no idea what it will be, so leave at 0, will still get run
    } else if ("PROMO_PROD_DISC".equals(productPromoActionEnumId)) {
        BigDecimal quantityDesired = productPromoAction.get("quantity") == null ? BigDecimal.ONE : productPromoAction.getBigDecimal("quantity");
        BigDecimal startingQuantity = quantityDesired;
        BigDecimal discountAmountTotal = BigDecimal.ZERO;
        Set<String> productIds = ProductPromoWorker.getPromoRuleActionProductIds(productPromoAction, delegator, nowTimestamp);
        List<ShoppingCartItem> lineOrderedByBasePriceList = cart.getLineListOrderedByBasePrice(false);
        Iterator<ShoppingCartItem> lineOrderedByBasePriceIter = lineOrderedByBasePriceList.iterator();
        while (quantityDesired.compareTo(BigDecimal.ZERO) > 0 && lineOrderedByBasePriceIter.hasNext()) {
            ShoppingCartItem cartItem = lineOrderedByBasePriceIter.next();
            // only include if it is in the productId Set for this check and if it is not a Promo (GWP) item
            GenericValue product = cartItem.getProduct();
            String parentProductId = cartItem.getParentProductId();
            boolean passedItemConds = checkConditionsForItem(productPromoAction, cart, cartItem, delegator, dispatcher, nowTimestamp);
            if (passedItemConds && !cartItem.getIsPromo() && (productIds.contains(cartItem.getProductId()) || (parentProductId != null && productIds.contains(parentProductId))) && (product == null || !"N".equals(product.getString("includeInPromotions")))) {
                // reduce quantity still needed to qualify for promo (quantityNeeded)
                BigDecimal quantityUsed = cartItem.addPromoQuantityCandidateUse(quantityDesired, productPromoAction, false);
                if (quantityUsed.compareTo(BigDecimal.ZERO) > 0) {
                    quantityDesired = quantityDesired.subtract(quantityUsed);
                    // create an adjustment and add it to the cartItem that implements the promotion action
                    BigDecimal percentModifier = productPromoAction.get("amount") == null ? BigDecimal.ZERO : productPromoAction.getBigDecimal("amount").movePointLeft(2);
                    BigDecimal lineAmount = quantityUsed.multiply(cartItem.getBasePrice()).multiply(cartItem.getRentalAdjustment());
                    BigDecimal discountAmount = lineAmount.multiply(percentModifier).negate();
                    discountAmountTotal = discountAmountTotal.add(discountAmount);
                // not doing this any more, now distributing among conditions and actions (see call below): doOrderItemPromoAction(productPromoAction, cartItem, discountAmount, "amount", delegator);
                }
            }
        }
        if (quantityDesired.compareTo(startingQuantity) == 0 || quantityDesired.compareTo(BigDecimal.ZERO) > 0) {
            // couldn't find any (or enough) cart items to give a discount to, don't consider action run
            actionResultInfo.ranAction = false;
            // clear out any action uses for this so they don't become part of anything else
            cart.resetPromoRuleUse(productPromoAction.getString("productPromoId"), productPromoAction.getString("productPromoRuleId"));
        } else {
            BigDecimal totalAmount = getCartItemsUsedTotalAmount(cart, productPromoAction);
            if (Debug.verboseOn()) {
                Debug.logVerbose("Applying promo [" + productPromoAction.getPrimaryKey() + "]\n totalAmount=" + totalAmount + ", discountAmountTotal=" + discountAmountTotal, module);
            }
            distributeDiscountAmount(discountAmountTotal, totalAmount, getCartItemsUsed(cart, productPromoAction), productPromoAction, delegator);
            actionResultInfo.ranAction = true;
            actionResultInfo.totalDiscountAmount = discountAmountTotal;
            actionResultInfo.quantityLeftInAction = quantityDesired;
        }
    } else if ("PROMO_PROD_AMDISC".equals(productPromoActionEnumId)) {
        BigDecimal quantityDesired = productPromoAction.get("quantity") == null ? BigDecimal.ONE : productPromoAction.getBigDecimal("quantity");
        BigDecimal startingQuantity = quantityDesired;
        BigDecimal discountAmountTotal = BigDecimal.ZERO;
        Set<String> productIds = ProductPromoWorker.getPromoRuleActionProductIds(productPromoAction, delegator, nowTimestamp);
        List<ShoppingCartItem> lineOrderedByBasePriceList = cart.getLineListOrderedByBasePrice(false);
        Iterator<ShoppingCartItem> lineOrderedByBasePriceIter = lineOrderedByBasePriceList.iterator();
        while (quantityDesired.compareTo(BigDecimal.ZERO) > 0 && lineOrderedByBasePriceIter.hasNext()) {
            ShoppingCartItem cartItem = lineOrderedByBasePriceIter.next();
            // only include if it is in the productId Set for this check and if it is not a Promo (GWP) item
            String parentProductId = cartItem.getParentProductId();
            GenericValue product = cartItem.getProduct();
            boolean passedItemConds = checkConditionsForItem(productPromoAction, cart, cartItem, delegator, dispatcher, nowTimestamp);
            if (passedItemConds && !cartItem.getIsPromo() && (productIds.contains(cartItem.getProductId()) || (parentProductId != null && productIds.contains(parentProductId))) && (product == null || !"N".equals(product.getString("includeInPromotions")))) {
                // reduce quantity still needed to qualify for promo (quantityNeeded)
                BigDecimal quantityUsed = cartItem.addPromoQuantityCandidateUse(quantityDesired, productPromoAction, false);
                quantityDesired = quantityDesired.subtract(quantityUsed);
                // create an adjustment and add it to the cartItem that implements the promotion action
                BigDecimal discount = productPromoAction.get("amount") == null ? BigDecimal.ZERO : productPromoAction.getBigDecimal("amount");
                // don't allow the discount to be greater than the price
                if (discount.compareTo(cartItem.getBasePrice().multiply(cartItem.getRentalAdjustment())) > 0) {
                    discount = cartItem.getBasePrice().multiply(cartItem.getRentalAdjustment());
                }
                BigDecimal discountAmount = quantityUsed.multiply(discount).negate();
                discountAmountTotal = discountAmountTotal.add(discountAmount);
            // not doing this any more, now distributing among conditions and actions (see call below): doOrderItemPromoAction(productPromoAction, cartItem, discountAmount, "amount", delegator);
            }
        }
        if (quantityDesired.compareTo(startingQuantity) == 0) {
            // couldn't find any cart items to give a discount to, don't consider action run
            actionResultInfo.ranAction = false;
        } else {
            BigDecimal totalAmount = getCartItemsUsedTotalAmount(cart, productPromoAction);
            if (Debug.verboseOn()) {
                Debug.logVerbose("Applying promo [" + productPromoAction.getPrimaryKey() + "]\n totalAmount=" + totalAmount + ", discountAmountTotal=" + discountAmountTotal, module);
            }
            distributeDiscountAmount(discountAmountTotal, totalAmount, getCartItemsUsed(cart, productPromoAction), productPromoAction, delegator);
            actionResultInfo.ranAction = true;
            actionResultInfo.totalDiscountAmount = discountAmountTotal;
            actionResultInfo.quantityLeftInAction = quantityDesired;
        }
    } else if ("PROMO_PROD_PRICE".equals(productPromoActionEnumId)) {
        // with this we want the set of used items to be one price, so total the price for all used items, subtract the amount we want them to cost, and create an adjustment for what is left
        BigDecimal quantityDesired = productPromoAction.get("quantity") == null ? BigDecimal.ONE : productPromoAction.getBigDecimal("quantity");
        BigDecimal desiredAmount = productPromoAction.get("amount") == null ? BigDecimal.ZERO : productPromoAction.getBigDecimal("amount");
        BigDecimal totalAmount = BigDecimal.ZERO;
        Set<String> productIds = ProductPromoWorker.getPromoRuleActionProductIds(productPromoAction, delegator, nowTimestamp);
        List<ShoppingCartItem> cartItemsUsed = new LinkedList<>();
        List<ShoppingCartItem> lineOrderedByBasePriceList = cart.getLineListOrderedByBasePrice(false);
        Iterator<ShoppingCartItem> lineOrderedByBasePriceIter = lineOrderedByBasePriceList.iterator();
        while (quantityDesired.compareTo(BigDecimal.ZERO) > 0 && lineOrderedByBasePriceIter.hasNext()) {
            ShoppingCartItem cartItem = lineOrderedByBasePriceIter.next();
            // only include if it is in the productId Set for this check and if it is not a Promo (GWP) item
            String parentProductId = cartItem.getParentProductId();
            GenericValue product = cartItem.getProduct();
            boolean passedItemConds = checkConditionsForItem(productPromoAction, cart, cartItem, delegator, dispatcher, nowTimestamp);
            if (passedItemConds && !cartItem.getIsPromo() && (productIds.contains(cartItem.getProductId()) || (parentProductId != null && productIds.contains(parentProductId))) && (product == null || !"N".equals(product.getString("includeInPromotions")))) {
                // reduce quantity still needed to qualify for promo (quantityNeeded)
                BigDecimal quantityUsed = cartItem.addPromoQuantityCandidateUse(quantityDesired, productPromoAction, false);
                if (quantityUsed.compareTo(BigDecimal.ZERO) > 0) {
                    quantityDesired = quantityDesired.subtract(quantityUsed);
                    totalAmount = totalAmount.add(quantityUsed.multiply(cartItem.getBasePrice()).multiply(cartItem.getRentalAdjustment()));
                    cartItemsUsed.add(cartItem);
                }
            }
        }
        if (totalAmount.compareTo(desiredAmount) > 0 && quantityDesired.compareTo(BigDecimal.ZERO) == 0) {
            BigDecimal discountAmountTotal = totalAmount.subtract(desiredAmount).negate();
            distributeDiscountAmount(discountAmountTotal, totalAmount, cartItemsUsed, productPromoAction, delegator);
            actionResultInfo.ranAction = true;
            actionResultInfo.totalDiscountAmount = discountAmountTotal;
        // no use setting the quantityLeftInAction because that does not apply for buy X for $Y type promotions, it is all or nothing
        } else {
            actionResultInfo.ranAction = false;
            // clear out any action uses for this so they don't become part of anything else
            cart.resetPromoRuleUse(productPromoAction.getString("productPromoId"), productPromoAction.getString("productPromoRuleId"));
        }
    } else if ("PROMO_ORDER_PERCENT".equals(productPromoActionEnumId)) {
        BigDecimal percentage = (productPromoAction.get("amount") == null ? BigDecimal.ZERO : (productPromoAction.getBigDecimal("amount").movePointLeft(2))).negate();
        Set<String> productIds = ProductPromoWorker.getPromoRuleActionProductIds(productPromoAction, delegator, nowTimestamp);
        BigDecimal amount;
        if (productIds.isEmpty()) {
            amount = cart.getSubTotalForPromotions().multiply(percentage);
        } else {
            amount = cart.getSubTotalForPromotions(productIds).multiply(percentage);
        }
        if (amount.compareTo(BigDecimal.ZERO) != 0) {
            doOrderPromoAction(productPromoAction, cart, amount, "amount", delegator);
            actionResultInfo.ranAction = true;
            actionResultInfo.totalDiscountAmount = amount;
        }
    } else if ("PROMO_ORDER_AMOUNT".equals(productPromoActionEnumId)) {
        BigDecimal amount = (productPromoAction.get("amount") == null ? BigDecimal.ZERO : productPromoAction.getBigDecimal("amount")).negate();
        // if amount is greater than the order sub total, set equal to order sub total, this normally wouldn't happen because there should be a condition that the order total be above a certain amount, but just in case...
        BigDecimal subTotal = cart.getSubTotalForPromotions();
        if (amount.negate().compareTo(subTotal) > 0) {
            amount = subTotal.negate();
        }
        if (amount.compareTo(BigDecimal.ZERO) != 0) {
            doOrderPromoAction(productPromoAction, cart, amount, "amount", delegator);
            actionResultInfo.ranAction = true;
            actionResultInfo.totalDiscountAmount = amount;
        }
    } else if ("PROMO_PROD_SPPRC".equals(productPromoActionEnumId)) {
        // if there are productIds associated with the action then restrict to those productIds, otherwise apply for all products
        Set<String> productIds = ProductPromoWorker.getPromoRuleActionProductIds(productPromoAction, delegator, nowTimestamp);
        // go through the cart items and for each product that has a specialPromoPrice use that price
        for (ShoppingCartItem cartItem : cart.items()) {
            String itemProductId = cartItem.getProductId();
            if (UtilValidate.isEmpty(itemProductId)) {
                continue;
            }
            if (productIds.size() > 0 && !productIds.contains(itemProductId)) {
                continue;
            }
            if (cartItem.getSpecialPromoPrice() == null) {
                continue;
            }
            // get difference between basePrice and specialPromoPrice and adjust for that
            BigDecimal difference = cartItem.getBasePrice().multiply(cartItem.getRentalAdjustment()).subtract(cartItem.getSpecialPromoPrice()).negate();
            if (difference.compareTo(BigDecimal.ZERO) != 0) {
                BigDecimal quantityUsed = cartItem.addPromoQuantityCandidateUse(cartItem.getQuantity(), productPromoAction, false);
                if (quantityUsed.compareTo(BigDecimal.ZERO) > 0) {
                    BigDecimal amount = difference.multiply(quantityUsed);
                    doOrderItemPromoAction(productPromoAction, cartItem, amount, "amount", delegator);
                    actionResultInfo.ranAction = true;
                    actionResultInfo.totalDiscountAmount = amount;
                }
            }
        }
    } else if ("PROMO_SHIP_CHARGE".equals(productPromoActionEnumId)) {
        BigDecimal percentage = (productPromoAction.get("amount") == null ? BigDecimal.ZERO : (productPromoAction.getBigDecimal("amount").movePointLeft(2))).negate();
        BigDecimal amount = cart.getTotalShipping().multiply(percentage);
        if (amount.compareTo(BigDecimal.ZERO) != 0) {
            int existingOrderPromoIndex = cart.getAdjustmentPromoIndex(productPromoAction.getString("productPromoId"));
            if (existingOrderPromoIndex != -1 && cart.getAdjustment(existingOrderPromoIndex).getBigDecimal("amount").compareTo(amount) == 0) {
                // already ran, no need to repeat
                actionResultInfo.ranAction = false;
            } else {
                if (existingOrderPromoIndex != -1 && cart.getAdjustment(existingOrderPromoIndex).getBigDecimal("amount").compareTo(amount) != 0) {
                    cart.removeAdjustment(existingOrderPromoIndex);
                }
                doOrderPromoAction(productPromoAction, cart, amount, "amount", delegator);
                actionResultInfo.ranAction = true;
                actionResultInfo.totalDiscountAmount = amount;
            }
        }
    } else if ("PROMO_TAX_PERCENT".equals(productPromoActionEnumId)) {
        BigDecimal percentage = (productPromoAction.get("amount") == null ? BigDecimal.ZERO : (productPromoAction.getBigDecimal("amount").movePointLeft(2))).negate();
        BigDecimal amount = cart.getTotalSalesTax().multiply(percentage);
        if (amount.compareTo(BigDecimal.ZERO) != 0) {
            doOrderPromoAction(productPromoAction, cart, amount, "amount", delegator);
            actionResultInfo.ranAction = true;
            actionResultInfo.totalDiscountAmount = amount;
        }
    } else {
        Debug.logError("An un-supported productPromoActionType was used: " + productPromoActionEnumId + ", not performing any action", module);
        actionResultInfo.ranAction = false;
    }
    // in action, if doesn't have enough quantity to use the promo at all, remove candidate promo uses and increment promoQuantityUsed; this should go for all actions, if any action runs we confirm
    if (actionResultInfo.ranAction) {
        cart.confirmPromoRuleUse(productPromoAction.getString("productPromoId"), productPromoAction.getString("productPromoRuleId"));
    } else {
        cart.resetPromoRuleUse(productPromoAction.getString("productPromoId"), productPromoAction.getString("productPromoRuleId"));
    }
}
Also used : GenericValue(org.apache.ofbiz.entity.GenericValue) HashSet(java.util.HashSet) Set(java.util.Set) BigDecimal(java.math.BigDecimal) CartItemModifyException(org.apache.ofbiz.order.shoppingcart.CartItemModifyException) Iterator(java.util.Iterator) GenericServiceException(org.apache.ofbiz.service.GenericServiceException) ArrayList(java.util.ArrayList) LinkedList(java.util.LinkedList) List(java.util.List) ShoppingCartItem(org.apache.ofbiz.order.shoppingcart.ShoppingCartItem) HashMap(java.util.HashMap) Map(java.util.Map)

Example 5 with ShoppingCartItem

use of org.apache.ofbiz.order.shoppingcart.ShoppingCartItem in project ofbiz-framework by apache.

the class ProductPromoWorker method checkCondition.

private static boolean checkCondition(GenericValue productPromoCond, ShoppingCart cart, Delegator delegator, LocalDispatcher dispatcher, Timestamp nowTimestamp) throws GenericEntityException {
    String condValue = productPromoCond.getString("condValue");
    String otherValue = productPromoCond.getString("otherValue");
    String inputParamEnumId = productPromoCond.getString("inputParamEnumId");
    String operatorEnumId = productPromoCond.getString("operatorEnumId");
    String shippingMethod = "";
    String carrierPartyId = "";
    if (otherValue != null && otherValue.contains("@")) {
        carrierPartyId = otherValue.substring(0, otherValue.indexOf('@'));
        shippingMethod = otherValue.substring(otherValue.indexOf('@') + 1);
        otherValue = "";
    }
    String partyId = cart.getPartyId();
    GenericValue userLogin = cart.getUserLogin();
    if (userLogin == null) {
        userLogin = cart.getAutoUserLogin();
    }
    if (Debug.verboseOn()) {
        Debug.logVerbose("Checking promotion condition: " + productPromoCond, module);
    }
    Integer compareBase = null;
    if ("PPIP_SERVICE".equals(inputParamEnumId)) {
        Map<String, Object> serviceCtx = UtilMisc.<String, Object>toMap("productPromoCond", productPromoCond, "shoppingCart", cart, "nowTimestamp", nowTimestamp);
        Map<String, Object> condResult;
        try {
            condResult = dispatcher.runSync(condValue, serviceCtx);
        } catch (GenericServiceException e) {
            Debug.logError(e, "Fatal error calling promo condition check service [" + condValue + "]", module);
            return false;
        }
        if (ServiceUtil.isError(condResult)) {
            Debug.logError("Error calling calling promo condition check service [" + condValue + "]", module);
            return false;
        }
        Boolean directResult = (Boolean) condResult.get("directResult");
        if (directResult != null) {
            return directResult.booleanValue();
        }
        compareBase = (Integer) condResult.get("compareBase");
        if (condResult.containsKey("operatorEnumId")) {
            operatorEnumId = (String) condResult.get("operatorEnumId");
        }
    } else if ("PPIP_PRODUCT_AMOUNT".equals(inputParamEnumId)) {
        // for this type of promo force the operatorEnumId = PPC_EQ, effectively ignore that setting because the comparison is implied in the code
        operatorEnumId = "PPC_EQ";
        // this type of condition requires items involved to not be involved in any other quantity consuming cond/action, and does not pro-rate the price, just uses the base price
        BigDecimal amountNeeded = BigDecimal.ZERO;
        if (UtilValidate.isNotEmpty(condValue)) {
            amountNeeded = new BigDecimal(condValue);
        }
        Set<String> productIds = ProductPromoWorker.getPromoRuleCondProductIds(productPromoCond, delegator, nowTimestamp);
        List<ShoppingCartItem> lineOrderedByBasePriceList = cart.getLineListOrderedByBasePrice(false);
        Iterator<ShoppingCartItem> lineOrderedByBasePriceIter = lineOrderedByBasePriceList.iterator();
        while (amountNeeded.compareTo(BigDecimal.ZERO) > 0 && lineOrderedByBasePriceIter.hasNext()) {
            ShoppingCartItem cartItem = lineOrderedByBasePriceIter.next();
            // only include if it is in the productId Set for this check and if it is not a Promo (GWP) item
            GenericValue product = cartItem.getProduct();
            String parentProductId = cartItem.getParentProductId();
            boolean passedItemConds = checkConditionsForItem(productPromoCond, cart, cartItem, delegator, dispatcher, nowTimestamp);
            if (passedItemConds && !cartItem.getIsPromo() && (productIds.contains(cartItem.getProductId()) || (parentProductId != null && productIds.contains(parentProductId))) && (product == null || !"N".equals(product.getString("includeInPromotions")))) {
                BigDecimal basePrice = cartItem.getBasePrice();
                // get a rough price, round it up to an integer
                BigDecimal quantityNeeded = amountNeeded.divide(basePrice, generalRounding).setScale(0, RoundingMode.CEILING);
                // reduce amount still needed to qualify for promo (amountNeeded)
                BigDecimal quantity = cartItem.addPromoQuantityCandidateUse(quantityNeeded, productPromoCond, false);
                // get pro-rated amount based on discount
                amountNeeded = amountNeeded.subtract(quantity.multiply(basePrice));
            }
        }
        // if amountNeeded > 0 then the promo condition failed, so remove candidate promo uses and increment the promoQuantityUsed to restore it
        if (amountNeeded.compareTo(BigDecimal.ZERO) > 0) {
            // failed, reset the entire rule, ie including all other conditions that might have been done before
            cart.resetPromoRuleUse(productPromoCond.getString("productPromoId"), productPromoCond.getString("productPromoRuleId"));
            compareBase = Integer.valueOf(-1);
        } else {
            // we got it, the conditions are in place...
            compareBase = Integer.valueOf(0);
        // NOTE: don't confirm promo rule use here, wait until actions are complete for the rule to do that
        }
    } else if ("PPIP_PRODUCT_TOTAL".equals(inputParamEnumId)) {
        // this type of condition allows items involved to be involved in other quantity consuming cond/action, and does pro-rate the price
        if (UtilValidate.isNotEmpty(condValue)) {
            BigDecimal amountNeeded = new BigDecimal(condValue);
            BigDecimal amountAvailable = BigDecimal.ZERO;
            Set<String> productIds = ProductPromoWorker.getPromoRuleCondProductIds(productPromoCond, delegator, nowTimestamp);
            List<ShoppingCartItem> lineOrderedByBasePriceList = cart.getLineListOrderedByBasePrice(false);
            for (ShoppingCartItem cartItem : lineOrderedByBasePriceList) {
                // only include if it is in the productId Set for this check and if it is not a Promo (GWP) item
                GenericValue product = cartItem.getProduct();
                String parentProductId = cartItem.getParentProductId();
                boolean passedItemConds = checkConditionsForItem(productPromoCond, cart, cartItem, delegator, dispatcher, nowTimestamp);
                if (passedItemConds && !cartItem.getIsPromo() && (productIds.contains(cartItem.getProductId()) || (parentProductId != null && productIds.contains(parentProductId))) && (product == null || !"N".equals(product.getString("includeInPromotions")))) {
                    // just count the entire sub-total of the item
                    amountAvailable = amountAvailable.add(cartItem.getItemSubTotal());
                }
            }
            compareBase = Integer.valueOf(amountAvailable.compareTo(amountNeeded));
        }
    } else if ("PPIP_PRODUCT_QUANT".equals(inputParamEnumId)) {
        if (operatorEnumId == null) {
            // if the operator is not specified in the condition, then assume as default PPC_EQ (for backward compatibility)
            operatorEnumId = "PPC_EQ";
        }
        BigDecimal quantityNeeded = BigDecimal.ONE;
        if (UtilValidate.isNotEmpty(condValue)) {
            quantityNeeded = new BigDecimal(condValue);
        }
        Set<String> productIds = ProductPromoWorker.getPromoRuleCondProductIds(productPromoCond, delegator, nowTimestamp);
        List<ShoppingCartItem> lineOrderedByBasePriceList = cart.getLineListOrderedByBasePrice(false);
        Iterator<ShoppingCartItem> lineOrderedByBasePriceIter = lineOrderedByBasePriceList.iterator();
        while (quantityNeeded.compareTo(BigDecimal.ZERO) > 0 && lineOrderedByBasePriceIter.hasNext()) {
            ShoppingCartItem cartItem = lineOrderedByBasePriceIter.next();
            // only include if it is in the productId Set for this check and if it is not a Promo (GWP) item
            GenericValue product = cartItem.getProduct();
            String parentProductId = cartItem.getParentProductId();
            boolean passedItemConds = checkConditionsForItem(productPromoCond, cart, cartItem, delegator, dispatcher, nowTimestamp);
            if (passedItemConds && !cartItem.getIsPromo() && (productIds.contains(cartItem.getProductId()) || (parentProductId != null && productIds.contains(parentProductId))) && (product == null || !"N".equals(product.getString("includeInPromotions")))) {
                // reduce quantity still needed to qualify for promo (quantityNeeded)
                quantityNeeded = quantityNeeded.subtract(cartItem.addPromoQuantityCandidateUse(quantityNeeded, productPromoCond, !"PPC_EQ".equals(operatorEnumId)));
            }
        }
        // if quantityNeeded > 0 then the promo condition failed, so remove candidate promo uses and increment the promoQuantityUsed to restore it
        if (quantityNeeded.compareTo(BigDecimal.ZERO) > 0) {
            // failed, reset the entire rule, ie including all other conditions that might have been done before
            cart.resetPromoRuleUse(productPromoCond.getString("productPromoId"), productPromoCond.getString("productPromoRuleId"));
            compareBase = Integer.valueOf(-1);
        } else {
            // we got it, the conditions are in place...
            compareBase = Integer.valueOf(0);
        // NOTE: don't confirm rpomo rule use here, wait until actions are complete for the rule to do that
        }
    } else if ("PPIP_NEW_ACCT".equals(inputParamEnumId)) {
        if (UtilValidate.isNotEmpty(condValue)) {
            BigDecimal acctDays = cart.getPartyDaysSinceCreated(nowTimestamp);
            if (acctDays == null) {
                // condition always fails if we don't know how many days since account created
                return false;
            }
            compareBase = acctDays.compareTo(new BigDecimal(condValue));
        }
    } else if ("PPIP_PARTY_ID".equals(inputParamEnumId)) {
        if (partyId != null && UtilValidate.isNotEmpty(condValue)) {
            compareBase = Integer.valueOf(partyId.compareTo(condValue));
        } else {
            compareBase = Integer.valueOf(1);
        }
    } else if ("PPIP_PARTY_GRP_MEM".equals(inputParamEnumId)) {
        if (UtilValidate.isEmpty(partyId) || UtilValidate.isEmpty(condValue)) {
            compareBase = Integer.valueOf(1);
        } else {
            String groupPartyId = condValue;
            if (partyId.equals(groupPartyId)) {
                compareBase = Integer.valueOf(0);
            } else {
                // look for PartyRelationship with partyRelationshipTypeId=GROUP_ROLLUP, the partyIdTo is the group member, so the partyIdFrom is the groupPartyId
                // and from/thru date within range
                List<GenericValue> partyRelationshipList = EntityQuery.use(delegator).from("PartyRelationship").where("partyIdFrom", groupPartyId, "partyIdTo", partyId, "partyRelationshipTypeId", "GROUP_ROLLUP").cache(true).filterByDate().queryList();
                if (UtilValidate.isNotEmpty(partyRelationshipList)) {
                    compareBase = Integer.valueOf(0);
                } else {
                    compareBase = Integer.valueOf(checkConditionPartyHierarchy(delegator, nowTimestamp, groupPartyId, partyId));
                }
            }
        }
    } else if ("PPIP_PARTY_CLASS".equals(inputParamEnumId)) {
        if (UtilValidate.isEmpty(partyId) || UtilValidate.isEmpty(condValue)) {
            compareBase = Integer.valueOf(1);
        } else {
            String partyClassificationGroupId = condValue;
            // find any PartyClassification
            // and from/thru date within range
            List<GenericValue> partyClassificationList = EntityQuery.use(delegator).from("PartyClassification").where("partyId", partyId, "partyClassificationGroupId", partyClassificationGroupId).cache(true).filterByDate().queryList();
            // then 0 (equals), otherwise 1 (not equals)
            if (UtilValidate.isNotEmpty(partyClassificationList)) {
                compareBase = Integer.valueOf(0);
            } else {
                compareBase = Integer.valueOf(1);
            }
        }
    } else if ("PPIP_ROLE_TYPE".equals(inputParamEnumId)) {
        if (partyId != null && UtilValidate.isNotEmpty(condValue)) {
            // if a PartyRole exists for this partyId and the specified roleTypeId
            GenericValue partyRole = EntityQuery.use(delegator).from("PartyRole").where("partyId", partyId, "roleTypeId", condValue).cache(true).queryOne();
            // then 0 (equals), otherwise 1 (not equals)
            if (partyRole != null) {
                compareBase = Integer.valueOf(0);
            } else {
                compareBase = Integer.valueOf(1);
            }
        } else {
            compareBase = Integer.valueOf(1);
        }
    } else if ("PPIP_GEO_ID".equals(inputParamEnumId)) {
        compareBase = Integer.valueOf(1);
        GenericValue shippingAddress = cart.getShippingAddress();
        if (UtilValidate.isNotEmpty(condValue) && shippingAddress != null) {
            if (condValue.equals(shippingAddress.getString("countryGeoId")) || condValue.equals(shippingAddress.getString("countyGeoId")) || condValue.equals(shippingAddress.getString("postalCodeGeoId")) || condValue.equals(shippingAddress.getString("stateProvinceGeoId"))) {
                compareBase = Integer.valueOf(0);
            } else {
                List<GenericValue> geoAssocList = EntityQuery.use(delegator).from("GeoAssoc").where("geoIdTo", condValue).queryList();
                for (GenericValue geo : geoAssocList) {
                    if (geo.get("geoId").equals(shippingAddress.getString("countryGeoId")) || geo.get("geoId").equals(shippingAddress.getString("countyGeoId")) || geo.get("geoId").equals(shippingAddress.getString("postalCodeGeoId")) || condValue.equals(shippingAddress.getString("stateProvinceGeoId"))) {
                        compareBase = Integer.valueOf(0);
                        break;
                    }
                }
            }
        }
    } else if ("PPIP_ORDER_TOTAL".equals(inputParamEnumId)) {
        if (UtilValidate.isNotEmpty(condValue)) {
            BigDecimal orderSubTotal = cart.getSubTotalForPromotions();
            if (Debug.verboseOn())
                Debug.logVerbose("Doing order total compare: orderSubTotal=" + orderSubTotal, module);
            compareBase = Integer.valueOf(orderSubTotal.compareTo(new BigDecimal(condValue)));
        }
    } else if ("PPIP_ORST_HIST".equals(inputParamEnumId)) {
        // description="Order sub-total X in last Y Months"
        if (partyId != null && userLogin != null && UtilValidate.isNotEmpty(condValue)) {
            // call the getOrderedSummaryInformation service to get the sub-total
            int monthsToInclude = 12;
            if (otherValue != null) {
                monthsToInclude = Integer.parseInt(otherValue);
            }
            Map<String, Object> serviceIn = UtilMisc.<String, Object>toMap("partyId", partyId, "roleTypeId", "PLACING_CUSTOMER", "orderTypeId", "SALES_ORDER", "statusId", "ORDER_COMPLETED", "monthsToInclude", Integer.valueOf(monthsToInclude), "userLogin", userLogin);
            try {
                Map<String, Object> result = dispatcher.runSync("getOrderedSummaryInformation", serviceIn);
                if (ServiceUtil.isError(result)) {
                    Debug.logError("Error calling getOrderedSummaryInformation service for the PPIP_ORST_HIST ProductPromo condition input value: " + ServiceUtil.getErrorMessage(result), module);
                    return false;
                } else {
                    BigDecimal orderSubTotal = (BigDecimal) result.get("totalSubRemainingAmount");
                    BigDecimal orderSubTotalAndCartSubTotal = orderSubTotal.add(cart.getSubTotal());
                    if (Debug.verboseOn())
                        Debug.logVerbose("Doing order history sub-total compare: orderSubTotal=" + orderSubTotal + ", for the last " + monthsToInclude + " months.", module);
                    compareBase = Integer.valueOf(orderSubTotalAndCartSubTotal.compareTo(new BigDecimal(condValue)));
                }
            } catch (GenericServiceException e) {
                Debug.logError(e, "Error getting order history sub-total in the getOrderedSummaryInformation service, evaluating condition to false.", module);
                return false;
            }
        } else {
            return false;
        }
    } else if ("PPIP_ORST_YEAR".equals(inputParamEnumId)) {
        // description="Order sub-total X since beginning of current year"
        if (partyId != null && userLogin != null && UtilValidate.isNotEmpty(condValue)) {
            // call the getOrderedSummaryInformation service to get the sub-total
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(nowTimestamp);
            int monthsToInclude = calendar.get(Calendar.MONTH) + 1;
            Map<String, Object> serviceIn = UtilMisc.<String, Object>toMap("partyId", partyId, "roleTypeId", "PLACING_CUSTOMER", "orderTypeId", "SALES_ORDER", "statusId", "ORDER_COMPLETED", "monthsToInclude", Integer.valueOf(monthsToInclude), "userLogin", userLogin);
            try {
                Map<String, Object> result = dispatcher.runSync("getOrderedSummaryInformation", serviceIn);
                if (ServiceUtil.isError(result)) {
                    Debug.logError("Error calling getOrderedSummaryInformation service for the PPIP_ORST_YEAR ProductPromo condition input value: " + ServiceUtil.getErrorMessage(result), module);
                    return false;
                } else {
                    BigDecimal orderSubTotal = (BigDecimal) result.get("totalSubRemainingAmount");
                    if (Debug.verboseOn())
                        Debug.logVerbose("Doing order history sub-total compare: orderSubTotal=" + orderSubTotal + ", for the last " + monthsToInclude + " months.", module);
                    compareBase = Integer.valueOf(orderSubTotal.compareTo(new BigDecimal((condValue))));
                }
            } catch (GenericServiceException e) {
                Debug.logError(e, "Error getting order history sub-total in the getOrderedSummaryInformation service, evaluating condition to false.", module);
                return false;
            }
        }
    } else if ("PPIP_ORST_LAST_YEAR".equals(inputParamEnumId)) {
        // description="Order sub-total X since beginning of last year"
        if (partyId != null && userLogin != null && UtilValidate.isNotEmpty(condValue)) {
            // call the getOrderedSummaryInformation service to get the sub-total
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(nowTimestamp);
            int lastYear = calendar.get(Calendar.YEAR) - 1;
            Calendar fromDateCalendar = Calendar.getInstance();
            fromDateCalendar.set(lastYear, 0, 0, 0, 0);
            Timestamp fromDate = new Timestamp(fromDateCalendar.getTime().getTime());
            Calendar thruDateCalendar = Calendar.getInstance();
            thruDateCalendar.set(lastYear, 12, 0, 0, 0);
            Timestamp thruDate = new Timestamp(thruDateCalendar.getTime().getTime());
            Map<String, Object> serviceIn = UtilMisc.toMap("partyId", partyId, "roleTypeId", "PLACING_CUSTOMER", "orderTypeId", "SALES_ORDER", "statusId", "ORDER_COMPLETED", "fromDate", fromDate, "thruDate", thruDate, "userLogin", userLogin);
            try {
                Map<String, Object> result = dispatcher.runSync("getOrderedSummaryInformation", serviceIn);
                if (ServiceUtil.isError(result)) {
                    Debug.logError("Error calling getOrderedSummaryInformation service for the PPIP_ORST_LAST_YEAR ProductPromo condition input value: " + ServiceUtil.getErrorMessage(result), module);
                    return false;
                } else {
                    Double orderSubTotal = (Double) result.get("totalSubRemainingAmount");
                    if (Debug.verboseOn())
                        Debug.logVerbose("Doing order history sub-total compare: orderSubTotal=" + orderSubTotal + ", for last year.", module);
                    compareBase = Integer.valueOf(orderSubTotal.compareTo(Double.valueOf(condValue)));
                }
            } catch (GenericServiceException e) {
                Debug.logError(e, "Error getting order history sub-total in the getOrderedSummaryInformation service, evaluating condition to false.", module);
                return false;
            }
        } else {
            return false;
        }
    } else if ("PPIP_RECURRENCE".equals(inputParamEnumId)) {
        if (UtilValidate.isNotEmpty(condValue)) {
            compareBase = Integer.valueOf(1);
            GenericValue recurrenceInfo = EntityQuery.use(delegator).from("RecurrenceInfo").where("recurrenceInfoId", condValue).cache().queryOne();
            if (recurrenceInfo != null) {
                RecurrenceInfo recurrence = null;
                try {
                    recurrence = new RecurrenceInfo(recurrenceInfo);
                } catch (RecurrenceInfoException e) {
                    Debug.logError(e, module);
                }
                // check the current recurrence
                if (recurrence != null) {
                    if (recurrence.isValidCurrent()) {
                        compareBase = Integer.valueOf(0);
                    }
                }
            }
        }
    } else if ("PPIP_ORDER_SHIPTOTAL".equals(inputParamEnumId) && shippingMethod.equals(cart.getShipmentMethodTypeId()) && carrierPartyId.equals(cart.getCarrierPartyId())) {
        if (UtilValidate.isNotEmpty(condValue)) {
            BigDecimal orderTotalShipping = cart.getTotalShipping();
            if (Debug.verboseOn()) {
                Debug.logVerbose("Doing order total Shipping compare: ordertotalShipping=" + orderTotalShipping, module);
            }
            compareBase = orderTotalShipping.compareTo(new BigDecimal(condValue));
        }
    } else if ("PPIP_LPMUP_AMT".equals(inputParamEnumId)) {
        // does nothing on order level, only checked on item level, so ignore by always considering passed
        return true;
    } else if ("PPIP_LPMUP_PER".equals(inputParamEnumId)) {
        // does nothing on order level, only checked on item level, so ignore by always considering passed
        return true;
    } else {
        Debug.logWarning(UtilProperties.getMessage(resource_error, "OrderAnUnSupportedProductPromoCondInputParameterLhs", UtilMisc.toMap("inputParamEnumId", productPromoCond.getString("inputParamEnumId")), cart.getLocale()), module);
        return false;
    }
    if (Debug.verboseOn())
        Debug.logVerbose("Condition compare done, compareBase=" + compareBase, module);
    if (compareBase != null) {
        int compare = compareBase.intValue();
        if ("PPC_EQ".equals(operatorEnumId)) {
            if (compare == 0)
                return true;
        } else if ("PPC_NEQ".equals(operatorEnumId)) {
            if (compare != 0)
                return true;
        } else if ("PPC_LT".equals(operatorEnumId)) {
            if (compare < 0)
                return true;
        } else if ("PPC_LTE".equals(operatorEnumId)) {
            if (compare <= 0)
                return true;
        } else if ("PPC_GT".equals(operatorEnumId)) {
            if (compare > 0)
                return true;
        } else if ("PPC_GTE".equals(operatorEnumId)) {
            if (compare >= 0)
                return true;
        } else {
            Debug.logWarning(UtilProperties.getMessage(resource_error, "OrderAnUnSupportedProductPromoCondCondition", UtilMisc.toMap("operatorEnumId", operatorEnumId), cart.getLocale()), module);
            return false;
        }
    }
    // default to not meeting the condition
    return false;
}
Also used : RecurrenceInfoException(org.apache.ofbiz.service.calendar.RecurrenceInfoException) GenericValue(org.apache.ofbiz.entity.GenericValue) HashSet(java.util.HashSet) Set(java.util.Set) Calendar(com.ibm.icu.util.Calendar) Timestamp(java.sql.Timestamp) BigDecimal(java.math.BigDecimal) RecurrenceInfo(org.apache.ofbiz.service.calendar.RecurrenceInfo) Iterator(java.util.Iterator) GenericServiceException(org.apache.ofbiz.service.GenericServiceException) ArrayList(java.util.ArrayList) LinkedList(java.util.LinkedList) List(java.util.List) ShoppingCartItem(org.apache.ofbiz.order.shoppingcart.ShoppingCartItem) HashMap(java.util.HashMap) Map(java.util.Map)

Aggregations

ShoppingCartItem (org.apache.ofbiz.order.shoppingcart.ShoppingCartItem)16 BigDecimal (java.math.BigDecimal)12 GenericValue (org.apache.ofbiz.entity.GenericValue)11 HashMap (java.util.HashMap)8 GenericEntityException (org.apache.ofbiz.entity.GenericEntityException)8 CartItemModifyException (org.apache.ofbiz.order.shoppingcart.CartItemModifyException)8 Delegator (org.apache.ofbiz.entity.Delegator)7 ShoppingCart (org.apache.ofbiz.order.shoppingcart.ShoppingCart)7 GenericServiceException (org.apache.ofbiz.service.GenericServiceException)7 Locale (java.util.Locale)5 Map (java.util.Map)5 GeneralException (org.apache.ofbiz.base.util.GeneralException)5 LocalDispatcher (org.apache.ofbiz.service.LocalDispatcher)5 HashSet (java.util.HashSet)4 LinkedList (java.util.LinkedList)4 Timestamp (java.sql.Timestamp)3 CheckOutHelper (org.apache.ofbiz.order.shoppingcart.CheckOutHelper)3 ItemNotFoundException (org.apache.ofbiz.order.shoppingcart.ItemNotFoundException)3 Calendar (com.ibm.icu.util.Calendar)2 ArrayList (java.util.ArrayList)2