killbill-aplcache

Adding code to calculate the period from subscription start

2/10/2012 10:25:31 PM

Details

diff --git a/analytics/src/test/java/com/ning/billing/analytics/MockPhase.java b/analytics/src/test/java/com/ning/billing/analytics/MockPhase.java
index 663ed78..10b5c70 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/MockPhase.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/MockPhase.java
@@ -59,6 +59,11 @@ public class MockPhase implements PlanPhase
                 return BigDecimal.valueOf(price);
             }
 
+			@Override
+			public boolean isZero() {
+				return price == 0.0;
+			}
+
          };
     }
 
@@ -78,7 +83,11 @@ public class MockPhase implements PlanPhase
             {
                 return BigDecimal.valueOf(price);
             }
-
+            
+        	@Override
+			public boolean isZero() {
+				return price == 0.0;
+			}
         };
     }
 
diff --git a/analytics/src/test/java/com/ning/billing/analytics/MockPlan.java b/analytics/src/test/java/com/ning/billing/analytics/MockPlan.java
index 72ce7ca..d611eee 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/MockPlan.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/MockPlan.java
@@ -18,6 +18,7 @@ package com.ning.billing.analytics;
 
 import com.ning.billing.catalog.api.BillingPeriod;
 import com.ning.billing.catalog.api.CatalogApiException;
+import com.ning.billing.catalog.api.PhaseType;
 import com.ning.billing.catalog.api.Plan;
 import com.ning.billing.catalog.api.PlanPhase;
 import com.ning.billing.catalog.api.Product;
@@ -25,6 +26,8 @@ import com.ning.billing.catalog.api.Product;
 import java.util.Date;
 import java.util.Iterator;
 
+import org.joda.time.DateTime;
+
 public class MockPlan implements Plan
 {
     private final String name;
@@ -98,4 +101,10 @@ public class MockPlan implements Plan
 	public boolean isRetired() {
 		return false;
 	}
+
+	@Override
+	public DateTime dateOfFirstRecurringNonZeroCharge(
+			DateTime subscriptionStartDate) {
+		 throw new UnsupportedOperationException();
+	}
 }
diff --git a/api/src/main/java/com/ning/billing/catalog/api/InternationalPrice.java b/api/src/main/java/com/ning/billing/catalog/api/InternationalPrice.java
index 2876f1d..e047175 100644
--- a/api/src/main/java/com/ning/billing/catalog/api/InternationalPrice.java
+++ b/api/src/main/java/com/ning/billing/catalog/api/InternationalPrice.java
@@ -25,4 +25,6 @@ public interface InternationalPrice {
 
 	public abstract BigDecimal getPrice(Currency currency) throws CatalogApiException;
 
+	public abstract boolean isZero();
+
 }
\ No newline at end of file
diff --git a/api/src/main/java/com/ning/billing/catalog/api/Plan.java b/api/src/main/java/com/ning/billing/catalog/api/Plan.java
index c0dbce5..3abbfbe 100644
--- a/api/src/main/java/com/ning/billing/catalog/api/Plan.java
+++ b/api/src/main/java/com/ning/billing/catalog/api/Plan.java
@@ -19,6 +19,8 @@ package com.ning.billing.catalog.api;
 import java.util.Date;
 import java.util.Iterator;
 
+import org.joda.time.DateTime;
+
 public interface Plan {
 
 	public abstract PlanPhase[] getInitialPhases();
@@ -42,4 +44,7 @@ public interface Plan {
 	public abstract Date getEffectiveDateForExistingSubscriptons();
 
 	public abstract PlanPhase findPhase(String name) throws CatalogApiException;
+
+	public abstract DateTime dateOfFirstRecurringNonZeroCharge(DateTime subscriptionStartDate);
+	
 }
\ No newline at end of file
diff --git a/catalog/src/main/java/com/ning/billing/catalog/DefaultInternationalPrice.java b/catalog/src/main/java/com/ning/billing/catalog/DefaultInternationalPrice.java
index 1c505f9..d0cf2c4 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/DefaultInternationalPrice.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/DefaultInternationalPrice.java
@@ -119,4 +119,18 @@ public class DefaultInternationalPrice extends ValidatingConfig<StandaloneCatalo
 		return zeroPrice;
 	}
 
+	@Override
+	public boolean isZero() {
+		for(DefaultPrice price :prices) {
+			try {
+				if( price.getValue().compareTo(BigDecimal.ZERO) != 0) {
+					return false;
+				}
+			} catch (CurrencyValueNull e) {
+				//Ignore if the currency is null we treat it as 0
+			}
+		}
+		return true;
+	}
+
 }
diff --git a/catalog/src/main/java/com/ning/billing/catalog/DefaultPlan.java b/catalog/src/main/java/com/ning/billing/catalog/DefaultPlan.java
index 4972e26..a249289 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/DefaultPlan.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/DefaultPlan.java
@@ -29,9 +29,12 @@ import javax.xml.bind.annotation.XmlElementWrapper;
 import javax.xml.bind.annotation.XmlID;
 import javax.xml.bind.annotation.XmlIDREF;
 
+import org.joda.time.DateTime;
+
 import com.ning.billing.ErrorCode;
 import com.ning.billing.catalog.api.BillingPeriod;
 import com.ning.billing.catalog.api.CatalogApiException;
+import com.ning.billing.catalog.api.PhaseType;
 import com.ning.billing.catalog.api.Plan;
 import com.ning.billing.catalog.api.PlanPhase;
 import com.ning.billing.catalog.api.Product;
@@ -228,6 +231,18 @@ public class DefaultPlan extends ValidatingConfig<StandaloneCatalog> implements 
 		this.plansAllowedInBundle = plansAllowedInBundle;
 		return this;
 	}
+	@Override
+	public DateTime dateOfFirstRecurringNonZeroCharge(DateTime subscriptionStartDate) {
+		DateTime result = subscriptionStartDate.toDateTime();
+		for (PlanPhase phase : getAllPhases()) {
+			if(phase.getRecurringPrice() == null || phase.getRecurringPrice().isZero()) {
+				result = phase.getDuration().addToDateTime(result);
+			} else {
+				break;
+			}
+		}
+		return result;
+	}
 	
 	
 }
diff --git a/catalog/src/test/java/com/ning/billing/catalog/TestPlan.java b/catalog/src/test/java/com/ning/billing/catalog/TestPlan.java
index 00dd1b6..e58f71c 100644
--- a/catalog/src/test/java/com/ning/billing/catalog/TestPlan.java
+++ b/catalog/src/test/java/com/ning/billing/catalog/TestPlan.java
@@ -18,17 +18,21 @@ package com.ning.billing.catalog;
 
 import java.util.Date;
 
+import org.joda.time.DateTime;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.testng.Assert;
 import org.testng.annotations.Test;
 
 import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.catalog.api.Duration;
+import com.ning.billing.catalog.api.InternationalPrice;
+import com.ning.billing.catalog.api.PlanPhase;
 import com.ning.billing.util.config.ValidationErrors;
 
 public class TestPlan {
 	private static final Logger log = LoggerFactory.getLogger(TestPlan.class);
-	@Test
+	@Test(groups={"fast"}, enabled = true)
 	public void testDateValidation() {
 
 		StandaloneCatalog c = new MockCatalog();
@@ -40,4 +44,80 @@ public class TestPlan {
 		errors.log(log);
 
 	}
+	
+	private static class MyDuration extends DefaultDuration {
+		final int days;
+		
+		public MyDuration(int days) {
+			this.days = days;
+		}
+		
+		@Override
+		public DateTime addToDateTime(DateTime dateTime) {
+			return dateTime.plusDays(days);
+		}
+	}
+	
+	private static class MyPlanPhase extends MockPlanPhase {
+		Duration duration;
+		boolean recurringPriceIsZero;
+		
+		MyPlanPhase(int duration, boolean recurringPriceIsZero) {
+			this.duration= new MyDuration( duration );
+			this.recurringPriceIsZero = recurringPriceIsZero;
+		}
+		@Override
+		public Duration getDuration(){
+			return duration;
+		}
+		
+		@Override
+		public InternationalPrice getRecurringPrice() {
+			return new MockInternationalPrice() {
+				@Override
+				public boolean isZero() {
+					return recurringPriceIsZero;
+				}
+			};
+		}
+	}
+	
+	@Test(groups={"fast"}, enabled = true)
+	public void testDataCalc() {
+		DefaultPlan p0 =  new MockPlan() {
+			public PlanPhase[] getAllPhases() {
+				return new PlanPhase[]{
+						new MyPlanPhase(10, true),
+						new MyPlanPhase(10, false),
+				};
+			}
+		};
+		
+		DefaultPlan p1 =  new MockPlan() {
+			public PlanPhase[] getAllPhases() {
+				return new PlanPhase[]{
+						new MyPlanPhase(10, true),
+						new MyPlanPhase(10, true),
+						new MyPlanPhase(10, true),
+						new MyPlanPhase(10, true),
+						new MyPlanPhase(10, false),
+						new MyPlanPhase(10, true),
+				};
+			}
+		};
+		
+		DefaultPlan p2 =  new MockPlan() {
+			public PlanPhase[] getAllPhases() {
+				return new PlanPhase[]{
+						new MyPlanPhase(10, false),
+						new MyPlanPhase(10, true),
+				};
+			}
+		};
+		DateTime requestedDate = new DateTime();
+		Assert.assertEquals(p0.dateOfFirstRecurringNonZeroCharge(requestedDate), requestedDate.plusDays(10));
+		Assert.assertEquals(p1.dateOfFirstRecurringNonZeroCharge(requestedDate), requestedDate.plusDays(40));
+		Assert.assertEquals(p2.dateOfFirstRecurringNonZeroCharge(requestedDate), requestedDate.plusDays(0));
+
+	}
 }
diff --git a/invoice/src/test/java/com/ning/billing/invoice/tests/InternationalPriceMock.java b/invoice/src/test/java/com/ning/billing/invoice/tests/InternationalPriceMock.java
index 8577544..ab11024 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/tests/InternationalPriceMock.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/tests/InternationalPriceMock.java
@@ -43,4 +43,9 @@ public class InternationalPriceMock implements InternationalPrice {
         return rate;
     }
 
+	@Override
+	public boolean isZero() {
+		return rate.compareTo(BigDecimal.ZERO) == 0;
+	}
+
 }