You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ofbiz.apache.org by jo...@apache.org on 2008/05/20 07:48:51 UTC
svn commit: r658108 - in /ofbiz/trunk: applications/ecommerce/data/
applications/order/src/org/ofbiz/order/shoppingcart/product/
applications/product/data/ framework/service/src/org/ofbiz/service/calendar/
Author: jonesde
Date: Mon May 19 22:48:51 2008
New Revision: 658108
URL: http://svn.apache.org/viewvc?rev=658108&view=rev
Log:
Applied patch from Bilgin Ibryam in Jira #OFBIZ-1756 to extend the support for by hours and by days in recurrence info and use them as part of conditions for promotions
Modified:
ofbiz/trunk/applications/ecommerce/data/DemoProduct.xml
ofbiz/trunk/applications/order/src/org/ofbiz/order/shoppingcart/product/ProductPromoWorker.java
ofbiz/trunk/applications/product/data/ProductTypeData.xml
ofbiz/trunk/framework/service/src/org/ofbiz/service/calendar/RecurrenceInfo.java
ofbiz/trunk/framework/service/src/org/ofbiz/service/calendar/RecurrenceRule.java
Modified: ofbiz/trunk/applications/ecommerce/data/DemoProduct.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/ecommerce/data/DemoProduct.xml?rev=658108&r1=658107&r2=658108&view=diff
==============================================================================
--- ofbiz/trunk/applications/ecommerce/data/DemoProduct.xml (original)
+++ ofbiz/trunk/applications/ecommerce/data/DemoProduct.xml Mon May 19 22:48:51 2008
@@ -565,6 +565,7 @@
<ProductPromo productPromoId="9019" promoName="Test Percent off when Customer Orders over $1000 in 12 months" userEntered="Y" useLimitPerOrder="1" createdDate="2001-05-13 12:00:00.0">
<promoText><![CDATA[Spend more than $1000 in any 12 months on our fabulous Widgets and Gizmos and get a 5% discount.]]></promoText>
</ProductPromo>
+ <ProductPromo productPromoId="9020" promoName="Test Promotion Recurrence - Happy hour" promoText="Get 1 Free [WG-1111], between 15:00 - 18:00 at weekdays" userEntered="Y" showToCustomer="Y" requireCode="N" useLimitPerOrder="1" createdDate="2008-01-01 12:00:00.0" createdByUserLogin="admin" lastModifiedDate="2008-01-01 12:00:00.0" lastModifiedByUserLogin="admin"/>
<ProductPromoRule productPromoId="9000" productPromoRuleId="01" ruleName="Rule 1: Free Widget"/>
<ProductPromoRule productPromoId="9010" productPromoRuleId="01" ruleName="Test Percent off rule"/>
<ProductPromoRule productPromoId="9011" productPromoRuleId="01" ruleName="Test percent off order"/>
@@ -576,6 +577,7 @@
<ProductPromoRule productPromoId="9017" productPromoRuleId="01" ruleName="GWP for Gizmos Only"/>
<ProductPromoRule productPromoId="9018" productPromoRuleId="01" ruleName="GWP for Gizmos Only Not Counted"/>
<ProductPromoRule productPromoId="9019" productPromoRuleId="01" ruleName="Percent off for Ordered Sub-Total History"/>
+ <ProductPromoRule productPromoId="9020" productPromoRuleId="01" ruleName="Test Promotion Recurrence"/>
<ProductPromoAction productPromoId="9000" productPromoRuleId="01" productPromoActionSeqId="01" productPromoActionEnumId="PROMO_GWP" orderAdjustmentTypeId="PROMOTION_ADJUSTMENT" quantity="1.0" productId="WG-1111"/>
<ProductPromoAction productPromoId="9010" productPromoRuleId="01" productPromoActionSeqId="01" productPromoActionEnumId="PROMO_PROD_DISC" orderAdjustmentTypeId="PROMOTION_ADJUSTMENT" quantity="1.0" amount="20.0"/>
<ProductPromoAction productPromoId="9011" productPromoRuleId="01" productPromoActionSeqId="01" productPromoActionEnumId="PROMO_ORDER_PERCENT" orderAdjustmentTypeId="PROMOTION_ADJUSTMENT" amount="10.0"/>
@@ -587,6 +589,7 @@
<ProductPromoAction productPromoId="9017" productPromoRuleId="01" productPromoActionSeqId="01" productPromoActionEnumId="PROMO_GWP" orderAdjustmentTypeId="PROMOTION_ADJUSTMENT" quantity="1.0" productId="GZ-1006"/>
<ProductPromoAction productPromoId="9018" productPromoRuleId="01" productPromoActionSeqId="01" productPromoActionEnumId="PROMO_GWP" orderAdjustmentTypeId="PROMOTION_ADJUSTMENT" quantity="1.0" productId="GZ-1006"/>
<ProductPromoAction productPromoId="9019" productPromoRuleId="01" productPromoActionSeqId="01" productPromoActionEnumId="PROMO_ORDER_PERCENT" orderAdjustmentTypeId="PROMOTION_ADJUSTMENT" amount="5.0"/>
+ <ProductPromoAction productPromoId="9020" productPromoRuleId="01" productPromoActionSeqId="01" productPromoActionEnumId="PROMO_GWP" orderAdjustmentTypeId="PROMOTION_ADJUSTMENT" quantity="1.0" productId="WG-1111"/>
<ProductPromoCond productPromoId="9000" productPromoRuleId="01" productPromoCondSeqId="01" inputParamEnumId="PPIP_ORDER_TOTAL" operatorEnumId="PPC_GT" condValue="100"/>
<ProductPromoCond productPromoId="9012" productPromoRuleId="01" productPromoCondSeqId="01" inputParamEnumId="PPIP_ORDER_TOTAL" operatorEnumId="PPC_GTE" condValue="50"/>
<ProductPromoCond productPromoId="9013" productPromoRuleId="01" productPromoCondSeqId="01" inputParamEnumId="PPIP_PRODUCT_QUANT" operatorEnumId="PPC_EQ" condValue="3"/>
@@ -594,6 +597,7 @@
<ProductPromoCond productPromoId="9017" productPromoRuleId="01" productPromoCondSeqId="01" inputParamEnumId="PPIP_PRODUCT_AMOUNT" operatorEnumId="PPC_EQ" condValue="50"/>
<ProductPromoCond productPromoId="9018" productPromoRuleId="01" productPromoCondSeqId="01" inputParamEnumId="PPIP_PRODUCT_TOTAL" operatorEnumId="PPC_GTE" condValue="150"/>
<ProductPromoCond productPromoId="9019" productPromoRuleId="01" productPromoCondSeqId="01" inputParamEnumId="PPIP_ORST_HIST" operatorEnumId="PPC_GTE" condValue="1000" otherValue="12"/>
+ <ProductPromoCond productPromoId="9020" productPromoRuleId="01" productPromoCondSeqId="01" inputParamEnumId="PPIP_RECURRENCE" operatorEnumId="PPC_EQ" condValue="205"/>
<ProductPromoCategory productPromoId="9013" productPromoRuleId="_NA_" productPromoActionSeqId="_NA_" productPromoCondSeqId="_NA_" productCategoryId="200" andGroupId="_NA_" productPromoApplEnumId="PPPA_INCLUDE" includeSubCategories="Y"/>
<ProductPromoCategory productPromoId="9013" productPromoRuleId="_NA_" productPromoActionSeqId="_NA_" productPromoCondSeqId="_NA_" productCategoryId="201" andGroupId="_NA_" productPromoApplEnumId="PPPA_EXCLUDE" includeSubCategories="Y"/>
<ProductPromoCategory productPromoId="9013" productPromoRuleId="_NA_" productPromoActionSeqId="_NA_" productPromoCondSeqId="_NA_" productCategoryId="20111" andGroupId="_NA_" productPromoApplEnumId="PPPA_ALWAYS" includeSubCategories="N"/>
@@ -622,6 +626,7 @@
<ProductStorePromoAppl productStoreId="9000" productPromoId="9017" fromDate="2001-05-13 12:00:00.0" sequenceNum="1"/>
<ProductStorePromoAppl productStoreId="9000" productPromoId="9018" fromDate="2001-05-13 12:00:00.0" sequenceNum="1"/>
<ProductStorePromoAppl productStoreId="9000" productPromoId="9019" fromDate="2001-05-13 12:00:00.0" sequenceNum="1"/>
+ <ProductStorePromoAppl productStoreId="9000" productPromoId="9020" fromDate="2001-05-13 12:00:00.0" sequenceNum="1"/>
<ProductPromo productPromoId="9021" promoName="Test Products for Special Promo Price" promoText="With special code [9021] get products in the Featured Products category for their special promotion price." userEntered="Y" showToCustomer="Y" requireCode="Y" createdDate="2001-05-13 12:00:00.0" createdByUserLogin="admin" lastModifiedDate="2001-05-13 12:00:00.0" lastModifiedByUserLogin="admin"/>
<ProductPromoCode productPromoCodeId="9021" productPromoId="9021" userEntered="Y" requireEmailOrParty="N" createdDate="2001-05-13 12:00:00.0" createdByUserLogin="admin" lastModifiedDate="2001-05-13 12:00:00.0" lastModifiedByUserLogin="admin"/>
@@ -629,6 +634,10 @@
<ProductPromoAction productPromoId="9021" productPromoRuleId="01" productPromoActionSeqId="01" productPromoActionEnumId="PROMO_PROD_SPPRC" orderAdjustmentTypeId="PROMOTION_ADJUSTMENT"/>
<ProductPromoCategory productPromoId="9021" productPromoRuleId="01" productPromoActionSeqId="01" productPromoCondSeqId="_NA_" productCategoryId="PROMOTIONS" andGroupId="_NA_" productPromoApplEnumId="PPPA_INCLUDE" includeSubCategories="N"/>
<ProductStorePromoAppl productStoreId="9000" productPromoId="9021" fromDate="2001-05-13 12:00:00.0" sequenceNum="1"/>
+
+ <!-- a promotion recurrence example for happy hour-->
+ <RecurrenceRule recurrenceRuleId="205" frequency="DAILY" intervalNumber="1" countNumber="-1" byHourList="15,16,17" byDayList="MO,TU,WE,TH,FR"/>
+ <RecurrenceInfo recurrenceInfoId="205" startDateTime="2008-01-01 00:00:00.000" recurrenceRuleId="205" recurrenceCount="0"/>
<!-- a default pricing rule to play with; take 20% off all products in the PROMOTIONS category -->
<ProductPriceRule productPriceRuleId="9000" ruleName="Test Rule 1" isSale="Y"/>
Modified: ofbiz/trunk/applications/order/src/org/ofbiz/order/shoppingcart/product/ProductPromoWorker.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/order/src/org/ofbiz/order/shoppingcart/product/ProductPromoWorker.java?rev=658108&r1=658107&r2=658108&view=diff
==============================================================================
--- ofbiz/trunk/applications/order/src/org/ofbiz/order/shoppingcart/product/ProductPromoWorker.java (original)
+++ ofbiz/trunk/applications/order/src/org/ofbiz/order/shoppingcart/product/ProductPromoWorker.java Mon May 19 22:48:51 2008
@@ -59,6 +59,8 @@
import org.ofbiz.service.LocalDispatcher;
import org.ofbiz.service.ModelService;
import org.ofbiz.service.ServiceUtil;
+import org.ofbiz.service.calendar.RecurrenceInfo;
+import org.ofbiz.service.calendar.RecurrenceInfoException;
/**
* ProductPromoWorker - Worker class for catalog/product promotion related functionality
@@ -1035,6 +1037,24 @@
} else {
return false;
}
+ } else if ("PPIP_RECURRENCE".equals(inputParamEnumId)) {
+ compareBase = new Integer(1);
+ GenericValue recurrenceInfo = delegator.findByPrimaryKeyCache("RecurrenceInfo", UtilMisc.toMap("recurrenceInfoId", condValue));
+ if (recurrenceInfo != null) {
+ RecurrenceInfo recurrence = null;
+ try {
+ recurrence = new RecurrenceInfo(recurrenceInfo);
+ } catch (RecurrenceInfoException e) {
+ Debug.logError(e, module);
+ }
+
+ // check the current recurrence
+ if (recurrence != null) {
+ if (recurrence.isValidCurrent()) {
+ compareBase = new Integer(0);
+ }
+ }
+ }
} else {
Debug.logWarning(UtilProperties.getMessage(resource_error,"OrderAnUnSupportedProductPromoCondInputParameterLhs", UtilMisc.toMap("inputParamEnumId",productPromoCond.getString("inputParamEnumId")), cart.getLocale()), module);
return false;
Modified: ofbiz/trunk/applications/product/data/ProductTypeData.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/product/data/ProductTypeData.xml?rev=658108&r1=658107&r2=658108&view=diff
==============================================================================
--- ofbiz/trunk/applications/product/data/ProductTypeData.xml (original)
+++ ofbiz/trunk/applications/product/data/ProductTypeData.xml Mon May 19 22:48:51 2008
@@ -348,6 +348,7 @@
<Enumeration description="Party Classification" enumCode="PARTY_CLASS" enumId="PPIP_PARTY_CLASS" sequenceId="08" enumTypeId="PROD_PROMO_IN_PARAM"/>
<Enumeration description="Role Type" enumCode="ROLE_TYPE" enumId="PPIP_ROLE_TYPE" sequenceId="09" enumTypeId="PROD_PROMO_IN_PARAM"/>
<Enumeration description="Order sub-total X in last Y Months" enumCode="ORST_HIST" enumId="PPIP_ORST_HIST" sequenceId="10" enumTypeId="PROD_PROMO_IN_PARAM"/>
+ <Enumeration description="Promotion Recurrence" enumCode="PROMO_RECURRENCE" enumId="PPIP_RECURRENCE" sequenceId="11" enumTypeId="PROD_PROMO_IN_PARAM"/>
<EnumerationType description="Product Promotion Condition" enumTypeId="PROD_PROMO_COND" hasTable="N" parentTypeId="PROD_PROMO"/>
<!-- old style very technical ...
Modified: ofbiz/trunk/framework/service/src/org/ofbiz/service/calendar/RecurrenceInfo.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/service/src/org/ofbiz/service/calendar/RecurrenceInfo.java?rev=658108&r1=658107&r2=658108&view=diff
==============================================================================
--- ofbiz/trunk/framework/service/src/org/ofbiz/service/calendar/RecurrenceInfo.java (original)
+++ ofbiz/trunk/framework/service/src/org/ofbiz/service/calendar/RecurrenceInfo.java Mon May 19 22:48:51 2008
@@ -19,7 +19,6 @@
package org.ofbiz.service.calendar;
import java.util.ArrayList;
-import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.Iterator;
@@ -27,7 +26,6 @@
import org.ofbiz.base.util.Debug;
import org.ofbiz.base.util.StringUtil;
-import org.ofbiz.base.util.UtilMisc;
import org.ofbiz.entity.GenericDelegator;
import org.ofbiz.entity.GenericEntityException;
import org.ofbiz.entity.GenericValue;
@@ -44,7 +42,7 @@
protected List<RecurrenceRule> rRulesList;
protected List<RecurrenceRule> eRulesList;
protected List<Date> rDateList;
- protected List<Date> eDateList;;
+ protected List<Date> eDateList;
/** Creates new RecurrenceInfo */
public RecurrenceInfo(GenericValue info) throws RecurrenceInfoException {
@@ -231,6 +229,33 @@
}
return nextRuleTime;
}
+
+ /** Checks the current recurrence validity at the moment. */
+ public boolean isValidCurrent() {
+ return isValidCurrent(RecurrenceUtil.now());
+ }
+
+ /** Checks the current recurrence validity for checkTime. */
+ public boolean isValidCurrent(long checkTime) {
+ if (checkTime == 0 || (rDateList == null && rRulesList == null)) {
+ return false;
+ }
+
+ boolean found = false;
+ Iterator<RecurrenceRule> rulesIterator = getRecurrenceRuleIterator();
+ while (rulesIterator.hasNext()) {
+ RecurrenceRule rule = rulesIterator.next();
+ long currentTime = rule.validCurrent(getStartTime(), checkTime, getCurrentCount());
+ currentTime = checkDateList(rDateList, currentTime, checkTime);
+ if ((currentTime > 0) && isValid(checkTime)) {
+ found = true;
+ } else {
+ return false;
+ }
+ }
+
+ return found;
+ }
private long getNextTime(RecurrenceRule rule, long fromTime) {
long nextTime = rule.next(getStartTime(), fromTime, getCurrentCount());
Modified: ofbiz/trunk/framework/service/src/org/ofbiz/service/calendar/RecurrenceRule.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/service/src/org/ofbiz/service/calendar/RecurrenceRule.java?rev=658108&r1=658107&r2=658108&view=diff
==============================================================================
--- ofbiz/trunk/framework/service/src/org/ofbiz/service/calendar/RecurrenceRule.java (original)
+++ ofbiz/trunk/framework/service/src/org/ofbiz/service/calendar/RecurrenceRule.java Mon May 19 22:48:51 2008
@@ -26,7 +26,6 @@
import org.ofbiz.base.util.Debug;
import org.ofbiz.base.util.StringUtil;
-import org.ofbiz.base.util.UtilMisc;
import org.ofbiz.entity.GenericDelegator;
import org.ofbiz.entity.GenericEntityException;
import org.ofbiz.entity.GenericValue;
@@ -285,6 +284,116 @@
}
/**
+ * Gets the current recurrence (current for the checkTime) of this rule and returns it if it is valid.
+ * If the current recurrence is not valid, doesn't try to find a valid one, instead returns 0.
+ *@param startTime The time this recurrence first began.
+ *@param checkTime The time to base the current recurrence on.
+ *@param currentCount The total number of times the recurrence has run.
+ *@return long The current recurrence as long if valid. If next recurrence is not valid, returns 0.
+ */
+ public long validCurrent(long startTime, long checkTime, long currentCount) {
+ if (startTime == 0) {
+ startTime = RecurrenceUtil.now();
+ }
+ if (checkTime == 0) {
+ checkTime = startTime;
+ }
+
+ // Test the end time of the recurrence.
+ if (getEndTime() != 0 && getEndTime() <= RecurrenceUtil.now()) {
+ return 0;
+ }
+
+ // Test the recurrence limit.
+ if (getCount() != -1 && currentCount >= getCount()) {
+ return 0;
+ }
+
+ // Get the next frequency from checkTime
+ Date nextRun = getNextFreq(startTime, checkTime);
+ Calendar cal = Calendar.getInstance();
+ Calendar checkTimeCal = Calendar.getInstance();
+ cal.setTime(nextRun);
+ checkTimeCal.setTime(new Date(checkTime));
+
+ // Get previous frequency and update its values from checkTime
+ switch (getFrequency()) {
+ case YEARLY:
+ cal.add(Calendar.YEAR, -getIntervalInt());
+ if (cal.get(Calendar.YEAR) != checkTimeCal.get(Calendar.YEAR)) {
+ return 0;
+ }
+
+ case MONTHLY:
+ if (MONTHLY == getFrequency()) {
+ cal.add(Calendar.MONTH, -getIntervalInt());
+ if (cal.get(Calendar.MONTH) != checkTimeCal.get(Calendar.MONTH)) {
+ return 0;
+ }
+ } else {
+ cal.set(Calendar.MONTH, checkTimeCal.get(Calendar.MONTH));
+ }
+
+ case WEEKLY:
+ if (WEEKLY == getFrequency()) {
+ cal.add(Calendar.WEEK_OF_YEAR, -getIntervalInt());
+ if (cal.get(Calendar.WEEK_OF_YEAR) != checkTimeCal.get(Calendar.WEEK_OF_YEAR)) {
+ return 0;
+ }
+ } else {
+ cal.set(Calendar.WEEK_OF_YEAR, checkTimeCal.get(Calendar.WEEK_OF_YEAR));
+ }
+
+ case DAILY:
+ if (DAILY == getFrequency()) {
+ cal.add(Calendar.DAY_OF_MONTH, -getIntervalInt());
+ if (cal.get(Calendar.DAY_OF_MONTH) != checkTimeCal.get(Calendar.DAY_OF_MONTH)) {
+ return 0;
+ }
+ } else {
+ cal.set(Calendar.DAY_OF_MONTH, checkTimeCal.get(Calendar.DAY_OF_MONTH));
+ }
+
+ case HOURLY:
+ if (HOURLY == getFrequency()) {
+ cal.add(Calendar.HOUR_OF_DAY, -getIntervalInt());
+ if (cal.get(Calendar.HOUR_OF_DAY) != checkTimeCal.get(Calendar.HOUR_OF_DAY)) {
+ return 0;
+ }
+ } else {
+ cal.set(Calendar.HOUR_OF_DAY, checkTimeCal.get(Calendar.HOUR_OF_DAY));
+ }
+
+ case MINUTELY:
+ if (MINUTELY == getFrequency()) {
+ cal.add(Calendar.MINUTE, -getIntervalInt());
+ if (cal.get(Calendar.MINUTE) != checkTimeCal.get(Calendar.MINUTE)) {
+ return 0;
+ }
+ } else {
+ cal.set(Calendar.MINUTE, checkTimeCal.get(Calendar.MINUTE));
+ }
+
+ case SECONDLY:
+ if (SECONDLY == getFrequency()) {
+ cal.add(Calendar.SECOND, -getIntervalInt());
+ if (cal.get(Calendar.SECOND) != checkTimeCal.get(Calendar.SECOND)) {
+ return 0;
+ }
+ } else {
+ cal.set(Calendar.SECOND, checkTimeCal.get(Calendar.SECOND));
+ }
+ }
+
+ // Check for validity of the current frequency.
+ if (validByRule(cal.getTime())) {
+ return cal.getTime().getTime();
+ }
+
+ return 0;
+ }
+
+ /**
* Tests the date to see if it falls within the rules
*@param startDate date object to test
*@return True if the date is within the rules
@@ -344,7 +453,7 @@
break;
case HOURLY:
- cal.add(Calendar.HOUR, getIntervalInt());
+ cal.add(Calendar.HOUR_OF_DAY, getIntervalInt());
break;
case DAILY:
@@ -380,15 +489,15 @@
// Test each byXXX rule.
if (bySecondList != null && bySecondList.size() > 0) {
- if (!bySecondList.contains(cal.get(Calendar.SECOND)))
+ if (!bySecondList.contains(String.valueOf(cal.get(Calendar.SECOND))))
return false;
}
if (byMinuteList != null && byMinuteList.size() > 0) {
- if (!byMinuteList.contains(cal.get(Calendar.MINUTE)))
+ if (!byMinuteList.contains(String.valueOf(cal.get(Calendar.MINUTE))))
return false;
}
if (byHourList != null && byHourList.size() > 0) {
- if (!byHourList.contains(cal.get(Calendar.HOUR)))
+ if (!byHourList.contains(String.valueOf(cal.get(Calendar.HOUR_OF_DAY))))
return false;
}
if (byDayList != null && byDayList.size() > 0) {
@@ -399,7 +508,7 @@
String dayRule = (String) iter.next();
String dayString = getDailyString(dayRule);
- if (Calendar.DAY_OF_WEEK == getCalendarDay(dayString)) {
+ if (cal.get(Calendar.DAY_OF_WEEK) == getCalendarDay(dayString)) {
if ((hasNumber(dayRule)) && (getFrequency() == MONTHLY || getFrequency() == YEARLY)) {
int modifier = getDailyNumber(dayRule);
@@ -563,7 +672,7 @@
private boolean hasNumber(String str) {
String list[] = {"+", "-", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0"};
List numberList = Arrays.asList(list);
- String firstChar = str.substring(0, 0);
+ String firstChar = str.substring(0, 1);
if (numberList.contains(firstChar))
return true;
@@ -599,7 +708,7 @@
StringBuilder sBuf = new StringBuilder();
for (int i = 0; i < str.length(); i++) {
- String thisChar = str.substring(i, i);
+ String thisChar = str.substring(i, i+1);
if (!hasNumber(thisChar)) {
sBuf.append(thisChar);
@@ -610,6 +719,7 @@
// Returns the Calendar day of the rule day string
private int getCalendarDay(String day) {
+ if (day != null) day = day.trim();
if (day.equalsIgnoreCase("MO"))
return Calendar.MONDAY;
if (day.equalsIgnoreCase("TU"))