📄 productpromoworker.java
字号:
// Debug.logInfo("Doing action: " + productPromoAction, module);
try {
ActionResultInfo actionResultInfo = performAction(productPromoAction, cart, delegator, dispatcher, nowTimestamp);
totalDiscountAmount += actionResultInfo.totalDiscountAmount;
quantityLeftInActions += actionResultInfo.quantityLeftInAction;
// only set if true, don't set back to false: implements OR logic (ie if ANY actions change content, redo loop)
boolean actionChangedCart = actionResultInfo.ranAction;
if (actionChangedCart) {
promoUsed = true;
cartChanged = true;
}
} catch (CartItemModifyException e) {
Debug.logError("Error modifying the cart while performing promotion action [" + productPromoAction.getPrimaryKey() + "]: " + e.toString(), module);
}
}
}
}
if (promoUsed) {
cart.addProductPromoUse(productPromo.getString("productPromoId"), productPromoCodeId, totalDiscountAmount, quantityLeftInActions);
} else {
// the promotion was not used, don't try again until we finish a full pass and come back to see the promo conditions are now satisfied based on changes to the cart
break;
}
if (cart.getProductPromoUseCount(productPromoId) > maxUseLimit) {
throw new UseLimitException("ERROR: While calculating promotions the promotion [" + productPromoId + "] action was applied more than " + maxUseLimit + " times, so the calculation has been ended. This should generally never happen unless you have bad rule definitions.");
}
}
return cartChanged;
}
protected static boolean checkCondition(GenericValue productPromoCond, ShoppingCart cart, GenericDelegator delegator, Timestamp nowTimestamp) throws GenericEntityException {
String condValue = productPromoCond.getString("condValue");
String inputParamEnumId = productPromoCond.getString("inputParamEnumId");
String operatorEnumId = productPromoCond.getString("operatorEnumId");
String partyId = cart.getPartyId();
if (Debug.verboseOn()) Debug.logVerbose("Checking promotion condition: " + productPromoCond, module);
int compare = 0;
if ("PPIP_PRODUCT_AMOUNT".equals(inputParamEnumId)) {
// for this type of promo force the operatorEnumId = PPC_EQ, effectively ignore that setting because the comparison is implied in the code
operatorEnumId = "PPC_EQ";
// this type of condition requires items involved to not be involved in any other quantity consuming cond/action, and does not pro-rate the price, just uses the base price
double amountNeeded = 0.0;
if (UtilValidate.isNotEmpty(condValue)) {
amountNeeded = Double.parseDouble(condValue);
}
// Debug.logInfo("Doing Amount Cond with Value: " + amountNeeded, module);
Set productIds = ProductPromoWorker.getPromoRuleCondProductIds(productPromoCond, delegator, nowTimestamp);
List lineOrderedByBasePriceList = cart.getLineListOrderedByBasePrice(false);
Iterator lineOrderedByBasePriceIter = lineOrderedByBasePriceList.iterator();
while (amountNeeded > 0 && lineOrderedByBasePriceIter.hasNext()) {
ShoppingCartItem cartItem = (ShoppingCartItem) 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();
if (!cartItem.getIsPromo() &&
(productIds.contains(cartItem.getProductId()) || (parentProductId != null && productIds.contains(parentProductId))) &&
(product == null || !"N".equals(product.getString("includeInPromotions")))) {
double basePrice = cartItem.getBasePrice();
// get a rough price, round it up to an integer
double quantityNeeded = Math.ceil(amountNeeded / basePrice);
// reduce amount still needed to qualify for promo (amountNeeded)
double quantity = cartItem.addPromoQuantityCandidateUse(quantityNeeded, productPromoCond, false);
// get pro-rated amount based on discount
amountNeeded -= (quantity * basePrice);
}
}
// Debug.logInfo("Doing Amount Cond with Value after finding applicable cart lines: " + amountNeeded, module);
// if amountNeeded > 0 then the promo condition failed, so remove candidate promo uses and increment the promoQuantityUsed to restore it
if (amountNeeded > 0) {
// failed, reset the entire rule, ie including all other conditions that might have been done before
cart.resetPromoRuleUse(productPromoCond.getString("productPromoId"), productPromoCond.getString("productPromoRuleId"));
compare = -1;
} else {
// we got it, the conditions are in place...
compare = 0;
// NOTE: don't confirm promo rule use here, wait until actions are complete for the rule to do that
}
} else if ("PPIP_PRODUCT_TOTAL".equals(inputParamEnumId)) {
// this type of condition allows items involved to be involved in other quantity consuming cond/action, and does pro-rate the price
Double amountNeeded = Double.valueOf(condValue);
double amountAvailable = 0;
// Debug.logInfo("Doing Amount Not Counted Cond with Value: " + amountNeeded, module);
Set productIds = ProductPromoWorker.getPromoRuleCondProductIds(productPromoCond, delegator, nowTimestamp);
List lineOrderedByBasePriceList = cart.getLineListOrderedByBasePrice(false);
Iterator lineOrderedByBasePriceIter = lineOrderedByBasePriceList.iterator();
while (lineOrderedByBasePriceIter.hasNext()) {
ShoppingCartItem cartItem = (ShoppingCartItem) 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();
if (!cartItem.getIsPromo() &&
(productIds.contains(cartItem.getProductId()) || (parentProductId != null && productIds.contains(parentProductId))) &&
(product == null || !"N".equals(product.getString("includeInPromotions")))) {
// just count the entire sub-total of the item
amountAvailable += cartItem.getItemSubTotal();
}
}
// Debug.logInfo("Doing Amount Not Counted Cond with Value after finding applicable cart lines: " + amountNeeded, module);
compare = new Double(amountAvailable).compareTo(amountNeeded);
} else if ("PPIP_PRODUCT_QUANT".equals(inputParamEnumId)) {
// for this type of promo force the operatorEnumId = PPC_EQ, effectively ignore that setting because the comparison is implied in the code
operatorEnumId = "PPC_EQ";
double quantityNeeded = 1.0;
if (UtilValidate.isNotEmpty(condValue)) {
quantityNeeded = Double.parseDouble(condValue);
}
Set productIds = ProductPromoWorker.getPromoRuleCondProductIds(productPromoCond, delegator, nowTimestamp);
List lineOrderedByBasePriceList = cart.getLineListOrderedByBasePrice(false);
Iterator lineOrderedByBasePriceIter = lineOrderedByBasePriceList.iterator();
while (quantityNeeded > 0 && lineOrderedByBasePriceIter.hasNext()) {
ShoppingCartItem cartItem = (ShoppingCartItem) 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();
if (!cartItem.getIsPromo() &&
(productIds.contains(cartItem.getProductId()) || (parentProductId != null && productIds.contains(parentProductId))) &&
(product == null || !"N".equals(product.getString("includeInPromotions")))) {
// reduce quantity still needed to qualify for promo (quantityNeeded)
quantityNeeded -= cartItem.addPromoQuantityCandidateUse(quantityNeeded, productPromoCond, false);
}
}
// if quantityNeeded > 0 then the promo condition failed, so remove candidate promo uses and increment the promoQuantityUsed to restore it
if (quantityNeeded > 0) {
// failed, reset the entire rule, ie including all other conditions that might have been done before
cart.resetPromoRuleUse(productPromoCond.getString("productPromoId"), productPromoCond.getString("productPromoRuleId"));
compare = -1;
} else {
// we got it, the conditions are in place...
compare = 0;
// NOTE: don't confirm rpomo rule use here, wait until actions are complete for the rule to do that
}
/* replaced by PPIP_PRODUCT_QUANT
} else if ("PPIP_PRODUCT_ID_IC".equals(inputParamEnumId)) {
String candidateProductId = condValue;
if (candidateProductId == null) {
// if null, then it's not in the cart
compare = 1;
} else {
// Debug.logInfo("Testing to see if productId \"" + candidateProductId + "\" is in the cart", module);
List productCartItems = cart.findAllCartItems(candidateProductId);
// don't count promotion items in this count...
Iterator pciIter = productCartItems.iterator();
while (pciIter.hasNext()) {
ShoppingCartItem productCartItem = (ShoppingCartItem) pciIter.next();
if (productCartItem.getIsPromo()) pciIter.remove();
}
if (productCartItems.size() > 0) {
//Debug.logError("Item with productId \"" + candidateProductId + "\" IS in the cart", module);
compare = 0;
} else {
//Debug.logError("Item with productId \"" + candidateProductId + "\" IS NOT in the cart", module);
compare = 1;
}
}
} else if ("PPIP_CATEGORY_ID_IC".equals(inputParamEnumId)) {
String productCategoryId = condValue;
Set productIds = new HashSet();
Iterator cartItemIter = cart.iterator();
while (cartItemIter.hasNext()) {
ShoppingCartItem cartItem = (ShoppingCartItem) cartItemIter.next();
if (!cartItem.getIsPromo()) {
productIds.add(cartItem.getProductId());
}
}
compare = 1;
// NOTE: this technique is efficient for a smaller number of items in the cart, if there are a lot of lines
//in the cart then a non-cached query with a set of productIds using the IN operator would be better
Iterator productIdIter = productIds.iterator();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -