📄 productpromoworker.java
字号:
List sortedProductPromoList = new ArrayList(productPromoDiscountMapList.size());
Iterator productPromoDiscountMapIter = productPromoDiscountMapList.iterator();
while (productPromoDiscountMapIter.hasNext()) {
Map productPromoDiscountMap = (Map) productPromoDiscountMapIter.next();
GenericValue productPromo = (GenericValue) productPromoDiscountMap.get("productPromo");
sortedProductPromoList.add(productPromo);
if (Debug.verboseOn()) Debug.logVerbose("Sorted Promo [" + productPromo.getString("productPromoId") + "] with total discount: " + productPromoDiscountMap.get("totalDiscountAmount"), module);
}
// okay, all ready, do the real run, clearing the temporary result first...
cart.clearAllPromotionInformation();
runProductPromos(sortedProductPromoList, cart, delegator, dispatcher, nowTimestamp, false);
} catch (NumberFormatException e) {
Debug.logError(e, "Number not formatted correctly in promotion rules, not completed...", module);
} catch (GenericEntityException e) {
Debug.logError(e, "Error looking up promotion data while doing promotions", module);
}
}
protected static boolean hasOrderTotalCondition(GenericValue productPromo, GenericDelegator delegator) throws GenericEntityException {
boolean hasOtCond = false;
List productPromoConds = delegator.findByAndCache("ProductPromoCond", UtilMisc.toMap("productPromoId", productPromo.get("productPromoId")), UtilMisc.toList("productPromoCondSeqId"));
Iterator productPromoCondIter = productPromoConds.iterator();
while (productPromoCondIter.hasNext()) {
GenericValue productPromoCond = (GenericValue) productPromoCondIter.next();
String inputParamEnumId = productPromoCond.getString("inputParamEnumId");
if ("PPIP_ORDER_TOTAL".equals(inputParamEnumId)) {
hasOtCond = true;
break;
}
}
return hasOtCond;
}
protected static void runProductPromos(List productPromoList, ShoppingCart cart, GenericDelegator delegator, LocalDispatcher dispatcher, Timestamp nowTimestamp, boolean isolatedTestRun) throws GenericEntityException {
String partyId = cart.getPartyId();
// this is our safety net; we should never need to loop through the rules more than a certain number of times, this is that number and may have to be changed for insanely large promo sets...
long maxIterations = 1000;
// part of the safety net to avoid infinite iteration
long numberOfIterations = 0;
// set a max limit on how many times each promo can be run, for cases where there is no use limit this will be the use limit
//default to 2 times the number of items in the cart
long maxUseLimit = 2 * Math.round(cart.getTotalQuantity());
try {
// repeat until no more rules to run: either all rules are run, or no changes to the cart in a loop
boolean cartChanged = true;
while (cartChanged) {
cartChanged = false;
numberOfIterations++;
if (numberOfIterations > maxIterations) {
Debug.logError("ERROR: While calculating promotions the promotion rules where run more than " + maxIterations + " times, so the calculation has been ended. This should generally never happen unless you have bad rule definitions.", module);
break;
}
Iterator productPromoIter = productPromoList.iterator();
while (productPromoIter.hasNext()) {
GenericValue productPromo = (GenericValue) productPromoIter.next();
String productPromoId = productPromo.getString("productPromoId");
List productPromoRules = productPromo.getRelatedCache("ProductPromoRule", null, null);
if (productPromoRules != null && productPromoRules.size() > 0) {
// always have a useLimit to avoid unlimited looping, default to 1 if no other is specified
Long candidateUseLimit = getProductPromoUseLimit(productPromo, partyId, delegator);
Long useLimit = candidateUseLimit;
if (Debug.verboseOn()) Debug.logVerbose("Running promotion [" + productPromoId + "], useLimit=" + useLimit + ", # of rules=" + productPromoRules.size(), module);
boolean requireCode = "Y".equals(productPromo.getString("requireCode"));
// check if promo code required
if (requireCode) {
Set enteredCodes = cart.getProductPromoCodesEntered();
if (enteredCodes.size() > 0) {
// get all promo codes entered, do a query with an IN condition to see if any of those are related
EntityCondition codeCondition = new EntityExpr(new EntityExpr("productPromoId", EntityOperator.EQUALS, productPromoId), EntityOperator.AND, new EntityExpr("productPromoCodeId", EntityOperator.IN, enteredCodes));
// may want to sort by something else to decide which code to use if there is more than one candidate
List productPromoCodeList = delegator.findByCondition("ProductPromoCode", codeCondition, null, UtilMisc.toList("productPromoCodeId"));
Iterator productPromoCodeIter = productPromoCodeList.iterator();
// support multiple promo codes for a single promo, ie if we run into a use limit for one code see if we can find another for this promo
// check the use limit before each pass so if the promo use limit has been hit we don't keep on trying for the promo code use limit, if there is one of course
while ((useLimit == null || useLimit.longValue() > cart.getProductPromoUseCount(productPromoId)) && productPromoCodeIter.hasNext()) {
GenericValue productPromoCode = (GenericValue) productPromoCodeIter.next();
String productPromoCodeId = productPromoCode.getString("productPromoCodeId");
Long codeUseLimit = getProductPromoCodeUseLimit(productPromoCode, partyId, delegator);
if (runProductPromoRules(cart, cartChanged, useLimit, true, productPromoCodeId, codeUseLimit, maxUseLimit, productPromo, productPromoRules, dispatcher, delegator, nowTimestamp)) {
cartChanged = true;
}
if (cart.getProductPromoUseCount(productPromoId) > maxUseLimit) {
Debug.logError("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.", module);
break;
}
}
}
} else {
if (runProductPromoRules(cart, cartChanged, useLimit, false, null, null, maxUseLimit, productPromo, productPromoRules, dispatcher, delegator, nowTimestamp)) {
cartChanged = true;
}
}
}
// if this is an isolatedTestRun clear out adjustments and cart item promo use info
if (isolatedTestRun) {
cart.clearAllPromotionAdjustments();
cart.clearCartItemUseInPromoInfo();
}
}
// if this is an isolatedTestRun, then only go through it once, never retry
if (isolatedTestRun) {
cartChanged = false;
}
}
} catch (UseLimitException e) {
Debug.logError(e, e.toString(), module);
}
}
/** calculate low use limit for this promo for the current "order", check per order, customer, promo */
public static Long getProductPromoUseLimit(GenericValue productPromo, String partyId, GenericDelegator delegator) throws GenericEntityException {
String productPromoId = productPromo.getString("productPromoId");
Long candidateUseLimit = null;
Long useLimitPerOrder = productPromo.getLong("useLimitPerOrder");
if (useLimitPerOrder != null) {
if (candidateUseLimit == null || candidateUseLimit.longValue() > useLimitPerOrder.longValue()) {
candidateUseLimit = useLimitPerOrder;
}
}
// Debug.logInfo("Promo [" + productPromoId + "] use limit after per order check: " + candidateUseLimit, module);
Long useLimitPerCustomer = productPromo.getLong("useLimitPerCustomer");
// check this whether or not there is a party right now
if (useLimitPerCustomer != null) {
// if partyId is not empty check previous usage
long productPromoCustomerUseSize = 0;
if (UtilValidate.isNotEmpty(partyId)) {
// check to see how many times this has been used for other orders for this customer, the remainder is the limit for this order
EntityCondition checkCondition = new EntityConditionList(UtilMisc.toList(
new EntityExpr("productPromoId", EntityOperator.EQUALS, productPromoId),
new EntityExpr("partyId", EntityOperator.EQUALS, partyId),
new EntityExpr("statusId", EntityOperator.NOT_EQUAL, "ORDER_REJECTED"),
new EntityExpr("statusId", EntityOperator.NOT_EQUAL, "ORDER_CANCELLED")), EntityOperator.AND);
productPromoCustomerUseSize = delegator.findCountByCondition("ProductPromoUseCheck", checkCondition, null);
}
long perCustomerThisOrder = useLimitPerCustomer.longValue() - productPromoCustomerUseSize;
if (candidateUseLimit == null || candidateUseLimit.longValue() > perCustomerThisOrder) {
candidateUseLimit = new Long(perCustomerThisOrder);
}
}
// Debug.logInfo("Promo [" + productPromoId + "] use limit after per customer check: " + candidateUseLimit, module);
Long useLimitPerPromotion = productPromo.getLong("useLimitPerPromotion");
if (useLimitPerPromotion != null) {
// check to see how many times this has been used for other orders for this customer, the remainder is the limit for this order
EntityCondition checkCondition = new EntityConditionList(UtilMisc.toList(
new EntityExpr("productPromoId", EntityOperator.EQUALS, productPromoId),
new EntityExpr("statusId", EntityOperator.NOT_EQUAL, "ORDER_REJECTED"),
new EntityExpr("statusId", EntityOperator.NOT_EQUAL, "ORDER_CANCELLED")), EntityOperator.AND);
long productPromoUseSize = delegator.findCountByCondition("ProductPromoUseCheck", checkCondition, null);
long perPromotionThisOrder = useLimitPerPromotion.longValue() - productPromoUseSize;
if (candidateUseLimit == null || candidateUseLimit.longValue() > perPromotionThisOrder) {
candidateUseLimit = new Long(perPromotionThisOrder);
}
}
// Debug.logInfo("Promo [" + productPromoId + "] use limit after per promotion check: " + candidateUseLimit, module);
return candidateUseLimit;
}
public static Long getProductPromoCodeUseLimit(GenericValue productPromoCode, String partyId, GenericDelegator delegator) throws GenericEntityException {
String productPromoCodeId = productPromoCode.getString("productPromoCodeId");
Long codeUseLimit = null;
// check promo code use limits, per customer, code
Long codeUseLimitPerCustomer = productPromoCode.getLong("useLimitPerCustomer");
if (codeUseLimitPerCustomer != null && UtilValidate.isNotEmpty(partyId)) {
// check to see how many times this has been used for other orders for this customer, the remainder is the limit for this order
EntityCondition checkCondition = new EntityConditionList(UtilMisc.toList(
new EntityExpr("productPromoCodeId", EntityOperator.EQUALS, productPromoCodeId),
new EntityExpr("partyId", EntityOperator.EQUALS, partyId),
new EntityExpr("statusId", EntityOperator.NOT_EQUAL, "ORDER_REJECTED"),
new EntityExpr("statusId", EntityOperator.NOT_EQUAL, "ORDER_CANCELLED")), EntityOperator.AND);
long productPromoCustomerUseSize = delegator.findCountByCondition("ProductPromoUseCheck", checkCondition, null);
long perCustomerThisOrder = codeUseLimitPerCustomer.longValue() - productPromoCustomerUseSize;
if (codeUseLimit == null || codeUseLimit.longValue() > perCustomerThisOrder) {
codeUseLimit = new Long(perCustomerThisOrder);
}
}
Long codeUseLimitPerCode = productPromoCode.getLong("useLimitPerCode");
if (codeUseLimitPerCode != null) {
// check to see how many times this has been used for other orders for this customer, the remainder is the limit for this order
EntityCondition checkCondition = new EntityConditionList(UtilMisc.toList(
new EntityExpr("productPromoCodeId", EntityOperator.EQUALS, productPromoCodeId),
new EntityExpr("statusId", EntityOperator.NOT_EQUAL, "ORDER_REJECTED"),
new EntityExpr("statusId", EntityOperator.NOT_EQUAL, "ORDER_CANCELLED")), EntityOperator.AND);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -