Added: 
ofbiz/ofbiz-framework/trunk/applications/product/groovyScripts/product/promo/ProductPromoActionServices.groovy
URL: 
http://svn.apache.org/viewvc/ofbiz/ofbiz-framework/trunk/applications/product/groovyScripts/product/promo/ProductPromoActionServices.groovy?rev=1831783&view=auto
==============================================================================
--- 
ofbiz/ofbiz-framework/trunk/applications/product/groovyScripts/product/promo/ProductPromoActionServices.groovy
 (added)
+++ 
ofbiz/ofbiz-framework/trunk/applications/product/groovyScripts/product/promo/ProductPromoActionServices.groovy
 Thu May 17 14:03:46 2018
@@ -0,0 +1,549 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License") you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.apache.ofbiz.base.util.Debug
+import org.apache.ofbiz.base.util.UtilMisc
+import org.apache.ofbiz.base.util.UtilProperties
+import org.apache.ofbiz.entity.GenericValue
+import org.apache.ofbiz.entity.util.EntityUtil
+import org.apache.ofbiz.order.shoppingcart.CartItemModifyException
+import org.apache.ofbiz.order.shoppingcart.ShoppingCart
+import org.apache.ofbiz.order.shoppingcart.ShoppingCartItem
+import org.apache.ofbiz.order.shoppingcart.product.ProductPromoWorker
+import 
org.apache.ofbiz.order.shoppingcart.product.ProductPromoWorker.ActionResultInfo
+import org.apache.ofbiz.service.GenericServiceException
+import org.apache.ofbiz.service.ServiceUtil
+
+/*
+ * ================================================================
+ * ProductPromoAction Services
+ * ================================================================
+ */
+
+/**
+ * This function return success if conditions are valid and generate gift with 
purchase
+ * @return result
+ */
+def productGWP() {
+    Map result = success()
+
+    GenericValue productPromoAction = parameters.productPromoAction
+    ActionResultInfo actionResultInfo = parameters.actionResultInfo
+    ShoppingCart cart = parameters.shoppingCart
+    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 = ProductPromoWorker.findPromoItem(productPromoAction, 
cart)
+    if (!allowMultipleGwp && itemLoc != null) {
+        if (Debug.verboseOn()) {
+            Debug.logVerbose("Not adding promo item, already there action: " + 
productPromoAction, "ProductPromoActionServices.groovy")
+        }
+        actionResultInfo.ranAction = false
+    } else {
+        BigDecimal quantity
+        if (productPromoAction.quantity != null) {
+            quantity = productPromoAction.getBigDecimal("quantity")
+        } else {
+            if ("Y" == productPromoAction.get("useCartQuantity")) {
+                quantity = BigDecimal.ZERO
+                List<ShoppingCartItem> used = 
ProductPromoWorker.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 (productId) {
+            product = 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, "ProductPromoActionServices.groovy")
+                throw new CartItemModifyException(errMsg)
+            }
+            if ("Y" == 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 {
+                // check inventory on this product, make sure it is available 
before going on
+                //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, 
"ProductPromoActionServices.groovy")
+                        throw new 
CartItemModifyException(ServiceUtil.getErrorMessage(invReqResult))
+                    } else if ("Y" != invReqResult.get("available")) {
+                        
Debug.logWarning(UtilProperties.getMessage(resource_error, 
"OrderNotApplyingGwpBecauseProductIdIsOutOfStockForProductPromoAction", 
UtilMisc.toMap("productId", productId, "productPromoAction", 
productPromoAction), cart.getLocale()), "ProductPromoActionServices.groovy")
+                        productId = null
+                        product = null
+                    }
+                } catch (GenericServiceException e) {
+                    String errMsg = "Fatal error calling inventory checking 
services: " + e.toString()
+                    Debug.logError(e, errMsg, 
"ProductPromoActionServices.groovy")
+                    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, "ProductPromoActionServices.groovy")
+                    throw new 
CartItemModifyException(ServiceUtil.getErrorMessage(invReqResult))
+                } else if ("Y" != invReqResult.get("available")) {
+                    optionProductIdIter.remove()
+                }
+            } catch (GenericServiceException e) {
+                String errMsg = "Fatal error calling inventory checking 
services: " + e.toString()
+                Debug.logError(e, errMsg, "ProductPromoActionServices.groovy")
+                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 (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 (!productId) {
+                    optionProductIds.add(productId)
+                }
+                optionProductIds.remove(alternateGwpProductId)
+                productId = alternateGwpProductId
+                product = from("Product").where("productId", 
productId).cache().queryOne()
+            } else {
+                Debug.logWarning(UtilProperties.getMessage(resource_error, 
"OrderAnAlternateGwpProductIdWasInPlaceButWasEitherNotValidOrIsNoLongerInStockForId",
 UtilMisc.toMap("alternateGwpProductId", alternateGwpProductId), 
cart.getLocale()), "ProductPromoActionServices.groovy")
+            }
+        }
+
+        // if product is null, get one from the productIds set
+        if (!product && 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 = from("Product").where("productId", 
productId).cache().queryOne()
+        }
+        if (!product) {
+            // 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(), "ProductPromoActionServices.groovy")
+            throw e
+        }
+
+        BigDecimal discountAmount = 
quantity.multiply(gwpItem.getBasePrice()).negate()
+        ProductPromoWorker.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(), "ProductPromoActionServices.groovy")
+        }
+
+        actionResultInfo.ranAction = true
+        actionResultInfo.totalDiscountAmount = discountAmount
+        result.actionResultInfo = actionResultInfo
+        return result
+    }
+}
+
+/**
+ * This function return success, if conditions are valid shipping will be set 
free
+ * @return result
+ */
+def productActFreeShip() {
+    Map result = success()
+
+    GenericValue productPromoAction = parameters.productPromoAction
+    ActionResultInfo actionResultInfo = parameters.actionResultInfo
+    ShoppingCart cart = parameters.shoppingCart
+    // this may look a bit funny: on each pass all rules that do free shipping 
will set their owrule 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
+    result.actionResultInfo = actionResultInfo
+    return result
+}
+
+/**
+ * This function return success, if conditions are valid so X Product for Y% 
Discount
+ * @return result
+ */
+def productDISC() {
+    Map result = success()
+
+    GenericValue productPromoAction = parameters.productPromoAction
+    ActionResultInfo actionResultInfo = parameters.actionResultInfo
+    ShoppingCart cart = parameters.shoppingCart
+
+    BigDecimal quantityDesired = !productPromoAction.quantity? 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 = 
ProductPromoWorker.checkConditionsForItem(productPromoAction, cart, cartItem, 
delegator, dispatcher, nowTimestamp)
+        
+        if (passedItemConds && !cartItem.getIsPromo()
+                && (productIds.contains(cartItem.getProductId()) || 
(parentProductId && productIds.contains(parentProductId)))
+                && (!product || "N" != product.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.amount ? 
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) {
+        // 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 = 
ProductPromoWorker.getCartItemsUsedTotalAmount(cart, productPromoAction)
+        if (Debug.verboseOn()) {
+            Debug.logVerbose("Applying promo [" + 
productPromoAction.getPrimaryKey() + "]\n totalAmount=" + totalAmount + ", 
discountAmountTotal=" + discountAmountTotal, 
"ProductPromoActionServices.groovy")
+        }
+        ProductPromoWorker.distributeDiscountAmount(discountAmountTotal, 
totalAmount, ProductPromoWorker.getCartItemsUsed(cart, productPromoAction), 
productPromoAction, delegator)
+        actionResultInfo.ranAction = true
+        actionResultInfo.totalDiscountAmount = discountAmountTotal
+        actionResultInfo.quantityLeftInAction = quantityDesired
+    }
+    result.actionResultInfo = actionResultInfo
+    return result
+}
+
+/**
+ * This function return success, if conditions are valid so X Product for Y 
Discount
+ * @return
+ */
+def productAMDISC() {
+    Map result = success()
+
+    GenericValue productPromoAction = parameters.productPromoAction
+    ActionResultInfo actionResultInfo = parameters.actionResultInfo
+    ShoppingCart cart = parameters.shoppingCart
+
+    BigDecimal quantityDesired = !productPromoAction.quantity? 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 = 
ProductPromoWorker.checkConditionsForItem(productPromoAction, cart, cartItem, 
delegator, dispatcher, nowTimestamp)
+        if (passedItemConds && !cartItem.getIsPromo() &&
+                (productIds.contains(cartItem.getProductId()) || 
(parentProductId != null && productIds.contains(parentProductId))) &&
+                (!product || "N" != 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.amount? 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 = 
ProductPromoWorker.getCartItemsUsedTotalAmount(cart, productPromoAction)
+        if (Debug.verboseOn()) {
+            Debug.logVerbose("Applying promo [" + 
productPromoAction.getPrimaryKey() + "]\n totalAmount=" + totalAmount + ", 
discountAmountTotal=" + discountAmountTotal, 
"ProductPromoActionServices.groovy")
+        }
+        ProductPromoWorker.distributeDiscountAmount(discountAmountTotal, 
totalAmount, ProductPromoWorker.getCartItemsUsed(cart, productPromoAction), 
productPromoAction, delegator)
+        actionResultInfo.ranAction = true
+        actionResultInfo.totalDiscountAmount = discountAmountTotal
+        actionResultInfo.quantityLeftInAction = quantityDesired
+    }
+    result.actionResultInfo = actionResultInfo
+    return result
+}
+
+/**
+ *
+ * @return
+ */
+def productPrice() {
+
+    Map result = success()
+
+    GenericValue productPromoAction = parameters.productPromoAction
+    ActionResultInfo actionResultInfo = parameters.actionResultInfo
+    ShoppingCart cart = parameters.shoppingCart
+
+    // 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.quantity? BigDecimal.ONE 
: productPromoAction.getBigDecimal("quantity")
+    BigDecimal desiredAmount = !productPromoAction.amount? 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 = 
ProductPromoWorker.checkConditionsForItem(productPromoAction, cart, cartItem, 
delegator, dispatcher, nowTimestamp)
+
+        if (passedItemConds &&
+                !cartItem.getIsPromo() &&
+                (productIds.contains(cartItem.getProductId()) || 
(parentProductId != null && productIds.contains(parentProductId))) &&
+                (product == null || "N" != 
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()
+        ProductPromoWorker.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"))
+    }
+    result.actionResultInfo = actionResultInfo
+    return result
+
+}
+
+def productOrderPercent() {
+    Map result = success()
+
+    GenericValue productPromoAction = parameters.productPromoAction
+    ActionResultInfo actionResultInfo = parameters.actionResultInfo
+    ShoppingCart cart = parameters.shoppingCart
+
+    BigDecimal percentage = !productPromoAction.amount ? BigDecimal.ZERO : 
productPromoAction.getBigDecimal("amount")
+    percentage = percentage.movePointLeft(2).negate()
+    Set<String> productIds = 
ProductPromoWorker.getPromoRuleActionProductIds(productPromoAction, delegator, 
nowTimestamp)
+    BigDecimal amount = BigDecimal.ZERO
+    if (!productIds) {
+        amount = cart.getSubTotalForPromotions().multiply(percentage)
+    } else {
+        amount = cart.getSubTotalForPromotions(productIds).multiply(percentage)
+    }
+    if (amount.compareTo(BigDecimal.ZERO) != 0) {
+        ProductPromoWorker.doOrderPromoAction(productPromoAction, cart, 
amount, "amount", delegator)
+        actionResultInfo.ranAction = true
+        actionResultInfo.totalDiscountAmount = amount
+    }
+    result.actionResultInfo = actionResultInfo
+    return result
+}
+
+def productOrderAmount() {
+    Map result = success()
+
+    GenericValue productPromoAction = parameters.productPromoAction
+    ActionResultInfo actionResultInfo = parameters.actionResultInfo
+    ShoppingCart cart = parameters.shoppingCart
+
+    BigDecimal amount = (!productPromoAction.amount? 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) {
+        ProductPromoWorker.doOrderPromoAction(productPromoAction, cart, 
amount, "amount", delegator)
+        actionResultInfo.ranAction = true
+        actionResultInfo.totalDiscountAmount = amount
+    }
+    result.actionResultInfo = actionResultInfo
+    return result
+}
+
+def productSpecialPrice() {
+    Map result = success()
+
+    GenericValue productPromoAction = parameters.productPromoAction
+    ActionResultInfo actionResultInfo = parameters.actionResultInfo
+    ShoppingCart cart = parameters.shoppingCart
+
+    // 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 (!itemProductId
+            || productIds && !productIds.contains(itemProductId)
+            || !cartItem.getSpecialPromoPrice()) {
+            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 > BigDecimal.ZERO) {
+                BigDecimal amount = difference.multiply(quantityUsed)
+                ProductPromoWorker.doOrderItemPromoAction(productPromoAction, 
cartItem, amount, "amount", delegator)
+                actionResultInfo.ranAction = true
+                actionResultInfo.totalDiscountAmount = amount
+            }
+        }
+    }
+    result.actionResultInfo = actionResultInfo
+    return result
+}
+
+def productShipCharge() {
+    Map result = success()
+
+    GenericValue productPromoAction = parameters.productPromoAction
+    ActionResultInfo actionResultInfo = parameters.actionResultInfo
+    ShoppingCart cart = parameters.shoppingCart
+
+    BigDecimal percentage = (!productPromoAction.amount? 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") == amount) {
+            actionResultInfo.ranAction = false  // already ran, no need to 
repeat
+        } else {
+            if (existingOrderPromoIndex != -1 && 
cart.getAdjustment(existingOrderPromoIndex).getBigDecimal("amount") != amount) {
+                cart.removeAdjustment(existingOrderPromoIndex)
+            }
+            ProductPromoWorker.doOrderPromoAction(productPromoAction, cart, 
amount, "amount", delegator)
+            actionResultInfo.ranAction = true
+            actionResultInfo.totalDiscountAmount = amount
+        }
+    }
+    result.actionResultInfo = actionResultInfo
+    return result
+}
+
+def productTaxPercent() {
+    Map result = success()
+
+    GenericValue productPromoAction = parameters.productPromoAction
+    ActionResultInfo actionResultInfo = parameters.actionResultInfo
+    ShoppingCart cart = parameters.shoppingCart
+
+    BigDecimal percentage = (!productPromoAction.amount? BigDecimal.ZERO : 
(productPromoAction.getBigDecimal("amount").movePointLeft(2))).negate()
+    BigDecimal amount = cart.getTotalSalesTax().multiply(percentage)
+    if (amount.compareTo(BigDecimal.ZERO) != 0) {
+        ProductPromoWorker.doOrderPromoAction(productPromoAction, cart, 
amount, "amount", delegator)
+        actionResultInfo.ranAction = true
+        actionResultInfo.totalDiscountAmount = amount
+    }
+    result.actionResultInfo = actionResultInfo
+    return result
+}
+
+
+
+

Propchange: 
ofbiz/ofbiz-framework/trunk/applications/product/groovyScripts/product/promo/ProductPromoActionServices.groovy
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
ofbiz/ofbiz-framework/trunk/applications/product/groovyScripts/product/promo/ProductPromoActionServices.groovy
------------------------------------------------------------------------------
    svn:keywords = Date Rev Author URL Id

Propchange: 
ofbiz/ofbiz-framework/trunk/applications/product/groovyScripts/product/promo/ProductPromoActionServices.groovy
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: 
ofbiz/ofbiz-framework/trunk/applications/product/groovyScripts/product/promo/ProductPromoCondServices.groovy
URL: 
http://svn.apache.org/viewvc/ofbiz/ofbiz-framework/trunk/applications/product/groovyScripts/product/promo/ProductPromoCondServices.groovy?rev=1831783&view=auto
==============================================================================
--- 
ofbiz/ofbiz-framework/trunk/applications/product/groovyScripts/product/promo/ProductPromoCondServices.groovy
 (added)
+++ 
ofbiz/ofbiz-framework/trunk/applications/product/groovyScripts/product/promo/ProductPromoCondServices.groovy
 Thu May 17 14:03:46 2018
@@ -0,0 +1,587 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License") you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.apache.ofbiz.base.util.Debug
+import org.apache.ofbiz.base.util.UtilDateTime
+import org.apache.ofbiz.base.util.UtilMisc
+import org.apache.ofbiz.entity.GenericValue
+import org.apache.ofbiz.order.shoppingcart.ShoppingCart
+import org.apache.ofbiz.order.shoppingcart.ShoppingCartItem
+import org.apache.ofbiz.order.shoppingcart.product.ProductPromoWorker
+import org.apache.ofbiz.service.GenericServiceException
+import org.apache.ofbiz.service.ServiceUtil
+import org.apache.ofbiz.service.calendar.RecurrenceInfo
+import org.apache.ofbiz.service.calendar.RecurrenceInfoException
+
+import java.math.MathContext
+import java.math.RoundingMode
+import java.sql.Timestamp
+
+/*
+ * ================================================================
+ * ProductPromoCond Services
+ * ================================================================
+ */
+
+/**
+ * This function return success if the conditions have been met for the 
product amount
+ * @return result
+ */
+def productAmount() {
+    Map result = success()
+    int compareBase = -1
+    result.operatorEnumId = "PPC_EQ"
+
+    GenericValue productPromoCond = parameters.productPromoCond
+    ShoppingCart cart = parameters.shoppingCart
+    String condValue = productPromoCond.condValue
+
+    // 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 (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 = 
ProductPromoWorker.checkConditionsForItem(productPromoCond, cart, cartItem, 
delegator, dispatcher, nowTimestamp)
+        boolean checkAmount = passedItemConds && !cartItem.getIsPromo() &&
+                (productIds.contains(cartItem.getProductId()) || 
(parentProductId && productIds.contains(parentProductId))) &&
+                (!product || !product.includeInPromotions || 'N' != 
product.includeInPromotions)
+        if (checkAmount) {
+            MathContext generalRounding = new MathContext(10)
+            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.productPromoId, 
productPromoCond.productPromoRuleId)
+        compareBase = -1
+    } else {
+        // we got it, the conditions are in place...
+        compareBase = 0
+        // NOTE: don't confirm promo rule use here, wait until actions are 
complete for the rule to do that
+    }
+    result.compareBase = compareBase
+    return result
+}
+
+/**
+ * This function return success if the conditions have been met for the 
product total
+ * @return result
+ */
+def productTotal() {
+    Map result = success()
+    int compareBase = -1
+
+    GenericValue productPromoCond = parameters.productPromoCond
+    ShoppingCart cart = parameters.shoppingCart
+    String condValue = productPromoCond.condValue
+    Timestamp nowTimestamp = UtilDateTime.nowTimestamp()
+
+    if (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 = 
ProductPromoWorker.checkConditionsForItem(productPromoCond, cart, cartItem, 
delegator, dispatcher, nowTimestamp)
+            if (passedItemConds && !cartItem.getIsPromo() 
+                    && (productIds.contains(cartItem.getProductId()) || 
(parentProductId && productIds.contains(parentProductId)))
+                    && (!product || 'N' != product.includeInPromotions)) {
+
+                // just count the entire sub-total of the item
+                amountAvailable = 
amountAvailable.add(cartItem.getItemSubTotal())
+            }
+        }
+        compareBase = amountAvailable.compareTo(amountNeeded)
+    }
+    result.compareBase = Integer.valueOf(compareBase)
+    return result
+}
+
+/**
+ * This function return success if the conditions have been met for the 
product quantity
+ * @return result
+ */
+def productQuant() {
+    Map result = success()
+
+    GenericValue productPromoCond = parameters.productPromoCond
+    String operatorEnumId = productPromoCond.operatorEnumId
+    ShoppingCart cart = parameters.shoppingCart
+    String condValue = productPromoCond.condValue
+    Timestamp nowTimestamp = UtilDateTime.nowTimestamp()
+
+    if (!operatorEnumId) {
+        // 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 (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 = 
ProductPromoWorker.checkConditionsForItem(productPromoCond, cart, cartItem, 
delegator, dispatcher, nowTimestamp)
+        if (passedItemConds && !cartItem.getIsPromo() &&
+                (productIds.contains(cartItem.getProductId()) || 
(parentProductId && productIds.contains(parentProductId))) &&
+                (!product || 'N' != product.includeInPromotions)) {
+            // reduce quantity still needed to qualify for promo 
(quantityNeeded)
+            quantityNeeded = 
quantityNeeded.subtract(cartItem.addPromoQuantityCandidateUse(quantityNeeded, 
productPromoCond, "PPC_EQ" != 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.productPromoId, 
productPromoCond.productPromoRuleId)
+        compareBase = -1
+    } else {
+        // we got it, the conditions are in place...
+        compareBase = 0
+        // NOTE: don't confirm rpomo rule use here, wait until actions are 
complete for the rule to do that
+    }
+    result.compareBase = Integer.valueOf(compareBase)
+    return result
+}
+
+/**
+ * This function return success if the conditions have been met for new 
accounts
+ * @return result
+ */
+def productNewACCT() {
+    // promotion description="Account Days Since Created"
+    Map result = success()
+
+    GenericValue productPromoCond = parameters.productPromoCond
+    ShoppingCart cart = parameters.shoppingCart
+    String condValue = productPromoCond.condValue
+    Timestamp nowTimestamp = UtilDateTime.nowTimestamp()
+    int compareBase = -1
+    if (condValue) {
+        BigDecimal acctDays = cart.getPartyDaysSinceCreated(nowTimestamp)
+        if (acctDays) {
+            compareBase = acctDays.compareTo(new BigDecimal(condValue))
+        }
+    }
+    result.compareBase = Integer.valueOf(compareBase)
+    return result
+}
+
+/**
+ * This function return success if the conditions have been met for the party 
ID
+ * @return result
+ */
+def productPartyID() {
+    Map result = success()
+
+    Map productPromoCond = parameters.productPromoCond
+    ShoppingCart cart = parameters.shoppingCart
+    String condValue = productPromoCond.condValue
+    String partyId = cart.getPartyId()
+    int compareBase = 1
+    if (partyId && condValue) {
+        compareBase = partyId.compareTo(condValue)
+    }
+    result.compareBase = Integer.valueOf(compareBase)
+    return result
+}
+
+/**
+ * This function return success if the conditions have been met for the party 
group member
+ * @return result
+ */
+def productPartyGM() {
+    Map result = success()
+
+    GenericValue productPromoCond = parameters.productPromoCond
+    ShoppingCart cart = parameters.shoppingCart
+    String condValue = productPromoCond.condValue
+    String partyId = cart.getPartyId()
+
+    int compareBase = 1
+    if (partyId && condValue) {
+        String groupPartyId = condValue
+        if (partyId == groupPartyId) {
+            compareBase = 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 = 
from("PartyRelationship").where("partyIdFrom", groupPartyId, "partyIdTo", 
partyId, "partyRelationshipTypeId", 
"GROUP_ROLLUP").cache(true).filterByDate().queryList()
+
+            if (partyRelationshipList) {
+                compareBase = 0
+            } else {
+                compareBase = 
ProductPromoWorker.checkConditionPartyHierarchy(delegator, nowTimestamp, 
groupPartyId, partyId)
+            }
+        }
+    }
+    result.compareBase = Integer.valueOf(compareBase)
+    return result
+}
+
+/**
+ * This function return success if the  conditions have been met for the party 
class
+ * @return result
+ */
+def productPartyClass() {
+    Map result = success()
+
+    GenericValue productPromoCond = parameters.productPromoCond
+    ShoppingCart cart = parameters.shoppingCart
+    String condValue = productPromoCond.condValue
+    String partyId = cart.getPartyId()
+
+    int compareBase = 1
+    if (partyId && condValue) {
+        String partyClassificationGroupId = condValue
+        // find any PartyClassification
+        // and from/thru date within range
+        List<GenericValue> partyClassificationList = 
from("PartyClassification").where("partyId", partyId, 
"partyClassificationGroupId", 
partyClassificationGroupId).cache(true).filterByDate().queryList()
+        // then 0 (equals), otherwise 1 (not equals)
+        compareBase = partyClassificationList? 0: 1
+    }
+    result.compareBase = Integer.valueOf(compareBase)
+    return result
+}
+
+/**
+ * This function return success if the conditions have been met for the role 
type
+ * @return result
+ */
+def productRoleType() {
+    Map result = success()
+
+    GenericValue productPromoCond = parameters.productPromoCond
+    ShoppingCart cart = parameters.shoppingCart
+    String condValue = productPromoCond.condValue
+    String partyId = cart.getPartyId()
+
+    int compareBase = 1
+    if (partyId && condValue) {
+        // if a PartyRole exists for this partyId and the specified roleTypeId
+        GenericValue partyRole = from("PartyRole").where("partyId", partyId, 
"roleTypeId", condValue).cache(true).queryOne()
+        // then 0 (equals), otherwise 1 (not equals)
+        compareBase = partyRole? 0: 1
+    }
+    result.compareBase = Integer.valueOf(compareBase)
+    return result
+}
+
+/**
+ * This function return success if the conditions have been met for the 
shipping destination
+ * @return result
+ */
+def productGeoID() {
+    Map result = success()
+
+    GenericValue productPromoCond = parameters.productPromoCond
+    String condValue = productPromoCond.condValue
+    ShoppingCart cart = parameters.shoppingCart
+    GenericValue shippingAddress = cart.getShippingAddress()
+
+    int compareBase = 1
+    if (condValue && shippingAddress) {
+        if (condValue == shippingAddress.countryGeoId
+                || condValue == shippingAddress.countyGeoId
+                || condValue == shippingAddress.postalCodeGeoId
+                || condValue == shippingAddress.stateProvinceGeoId) {
+            compareBase = 0
+        } else {
+            List<GenericValue> geoAssocList = 
from("GeoAssoc").where("geoIdTo", condValue).queryList()
+            for (GenericValue geo : geoAssocList) {
+                if (geo.geoId == shippingAddress.countryGeoId
+                        || geo.geoId == shippingAddress.countyGeoId
+                        || geo.geoId == shippingAddress.postalCodeGeoId
+                        || geo.geoId == shippingAddress.stateProvinceGeoId) {
+                    compareBase = 0
+                    break
+                }
+            }
+        }
+    }
+    result.compareBase = Integer.valueOf(compareBase)
+    return result
+}
+
+/**
+ * This function return success if the conditions have been met for the 
product order total
+ * @return result
+ */
+def productOrderTotal() {
+    Map result = success()
+    int compareBase = 1
+
+    GenericValue productPromoCond = parameters.productPromoCond
+    ShoppingCart cart = parameters.shoppingCart
+    String condValue = productPromoCond.condValue
+
+    if (condValue) {
+        BigDecimal orderSubTotal = cart.getSubTotalForPromotions()
+        if (Debug.infoOn()) Debug.logInfo("Doing order total compare: 
orderSubTotal=" + orderSubTotal, module)
+        compareBase = orderSubTotal.compareTo(new BigDecimal(condValue))
+    }
+    result.compareBase = Integer.valueOf(compareBase)
+    return result
+}
+
+/**
+ * This function return success if the conditions have been met for the 
product order sub-total X in last Y Months
+ * @return result
+ */
+def productOrderHist() {
+    // description="Order sub-total X in last Y Months"
+    GenericValue productPromoCond = parameters.productPromoCond
+    ShoppingCart cart = parameters.shoppingCart
+    String condValue = productPromoCond.condValue
+    String otherValue = productPromoCond.otherValue
+    String partyId = cart.getPartyId()
+    GenericValue userLogin = cart.getUserLogin()
+    Map result = success()
+    int compareBase = 1
+    result.operatorEnumId = "PPC_GTE"
+
+    if (partyId && userLogin && condValue) {
+        // call the getOrderedSummaryInformation service to get the sub-total
+        int monthsToInclude = 12
+        if (otherValue != null) {
+            monthsToInclude = Integer.parseInt(otherValue)
+        }
+        Map<String, Object> serviceIn = [partyId: partyId, roleTypeId: 
"PLACING_CUSTOMER", orderTypeId: "SALES_ORDER", statusId: "ORDER_COMPLETED",
+                                         monthsToInclude: 
Integer.valueOf(monthsToInclude), userLogin: userLogin]
+        try {
+            Map<String, Object> serviceResult = run service: 
"getOrderedSummaryInformation", with: serviceIn
+            if (ServiceUtil.isError(serviceResult)) {
+                Debug.logError("Error calling getOrderedSummaryInformation 
service for the PPIP_ORST_HIST ProductPromo condition input value: " + 
ServiceUtil.getErrorMessage(result), module)
+                return serviceResult
+            } else {
+                BigDecimal orderSubTotal = (BigDecimal) 
serviceResult.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 = 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 ServiceUtil.returnError("Error getting order history")
+        }
+    }
+    result.compareBase = compareBase
+    return result
+}
+
+/**
+ * This function return success if the conditions have been met for the 
product order of the current year
+ * @return result
+ */
+def productOrderYear() {
+    Map result = success()
+    compareBase = 1
+
+    GenericValue productPromoCond = parameters.productPromoCond
+    ShoppingCart cart = parameters.shoppingCart
+    String condValue = productPromoCond.condValue
+    GenericValue userLogin = cart.getUserLogin()
+    String partyId = cart.getPartyId()
+
+    // description="Order sub-total X since beginning of current year"
+    if (partyId && userLogin  && 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> serviceResult = 
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 serviceResult
+            } 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 = 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 ServiceUtil.returnError("Error getting order history")
+        }
+    }
+    result.compareBase = Integer.valueOf(compareBase)
+    return result
+}
+
+/**
+ * This function return success if the conditions have been met for the 
product order last year
+ * @return result
+ */
+def productOrderLastYear() {
+    // description="Order sub-total X since beginning of last year"
+    Map result = success()
+    compareBase = 1
+
+    GenericValue productPromoCond = parameters.productPromoCond
+    ShoppingCart cart = parameters.shoppingCart
+    String condValue = productPromoCond.condValue
+    GenericValue userLogin = cart.getUserLogin()
+    String partyId = cart.getPartyId()
+
+    if (partyId && userLogin  && 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> serviceResult = 
dispatcher.runSync("getOrderedSummaryInformation", serviceIn)
+            if (ServiceUtil.isError(serviceResult)) {
+                Debug.logError("Error calling getOrderedSummaryInformation 
service for the PPIP_ORST_LAST_YEAR ProductPromo condition input value: " + 
ServiceUtil.getErrorMessage(result), module)
+                return serviceResult
+            } 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 = 
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 ServiceUtil.returnError("Error getting order history")
+        }
+    }
+    result.compareBase = Integer.valueOf(compareBase)
+    return result
+}
+
+/**
+ * This function return success if the conditions have been met for the 
product promo recurrence
+ * @return result
+ */
+def productPromoRecurrence() {
+    Map result = success()
+    int compareBase = 1
+    GenericValue productPromoCond = parameters.productPromoCond
+    String condValue = productPromoCond.condValue
+
+    if (condValue) {
+        GenericValue recurrenceInfo = 
from("RecurrenceInfo").where("recurrenceInfoId", condValue).cache().queryOne();
+        if (recurrenceInfo) {
+            RecurrenceInfo recurrence = null
+            try {
+                recurrence = new RecurrenceInfo(recurrenceInfo)
+            } catch (RecurrenceInfoException e) {
+                Debug.logError(e, module)
+            }
+
+            // check the current recurrence
+            if (recurrence && recurrence.isValidCurrent()) {
+                compareBase = 0
+            }
+        }
+    }
+
+    result.compareBase = Integer.valueOf(compareBase)
+    return result
+}
+
+/**
+ * This function return success if the conditions have been met for the 
product total shipping
+ * @return result
+ */
+def productShipTotal() {
+    Map result = success()
+    compareBase = 1
+
+    GenericValue productPromoCond = parameters.productPromoCond
+    String condValue = productPromoCond.condValue
+    ShoppingCart cart = parameters.shoppingCart
+
+    if (condValue) {
+        BigDecimal orderTotalShipping = cart.getTotalShipping()
+        if (Debug.verboseOn()) {
+            Debug.logVerbose("Doing order total Shipping compare: 
ordertotalShipping=" + orderTotalShipping, module)
+        }
+        compareBase = orderTotalShipping.compareTo(new BigDecimal(condValue))
+    }
+    result.compareBase = Integer.valueOf(compareBase)
+    return result
+}
+
+/**
+ * This function do nothing except to return true for the product list price 
minimum amount
+ * @return true
+ */
+def productListPriceMinAmount() {
+    // does nothing on order level, only checked on item level, so ignore by 
always considering passed
+    return true
+}
+
+/**
+ * This function do nothing except to return true for the product list percent 
minimum amount
+ * @return true
+ */
+def productListPriceMinPercent() {
+    // does nothing on order level, only checked on item level, so ignore by 
always considering passed
+    return true
+}

Propchange: 
ofbiz/ofbiz-framework/trunk/applications/product/groovyScripts/product/promo/ProductPromoCondServices.groovy
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
ofbiz/ofbiz-framework/trunk/applications/product/groovyScripts/product/promo/ProductPromoCondServices.groovy
------------------------------------------------------------------------------
    svn:keywords = Date Rev Author URL Id

Propchange: 
ofbiz/ofbiz-framework/trunk/applications/product/groovyScripts/product/promo/ProductPromoCondServices.groovy
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: 
ofbiz/ofbiz-framework/trunk/applications/product/groovyScripts/product/test/ProductPromoActionTests.groovy
URL: 
http://svn.apache.org/viewvc/ofbiz/ofbiz-framework/trunk/applications/product/groovyScripts/product/test/ProductPromoActionTests.groovy?rev=1831783&view=auto
==============================================================================
--- 
ofbiz/ofbiz-framework/trunk/applications/product/groovyScripts/product/test/ProductPromoActionTests.groovy
 (added)
+++ 
ofbiz/ofbiz-framework/trunk/applications/product/groovyScripts/product/test/ProductPromoActionTests.groovy
 Thu May 17 14:03:46 2018
@@ -0,0 +1,355 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License") you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.apache.ofbiz.base.util.Debug
+import org.apache.ofbiz.base.util.UtilDateTime
+import org.apache.ofbiz.base.util.UtilMisc
+import org.apache.ofbiz.base.util.UtilValidate
+import org.apache.ofbiz.entity.GenericValue
+import org.apache.ofbiz.entity.util.EntityQuery
+import org.apache.ofbiz.order.shoppingcart.CheckOutHelper
+import org.apache.ofbiz.order.shoppingcart.ShoppingCart
+import org.apache.ofbiz.order.shoppingcart.ShoppingCartItem
+import org.apache.ofbiz.testtools.GroovyScriptTestCase
+import org.apache.ofbiz.order.shoppingcart.product.ProductPromoWorker
+import 
org.apache.ofbiz.order.shoppingcart.product.ProductPromoWorker.ActionResultInfo
+import org.apache.ofbiz.service.ServiceUtil
+
+import java.sql.Timestamp
+import java.util.Map
+
+class ProductPromoActionTest extends GroovyScriptTestCase {
+
+    ShoppingCart loadOrder(String orderId) {
+        GenericValue permUserLogin = 
EntityQuery.use(delegator).from("UserLogin").where("userLoginId", 
"system").cache().queryOne()
+        Map<String, Object> serviceCtx = [orderId: orderId,
+                skipInventoryChecks: true, // the items are already reserved, 
no need to check again
+                skipProductChecks: true, // the products are already in the 
order, no need to check their validity now
+                userLogin: permUserLogin]
+        Map<String, Object> loadCartResp = 
dispatcher.runSync("loadCartFromOrder", serviceCtx)
+
+        return loadCartResp.shoppingCart
+    }
+
+    Map prepareConditionMap(ShoppingCart cart, BigDecimal amount, boolean 
persist) {
+        GenericValue productPromoAction = 
delegator.makeValue("ProductPromoAction", [amount: amount, 
orderAdjustmentTypeId:'PROMOTION_ADJUSTMENT'])
+        if (persist) {
+            GenericValue productPromo = delegator.makeValue("ProductPromo", 
[productPromoId: 'TEST'])
+            delegator.createOrStore(productPromo)
+            GenericValue productPromoRule = 
delegator.makeValue("ProductPromoRule", [productPromoId: 'TEST', 
productPromoRuleId:'01'])
+            delegator.createOrStore(productPromoRule)
+            productPromoAction.productPromoId = 'TEST'
+            productPromoAction.productPromoRuleId = '01'
+            productPromoAction.productPromoActionSeqId = '01'
+            delegator.createOrStore(productPromoAction)
+        }
+        return  [shoppingCart: cart, nowTimestamp: 
UtilDateTime.nowTimestamp(), actionResultInfo: new ActionResultInfo(), 
productPromoAction: productPromoAction]
+    }
+
+    /**
+     * This test check if the function productTaxPercent work correctly
+     *  1. test failed with passing non valid value
+     *  2. test success if the tax percent promo is set for tax percent
+     */
+    void testActionProductTaxPercent() {
+        ShoppingCart cart = loadOrder("DEMO10090")
+
+        Map<String, Object> serviceContext = prepareConditionMap(cart, 10, 
true)
+        Map<String, Object> serviceResult = 
dispatcher.runSync("productPromoActTaxPercent", serviceContext)
+
+        //Check result service false test
+        assert ServiceUtil.isSuccess(serviceResult)
+        assert !serviceResult.actionResultInfo.ranAction
+        assert serviceResult.actionResultInfo.totalDiscountAmount == 0
+
+        //Increase item quantity to generate higher tax amount
+        for (ShoppingCartItem item : cart.items()) {
+            if (!item.getIsPromo()) {
+                item.setQuantity(300, dispatcher, cart)
+            }
+        }
+
+        //Add tax to cart
+        CheckOutHelper coh = new CheckOutHelper(dispatcher, delegator, cart);
+        coh.calcAndAddTax(false);
+
+        serviceResult = dispatcher.runSync("productPromoActTaxPercent", 
serviceContext)
+
+        //Check result service
+        assert ServiceUtil.isSuccess(serviceResult)
+        assert serviceResult.actionResultInfo.ranAction
+        assert serviceResult.actionResultInfo.totalDiscountAmount != null
+    }
+
+    /**
+     * This test check if the function productShipCharge work correctly
+     *  1. test failed with passing non valid value
+     *  2. test success if the ship charge promo is set for the shipping amount
+     */
+    void testProductShipCharge() {
+        ShoppingCart cart = loadOrder("DEMO10090")
+
+        Map<String, Object> serviceContext = prepareConditionMap(cart, 10, 
true)
+        Map<String, Object> serviceResult = 
dispatcher.runSync("productPromoActShipCharge", serviceContext)
+
+        //Check result service false test
+        assert ServiceUtil.isSuccess(serviceResult)
+        assert !serviceResult.actionResultInfo.ranAction
+        assert serviceResult.actionResultInfo.totalDiscountAmount == 0
+
+        //Add shipgroup estimate to cart
+        cart.setItemShipGroupEstimate(22 , 0)
+
+        serviceResult = dispatcher.runSync("productPromoActShipCharge", 
serviceContext)
+
+        //Check result service
+        assert ServiceUtil.isSuccess(serviceResult)
+        assert serviceResult.actionResultInfo.ranAction
+        assert serviceResult.actionResultInfo.totalDiscountAmount != null
+    }
+
+    /**
+     * This test check if the function PoductSpecialPrice work correctly
+     *  1. test failed with passing non valid value
+     *  2. test success if the special price is set
+     */
+    void testPoductSpecialPrice() {
+        ShoppingCart cart = loadOrder("DEMO10091")
+
+        Map<String, Object> serviceContext = prepareConditionMap(cart, 10, 
false)
+        GenericValue productPromoAction = 
EntityQuery.use(delegator).from("ProductPromoAction").where("productPromoId", 
"9013", "productPromoRuleId", "01", "productPromoActionSeqId", "01").queryOne()
+        serviceContext.productPromoAction = productPromoAction
+        Map<String, Object> serviceResult = 
dispatcher.runSync("productPromoActProdSpecialPrice", serviceContext)
+
+        //Check result service false test
+        assert ServiceUtil.isSuccess(serviceResult)
+        assert !serviceResult.actionResultInfo.ranAction
+        assert serviceResult.actionResultInfo.totalDiscountAmount == 0
+
+        //Add item to cart to trigger action
+        int itemIndex = cart.addItemToEnd("WG-1111", 100, 10, null, null, 
null, null, null, dispatcher, null, null)
+        ShoppingCartItem item = cart.findCartItem(itemIndex)
+        if (item) {
+            item.setSpecialPromoPrice(BigDecimal.valueOf(22))
+        }
+
+        serviceResult = dispatcher.runSync("productPromoActProdSpecialPrice", 
serviceContext)
+
+        //Check result service
+        assert ServiceUtil.isSuccess(serviceResult)
+        assert serviceResult.actionResultInfo.ranAction
+        assert serviceResult.actionResultInfo.totalDiscountAmount != null
+    }
+
+    /**
+     * This test check if the function ProductOrderAmount work correctly
+     *  1. test success if the order amount off is set
+     */
+    void testProductOrderAmount() {
+        ShoppingCart cart = loadOrder("DEMO10090")
+
+        Map<String, Object> serviceContext = prepareConditionMap(cart, 10, 
false)
+        GenericValue productPromoAction = 
EntityQuery.use(delegator).from("ProductPromoAction").where("productPromoId", 
"9012", "productPromoRuleId", "01", "productPromoActionSeqId", "01").queryOne()
+        serviceContext.productPromoAction = productPromoAction
+        Map<String, Object> serviceResult = 
dispatcher.runSync("productPromoActOrderAmount", serviceContext)
+
+        //Check result service
+        assert ServiceUtil.isSuccess(serviceResult)
+        assert serviceResult.actionResultInfo.ranAction
+        assert serviceResult.actionResultInfo.totalDiscountAmount != null
+
+        // no condition so no false test
+    }
+
+    /**
+     * This test check if the function productOrderPercent work correctly
+     *  1. test success if the order percent off promo is set
+     *  2. test failed with passing non valid value
+     */
+    void testProductOrderPercent() {
+        ShoppingCart cart = loadOrder("DEMO10090")
+
+        Map<String, Object> serviceContext = prepareConditionMap(cart, 10, 
false)
+        GenericValue productPromoAction = 
EntityQuery.use(delegator).from("ProductPromoAction").where("productPromoId", 
"9019", "productPromoRuleId", "01", "productPromoActionSeqId", "01").queryOne()
+        serviceContext.productPromoAction = productPromoAction
+        Map<String, Object> serviceResult = 
dispatcher.runSync("productPromoActOrderPercent", serviceContext)
+
+        //Check result service
+        assert ServiceUtil.isSuccess(serviceResult)
+        assert serviceResult.actionResultInfo.ranAction
+        assert serviceResult.actionResultInfo.totalDiscountAmount != null
+
+        //Update cart to cancel trigger action
+        cart.clearAllAdjustments()
+        for (ShoppingCartItem item : cart.items()) {
+            if (!item.getIsPromo()) {
+                GenericValue product = 
EntityQuery.use(delegator).from("Product").where("productId", 
item.getProductId()).queryOne()
+                if (product != null) {
+                    product.put("includeInPromotions", "N")
+                    item._product = product
+                }
+            }
+        }
+
+        serviceContext.shoppingCart = cart
+        serviceContext.actionResultInfo = new ActionResultInfo()
+        serviceResult = dispatcher.runSync("productPromoActOrderPercent", 
serviceContext)
+
+        //Check result service false test
+        assert ServiceUtil.isSuccess(serviceResult)
+        assert !serviceResult.actionResultInfo.ranAction
+        assert serviceResult.actionResultInfo.totalDiscountAmount == 0
+    }
+
+    /**
+     * This test check if the function productPromoActProdPrice work correctly
+     *  1. test failed with passing non valid value
+     *  2. test success if promo is applied
+     */
+    void testProductPrice() {
+        ShoppingCart cart = loadOrder("DEMO10090")
+
+        Map<String, Object> serviceContext = prepareConditionMap(cart, 10, 
false)
+        GenericValue productPromoAction = 
EntityQuery.use(delegator).from("ProductPromoAction").where("productPromoId", 
"9015", "productPromoRuleId", "01", "productPromoActionSeqId", "01").queryOne()
+        serviceContext.productPromoAction = productPromoAction
+        Map<String, Object> serviceResult = 
dispatcher.runSync("productPromoActProdPrice", serviceContext)
+
+        //Check result service false test
+        assert ServiceUtil.isSuccess(serviceResult)
+        assert !serviceResult.actionResultInfo.ranAction
+        assert serviceResult.actionResultInfo.totalDiscountAmount == 0
+
+        //Update cart to trigger action
+        for (ShoppingCartItem item : cart.items()) {
+            if (!item.getIsPromo()) {
+                item.setQuantity(20, dispatcher, cart)
+            }
+        }
+
+        serviceContext.shoppingCart = cart
+        serviceContext.actionResultInfo = new ActionResultInfo()
+        serviceResult = dispatcher.runSync("productPromoActProdPrice", 
serviceContext)
+
+        //Check result service
+        assert ServiceUtil.isSuccess(serviceResult)
+        assert serviceResult.actionResultInfo.ranAction
+        assert serviceResult.actionResultInfo.totalDiscountAmount != null
+    }
+
+    /**
+     * This test check if the function productPromoActProdAMDISC work correctly
+     *  1. test success if promo is applied
+     *  2. test failed with passing already applied promo
+     */
+    void testProductAMDISC() {
+        ShoppingCart cart = loadOrder("DEMO10090")
+
+        Map<String, Object> serviceContext = prepareConditionMap(cart, 10, 
false)
+        GenericValue productPromoAction = 
EntityQuery.use(delegator).from("ProductPromoAction").where("productPromoId", 
"9015", "productPromoRuleId", "01", "productPromoActionSeqId", "01").queryOne()
+        serviceContext.productPromoAction = productPromoAction
+        Map<String, Object> serviceResult = 
dispatcher.runSync("productPromoActProdAMDISC", serviceContext)
+
+        //Check result service
+        assert ServiceUtil.isSuccess(serviceResult)
+        assert serviceResult.actionResultInfo.ranAction
+        assert serviceResult.actionResultInfo.totalDiscountAmount != null
+
+        serviceContext.shoppingCart = cart
+        serviceContext.actionResultInfo = new ActionResultInfo()
+        serviceResult = dispatcher.runSync("productPromoActProdAMDISC", 
serviceContext)
+
+        //Check result service false test
+        assert ServiceUtil.isSuccess(serviceResult)
+        assert !serviceResult.actionResultInfo.ranAction
+        assert serviceResult.actionResultInfo.totalDiscountAmount == 0
+    }
+
+    /**
+     * This test check if the function productPromoActProdDISC work correctly
+     *  1. test success if promo is applied
+     *  2. test failed with passing already applied promo
+     */
+    void testProductDISC() {
+        ShoppingCart cart = loadOrder("DEMO10090")
+
+        Map<String, Object> serviceContext = prepareConditionMap(cart, 10, 
false)
+        GenericValue productPromoAction = 
EntityQuery.use(delegator).from("ProductPromoAction").where("productPromoId", 
"9015", "productPromoRuleId", "01", "productPromoActionSeqId", "01").queryOne()
+        serviceContext.productPromoAction = productPromoAction
+        Map<String, Object> serviceResult = 
dispatcher.runSync("productPromoActProdDISC", serviceContext)
+
+        //Check result service
+        assert ServiceUtil.isSuccess(serviceResult)
+        assert serviceResult.actionResultInfo.ranAction
+        assert serviceResult.actionResultInfo.totalDiscountAmount != null
+
+        //Check result service false test
+        serviceContext.shoppingCart = cart
+        serviceContext.actionResultInfo = new ActionResultInfo()
+        serviceResult = dispatcher.runSync("productPromoActProdDISC", 
serviceContext)
+
+        assert ServiceUtil.isSuccess(serviceResult)
+        assert !serviceResult.actionResultInfo.ranAction
+        assert serviceResult.actionResultInfo.totalDiscountAmount == 0
+    }
+
+    /**
+     * This test check if the function ProductGWP work correctly
+     *  1. test failed with passing non valid value
+     *  2. test success if gift with purchase promo is set for order
+     */
+    void testProductGWP() {
+        ShoppingCart cart = loadOrder("DEMO10090")
+
+        Map<String, Object> serviceContext = prepareConditionMap(cart, 10, 
true)
+        Map<String, Object> serviceResult = 
dispatcher.runSync("productPromoActGiftGWP", serviceContext)
+
+        //Check result service false test
+        assert ServiceUtil.isSuccess(serviceResult)
+        assert !serviceResult.actionResultInfo.ranAction
+        assert serviceResult.actionResultInfo.totalDiscountAmount == 0
+
+        serviceContext.shoppingCart = cart
+        serviceContext.actionResultInfo = new ActionResultInfo()
+        GenericValue productPromoAction = 
EntityQuery.use(delegator).from("ProductPromoAction").where("productPromoId", 
"9017",  "productPromoRuleId", "01", "productPromoActionSeqId", "01").queryOne()
+        serviceContext.productPromoAction = productPromoAction
+        serviceResult = dispatcher.runSync("productPromoActGiftGWP", 
serviceContext)
+
+        //Check result service
+        assert ServiceUtil.isSuccess(serviceResult)
+        assert serviceResult.actionResultInfo.ranAction
+        assert serviceResult.actionResultInfo.totalDiscountAmount != null
+    }
+
+    /**
+     * This test check if the function productActFreeShip work correctly
+     *  1. test success if the free shipping promo is set for tax percent
+     *  2. don't need to make false test because this fonction doesn't need 
condition
+     */
+    void testFreeShippingAct() {
+        ShoppingCart cart = loadOrder("DEMO10090")
+
+        Map<String, Object> serviceContext = prepareConditionMap(cart, 10, 
true)
+        Map<String, Object> serviceResult = 
dispatcher.runSync("productPromoActFreeShip", serviceContext)
+
+        //Check result service
+        assert ServiceUtil.isSuccess(serviceResult)
+        assert serviceResult.actionResultInfo.ranAction
+        assert serviceResult.actionResultInfo.totalDiscountAmount != null
+    }
+}

Propchange: 
ofbiz/ofbiz-framework/trunk/applications/product/groovyScripts/product/test/ProductPromoActionTests.groovy
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
ofbiz/ofbiz-framework/trunk/applications/product/groovyScripts/product/test/ProductPromoActionTests.groovy
------------------------------------------------------------------------------
    svn:keywords = Date Rev Author URL Id

Propchange: 
ofbiz/ofbiz-framework/trunk/applications/product/groovyScripts/product/test/ProductPromoActionTests.groovy
------------------------------------------------------------------------------
    svn:mime-type = text/plain


Reply via email to