Search in sources :

Example 1 with CartItemModifyException

use of org.apache.ofbiz.order.shoppingcart.CartItemModifyException 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 CartItemModifyException

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

the class OrderServices method shoppingCartTest.

// sample test services
public static Map<String, Object> shoppingCartTest(DispatchContext dctx, Map<String, ? extends Object> context) {
    Locale locale = (Locale) context.get("locale");
    ShoppingCart cart = new ShoppingCart(dctx.getDelegator(), "9000", "webStore", locale, "USD");
    try {
        cart.addOrIncreaseItem("GZ-1005", null, BigDecimal.ONE, null, null, null, null, null, null, null, "DemoCatalog", null, null, null, null, dctx.getDispatcher());
    } catch (CartItemModifyException | ItemNotFoundException e) {
        Debug.logError(e, module);
    }
    try {
        dctx.getDispatcher().runAsync("shoppingCartRemoteTest", UtilMisc.toMap("cart", cart), true);
    } catch (GenericServiceException e) {
        Debug.logError(e, module);
    }
    return ServiceUtil.returnSuccess();
}
Also used : Locale(java.util.Locale) ShoppingCart(org.apache.ofbiz.order.shoppingcart.ShoppingCart) CartItemModifyException(org.apache.ofbiz.order.shoppingcart.CartItemModifyException) GenericServiceException(org.apache.ofbiz.service.GenericServiceException) ItemNotFoundException(org.apache.ofbiz.order.shoppingcart.ItemNotFoundException)

Example 3 with CartItemModifyException

use of org.apache.ofbiz.order.shoppingcart.CartItemModifyException 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 4 with CartItemModifyException

use of org.apache.ofbiz.order.shoppingcart.CartItemModifyException 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 5 with CartItemModifyException

use of org.apache.ofbiz.order.shoppingcart.CartItemModifyException 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)

Aggregations

CartItemModifyException (org.apache.ofbiz.order.shoppingcart.CartItemModifyException)12 GenericValue (org.apache.ofbiz.entity.GenericValue)11 ShoppingCart (org.apache.ofbiz.order.shoppingcart.ShoppingCart)9 BigDecimal (java.math.BigDecimal)8 Locale (java.util.Locale)8 Delegator (org.apache.ofbiz.entity.Delegator)8 GenericServiceException (org.apache.ofbiz.service.GenericServiceException)8 GenericEntityException (org.apache.ofbiz.entity.GenericEntityException)7 ShoppingCartItem (org.apache.ofbiz.order.shoppingcart.ShoppingCartItem)7 LocalDispatcher (org.apache.ofbiz.service.LocalDispatcher)7 ItemNotFoundException (org.apache.ofbiz.order.shoppingcart.ItemNotFoundException)6 Timestamp (java.sql.Timestamp)4 HashMap (java.util.HashMap)4 Map (java.util.Map)4 GeneralException (org.apache.ofbiz.base.util.GeneralException)4 CheckOutHelper (org.apache.ofbiz.order.shoppingcart.CheckOutHelper)4 HashSet (java.util.HashSet)3 LinkedList (java.util.LinkedList)3 List (java.util.List)2 ProductConfigWrapper (org.apache.ofbiz.product.config.ProductConfigWrapper)2