1 24 package org.ofbiz.order.shoppingcart.product; 25 26 import java.sql.Timestamp ; 27 import java.util.ArrayList ; 28 import java.util.HashMap ; 29 import java.util.HashSet ; 30 import java.util.Iterator ; 31 import java.util.LinkedList ; 32 import java.util.List ; 33 import java.util.Locale ; 34 import java.util.Map ; 35 import java.util.Set ; 36 37 import javax.servlet.ServletRequest ; 38 import javax.servlet.http.HttpServletRequest ; 39 40 import javolution.util.FastList; 41 42 import org.ofbiz.base.util.Debug; 43 import org.ofbiz.base.util.GeneralException; 44 import org.ofbiz.base.util.UtilDateTime; 45 import org.ofbiz.base.util.UtilMisc; 46 import org.ofbiz.base.util.UtilProperties; 47 import org.ofbiz.base.util.UtilValidate; 48 import org.ofbiz.entity.GenericDelegator; 49 import org.ofbiz.entity.GenericEntityException; 50 import org.ofbiz.entity.GenericValue; 51 import org.ofbiz.entity.condition.EntityCondition; 52 import org.ofbiz.entity.condition.EntityConditionList; 53 import org.ofbiz.entity.condition.EntityExpr; 54 import org.ofbiz.entity.condition.EntityOperator; 55 import org.ofbiz.entity.util.EntityUtil; 56 import org.ofbiz.order.shoppingcart.CartItemModifyException; 57 import org.ofbiz.order.shoppingcart.ShoppingCart; 58 import org.ofbiz.order.shoppingcart.ShoppingCartEvents; 59 import org.ofbiz.order.shoppingcart.ShoppingCartItem; 60 import org.ofbiz.product.product.ProductContentWrapper; 61 import org.ofbiz.product.product.ProductSearch; 62 import org.ofbiz.service.GenericServiceException; 63 import org.ofbiz.service.LocalDispatcher; 64 import org.ofbiz.service.ModelService; 65 import org.ofbiz.service.ServiceUtil; 66 67 75 public class ProductPromoWorker { 76 77 public static final String module = ProductPromoWorker.class.getName(); 78 public static final String resource_error = "OrderErrorUiLabels"; 79 80 public static List getStoreProductPromos(GenericDelegator delegator, LocalDispatcher dispatcher, ServletRequest request) { 81 List productPromos = FastList.newInstance(); 82 Timestamp nowTimestamp = UtilDateTime.nowTimestamp(); 83 84 HttpServletRequest req = null; 86 ShoppingCart cart = null; 87 try { 88 req = (HttpServletRequest ) request; 89 cart = ShoppingCartEvents.getCartObject(req); 90 } catch (ClassCastException cce) { 91 Debug.logError("Not a HttpServletRequest, no shopping cart found.", module); 92 return null; 93 } catch (IllegalArgumentException e) { 94 Debug.logError(e, module); 95 return null; 96 } 97 98 boolean condResult = true; 99 100 try { 101 String productStoreId = cart.getProductStoreId(); 102 GenericValue productStore = null; 103 try { 104 productStore = delegator.findByPrimaryKeyCache("ProductStore", UtilMisc.toMap("productStoreId", productStoreId)); 105 } catch (GenericEntityException e) { 106 Debug.logError(e, "Error looking up store with id " + productStoreId, module); 107 } 108 if (productStore == null) { 109 Debug.logWarning(UtilProperties.getMessage(resource_error,"OrderNoStoreFoundWithIdNotDoingPromotions", UtilMisc.toMap("productStoreId",productStoreId), cart.getLocale()), module); 110 return productPromos; 111 } 112 113 if (productStore != null) { 114 Iterator productStorePromoAppls = UtilMisc.toIterator(EntityUtil.filterByDate(productStore.getRelatedCache("ProductStorePromoAppl", UtilMisc.toMap("productStoreId", productStoreId), UtilMisc.toList("sequenceNum")), true)); 115 while (productStorePromoAppls != null && productStorePromoAppls.hasNext()) { 116 GenericValue productStorePromoAppl = (GenericValue) productStorePromoAppls.next(); 117 GenericValue productPromo = productStorePromoAppl.getRelatedOneCache("ProductPromo"); 118 List productPromoRules = productPromo.getRelatedCache("ProductPromoRule", null, null); 119 120 121 if (productPromoRules != null) { 122 Iterator promoRulesItr = productPromoRules.iterator(); 123 124 while (condResult && promoRulesItr != null && promoRulesItr.hasNext()) { 125 GenericValue promoRule = (GenericValue) promoRulesItr.next(); 126 Iterator productPromoConds = UtilMisc.toIterator(promoRule.getRelatedCache("ProductPromoCond", null, UtilMisc.toList("productPromoCondSeqId"))); 127 128 while (condResult && productPromoConds != null && productPromoConds.hasNext()) { 129 GenericValue productPromoCond = (GenericValue) productPromoConds.next(); 130 131 if ("PPIP_PARTY_ID".equals(productPromoCond.getString("inputParamEnumId"))) { 133 condResult = checkCondition(productPromoCond, cart, delegator, dispatcher, nowTimestamp); 134 } else if ("PPIP_PARTY_GRP_MEM".equals(productPromoCond.getString("inputParamEnumId"))) { 135 condResult = checkCondition(productPromoCond, cart, delegator, dispatcher, nowTimestamp); 136 } else if ("PPIP_PARTY_CLASS".equals(productPromoCond.getString("inputParamEnumId"))) { 137 condResult = checkCondition(productPromoCond, cart, delegator, dispatcher, nowTimestamp); 138 } else if ("PPIP_ROLE_TYPE".equals(productPromoCond.getString("inputParamEnumId"))) { 139 condResult = checkCondition(productPromoCond, cart, delegator, dispatcher, nowTimestamp); 140 } 141 } 142 } 143 if (!condResult) productPromo = null; 144 } 145 if (productPromo != null) productPromos.add(productPromo); 146 } 147 } 148 } catch (GenericEntityException e) { 149 Debug.logError(e, module); 150 } 151 return productPromos; 152 } 153 154 public static List getProductStorePromotions(ShoppingCart cart, Timestamp nowTimestamp, LocalDispatcher dispatcher) { 155 List productPromoList = FastList.newInstance(); 156 157 GenericDelegator delegator = cart.getDelegator(); 158 159 String productStoreId = cart.getProductStoreId(); 160 GenericValue productStore = null; 161 try { 162 productStore = delegator.findByPrimaryKeyCache("ProductStore", UtilMisc.toMap("productStoreId", productStoreId)); 163 } catch (GenericEntityException e) { 164 Debug.logError(e, "Error looking up store with id " + productStoreId, module); 165 } 166 if (productStore == null) { 167 Debug.logWarning(UtilProperties.getMessage(resource_error,"OrderNoStoreFoundWithIdNotDoingPromotions", UtilMisc.toMap("productStoreId",productStoreId), cart.getLocale()), module); 168 return productPromoList; 169 } 170 171 try { 172 List productStorePromoApplsList = productStore.getRelatedCache("ProductStorePromoAppl", null, UtilMisc.toList("sequenceNum")); 174 productStorePromoApplsList = EntityUtil.filterByDate(productStorePromoApplsList, nowTimestamp); 175 176 if (productStorePromoApplsList == null || productStorePromoApplsList.size() == 0) { 177 if (Debug.verboseOn()) Debug.logVerbose("Not doing promotions, none applied to store with ID " + productStoreId, module); 178 } 179 180 Iterator prodCatalogPromoAppls = UtilMisc.toIterator(productStorePromoApplsList); 181 while (prodCatalogPromoAppls != null && prodCatalogPromoAppls.hasNext()) { 182 GenericValue prodCatalogPromoAppl = (GenericValue) prodCatalogPromoAppls.next(); 183 GenericValue productPromo = prodCatalogPromoAppl.getRelatedOneCache("ProductPromo"); 184 productPromoList.add(productPromo); 185 } 186 } catch (GenericEntityException e) { 187 Debug.logError(e, "Error looking up promotion data while doing promotions", module); 188 } 189 return productPromoList; 190 } 191 192 public static List getAgreementPromotions(ShoppingCart cart, Timestamp nowTimestamp, LocalDispatcher dispatcher) { 193 List productPromoList = FastList.newInstance(); 194 195 GenericDelegator delegator = cart.getDelegator(); 196 197 String agreementId = cart.getAgreementId(); 198 GenericValue agreement = null; 199 try { 200 agreement = delegator.findByPrimaryKeyCache("Agreement", UtilMisc.toMap("agreementId", agreementId)); 201 } catch (GenericEntityException e) { 202 Debug.logError(e, "Error looking up agreement with id " + agreementId, module); 203 } 204 if (agreement == null) { 205 Debug.logWarning(UtilProperties.getMessage(resource_error,"OrderNoAgreementFoundWithIdNotDoingPromotions", UtilMisc.toMap("agreementId", agreementId), cart.getLocale()), module); 206 return productPromoList; 207 } 208 GenericValue agreementItem = null; 209 try { 210 List agreementItems = delegator.findByAndCache("AgreementItem", UtilMisc.toMap("agreementId", agreementId, "agreementItemTypeId", "AGREEMENT_PRICING_PR", "currencyUomId", cart.getCurrency())); 211 agreementItem = EntityUtil.getFirst(agreementItems); 212 } catch (GenericEntityException e) { 213 Debug.logError(e, "Error looking up agreement items for agreement with id " + agreementId, module); 214 } 215 if (agreementItem == null) { 216 Debug.logWarning(UtilProperties.getMessage(resource_error,"OrderNoAgreementItemFoundForAgreementWithIdNotDoingPromotions", UtilMisc.toMap("agreementId", agreementId), cart.getLocale()), module); 217 return productPromoList; 218 } 219 220 try { 221 List agreementPromoApplsList = agreementItem.getRelatedCache("AgreementPromoAppl", null, UtilMisc.toList("sequenceNum")); 223 agreementPromoApplsList = EntityUtil.filterByDate(agreementPromoApplsList, nowTimestamp); 224 225 if (agreementPromoApplsList == null || agreementPromoApplsList.size() == 0) { 226 if (Debug.verboseOn()) Debug.logVerbose("Not doing promotions, none applied to agreement with ID " + agreementId, module); 227 } 228 229 Iterator agreementPromoAppls = UtilMisc.toIterator(agreementPromoApplsList); 230 while (agreementPromoAppls != null && agreementPromoAppls.hasNext()) { 231 GenericValue agreementPromoAppl = (GenericValue) agreementPromoAppls.next(); 232 GenericValue productPromo = agreementPromoAppl.getRelatedOneCache("ProductPromo"); 233 productPromoList.add(productPromo); 234 } 235 } catch (GenericEntityException e) { 236 Debug.logError(e, "Error looking up promotion data while doing promotions", module); 237 } 238 return productPromoList; 239 } 240 241 public static void doPromotions(ShoppingCart cart, LocalDispatcher dispatcher) { 242 ProductPromoWorker.doPromotions(cart, null, dispatcher); 243 } 244 245 public static void doPromotions(ShoppingCart cart, List productPromoList, LocalDispatcher dispatcher) { 246 252 GenericDelegator delegator = cart.getDelegator(); 253 Timestamp nowTimestamp = UtilDateTime.nowTimestamp(); 254 255 cart.clearAllPromotionInformation(); 257 258 try { 260 if (productPromoList == null) { 261 if (cart.getOrderType().equals("SALES_ORDER")) { 262 productPromoList = ProductPromoWorker.getProductStorePromotions(cart, nowTimestamp, dispatcher); 263 } else { 264 productPromoList = ProductPromoWorker.getAgreementPromotions(cart, nowTimestamp, dispatcher); 265 } 266 } 267 runProductPromos(productPromoList, cart, delegator, dispatcher, nowTimestamp, true); 272 273 277 List productPromoDiscountMapList = FastList.newInstance(); 279 List productPromoDiscountMapListOrderTotal = FastList.newInstance(); 280 Iterator productPromoIter = productPromoList.iterator(); 281 while (productPromoIter.hasNext()) { 282 GenericValue productPromo = (GenericValue) productPromoIter.next(); 283 Map productPromoDiscountMap = UtilMisc.toMap("productPromo", productPromo, "totalDiscountAmount", new Double (cart.getProductPromoUseTotalDiscount(productPromo.getString("productPromoId")))); 284 if (hasOrderTotalCondition(productPromo, delegator)) { 285 productPromoDiscountMapListOrderTotal.add(productPromoDiscountMap); 286 } else { 287 productPromoDiscountMapList.add(productPromoDiscountMap); 288 } 289 } 290 291 292 productPromoDiscountMapList = UtilMisc.sortMaps(productPromoDiscountMapList, UtilMisc.toList("+totalDiscountAmount")); 294 productPromoDiscountMapListOrderTotal = UtilMisc.sortMaps(productPromoDiscountMapListOrderTotal, UtilMisc.toList("+totalDiscountAmount")); 295 296 productPromoDiscountMapList.addAll(productPromoDiscountMapListOrderTotal); 297 298 List sortedProductPromoList = new ArrayList (productPromoDiscountMapList.size()); 299 Iterator productPromoDiscountMapIter = productPromoDiscountMapList.iterator(); 300 while (productPromoDiscountMapIter.hasNext()) { 301 Map productPromoDiscountMap = (Map ) productPromoDiscountMapIter.next(); 302 GenericValue productPromo = (GenericValue) productPromoDiscountMap.get("productPromo"); 303 sortedProductPromoList.add(productPromo); 304 if (Debug.verboseOn()) Debug.logVerbose("Sorted Promo [" + productPromo.getString("productPromoId") + "] with total discount: " + productPromoDiscountMap.get("totalDiscountAmount"), module); 305 } 306 307 cart.clearAllPromotionInformation(); 309 runProductPromos(sortedProductPromoList, cart, delegator, dispatcher, nowTimestamp, false); 310 } catch (NumberFormatException e) { 311 Debug.logError(e, "Number not formatted correctly in promotion rules, not completed...", module); 312 } catch (GenericEntityException e) { 313 Debug.logError(e, "Error looking up promotion data while doing promotions", module); 314 } catch (Exception e) { 315 Debug.logError(e, "Error running promotions, will ignore: " + e.toString(), module); 316 } 317 } 318 319 protected static boolean hasOrderTotalCondition(GenericValue productPromo, GenericDelegator delegator) throws GenericEntityException { 320 boolean hasOtCond = false; 321 List productPromoConds = delegator.findByAndCache("ProductPromoCond", UtilMisc.toMap("productPromoId", productPromo.get("productPromoId")), UtilMisc.toList("productPromoCondSeqId")); 322 Iterator productPromoCondIter = productPromoConds.iterator(); 323 while (productPromoCondIter.hasNext()) { 324 GenericValue productPromoCond = (GenericValue) productPromoCondIter.next(); 325 String inputParamEnumId = productPromoCond.getString("inputParamEnumId"); 326 if ("PPIP_ORDER_TOTAL".equals(inputParamEnumId)) { 327 hasOtCond = true; 328 break; 329 } 330 } 331 return hasOtCond; 332 } 333 334 protected static void runProductPromos(List productPromoList, ShoppingCart cart, GenericDelegator delegator, LocalDispatcher dispatcher, Timestamp nowTimestamp, boolean isolatedTestRun) throws GeneralException { 335 String partyId = cart.getPartyId(); 336 337 long maxIterations = 1000; 339 long numberOfIterations = 0; 341 342 long maxUseLimit = 2 * Math.round(cart.getTotalQuantity()); 345 346 try { 347 boolean cartChanged = true; 349 while (cartChanged) { 350 cartChanged = false; 351 numberOfIterations++; 352 if (numberOfIterations > maxIterations) { 353 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); 354 break; 355 } 356 357 Iterator productPromoIter = productPromoList.iterator(); 358 while (productPromoIter.hasNext()) { 359 GenericValue productPromo = (GenericValue) productPromoIter.next(); 360 String productPromoId = productPromo.getString("productPromoId"); 361 362 List productPromoRules = productPromo.getRelatedCache("ProductPromoRule", null, null); 363 if (productPromoRules != null && productPromoRules.size() > 0) { 364 Long candidateUseLimit = getProductPromoUseLimit(productPromo, partyId, delegator); 366 Long useLimit = candidateUseLimit; 367 if (Debug.verboseOn()) Debug.logVerbose("Running promotion [" + productPromoId + "], useLimit=" + useLimit + ", # of rules=" + productPromoRules.size(), module); 368 369 boolean requireCode = "Y".equals(productPromo.getString("requireCode")); 370 if (requireCode) { 372 Set enteredCodes = cart.getProductPromoCodesEntered(); 373 if (enteredCodes.size() > 0) { 374 EntityCondition codeCondition = new EntityExpr(new EntityExpr("productPromoId", EntityOperator.EQUALS, productPromoId), EntityOperator.AND, new EntityExpr("productPromoCodeId", EntityOperator.IN, enteredCodes)); 376 List productPromoCodeList = delegator.findByCondition("ProductPromoCode", codeCondition, null, UtilMisc.toList("productPromoCodeId")); 378 Iterator productPromoCodeIter = productPromoCodeList.iterator(); 379 while ((useLimit == null || useLimit.longValue() > cart.getProductPromoUseCount(productPromoId)) && productPromoCodeIter.hasNext()) { 382 GenericValue productPromoCode = (GenericValue) productPromoCodeIter.next(); 383 String productPromoCodeId = productPromoCode.getString("productPromoCodeId"); 384 Long codeUseLimit = getProductPromoCodeUseLimit(productPromoCode, partyId, delegator); 385 if (runProductPromoRules(cart, cartChanged, useLimit, true, productPromoCodeId, codeUseLimit, maxUseLimit, productPromo, productPromoRules, dispatcher, delegator, nowTimestamp)) { 386 cartChanged = true; 387 } 388 389 if (cart.getProductPromoUseCount(productPromoId) > maxUseLimit) { 390 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); 391 break; 392 } 393 } 394 } 395 } else { 396 try { 397 if (runProductPromoRules(cart, cartChanged, useLimit, false, null, null, maxUseLimit, productPromo, productPromoRules, dispatcher, delegator, nowTimestamp)) { 398 cartChanged = true; 399 } 400 } catch (RuntimeException e) { 401 throw new GeneralException("Error running promotion with ID [" + productPromoId + "]", e); 402 } 403 } 404 } 405 406 if (isolatedTestRun) { 408 cart.clearAllPromotionAdjustments(); 409 cart.clearCartItemUseInPromoInfo(); 410 } 411 } 412 413 if (isolatedTestRun) { 415 cartChanged = false; 416 } 417 } 418 } catch (UseLimitException e) { 419 Debug.logError(e, e.toString(), module); 420 } 421 } 422 423 424 public static Long getProductPromoUseLimit(GenericValue productPromo, String partyId, GenericDelegator delegator) throws GenericEntityException { 425 String productPromoId = productPromo.getString("productPromoId"); 426 Long candidateUseLimit = null; 427 428 Long useLimitPerOrder = productPromo.getLong("useLimitPerOrder"); 429 if (useLimitPerOrder != null) { 430 if (candidateUseLimit == null || candidateUseLimit.longValue() > useLimitPerOrder.longValue()) { 431 candidateUseLimit = useLimitPerOrder; 432 } 433 } 434 435 437 Long useLimitPerCustomer = productPromo.getLong("useLimitPerCustomer"); 438 if (useLimitPerCustomer != null) { 440 long productPromoCustomerUseSize = 0; 442 if (UtilValidate.isNotEmpty(partyId)) { 443 EntityCondition checkCondition = new EntityConditionList(UtilMisc.toList( 445 new EntityExpr("productPromoId", EntityOperator.EQUALS, productPromoId), 446 new EntityExpr("partyId", EntityOperator.EQUALS, partyId), 447 new EntityExpr("statusId", EntityOperator.NOT_EQUAL, "ORDER_REJECTED"), 448 new EntityExpr("statusId", EntityOperator.NOT_EQUAL, "ORDER_CANCELLED")), EntityOperator.AND); 449 productPromoCustomerUseSize = delegator.findCountByCondition("ProductPromoUseCheck", checkCondition, null); 450 } 451 long perCustomerThisOrder = useLimitPerCustomer.longValue() - productPromoCustomerUseSize; 452 if (candidateUseLimit == null || candidateUseLimit.longValue() > perCustomerThisOrder) { 453 candidateUseLimit = new Long (perCustomerThisOrder); 454 } 455 } 456 457 459 Long useLimitPerPromotion = productPromo.getLong("useLimitPerPromotion"); 460 if (useLimitPerPromotion != null) { 461 EntityCondition checkCondition = new EntityConditionList(UtilMisc.toList( 463 new EntityExpr("productPromoId", EntityOperator.EQUALS, productPromoId), 464 new EntityExpr("statusId", EntityOperator.NOT_EQUAL, "ORDER_REJECTED"), 465 new EntityExpr("statusId", EntityOperator.NOT_EQUAL, "ORDER_CANCELLED")), EntityOperator.AND); 466 long productPromoUseSize = delegator.findCountByCondition("ProductPromoUseCheck", checkCondition, null); 467 long perPromotionThisOrder = useLimitPerPromotion.longValue() - productPromoUseSize; 468 if (candidateUseLimit == null || candidateUseLimit.longValue() > perPromotionThisOrder) { 469 candidateUseLimit = new Long (perPromotionThisOrder); 470 } 471 } 472 473 475 return candidateUseLimit; 476 } 477 478 public static Long getProductPromoCodeUseLimit(GenericValue productPromoCode, String partyId, GenericDelegator delegator) throws GenericEntityException { 479 String productPromoCodeId = productPromoCode.getString("productPromoCodeId"); 480 Long codeUseLimit = null; 481 482 Long codeUseLimitPerCustomer = productPromoCode.getLong("useLimitPerCustomer"); 484 if (codeUseLimitPerCustomer != null && UtilValidate.isNotEmpty(partyId)) { 485 EntityCondition checkCondition = new EntityConditionList(UtilMisc.toList( 487 new EntityExpr("productPromoCodeId", EntityOperator.EQUALS, productPromoCodeId), 488 new EntityExpr("partyId", EntityOperator.EQUALS, partyId), 489 new EntityExpr("statusId", EntityOperator.NOT_EQUAL, "ORDER_REJECTED"), 490 new EntityExpr("statusId", EntityOperator.NOT_EQUAL, "ORDER_CANCELLED")), EntityOperator.AND); 491 long productPromoCustomerUseSize = delegator.findCountByCondition("ProductPromoUseCheck", checkCondition, null); 492 long perCustomerThisOrder = codeUseLimitPerCustomer.longValue() - productPromoCustomerUseSize; 493 if (codeUseLimit == null || codeUseLimit.longValue() > perCustomerThisOrder) { 494 codeUseLimit = new Long (perCustomerThisOrder); 495 } 496 } 497 498 Long codeUseLimitPerCode = productPromoCode.getLong("useLimitPerCode"); 499 if (codeUseLimitPerCode != null) { 500 EntityCondition checkCondition = new EntityConditionList(UtilMisc.toList( 502 new EntityExpr("productPromoCodeId", EntityOperator.EQUALS, productPromoCodeId), 503 new EntityExpr("statusId", EntityOperator.NOT_EQUAL, "ORDER_REJECTED"), 504 new EntityExpr("statusId", EntityOperator.NOT_EQUAL, "ORDER_CANCELLED")), EntityOperator.AND); 505 long productPromoCodeUseSize = delegator.findCountByCondition("ProductPromoUseCheck", checkCondition, null); 506 long perCodeThisOrder = codeUseLimitPerCode.longValue() - productPromoCodeUseSize; 507 if (codeUseLimit == null || codeUseLimit.longValue() > perCodeThisOrder) { 508 codeUseLimit = new Long (perCodeThisOrder); 509 } 510 } 511 512 return codeUseLimit; 513 } 514 515 public static String checkCanUsePromoCode(String productPromoCodeId, String partyId, GenericDelegator delegator) { 516 try { 517 GenericValue productPromoCode = delegator.findByPrimaryKey("ProductPromoCode", UtilMisc.toMap("productPromoCodeId", productPromoCodeId)); 518 if (productPromoCode == null) { 519 return "The promotion code [" + productPromoCodeId + "] is not valid."; 520 } 521 522 if ("Y".equals(productPromoCode.getString("requireEmailOrParty"))) { 523 boolean hasEmailOrParty = false; 524 525 if (UtilValidate.isNotEmpty(partyId)) { 527 if (delegator.findByPrimaryKey("ProductPromoCodeParty", UtilMisc.toMap("productPromoCodeId", productPromoCodeId, "partyId", partyId)) != null) { 528 return null; 530 } 531 532 Timestamp nowTimestamp = UtilDateTime.nowTimestamp(); 534 List validEmailCondList = new ArrayList (); 535 validEmailCondList.add(new EntityExpr("partyId", EntityOperator.EQUALS, partyId)); 536 validEmailCondList.add(new EntityExpr("productPromoCodeId", EntityOperator.EQUALS, productPromoCodeId)); 537 validEmailCondList.add(new EntityExpr("fromDate", EntityOperator.LESS_THAN_EQUAL_TO, nowTimestamp)); 538 validEmailCondList.add(new EntityExpr(new EntityExpr("thruDate", EntityOperator.GREATER_THAN_EQUAL_TO, nowTimestamp), 539 EntityOperator.OR, new EntityExpr("thruDate", EntityOperator.EQUALS, null))); 540 EntityCondition validEmailCondition = new EntityConditionList(validEmailCondList, EntityOperator.AND); 541 long validEmailCount = delegator.findCountByCondition("ProductPromoCodeEmailParty", validEmailCondition, null); 542 if (validEmailCount > 0) { 543 return null; 545 } 546 } 547 548 if (!hasEmailOrParty) { 549 return "This promotion code [" + productPromoCodeId + "] requires you to be associated with it by account or email address and you are not associated with it."; 550 } 551 } 552 553 Long useLimit = getProductPromoCodeUseLimit(productPromoCode, partyId, delegator); 555 if (useLimit != null && useLimit.longValue() <= 0) { 556 return "This promotion code [" + productPromoCodeId + "] has reached it's maximum use limit for you and can no longer be used."; 557 } 558 559 return null; 560 } catch (GenericEntityException e) { 561 Debug.logError(e, "Error looking up ProductPromoCode", module); 562 return "Error looking up code [" + productPromoCodeId + "]:" + e.toString(); 563 } 564 } 565 566 public static String makeAutoDescription(GenericValue productPromo, GenericDelegator delegator, Locale locale) throws GenericEntityException { 567 if (productPromo == null) { 568 return ""; 569 } 570 StringBuffer promoDescBuf = new StringBuffer (); 571 List productPromoRules = productPromo.getRelatedCache("ProductPromoRule", null, null); 572 Iterator promoRulesIter = productPromoRules.iterator(); 573 while (promoRulesIter != null && promoRulesIter.hasNext()) { 574 GenericValue productPromoRule = (GenericValue) promoRulesIter.next(); 575 576 List productPromoConds = delegator.findByAndCache("ProductPromoCond", UtilMisc.toMap("productPromoId", productPromo.get("productPromoId")), UtilMisc.toList("productPromoCondSeqId")); 577 productPromoConds = EntityUtil.filterByAnd(productPromoConds, UtilMisc.toMap("productPromoRuleId", productPromoRule.get("productPromoRuleId"))); 578 Iterator productPromoCondIter = UtilMisc.toIterator(productPromoConds); 580 while (productPromoCondIter != null && productPromoCondIter.hasNext()) { 581 GenericValue productPromoCond = (GenericValue) productPromoCondIter.next(); 582 583 String equalityOperator = UtilProperties.getMessage("promotext", "operator.equality." + productPromoCond.getString("operatorEnumId"), locale); 584 String quantityOperator = UtilProperties.getMessage("promotext", "operator.quantity." + productPromoCond.getString("operatorEnumId"), locale); 585 586 String condValue = "invalid"; 587 if (UtilValidate.isNotEmpty(productPromoCond.getString("condValue"))) { 588 condValue = productPromoCond.getString("condValue"); 589 } 590 591 Map messageContext = UtilMisc.toMap("condValue", condValue, "equalityOperator", equalityOperator, "quantityOperator", quantityOperator); 592 String msgProp = UtilProperties.getMessage("promotext", "condition." + productPromoCond.getString("inputParamEnumId"), messageContext, locale); 593 promoDescBuf.append(msgProp); 594 promoDescBuf.append(" "); 595 596 if (promoRulesIter.hasNext()) { 597 promoDescBuf.append(" and "); 598 } 599 } 600 601 List productPromoActions = productPromoRule.getRelatedCache("ProductPromoAction", null, UtilMisc.toList("productPromoActionSeqId")); 602 Iterator productPromoActionIter = UtilMisc.toIterator(productPromoActions); 603 while (productPromoActionIter != null && productPromoActionIter.hasNext()) { 604 GenericValue productPromoAction = (GenericValue) productPromoActionIter.next(); 605 606 String productId = productPromoAction.getString("productId"); 607 608 Map messageContext = UtilMisc.toMap("quantity", productPromoAction.get("quantity"), "amount", productPromoAction.get("amount"), "productId", productId, "partyId", productPromoAction.get("partyId")); 609 610 if (UtilValidate.isEmpty((String ) messageContext.get("productId"))) messageContext.put("productId", "any"); 611 if (UtilValidate.isEmpty((String ) messageContext.get("partyId"))) messageContext.put("partyId", "any"); 612 GenericValue product = delegator.findByPrimaryKeyCache("Product", UtilMisc.toMap("productId", productId)); 613 if (product != null) { 614 messageContext.put("productName", ProductContentWrapper.getProductContentAsText(product, "PRODUCT_NAME", locale)); 615 } 616 617 String msgProp = UtilProperties.getMessage("promotext", "action." + productPromoAction.getString("productPromoActionEnumId"), messageContext, locale); 618 promoDescBuf.append(msgProp); 619 promoDescBuf.append(" "); 620 621 if (promoRulesIter.hasNext()) { 622 promoDescBuf.append(" and "); 623 } 624 } 625 626 if (promoRulesIter.hasNext()) { 627 promoDescBuf.append(" or "); 628 } 629 } 630 631 if (promoDescBuf.length() > 0) { 632 if (promoDescBuf.charAt(promoDescBuf.length() - 1) == ' ') promoDescBuf.deleteCharAt(promoDescBuf.length() - 1); 634 promoDescBuf.append(". "); 636 promoDescBuf.setCharAt(0, Character.toUpperCase(promoDescBuf.charAt(0))); 638 } 639 640 if ("Y".equals(productPromo.getString("requireCode"))) { 641 promoDescBuf.append("Requires code to use. "); 642 } 643 if (productPromo.getLong("useLimitPerOrder") != null) { 644 promoDescBuf.append("Limit "); 645 promoDescBuf.append(productPromo.getLong("useLimitPerOrder")); 646 promoDescBuf.append(" per order. "); 647 } 648 if (productPromo.getLong("useLimitPerCustomer") != null) { 649 promoDescBuf.append("Limit "); 650 promoDescBuf.append(productPromo.getLong("useLimitPerCustomer")); 651 promoDescBuf.append(" per customer. "); 652 } 653 if (productPromo.getLong("useLimitPerPromotion") != null) { 654 promoDescBuf.append("Limit "); 655 promoDescBuf.append(productPromo.getLong("useLimitPerPromotion")); 656 promoDescBuf.append(" per promotion. "); 657 } 658 659 return promoDescBuf.toString(); 660 } 661 662 protected static boolean runProductPromoRules(ShoppingCart cart, boolean cartChanged, Long useLimit, boolean requireCode, String productPromoCodeId, Long codeUseLimit, long maxUseLimit, 663 GenericValue productPromo, List productPromoRules, LocalDispatcher dispatcher, GenericDelegator delegator, Timestamp nowTimestamp) throws GenericEntityException, UseLimitException { 664 String productPromoId = productPromo.getString("productPromoId"); 665 while ((useLimit == null || useLimit.longValue() > cart.getProductPromoUseCount(productPromoId)) && 666 (!requireCode || UtilValidate.isNotEmpty(productPromoCodeId)) && 667 (codeUseLimit == null || codeUseLimit.longValue() > cart.getProductPromoCodeUse(productPromoCodeId))) { 668 boolean promoUsed = false; 669 double totalDiscountAmount = 0; 670 double quantityLeftInActions = 0; 671 672 Iterator promoRulesIter = productPromoRules.iterator(); 673 while (promoRulesIter != null && promoRulesIter.hasNext()) { 674 GenericValue productPromoRule = (GenericValue) promoRulesIter.next(); 675 676 boolean performActions = true; 678 679 List productPromoConds = delegator.findByAndCache("ProductPromoCond", UtilMisc.toMap("productPromoId", productPromo.get("productPromoId")), UtilMisc.toList("productPromoCondSeqId")); 681 productPromoConds = EntityUtil.filterByAnd(productPromoConds, UtilMisc.toMap("productPromoRuleId", productPromoRule.get("productPromoRuleId"))); 682 if (Debug.verboseOn()) Debug.logVerbose("Checking " + productPromoConds.size() + " conditions for rule " + productPromoRule, module); 684 685 Iterator productPromoCondIter = UtilMisc.toIterator(productPromoConds); 686 while (productPromoCondIter != null && productPromoCondIter.hasNext()) { 687 GenericValue productPromoCond = (GenericValue) productPromoCondIter.next(); 688 689 boolean condResult = checkCondition(productPromoCond, cart, delegator, dispatcher, nowTimestamp); 690 691 if (condResult == false) { 693 performActions = false; 694 break; 695 } 696 } 697 698 if (performActions) { 699 701 List productPromoActions = productPromoRule.getRelatedCache("ProductPromoAction", null, UtilMisc.toList("productPromoActionSeqId")); 702 if (Debug.verboseOn()) Debug.logVerbose("Performing " + productPromoActions.size() + " actions for rule " + productPromoRule, module); 703 Iterator productPromoActionIter = UtilMisc.toIterator(productPromoActions); 704 while (productPromoActionIter != null && productPromoActionIter.hasNext()) { 705 GenericValue productPromoAction = (GenericValue) productPromoActionIter.next(); 706 707 try { 709 ActionResultInfo actionResultInfo = performAction(productPromoAction, cart, delegator, dispatcher, nowTimestamp); 710 totalDiscountAmount += actionResultInfo.totalDiscountAmount; 711 quantityLeftInActions += actionResultInfo.quantityLeftInAction; 712 713 boolean actionChangedCart = actionResultInfo.ranAction; 715 if (actionChangedCart) { 716 promoUsed = true; 717 cartChanged = true; 718 } 719 } catch (CartItemModifyException e) { 720 Debug.logError("Error modifying the cart while performing promotion action [" + productPromoAction.getPrimaryKey() + "]: " + e.toString(), module); 721 } 722 } 723 } 724 } 725 726 if (promoUsed) { 727 cart.addProductPromoUse(productPromo.getString("productPromoId"), productPromoCodeId, totalDiscountAmount, quantityLeftInActions); 728 } else { 729 break; 731 } 732 733 734 if (cart.getProductPromoUseCount(productPromoId) > maxUseLimit) { 735 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."); 736 } 737 } 738 739 return cartChanged; 740 } 741 742 protected static boolean checkCondition(GenericValue productPromoCond, ShoppingCart cart, GenericDelegator delegator, LocalDispatcher dispatcher, Timestamp nowTimestamp) throws GenericEntityException { 743 String condValue = productPromoCond.getString("condValue"); 744 String otherValue = productPromoCond.getString("otherValue"); 745 String inputParamEnumId = productPromoCond.getString("inputParamEnumId"); 746 String operatorEnumId = productPromoCond.getString("operatorEnumId"); 747 748 String partyId = cart.getPartyId(); 749 GenericValue userLogin = cart.getUserLogin(); 750 if (userLogin == null) { 751 userLogin = cart.getAutoUserLogin(); 752 } 753 754 if (Debug.verboseOn()) Debug.logVerbose("Checking promotion condition: " + productPromoCond, module); 755 Integer compareBase = null; 756 757 if ("PPIP_PRODUCT_AMOUNT".equals(inputParamEnumId)) { 758 operatorEnumId = "PPC_EQ"; 760 761 double amountNeeded = 0.0; 763 if (UtilValidate.isNotEmpty(condValue)) { 764 amountNeeded = Double.parseDouble(condValue); 765 } 766 767 769 Set productIds = ProductPromoWorker.getPromoRuleCondProductIds(productPromoCond, delegator, nowTimestamp); 770 771 List lineOrderedByBasePriceList = cart.getLineListOrderedByBasePrice(false); 772 Iterator lineOrderedByBasePriceIter = lineOrderedByBasePriceList.iterator(); 773 while (amountNeeded > 0 && lineOrderedByBasePriceIter.hasNext()) { 774 ShoppingCartItem cartItem = (ShoppingCartItem) lineOrderedByBasePriceIter.next(); 775 GenericValue product = cartItem.getProduct(); 777 String parentProductId = cartItem.getParentProductId(); 778 if (!cartItem.getIsPromo() && 779 (productIds.contains(cartItem.getProductId()) || (parentProductId != null && productIds.contains(parentProductId))) && 780 (product == null || !"N".equals(product.getString("includeInPromotions")))) { 781 782 double basePrice = cartItem.getBasePrice(); 783 double quantityNeeded = Math.ceil(amountNeeded / basePrice); 785 786 double quantity = cartItem.addPromoQuantityCandidateUse(quantityNeeded, productPromoCond, false); 788 amountNeeded -= (quantity * basePrice); 790 } 791 } 792 793 795 if (amountNeeded > 0) { 797 cart.resetPromoRuleUse(productPromoCond.getString("productPromoId"), productPromoCond.getString("productPromoRuleId")); 799 compareBase = new Integer (-1); 800 } else { 801 compareBase = new Integer (0); 803 } 805 } else if ("PPIP_PRODUCT_TOTAL".equals(inputParamEnumId)) { 806 Double amountNeeded = Double.valueOf(condValue); 808 double amountAvailable = 0; 809 810 812 Set productIds = ProductPromoWorker.getPromoRuleCondProductIds(productPromoCond, delegator, nowTimestamp); 813 814 List lineOrderedByBasePriceList = cart.getLineListOrderedByBasePrice(false); 815 Iterator lineOrderedByBasePriceIter = lineOrderedByBasePriceList.iterator(); 816 while (lineOrderedByBasePriceIter.hasNext()) { 817 ShoppingCartItem cartItem = (ShoppingCartItem) lineOrderedByBasePriceIter.next(); 818 GenericValue product = cartItem.getProduct(); 820 String parentProductId = cartItem.getParentProductId(); 821 if (!cartItem.getIsPromo() && 822 (productIds.contains(cartItem.getProductId()) || (parentProductId != null && productIds.contains(parentProductId))) && 823 (product == null || !"N".equals(product.getString("includeInPromotions")))) { 824 825 amountAvailable += cartItem.getItemSubTotal(); 827 } 828 } 829 830 832 compareBase = new Integer (new Double (amountAvailable).compareTo(amountNeeded)); 833 } else if ("PPIP_PRODUCT_QUANT".equals(inputParamEnumId)) { 834 operatorEnumId = "PPC_EQ"; 836 837 double quantityNeeded = 1.0; 838 if (UtilValidate.isNotEmpty(condValue)) { 839 quantityNeeded = Double.parseDouble(condValue); 840 } 841 842 Set productIds = ProductPromoWorker.getPromoRuleCondProductIds(productPromoCond, delegator, nowTimestamp); 843 844 List lineOrderedByBasePriceList = cart.getLineListOrderedByBasePrice(false); 845 Iterator lineOrderedByBasePriceIter = lineOrderedByBasePriceList.iterator(); 846 while (quantityNeeded > 0 && lineOrderedByBasePriceIter.hasNext()) { 847 ShoppingCartItem cartItem = (ShoppingCartItem) lineOrderedByBasePriceIter.next(); 848 GenericValue product = cartItem.getProduct(); 850 String parentProductId = cartItem.getParentProductId(); 851 if (!cartItem.getIsPromo() && 852 (productIds.contains(cartItem.getProductId()) || (parentProductId != null && productIds.contains(parentProductId))) && 853 (product == null || !"N".equals(product.getString("includeInPromotions")))) { 854 quantityNeeded -= cartItem.addPromoQuantityCandidateUse(quantityNeeded, productPromoCond, false); 856 } 857 } 858 859 if (quantityNeeded > 0) { 861 cart.resetPromoRuleUse(productPromoCond.getString("productPromoId"), productPromoCond.getString("productPromoRuleId")); 863 compareBase = new Integer (-1); 864 } else { 865 compareBase = new Integer (0); 867 } 869 870 927 } else if ("PPIP_NEW_ACCT".equals(inputParamEnumId)) { 928 Double acctDays = cart.getPartyDaysSinceCreated(nowTimestamp); 929 if (acctDays == null) { 930 return false; 932 } 933 compareBase = new Integer (acctDays.compareTo(Double.valueOf(condValue))); 934 } else if ("PPIP_PARTY_ID".equals(inputParamEnumId)) { 935 if (partyId != null) { 936 compareBase = new Integer (partyId.compareTo(condValue)); 937 } else { 938 compareBase = new Integer (1); 939 } 940 } else if ("PPIP_PARTY_GRP_MEM".equals(inputParamEnumId)) { 941 if (UtilValidate.isEmpty(partyId)) { 942 compareBase = new Integer (1); 943 } else { 944 String groupPartyId = condValue; 945 if (partyId.equals(groupPartyId)) { 946 compareBase = new Integer (0); 947 } else { 948 List partyRelationshipList = delegator.findByAndCache("PartyRelationship", UtilMisc.toMap("partyIdFrom", groupPartyId, "partyIdTo", partyId, "partyRelationshipTypeId", "GROUP_ROLLUP")); 950 partyRelationshipList = EntityUtil.filterByDate(partyRelationshipList, true); 952 if (partyRelationshipList != null && partyRelationshipList.size() > 0) { 954 compareBase = new Integer (0); 955 } else { 956 compareBase = new Integer (1); 957 } 958 } 959 } 960 } else if ("PPIP_PARTY_CLASS".equals(inputParamEnumId)) { 961 if (UtilValidate.isEmpty(partyId)) { 962 compareBase = new Integer (1); 963 } else { 964 String partyClassificationGroupId = condValue; 965 List partyClassificationList = delegator.findByAndCache("PartyClassification", UtilMisc.toMap("partyId", partyId, "partyClassificationGroupId", partyClassificationGroupId)); 967 partyClassificationList = EntityUtil.filterByDate(partyClassificationList, true); 969 if (partyClassificationList != null && partyClassificationList.size() > 0) { 971 compareBase = new Integer (0); 972 } else { 973 compareBase = new Integer (1); 974 } 975 } 976 } else if ("PPIP_ROLE_TYPE".equals(inputParamEnumId)) { 977 if (partyId != null) { 978 GenericValue partyRole = delegator.findByPrimaryKeyCache("PartyRole", 980 UtilMisc.toMap("partyId", partyId, "roleTypeId", condValue)); 981 982 if (partyRole != null) { 984 compareBase = new Integer (0); 985 } else { 986 compareBase = new Integer (1); 987 } 988 } else { 989 compareBase = new Integer (1); 990 } 991 } else if ("PPIP_ORDER_TOTAL".equals(inputParamEnumId)) { 992 Double orderSubTotal = new Double (cart.getSubTotalForPromotions()); 993 if (Debug.verboseOn()) Debug.logVerbose("Doing order total compare: orderSubTotal=" + orderSubTotal, module); 994 compareBase = new Integer (orderSubTotal.compareTo(Double.valueOf(condValue))); 995 } else if ("PPIP_ORST_HIST".equals(inputParamEnumId)) { 996 if (partyId != null && userLogin != null) { 998 int monthsToInclude = 12; 1000 if (otherValue != null) { 1001 monthsToInclude = Integer.parseInt(condValue); 1002 } 1003 Map serviceIn = UtilMisc.toMap("partyId", partyId, "roleTypeId", "PLACING_CUSTOMER", "orderTypeId", "SALES_ORDER", "statusId", "ORDER_COMPLETED", "monthsToInclude", new Integer (monthsToInclude), "userLogin", userLogin); 1004 try { 1005 Map result = dispatcher.runSync("getOrderedSummaryInformation", serviceIn); 1006 if (ServiceUtil.isError(result)) { 1007 Debug.logError("Error calling getOrderedSummaryInformation service for the PPIP_ORST_HIST ProductPromo condition input value: " + ServiceUtil.getErrorMessage(result), module); 1008 return false; 1009 } else { 1010 Double orderSubTotal = (Double ) result.get("totalSubRemainingAmount"); 1011 if (Debug.verboseOn()) Debug.logVerbose("Doing order history sub-total compare: orderSubTotal=" + orderSubTotal + ", for the last " + monthsToInclude + " months.", module); 1012 compareBase = new Integer (orderSubTotal.compareTo(Double.valueOf(condValue))); 1013 } 1014 } catch (GenericServiceException e) { 1015 Debug.logError(e, "Error getting order history sub-total in the getOrderedSummaryInformation service, evaluating condition to false.", module); 1016 return false; 1017 } 1018 } else { 1019 return false; 1020 } 1021 } else { 1022 Debug.logWarning(UtilProperties.getMessage(resource_error,"OrderAnUnSupportedProductPromoCondInputParameterLhs", UtilMisc.toMap("inputParamEnumId",productPromoCond.getString("inputParamEnumId")), cart.getLocale()), module); 1023 return false; 1024 } 1025 1026 if (Debug.verboseOn()) Debug.logVerbose("Condition compare done, compareBase=" + compareBase, module); 1027 1028 if (compareBase != null) { 1029 int compare = compareBase.intValue(); 1030 if ("PPC_EQ".equals(operatorEnumId)) { 1031 if (compare == 0) return true; 1032 } else if ("PPC_NEQ".equals(operatorEnumId)) { 1033 if (compare != 0) return true; 1034 } else if ("PPC_LT".equals(operatorEnumId)) { 1035 if (compare < 0) return true; 1036 } else if ("PPC_LTE".equals(operatorEnumId)) { 1037 if (compare <= 0) return true; 1038 } else if ("PPC_GT".equals(operatorEnumId)) { 1039 if (compare > 0) return true; 1040 } else if ("PPC_GTE".equals(operatorEnumId)) { 1041 if (compare >= 0) return true; 1042 } else { 1043 Debug.logWarning(UtilProperties.getMessage(resource_error,"OrderAnUnSupportedProductPromoCondCondition", UtilMisc.toMap("operatorEnumId",operatorEnumId) , cart.getLocale()), module); 1044 return false; 1045 } 1046 } 1047 return false; 1049 } 1050 1051 public static class ActionResultInfo { 1052 public boolean ranAction = false; 1053 public double totalDiscountAmount = 0; 1054 public double quantityLeftInAction = 0; 1055 } 1056 1057 1058 protected static ActionResultInfo performAction(GenericValue productPromoAction, ShoppingCart cart, GenericDelegator delegator, LocalDispatcher dispatcher, Timestamp nowTimestamp) throws GenericEntityException, CartItemModifyException { 1059 ActionResultInfo actionResultInfo = new ActionResultInfo(); 1060 1061 String productPromoActionEnumId = productPromoAction.getString("productPromoActionEnumId"); 1062 1063 if ("PROMO_GWP".equals(productPromoActionEnumId)) { 1064 String productStoreId = cart.getProductStoreId(); 1065 1066 boolean allowMultipleGwp = true; 1068 1069 Integer itemLoc = findPromoItem(productPromoAction, cart); 1070 if (!allowMultipleGwp && itemLoc != null) { 1071 if (Debug.verboseOn()) Debug.logVerbose("Not adding promo item, already there; action: " + productPromoAction, module); 1072 actionResultInfo.ranAction = false; 1073 } else { 1074 double quantity = productPromoAction.get("quantity") == null ? 0.0 : productPromoAction.getDouble("quantity").doubleValue(); 1075 1076 List optionProductIds = FastList.newInstance(); 1077 String productId = productPromoAction.getString("productId"); 1078 1079 GenericValue product = null; 1080 if (UtilValidate.isNotEmpty(productId)) { 1081 product = delegator.findByPrimaryKeyCache("Product", UtilMisc.toMap("productId", productId)); 1083 if (product == null) { 1084 String errMsg = "GWP Product not found with ID [" + productId + "] for ProductPromoAction [" + productPromoAction.get("productPromoId") + ":" + productPromoAction.get("productPromoRuleId") + ":" + productPromoAction.get("productPromoActionSeqId") + "]"; 1085 Debug.logError(errMsg, module); 1086 throw new CartItemModifyException(errMsg); 1087 } 1088 if ("Y".equals(product.getString("isVirtual"))) { 1089 List productAssocs = EntityUtil.filterByDate(product.getRelatedCache("MainProductAssoc", 1090 UtilMisc.toMap("productAssocTypeId", "PRODUCT_VARIANT"), UtilMisc.toList("sequenceNum")), true); 1091 Iterator productAssocIter = productAssocs.iterator(); 1092 while (productAssocIter.hasNext()) { 1093 GenericValue productAssoc = (GenericValue) productAssocIter.next(); 1094 optionProductIds.add(productAssoc.get("productIdTo")); 1095 } 1096 productId = null; 1097 product = null; 1098 } else { 1100 try { 1103 Map invReqResult = dispatcher.runSync("isStoreInventoryAvailable", UtilMisc.toMap("productStoreId", productStoreId, "productId", productId, "product", product, "quantity", new Double (quantity))); 1104 if (ServiceUtil.isError(invReqResult)) { 1105 Debug.logError("Error calling isStoreInventoryAvailable service, result is: " + invReqResult, module); 1106 throw new CartItemModifyException((String ) invReqResult.get(ModelService.ERROR_MESSAGE)); 1107 } else if (!"Y".equals((String ) invReqResult.get("available"))) { 1108 productId = null; 1109 product = null; 1110 Debug.logWarning(UtilProperties.getMessage(resource_error,"OrderNotApplyingGwpBecauseProductIdIsOutOfStockForProductPromoAction", cart.getLocale()), module); 1111 } 1112 } catch (GenericServiceException e) { 1113 String errMsg = "Fatal error calling inventory checking services: " + e.toString(); 1114 Debug.logError(e, errMsg, module); 1115 throw new CartItemModifyException(errMsg); 1116 } 1117 } 1118 } 1119 1120 Set productIds = ProductPromoWorker.getPromoRuleActionProductIds(productPromoAction, delegator, nowTimestamp); 1122 if (productIds != null) { 1123 optionProductIds.addAll(productIds); 1124 } 1125 1126 Iterator optionProductIdIter = optionProductIds.iterator(); 1128 while (optionProductIdIter.hasNext()) { 1129 String optionProductId = (String ) optionProductIdIter.next(); 1130 1131 try { 1132 Map invReqResult = dispatcher.runSync("isStoreInventoryAvailable", UtilMisc.toMap("productStoreId", productStoreId, "productId", optionProductId, "product", product, "quantity", new Double (quantity))); 1133 if (ServiceUtil.isError(invReqResult)) { 1134 Debug.logError("Error calling isStoreInventoryAvailable service, result is: " + invReqResult, module); 1135 throw new CartItemModifyException((String ) invReqResult.get(ModelService.ERROR_MESSAGE)); 1136 } else if (!"Y".equals((String ) invReqResult.get("available"))) { 1137 optionProductIdIter.remove(); 1138 } 1139 } catch (GenericServiceException e) { 1140 String errMsg = "Fatal error calling inventory checking services: " + e.toString(); 1141 Debug.logError(e, errMsg, module); 1142 throw new CartItemModifyException(errMsg); 1143 } 1144 } 1145 1146 String alternateGwpProductId = cart.getDesiredAlternateGiftByAction(productPromoAction.getPrimaryKey()); 1148 if (UtilValidate.isNotEmpty(alternateGwpProductId)) { 1149 if (optionProductIds.contains(alternateGwpProductId)) { 1151 if (UtilValidate.isNotEmpty(productId)) { 1152 optionProductIds.add(productId); 1153 } 1154 optionProductIds.remove(alternateGwpProductId); 1155 productId = alternateGwpProductId; 1156 product = delegator.findByPrimaryKeyCache("Product", UtilMisc.toMap("productId", productId)); 1157 } else { 1158 Debug.logWarning(UtilProperties.getMessage(resource_error,"OrderAnAlternateGwpProductIdWasInPlaceButWasEitherNotValidOrIsNoLongerInStockForId", UtilMisc.toMap("alternateGwpProductId",alternateGwpProductId), cart.getLocale()), module); 1159 } 1160 } 1161 1162 if (product == null && optionProductIds.size() > 0) { 1164 Iterator optionProductIdTempIter = optionProductIds.iterator(); 1166 productId = (String ) optionProductIdTempIter.next(); 1167 optionProductIdTempIter.remove(); 1168 product = delegator.findByPrimaryKeyCache("Product", UtilMisc.toMap("productId", productId)); 1169 } 1170 1171 if (product == null) { 1172 return actionResultInfo; 1174 } 1175 1176 ShoppingCartItem gwpItem = null; 1178 try { 1179 String prodCatalogId = null; 1181 gwpItem = ShoppingCartItem.makeItem(null, product, quantity, null, null, prodCatalogId, dispatcher, cart, false); 1182 if (optionProductIds.size() > 0) { 1183 gwpItem.setAlternativeOptionProductIds(optionProductIds); 1184 } else { 1185 gwpItem.setAlternativeOptionProductIds(null); 1186 } 1187 } catch (CartItemModifyException e) { 1188 int gwpItemIndex = cart.getItemIndex(gwpItem); 1189 cart.removeCartItem(gwpItemIndex, dispatcher); 1190 throw e; 1191 } 1192 1193 double discountAmount = -(quantity * gwpItem.getBasePrice()); 1194 1195 doOrderItemPromoAction(productPromoAction, gwpItem, discountAmount, "amount", delegator); 1196 1197 gwpItem.setIsPromo(true); 1199 if (Debug.verboseOn()) Debug.logVerbose("gwpItem adjustments: " + gwpItem.getAdjustments(), module); 1200 1201 actionResultInfo.ranAction = true; 1202 actionResultInfo.totalDiscountAmount = discountAmount; 1203 } 1204 } else if ("PROMO_FREE_SHIPPING".equals(productPromoActionEnumId)) { 1205 cart.addFreeShippingProductPromoAction(productPromoAction); 1209 actionResultInfo.ranAction = true; 1211 } else if ("PROMO_PROD_DISC".equals(productPromoActionEnumId)) { 1213 double quantityDesired = productPromoAction.get("quantity") == null ? 1.0 : productPromoAction.getDouble("quantity").doubleValue(); 1214 double startingQuantity = quantityDesired; 1215 double discountAmountTotal = 0; 1216 1217 Set productIds = ProductPromoWorker.getPromoRuleActionProductIds(productPromoAction, delegator, nowTimestamp); 1218 1219 List lineOrderedByBasePriceList = cart.getLineListOrderedByBasePrice(false); 1220 Iterator lineOrderedByBasePriceIter = lineOrderedByBasePriceList.iterator(); 1221 while (quantityDesired > 0 && lineOrderedByBasePriceIter.hasNext()) { 1222 ShoppingCartItem cartItem = (ShoppingCartItem) lineOrderedByBasePriceIter.next(); 1223 GenericValue product = cartItem.getProduct(); 1225 String parentProductId = cartItem.getParentProductId(); 1226 if (!cartItem.getIsPromo() && 1227 (productIds.contains(cartItem.getProductId()) || (parentProductId != null && productIds.contains(parentProductId))) && 1228 (product == null || !"N".equals(product.getString("includeInPromotions")))) { 1229 double quantityUsed = cartItem.addPromoQuantityCandidateUse(quantityDesired, productPromoAction, false); 1231 if (quantityUsed > 0) { 1232 quantityDesired -= quantityUsed; 1233 1234 double percentModifier = productPromoAction.get("amount") == null ? 0.0 : (productPromoAction.getDouble("amount").doubleValue()/100.0); 1236 double lineAmount = quantityUsed * cartItem.getBasePrice(); 1237 double discountAmount = -(lineAmount * percentModifier); 1238 discountAmountTotal += discountAmount; 1239 } 1241 } 1242 } 1243 1244 if (quantityDesired == startingQuantity) { 1245 actionResultInfo.ranAction = false; 1247 } else { 1248 double totalAmount = getCartItemsUsedTotalAmount(cart, productPromoAction); 1249 if (Debug.verboseOn()) Debug.logVerbose("Applying promo [" + productPromoAction.getPrimaryKey() + "]\n totalAmount=" + totalAmount + ", discountAmountTotal=" + discountAmountTotal, module); 1250 distributeDiscountAmount(discountAmountTotal, totalAmount, getCartItemsUsed(cart, productPromoAction), productPromoAction, delegator); 1251 actionResultInfo.ranAction = true; 1252 actionResultInfo.totalDiscountAmount = discountAmountTotal; 1253 actionResultInfo.quantityLeftInAction = quantityDesired; 1254 } 1255 } else if ("PROMO_PROD_AMDISC".equals(productPromoActionEnumId)) { 1256 double quantityDesired = productPromoAction.get("quantity") == null ? 1.0 : productPromoAction.getDouble("quantity").doubleValue(); 1257 double startingQuantity = quantityDesired; 1258 double discountAmountTotal = 0; 1259 1260 Set productIds = ProductPromoWorker.getPromoRuleActionProductIds(productPromoAction, delegator, nowTimestamp); 1261 1262 List lineOrderedByBasePriceList = cart.getLineListOrderedByBasePrice(false); 1263 Iterator lineOrderedByBasePriceIter = lineOrderedByBasePriceList.iterator(); 1264 while (quantityDesired > 0 && lineOrderedByBasePriceIter.hasNext()) { 1265 ShoppingCartItem cartItem = (ShoppingCartItem) lineOrderedByBasePriceIter.next(); 1266 String parentProductId = cartItem.getParentProductId(); 1268 GenericValue product = cartItem.getProduct(); 1269 if (!cartItem.getIsPromo() && 1270 (productIds.contains(cartItem.getProductId()) || (parentProductId != null && productIds.contains(parentProductId))) && 1271 (product == null || !"N".equals(product.getString("includeInPromotions")))) { 1272 double quantityUsed = cartItem.addPromoQuantityCandidateUse(quantityDesired, productPromoAction, false); 1274 quantityDesired -= quantityUsed; 1275 1276 double discount = productPromoAction.get("amount") == null ? 0.0 : productPromoAction.getDouble("amount").doubleValue(); 1278 if (discount > cartItem.getBasePrice()) { 1280 discount = cartItem.getBasePrice(); 1281 } 1282 double discountAmount = -(quantityUsed * discount); 1283 discountAmountTotal += discountAmount; 1284 } 1286 } 1287 1288 if (quantityDesired == startingQuantity) { 1289 actionResultInfo.ranAction = false; 1291 } else { 1292 double totalAmount = getCartItemsUsedTotalAmount(cart, productPromoAction); 1293 if (Debug.verboseOn()) Debug.logVerbose("Applying promo [" + productPromoAction.getPrimaryKey() + "]\n totalAmount=" + totalAmount + ", discountAmountTotal=" + discountAmountTotal, module); 1294 distributeDiscountAmount(discountAmountTotal, totalAmount, getCartItemsUsed(cart, productPromoAction), productPromoAction, delegator); 1295 actionResultInfo.ranAction = true; 1296 actionResultInfo.totalDiscountAmount = discountAmountTotal; 1297 actionResultInfo.quantityLeftInAction = quantityDesired; 1298 } 1299 } else if ("PROMO_PROD_PRICE".equals(productPromoActionEnumId)) { 1300 double quantityDesired = productPromoAction.get("quantity") == null ? 1.0 : productPromoAction.getDouble("quantity").doubleValue(); 1302 double desiredAmount = productPromoAction.get("amount") == null ? 0.0 : productPromoAction.getDouble("amount").doubleValue(); 1303 double totalAmount = 0; 1304 1305 Set productIds = ProductPromoWorker.getPromoRuleActionProductIds(productPromoAction, delegator, nowTimestamp); 1306 1307 List cartItemsUsed = FastList.newInstance(); 1308 List lineOrderedByBasePriceList = cart.getLineListOrderedByBasePrice(false); 1309 Iterator lineOrderedByBasePriceIter = lineOrderedByBasePriceList.iterator(); 1310 while (quantityDesired > 0 && lineOrderedByBasePriceIter.hasNext()) { 1311 ShoppingCartItem cartItem = (ShoppingCartItem) lineOrderedByBasePriceIter.next(); 1312 String parentProductId = cartItem.getParentProductId(); 1314 GenericValue product = cartItem.getProduct(); 1315 if (!cartItem.getIsPromo() && (productIds.contains(cartItem.getProductId()) || (parentProductId != null && productIds.contains(parentProductId))) && 1316 (product == null || !"N".equals(product.getString("includeInPromotions")))) { 1317 double quantityUsed = cartItem.addPromoQuantityCandidateUse(quantityDesired, productPromoAction, false); 1319 if (quantityUsed > 0) { 1320 quantityDesired -= quantityUsed; 1321 totalAmount += quantityUsed * cartItem.getBasePrice(); 1322 cartItemsUsed.add(cartItem); 1323 } 1324 } 1325 } 1326 1327 if (totalAmount > desiredAmount && quantityDesired == 0) { 1328 double discountAmountTotal = -(totalAmount - desiredAmount); 1329 distributeDiscountAmount(discountAmountTotal, totalAmount, cartItemsUsed, productPromoAction, delegator); 1330 actionResultInfo.ranAction = true; 1331 actionResultInfo.totalDiscountAmount = discountAmountTotal; 1332 } else { 1334 actionResultInfo.ranAction = false; 1335 cart.resetPromoRuleUse(productPromoAction.getString("productPromoId"), productPromoAction.getString("productPromoRuleId")); 1337 } 1338 } else if ("PROMO_ORDER_PERCENT".equals(productPromoActionEnumId)) { 1339 double percentage = -(productPromoAction.get("amount") == null ? 0.0 : (productPromoAction.getDouble("amount").doubleValue() / 100.0)); 1340 double amount = cart.getSubTotalForPromotions() * percentage; 1341 if (amount != 0) { 1342 doOrderPromoAction(productPromoAction, cart, amount, "amount", delegator); 1343 actionResultInfo.ranAction = true; 1344 actionResultInfo.totalDiscountAmount = amount; 1345 } 1346 } else if ("PROMO_ORDER_AMOUNT".equals(productPromoActionEnumId)) { 1347 double amount = -(productPromoAction.get("amount") == null ? 0.0 : productPromoAction.getDouble("amount").doubleValue()); 1348 double subTotal = cart.getSubTotalForPromotions(); 1350 if (-amount > subTotal) { 1351 amount = -subTotal; 1352 } 1353 if (amount != 0) { 1354 doOrderPromoAction(productPromoAction, cart, amount, "amount", delegator); 1355 actionResultInfo.ranAction = true; 1356 actionResultInfo.totalDiscountAmount = amount; 1357 } 1358 } else if ("PROMO_PROD_SPPRC".equals(productPromoActionEnumId)) { 1359 Set productIds = ProductPromoWorker.getPromoRuleActionProductIds(productPromoAction, delegator, nowTimestamp); 1361 1362 Iterator cartItemIter = cart.items().iterator(); 1364 while (cartItemIter.hasNext()) { 1365 ShoppingCartItem cartItem = (ShoppingCartItem) cartItemIter.next(); 1366 String itemProductId = cartItem.getProductId(); 1367 if (UtilValidate.isEmpty(itemProductId)) { 1368 continue; 1369 } 1370 1371 if (productIds.size() > 0 && !productIds.contains(itemProductId)) { 1372 continue; 1373 } 1374 1375 if (cartItem.getSpecialPromoPrice() == null) { 1376 continue; 1377 } 1378 1379 double difference = -(cartItem.getBasePrice() - cartItem.getSpecialPromoPrice().doubleValue()); 1381 1382 if (difference != 0.0) { 1383 double quantityUsed = cartItem.addPromoQuantityCandidateUse(cartItem.getQuantity(), productPromoAction, false); 1384 if (quantityUsed > 0) { 1385 double amount = difference * quantityUsed; 1386 doOrderItemPromoAction(productPromoAction, cartItem, amount, "amount", delegator); 1387 actionResultInfo.ranAction = true; 1388 actionResultInfo.totalDiscountAmount = amount; 1389 } 1390 } 1391 } 1392 } else { 1393 Debug.logError("An un-supported productPromoActionType was used: " + productPromoActionEnumId + ", not performing any action", module); 1394 actionResultInfo.ranAction = false; 1395 } 1396 1397 if (actionResultInfo.ranAction) { 1398 cart.confirmPromoRuleUse(productPromoAction.getString("productPromoId"), productPromoAction.getString("productPromoRuleId")); 1400 } else { 1401 cart.resetPromoRuleUse(productPromoAction.getString("productPromoId"), productPromoAction.getString("productPromoRuleId")); 1402 } 1403 1404 return actionResultInfo; 1405 } 1406 1407 protected static List getCartItemsUsed(ShoppingCart cart, GenericValue productPromoAction) { 1408 List cartItemsUsed = FastList.newInstance(); 1409 Iterator cartItemsIter = cart.iterator(); 1410 while (cartItemsIter.hasNext()) { 1411 ShoppingCartItem cartItem = (ShoppingCartItem) cartItemsIter.next(); 1412 double quantityUsed = cartItem.getPromoQuantityCandidateUseActionAndAllConds(productPromoAction); 1413 if (quantityUsed > 0) { 1414 cartItemsUsed.add(cartItem); 1415 } 1416 } 1417 return cartItemsUsed; 1418 } 1419 1420 protected static double getCartItemsUsedTotalAmount(ShoppingCart cart, GenericValue productPromoAction) { 1421 double totalAmount = 0; 1422 Iterator cartItemsIter = cart.iterator(); 1423 while (cartItemsIter.hasNext()) { 1424 ShoppingCartItem cartItem = (ShoppingCartItem) cartItemsIter.next(); 1425 double quantityUsed = cartItem.getPromoQuantityCandidateUseActionAndAllConds(productPromoAction); 1426 if (quantityUsed > 0) { 1427 totalAmount += quantityUsed * cartItem.getBasePrice(); 1428 } 1429 } 1430 return totalAmount; 1431 } 1432 1433 protected static void distributeDiscountAmount(double discountAmountTotal, double totalAmount, List cartItemsUsed, GenericValue productPromoAction, GenericDelegator delegator) { 1434 double discountAmount = discountAmountTotal; 1435 Iterator cartItemsUsedIter = cartItemsUsed.iterator(); 1437 while (cartItemsUsedIter.hasNext()) { 1438 ShoppingCartItem cartItem = (ShoppingCartItem) cartItemsUsedIter.next(); 1439 if (cartItemsUsedIter.hasNext()) { 1441 double quantityUsed = cartItem.getPromoQuantityCandidateUseActionAndAllConds(productPromoAction); 1442 double ratioOfTotal = (quantityUsed * cartItem.getBasePrice()) / totalAmount; 1443 double weightedAmount = ratioOfTotal * discountAmountTotal; 1444 weightedAmount = weightedAmount * 100.0; 1446 long roundedAmount = Math.round(weightedAmount); 1447 weightedAmount = ((double) roundedAmount) / 100.0; 1448 discountAmount -= weightedAmount; 1449 doOrderItemPromoAction(productPromoAction, cartItem, weightedAmount, "amount", delegator); 1450 } else { 1451 doOrderItemPromoAction(productPromoAction, cartItem, discountAmount, "amount", delegator); 1453 } 1454 } 1455 } 1457 1458 protected static Integer findPromoItem(GenericValue productPromoAction, ShoppingCart cart) { 1459 List cartItems = cart.items(); 1460 1461 for (int i = 0; i < cartItems.size(); i++) { 1462 ShoppingCartItem checkItem = (ShoppingCartItem) cartItems.get(i); 1463 1464 if (checkItem.getIsPromo()) { 1465 Iterator checkOrderAdjustments = UtilMisc.toIterator(checkItem.getAdjustments()); 1467 while (checkOrderAdjustments != null && checkOrderAdjustments.hasNext()) { 1468 GenericValue checkOrderAdjustment = (GenericValue) checkOrderAdjustments.next(); 1469 if (productPromoAction.getString("productPromoId").equals(checkOrderAdjustment.get("productPromoId")) && 1470 productPromoAction.getString("productPromoRuleId").equals(checkOrderAdjustment.get("productPromoRuleId")) && 1471 productPromoAction.getString("productPromoActionSeqId").equals(checkOrderAdjustment.get("productPromoActionSeqId"))) { 1472 return new Integer (i); 1473 } 1474 } 1475 } 1476 } 1477 return null; 1478 } 1479 1480 public static void doOrderItemPromoAction(GenericValue productPromoAction, ShoppingCartItem cartItem, double amount, String amountField, GenericDelegator delegator) { 1481 GenericValue orderAdjustment = delegator.makeValue("OrderAdjustment", 1482 UtilMisc.toMap("orderAdjustmentTypeId", "PROMOTION_ADJUSTMENT", amountField, new Double (amount), 1483 "productPromoId", productPromoAction.get("productPromoId"), 1484 "productPromoRuleId", productPromoAction.get("productPromoRuleId"), 1485 "productPromoActionSeqId", productPromoAction.get("productPromoActionSeqId"))); 1486 1487 if (UtilValidate.isNotEmpty(productPromoAction.getString("orderAdjustmentTypeId"))) { 1489 orderAdjustment.set("orderAdjustmentTypeId", productPromoAction.get("orderAdjustmentTypeId")); 1490 } 1491 1492 cartItem.addAdjustment(orderAdjustment); 1493 } 1494 1495 public static void doOrderPromoAction(GenericValue productPromoAction, ShoppingCart cart, double amount, String amountField, GenericDelegator delegator) { 1496 GenericValue orderAdjustment = delegator.makeValue("OrderAdjustment", 1497 UtilMisc.toMap("orderAdjustmentTypeId", "PROMOTION_ADJUSTMENT", amountField, new Double (amount), 1498 "productPromoId", productPromoAction.get("productPromoId"), 1499 "productPromoRuleId", productPromoAction.get("productPromoRuleId"), 1500 "productPromoActionSeqId", productPromoAction.get("productPromoActionSeqId"))); 1501 1502 if (UtilValidate.isNotEmpty(productPromoAction.getString("orderAdjustmentTypeId"))) { 1504 orderAdjustment.set("orderAdjustmentTypeId", productPromoAction.get("orderAdjustmentTypeId")); 1505 } 1506 1507 cart.addAdjustment(orderAdjustment); 1508 } 1509 1510 protected static Integer findAdjustment(GenericValue productPromoAction, List adjustments) { 1511 for (int i = 0; i < adjustments.size(); i++) { 1512 GenericValue checkOrderAdjustment = (GenericValue) adjustments.get(i); 1513 1514 if (productPromoAction.getString("productPromoId").equals(checkOrderAdjustment.get("productPromoId")) && 1515 productPromoAction.getString("productPromoRuleId").equals(checkOrderAdjustment.get("productPromoRuleId")) && 1516 productPromoAction.getString("productPromoActionSeqId").equals(checkOrderAdjustment.get("productPromoActionSeqId"))) { 1517 return new Integer (i); 1518 } 1519 } 1520 return null; 1521 } 1522 1523 public static Set getPromoRuleCondProductIds(GenericValue productPromoCond, GenericDelegator delegator, Timestamp nowTimestamp) throws GenericEntityException { 1524 List productPromoCategoriesAll = delegator.findByAndCache("ProductPromoCategory", UtilMisc.toMap("productPromoId", productPromoCond.get("productPromoId"))); 1526 List productPromoCategories = EntityUtil.filterByAnd(productPromoCategoriesAll, UtilMisc.toMap("productPromoRuleId", "_NA_", "productPromoCondSeqId", "_NA_")); 1527 productPromoCategories.addAll(EntityUtil.filterByAnd(productPromoCategoriesAll, UtilMisc.toMap("productPromoRuleId", productPromoCond.get("productPromoRuleId"), "productPromoCondSeqId", productPromoCond.get("productPromoCondSeqId")))); 1528 1529 List productPromoProductsAll = delegator.findByAndCache("ProductPromoProduct", UtilMisc.toMap("productPromoId", productPromoCond.get("productPromoId"))); 1530 List productPromoProducts = EntityUtil.filterByAnd(productPromoProductsAll, UtilMisc.toMap("productPromoRuleId", "_NA_", "productPromoCondSeqId", "_NA_")); 1531 productPromoProducts.addAll(EntityUtil.filterByAnd(productPromoProductsAll, UtilMisc.toMap("productPromoRuleId", productPromoCond.get("productPromoRuleId"), "productPromoCondSeqId", productPromoCond.get("productPromoCondSeqId")))); 1532 1533 Set productIds = new HashSet (); 1534 makeProductPromoIdSet(productIds, productPromoCategories, productPromoProducts, delegator, nowTimestamp, false); 1535 return productIds; 1536 } 1537 1538 public static Set getPromoRuleActionProductIds(GenericValue productPromoAction, GenericDelegator delegator, Timestamp nowTimestamp) throws GenericEntityException { 1539 List productPromoCategoriesAll = delegator.findByAndCache("ProductPromoCategory", UtilMisc.toMap("productPromoId", productPromoAction.get("productPromoId"))); 1541 List productPromoCategories = EntityUtil.filterByAnd(productPromoCategoriesAll, UtilMisc.toMap("productPromoRuleId", "_NA_", "productPromoActionSeqId", "_NA_")); 1542 productPromoCategories.addAll(EntityUtil.filterByAnd(productPromoCategoriesAll, UtilMisc.toMap("productPromoRuleId", productPromoAction.get("productPromoRuleId"), "productPromoActionSeqId", productPromoAction.get("productPromoActionSeqId")))); 1543 1544 List productPromoProductsAll = delegator.findByAndCache("ProductPromoProduct", UtilMisc.toMap("productPromoId", productPromoAction.get("productPromoId"))); 1545 List productPromoProducts = EntityUtil.filterByAnd(productPromoProductsAll, UtilMisc.toMap("productPromoRuleId", "_NA_", "productPromoActionSeqId", "_NA_")); 1546 productPromoProducts.addAll(EntityUtil.filterByAnd(productPromoProductsAll, UtilMisc.toMap("productPromoRuleId", productPromoAction.get("productPromoRuleId"), "productPromoActionSeqId", productPromoAction.get("productPromoActionSeqId")))); 1547 1548 Set productIds = new HashSet (); 1549 makeProductPromoIdSet(productIds, productPromoCategories, productPromoProducts, delegator, nowTimestamp, false); 1550 return productIds; 1551 } 1552 1553 public static void makeProductPromoIdSet(Set productIds, List productPromoCategories, List productPromoProducts, GenericDelegator delegator, Timestamp nowTimestamp, boolean filterOldProducts) throws GenericEntityException { 1554 handleProductPromoCategories(productIds, productPromoCategories, "PPPA_INCLUDE", delegator, nowTimestamp); 1556 handleProductPromoProducts(productIds, productPromoProducts, "PPPA_INCLUDE"); 1557 1558 handleProductPromoCategories(productIds, productPromoCategories, "PPPA_EXCLUDE", delegator, nowTimestamp); 1560 handleProductPromoProducts(productIds, productPromoProducts, "PPPA_EXCLUDE"); 1561 1562 handleProductPromoCategories(productIds, productPromoCategories, "PPPA_ALWAYS", delegator, nowTimestamp); 1564 handleProductPromoProducts(productIds, productPromoProducts, "PPPA_ALWAYS"); 1565 } 1566 1567 public static void makeProductPromoCondActionIdSets(String productPromoId, Set productIdsCond, Set productIdsAction, GenericDelegator delegator, Timestamp nowTimestamp) throws GenericEntityException { 1568 makeProductPromoCondActionIdSets(productPromoId, productIdsCond, productIdsAction, delegator, nowTimestamp, false); 1569 } 1570 1571 public static void makeProductPromoCondActionIdSets(String productPromoId, Set productIdsCond, Set productIdsAction, GenericDelegator delegator, Timestamp nowTimestamp, boolean filterOldProducts) throws GenericEntityException { 1572 if (nowTimestamp == null) { 1573 nowTimestamp = UtilDateTime.nowTimestamp(); 1574 } 1575 1576 List productPromoCategoriesAll = delegator.findByAndCache("ProductPromoCategory", UtilMisc.toMap("productPromoId", productPromoId)); 1577 List productPromoProductsAll = delegator.findByAndCache("ProductPromoProduct", UtilMisc.toMap("productPromoId", productPromoId)); 1578 1579 List productPromoProductsCond = FastList.newInstance(); 1580 List productPromoCategoriesCond = FastList.newInstance(); 1581 List productPromoProductsAction = FastList.newInstance(); 1582 List productPromoCategoriesAction = FastList.newInstance(); 1583 1584 Iterator productPromoProductsAllIter = productPromoProductsAll.iterator(); 1585 while (productPromoProductsAllIter.hasNext()) { 1586 GenericValue productPromoProduct = (GenericValue) productPromoProductsAllIter.next(); 1587 if (!"_NA_".equals(productPromoProduct.getString("productPromoCondSeqId")) || "_NA_".equals(productPromoProduct.getString("productPromoRuleId"))) { 1589 productPromoProductsCond.add(productPromoProduct); 1590 } 1591 if (!"_NA_".equals(productPromoProduct.getString("productPromoActionSeqId")) || "_NA_".equals(productPromoProduct.getString("productPromoRuleId"))) { 1592 productPromoProductsAction.add(productPromoProduct); 1593 } 1594 } 1595 Iterator productPromoCategoriesAllIter = productPromoCategoriesAll.iterator(); 1596 while (productPromoCategoriesAllIter.hasNext()) { 1597 GenericValue productPromoCategory = (GenericValue) productPromoCategoriesAllIter.next(); 1598 if (!"_NA_".equals(productPromoCategory.getString("productPromoCondSeqId")) || "_NA_".equals(productPromoCategory.getString("productPromoRuleId"))) { 1599 productPromoCategoriesCond.add(productPromoCategory); 1600 } 1601 if (!"_NA_".equals(productPromoCategory.getString("productPromoActionSeqId")) || "_NA_".equals(productPromoCategory.getString("productPromoRuleId"))) { 1602 productPromoCategoriesAction.add(productPromoCategory); 1603 } 1604 } 1605 1606 makeProductPromoIdSet(productIdsCond, productPromoCategoriesCond, productPromoProductsCond, delegator, nowTimestamp, filterOldProducts); 1607 makeProductPromoIdSet(productIdsAction, productPromoCategoriesAction, productPromoProductsAction, delegator, nowTimestamp, filterOldProducts); 1608 1609 if (filterOldProducts) { 1611 Iterator productIdsCondIter = productIdsCond.iterator(); 1612 while (productIdsCondIter.hasNext()) { 1613 String productId = (String ) productIdsCondIter.next(); 1614 if (isProductOld(productId, delegator, nowTimestamp)) { 1615 productIdsCondIter.remove(); 1616 } 1617 } 1618 Iterator productIdsActionIter = productIdsAction.iterator(); 1619 while (productIdsActionIter.hasNext()) { 1620 String productId = (String ) productIdsActionIter.next(); 1621 if (isProductOld(productId, delegator, nowTimestamp)) { 1622 productIdsActionIter.remove(); 1623 } 1624 } 1625 } 1626 } 1627 1628 protected static boolean isProductOld(String productId, GenericDelegator delegator, Timestamp nowTimestamp) throws GenericEntityException { 1629 GenericValue product = delegator.findByPrimaryKeyCache("Product", UtilMisc.toMap("productId", productId)); 1630 if (product != null) { 1631 Timestamp salesDiscontinuationDate = product.getTimestamp("salesDiscontinuationDate"); 1632 if (salesDiscontinuationDate != null && salesDiscontinuationDate.before(nowTimestamp)) { 1633 return true; 1634 } 1635 } 1636 return false; 1637 } 1638 1639 protected static void handleProductPromoCategories(Set productIds, List productPromoCategories, String productPromoApplEnumId, GenericDelegator delegator, Timestamp nowTimestamp) throws GenericEntityException { 1640 boolean include = !"PPPA_EXCLUDE".equals(productPromoApplEnumId); 1641 Set productCategoryIds = new HashSet (); 1642 Map productCategoryGroupSetListMap = new HashMap (); 1643 1644 Iterator productPromoCategoryIter = productPromoCategories.iterator(); 1645 while (productPromoCategoryIter.hasNext()) { 1646 GenericValue productPromoCategory = (GenericValue) productPromoCategoryIter.next(); 1647 if (productPromoApplEnumId.equals(productPromoCategory.getString("productPromoApplEnumId"))) { 1648 Set tempCatIdSet = new HashSet (); 1649 if ("Y".equals(productPromoCategory.getString("includeSubCategories"))) { 1650 ProductSearch.getAllSubCategoryIds(productPromoCategory.getString("productCategoryId"), tempCatIdSet, delegator, nowTimestamp); 1651 } else { 1652 tempCatIdSet.add(productPromoCategory.getString("productCategoryId")); 1653 } 1654 1655 String andGroupId = productPromoCategory.getString("andGroupId"); 1656 if ("_NA_".equals(andGroupId)) { 1657 productCategoryIds.addAll(tempCatIdSet); 1658 } else { 1659 List catIdSetList = (List ) productCategoryGroupSetListMap.get(andGroupId); 1660 if (catIdSetList == null) { 1661 catIdSetList = FastList.newInstance(); 1662 } 1663 catIdSetList.add(tempCatIdSet); 1664 } 1665 } 1666 } 1667 1668 Iterator pcgslmeIter = productCategoryGroupSetListMap.entrySet().iterator(); 1671 while (pcgslmeIter.hasNext()) { 1672 Map.Entry entry = (Map.Entry ) pcgslmeIter.next(); 1673 List catIdSetList = (List ) entry.getValue(); 1674 if (catIdSetList.size() == 0) { 1675 pcgslmeIter.remove(); 1676 } else if (catIdSetList.size() == 1) { 1677 Set catIdSet = (Set ) catIdSetList.iterator().next(); 1678 if (catIdSet.size() == 0) { 1679 pcgslmeIter.remove(); 1680 } else { 1681 productCategoryIds.addAll(catIdSet); 1683 pcgslmeIter.remove(); 1684 } 1685 } 1686 } 1687 1688 getAllProductIds(productCategoryIds, productIds, delegator, nowTimestamp, include); 1690 1691 Iterator pcgslmIter = productCategoryGroupSetListMap.entrySet().iterator(); 1695 while (pcgslmIter.hasNext()) { 1696 Map.Entry entry = (Map.Entry ) pcgslmIter.next(); 1697 List catIdSetList = (List ) entry.getValue(); 1698 List productIdSetList = FastList.newInstance(); 1700 1701 Iterator cidslIter = catIdSetList.iterator(); 1702 while (cidslIter.hasNext()) { 1703 Set catIdSet = (Set ) cidslIter.next(); 1705 Set groupProductIdSet = new HashSet (); 1706 getAllProductIds(catIdSet, groupProductIdSet, delegator, nowTimestamp, true); 1707 productIdSetList.add(groupProductIdSet); 1708 } 1709 1710 Set firstProductIdSet = (Set ) productIdSetList.remove(0); 1713 Iterator productIdSetIter = productIdSetList.iterator(); 1714 while (productIdSetIter.hasNext()) { 1715 Set productIdSet = (Set ) productIdSetIter.next(); 1716 firstProductIdSet.retainAll(productIdSet); 1717 } 1718 1719 1739 1740 if (firstProductIdSet.size() >= 0) { 1741 if (include) { 1742 productIds.addAll(firstProductIdSet); 1743 } else { 1744 productIds.removeAll(firstProductIdSet); 1745 } 1746 } 1747 } 1748 } 1749 1750 protected static void getAllProductIds(Set productCategoryIdSet, Set productIdSet, GenericDelegator delegator, Timestamp nowTimestamp, boolean include) throws GenericEntityException { 1751 Iterator productCategoryIdIter = productCategoryIdSet.iterator(); 1752 while (productCategoryIdIter.hasNext()) { 1753 String productCategoryId = (String ) productCategoryIdIter.next(); 1754 List productCategoryMembers = delegator.findByAndCache("ProductCategoryMember", UtilMisc.toMap("productCategoryId", productCategoryId)); 1756 productCategoryMembers = EntityUtil.filterByDate(productCategoryMembers, nowTimestamp); 1757 Iterator productCategoryMemberIter = productCategoryMembers.iterator(); 1758 while (productCategoryMemberIter.hasNext()) { 1759 GenericValue productCategoryMember = (GenericValue) productCategoryMemberIter.next(); 1760 String productId = productCategoryMember.getString("productId"); 1761 if (include) { 1762 productIdSet.add(productId); 1763 } else { 1764 productIdSet.remove(productId); 1765 } 1766 } 1767 } 1768 } 1769 1770 protected static void handleProductPromoProducts(Set productIds, List productPromoProducts, String productPromoApplEnumId) throws GenericEntityException { 1771 boolean include = !"PPPA_EXCLUDE".equals(productPromoApplEnumId); 1772 Iterator productPromoProductIter = productPromoProducts.iterator(); 1773 while (productPromoProductIter.hasNext()) { 1774 GenericValue productPromoProduct = (GenericValue) productPromoProductIter.next(); 1775 if (productPromoApplEnumId.equals(productPromoProduct.getString("productPromoApplEnumId"))) { 1776 String productId = productPromoProduct.getString("productId"); 1777 if (include) { 1778 productIds.add(productId); 1779 } else { 1780 productIds.remove(productId); 1781 } 1782 } 1783 } 1784 } 1785 1786 protected static class UseLimitException extends Exception { 1787 public UseLimitException(String str) { 1788 super(str); 1789 } 1790 } 1791} 1792 | Popular Tags |